pax_global_header00006660000000000000000000000064132501716360014516gustar00rootroot0000000000000052 comment=871f6af72b093b7d22334c00ab39eff440662198 spass-3.9/000077500000000000000000000000001325017163600125225ustar00rootroot00000000000000spass-3.9/LICENCE000066400000000000000000000027771325017163600135240ustar00rootroot00000000000000Copyright 1996-2010 Max Planck Institute for Informatics. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED "AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE MAX PLANCK INSTITUTE FOR INFORMATICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the Max Planck Institute for Informatics. spass-3.9/analyze.c000066400000000000000000001073421325017163600143400ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * ANALYSIS OF CLAUSE SETS * */ /* * * */ /* * $Module: ANALYZE * */ /* * * */ /* * 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* $Revision: 1.7 $ * */ /* $State: Exp $ * */ /* $Date: 2011-05-22 09:05:45 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: analyze.c,v $ */ #include #include "analyze.h" /**************************************************************/ /* Functions */ /**************************************************************/ static LIST ana_CalculatePredicatePrecedence(LIST, LIST); static LIST ana_CalculateFunctionPrecedence(ANALYZE, LIST, LIST, FLAGSTORE); BOOL ana_GetFeature(ANALYZE Ana, ANA_FEATUREID id) { return Ana->boolarray[id]; } BOOL* ana_GetFeatureAddr(ANALYZE Ana, ANA_FEATUREID id) { return &(Ana->boolarray[id]); } void ana_SetFeature(ANALYZE Ana, ANA_FEATUREID id, BOOL newval) { Ana->boolarray[id] = newval; } int ana_GetAxiomClauses(ANALYZE Ana) { return Ana->ana_AXIOMCLAUSES; } int ana_GetConClauses(ANALYZE Ana) { return Ana->ana_CONCLAUSES; } int ana_GetNonHornClauses(ANALYZE Ana) { return Ana->ana_NONHORNCLAUSES; } void ana_IncAxiomClauses(ANALYZE Ana) { Ana->ana_AXIOMCLAUSES++; } void ana_IncConClauses(ANALYZE Ana) { Ana->ana_CONCLAUSES++; } void ana_IncNonHornClauses(ANALYZE Ana) { Ana->ana_NONHORNCLAUSES++; } void ana_SetAxiomClauses(ANALYZE Ana, int newval) { Ana->ana_AXIOMCLAUSES = newval; } void ana_SetConClauses(ANALYZE Ana, int newval) { Ana->ana_CONCLAUSES = newval; } void ana_SetNonHornClauses(ANALYZE Ana, int newval) { Ana->ana_NONHORNCLAUSES = newval; } LIST ana_GetFinMonPredList(ANALYZE Ana) { return Ana->ana_FINITEMONADICPREDICATES; } void ana_SetFinMonPredList(ANALYZE Ana, LIST newval) { Ana->ana_FINITEMONADICPREDICATES = newval; } NAT ana_NonTrivClauseNumber(ANALYZE Ana) { return Ana->nontrivclausenumber; } void ana_SetNonTrivClauseNumber(ANALYZE Ana, NAT Number) { Ana->nontrivclausenumber = Number; } void ana_AddTransAxClause(ANALYZE Ana,CLAUSE Ax) { Ana->transitivityaxioms = list_Cons(Ax,Ana->transitivityaxioms); } LIST ana_GetTransAxClauseList(ANALYZE Ana) { return Ana->transitivityaxioms; } void ana_SetTransAxClauseList(ANALYZE Ana, LIST NewList) { Ana->transitivityaxioms = NewList; } CLAUSE ana_LookupTransAxClause(ANALYZE Ana, SYMBOL s) { LIST Scan; Scan = Ana->transitivityaxioms; while (!list_Empty(Scan)) { if (symbol_Equal(term_TopSymbol(clause_GetLiteralAtom(list_Car(Scan),0)),s)) return list_Car(Scan); Scan = list_Cdr(Scan); } return NULL; } ANALYZE ana_Init(void) { ANALYZE Ana; Ana = (ANALYZE)memory_Malloc(sizeof(ANALYZE_NODE)); Ana->ana_FINITEMONADICPREDICATES = list_Nil(); Ana->transitivityaxioms = list_Nil(); Ana->nontrivclausenumber = 0; return Ana; } void ana_Clean(ANALYZE Ana) { list_DeleteWithElement(Ana->transitivityaxioms,(void (*)(POINTER))clause_Delete); list_Delete(Ana->ana_FINITEMONADICPREDICATES); Ana->ana_FINITEMONADICPREDICATES = list_Nil(); Ana->transitivityaxioms = list_Nil(); Ana->nontrivclausenumber = 0; } void ana_Free(ANALYZE Ana) { ana_Clean(Ana); memory_Free(Ana, sizeof(ANALYZE_NODE)); } void ana_AnalyzeProblem(ANALYZE Ana, FLAGSTORE Flags, LIST Clauses) /************************************************************** INPUT: An analyze object, flagstore, and a list of clauses. RETURNS: Void. EFFECT: Analyzes the clauses and sets the analyze variables. Recomputes the weight for the clauses. is modified according to clauses: non trivial domain number is set ***************************************************************/ { CLAUSE Clause; ana_SetFeature(Ana,ana_EQUATIONS,FALSE); ana_SetFeature(Ana,ana_PEQUATIONS,FALSE); /* Defaults for properties */ ana_SetFeature(Ana,ana_NEQUATIONS,FALSE); ana_SetFeature(Ana,ana_FUNCTIONS,FALSE); ana_SetFeature(Ana,ana_FINDOMAIN,FALSE); ana_SetFeature(Ana,ana_NONTRIVDOMAIN,FALSE); ana_SetFeature(Ana,ana_MONADIC,FALSE); ana_SetFeature(Ana,ana_NONMONADIC,FALSE); ana_SetFeature(Ana,ana_PROP,FALSE); ana_SetFeature(Ana,ana_GROUND,FALSE); ana_SetFeature(Ana,ana_SORTRES,FALSE); ana_SetFeature(Ana,ana_USORTRES,FALSE); ana_SetFeature(Ana,ana_NONUNIT,FALSE); ana_SetFeature(Ana,ana_CONGROUND,TRUE); ana_SetFeature(Ana,ana_TRANSITIVITY,FALSE); ana_SetAxiomClauses(Ana,0); ana_SetConClauses(Ana,0); ana_SetNonHornClauses(Ana,0); list_Delete(ana_GetFinMonPredList(Ana)); ana_SetFinMonPredList(Ana,list_Nil()); if (list_Empty(Clauses)) return; ana_SetFinMonPredList(Ana,clause_FiniteMonadicPredicates(Clauses)); while (!list_Empty(Clauses)) { Clause = (CLAUSE)list_Car(Clauses); clause_UpdateWeight(Clause, Flags); if (clause_GetFlag(Clause,CONCLAUSE)) ana_IncConClauses(Ana); else ana_IncAxiomClauses(Ana); if (clause_NumOfSuccLits(Clause) > 1) ana_IncNonHornClauses(Ana); if (ana_GetFeature(Ana,ana_CONGROUND) && clause_GetFlag(Clause,CONCLAUSE) && clause_MaxVar(Clause) != symbol_GetInitialStandardVarCounter()) ana_SetFeature(Ana,ana_CONGROUND,FALSE); if (!ana_GetFeature(Ana,ana_PEQUATIONS) && clause_ContainsPositiveEquations(Clause)) { ana_SetFeature(Ana,ana_PEQUATIONS,TRUE); } if (!ana_GetFeature(Ana,ana_NEQUATIONS) && clause_ContainsNegativeEquations(Clause)) { ana_SetFeature(Ana,ana_NEQUATIONS,TRUE); } if (!ana_GetFeature(Ana,ana_MONADIC) || !ana_GetFeature(Ana,ana_NONMONADIC) || !ana_GetFeature(Ana,ana_PROP) || !ana_GetFeature(Ana,ana_GROUND)) clause_ContainsFolAtom(Clause,ana_GetFeatureAddr(Ana,ana_PROP),ana_GetFeatureAddr(Ana,ana_GROUND),ana_GetFeatureAddr(Ana,ana_MONADIC),ana_GetFeatureAddr(Ana,ana_NONMONADIC)); if (!ana_GetFeature(Ana,ana_FUNCTIONS) && clause_ContainsFunctions(Clause)) { ana_SetFeature(Ana,ana_FUNCTIONS,TRUE); } if (!ana_GetFeature(Ana,ana_FINDOMAIN) && clause_ImpliesFiniteDomain(Clause)) { ana_SetFeature(Ana,ana_FINDOMAIN,TRUE); } if (!ana_GetFeature(Ana,ana_NONTRIVDOMAIN) && clause_ImpliesNonTrivialDomain(Clause)) { ana_SetNonTrivClauseNumber(Ana, clause_Number(Clause)); ana_SetFeature(Ana,ana_NONTRIVDOMAIN,TRUE); } if (!ana_GetFeature(Ana,ana_NONUNIT) && clause_Length(Clause) > 1) { ana_SetFeature(Ana,ana_NONUNIT,TRUE); } if (!ana_GetFeature(Ana,ana_SORTRES) || !ana_GetFeature(Ana,ana_USORTRES)) clause_ContainsSortRestriction(Clause,ana_GetFeatureAddr(Ana,ana_SORTRES),ana_GetFeatureAddr(Ana,ana_USORTRES)); if (!ana_GetFeature(Ana,ana_TRANSITIVITY) && clause_IsTransitivityAxiom(Clause)) ana_SetFeature(Ana,ana_TRANSITIVITY,TRUE); Clauses = list_Cdr(Clauses); } ana_SetFeature(Ana,ana_PUREEQUATIONAL,((ana_GetFeature(Ana,ana_PEQUATIONS) || ana_GetFeature(Ana,ana_NEQUATIONS)) && !ana_GetFeature(Ana,ana_MONADIC) && !ana_GetFeature(Ana,ana_NONMONADIC) && !ana_GetFeature(Ana,ana_PROP) && !ana_GetFeature(Ana,ana_GROUND))); ana_SetFeature(Ana,ana_EQUATIONS,(ana_GetFeature(Ana,ana_PEQUATIONS) || ana_GetFeature(Ana,ana_NEQUATIONS))); ana_SetFeature(Ana,ana_PUREPROPOSITIONAL,(!ana_GetFeature(Ana,ana_PEQUATIONS) && !ana_GetFeature(Ana,ana_NEQUATIONS) && !ana_GetFeature(Ana,ana_MONADIC) && !ana_GetFeature(Ana,ana_NONMONADIC) && ana_GetFeature(Ana,ana_PROP))); } void ana_AnalyzeSortStructure(ANALYZE Ana, LIST Clauses, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A list of clauses, a flag store and a precedence. RETURNS: Nothing. EFFECT: The sort structure with respect to equations is analyzed. It is detected whether all equations are many sorted or sort decreasing. ***************************************************************/ { if (ana_GetFeature(Ana,ana_PEQUATIONS) && ana_GetFeature(Ana,ana_SORTRES)) { STR Result; Result = sort_AnalyzeSortStructure(Clauses,Flags,Precedence); ana_SetFeature(Ana,ana_SORTMANYEQUATIONS,(Result == SORTEQMANY)); ana_SetFeature(Ana,ana_SORTDECEQUATIONS,(Result == SORTEQMANY || Result == SORTEQDECR)); } } void ana_ProcessTranstivityAxiom(ANALYZE Ana, CLAUSE Clause, SYMBOL s, BOOL twisted) { /* twisted means the axiom clause premise literals are in non-standard order */ if (twisted) { LITERAL lit1, lit2; lit1 = clause_GetLiteral(Clause,0); lit2 = clause_GetLiteral(Clause,1); clause_SetLiteral(Clause,0,lit2); clause_SetLiteral(Clause,1,lit1); } if (symbol_HasProperty(s,TRANSITIVE)) { /*duplicated axiom*/ clause_Delete(Clause); } else { clause_SetFlag(Clause,TRANSAX); ana_AddTransAxClause(Ana,Clause); symbol_AddProperty(s,TRANSITIVE); } } LIST ana_AnalyzeTransitivity(ANALYZE Ana, LIST Clauses) /************************************************************** INPUT: An analyze object and a list of problem clauses. RETURNS: Updated list of problem clauses. EFFECT: The list of clauses is scanned and and if a clause in the form of a transitivity axiom is found the respective symbol is remembered as transitive. Such a clause is deleted from the list and stored in a special place in Also, if the clause found is an axiom of the twisted form (i.e. y S z , x S y -> x S z) it is set right. ***************************************************************/ { SYMBOL s; BOOL twisted; LIST Scan1,Scan2; while (!list_Empty(Clauses) && clause_IsTransitivityAxiomExt(list_Car(Clauses),&s,&twisted)) { Scan1 = list_Cdr(Clauses); ana_ProcessTranstivityAxiom(Ana,list_Car(Clauses),s,twisted); list_Free(Clauses); Clauses = Scan1; } if (list_Empty(Clauses)) return list_Nil(); Scan2 = Clauses; Scan1 = list_Cdr(Clauses); while (!list_Empty(Scan1)) { if (clause_IsTransitivityAxiomExt(list_Car(Scan1),&s,&twisted)) { ana_ProcessTranstivityAxiom(Ana,list_Car(Scan1),s,twisted); list_Rplacd(Scan2, list_Cdr(Scan1)); list_Free(Scan1); Scan1 = list_Cdr(Scan2); } else { Scan2 = Scan1; Scan1 = list_Cdr(Scan1); } } return Clauses; } void ana_Print(ANALYZE Ana, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: An analyze object, a flag store and a precedence. RETURNS: Nothing. EFFECT: The results of an analysis stored in the module variables is printed to stdout. ***************************************************************/ { const char* Horn; if (ana_GetNonHornClauses(Ana) == 0) Horn = "Horn"; else Horn = "Non-Horn"; if (ana_GetFeature(Ana,ana_MONADIC) && !ana_GetFeature(Ana,ana_NONMONADIC)) { printf("\n This is a monadic %s problem",Horn); if (ana_GetFeature(Ana,ana_PEQUATIONS) || ana_GetFeature(Ana,ana_NEQUATIONS)) fputs(" with equality.", stdout); else fputs(" without equality.", stdout); } else if (ana_GetFeature(Ana,ana_PEQUATIONS) || ana_GetFeature(Ana,ana_NEQUATIONS)) { if (ana_GetFeature(Ana,ana_NONMONADIC) || ana_GetFeature(Ana,ana_MONADIC) || ana_GetFeature(Ana,ana_PROP)) printf("\n This is a first-order %s problem containing equality.",Horn); else if (ana_GetFeature(Ana,ana_NONUNIT)) printf("\n This is a pure equality %s problem.",Horn); else fputs("\n This is a unit equality problem.", stdout); } else if (ana_GetFeature(Ana,ana_NONMONADIC) || ana_GetFeature(Ana,ana_MONADIC)) printf("\n This is a first-order %s problem without equality.",Horn); if (ana_GetFeature(Ana,ana_PUREPROPOSITIONAL)) printf("\n This is a propositional %s problem.",Horn); else if (ana_GetFeature(Ana,ana_FINDOMAIN) || !ana_GetFeature(Ana,ana_FUNCTIONS)) { fputs("\n This is a problem that has, if any, a finite domain model.", stdout); if (ana_GetFeature(Ana,ana_FINDOMAIN)) fputs("\n There is a finite domain clause.", stdout); if (!ana_GetFeature(Ana,ana_FUNCTIONS)) fputs("\n There are no function symbols.", stdout); } if (ana_GetFeature(Ana,ana_NONTRIVDOMAIN)) fputs("\n This is a problem that has, if any, a non-trivial domain model.", stdout); if (ana_GetFeature(Ana,ana_SORTRES)) { fputs("\n This is a problem that contains sort information.", stdout); if (ana_GetFeature(Ana,ana_PEQUATIONS)) { if (ana_GetFeature(Ana,ana_SORTMANYEQUATIONS)) fputs("\n All equations are many sorted.", stdout); else { if (ana_GetFeature(Ana,ana_SORTDECEQUATIONS)) fputs("\n All equations are sort-decreasing.", stdout); } } } if (ana_GetConClauses(Ana) > 0 && ana_GetFeature(Ana,ana_CONGROUND) && !ana_GetFeature(Ana,ana_PUREPROPOSITIONAL)) fputs("\n The conjecture is ground.", stdout); if (ana_GetFeature(Ana,ana_TRANSITIVITY)) fputs("\n The problem contains transitivity axiom(s).", stdout); if (!list_Empty(ana_GetFinMonPredList(Ana))) { LIST Scan; fputs("\n The following monadic predicates have finite extensions: ", stdout); for (Scan=ana_GetFinMonPredList(Ana);!list_Empty(Scan);Scan=list_Cdr(Scan)) { symbol_Print((SYMBOL)list_Car(Scan)); if (!list_Empty(list_Cdr(Scan))) fputs(", ", stdout); } putchar('.'); } printf("\n Axiom clauses: %d Conjecture clauses: %d",ana_GetAxiomClauses(Ana),ana_GetConClauses(Ana)); flag_PrintInferenceRules(Flags); flag_PrintReductionRules(Flags); fputs("\n Extras : ", stdout); if (flag_GetFlagIntValue(Flags, flag_SATINPUT)) fputs("Input Saturation, ", stdout); else fputs("No Input Saturation, ", stdout); if (flag_GetFlagIntValue(Flags, flag_SELECT) == flag_SELECTOFF) fputs("No Selection, ", stdout); else if (flag_GetFlagIntValue(Flags, flag_SELECT) == flag_SELECTIFSEVERALMAXIMAL) fputs("Dynamic Selection, ", stdout); else if (flag_GetFlagIntValue(Flags, flag_SELECT) == flag_SELECTALWAYS) fputs("Always Selection, ", stdout); else fputs("Selection From List, ", stdout); if (flag_GetFlagIntValue(Flags, flag_SPLITS) == flag_SPLITSUNLIMITED) fputs("Full Splitting, ", stdout); else if (flag_GetFlagIntValue(Flags, flag_SPLITS) == flag_SPLITSOFF) fputs("No Splitting, ", stdout); else printf("Maximum of %d Splits, ",flag_GetFlagIntValue(Flags, flag_SPLITS)); if (flag_GetFlagIntValue(Flags,flag_Transitivity)) { fputs("Chaining, ", stdout); /* Meaning: Transitivity Analyzed (labelling symbols and clauses for special use), Removed Transitivity Axioms, Subterm Chaining Restriction of Superposition, Literal Ordering Admissible for Chaining */ } if (flag_GetFlagIntValue(Flags, flag_FULLRED)) fputs("Full Reduction, ", stdout); else fputs("Lazy Reduction, ", stdout); printf(" Ratio: %d, FuncWeight: %d, VarWeight: %d", flag_GetFlagIntValue(Flags, flag_WDRATIO), flag_GetFlagIntValue(Flags, flag_FUNCWEIGHT), flag_GetFlagIntValue(Flags, flag_VARWEIGHT)); fputs("\n Precedence: ", stdout); fol_PrintPrecedence(Precedence); fputs("\n Ordering : ", stdout); fputs(flag_GetFlagIntValue(Flags, flag_ORD) == flag_ORDKBO ? "KBO" : "RPOS", stdout); if (flag_GetFlagIntValue(Flags,flag_Transitivity)) { LIST Scan; fputs("\n Chaining predicates: ", stdout); Scan = ana_GetTransAxClauseList(Ana); while (!list_Empty(Scan)) { fputs(symbol_Name(term_TopSymbol(clause_GetLiteralAtom(list_Car(Scan),0))), stdout); Scan = list_Cdr(Scan); if (!list_Empty(Scan)) fputs(", ", stdout); } } } void ana_AutoConfiguration(ANALYZE Ana, LIST Clauses, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A list of clauses, a flag store and a precedence. RETURNS: Nothing. EFFECT: Based on the values of the ana analysis module, an appropriate complete configuration of inference, reduction rules and other settings is established. ***************************************************************/ { LIST Scan, Functions, Predicates, Constants; Functions = symbol_GetAllFunctions(); Predicates = fol_GetNonFOLPredicates(); /* Set precedence */ Predicates = ana_CalculatePredicatePrecedence(Predicates, Clauses); Functions = ana_CalculateFunctionPrecedence(Ana, Functions, Clauses, Flags); Constants = list_Nil(); for (Scan=Functions; !list_Empty(Scan); Scan=list_Cdr(Scan)) if (symbol_IsConstant((SYMBOL)list_Car(Scan))) Constants = list_Cons(list_Car(Scan),Constants); Functions = list_NPointerDifference(Functions,Constants); Constants = list_NReverse(Constants); for ( ; !list_Empty(Functions); Functions = list_Pop(Functions)) symbol_SetIncreasedOrdering(Precedence, (SYMBOL)list_Car(Functions)); /* Predicates < Functions */ for ( ; !list_Empty(Predicates); Predicates = list_Pop(Predicates)) symbol_SetIncreasedOrdering(Precedence, (SYMBOL)list_Car(Predicates)); /* Constants < Predicates */ /* Predicates < Functions */ for ( ; !list_Empty(Constants); Constants = list_Pop(Constants)) symbol_SetIncreasedOrdering(Precedence, (SYMBOL)list_Car(Constants)); flag_ClearInferenceRules(Flags); flag_ClearReductionRules(Flags); flag_SetFlagIntValue(Flags, flag_ROBV, flag_ROBVON); flag_SetFlagIntValue(Flags, flag_RTAUT, flag_RTAUTSYNTACTIC); flag_SetFlagIntValue(Flags, flag_RFSUB, flag_RFSUBON); flag_SetFlagIntValue(Flags, flag_RBSUB, flag_RBSUBON); flag_SetFlagIntValue(Flags, flag_RFMRR, flag_RFMRRON); flag_SetFlagIntValue(Flags, flag_RBMRR, flag_RBMRRON); flag_SetFlagIntValue(Flags, flag_RUNC, flag_RUNCON); flag_SetFlagIntValue(Flags, flag_FULLRED, flag_FULLREDON); /*flag_SetFlagIntValue(Flags, flag_FUNCWEIGHT,1); flag_SetFlagIntValue(Flags, flag_VARWEIGHT,1);*/ flag_SetFlagIntValue(Flags, flag_WDRATIO,5); if (ana_GetFeature(Ana,ana_TRANSITIVITY)) { flag_SetFlagIntValue(Flags,flag_Transitivity,flag_TRANSON); flag_SetFlagIntValue(Flags, flag_IChain, flag_CHAININGON); if (ana_GetNonHornClauses(Ana) > 0) flag_SetFlagIntValue(Flags, flag_ICompRes, flag_COMPOSITIONRESOLUTIONON); } if (ana_GetFeature(Ana,ana_NEQUATIONS)) { flag_SetFlagIntValue(Flags, flag_IEQR, flag_EQUALITYRESOLUTIONON); if (ana_GetFeature(Ana,ana_NONUNIT)) { if (ana_GetFeature(Ana,ana_NONTRIVDOMAIN)) flag_SetFlagIntValue(Flags, flag_RAED, flag_RAEDPOTUNSOUND); else flag_SetFlagIntValue(Flags, flag_RAED, flag_RAEDSOUND); } } if (ana_GetFeature(Ana,ana_PEQUATIONS)) { flag_SetFlagIntValue(Flags, flag_ISPR, flag_SUPERPOSITIONRIGHTON); flag_SetFlagIntValue(Flags, flag_ISPL, flag_SUPERPOSITIONLEFTON); if (ana_GetNonHornClauses(Ana) > 0) flag_SetFlagIntValue(Flags, flag_IEQF, flag_EQUALITYFACTORINGON); if (ana_GetFeature(Ana,ana_NONUNIT)) flag_SetFlagIntValue(Flags, flag_RCON, flag_RCONON); flag_SetFlagIntValue(Flags, flag_RFREW, flag_RFREWON); flag_SetFlagIntValue(Flags, flag_RBREW, flag_RBREWON); } if (ana_GetFeature(Ana,ana_SORTRES)) { flag_SetFlagIntValue(Flags, flag_SORTS, flag_SORTSMONADICWITHVARIABLE); flag_SetFlagIntValue(Flags, flag_IEMS, flag_EMPTYSORTON); flag_SetFlagIntValue(Flags, flag_ISOR, flag_SORTRESOLUTIONON); flag_SetFlagIntValue(Flags, flag_RSSI, flag_RSSION); if (!ana_GetFeature(Ana,ana_PEQUATIONS) || ana_GetFeature(Ana,ana_SORTMANYEQUATIONS)) flag_SetFlagIntValue(Flags, flag_RSST, flag_RSSTON); } else flag_SetFlagIntValue(Flags, flag_SORTS, flag_SORTSOFF); if (ana_GetFeature(Ana,ana_MONADIC) || ana_GetFeature(Ana,ana_NONMONADIC)) { /* Problem contains real predicates */ flag_SetFlagIntValue(Flags, flag_IORE, flag_ORDEREDRESOLUTIONNOEQUATIONS); if (ana_GetNonHornClauses(Ana) > 0) flag_SetFlagIntValue(Flags, flag_IOFC, flag_FACTORINGONLYRIGHT); if (ana_GetFeature(Ana,ana_NONUNIT)) flag_SetFlagIntValue(Flags, flag_RCON, flag_RCONON); } if (!ana_GetFeature(Ana,ana_FUNCTIONS)) flag_SetFlagIntValue(Flags, flag_SELECT, flag_SELECTALWAYS); else if (ana_GetFeature(Ana,ana_NONUNIT)) flag_SetFlagIntValue(Flags, flag_SELECT, flag_SELECTIFSEVERALMAXIMAL); else flag_SetFlagIntValue(Flags, flag_SELECT, flag_SELECTOFF); if (ana_GetConClauses(Ana) < ana_GetAxiomClauses(Ana) || (ana_GetFeature(Ana,ana_CONGROUND) && !ana_GetFeature(Ana,ana_PUREPROPOSITIONAL))) flag_SetFlagIntValue(Flags, flag_SATINPUT, flag_SATINPUTON); else flag_SetFlagIntValue(Flags, flag_SATINPUT, flag_SATINPUTOFF); if (ana_GetNonHornClauses(Ana) > 0) flag_SetFlagIntValue(Flags, flag_SPLITS, flag_SPLITSUNLIMITED); else flag_SetFlagIntValue(Flags, flag_SPLITS, flag_SPLITSOFF); /* if (ana_GetFeature(Ana,ana_PUREPROPOSITIONAL)) */ /* flag_SetFlagIntValue(Flags, flag_SPLITHEURISTIC, flag_SPLITHEURISTICALWAYS); */ } void ana_ExploitSortAnalysis(ANALYZE Ana, FLAGSTORE Flags) /************************************************************** INPUT: A flag store. EFFECT: If all equations are many sorted and or no positive equations occur at all and the problem contains sort information, static soft typing is activated. ***************************************************************/ { if (ana_GetFeature(Ana,ana_SORTRES) && (!ana_GetFeature(Ana,ana_PEQUATIONS) || ana_GetFeature(Ana,ana_SORTMANYEQUATIONS))) flag_SetFlagIntValue(Flags, flag_RSST, flag_RSSTON); } static LIST ana_CalculatePredicatePrecedence(LIST Predicates, LIST Clauses) /************************************************************** INPUT: A list of predicates and a list of clauses. RETURNS: A list of predicate symbols, which should be used for setting the symbol precedence. The list is sorted in descending order, that means predicates with highest precedence come first. EFFECT: Analyze the clause list to build a directed graph G where the predicates are vertices. There's an edge (P,Q) in G iff a clause exists where P is a negative literal and Q is a positive literal and P != Q. Apply DFS to find the strongly connected components of this graph. The list is deleted. CAUTION: The predicate list must contain ALL predicates occurring in the clause list! ***************************************************************/ { GRAPH graph; LIST result, scan; int i, j; NAT count; SYMBOL s; /* clause_ListPrint(Clauses); DBG */ if (list_Empty(Predicates)) { return Predicates; } graph = graph_Create(); /* First create the nodes: one node for every predicate symbol. */ for ( ; !list_Empty(Predicates); Predicates = list_Pop(Predicates)) graph_AddNode(graph, symbol_Index((SYMBOL)list_Car(Predicates))); /* Now scan the clause clause list to create the edges */ /* An edge (P,Q) means P is smaller than Q */ for (scan = Clauses; !list_Empty(scan); scan = list_Cdr(scan)) { CLAUSE c = list_Car(scan); for (i = clause_FirstLitIndex(); i < clause_FirstSuccedentLitIndex(c); i++) { SYMBOL negPred = term_TopSymbol(clause_GetLiteralAtom(c, i)); if (!symbol_Equal(negPred, fol_Equality())) { /* negative predicate */ for (j = clause_FirstSuccedentLitIndex(c); j < clause_Length(c); j++) { SYMBOL posPred = term_TopSymbol(clause_GetLiteralAtom(c, j)); if (!symbol_Equal(posPred, fol_Equality()) && /* positive predicate */ negPred != posPred) { /* No self loops! */ graph_AddEdge(graph_GetNode(graph, symbol_Index(negPred)), graph_GetNode(graph, symbol_Index(posPred))); } } } } } /* graph_Print(graph); fflush(stdout); DBG */ /* Calculate the strongly connected components of the graph */ count = 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(); for (i = count - 1; i >= 0; i--) { for (scan = graph_Nodes(graph); !list_Empty(scan); scan = list_Cdr(scan)) { GRAPHNODE n = list_Car(scan); if (graph_NodeCompNum(n) == i) { /* The symbol represented by the node < belongs to component */ s = symbol_GetSigSymbol(graph_NodeNumber(n)); 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); putchar(' '); } putchar('\n'); fflush(stdout); DBG */ graph_Delete(graph); return result; } /* We use the node info to store the degree of the node */ NAT ana_NodeDegree(GRAPHNODE Node) { return (NAT)graph_NodeInfo(Node); } void ana_IncNodeDegree(GRAPHNODE Node) { graph_NodeSetInfo(Node, (POINTER)(ana_NodeDegree(Node)+1)); } static BOOL ana_NodeGreater(GRAPHNODE N1, GRAPHNODE N2) /************************************************************** INPUT: Two graph nodes. RETURNS: TRUE, if N1 is greater than N2. EFFECT: This function is used to sort the node list of the graph in ana_CalculateFunctionPrecedence. ***************************************************************/ { return (symbol_Arity(symbol_GetSigSymbol(graph_NodeNumber(N1))) > symbol_Arity(symbol_GetSigSymbol(graph_NodeNumber(N2)))); } static BOOL ana_BidirectionalDistributivity(LIST SymbolPairs) /************************************************************** INPUT: A list of symbol pairs defining distributivity. RETURNS: TRUE, if the list contains two pairs (s1, s2) and (s2, s1) FALSE otherwise. EFFECT: This function is used to detect symbols that are distributive in both directions, logical OR and AND for example. ***************************************************************/ { LIST scan, actPair, nextPair; for ( ; !list_Empty(SymbolPairs); SymbolPairs = list_Cdr(SymbolPairs)) { actPair = list_Car(SymbolPairs); /* If actPair = (s1, s2), check whether there's a pair (s2, s1) in list */ for (scan = list_Cdr(SymbolPairs); !list_Empty(scan); scan = list_Cdr(scan)) { nextPair = list_Car(scan); if (symbol_Equal((SYMBOL)list_PairFirst(actPair),(SYMBOL)list_PairSecond(nextPair)) && symbol_Equal((SYMBOL)list_PairSecond(actPair),(SYMBOL)list_PairFirst(nextPair))) return TRUE; } } return FALSE; } static LIST ana_CalculateFunctionPrecedence(ANALYZE Ana, LIST Functions, LIST Clauses, FLAGSTORE Flags) /************************************************************** INPUT: An analyze object, 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_GetFeature(Ana,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 */ 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. */ /* 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 belongs to component */ 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; } spass-3.9/analyze.h000066400000000000000000000155211325017163600143420ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * ANALYSIS OF CLAUSE SETS * */ /* * * */ /* * $Module: ANALYZE * */ /* * * */ /* * 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.4 $ * */ /* $State: Exp $ * */ /* $Date: 2011-05-22 09:05:45 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: analyze.h,v $ */ #ifndef _ANALYZE_ #define _ANALYZE_ #include "memory.h" #include "clause.h" #include "sort.h" #include "list.h" #include "graph.h" /**************************************************************/ /* Data Structures and Constants */ /**************************************************************/ typedef enum { ana_EQUATIONS, /* Problem contains any equations at all */ ana_PEQUATIONS, /* Problem contains positive equations */ ana_NEQUATIONS, /* Problem contains negative equations */ ana_FUNCTIONS, /* Problem contains non-constant function symbols */ ana_PROP, /* Problem contains propositional variables */ ana_GROUND, /* Problem contains non-propositional, non-equational ground atoms */ ana_NONUNIT, /* Problem contains non-unit clauses */ ana_MONADIC, /* Problem contains non-ground monadic predicates */ ana_NONMONADIC, /* Problem contains non-ground n-place predicates, n>1, not equality */ ana_SORTRES, /* Problem contains literal not(S(x)) for some S */ ana_USORTRES, /* Problem contains literal not(S(t)) for some S */ ana_FINDOMAIN, /* Problem contains clause implying a finite domain */ ana_NONTRIVDOMAIN, /* Problem contains clause implying a domain of size greater one */ ana_CONGROUND, /* Conjecture is ground */ ana_TRANSITIVITY, /* Problem contains transitivity axiom for some predicate exploited by chaining */ ana_PUREEQUATIONAL, /* Problem is purely equational */ ana_PUREPROPOSITIONAL, /* Problem is purely propositional */ ana_SORTDECEQUATIONS, /* True if all positive equations are sort decreasing with respect to the static sort theory contained in the problem */ ana_SORTMANYEQUATIONS, /* True if all positive equations have the same sort on left and right hand side with respect to the static sort theory contained in the problem */ ana_MAXFEATURE /* ana_MAXFEATURE is a final Dummy */ } ANA_FEATUREID; typedef struct ANALYZE_HELP { BOOL boolarray[ana_MAXFEATURE]; /*all the boolean features of the problem*/ LIST ana_FINITEMONADICPREDICATES; /* List of monadic predicates with finite extension */ NAT ana_AXIOMCLAUSES; /* Number of axiom clauses */ NAT ana_CONCLAUSES; /* Number of conjecture clauses */ NAT ana_NONHORNCLAUSES; /* Number of Non-Horn clauses */ NAT nontrivclausenumber; LIST transitivityaxioms; /* In the case that chaining is activated, is a list of the */ /* transitivity axiom clauses that have been removed from the input clause set. */ /* The axioms are used to extract the clause number for proof documentation and */ /* possibly to be printed into the model. */ } ANALYZE_NODE; typedef ANALYZE_NODE *ANALYZE; /**************************************************************/ /* Functions */ /**************************************************************/ BOOL ana_GetFeature(ANALYZE, ANA_FEATUREID); BOOL* ana_GetFeatureAddr(ANALYZE, ANA_FEATUREID); void ana_SetFeature(ANALYZE, ANA_FEATUREID, BOOL); int ana_GetAxiomClauses(ANALYZE); int ana_GetConClauses(ANALYZE); int ana_GetNonHornClauses(ANALYZE); void ana_IncAxiomClauses(ANALYZE); void ana_IncConClauses(ANALYZE); void ana_IncNonHornClauses(ANALYZE); void ana_SetAxiomClauses(ANALYZE, int); void ana_SetConClauses(ANALYZE, int); void ana_SetNonHornClauses(ANALYZE, int); LIST ana_GetFinMonPredList(ANALYZE); void ana_SetFinMonPredList(ANALYZE, LIST); NAT ana_NonTrivClauseNumber(ANALYZE); void ana_SetNonTrivClauseNumber(ANALYZE, NAT); void ana_AddTransAxClause(ANALYZE, CLAUSE); LIST ana_GetTransAxClauseList(ANALYZE); void ana_SetTransAxClauseList(ANALYZE, LIST); CLAUSE ana_LookupTransAxClause(ANALYZE, SYMBOL); ANALYZE ana_Init(void); void ana_Clean(ANALYZE); void ana_Free(ANALYZE); void ana_AnalyzeProblem(ANALYZE, FLAGSTORE, LIST); void ana_AnalyzeSortStructure(ANALYZE, LIST, FLAGSTORE, PRECEDENCE); LIST ana_AnalyzeTransitivity(ANALYZE, LIST); void ana_AutoConfiguration(ANALYZE, LIST, FLAGSTORE, PRECEDENCE); void ana_ExploitSortAnalysis(ANALYZE,FLAGSTORE); void ana_Print(ANALYZE, FLAGSTORE, PRECEDENCE); #endif spass-3.9/approx.c000066400000000000000000001145161325017163600142070ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * CLAUSE APPROXIMATION * */ /* * * */ /* * $Module: APPROX * */ /* * * */ /* * Copyright (C) 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.4 $ * */ /* $State: Exp $ * */ /* $Date: 2013-10-21 08:38:45 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: approx.c,v $ */ #include #include "approx.h" #include "clause.h" static NAT approx_PREDICATECOUNTER; /* Used by approx_MonadicFlattenHeads */ static SYMBOL approx_TRUESYMBOL; /* Used by approx_MonadicByTermEncoding */ const char approx_TRUENAME[] = "True"; typedef struct { SYMBOL original; LIST newSymbols; } APPROX_NODE, *APPROX_TRANSLATION; void approx_Init(void) /************************************************************** INPUT: None. RETURNS: Nothing. EFFECT: Initialize the module's variables. ***************************************************************/ { approx_PREDICATECOUNTER = 0; approx_TRUESYMBOL = symbol_Null(); } static void approx_DeleteTranslation(LIST Translation) /************************************************************** INPUT: A list of APPROX_TRANSLATIONs. RETURNS: Nothing. EFFECT: All memory used by the translation is freed. ***************************************************************/ { for ( ; !list_Empty(Translation); Translation = list_Pop(Translation)) { APPROX_TRANSLATION t; t = list_Car(Translation); list_Delete(t->newSymbols); memory_Free(t, sizeof(APPROX_NODE)); } } static APPROX_TRANSLATION approx_LookupTranslationSymbols(LIST Translation, SYMBOL Symbol) /************************************************************** INPUT: A list of APPROX_TRANSLATIONs and a symbol. RETURNS: If the list contains a translation for the , the corresponding APPROX_TRANSLATION is returned, otherwise NULL is returned. ***************************************************************/ { APPROX_TRANSLATION trans; for (trans = NULL; trans == NULL && !list_Empty(Translation); Translation = list_Cdr(Translation)) { SYMBOL s = ((APPROX_TRANSLATION)list_Car(Translation))->original; if (symbol_Equal(Symbol, s)) trans = list_Car(Translation); } return trans; } /**************************************************************/ /* Help functions for approx_MonadicByProjection */ /**************************************************************/ static APPROX_TRANSLATION approx_CreateProjectionSymbols(SYMBOL Symbol, PRECEDENCE Precedence) /************************************************************** INPUT: A n-ary predicate symbol and a precedence. RETURNS: An APPROX_TRANSLATION containing n new, unary predicate symbols. EFFECT: When the symbol's name is then n new predicates with the names 1, 2, ..., n are created. The precedence of the new symbols is set in . ***************************************************************/ { APPROX_TRANSLATION Result; SYMBOL Predicate; NAT Suffix, Arity; int i; Result = (APPROX_TRANSLATION) memory_Malloc(sizeof(APPROX_NODE)); Result->original = Symbol; Result->newSymbols = list_Nil(); Arity = symbol_Arity(Symbol); /* If has arity create new symbols */ for (i = 1; i <= Arity; ++i) { char* approx_BUFFER = NULL; Suffix = i; /* Ensure that new symbol wasn't previously defined */ do { char* SuffixStr = string_IntToString(Suffix++); if (approx_BUFFER) string_StringFree(approx_BUFFER); approx_BUFFER = string_Conc(symbol_Name(Symbol),SuffixStr); string_StringFree(SuffixStr); } while (symbol_Lookup(approx_BUFFER) != 0); Predicate = symbol_CreatePredicate(approx_BUFFER,1,symbol_STATLEX,Precedence); Result->newSymbols = list_Cons((POINTER)Predicate, Result->newSymbols); string_StringFree(approx_BUFFER); } Result->newSymbols = list_NReverse(Result->newSymbols); return Result; } static LIST approx_ApplyProjection(APPROX_TRANSLATION Translation, CLAUSE Clause, int LitIndex, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: An APPROX_TRANSLATION, a clause, a literal index within the clause, a flag store and a precedence. RETURNS: A list of new clauses generated from . EFFECT: The non-monadic literal with arity n at index is replaced by monadic literals, resulting in n new clauses. The flag store and the precedence are needed to create the new clauses. ***************************************************************/ { SYMBOL Symbol; LIST Result, Scan, ArgScan; TERM Atom, NewAtom; CLAUSE NewClause; Result = list_Nil(); Atom = clause_GetLiteralAtom(Clause, LitIndex); /* Now create the new clauses */ if (LitIndex <= clause_LastAntecedentLitIndex(Clause)) { /* A negative literal, so create a single clause */ LIST Constraint, Antecedent, Succedent; int i; Constraint = clause_CopyConstraint(Clause); Antecedent = list_Nil(); Succedent = clause_CopySuccedent(Clause); for (i = clause_FirstAntecedentLitIndex(Clause); i <= clause_LastAntecedentLitIndex(Clause); i++) { if (i != LitIndex) { NewAtom = term_Copy(clause_GetLiteralAtom(Clause, i)); Antecedent = list_Cons(NewAtom, Antecedent); } else { for (Scan = Translation->newSymbols, ArgScan = term_ArgumentList(Atom); !list_Empty(Scan); Scan = list_Cdr(Scan), ArgScan = list_Cdr(ArgScan)) { Symbol = (SYMBOL) list_Car(Scan); /* The new Predicate */ /* Create the new monadic atom */ NewAtom = term_Create(Symbol, list_List(term_Copy(list_Car(ArgScan)))); Antecedent = list_Cons(NewAtom, Antecedent); } } } /* create the new clause */ NewClause = clause_Create(Constraint,Antecedent,Succedent,Flags,Precedence); if (clause_GetFlag(Clause, CONCLAUSE)) clause_SetFlag(NewClause, CONCLAUSE); clause_Normalize(NewClause); clause_UpdateWeight(NewClause, Flags); clause_UpdateMaxVar(NewClause); Result = list_Cons(NewClause, Result); /* clean up */ list_Delete(Constraint); list_Delete(Antecedent); list_Delete(Succedent); } else { /* A positive literal, so create a set of clauses */ for (Scan = Translation->newSymbols, ArgScan = term_ArgumentList(Atom); !list_Empty(Scan); Scan = list_Cdr(Scan), ArgScan = list_Cdr(ArgScan)) { Symbol = (SYMBOL) list_Car(Scan); /* The new Predicate */ /* Create the new monadic atom */ Atom = term_Create(Symbol, list_List(term_Copy(list_Car(ArgScan)))); NewClause = clause_Copy(Clause); /* Delete the old literal */ clause_LiteralDelete(clause_GetLiteral(NewClause,LitIndex)); /* and replace it with the new one */ clause_SetLiteral(NewClause, LitIndex, clause_LiteralCreate(Atom, NewClause)); clause_Normalize(NewClause); clause_UpdateWeight(NewClause, Flags); clause_UpdateMaxVar(NewClause); Result = list_Nconc(Result, list_List(NewClause)); } } return Result; } static LIST approx_ApplyProjectionToList(LIST* Translation, LIST Clauses, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A list of APPROX_TRANSLATIONs, a list of clauses that were approximated from the same "father" clause, a flag store and a precedence. RETURNS: A list of clauses. EFFECT: This recursive function is initially called with a one-element list containing a clause. It searches for a non-monadic literal in the first clause of the list. If there's no such literal the list is just returned. If a non-monadic literal was found, all clauses in the list are transformed in the same way, adding new clauses to the list. Finally the function is called recursively with the new list to check for other non-monadic literals. The flag store and the precedence are needed to create the new clauses. ***************************************************************/ { APPROX_TRANSLATION Trans; CLAUSE Clause; SYMBOL Symbol; LIST Result; BOOL Hit; NAT i; /* Check whether projection is possible for the first clause */ Clause = list_Car(Clauses); for (Hit = FALSE, i = clause_FirstLitIndex(); !Hit && i <= clause_LastLitIndex(Clause); i++) { Symbol = term_TopSymbol(clause_GetLiteralAtom(Clause, i)); if (!symbol_Equal(fol_Equality(),Symbol) && symbol_Arity(Symbol) > 1) Hit = TRUE; } --i; /* Important! */ /* If projection wasn't possible for the first clause, */ /* it isn't possible for the other clauses. */ /* If projection was possible for the first clause, */ /* it's also applicable to the other clauses at the */ /* same literal index. */ if (!Hit) { return Clauses; /* Stop recursion */ } else { Symbol = term_TopSymbol(clause_GetLiteralAtom(Clause, i)); /* Examine whether the symbol was translated earlier */ Trans = approx_LookupTranslationSymbols(*Translation, Symbol); if (Trans == NULL) { /* Symbol not found in translation list */ Trans = approx_CreateProjectionSymbols(Symbol, Precedence); *Translation = list_Cons(Trans, *Translation); } /* Apply projection at literal index */ Result = list_Nil(); for ( ; !list_Empty(Clauses); Clauses = list_Pop(Clauses)) { Result = list_Nconc(Result, approx_ApplyProjection(Trans,list_Car(Clauses),i, Flags, Precedence)); /* Delete the old clause */ clause_Delete(list_Car(Clauses)); } /* recursion */ return approx_ApplyProjectionToList(Translation, Result, Flags, Precedence); } } LIST approx_MonadicByProjection(LIST Clauses, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A list of clauses, a flag store and a precedence. RETURNS: A list of clauses with monadic literals. If a clause contains a n-ary atom P(t_1,...t_n), n clause copies are created where the atom in the i-th new clause is replaced by Pi(t_i). Equality is left unchanged. EFFECT: The original clauses are not changed. Copies are created even if no projection was applied. The flag store and the precedence are needed to create the new clauses. ***************************************************************/ { LIST Result, Translation; Result = Translation = list_Nil(); for ( ; !list_Empty(Clauses); Clauses = list_Cdr(Clauses)) { Result = list_Nconc(Result, approx_ApplyProjectionToList(&Translation, list_List(clause_Copy(list_Car(Clauses))), Flags, Precedence)); } approx_DeleteTranslation(Translation); list_Apply((void (*)(POINTER)) clause_NewNumber, Result); return Result; } /**************************************************************/ /* Help functions for approx_MonadicByTermEncoding */ /**************************************************************/ static APPROX_TRANSLATION approx_CreateFunctionForPredicate(SYMBOL Symbol, PRECEDENCE Precedence) /************************************************************** INPUT: A predicate and a precedence. RETURNS: A one-element list with an APPROX_TRANSLATION for the predicate. EFFECT: If the predicate has the name "P", a function "P_f" is created for the predicate. The precedence of the new symbol is set in . ***************************************************************/ { APPROX_TRANSLATION Result; SYMBOL Predicate; char* approx_BUFFER; char* base; int size, i; Result = (APPROX_TRANSLATION) memory_Malloc(sizeof(APPROX_NODE)); Result->original = Symbol; Result->newSymbols = list_Nil(); size = strlen(symbol_Name(Symbol))+3; base = memory_Malloc(size*sizeof(char)); sprintf(base,"%s_f",symbol_Name(Symbol)); approx_BUFFER = string_StringCopy(base); /* If the predicate symbol name + "_f" is already defined, try additional numbers */ i = 0; while (symbol_Lookup(approx_BUFFER) != 0) { char* Suffix = string_IntToString(++i); string_StringFree(approx_BUFFER); approx_BUFFER = string_Conc(base,Suffix); string_StringFree(Suffix); } Predicate = symbol_CreateFunction(approx_BUFFER, symbol_Arity(Symbol), symbol_STATLEX, Precedence); Result->newSymbols = list_Cons((POINTER)Predicate, Result->newSymbols); string_StringFree(approx_BUFFER); memory_Free(base,size*sizeof(char)); return Result; } static void approx_EncodeClause(LIST* Translation, CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A clause, a list of APPROX_TRANSLATIONs, a flag store and a precedence. RETURNS: Nothing. EFFECT: All non-monadic literals of the clause are transformed into monadic literals. The clause is destructively changed! ***************************************************************/ { APPROX_TRANSLATION Trans; SYMBOL Symbol; TERM Atom; NAT i; for (i = clause_FirstLitIndex(); i <= clause_LastLitIndex(Clause); ++i) { Symbol = term_TopSymbol(clause_GetLiteralAtom(Clause, i)); if (!symbol_Equal(fol_Equality(),Symbol) && symbol_Arity(Symbol) > 1) { Trans = approx_LookupTranslationSymbols(*Translation, Symbol); if (Trans == NULL) { Trans = approx_CreateFunctionForPredicate(Symbol, Precedence); *Translation = list_Cons(Trans, *Translation); } Atom = clause_GetLiteralAtom(Clause, i); term_RplacTop(Atom, (SYMBOL)list_Car(Trans->newSymbols)); Atom = term_Create(approx_TRUESYMBOL, list_List(Atom)); clause_LiteralSetAtom(clause_GetLiteral(Clause, i), Atom); } } /* The weight of the clause has changed */ clause_UpdateWeight(Clause, Flags); } LIST approx_MonadicByTermEncoding(LIST Clauses, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A list of clauses, a flag store and a precedence. RETURNS: A list of clauses with monadic literals. A non-monadic literal P(t1,t2,...) is translated to True(p(t1,t2,...)) where p is a function with the same arity as P and True is a special predicate with boolean domain. Equality literals are left unchanged. EFFECT: The clauses are not changed. This transformation is satisfiability preserving. The flag store and the precedence are needed to create the new clauses. ***************************************************************/ { LIST Result, Translation; NAT i; /* Ensure that the special predicate "True" is defined */ if (symbol_Equal(approx_TRUESYMBOL, symbol_Null())) { char* approx_BUFFER; i = 0; approx_BUFFER = string_StringCopy(approx_TRUENAME); while (symbol_Lookup(approx_BUFFER) != 0) { char* Suffix = string_IntToString(++i); string_StringFree(approx_BUFFER); approx_BUFFER = string_Conc(approx_TRUENAME,Suffix); string_StringFree(Suffix); } approx_TRUESYMBOL = symbol_CreatePredicate(approx_BUFFER, 1, symbol_STATLEX, Precedence); string_StringFree(approx_BUFFER); } Translation = list_Nil(); Result = clause_CopyClauseList(Clauses); for (Clauses = Result; !list_Empty(Clauses); Clauses = list_Cdr(Clauses)) { approx_EncodeClause(&Translation, list_Car(Clauses), Flags, Precedence); } approx_DeleteTranslation(Translation); list_Apply((void (*)(POINTER)) clause_NewNumber, Result); return Result; } /**************************************************************/ /* Help functions for approx_MonadicMakeLinear */ /**************************************************************/ static LIST approx_MakeTermLinear(TERM Term, NAT Mark) /************************************************************** INPUT: A TERM and the current term binding mark. RETURNS: A list of pairs (oldvar, newvar) of variable renamings. EFFECT: The term is destructively changed. The variables within Term are made unique with respect to previous variable occurrences since the last term_StartBinding call. ***************************************************************/ { LIST Scan, Result; SYMBOL s; Result = list_Nil(); if (term_IsComplex(Term)) { for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) Result = list_Nconc(approx_MakeTermLinear(list_Car(Scan),Mark), Result); } else { s = term_TopSymbol(Term); if (symbol_IsVariable(s)) { if (term_VarIsMarked(s, Mark)) { term_RplacTop(Term, symbol_CreateStandardVariable()); Result = list_Cons(list_PairCreate((POINTER)s,(POINTER)term_TopSymbol(Term)), Result); } else { term_CreateValueBinding(s, Mark, NULL); } } } return Result; } static CLAUSE approx_MakeClauseLinear(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A clause with monadic positive literals, a flag store and a precedence RETURNS: The linear approximation of the clause. EFFECT: The original clause is not changed. The flag store and the precedence are needed to create the new clause. CAUTION: The MaxVar info of the clause must be up to date! ***************************************************************/ { LIST Renamings, Scan, Constraint, Antecedent, Succedent; SYMBOL NewVar, OldVar; CLAUSE NewClause; TERM Atom, NewAtom; NAT Mark; int i; #ifdef DEBUG if (term_InBindingPhase()) { misc_StartErrorReport(); misc_ErrorReport("\n In approx_makeClauseLinear: Function called inside binding phase.\n"); misc_FinishErrorReport(); } #endif if (clause_NumOfSuccLits(Clause) == 0) return clause_Copy(Clause); for (i = clause_FirstLitIndex(); i <= clause_LastLitIndex(Clause); ++i) { Atom = clause_GetLiteralAtom(Clause, i); if (fol_IsEquality(Atom) || !term_IsDeclaration(Atom)) return clause_Copy(Clause); } /* Ensure that all new variables don't occur in the clause */ symbol_SetStandardVarCounter(clause_MaxVar(Clause)); term_StartBinding(); Mark = term_ActMark(); Constraint = Antecedent = Succedent = list_Nil(); Renamings = list_Nil(); /* Make the positive literals linear */ for (i = clause_LastSuccedentLitIndex(Clause); i >= clause_FirstSuccedentLitIndex(Clause); --i) { Atom = term_Copy(clause_GetLiteralAtom(Clause, i)); Succedent = list_Cons(Atom, Succedent); Renamings = list_Nconc(approx_MakeTermLinear(Atom, Mark), Renamings); } term_StopBinding(); /* Now examine the negative literals */ for (i = clause_LastAntecedentLitIndex(Clause); i >= clause_FirstConstraintLitIndex(Clause); --i) { /* Keep a copy of the original literal */ Atom = term_Copy(clause_GetLiteralAtom(Clause, i)); if (i <= clause_LastConstraintLitIndex(Clause)) Constraint = list_Cons(Atom, Constraint); else Antecedent = list_Cons(Atom, Antecedent); for (Scan = Renamings; !list_Empty(Scan); Scan = list_Cdr(Scan)) { OldVar = (SYMBOL) list_PairFirst(list_Car(Scan)); NewVar = (SYMBOL) list_PairSecond(list_Car(Scan)); if (term_ContainsSymbol(Atom, OldVar)) { NewAtom = term_Copy(Atom); term_ExchangeVariable(NewAtom, OldVar, NewVar); /* Add additional literals for renamed variables */ if (i <= clause_LastConstraintLitIndex(Clause)) Constraint = list_Cons(NewAtom, Constraint); else Antecedent = list_Cons(NewAtom, Antecedent); } } } /* Create the new clause */ NewClause = clause_Create(Constraint,Antecedent,Succedent,Flags,Precedence); if (clause_GetFlag(Clause, CONCLAUSE)) clause_SetFlag(NewClause, CONCLAUSE); /* clean up */ list_Delete(Constraint); list_Delete(Antecedent); list_Delete(Succedent); list_DeletePairList(Renamings); return NewClause; } LIST approx_MonadicMakeLinear(LIST Clauses, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A list of clauses, a flag store and a precedence. RETURNS: A list of copies of the clauses. EFFECT: The entire succedent of a clause is made linear if all literals of are monadic. The original clauses are not changed, the clauses are copied even if no transformation was applied. For every variable renaming X -> Y, that is necessary to make the positive literals linear, we collect all negative literals P(t) containing X and add new negative literals P(t) where X is replaced by Y. The flag store and the precedence are needed to create the new clauses. CAUTION: The MaxVar info of the clause must be up to date! ***************************************************************/ { LIST Result, Scan; Result = list_Copy(Clauses); for (Scan = Result; !list_Empty(Scan); Scan = list_Cdr(Scan)) list_Rplaca(Scan, approx_MakeClauseLinear(list_Car(Scan),Flags,Precedence)); return Result; } /**************************************************************/ /* Help functions for approx_MonadicFlattenHeads */ /**************************************************************/ static TERM approx_ReplaceSubterms(TERM Term, LIST Duplicates, TERM NewVarTerm) /************************************************************** INPUT: A term, a list of terms that are possibly subterms of , and a third term, that consists of a variable. RETURNS: A copy of where all subterms that are element of the list are replaced by a copy of . Note that pointers are used to check for equality of terms. ***************************************************************/ { if (list_PointerMember(Duplicates, Term)) return term_Copy(NewVarTerm); else { LIST Arguments, Scan; Arguments = list_Copy(term_ArgumentList(Term)); for (Scan = Arguments; !list_Empty(Scan); Scan = list_Cdr(Scan)) list_Rplaca(Scan, approx_ReplaceSubterms(list_Car(Scan),Duplicates, NewVarTerm)); return term_Create(term_TopSymbol(Term), Arguments); } } static LIST approx_ApplyFlattening(CLAUSE Clause, LIST Duplicates, BOOL CheckNegativeLiterals, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A horn clause with one positive literal, a list of terms that shall be replaced by some new variable, a boolean flag indicating which transformation will be applied, a flag store and a precedence. Note that contains all occurrences of a complex subterm of the single positive atom of . RETURNS: A list of two clauses. EFFECT: The is not changed. A new predicate with a name starting with "Fl" is created. See approx_MonadicFlattenHeads for more details. ***************************************************************/ { LIST Constraint1, Antecedent1, Succedent1; /* literals for 1st clause */ LIST Constraint2, Antecedent2, Succedent2; /* literals for 2nd clause */ LIST VarsInTerm; TERM Term, NewVarTerm; SYMBOL NewPredicate; CLAUSE Clause1, Clause2; int i; char* approx_BUFFER; const char* base; /* The set of variables of the subterm is required both for */ /* transformation 1) and 2) (CheckNegative=TRUE, CheckVar arbitrary). */ if (CheckNegativeLiterals) VarsInTerm = term_VariableSymbols(list_Car(Duplicates)); else VarsInTerm = list_Nil(); Constraint1 = Antecedent1 = Succedent1 = list_Nil(); Constraint2 = Antecedent2 = Succedent2 = list_Nil(); for (i = clause_LastAntecedentLitIndex(Clause); i >= clause_FirstConstraintLitIndex(Clause); --i) { SYMBOL Var; Term = term_Copy(clause_GetLiteralAtom(Clause, i)); /* an atom */ Var = term_TopSymbol(term_FirstArgument(Term)); if (i <= clause_LastConstraintLitIndex(Clause)) { if (CheckNegativeLiterals) { if (list_PointerMember(VarsInTerm, (POINTER)Var)) Constraint2 = list_Cons(Term, Constraint2); else Constraint1 = list_Cons(Term, Constraint1); } else { /* copy the constraint for both clauses */ Constraint1 = list_Cons(Term, Constraint1); Constraint2 = list_Cons(term_Copy(Term), Constraint2); } } else { if (CheckNegativeLiterals) { if (list_PointerMember(VarsInTerm, (POINTER)Var)) Antecedent2 = list_Cons(Term, Antecedent2); else Antecedent1 = list_Cons(Term, Antecedent1); } else { /* copy the antecedent for both clauses */ Antecedent1 = list_Cons(Term, Antecedent1); Antecedent2 = list_Cons(term_Copy(Term), Antecedent2); } } } list_Delete(VarsInTerm); /* Create a new predicate */ base = "Fl"; approx_BUFFER = string_StringCopy(base); /* Ensure that new symbol wasn't previously defined */ do { char* Suffix = string_IntToString(++approx_PREDICATECOUNTER); string_StringFree(approx_BUFFER); approx_BUFFER = string_Conc(base,Suffix); string_StringFree(Suffix); } while (symbol_Lookup(approx_BUFFER) != 0); NewPredicate = symbol_CreatePredicate(approx_BUFFER,1,symbol_STATLEX,Precedence); string_StringFree(approx_BUFFER); /* Create a new variable not occurring in the clause */ symbol_SetStandardVarCounter(clause_MaxVar(Clause)); NewVarTerm = term_CreateStandardVariable(); /* Add the new negative literal to the first clause */ Antecedent1 = list_Cons(term_Create(NewPredicate, list_List(NewVarTerm)), Antecedent1); /* Now create the succedent of the first result clause. To do this we have */ /* to replace all occurrences of the subterm by the new variable. */ Term = clause_GetLiteralAtom(Clause, clause_FirstSuccedentLitIndex(Clause)); Succedent1 = list_List(approx_ReplaceSubterms(Term, Duplicates, NewVarTerm)); /* Create the succedent of the second result clause */ Term = term_Copy(list_Car(Duplicates)); Succedent2 = list_List(term_Create(NewPredicate, list_List(Term))); Clause1 = clause_Create(Constraint1, Antecedent1, Succedent1,Flags,Precedence); Clause2 = clause_Create(Constraint2, Antecedent2, Succedent2,Flags,Precedence); if (clause_GetFlag(Clause, CONCLAUSE)) { clause_SetFlag(Clause1, CONCLAUSE); clause_SetFlag(Clause2, CONCLAUSE); } /* cleanup */ list_Delete(Constraint1); list_Delete(Antecedent1); list_Delete(Succedent1); list_Delete(Constraint2); list_Delete(Antecedent2); list_Delete(Succedent2); return list_Cons(Clause1, list_List(Clause2)); } static LIST approx_GetDuplicatesAndCheckVariables(TERM Atom, TERM ComplexTerm, BOOL CheckVariables) /************************************************************** INPUT: An atom, a subterm of the atom, and a boolean flag. RETURNS: Let be the with all duplicates of replaced by some constant. This function returns the empty list if is true and shares any variable with . Otherwise the list of all duplicates of in is returned. ***************************************************************/ { NAT Stack, ActMark; LIST Result; #ifdef CHECK if (term_InBindingPhase()) { misc_StartErrorReport(); misc_ErrorReport("\n In approx_CheckVariables: Called while in variable "); misc_ErrorReport("binding phase."); misc_FinishErrorReport(); } #endif term_StartBinding(); ActMark = term_ActMark(); Result = list_Nil(); Stack = stack_Bottom(); /* Mark all variables from */ term_MarkVariables(ComplexTerm, ActMark); term_StopBinding(); do { if (term_Equal(Atom, ComplexTerm)) Result = list_Cons(Atom, Result); else { if (CheckVariables && term_IsVariable(Atom) && term_VarIsMarked(term_TopSymbol(Atom), ActMark)) { /* Variable from occurs in the rest of */ list_Delete(Result); stack_SetBottom(Stack); return list_Nil(); } else stack_Push(term_ArgumentList(Atom)); } while (!stack_Empty(Stack) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(Stack)) { Atom = list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(Stack)); return Result; } static LIST approx_OneFlatteningStep(CLAUSE Clause, BOOL CheckVarCondition, BOOL CheckNegativeLiterals, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A horn clause, two boolean flags, a flag store and a precedence. RETURNS: An empty list, if the clause wasn't flattened, else a list of clauses resulting from the flattening of the clause. EFFECT: The is not changed. ***************************************************************/ { TERM Atom, Term; LIST Result; NAT Stack; /* Nothing to do if clause has no positive literal */ if (clause_NumOfSuccLits(Clause) != 1) return list_Nil(); /* Get the atom of the only positive literal */ Atom = clause_GetLiteralAtom(Clause, clause_FirstSuccedentLitIndex(Clause)); if (fol_IsEquality(Atom) || !term_IsDeclaration(Atom)) { /* positive literal is equality or isn't monadic */ return list_Nil(); } Term = term_FirstArgument(Atom); /* the term of the monadic literal */ Stack = stack_Bottom(); /* Start with the arguments of the term, not the term itself */ stack_Push(term_ArgumentList(Term)); do { 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())); if (term_IsComplex(Term)) { /* replace only complex terms */ LIST duplicates; duplicates = approx_GetDuplicatesAndCheckVariables(Atom, Term, CheckVarCondition); if (list_Empty(duplicates)) /* Var condition had to be checked but was violated */ stack_Push(term_ArgumentList(Term)); else { /* Apply rule */ Result = approx_ApplyFlattening(Clause, duplicates, CheckNegativeLiterals, Flags, Precedence); list_Delete(duplicates); stack_SetBottom(Stack); return Result; } } } } while (!stack_Empty(Stack)); return list_Nil(); } LIST approx_HornMonadicFlattenHeads(CLAUSE Clause, BOOL CheckVarCondition, BOOL CheckNegativeLiterals, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A clause, two boolean flags, a flag store and a precedence. RETURNS: An empty list, if the clause wasn't flattened, else the list of clauses resulting from the flattening of the clause. EFFECT: This function implements three kinds of flattening that require all literals in to be monadic and is Horn: 1) CheckVarCondition=TRUE, CheckNegativeLiterals=TRUE C || D -> P(t[s]_p) --------------------------- Fl(x) C1 || D1 -> P(t[p/x]) C2 || D2 -> Fl(s) all terms in C, D are variables, where s is a complex term at the non-top position p, Var(s) is disjoint from Var(P(t[p/c])) (where c is an arbitrary constant), x is a new variable, Fl is a new predicate, L\in C2 if Var(L) \subset Var(s), L\in D2 if Var(L) \subset Var(s), C1 and C2 are a partition of C, D1 and D2 are a partition of D This transformation is equivalence preserving with respect to the extension of P in the minimal model. 2) CheckVarCondition=FALSE, CheckNegativeLiterals=TRUE This setting does the same transformation as above, but doesn't require that Var(s) is disjoint from Var(P(t[p/c])). This transformation is an upper approximation of P. 3) CheckVarCondition=FALSE, CheckNegativeLiterals=FALSE C || D -> P(t[s]_p) ------------------ Fl(x) C || D -> P(t[p/x]) C || D -> Fl(s) where C and D may contain non-variable terms and s and t[p/c] may share variables This transformation is an upper approximation of P. These transformations are recursively applied. The itself is not changed. If the clause doesn't meet the requirements an empty list is returned. MEMORY : is not changed, the result consists of newly generated clauses. ***************************************************************/ { LIST Result, Queue, NewClauses; CLAUSE ActClause; TERM Term; BOOL FirstTime; int i; #ifdef DEBUG if (CheckVarCondition && !CheckNegativeLiterals) { misc_StartErrorReport(); misc_ErrorReport("\n In approx_MonadicFlattenHeads: Illegal input parameters.\n"); misc_FinishErrorReport(); } #endif /* Apply transformation only to clauses with a single positive literal */ if (clause_NumOfSuccLits(Clause) != 1) return list_Nil(); /* Check the negative literals */ for (i = clause_FirstConstraintLitIndex(Clause); i <= clause_LastAntecedentLitIndex(Clause); ++i) { Term = clause_GetLiteralAtom(Clause, i); /* an atom */ if (fol_IsEquality(Term) || !term_IsDeclaration(Term)) { /* negative literal isn't monadic */ return list_Nil(); } if (CheckNegativeLiterals && !term_IsVariable(term_FirstArgument(Term))) { /* negative literal hasn't simple variable as argument */ return list_Nil(); } } Result = list_Nil(); FirstTime = TRUE; Queue = list_List(Clause); /* Initialize the queue with the first clause */ do { ActClause = list_NCar(&Queue); NewClauses = approx_OneFlatteningStep(ActClause, CheckVarCondition, CheckNegativeLiterals, Flags, Precedence); if (list_Empty(NewClauses)) { /* ActClause is finished */ Result = list_Cons(ActClause, Result); } else { /* ActClause was transformed */ Queue = list_Nconc(NewClauses, Queue); /* Delete temporary clauses */ if (!FirstTime) /* Avoid deletion of the initial clause */ clause_Delete(ActClause); } FirstTime = FALSE; } while (!list_Empty(Queue)); if (list_Empty(list_Cdr(Result))) { /* list contains only the original clause */ list_Delete(Result); return list_Nil(); } else return list_NReverse(Result); } /**************************************************************/ /* approx_MakeHorn */ /**************************************************************/ LIST approx_MakeHorn(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A clause, a flag store and a precedence. RETURNS: An empty list if is already a horn clause, otherwise a list of horn clauses resulting from . EFFECT: A non-horn clause with n positive literals is replaced by n horn clauses. The i-th horn clause has the i-th positive literal from as only positive literal. The flag store and the precedence are needed to create the new clauses. ***************************************************************/ { LIST Result, Constraint, Antecedent, Succedent; int i; Result = list_Nil(); if (!clause_IsHornClause(Clause)) { Constraint = Antecedent = list_Nil(); /* Collect constraint atoms */ for (i = clause_LastConstraintLitIndex(Clause); i >= clause_FirstConstraintLitIndex(Clause); --i) Constraint = list_Cons(clause_GetLiteralAtom(Clause, i), Constraint); /* Collect antecedent atoms */ for (i = clause_LastAntecedentLitIndex(Clause); i >= clause_FirstAntecedentLitIndex(Clause); --i) Antecedent = list_Cons(clause_GetLiteralAtom(Clause, i), Antecedent); for (i = clause_FirstSuccedentLitIndex(Clause); i <= clause_LastSuccedentLitIndex(Clause); ++i) { CLAUSE NewClause; /* Copy constraint and antecedent atoms */ term_CopyTermsInList(Constraint); term_CopyTermsInList(Antecedent); Succedent = list_List(term_Copy(clause_GetLiteralAtom(Clause, i))); NewClause = clause_Create(Constraint,Antecedent,Succedent,Flags,Precedence); if (clause_GetFlag(Clause, CONCLAUSE)) clause_SetFlag(NewClause, CONCLAUSE); list_Delete(Succedent); Result = list_Cons(NewClause, Result); } list_Delete(Constraint); list_Delete(Antecedent); } return list_NReverse(Result); } spass-3.9/approx.h000066400000000000000000000053541325017163600142130ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * CLAUSE APPROXIMATION * */ /* * * */ /* * $Module: APPROX * */ /* * * */ /* * Copyright (C) 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.2 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:57 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: approx.h,v $ */ #ifndef _APPROX_ #define _APPROX_ #include "list.h" #include "clause.h" void approx_Init(void); LIST approx_MonadicByProjection(LIST, FLAGSTORE, PRECEDENCE); LIST approx_MonadicByTermEncoding(LIST, FLAGSTORE, PRECEDENCE); LIST approx_MonadicMakeLinear(LIST, FLAGSTORE, PRECEDENCE); LIST approx_HornMonadicFlattenHeads(CLAUSE, BOOL, BOOL, FLAGSTORE, PRECEDENCE); LIST approx_MakeHorn(CLAUSE, FLAGSTORE, PRECEDENCE); #endif spass-3.9/array.c000066400000000000000000000353431325017163600140140ustar00rootroot00000000000000/************************************************************/ /************************************************************/ /** **/ /** ARRAY **/ /** **/ /** Growable array with bound checks. **/ /** **/ /** **/ /** Author: Martin Suda **/ /** **/ /** This program is free software; you can redistribute **/ /** it and/or modify it under the terms of the FreeBSD **/ /** Licence. **/ /** **/ /** 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 LICENCE file **/ /** for more details. **/ /** **/ /************************************************************/ /************************************************************/ #include "array.h" /**************************************************************/ /* Functions */ /**************************************************************/ void array_Init(void) /************************************************************** INPUT: None. RETURNS: void. SUMMARY: Placebo satisfying the general module layout. ***************************************************************/ { return; } void array_Free(void) /************************************************************** INPUT: None. RETURNS: void. SUMMARY: Placebo satisfying the general module layout. ***************************************************************/ { return; } ARRAY array_Create(int init, int extend) /************************************************************** INPUT: Initial capacity and increase in % of the array. Should be positive! RETURNS: A new array of the specified capacity and size = 0. MEMORY: Allocates a new array struct and the internal array itself plus NULL initialization. . ***************************************************************/ { ARRAY ar; int i; ar = (ARRAY)memory_Malloc(sizeof(ARRAY_NODE)+init*sizeof(intptr_t)); ar->size = 0; ar->extend = extend; ar->capacity = init; for(i=0;idata[i] = (intptr_t)NULL; return ar; } void array_Claim(ARRAY ar) /************************************************************** EFFECT: Let all the allocated part be accessible. The content the newly accessible cells is init to zeros. ***************************************************************/ { int i; for(i = ar->size; i < ar->capacity; i++) ar->data[i] = (intptr_t)NULL; ar->size = ar->capacity; } ARRAY array_DeleteIndex(ARRAY ar, int idx) /************************************************************** INPUT: Pointer to the array and an index. RETURNS: The updated array with the element at index deleted and the rest (higher indexed elemets) shitfed left by 1. ***************************************************************/ { int i; /*ASSERT((idx >= 0) && (idx < ar->size));*/ for(i = idx+1; i < ar->size; i++ ) ar->data[i-1] = ar->data[i]; ar->size--; return ar; } ARRAY array_Clean(ARRAY ar) /************************************************************** INPUT: Pointer to the array. RETURNS: The same array with all elements deleted. NOTE: Just sets size to 0, capacity remains untoutched. ***************************************************************/ { ar->size = 0; return ar; } int array_GetSize(ARRAY ar) /************************************************************** INPUT: Pointer to the array. RETURNS: The current size of the array. ***************************************************************/ { return ar->size; } ARRAY array_Add(ARRAY ar, intptr_t el) /************************************************************** INPUT: A pointer to the array and element. RETURNS: The updated array with the element added to the end and size increased by one. MEMORY: If the capacity is reached, capacity is doubled, new internal array allocated and the content copied. ***************************************************************/ { if (ar->size==ar->capacity) { int oldcap; oldcap = ar->capacity; ar->capacity = (ar->capacity * ar->extend)/100 + ar->capacity + 1; /*added + ar->capacity*/ ar = memory_Realloc(ar,sizeof(ARRAY_NODE)+oldcap*sizeof(intptr_t),sizeof(ARRAY_NODE)+(ar->capacity)*sizeof(intptr_t)); for(oldcap = ar->size; oldcap < ar->capacity; oldcap++) /* reuse of oldcap saving one variable */ ar->data[oldcap] = (intptr_t)NULL; } ar->data[ar->size] = el; ar->size++; return ar; } ARRAY array_AddAtIndex(ARRAY ar, int idx, intptr_t el) /************************************************************** INPUT: A pointer to the array and index and element. RETURNS: The updated array with the element added at position and of the array increased arrordingly. New cells set to NULL. MEMORY: If the capacity is reached, capacity is doubled until available, new internal array allocated and the content copied. ***************************************************************/ { int oldcap; oldcap = ar->capacity; while (ar->capacity <= idx) ar->capacity = (ar->capacity * ar->extend)/100 + 1 + ar->capacity; if (oldcap !=ar->capacity) { ar = memory_Realloc(ar,sizeof(ARRAY_NODE)+oldcap*sizeof(intptr_t), sizeof(ARRAY_NODE)+(ar->capacity)*sizeof(intptr_t)); for(oldcap = ar->size; oldcap < ar->capacity; oldcap++) /* reuse of oldcap saving one variable */ ar->data[oldcap] = (intptr_t)NULL; } if (ar->size <= idx) ar->size = idx+1; ar->data[idx] = el; return ar; } void array_RemoveAtIndex(ARRAY ar, int idx) /************************************************************** INPUT: A pointer to the array and index. RETURNS: The updated array where the element at position is removed. The size is decremented and the element at position size-1> moved to . ***************************************************************/ { (ar->size)--; ar->data[idx] = ar->data[ar->size]; } ARRAY array_AddGetIndex(ARRAY ar, intptr_t el, int *index) /************************************************************** INPUT: Pointer to the array, an element and a pointer to int RETURNS: The updated array with the element added to the end and size increased by one, the actual index is returned in <*index> New cells are set to NULL. MEMORY: If the capacity is reached, capacity is doubled, new internal array allocated and the content copied. ***************************************************************/ { if (ar->size==ar->capacity) { int oldcap; oldcap = ar->capacity; ar->capacity = (ar->capacity * ar->extend)/100 + 1 + ar->capacity; ar = memory_Realloc(ar,sizeof(ARRAY_NODE)+oldcap*sizeof(intptr_t), sizeof(ARRAY_NODE)+(ar->capacity)*sizeof(intptr_t)); for(oldcap = ar->size; oldcap < ar->capacity; oldcap++) /* reuse of oldcap saving one variable */ ar->data[oldcap] = (intptr_t)NULL; } ar->data[ar->size] = el; *index = ar->size; ar->size++; return ar; } intptr_t array_GetElement(ARRAY ar, int idx) /************************************************************** INPUT: Pointer to the array and a specific index. EFFECT: In Check mode the bounds of are checked. RETURNS: The element at position of . ***************************************************************/ { #ifdef CHECK if (!((idx >= 0) && (idx < ar->size))) { misc_StartErrorReport(); misc_ErrorReport("\n array_GetElement: %d outside array bounds. ", idx); misc_FinishErrorReport(); } #endif return ar->data[idx]; } void array_SetElement(ARRAY ar, int idx, intptr_t new_el) /************************************************************** INPUT: Pointer to the array, specific index and a new value. EFFECT: In Check mode the bounds of are checked. RETURNS: The element at position of is set to . ***************************************************************/ { #ifdef CHECK if (!((idx >= 0) && (idx < ar->size))) { misc_StartErrorReport(); misc_ErrorReport("\n array_SetElement: %d outside array bounds. ", idx); misc_FinishErrorReport(); } #endif ar->data[idx] = new_el; } BOOL array_ContainsElement(ARRAY ar, intptr_t el, int * index) /************************************************************** INPUT: Pointer to the array, an element and a pointer to integer. RETURNS: TRUE iff the array contains that int as its element. If so, <*index> is set to index of the first found occurence. ***************************************************************/ { int i; for(i = 0; i < ar->size; i++) if ((intptr_t)ar->data[i] == el) { *index = i; return TRUE; } return FALSE; } BOOL array_HasElement(ARRAY ar, intptr_t el) /************************************************************** INPUT: Pointer to the array, an element and a pointer to integer. RETURNS: TRUE iff the array contains that int as its element. ***************************************************************/ { int i; for(i = 0; i < ar->size; i++) if ((intptr_t)ar->data[i] == el) { return TRUE; } return FALSE; } void array_Sort(ARRAY ar, int (* compartor) ( const void *, const void * )) /************************************************************** INPUT: Pointer to the array and a comparator. EFFECT: Uses stdlib qsort to sort the array with the help of the given comparator. ***************************************************************/ { qsort(ar->data, ar->size, sizeof(ar->data[0]), compartor); } int array_BSearch(ARRAY ar, const void * key, int (* comparator) ( const void *, const void * )) /************************************************************** INPUT: Pointer to the array, an element to look for and a comparator. RETURNS: an index of the element if found, -1 otherwise CAUTION: Assumes the array has been sorted previously using the same comparator "relation" ***************************************************************/ { intptr_t* result; result = (intptr_t*)bsearch(key,ar->data,ar->size,sizeof(ar->data[0]),comparator); if (result == NULL) return -1; else return (result - ar->data); } void array_Delete(ARRAY ar) /************************************************************** INPUT: Pointer to the array to be deleted. MEMORY: Frees the memory associated with the given array. ***************************************************************/ { memory_Free(ar,sizeof(ARRAY_NODE)+ar->capacity*sizeof(intptr_t)); } intptr_t array_Top(ARRAY ar) /************************************************************** INPUT: A pointer to the array RETURNS: A pointer to the element at the end of the array ***************************************************************/ { return ar->data[ar->size-1]; } intptr_t array_Pop(ARRAY ar) /************************************************************** INPUT: A pointer to the array RETURNS: A pointer to the element at the end of the array which then will be removed ***************************************************************/ { intptr_t ret; ret = ar->data[--ar->size]; return ret; } ARRAY array_Nconc(ARRAY ar1, ARRAY ar2) /************************************************************** INPUT: Two arrays RETURNS: Adds all elements of to and returns new EFFECT: Size of is set to 0, is NOT deleted ***************************************************************/ { int i; for(i = 0; i < array_GetSize(ar2) ; i++){ ar1 = array_Add(ar1,array_GetElement(ar2,i)); /* Assignation where missing*/ } array_Clean(ar2); return ar1; } ARRAY array_AddList(ARRAY ar, LIST List) /************************************************************** INPUT: An array and a list. RETURNS: Adds all elements of to and returns new ***************************************************************/ { while(!list_Empty(List)){ ar = array_Add(ar,(intptr_t)list_Car(List)); List = list_Cdr(List); } return ar; } LIST array_ToList(ARRAY ar) /************************************************************** INPUT: An array. RETURNS: A list with the elements of , preserving order. EFFECT: The array is emptied after the oparation. ***************************************************************/ { LIST list1; list1 = list_Nil(); while(array_GetSize(ar) > 0){ list1 = list_Cons((POINTER)array_Pop(ar),list1); } return list1; } ARRAY array_PointerDeleteElement(ARRAY ar, intptr_t Element) /************************************************************** INPUT: An array and an element. RETURNS: The array where all occurrences of with respect to pointer equality are removed and the gaps filled with elements of of higher index, preserving order. ***************************************************************/ { intptr_t scan; int i,j; i = j = 0; while(i < array_GetSize(ar)){ scan = array_GetElement(ar,i); if(scan != Element){ array_SetElement(ar,j,scan); j++; } i++; } i = i-j; while(i>0){ array_Pop(ar); i--; } return ar; } ARRAY array_DeleteElementIfFree(ARRAY ar, BOOL (*Test)(intptr_t), void (*Delete)(intptr_t)) /************************************************************** INPUT: An array, a test for elements and a delete function for elements. RETURNS: The array where an element is deleted if on it succeeds. The element is then deleted with . The gaps filled with elements of of higher index, preserving order. ***************************************************************/ { intptr_t scan; int i,j; i = j = 0; while(i < array_GetSize(ar)){ scan = array_GetElement(ar,i); if(Test(scan)){ Delete(scan); array_SetElement(ar,i,(intptr_t)NULL); }else{ array_SetElement(ar,j,scan); j++; } i++; } i = i-j; while(i>0){ array_Pop(ar); i--; } return ar; } spass-3.9/array.h000066400000000000000000000100121325017163600140030ustar00rootroot00000000000000/************************************************************/ /************************************************************/ /** **/ /** ARRAY **/ /** **/ /** Growable array with bound checks. **/ /** **/ /** Author: Martin Suda **/ /** **/ /** **/ /** This program is free software; you can redistribute **/ /** it and/or modify it under the terms of the FreeBSD **/ /** Licence. **/ /** **/ /** 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 LICENCE file **/ /** for more details. **/ /************************************************************/ /************************************************************/ #ifndef _ARRAY_ #define _ARRAY_ /**************************************************************/ /* Includes */ /**************************************************************/ #include "memory.h" #include "list.h" /**************************************************************/ /* Structures */ /**************************************************************/ typedef struct ARRAY_HELP { int size; int capacity; int extend; intptr_t data[]; } ARRAY_NODE, *ARRAY; /**************************************************************/ /**************************************************************/ /* This is the structure to implement growable array: */ /* size is the number of valid elements of the array. */ /* capacity denotes how much is currently allocated. */ /* increase is the factor when increasing the array in % */ /* default is 200 */ /* data contains a pointer to the actual internal array. */ /* */ /* The structure can hold general objects via pointers */ /* or integers. */ /* */ /**************************************************************/ /**************************************************************/ /**************************************************************/ /* Functions */ /**************************************************************/ void array_Init(void); void array_Free(void); ARRAY array_Create(int,int); void array_Claim(ARRAY); int array_GetSize(ARRAY); ARRAY array_DeleteIndex(ARRAY, int); ARRAY array_Clean(ARRAY); ARRAY array_Add(ARRAY, intptr_t); ARRAY array_AddAtIndex(ARRAY, int, intptr_t); void array_RemoveAtIndex(ARRAY, int); ARRAY array_AddGetIndex(ARRAY, intptr_t, int *); intptr_t array_GetElement(ARRAY, int); void array_SetElement(ARRAY, int, intptr_t); BOOL array_ContainsElement(ARRAY, intptr_t, int *); BOOL array_HasElement(ARRAY, intptr_t); void array_Sort(ARRAY, int (*) ( const void *, const void * )); int array_BSearch(ARRAY, const void *, int (*) ( const void *, const void * )); intptr_t array_Top(ARRAY); intptr_t array_Pop(ARRAY); ARRAY array_Nconc(ARRAY, ARRAY); ARRAY array_AddList(ARRAY, LIST); LIST array_ToList(ARRAY); ARRAY array_PointerDeleteElement(ARRAY, intptr_t); ARRAY array_DeleteElementIfFree(ARRAY, BOOL (*)(intptr_t), void (*)(intptr_t)); void array_Delete(ARRAY); #endif spass-3.9/cl.h000066400000000000000000000050561325017163600132770ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * INTERFACE FOR THE CLAUSE PARSER * */ /* * * */ /* * $Module: CL * */ /* * * */ /* * Copyright (C) 1999, 2000 MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.2 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:57 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Im Stadtwald * */ /* * 66123 Saarbruecken * */ /* * Email: weidenb@mpi-sb.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: cl.h,v $ */ #ifndef _CLPARSER_ #define _CLPARSER_ #include "misc.h" #include "symbol.h" #include "flags.h" /* Parser functions */ POINTER cl_GetClauseOrFormula(const char*, FLAGSTORE, PRECEDENCE); /* Interaction between scanner and parser */ void cl_ScannerInit(const char*); void cl_ScannerFree(void); #endif spass-3.9/clause.c000066400000000000000000007157521325017163600141630ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * CLAUSES * */ /* * * */ /* * $Module: CLAUSE * */ /* * * */ /* * 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.18 $ * */ /* $State: Exp $ * */ /* $Date: 2011-11-27 10:57:34 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: clause.c,v $ */ #include "clause.h" /**************************************************************/ /* Global variables and constants */ /**************************************************************/ /* Means weight of literal or clause is undefined */ const NAT clause_WEIGHTUNDEFINED = NAT_MAX; int clause_CLAUSECOUNTER; NAT clause_STAMPID; /* The following array is used for bucket sort on clauses */ #define clause_MAXWEIGHT 20 LIST clause_SORT[clause_MAXWEIGHT+1]; /**************************************************************/ /*Previously Inlined functions */ /**************************************************************/ LIST clause_CopyClauseList(LIST List) { return list_CopyWithElement(List, (POINTER (*)(POINTER)) clause_Copy); } BOOL clause_IsTransitivityAxiom(CLAUSE Clause) { SYMBOL s; BOOL b; return clause_IsTransitivityAxiomExt(Clause,&s,&b); } /**************************************************************/ /* Accessing Literals 1 */ /**************************************************************/ TERM clause_LiteralSignedAtom(LITERAL L) { return L->atomWithSign; } CLAUSE clause_LiteralOwningClause(LITERAL L) { return L->owningClause; } void clause_LiteralSetOwningClause(LITERAL L, CLAUSE C) { L->owningClause = C; } void clause_LiteralSetOrderStatus(LITERAL L, ord_RESULT OS) { L->ord_stat = OS; } ord_RESULT clause_LiteralGetOrderStatus(LITERAL L) { return L->ord_stat; } NAT clause_LiteralWeight(LITERAL L) { #ifdef CHECK if (L->weight == clause_WEIGHTUNDEFINED) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_LiteralWeight:"); misc_ErrorReport(" Tried to access undefined weight."); misc_FinishErrorReport(); } #endif return L->weight; } void clause_UpdateLiteralWeight(LITERAL L, FLAGSTORE Flags) { L->weight = clause_LiteralComputeWeight(L, Flags); } void clause_LiteralFlagReset(LITERAL L) { L->maxLit = 0; } void clause_LiteralFlagResetAndKeepSelFlag(LITERAL L) { L->maxLit &= LITSELECT; } BOOL clause_LiteralGetFlag(LITERAL L, MAXFLAG Flag) { return ((L->maxLit & Flag) != 0); } void clause_LiteralSetFlag(LITERAL L, MAXFLAG Flag) { L->maxLit = (L->maxLit) | Flag; } void clause_LiteralClearFlag(LITERAL L, MAXFLAG Flag) { L->maxLit = (L->maxLit) & ~Flag; } BOOL clause_LiteralIsMaximal(LITERAL L) { return clause_LiteralGetFlag(L, MAXIMAL); } BOOL clause_LiteralIsOrientedEquality(LITERAL L) { return fol_IsEquality(clause_LiteralAtom(L)) && (L->ord_stat == ord_GREATER_THAN); } BOOL clause_LiteralIsNotOrientedEquality(LITERAL L) { return !fol_IsEquality(clause_LiteralAtom(L)) || (L->ord_stat != ord_GREATER_THAN); } /**************************************************************/ /* Literal Comparison 1 */ /**************************************************************/ BOOL clause_LiteralIsNegative(LITERAL L) { return (term_TopSymbol(clause_LiteralSignedAtom(L)) == fol_Not()); } BOOL clause_LiteralIsPositive(LITERAL L) { return !clause_LiteralIsNegative(L); } BOOL clause_LiteralsAreComplementary(LITERAL L1, LITERAL L2) { return ((clause_LiteralIsNegative(L1) && clause_LiteralIsPositive(L2)) || (clause_LiteralIsNegative(L2) && clause_LiteralIsPositive(L1))); /* xor */ } BOOL clause_HyperLiteralIsBetter(LITERAL Dummy1, NAT S1, LITERAL Dummy2, NAT S2) /************************************************************** INPUT: Two literals and its sizes wrt. some substitution. RETURNS: TRUE, if the first literal is 'better' than the second literal, FALSE otherwise. EFFECT: A literal is 'better' than another, if S1 > Ss. Since we have to find unifiable complementary literals for every remaining antecedent literal, it seems to be a good idea to try the most 'difficult' literal first, in order to stop the search as early as possible.. Here we prefer the literal with the highest number of symbols.. This function is used as parameter for the function clause_MoveBestLiteralToFront. CAUTION: The parameters and are unused, they're just added to keep the compiler quiet. ***************************************************************/ { return (S1 > S2); } /**************************************************************/ /* Accessing Literals 2 */ /**************************************************************/ SYMBOL clause_LiteralPredicate(LITERAL L) { return term_TopSymbol(clause_LiteralAtom(L)); } BOOL clause_LiteralIsPredicate(LITERAL L) { return !fol_IsEquality(clause_LiteralAtom(L)); } BOOL clause_LiteralIsEquality(LITERAL L) { return fol_IsEquality(clause_LiteralAtom(L)); } void clause_LiteralSetAtom(LITERAL L, TERM A) { if (clause_LiteralIsNegative(L)) list_Rplaca(term_ArgumentList(clause_LiteralSignedAtom(L)),A); else L->atomWithSign = A; } void clause_LiteralSetNegAtom(LITERAL L, TERM A) { list_Rplaca(term_ArgumentList(clause_LiteralSignedAtom(L)), A); } void clause_LiteralSetPosAtom(LITERAL L, TERM A) { L->atomWithSign = A; } void clause_NLiteralSetLiteral(LITERAL L, TERM LIT) { L->atomWithSign = LIT; } /**************************************************************/ /* Memory management */ /**************************************************************/ void clause_LiteralFree(LITERAL L) { memory_Free(L, sizeof(LITERAL_NODE)); } /**************************************************************/ /* Functions to access literals. */ /**************************************************************/ LITERAL clause_GetLiteral(CLAUSE C, intptr_t Index) { return C->literals[Index]; } void clause_SetLiteral(CLAUSE C, int Index, LITERAL L) { C->literals[Index]= L; } TERM clause_GetLiteralTerm(CLAUSE C, int Index) { return clause_LiteralSignedAtom(clause_GetLiteral(C, Index)); } TERM clause_GetLiteralAtom(CLAUSE C, intptr_t Index) { return clause_LiteralAtom(clause_GetLiteral(C, Index)); } int clause_NumOfConsLits(CLAUSE Clause) { return Clause->c; } int clause_NumOfAnteLits(CLAUSE Clause) { return Clause->a; } int clause_NumOfSuccLits(CLAUSE Clause) { return Clause->s; } void clause_SetNumOfConsLits(CLAUSE Clause, int Number) { Clause->c = Number; } void clause_SetNumOfAnteLits(CLAUSE Clause, int Number) { Clause->a = Number; } void clause_SetNumOfSuccLits(CLAUSE Clause, int Number) { Clause->s = Number; } int clause_Length(CLAUSE Clause) { return (clause_NumOfConsLits(Clause) + clause_NumOfAnteLits(Clause) + clause_NumOfSuccLits(Clause)); } int clause_LastLitIndex(CLAUSE Clause) { return clause_Length(Clause) - 1; } intptr_t clause_FirstLitIndex(void) { return 0; } int clause_FirstConstraintLitIndex(CLAUSE Clause) { return 0; } intptr_t clause_FirstAntecedentLitIndex(CLAUSE Clause) { return clause_NumOfConsLits(Clause); } intptr_t clause_FirstSuccedentLitIndex(CLAUSE Clause) { return (clause_NumOfAnteLits(Clause) + clause_NumOfConsLits(Clause)); } int clause_LastConstraintLitIndex(CLAUSE Clause) { return clause_NumOfConsLits(Clause) - 1; } int clause_LastAntecedentLitIndex(CLAUSE Clause) { return clause_FirstSuccedentLitIndex(Clause) - 1; } int clause_LastSuccedentLitIndex(CLAUSE Clause) { return clause_Length(Clause) - 1; } LIST clause_GetLiteralList(CLAUSE Clause) /************************************************************** INPUT: A clause. RETURNS: A new list is created containing all literals of the clause. The list contains pointers, not literal indexes. ***************************************************************/ { LIST Result; int i; Result = list_Nil(); for (i=clause_FirstLitIndex(); i<=clause_LastLitIndex(Clause); i++) Result = list_Cons(clause_GetLiteral(Clause, i), Result); return Result; } LIST clause_GetLiteralListExcept(CLAUSE Clause, int Index) /************************************************************** INPUT: A clause. RETURNS: A new list is created containing all literals of the clause except the literal at . The list contains pointers, not literal indexes. ***************************************************************/ { LIST Result; int i; Result = list_Nil(); for (i=clause_FirstLitIndex(); i<=clause_LastLitIndex(Clause); i++) if (i != Index) Result = list_Cons(clause_GetLiteral(Clause, i), Result); return Result; } /**************************************************************/ /* Clause Access Macros */ /**************************************************************/ int clause_Counter(void) { return clause_CLAUSECOUNTER; } void clause_SetCounter(int Value) { #ifdef CHECK if (Value < 0) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_SetCounter: new counter value is negative."); misc_FinishErrorReport(); } #endif clause_CLAUSECOUNTER = Value; } int clause_IncreaseCounter(void) { #ifdef CHECK if (clause_CLAUSECOUNTER == INT_MAX) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_IncreaseCounter: counter overflow."); misc_FinishErrorReport(); } #endif return clause_CLAUSECOUNTER++; } void clause_DecreaseCounter(void) { #ifdef CHECK if (clause_CLAUSECOUNTER == 0) { misc_FinishErrorReport(); misc_ErrorReport("\n In clause_DecreaseCounter: counter underflow."); misc_FinishErrorReport(); } #endif clause_CLAUSECOUNTER--; } NAT clause_Depth(CLAUSE Clause) { return Clause->depth; } void clause_SetDepth(CLAUSE Clause, NAT NewDepth) { Clause->depth = NewDepth; } NAT clause_Weight(CLAUSE Clause) { #ifdef CHECK if (Clause->weight == clause_WEIGHTUNDEFINED) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_Weight: Tried to access undefined weight."); misc_FinishErrorReport(); } #endif return Clause->weight; } void clause_UpdateWeight(CLAUSE Clause, FLAGSTORE Flags) { Clause->weight = clause_ComputeWeight(Clause, Flags); } float clause_SplitPotential(CLAUSE Clause) { return Clause->splitpotential; } void clause_SetSplitPotential(CLAUSE Clause, float pot) { Clause->splitpotential = pot; } intptr_t clause_Number(const CLAUSE Clause) { return Clause->clausenumber; } void clause_SetNumber(CLAUSE Clause, int Number) { Clause->clausenumber = Number; } void clause_NewNumber(CLAUSE Clause) { Clause->clausenumber = clause_IncreaseCounter(); } NAT clause_SplitLevel(CLAUSE Clause) { return Clause->validlevel; } BOOL clause_CheckSplitLevel(CLAUSE Clause) /************************************************************** INPUT: A clause. RETURNS: TRUE, if the splitlevel invariant for the clause is fulfilled. EFFECT: Checks, if the validlevel of the clause is the order of the highest set bit in the SPLITFIELD entry of the clause. ***************************************************************/ { if (Clause->validlevel == 0) return (Clause->splitfield == NULL); else { int i, j; for (i = Clause->splitfield_length-1; i >= 0; i--) if (Clause->splitfield[i] != 0) break; for (j = sizeof(SPLITFIELDENTRY)*CHAR_BIT-1; j >= 0; j--) if (Clause->splitfield[i] & ((SPLITFIELDENTRY)1 << j)) break; return (Clause->validlevel == (i*sizeof(SPLITFIELDENTRY)*CHAR_BIT+j)); } } NAT clause_SplitLevelDependencies(CLAUSE Clause) /************************************************************** INPUT: A clause. RETURNS: The number of split levels the clause depends on ***************************************************************/ { if (Clause->validlevel == 0) return 0; else { int i, j; j = 0; for (i = Clause->splitfield_length-1; i >= 0; i--) if (Clause->splitfield[i] != 0) j++; return j; } } LIST clause_ParentClauses(CLAUSE Clause) { return Clause->parentCls; } LIST clause_ParentLiterals(CLAUSE Clause) { return Clause->parentLits; } SYMBOL clause_MaxVar(CLAUSE Clause) { return Clause->maxVar; } void clause_SetMaxVar(CLAUSE Clause, SYMBOL Variable) { Clause->maxVar = Variable; } RULE clause_Origin(CLAUSE Clause) { return Clause->origin; } BOOL clause_Exists(CLAUSE Clause) { return (Clause != (CLAUSE)NULL); } BOOL clause_LiteralExists(LITERAL L) { return (L != (LITERAL)NULL); } CLAUSE clause_Null(void) { return (CLAUSE) NULL; } void clause_SetSplitLevel(CLAUSE Clause, NAT Level) { Clause->validlevel = Level; } void clause_InitSplitData(CLAUSE C) { C->splitfield = NULL; C->splitfield_length = 0; clause_SetSplitLevel(C, 0); } void clause_SetSplitField(CLAUSE Clause, SPLITFIELD B, unsigned Length) { unsigned i; if (Clause->splitfield_length != Length) { if (Clause->splitfield != NULL) { memory_Free(Clause->splitfield, sizeof(SPLITFIELDENTRY) * Clause->splitfield_length); } if (Length != 0) { Clause->splitfield = memory_Malloc(sizeof(SPLITFIELDENTRY) * Length); } else Clause->splitfield = NULL; Clause->splitfield_length = Length; } for (i=0; i < Length; i++) Clause->splitfield[i] = B[i]; } NAT clause_ComputeSplitFieldAddress(NAT n, NAT* field) { *field = 0; while (n >= (sizeof(SPLITFIELDENTRY) * CHAR_BIT)) { (*field)++; n -= sizeof(SPLITFIELDENTRY) * CHAR_BIT; } return n; } void clause_ExpandSplitField(CLAUSE C, NAT Length) { SPLITFIELD NewField; NAT i; if (C->splitfield_length < Length) { NewField = memory_Malloc(sizeof(SPLITFIELDENTRY) * Length); for (i=0; i < C->splitfield_length; i++) NewField[i] = C->splitfield[i]; for (i=C->splitfield_length; i < Length; i++) NewField[i] = 0; if (C->splitfield != NULL) { memory_Free(C->splitfield, sizeof(SPLITFIELDENTRY) * C->splitfield_length); } C->splitfield = NewField; C->splitfield_length = Length; } } void clause_ClearSplitField(CLAUSE C) { int i; for (i=C->splitfield_length-1; i >=0; i--) C->splitfield[i] = 0; } void clause_SetSplitFieldBit(CLAUSE Clause, NAT n) { uintptr_t field; n = clause_ComputeSplitFieldAddress(n, &field); if (field >= Clause->splitfield_length) clause_ExpandSplitField(Clause, field + 1); Clause->splitfield[field] = (Clause->splitfield[field]) | ((SPLITFIELDENTRY)1 << n); } BOOL clause_GetFlag(CLAUSE Clause, CLAUSE_FLAGS Flag) { return (Clause->flags & Flag) != 0; } void clause_SetFlag(CLAUSE Clause, CLAUSE_FLAGS Flag) { Clause->flags = Clause->flags | Flag; } void clause_RemoveFlag(CLAUSE Clause, CLAUSE_FLAGS Flag) { if (Clause->flags & Flag) Clause->flags = Clause->flags - Flag; } void clause_ClearFlags(CLAUSE Clause) { Clause->flags = 0; } BOOL clause_DependsOnSplitLevel(CLAUSE C, NAT N) { if (N==0) return TRUE; else { uintptr_t field; N = clause_ComputeSplitFieldAddress(N, &field); if (field >= C->splitfield_length) return FALSE; else return (C->splitfield[field] & ((SPLITFIELDENTRY)1 << N)) != 0; } } void clause_UpdateSplitDataFromNewSplitting(CLAUSE Result, CLAUSE Father, NAT Level) { uintptr_t field; NAT i; clause_SetSplitLevel(Result, Level); Level = clause_ComputeSplitFieldAddress(Level, &field); if (field >= Result->splitfield_length) { if (Result->splitfield != NULL) memory_Free(Result->splitfield, sizeof(SPLITFIELDENTRY) * Result->splitfield_length); Result->splitfield = memory_Malloc((field + 1) * sizeof(SPLITFIELDENTRY)); Result->splitfield_length = field + 1; } if (clause_GetFlag(Father, CONCLAUSE)) clause_SetFlag(Result, CONCLAUSE); for (i=0; i < Father->splitfield_length; i++) Result->splitfield[i] = Father->splitfield[i]; for (i=Father->splitfield_length; i < Result->splitfield_length; i++) Result->splitfield[i] = 0; Result->splitfield[field] = (Result->splitfield[field] | ((SPLITFIELDENTRY)1 << Level)); } void clause_UpdateSplitDataFromPartner(CLAUSE Result, CLAUSE Partner) { if (clause_GetFlag(Partner, CONCLAUSE)) clause_SetFlag(Result, CONCLAUSE); if (clause_SplitLevel(Partner) == 0) return; /* Set Split level to misc_Max(Partner, Result) */ clause_SetSplitLevel(Result, clause_SplitLevel(Partner) > clause_SplitLevel(Result) ? clause_SplitLevel(Partner) : clause_SplitLevel(Result)); clause_UpdateSplitField(Result, Partner); } void clause_SetParentClauses(CLAUSE Clause, LIST PClauses) { Clause->parentCls = PClauses; } void clause_AddParentClause(CLAUSE Clause, intptr_t PClause) { Clause->parentCls = list_Cons((POINTER) PClause, Clause->parentCls); } void clause_SetParentLiterals(CLAUSE Clause, LIST PLits) { Clause->parentLits = PLits; } void clause_AddParentLiteral(CLAUSE Clause, intptr_t PLit) { Clause->parentLits = list_Cons((POINTER) PLit, Clause->parentLits); } BOOL clause_ValidityIsNotSmaller(CLAUSE C1, CLAUSE C2) { return (C1->validlevel <= C2->validlevel); } BOOL clause_IsMoreValid(CLAUSE C1, CLAUSE C2) { return (C1->validlevel < C2->validlevel); } BOOL clause_CompareAbstractLEQ (CLAUSE Left, CLAUSE Right) /************************************************************** INPUT: Two clauses. RETURNS: TRUE if left <= right, FALSE otherwise. EFFECTS: Internal function used to compare clauses for sorting. CAUTION: Expects clause literal order to be fixed. ***************************************************************/ { return (BOOL) (clause_CompareAbstract(Left, Right) <= 0); } BOOL clause_IsFromRewriting(CLAUSE Clause) { return Clause->origin == REWRITING; } BOOL clause_IsFromCondensing(CLAUSE Clause) { return Clause->origin == CONDENSING; } BOOL clause_IsFromObviousReductions(CLAUSE Clause) { return Clause->origin == OBVIOUS_REDUCTIONS; } BOOL clause_IsFromSortSimplification(CLAUSE Clause) { return Clause->origin == SORT_SIMPLIFICATION; } BOOL clause_IsFromMatchingReplacementResolution(CLAUSE Clause) { return Clause->origin == MATCHING_REPLACEMENT_RESOLUTION; } BOOL clause_IsFromClauseDeletion(CLAUSE Clause) { return Clause->origin == CLAUSE_DELETION; } BOOL clause_IsFromEmptySort(CLAUSE Clause) { return Clause->origin == EMPTY_SORT; } BOOL clause_IsFromSortResolution(CLAUSE Clause) { return Clause->origin == SORT_RESOLUTION; } BOOL clause_IsFromUnitConflict(CLAUSE Clause) { return Clause->origin == UNIT_CONFLICT; } BOOL clause_IsFromEqualityResolution(CLAUSE Clause) { return Clause->origin == EQUALITY_RESOLUTION; } BOOL clause_IsFromEqualityFactoring(CLAUSE Clause) { return Clause->origin == EQUALITY_FACTORING; } BOOL clause_IsFromMergingParamodulation(CLAUSE Clause) { return Clause->origin == MERGING_PARAMODULATION; } BOOL clause_IsFromSuperpositionRight(CLAUSE Clause) { return Clause->origin == SUPERPOSITION_RIGHT; } BOOL clause_IsFromSuperpositionLeft(CLAUSE Clause) { return Clause->origin == SUPERPOSITION_LEFT; } BOOL clause_IsFromGeneralResolution(CLAUSE Clause) { return Clause->origin == GENERAL_RESOLUTION; } BOOL clause_IsFromGeneralFactoring(CLAUSE Clause) { return Clause->origin == GENERAL_FACTORING; } BOOL clause_IsFromSplitting(CLAUSE Clause) { return Clause->origin == SPLITTING; } BOOL clause_IsFromDefApplication(CLAUSE Clause) { return Clause->origin == DEFAPPLICATION; } BOOL clause_IsFromTerminator(CLAUSE Clause) { return Clause->origin == TERMINATOR; } BOOL clause_IsTemporary(CLAUSE Clause) { return Clause->origin == TEMPORARY; } BOOL clause_IsFromInput(CLAUSE Clause) { return Clause->origin == INPUTCLAUSE; } BOOL clause_IsFromOrderedChaining(CLAUSE Clause) { return Clause->origin == ORDERED_CHAINING; } BOOL clause_IsFromNegativeChaining(CLAUSE Clause) { return Clause->origin == NEGATIVE_CHAINING; } BOOL clause_IsFromCompositionResolution(CLAUSE Clause) { return Clause->origin == COMPOSITION_RESOLUTION; } BOOL clause_HasReducedPredecessor(CLAUSE Clause) { RULE origin = clause_Origin(Clause); return (origin == CONDENSING || origin == REWRITING || origin == SPLITTING || origin == ASSIGNMENT_EQUATION_DELETION || origin == SORT_SIMPLIFICATION || origin == OBVIOUS_REDUCTIONS); } BOOL clause_IsSplitFather(CLAUSE C1, CLAUSE C2) { return (C1->clausenumber == (intptr_t)list_Car(C2->parentCls)); } void clause_SetFromRewriting(CLAUSE Clause) { Clause->origin = REWRITING; } void clause_SetFromContextualRewriting(CLAUSE Clause) { Clause->origin = CONTEXTUAL_REWRITING; } void clause_SetFromUnitConflict(CLAUSE Clause) { Clause->origin = UNIT_CONFLICT; } void clause_SetFromCondensing(CLAUSE Clause) { Clause->origin = CONDENSING; } void clause_SetFromAssignmentEquationDeletion(CLAUSE Clause) { Clause->origin = ASSIGNMENT_EQUATION_DELETION; } void clause_SetFromObviousReductions(CLAUSE Clause) { Clause->origin = OBVIOUS_REDUCTIONS; } void clause_SetFromSortSimplification(CLAUSE Clause) { Clause->origin = SORT_SIMPLIFICATION; } void clause_SetFromMatchingReplacementResolution(CLAUSE Clause) { Clause->origin = MATCHING_REPLACEMENT_RESOLUTION; } void clause_SetFromClauseDeletion(CLAUSE Clause) { Clause->origin = CLAUSE_DELETION; } void clause_SetFromEmptySort(CLAUSE Clause) { Clause->origin = EMPTY_SORT; } void clause_SetFromSortResolution(CLAUSE Clause) { Clause->origin = SORT_RESOLUTION; } void clause_SetFromEqualityResolution(CLAUSE Clause) { Clause->origin = EQUALITY_RESOLUTION; } void clause_SetFromEqualityFactoring(CLAUSE Clause) { Clause->origin = EQUALITY_FACTORING; } void clause_SetFromMergingParamodulation(CLAUSE Clause) { Clause->origin = MERGING_PARAMODULATION; } void clause_SetFromParamodulation(CLAUSE Clause) { Clause->origin = PARAMODULATION; } void clause_SetFromOrderedParamodulation(CLAUSE Clause) { Clause->origin = ORDERED_PARAMODULATION; } void clause_SetFromSuperpositionRight(CLAUSE Clause) { Clause->origin = SUPERPOSITION_RIGHT; } void clause_SetFromSuperpositionLeft(CLAUSE Clause) { Clause->origin = SUPERPOSITION_LEFT; } void clause_SetFromGeneralResolution(CLAUSE Clause) { Clause->origin = GENERAL_RESOLUTION; } void clause_SetFromOrderedHyperResolution(CLAUSE Clause) { Clause->origin = ORDERED_HYPER; } void clause_SetFromSimpleHyperResolution(CLAUSE Clause) { Clause->origin = SIMPLE_HYPER; } void clause_SetFromURResolution(CLAUSE Clause) { Clause->origin = UR_RESOLUTION; } void clause_SetFromGeneralFactoring(CLAUSE Clause) { Clause->origin = GENERAL_FACTORING; } void clause_SetFromSplitting(CLAUSE Clause) { Clause->origin = SPLITTING; } void clause_SetFromDefApplication(CLAUSE Clause) { Clause->origin = DEFAPPLICATION; } void clause_SetFromTerminator(CLAUSE Clause) { Clause->origin = TERMINATOR; } void clause_SetTemporary(CLAUSE Clause) { Clause->origin = TEMPORARY; } void clause_SetFromOrderedChaining(CLAUSE Clause) { Clause->origin = ORDERED_CHAINING; } void clause_SetFromNegativeChaining(CLAUSE Clause) { Clause->origin = NEGATIVE_CHAINING; } void clause_SetFromCompositionResolution(CLAUSE Clause) { Clause->origin = COMPOSITION_RESOLUTION; } void clause_SetFromInput(CLAUSE Clause) { Clause->origin = INPUTCLAUSE; } LITERAL clause_FirstConstraintLit(CLAUSE Clause) { return Clause->literals[0]; } LITERAL clause_FirstAntecedentLit(CLAUSE Clause) { return Clause->literals[clause_FirstAntecedentLitIndex(Clause)]; } LITERAL clause_FirstSuccedentLit(CLAUSE Clause) { return Clause->literals[clause_FirstSuccedentLitIndex(Clause)]; } LITERAL clause_LastConstraintLit(CLAUSE Clause) { return Clause->literals[clause_LastConstraintLitIndex(Clause)]; } LITERAL clause_LastAntecedentLit(CLAUSE Clause) { return Clause->literals[clause_LastAntecedentLitIndex(Clause)]; } LITERAL clause_LastSuccedentLit(CLAUSE Clause) { return Clause->literals[clause_LastSuccedentLitIndex(Clause)]; } BOOL clause_HasEmptyConstraint(CLAUSE Clause) { return clause_NumOfConsLits(Clause) == 0; } BOOL clause_HasEmptyAntecedent(CLAUSE Clause) { return clause_NumOfAnteLits(Clause) == 0; } BOOL clause_HasEmptySuccedent(CLAUSE Clause) { return clause_NumOfSuccLits(Clause) == 0; } BOOL clause_IsGround(CLAUSE Clause) { #ifdef CHECK if (!symbol_Equal(clause_MaxVar(Clause), clause_SearchMaxVar(Clause))) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_IsGround: Clause is corrupted."); misc_FinishErrorReport(); } #endif return (symbol_VarIndex(clause_MaxVar(Clause)) == symbol_GetInitialStandardVarCounter()); } BOOL clause_IsEmptyClause(CLAUSE C) { return (C != (CLAUSE)NULL && clause_HasEmptyAntecedent(C) && clause_HasEmptySuccedent(C) && clause_HasEmptyConstraint(C)); } intptr_t clause_LiteralGetIndex(LITERAL L) { intptr_t j = 0; while (clause_GetLiteral(clause_LiteralOwningClause(L), j) != L) j++; return j; } BOOL clause_LiteralIsFromConstraint(LITERAL Literal) { int literal_index = clause_LiteralGetIndex(Literal); CLAUSE clause = clause_LiteralOwningClause(Literal); return (literal_index <= clause_LastConstraintLitIndex(clause) && literal_index >= clause_FirstConstraintLitIndex(clause)); } BOOL clause_LiteralIsFromAntecedent(LITERAL Literal) { int literal_index = clause_LiteralGetIndex(Literal); CLAUSE clause = clause_LiteralOwningClause(Literal); return (literal_index <= clause_LastAntecedentLitIndex(clause) && literal_index >= clause_FirstAntecedentLitIndex(clause)); } BOOL clause_LiteralIsFromSuccedent(LITERAL Literal) { int literal_index; CLAUSE clause; literal_index = clause_LiteralGetIndex(Literal); clause = clause_LiteralOwningClause(Literal); return (literal_index <= clause_LastSuccedentLitIndex(clause) && literal_index >= clause_FirstSuccedentLitIndex(clause)); } BOOL clause_IsSimpleSortClause(CLAUSE Clause) { return (clause_HasEmptyAntecedent(Clause) && (clause_NumOfSuccLits(Clause) == 1) && clause_LiteralIsSort(clause_GetLiteral(Clause, clause_NumOfConsLits(Clause))) && clause_HasSolvedConstraint(Clause)); } BOOL clause_IsSubsortClause(CLAUSE Clause) { return (clause_IsSimpleSortClause(Clause) && term_IsVariable(term_FirstArgument( clause_LiteralSignedAtom( clause_GetLiteral(Clause, clause_NumOfConsLits(Clause)))))); } BOOL clause_HasSuccLits(CLAUSE Clause) { return (clause_NumOfSuccLits(Clause) > 1); } BOOL clause_HasGroundSuccLit(CLAUSE Clause) { int i, l; l = clause_Length(Clause); for (i = clause_FirstSuccedentLitIndex(Clause); i < l; i++) if (term_IsGround(Clause->literals[i]->atomWithSign)) return TRUE; return FALSE; } LITERAL clause_GetGroundSuccLit(CLAUSE Clause) { int i, l; l = clause_Length(Clause); for (i = clause_FirstSuccedentLitIndex(Clause); i < l; i++) if (term_IsGround(Clause->literals[i]->atomWithSign)) return Clause->literals[i]; return (LITERAL)NULL; } void clause_Free(CLAUSE Clause) { memory_Free(Clause, sizeof(CLAUSE_NODE)); } void clause_ReInit(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence) { clause_Normalize(Clause); clause_SetMaxLitFlags(Clause, Flags, Precedence); clause_UpdateWeight(Clause, Flags); Clause->splitpotential = 0.0; clause_UpdateMaxVar(Clause); } void clause_ReInitSkolem(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence) { /* No clause_Normalize(Clause) because variables are interpreted * as constants */ clause_SetMaxLitFlagsSkolem(Clause, Flags, Precedence); clause_UpdateWeight(Clause, Flags); /* Variables are assumed to be constants - therefore * has no variables */ clause_SetMaxVar(Clause, symbol_GetInitialStandardVarCounter()); } void clause_PrecomputeOrderingAndReInit(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence) { clause_PrecomputeOrdering(Clause, Flags, Precedence); clause_ReInit(Clause, Flags, Precedence); } void clause_PrecomputeOrderingAndReInitSkolem(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence) { clause_PrecomputeOrderingSkolem(Clause, Flags, Precedence); clause_ReInitSkolem(Clause, Flags, Precedence); } void clause_SetDataFromFather(CLAUSE Result, CLAUSE Father, int i, FLAGSTORE Flags, PRECEDENCE Precedence) { clause_PrecomputeOrderingAndReInit(Result, Flags, Precedence); clause_SetSplitDataFromFather(Result, Father); clause_SetDepth(Result, clause_Depth(Father) + 1); clause_AddParentClause(Result, clause_Number(Father)); clause_AddParentLiteral(Result, i); } void clause_SetDataFromParents(CLAUSE Result, CLAUSE Father, int i, CLAUSE Mother, int j, FLAGSTORE Flags, PRECEDENCE Precedence) { clause_PrecomputeOrderingAndReInit(Result, Flags, Precedence); clause_SetSplitDataFromParents(Result, Father, Mother); clause_SetDepth(Result, misc_Max(clause_Depth(Father), clause_Depth(Mother)) +1); clause_AddParentClause(Result, clause_Number(Father)); clause_AddParentLiteral(Result, i); clause_AddParentClause(Result, clause_Number(Mother)); clause_AddParentLiteral(Result, j); } SPLITFIELD clause_GetSplitfield(CLAUSE C, unsigned *Length) { *Length = C->splitfield_length; return C->splitfield; } /**************************************************************/ /*Previously Inlined functions ends here */ /**************************************************************/ /**************************************************************/ /* Inline functions */ /**************************************************************/ void clause_FreeLitArray(CLAUSE Clause) { NAT Length = clause_Length(Clause); if (Length > 0) memory_Free(Clause->literals, sizeof(LITERAL) * Length); } /**************************************************************/ /* Primitive literal functions */ /**************************************************************/ BOOL clause_LiteralIsLiteral(LITERAL Literal) /********************************************************* INPUT: A literal. RETURNS: TRUE, if 'Literal' is not NULL and has a predicate symbol as its atoms top symbol. **********************************************************/ { return ((Literal != NULL) && symbol_IsPredicate(clause_LiteralPredicate(Literal))); } NAT clause_LiteralComputeWeight(LITERAL Literal, FLAGSTORE Flags) /********************************************************* INPUT: A literal and a flag store. RETURNS: The weight of the literal. CAUTION: This function does not update the weight of the literal! **********************************************************/ { TERM Term; int Bottom; NAT Number; #ifdef CHECK if (!clause_LiteralIsLiteral(Literal)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_LiteralComputeWeight :"); misc_ErrorReport("Illegal Input. Input not a literal."); misc_FinishErrorReport(); } #endif Term = clause_LiteralSignedAtom(Literal); Bottom = stack_Bottom(); Number = 0; do { if (term_IsComplex(Term)) { if (symbol_HasProperty(term_TopSymbol(Term), TRANSITIVE)) { Number += flag_GetFlagIntValue(Flags, flag_TransWeight); } else Number += flag_GetFlagIntValue(Flags, flag_FUNCWEIGHT); stack_Push(term_ArgumentList(Term)); } else if (term_IsVariable(Term)) Number += flag_GetFlagIntValue(Flags, flag_VARWEIGHT); else Number += flag_GetFlagIntValue(Flags, flag_FUNCWEIGHT); while (!stack_Empty(Bottom) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(Bottom)) { Term = (TERM) list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(Bottom)); return Number; } LITERAL clause_LiteralCreate(TERM Atom, CLAUSE Clause) /********************************************************** INPUT: A Pointer to a signed Predicate-Term and one to a clause it shall belong to. RETURNS: An appropriate literal where the other values are set to default values. MEMORY: A LITERAL_NODE is allocated. CAUTION: The weight of the literal is not set correctly! ***********************************************************/ { LITERAL Result; #ifdef CHECK if (!term_IsTerm(Atom)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_LiteralCreate:"); misc_ErrorReport("\n Illegal input. Input not a term."); misc_FinishErrorReport(); } if (!symbol_IsPredicate(term_TopSymbol(Atom)) && (term_TopSymbol(Atom) != fol_Not())) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_LiteralCreate:"); misc_ErrorReport("\n Illegal input. No predicate- or negated term."); misc_FinishErrorReport(); } #endif Result = (LITERAL)memory_Malloc(sizeof(LITERAL_NODE)); Result->atomWithSign = Atom; Result->ord_stat = ord_UNCOMPARABLE; Result->weight = clause_WEIGHTUNDEFINED; Result->maxLit = 0; Result->owningClause = Clause; return Result; } LITERAL clause_LiteralCreateNegative(TERM Atom, CLAUSE Clause) /********************************************************** INPUT: A Pointer to a unsigned Predicate-Term and one to a clause it shall belong to. RETURNS: An appropriate literal where the other values are set to default values and the term gets a sign. MEMORY: A LITERAL_NODE is allocated. CAUTION: The weight of the literal is not set correctly! ***********************************************************/ { LITERAL Result; #ifdef CHECK if (!term_IsTerm(Atom)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_LiteralCreateNegative:"); misc_ErrorReport("\n Illegal input. Input not an atom."); misc_FinishErrorReport(); } if (!symbol_IsPredicate(term_TopSymbol(Atom)) && (term_TopSymbol(Atom) != fol_Not())) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_LiteralCreateNegative:"); misc_ErrorReport("\n Illegal input. Input term not normalized."); misc_FinishErrorReport(); } #endif Result = (LITERAL)memory_Malloc(sizeof(LITERAL_NODE)); term_RplacSupertermList(Atom, list_Nil()); Result->atomWithSign = term_Create(fol_Not(), list_List(Atom)); Result->ord_stat = ord_UNCOMPARABLE; Result->maxLit = 0; Result->weight = clause_WEIGHTUNDEFINED; Result->owningClause = Clause; return Result; } void clause_LiteralDelete(LITERAL Literal) /********************************************************* INPUT: A literal, which has an unshared Atom. For Shared literals clause_LiteralDeleteFromSharing(Lit) is available. RETURNS: Nothing. MEMORY: The Atom of 'Literal' is deleted and its memory is freed as well as the LITERAL_NODE. **********************************************************/ { #ifdef CHECK if (!clause_LiteralIsLiteral(Literal)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_LiteralDelete:"); misc_ErrorReport("\n Illegal input. Input not a literal."); misc_FinishErrorReport(); } #endif term_Delete(clause_LiteralSignedAtom(Literal)); clause_LiteralFree(Literal); } void clause_LiteralInsertIntoSharing(LITERAL Lit, SHARED_INDEX ShIndex) /********************************************************** INPUT: A Literal with an unshared Atom and an Index. RETURNS: The literal with a shared Atom inserted into the 'Index'. MEMORY: Allocates TERM_NODE memory needed to insert 'Lit' into the sharing and frees the memory of the unshared Atom. ***********************************************************/ { TERM Atom; #ifdef CHECK if (!clause_LiteralIsLiteral(Lit)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_LiteralInsertIntoSharing:"); misc_ErrorReport("\n Illegal literal input."); misc_FinishErrorReport(); } #endif Atom = clause_LiteralAtom(Lit); clause_LiteralSetAtom(Lit, sharing_Insert(Lit, Atom, ShIndex)); term_Delete(Atom); } void clause_LiteralDeleteFromSharing(LITERAL Lit, SHARED_INDEX ShIndex) /********************************************************** INPUT: A Literal and an 'Index'. RETURNS: Nothing. MEMORY: Deletes 'Lit' from Sharing, frees no more used TERM memory and frees the LITERAL_NODE. ********************************************************/ { TERM Atom; #ifdef CHECK if (!clause_LiteralIsLiteral(Lit)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_LiteralDeleteFromSharing:"); misc_ErrorReport("\n Illegal literal input."); misc_FinishErrorReport(); } #endif Atom = clause_LiteralAtom(Lit); if (clause_LiteralIsNegative(Lit)) { list_Free(term_ArgumentList(clause_LiteralSignedAtom(Lit))); term_Free(clause_LiteralSignedAtom(Lit)); } sharing_Delete(Lit, Atom, ShIndex); clause_LiteralFree(Lit); } NAT clause_GetNumberOfInstances(TERM Term, SHARED_INDEX Index) /************************************************************** INPUT: A (!) shared term and a shared index. The term has to be part of the index. RETURNS: How many clauses contain a literal that is an instance of . ***************************************************************/ { NAT Result; TERM Instance; LIST Scan; Result = 0; Instance = st_ExistInstance(cont_LeftContext(), sharing_Index(Index), Term); if (term_IsAtom(Term)) { while (Instance != NULL) { for (Scan=sharing_NAtomDataList(Instance);!list_Empty(Scan);Scan=list_Cdr(Scan)) if (!clause_GetFlag(clause_LiteralOwningClause(list_Car(Scan)), MARK)) { clause_SetFlag(clause_LiteralOwningClause(list_Car(Scan)), MARK); Result++; } Instance = st_NextCandidate(); } } else { while (Instance != NULL) { Scan = sharing_GetDataList(Instance, Index); for ( ; !list_Empty(Scan); Scan = list_Pop(Scan)) if (!clause_GetFlag(clause_LiteralOwningClause(list_Car(Scan)), MARK)) { clause_SetFlag(clause_LiteralOwningClause(list_Car(Scan)), MARK); Result++; } Instance = st_NextCandidate(); } } return Result; } static LIST clause_CopyLitInterval(CLAUSE Clause, int Start, int End) /************************************************************** INPUT: A clause and two integers representing literal indices. RETURNS: Copies of all literals in with index i and in the interval [Start:End] are prepended to . MEMORY: All atoms are copied. ***************************************************************/ { TERM Atom; LIST List; List = list_Nil(); for ( ; Start <= End; Start++) { Atom = term_Copy(clause_GetLiteralAtom(Clause, Start)); List = list_Cons(Atom, List); } return List; } static LIST clause_CopyLitIntervalExcept(CLAUSE Clause, int Start, int End, int i) /************************************************************** INPUT: A clause and three integers representing literal indeces. RETURNS: A list of atoms from literals within the interval [Start:End] except the literal at index . MEMORY: All atoms are copied. ***************************************************************/ { TERM Atom; LIST Result; Result = list_Nil(); for ( ; End >= Start; End--) if (End != i) { Atom = term_Copy(clause_GetLiteralAtom(Clause, End)); Result = list_Cons(Atom, Result); } return Result; } LIST clause_CopyConstraint(CLAUSE Clause) /************************************************************** INPUT: A clause. RETURNS: The list of copied constraint literals from . ***************************************************************/ { return clause_CopyLitInterval(Clause, clause_FirstConstraintLitIndex(Clause), clause_LastConstraintLitIndex(Clause)); } LIST clause_CopyAntecedentExcept(CLAUSE Clause, int i) /************************************************************** INPUT: A clause. RETURNS: A list containing copies of all antecedent literals except . ***************************************************************/ { return clause_CopyLitIntervalExcept(Clause, clause_FirstAntecedentLitIndex(Clause), clause_LastAntecedentLitIndex(Clause), i); } LIST clause_CopySuccedent(CLAUSE Clause) /************************************************************** INPUT: A clause. RETURNS: The list of copied succedent literals from . ***************************************************************/ { return clause_CopyLitInterval(Clause, clause_FirstSuccedentLitIndex(Clause), clause_LastSuccedentLitIndex(Clause)); } LIST clause_CopySuccedentExcept(CLAUSE Clause, int i) /************************************************************** INPUT: A clause. RETURNS: A list containing copies of all succedent literals except . ***************************************************************/ { return clause_CopyLitIntervalExcept(Clause, clause_FirstSuccedentLitIndex(Clause), clause_LastSuccedentLitIndex(Clause), i); } /**************************************************************/ /* Specials */ /**************************************************************/ BOOL clause_IsUnorderedClause(CLAUSE Clause) /********************************************************* INPUT: A clause. RETURNS: TRUE, if the invariants concerning splitting etc. hold Invariants concerning maximality restrictions are not tested. **********************************************************/ { return ((Clause != NULL) && clause_CheckSplitLevel(Clause) && (clause_IsEmptyClause(Clause) || /* Check the first literal as a "random" sample */ clause_LiteralIsLiteral(clause_GetLiteral(Clause,clause_FirstLitIndex()))) && (clause_SplitLevel(Clause) == 0 || Clause->splitfield_length>0) && clause_DependsOnSplitLevel(Clause,clause_SplitLevel(Clause))); } BOOL clause_IsClauseAux(CLAUSE Clause, FLAGSTORE FlagStore, PRECEDENCE Precedence, BOOL VarIsConst) /********************************************************* INPUT: A clause, a flag store and a precedence and a flag. RETURNS: TRUE, if literals are correctly ordered and the invariants concerning splitting etc. hold CAUTION: If is set to TRUE variables are interpreted as constants **********************************************************/ { int i; LITERAL ActLit; if (!clause_IsUnorderedClause(Clause)) return FALSE; for (i=clause_FirstAntecedentLitIndex(Clause);i<=clause_LastSuccedentLitIndex(Clause);i++) { ActLit = clause_GetLiteral(Clause,i); if (!clause_LiteralIsLiteral(ActLit)) return FALSE; if (fol_IsEquality(clause_LiteralAtom(ActLit))) { ord_RESULT HelpRes; HelpRes = ord_CompareAux(term_FirstArgument(clause_LiteralAtom(ActLit)), term_SecondArgument(clause_LiteralAtom(ActLit)), FlagStore, Precedence, VarIsConst); if (ord_IsSmallerThan(HelpRes)) return FALSE; } if (symbol_HasProperty(term_TopSymbol(clause_LiteralAtom(ActLit)), TRANSITIVE)) { ord_RESULT HelpRes; HelpRes = ord_CompareAux(term_FirstArgument(clause_LiteralAtom(ActLit)), term_SecondArgument(clause_LiteralAtom(ActLit)), FlagStore, Precedence, VarIsConst); if (HelpRes != clause_LiteralGetOrderStatus(ActLit)) return FALSE; } } return TRUE; } BOOL clause_IsClause(CLAUSE Clause, FLAGSTORE FlagStore, PRECEDENCE Precedence) /********************************************************* INPUT: A clause, a flag store and a precedence. RETURNS: TRUE, if literals are correctly ordered and the invariants concerning splitting etc. hold **********************************************************/ { return clause_IsClauseAux(Clause, FlagStore, Precedence, FALSE); } BOOL clause_IsClauseSkolem(CLAUSE Clause, FLAGSTORE FlagStore, PRECEDENCE Precedence) /********************************************************* INPUT: A clause, a flag store and a precedence. RETURNS: TRUE, if literals are correctly ordered and the invariants concerning splitting etc. hold CAUTION: Variables of are interpreted as constants **********************************************************/ { return clause_IsClauseAux(Clause, FlagStore, Precedence, TRUE); } BOOL clause_ContainsPositiveEquations(CLAUSE Clause) /********************************************************* INPUT: A clause. RETURNS: TRUE, if the clause contains a positive equality literal. **********************************************************/ { int i; for (i = clause_FirstSuccedentLitIndex(Clause); i < clause_Length(Clause); i++) if (clause_LiteralIsEquality(clause_GetLiteral(Clause, i))) return TRUE; return FALSE; } BOOL clause_ContainsNegativeEquations(CLAUSE Clause) /********************************************************* INPUT: A clause. RETURNS: TRUE, if the clause contains a positive equality literal. **********************************************************/ { int i; for (i = clause_FirstAntecedentLitIndex(Clause); i < clause_FirstSuccedentLitIndex(Clause); i++) if (clause_LiteralIsEquality(clause_GetLiteral(Clause, i))) return TRUE; return FALSE; } int clause_ContainsFolAtom(CLAUSE Clause, BOOL *Prop, BOOL *Grd, BOOL *Monadic, BOOL *NonMonadic) /********************************************************* INPUT: A clause. RETURNS: The number of boolean variables changed. If <*Prop> is FALSE and the clause contains a propositional variable, it is changed to TRUE. If <*Grd> is FALSE and the clause contains a non-propositional ground atom, it is changed to TRUE. If <*Monadic> is FALSE and the clause contains a monadic atom, it is changed to TRUE. If <*NonMonadic> is FALSE and the clause contains an at least 2-place non-equality atom, it is changed to TRUE. **********************************************************/ { int i,Result,Arity; BOOL Ground; Result = 0; i = clause_FirstLitIndex(); while (Result < 4 && i < clause_Length(Clause) && (!(*Prop) || !(*Monadic) || !(*NonMonadic))) { Arity = symbol_Arity(term_TopSymbol(clause_GetLiteralAtom(Clause,i))); Ground = term_IsGround(clause_GetLiteralAtom(Clause,i)); if (!(*Prop) && Arity == 0) { Result++; *Prop = TRUE; } if (!(*Grd) && Arity > 0 && Ground && !fol_IsEquality(clause_GetLiteralAtom(Clause,i))) { Result++; *Grd = TRUE; } if (!(*Monadic) && Arity == 1 && !Ground) { Result++; *Monadic = TRUE; } if (!(*NonMonadic) && Arity > 1 && !Ground && !fol_IsEquality(clause_GetLiteralAtom(Clause,i))) { Result++; *NonMonadic = TRUE; } i++; } return Result; } BOOL clause_ContainsVariables(CLAUSE Clause) /********************************************************* INPUT: A clause. RETURNS: TRUE, if the clause contains at least one variable **********************************************************/ { int i; TERM Term; for (i = clause_FirstLitIndex(); i < clause_Length(Clause); i++) { Term = clause_GetLiteralAtom(Clause,i); if (term_NumberOfVarOccs(Term)>0) return TRUE; } return FALSE; } void clause_ContainsSortRestriction(CLAUSE Clause, BOOL *Sortres, BOOL *USortres) /********************************************************* INPUT: A clause. RETURNS: TRUE, if the clause contains a negative monadic atom with a variable argument **********************************************************/ { int i; TERM Term; for (i = clause_FirstLitIndex(); i <= clause_LastAntecedentLitIndex(Clause) && (!*Sortres || !*USortres); i++) { Term = clause_GetLiteralAtom(Clause,i); if (symbol_IsBaseSort(term_TopSymbol(Term))) { *USortres = TRUE; if (symbol_IsVariable(term_TopSymbol(term_FirstArgument(Term)))) *Sortres = TRUE; } } } BOOL clause_ContainsFunctions(CLAUSE Clause) /********************************************************* INPUT: A clause. RETURNS: TRUE, if the clause contains at least one function symbol **********************************************************/ { int i; TERM Term; for (i = clause_FirstLitIndex(); i < clause_Length(Clause); i++) { Term = clause_GetLiteralAtom(Clause,i); if (term_ContainsFunctions(Term)) return TRUE; } return FALSE; } BOOL clause_ContainsSymbol(CLAUSE Clause, SYMBOL Symbol) /********************************************************* INPUT: A clause and a symbol. RETURNS: TRUE, if the clause contains the symbol **********************************************************/ { int i; for (i = clause_FirstLitIndex(); i < clause_Length(Clause); i++) if (term_ContainsSymbol(clause_GetLiteralAtom(Clause,i), Symbol)) return TRUE; return FALSE; } NAT clause_NumberOfSymbolOccurrences(CLAUSE Clause, SYMBOL Symbol) /********************************************************* INPUT: A clause and a symbol. RETURNS: the number of occurrences of in **********************************************************/ { int i; NAT Result; Result = 0; for (i = clause_FirstLitIndex(); i < clause_Length(Clause); i++) Result += term_NumberOfSymbolOccurrences(clause_GetLiteralAtom(Clause,i), Symbol); return Result; } BOOL clause_ImpliesFiniteDomain(CLAUSE Clause) /********************************************************* INPUT: A clause. RETURNS: TRUE, if the clause consists of a positive disjunction of equations, where each equation is of the form "x=t" for some variable "x" and ground term "t" **********************************************************/ { int i; TERM Term; if (clause_FirstLitIndex() != clause_FirstSuccedentLitIndex(Clause)) return FALSE; for (i = clause_FirstLitIndex(); i < clause_Length(Clause); i++) { Term = clause_GetLiteralTerm(Clause,i); if (!symbol_Equal(term_TopSymbol(Term),fol_Equality()) || (!symbol_IsVariable(term_TopSymbol(term_FirstArgument(Term))) && !symbol_IsVariable(term_TopSymbol(term_SecondArgument(Term)))) || (symbol_IsVariable(term_TopSymbol(term_FirstArgument(Term))) && !term_IsGround(term_SecondArgument(Term))) || (symbol_IsVariable(term_TopSymbol(term_SecondArgument(Term))) && !term_IsGround(term_FirstArgument(Term)))) return FALSE; } return TRUE; } BOOL clause_ImpliesNonTrivialDomain(CLAUSE Clause) /********************************************************* INPUT: A clause. RETURNS: TRUE, if the clause consists of a negative equation with two syntactically different arguments **********************************************************/ { if (clause_Length(Clause) == 1 && !clause_HasEmptyAntecedent(Clause) && clause_LiteralIsEquality(clause_FirstAntecedentLit(Clause)) && !term_Equal(term_FirstArgument(clause_LiteralAtom(clause_FirstAntecedentLit(Clause))), term_SecondArgument(clause_LiteralAtom(clause_FirstAntecedentLit(Clause))))) return TRUE; return FALSE; } LIST clause_FiniteMonadicPredicates(LIST Clauses) /********************************************************* INPUT: A list of clauses. RETURNS: A list of all predicate symbols that are guaranteed to have a finite extension in any minimal Herbrand model. These predicates must only positively occur in unit clauses and must have a ground term argument. **********************************************************/ { LIST Result, NonFinite, Scan; CLAUSE Clause; int i, n; SYMBOL Pred; Result = list_Nil(); NonFinite = list_Nil(); for (Scan=Clauses;!list_Empty(Scan);Scan=list_Cdr(Scan)) { Clause = (CLAUSE)list_Car(Scan); n = clause_Length(Clause); for (i=clause_FirstSuccedentLitIndex(Clause);i 0 || n > 1) { NonFinite = list_Cons((POINTER)Pred, NonFinite); Result = list_PointerDeleteElement(Result, (POINTER)Pred); } else { if (!list_PointerMember(Result, (POINTER)Pred)) Result = list_Cons((POINTER)Pred, Result); } } } } list_Delete(NonFinite); Result = list_PointerDeleteElement(Result, (POINTER)fol_Equality()); return Result; } NAT clause_NumberOfVarOccs(CLAUSE Clause) /************************************************************** INPUT: A Clause. RETURNS: The number of variable occurrences in the clause. ***************************************************************/ { int i,n; NAT Result; Result = 0; n = clause_Length(Clause); for (i = clause_FirstLitIndex(); i < n; i++) Result += term_NumberOfVarOccs(clause_GetLiteralTerm(Clause,i)); return Result; } NAT clause_ComputeWeight(CLAUSE Clause, FLAGSTORE Flags) /************************************************************** INPUT: A clause and a flag store. RETURNS: The Weight of the literals in the clause, up to now the number of variable symbols plus twice the number of signature symbols. EFFECT: The weight of the literals is updated, but not the weight of the clause! ***************************************************************/ { int i, n; NAT Weight; LITERAL Lit; Weight = 0; n = clause_Length(Clause); for (i = clause_FirstLitIndex(); i < n; i++) { Lit = clause_GetLiteral(Clause, i); clause_UpdateLiteralWeight(Lit, Flags); Weight += clause_LiteralWeight(Lit); } return Weight; } NAT clause_ComputeTermDepth(CLAUSE Clause) /************************************************************** INPUT: A Clause. RETURNS: Maximal depth of a literal in . ***************************************************************/ { int i,n; NAT Depth,Help; #ifdef CHECK if (!clause_IsUnorderedClause(Clause)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_ComputeTermDepth:"); misc_ErrorReport("\n Illegal input. Input not a clause."); misc_FinishErrorReport(); } #endif Depth = 0; n = clause_Length(Clause); for (i = clause_FirstLitIndex();i < n;i++) { Help = term_Depth(clause_GetLiteralAtom(Clause,i)); if (Help > Depth) Depth = Help; } return Depth; } NAT clause_MaxTermDepthClauseList(LIST Clauses) /************************************************************** INPUT: A list of clauses. RETURNS: Maximal depth of a clause in . ***************************************************************/ { NAT Depth,Help; Depth = 0; while (!list_Empty(Clauses)) { Help = clause_ComputeTermDepth(list_Car(Clauses)); if (Help > Depth) Depth = Help; Clauses = list_Cdr(Clauses); } return Depth; } NAT clause_ComputeSize(CLAUSE Clause) /************************************************************** INPUT: A Clause. RETURNS: The Size of the literals in the clause, up to now the number of symbols. ***************************************************************/ { int i,n; NAT Size; #ifdef CHECK if (!clause_IsUnorderedClause(Clause)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_ComputeSize:"); misc_ErrorReport("\n Illegal input. Input not a clause."); misc_FinishErrorReport(); } #endif Size = 0; n = clause_Length(Clause); for (i = clause_FirstLitIndex();i < n;i++) Size += term_ComputeSize(clause_GetLiteralTerm(Clause,i)); return Size; } BOOL clause_WeightCorrect(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence) /********************************************************* INPUT: A clause, a flag store and a precedence. RETURNS: TRUE iff the weight fields of the clause and its literals are correct. **********************************************************/ { int i, n; NAT Weight, Help; LITERAL Lit; #ifdef CHECK if (!clause_IsClause(Clause, Flags, Precedence)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_WeightCorrect:"); misc_ErrorReport("\n Illegal input. Input not a clause."); misc_FinishErrorReport(); } #endif Weight = 0; n = clause_Length(Clause); for (i = clause_FirstLitIndex(); i < n; i++) { Lit = clause_GetLiteral(Clause, i); Help = clause_LiteralComputeWeight(Lit, Flags); if (Help != clause_LiteralWeight(Lit)) return FALSE; Weight += Help; } return (clause_Weight(Clause) == Weight); } LIST clause_InsertWeighed(CLAUSE Clause, LIST UsList, FLAGSTORE Flags, PRECEDENCE Precedence) /********************************************************* INPUT: A clause, a list to insert the clause into, a flag store and a precedence. RETURNS: The list where the clause is inserted wrt its weight (Weight(Car(list)) <= Weight(Car(Cdr(list)))). MEMORY: A new listnode is allocated. **********************************************************/ { LIST Scan; NAT Weight; #ifdef CHECK if (!clause_IsClause(Clause, Flags, Precedence)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_InsertWeighted:"); misc_ErrorReport("\n Illegal input. Input not a clause."); misc_FinishErrorReport(); } #endif Weight = clause_Weight(Clause); Scan = UsList; if (list_Empty(Scan) || (clause_Weight(list_Car(Scan)) > Weight)) { return list_Cons(Clause, Scan); } else { while (!list_Empty(list_Cdr(Scan)) && (clause_Weight(list_Car(list_Cdr(Scan))) <= Weight)) { Scan = list_Cdr(Scan); } list_Rplacd(Scan, list_Cons(Clause, list_Cdr(Scan))); return UsList; } } LIST clause_ListSortWeighed(LIST Clauses) /********************************************************* INPUT: A list of clauses. RETURNS: The clause list sorted with respect to the weight of clauses, minimal weight first. EFFECT: The original list is destructively changed! This function doesn't sort stable! The function uses bucket sort for clauses with weight smaller than clause_MAXWEIGHT, and the usual list sort function for clauses with weight >= clause_MAXWEIGHT. This implies the function uses time O(n-c + c*log c), where n is the length of the list and c is the number of clauses with weight >= clause_MAXWEIGHT. For c=0 you get time O(n), for c=n you get time (n*log n). **********************************************************/ { int weight; LIST Scan; for (Scan=Clauses; !list_Empty(Scan); Scan=list_Cdr(Scan)) { weight = clause_Weight(list_Car(Scan)); if (weight < clause_MAXWEIGHT) clause_SORT[weight] = list_Cons(list_Car(Scan),clause_SORT[weight]); else clause_SORT[clause_MAXWEIGHT] = list_Cons(list_Car(Scan),clause_SORT[clause_MAXWEIGHT]); } Scan = list_NumberSort(clause_SORT[clause_MAXWEIGHT], (NAT (*)(POINTER)) clause_Weight); clause_SORT[clause_MAXWEIGHT] = list_Nil(); for (weight = clause_MAXWEIGHT-1; weight >= 0; weight--) { Scan = list_Nconc(clause_SORT[weight],Scan); clause_SORT[weight] = list_Nil(); } list_Delete(Clauses); return Scan; } LITERAL clause_LiteralCopy(LITERAL Literal) /********************************************************* INPUT: A literal. RETURNS: An unshared copy of the literal, where the owning clause-slot is set to NULL. MEMORY: Memory for a new LITERAL_NODE and all its TERMs subterms is allocated. **********************************************************/ { LITERAL Result; #ifdef CHECK if (!clause_LiteralIsLiteral(Literal)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_LiteralCopy:"); misc_ErrorReport("\n Illegal input. Input not a literal."); misc_FinishErrorReport(); } #endif Result = (LITERAL)memory_Malloc(sizeof(LITERAL_NODE)); Result->atomWithSign = term_Copy(clause_LiteralSignedAtom(Literal)); Result->ord_stat = clause_LiteralGetOrderStatus(Literal); Result->maxLit = Literal->maxLit; Result->weight = Literal->weight; Result->owningClause = (POINTER)NULL; return Result; } void clause_SetSplitDataFromList(CLAUSE Result, LIST List) { CLAUSE TempClause; LIST Scan; NAT l; Scan = List; l = Result->splitfield_length; while (!list_Empty(Scan)) { TempClause = (CLAUSE) list_Top(Scan); if (clause_GetFlag(TempClause, CONCLAUSE)) clause_SetFlag(Result, CONCLAUSE); clause_SetSplitLevel(Result, clause_SplitLevel(TempClause) > clause_SplitLevel(Result) ? clause_SplitLevel(TempClause) : clause_SplitLevel(Result)); if (l < TempClause->splitfield_length) l = TempClause->splitfield_length; Scan = list_Cdr(Scan); } if (l > Result->splitfield_length) { if (Result->splitfield != NULL) memory_Free(Result->splitfield, sizeof(SPLITFIELDENTRY) * Result->splitfield_length); Result->splitfield = memory_Malloc(sizeof(SPLITFIELDENTRY) * l); Result->splitfield_length = l; } for (l=0; l < Result->splitfield_length; l++) Result->splitfield[l] = 0; while (!list_Empty(List)) { TempClause= (CLAUSE) list_Top(List); List = list_Cdr(List); for (l=0; l < TempClause->splitfield_length; l++) Result->splitfield[l] = Result->splitfield[l] | TempClause->splitfield[l]; } } void clause_SetSplitDataFromParents(CLAUSE Result, CLAUSE Mother, CLAUSE Father) { NAT i; if (clause_GetFlag(Father, CONCLAUSE) || clause_GetFlag(Mother, CONCLAUSE)) clause_SetFlag(Result, CONCLAUSE); if ((clause_SplitLevel(Father) == 0) && (clause_SplitLevel(Mother) == 0)) return; clause_SetSplitLevel(Result, clause_SplitLevel(Mother) > clause_SplitLevel(Father) ? clause_SplitLevel(Mother) : clause_SplitLevel(Father)); if (Mother->splitfield_length > Father->splitfield_length) { if (Result->splitfield != NULL) memory_Free(Result->splitfield, sizeof(SPLITFIELDENTRY) * Result->splitfield_length); Result->splitfield = memory_Malloc(sizeof(SPLITFIELDENTRY) * Mother->splitfield_length); Result->splitfield_length = Mother->splitfield_length; for (i=0; i < Father->splitfield_length; i++) Result->splitfield[i] = Mother->splitfield[i] | Father->splitfield[i]; for (i=Father->splitfield_length; i < Mother->splitfield_length; i++) Result->splitfield[i] = Mother->splitfield[i]; } else { if (Result->splitfield != NULL) memory_Free(Result->splitfield, sizeof(SPLITFIELDENTRY) * Result->splitfield_length); Result->splitfield = memory_Malloc(sizeof(SPLITFIELDENTRY) * Father->splitfield_length); Result->splitfield_length = Father->splitfield_length; for (i=0; i < Mother->splitfield_length; i++) Result->splitfield[i] = Mother->splitfield[i] | Father->splitfield[i]; for (i=Mother->splitfield_length; i < Father->splitfield_length; i++) Result->splitfield[i] = Father->splitfield[i]; } } void clause_SetSplitDataFromFather(CLAUSE Result, CLAUSE Father) { if (clause_GetFlag(Father, CONCLAUSE)) clause_SetFlag(Result, CONCLAUSE); clause_SetSplitLevel(Result, clause_SplitLevel(Father)); clause_SetSplitField(Result, Father->splitfield, Father->splitfield_length); } void clause_UpdateSplitField(CLAUSE C1, CLAUSE C2) /********************************************************* INPUT: Two clauses C1 and C2. RETURNS: None. EFFECT: Add the split data of to . **********************************************************/ { unsigned i; if (C1->splitfield_length < C2->splitfield_length) clause_ExpandSplitField(C1, C2->splitfield_length); for (i=0; i < C2->splitfield_length; i++) C1->splitfield[i] = C1->splitfield[i] | C2->splitfield[i]; } BOOL clause_LiteralIsSort(LITERAL L) { SYMBOL S; S = clause_LiteralPredicate(L); return (symbol_IsPredicate(S) && (symbol_Arity(S) == 1)); } TERM clause_LiteralAtom(LITERAL L) { if (clause_LiteralIsNegative(L)) return term_FirstArgument(clause_LiteralSignedAtom(L)); else return clause_LiteralSignedAtom(L); } CLAUSE clause_Copy(CLAUSE Clause) /********************************************************* INPUT: A Clause. RETURNS: An unshared copy of the Clause. MEMORY: Memory for a new CLAUSE_NODE, LITERAL_NODE and all its TERMs subterms is allocated. **********************************************************/ { CLAUSE Result; int i,c,a,s,l; Result = (CLAUSE)memory_Malloc(sizeof(CLAUSE_NODE)); Result->clausenumber = clause_Number(Clause); Result->maxVar = clause_MaxVar(Clause); Result->flags = Clause->flags; clause_InitSplitData(Result); Result->validlevel = clause_SplitLevel(Clause); clause_SetSplitField(Result, Clause->splitfield, Clause->splitfield_length); Result->depth = clause_Depth(Clause); Result->weight = Clause->weight; Result->splitpotential = Clause->splitpotential; Result->parentCls = list_Copy(clause_ParentClauses(Clause)); Result->parentLits = list_Copy(clause_ParentLiterals(Clause)); Result->origin = clause_Origin(Clause); Result->c = (c = clause_NumOfConsLits(Clause)); Result->a = (a = clause_NumOfAnteLits(Clause)); Result->s = (s = clause_NumOfSuccLits(Clause)); l = c + a + s; if (l != 0) Result->literals = (LITERAL *)memory_Malloc(l * sizeof(LITERAL)); for (i = 0; i < l; i++) { clause_SetLiteral(Result, i, clause_LiteralCopy(clause_GetLiteral(Clause, i))); clause_LiteralSetOwningClause((Result->literals[i]), Result); } return Result; } SYMBOL clause_LiteralMaxVar(LITERAL Literal) /********************************************************* INPUT: A literal. RETURNS: The maximal symbol of the literals variables, if the literal is ground, symbol_GetInitialStandardVarCounter(). **********************************************************/ { TERM Term; int Bottom; SYMBOL MaxSym,Help; #ifdef CHECK if (!clause_LiteralIsLiteral(Literal)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_LiteralMaxVar:"); misc_ErrorReport("\n Illegal input. Input not a literal."); misc_FinishErrorReport(); } #endif Bottom = stack_Bottom(); MaxSym = symbol_GetInitialStandardVarCounter(); Term = clause_LiteralAtom(Literal); do { if (term_IsComplex(Term)) stack_Push(term_ArgumentList(Term)); else if (term_IsVariable(Term)) MaxSym = ((MaxSym < (Help = term_TopSymbol(Term))) ? Help : MaxSym); while (!stack_Empty(Bottom) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(Bottom)) { Term = (TERM) list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(Bottom)); return MaxSym; } SYMBOL clause_AtomMaxVar(TERM Term) /********************************************************* INPUT: A term. RETURNS: The maximal symbol of the lcontained variables, if is ground, symbol_GetInitialStandardVarCounter(). **********************************************************/ { int Bottom; SYMBOL VarSym,Help; Bottom = stack_Bottom(); VarSym = symbol_GetInitialStandardVarCounter(); do { if (term_IsComplex(Term)) stack_Push(term_ArgumentList(Term)); else if (term_IsVariable(Term)) VarSym = ((VarSym < (Help = term_TopSymbol(Term))) ? Help : VarSym); while (!stack_Empty(Bottom) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(Bottom)) { Term = (TERM)list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(Bottom)); return VarSym; } void clause_SetMaxLitFlagsAux(CLAUSE Clause, FLAGSTORE FlagStore, PRECEDENCE Precedence, BOOL VarIsConst) /********************************************************** INPUT: A clause, a flag store and a precedence. A boolean flag. RETURNS: Nothing. EFFECT: Sets the maxLit-flag for maximal literals. if is set then variables are interpreted as skolem constants. ***********************************************************/ { int i,j,n,fa; LITERAL ActLit,CompareLit; BOOL Result, Twin; ord_RESULT HelpRes; n = clause_Length(Clause); fa = clause_FirstAntecedentLitIndex(Clause); clause_RemoveFlag(Clause,CLAUSESELECT); for (i = clause_FirstLitIndex(); i < n; i++) clause_LiteralFlagReset(clause_GetLiteral(Clause, i)); if (term_StampOverflow(clause_STAMPID)) for (i = clause_FirstLitIndex(); i < n; i++) term_ResetTermStamp(clause_LiteralSignedAtom(clause_GetLiteral(Clause, i))); term_StartStamp(); /*printf("\n Start: "); clause_Print(Clause);*/ for (i = fa; i < n; i++) { ActLit = clause_GetLiteral(Clause, i); if (!term_HasTermStamp(clause_LiteralSignedAtom(ActLit))) { Result = TRUE; Twin = FALSE; for (j = fa; j < n && Result; j++) if (i != j) { CompareLit = clause_GetLiteral(Clause, j); HelpRes = ord_LiteralCompareAux(clause_LiteralSignedAtom(ActLit), clause_LiteralGetOrderStatus(ActLit), clause_LiteralSignedAtom(CompareLit), clause_LiteralGetOrderStatus(CompareLit), FALSE, VarIsConst, FlagStore, Precedence); /*printf("\n\tWe compare: "); fol_PrintDFG(clause_LiteralAtom(ActLit)); putchar(' '); fol_PrintDFG(clause_LiteralAtom(CompareLit)); printf(" Result: "); ord_Print(HelpRes);*/ if (ord_IsEqual(HelpRes)) Twin = TRUE; if (ord_IsSmallerThan(HelpRes)) Result = FALSE; if (ord_IsGreaterThan(HelpRes)) term_SetTermStamp(clause_LiteralSignedAtom(CompareLit)); } if (Result) { clause_LiteralSetFlag(ActLit, MAXIMAL); if (!Twin) clause_LiteralSetFlag(ActLit, STRICTMAXIMAL); } } } term_StopStamp(); /*printf("\n End: "); clause_Print(Clause);*/ } void clause_SetMaxLitFlagsSkolem(CLAUSE Clause, FLAGSTORE FlagStore, PRECEDENCE Precedence) /********************************************************** INPUT: A clause, a flag store and a precedence. RETURNS: Nothing. EFFECT: Sets the maxLit-flag for maximal literals. variables are interpreted as skolem constants ***********************************************************/ { clause_SetMaxLitFlagsAux(Clause, FlagStore, Precedence, TRUE); } void clause_SetMaxLitFlags(CLAUSE Clause, FLAGSTORE FlagStore, PRECEDENCE Precedence) /********************************************************** INPUT: A clause, a flag store and a precedence. RETURNS: Nothing. EFFECT: Sets the maxLit-flag for maximal literals. ***********************************************************/ { clause_SetMaxLitFlagsAux(Clause, FlagStore, Precedence, FALSE); } void clause_SetNativeMaxLitFlags(CLAUSE Clause, FLAGSTORE FlagStore, PRECEDENCE Precedence) /********************************************************** INPUT: A clause, a flag store and a precedence. RETURNS: Nothing. EFFECT: Sets the maxLit-flag for maximal literals, keeping the sel flag on literals in input clauses. ***********************************************************/ { int i,j,n,fa; LITERAL ActLit,CompareLit; BOOL Result, Twin; ord_RESULT HelpRes; n = clause_Length(Clause); fa = clause_FirstAntecedentLitIndex(Clause); /* Reset literal flags first. */ if (clause_GetFlag(Clause, CLAUSESELECT)) /* If selected literals need to be kept, only reset maxlit and strictmaxlit flags. */ for (i = clause_FirstLitIndex(); i < n; i++) clause_LiteralFlagResetAndKeepSelFlag(clause_GetLiteral(Clause, i)); else { /* Otherwise, reset the literal flag. */ for (i = clause_FirstLitIndex(); i < n; i++) clause_LiteralFlagReset(clause_GetLiteral(Clause, i)); } if (term_StampOverflow(clause_STAMPID)) for (i = clause_FirstLitIndex(); i < n; i++) term_ResetTermStamp(clause_LiteralSignedAtom(clause_GetLiteral(Clause, i))); term_StartStamp(); /*printf("\n Start: "); clause_Print(Clause);*/ for (i = fa; i < n; i++) { ActLit = clause_GetLiteral(Clause, i); if (!term_HasTermStamp(clause_LiteralSignedAtom(ActLit))) { Result = TRUE; Twin = FALSE; for (j = fa; j < n && Result; j++) if (i != j) { CompareLit = clause_GetLiteral(Clause, j); HelpRes = ord_LiteralCompare(clause_LiteralSignedAtom(ActLit), clause_LiteralGetOrderStatus(ActLit), clause_LiteralSignedAtom(CompareLit), clause_LiteralGetOrderStatus(CompareLit), FALSE, FlagStore, Precedence); /*printf("\n\tWe compare: "); fol_PrintDFG(clause_LiteralAtom(ActLit)); putchar(' '); fol_PrintDFG(clause_LiteralAtom(CompareLit)); printf(" Result: "); ord_Print(HelpRes);*/ if (ord_IsEqual(HelpRes)) Twin = TRUE; if (ord_IsSmallerThan(HelpRes)) Result = FALSE; if (ord_IsGreaterThan(HelpRes)) term_SetTermStamp(clause_LiteralSignedAtom(CompareLit)); } if (Result) { clause_LiteralSetFlag(ActLit, MAXIMAL); if (!Twin) clause_LiteralSetFlag(ActLit, STRICTMAXIMAL); } } } term_StopStamp(); /*printf("\n End: "); clause_Print(Clause);*/ } SYMBOL clause_SearchMaxVar(CLAUSE Clause) /********************************************************** INPUT: A clause. RETURNS: The maximal symbol of the clauses variables. If the clause is ground, symbol_GetInitialStandardVarCounter(). ***********************************************************/ { int i, n; SYMBOL Help, MaxSym; n = clause_Length(Clause); MaxSym = symbol_GetInitialStandardVarCounter(); for (i = 0; i < n; i++) { Help = clause_LiteralMaxVar(clause_GetLiteral(Clause, i)); if (Help > MaxSym) MaxSym = Help; } return MaxSym; } void clause_RenameVarsBiggerThan(CLAUSE Clause, SYMBOL MinVar) /********************************************************** INPUT: A clause and a variable symbol. RETURNS: The clause with variables renamed in a way, that all vars are (excl.) bigger than MinVar. ***********************************************************/ { int i,n; #ifdef CHECK if (!clause_IsUnorderedClause(Clause)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_RenameVarsBiggerThan:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } #endif if (MinVar != symbol_GetInitialStandardVarCounter()) { n = clause_Length(Clause); term_StartMaxRenaming(MinVar); for (i = clause_FirstLitIndex(); i < n; i++) term_Rename(clause_GetLiteralTerm(Clause, i)); } } void clause_Normalize(CLAUSE Clause) /********************************************************** INPUT: A clause. RETURNS: The term with normalized Variables, DESTRUCTIVE on the variable subterms' topsymbols. ***********************************************************/ { int i,n; n = clause_Length(Clause); term_StartMinRenaming(); for (i = clause_FirstLitIndex(); i < n; i++) term_Rename(clause_GetLiteralTerm(Clause, i)); } void clause_SubstApply(SUBST Subst, CLAUSE Clause) /********************************************************** INPUT: A clause. RETURNS: Nothing. EFFECTS: Applies the substitution to the clause. ***********************************************************/ { int i,n; #ifdef CHECK if (!clause_IsUnorderedClause(Clause)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_SubstApply:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } #endif n = clause_Length(Clause); for (i=clause_FirstLitIndex(); i in are replaced by copies if . CAUTION: The maximum variable of the clause is not updated! ***********************************************************/ { int i, li; #ifdef CHECK if (!symbol_IsVariable(Var)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_ReplaceVariable: symbol is not a variable"); misc_FinishErrorReport(); } #endif li = clause_LastLitIndex(Clause); for (i = clause_FirstLitIndex(); i <= li; i++) term_ReplaceVariable(clause_GetLiteralAtom(Clause,i), Var, Term); } void clause_UpdateMaxVar(CLAUSE Clause) /********************************************************** INPUT: A clause. RETURNS: Nothing. EFFECTS: Actualizes the MaxVar slot wrt the actual literals. ***********************************************************/ { clause_SetMaxVar(Clause, clause_SearchMaxVar(Clause)); } void clause_PrecomputeOrderingAux(CLAUSE Clause, FLAGSTORE FlagStore, PRECEDENCE Precedence, BOOL VarIsConst) /********************************************************** INPUT: An unshared clause, a flag store and a precedence, a boolean flag RETURNS: Nothing. EFFECTS: Reorders the arguments of equality literals wrt. the ordering. Thus first arguments aren't smaller after the application. Also computes the ordering status of transitive predicates. If is set variables are treated as skolem constants ***********************************************************/ { int i,length; LITERAL Lit; ord_RESULT HelpRes; /*printf("\n Clause: ");clause_Print(Clause);*/ length = clause_Length(Clause); for (i = clause_FirstLitIndex(); i < length; i++) { Lit = clause_GetLiteral(Clause, i); if (clause_LiteralIsEquality(Lit)) { HelpRes = ord_CompareAux(term_FirstArgument(clause_LiteralAtom(Lit)), term_SecondArgument(clause_LiteralAtom(Lit)), FlagStore, Precedence, VarIsConst); /*printf("\n\tWe compare: "); fol_PrintDFG(term_FirstArgument(clause_LiteralAtom(Lit))); putchar(' '); fol_PrintDFG(term_SecondArgument(clause_LiteralAtom(Lit))); printf("\nResult: "); ord_Print(HelpRes);*/ switch(HelpRes) { case ord_SMALLER_THAN: /* printf("\nSwapping: "); term_Print(clause_LiteralAtom(Lit)); DBG */ term_EqualitySwap(clause_LiteralAtom(Lit)); clause_LiteralSetOrderStatus(Lit,ord_GREATER_THAN); /* Swapped = TRUE; */ break; case ord_GREATER_THAN: clause_LiteralSetOrderStatus(Lit,ord_GREATER_THAN); break; default: clause_LiteralSetOrderStatus(Lit,HelpRes); break; } } else { if (symbol_HasProperty(term_TopSymbol(clause_LiteralAtom(Lit)), TRANSITIVE)) { HelpRes = ord_CompareAux(term_FirstArgument(clause_LiteralAtom(Lit)), term_SecondArgument(clause_LiteralAtom(Lit)), FlagStore, Precedence, VarIsConst); /* printf("\n\tWe compare: "); fol_PrintDFG(term_FirstArgument(clause_LiteralAtom(Lit))); putchar(' '); fol_PrintDFG(term_SecondArgument(clause_LiteralAtom(Lit))); printf("\nResult: "); ord_Print(HelpRes); */ clause_LiteralSetOrderStatus(Lit,HelpRes); } else /* This is slightly arbitrary (although consistent with the theory).*/ clause_LiteralSetOrderStatus(Lit,ord_GREATER_THAN); } } } void clause_PrecomputeOrderingSkolem(CLAUSE Clause, FLAGSTORE FlagStore, PRECEDENCE Precedence) /********************************************************** INPUT: A clause, a Flagstore and a precedence RETURNS: Nothing. EFFECTS: Reorders the arguments of equalities. Also computes the ordering status of transitive predicates. Variables are interpreted as skolem constants ***********************************************************/ { clause_PrecomputeOrderingAux(Clause, FlagStore, Precedence, TRUE); } void clause_PrecomputeOrdering(CLAUSE Clause, FLAGSTORE FlagStore, PRECEDENCE Precedence) /********************************************************** INPUT: A Clause, a Flagstore and a precedence RETURNS: Nothing. EFFECTS: Reorders the arguments of equality literals wrt. the ordering. Thus first arguments aren't smaller after the application. Also computes the ordering status of transitive predicates. If is set variables are treated as skolem constants ***********************************************************/ { clause_PrecomputeOrderingAux(Clause, FlagStore, Precedence, FALSE); } void clause_InsertFlatIntoIndex(CLAUSE Clause, st_INDEX Index) /********************************************************** INPUT: An unshared clause and an index. EFFECT: The atoms of are inserted into the index. A link from the atom to its literal via the supertermlist is established. ***********************************************************/ { int i,n; LITERAL Lit; TERM Atom ; n = clause_Length(Clause); for (i=clause_FirstLitIndex();i of size +1. RETURNS: Nothing. EFFECT: The index i within the array corresponds to the index of a variable x_i. For each variable x_i, 0<=i<=MaxIndex the size of its substitution term is calculated and written to Map[i]. ***************************************************************/ { NAT *Scan; #ifdef CHECK if (subst_Empty(Subst) || Map == NULL) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_VarToSizeMap: Illegal input."); misc_FinishErrorReport(); } #endif /* Initialization */ for (Scan = Map + MaxIndex; Scan >= Map; Scan--) *Scan = 1; /* Compute the size of substitution terms */ for ( ; !subst_Empty(Subst); Subst = subst_Next(Subst)) Map[subst_Dom(Subst)] = term_ComputeSize(subst_Cod(Subst)); } static NAT clause_ComputeTermSize(TERM Term, NAT* VarMap) /************************************************************** INPUT: A term and a an array of NATs. RETURNS: The number of symbols in the term. EFFECT: This function calculates the number of symbols in with respect to some substitution s. A naive way to do this is to apply the substitution to a copy of the term, and to count the number of symbols in the copied term. We use a more sophisticated algorithm, that first stores the size of every variable's substitution term in . We then 'scan' the term and for a variable occurrence x_i we simply add the corresponding value VarMap[i] to the result. This way we avoid copying the term and the substitution terms, which is especially useful if we reuse the VarMap several times. ***************************************************************/ { NAT Stack, Size; #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_ComputeTermSize: Illegal input."); misc_FinishErrorReport(); } #endif Size = 0; Stack = stack_Bottom(); do { if (VarMap!=NULL && symbol_IsVariable(term_TopSymbol(Term))) Size += VarMap[symbol_VarIndex(term_TopSymbol(Term))]; else { Size++; 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)); return Size; } LIST clause_MoveBestLiteralToFront(LIST Literals, SUBST Subst, SYMBOL MaxVar, BOOL (*Better)(LITERAL, NAT, LITERAL, NAT)) /************************************************************** INPUT: A list of literals, a substitution, the maximum variable from the domain of the substitution, and a comparison function. The function will be called with two literals L1 and L2 and two number S1 and S2, where Si is the size of the atom of Li with respect to variable bindings in . RETURNS: The same list. EFFECT: This function moves the first literal L to the front of the list, so that no other literal L' is better than L with respect to the function . The function exchanges only the literals, the order of list items within the list is not changed. ***************************************************************/ { NAT *Map, MapSize, BestSize, Size; LIST Best, Scan; #ifdef CHECK if (!list_IsSetOfPointers(Literals)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_MoveBestLiteralToFront: List contains duplicates"); misc_FinishErrorReport(); } #endif if (list_Empty(Literals) || list_Empty(list_Cdr(Literals))) /* < 2 list items, so nothing to do */ return Literals; Map = NULL; MapSize = 0; if (!subst_Empty(Subst)) { MapSize = symbol_VarIndex(MaxVar) + 1; Map = memory_Malloc(sizeof(NAT)*MapSize); clause_VarToSizeMap(Subst, Map, MapSize-1); } Best = Literals; /* Remember list item, not literal itself */ BestSize = clause_ComputeTermSize(clause_LiteralAtom(list_Car(Best)), Map); for (Scan = list_Cdr(Literals); !list_Empty(Scan); Scan = list_Cdr(Scan)) { Size = clause_ComputeTermSize(clause_LiteralAtom(list_Car(Scan)), Map); if (Better(list_Car(Scan), Size, list_Car(Best), BestSize)) { /* Actual literal is better than the best encountered so far */ BestSize = Size; Best = Scan; } } if (Best != Literals) { /* Move best literal to the front. We just exchange the literals. */ LITERAL h = list_Car(Literals); list_Rplaca(Literals, list_Car(Best)); list_Rplaca(Best, h); } /* cleanup */ if (Map != NULL) memory_Free(Map, sizeof(NAT)*MapSize); return Literals; } /**************************************************************/ /* Literal Output Functions */ /**************************************************************/ void clause_LiteralPrint(LITERAL Literal) /************************************************************** INPUT: A Literal. RETURNS: Nothing. ***************************************************************/ { #ifdef CHECK if (!clause_LiteralIsLiteral(Literal)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_LiteralPrint:"); misc_ErrorReport("\n Illegal input. Input not a literal."); misc_FinishErrorReport(); } #endif term_PrintPrefix(clause_LiteralSignedAtom(Literal)); } void clause_LiteralListPrint(LIST LitList) /************************************************************** INPUT: A list of literals. RETURNS: Nothing. SUMMARY: Prints the literals to stdout. ***************************************************************/ { while (!(list_Empty(LitList))) { clause_LiteralPrint(list_First(LitList)); LitList = list_Cdr(LitList); if (!list_Empty(LitList)) putchar(' '); } } void clause_LiteralPrintUnsigned(LITERAL Literal) /************************************************************** INPUT: A Literal. RETURNS: Nothing. SUMMARY: ***************************************************************/ { #ifdef CHECK if (!clause_LiteralIsLiteral(Literal)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_LiteralPrintUnsigned:"); misc_ErrorReport("\n Illegal input. Input not a literal."); misc_FinishErrorReport(); } #endif term_PrintPrefix(clause_LiteralAtom(Literal)); fflush(stdout); } void clause_LiteralPrintSigned(LITERAL Literal) /************************************************************** INPUT: A Literal. RETURNS: Nothing. SUMMARY: ***************************************************************/ { #ifdef CHECK if (!clause_LiteralIsLiteral(Literal)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_LiteralPrintSigned:"); misc_ErrorReport("\n Illegal input. Input not a literal."); misc_FinishErrorReport(); } #endif term_PrintPrefix(clause_LiteralSignedAtom(Literal)); fflush(stdout); } void clause_LiteralFPrint(FILE* File, LITERAL Lit) /************************************************************** INPUT: A file and a literal. RETURNS: Nothing. ************************************************************/ { term_FPrintPrefix(File, clause_LiteralSignedAtom(Lit)); } void clause_LiteralFPrintUnsigned(FILE* File, LITERAL Lit) /************************************************************** INPUT: A file and a literal. RETURNS: Nothing. ************************************************************/ { term_FPrintPrefix(File, clause_LiteralAtom(Lit)); } LIST clause_GetLiteralSubSetList(CLAUSE Clause, int StartIndex, int EndIndex, FLAGSTORE FlagStore, PRECEDENCE Precedence) /************************************************************** INPUT: A clause, a start literal index, an end index, a flag store and a precedence. RETURNS: The list of literals between the start and the end index. It is a list of pointers, not a list of indices. **************************************************************/ { LIST Result; int i; #ifdef CHECK if (!clause_IsClause(Clause, FlagStore, Precedence)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_ReplaceLiteralSubSet:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } if ((StartIndex < clause_FirstLitIndex()) || (EndIndex > clause_LastLitIndex(Clause))) { misc_ErrorReport("\n In clause_ReplaceLiteralSubSet:"); misc_ErrorReport("\n Illegal input."); misc_ErrorReport("\n Index out of range."); misc_FinishErrorReport(); } #endif Result = list_Nil(); for (i=StartIndex; i<=EndIndex; i++) { Result = list_Cons(clause_GetLiteral(Clause, i), Result); } return Result; } void clause_ReplaceLiteralSubSet(CLAUSE Clause, int StartIndex, int EndIndex, LIST Replacement, FLAGSTORE FlagStore, PRECEDENCE Precedence) /************************************************************** INPUT: A clause, a start literal index, an end literal index, a flag store and a precedence. RETURNS: None. EFFECT: Replaces the subset of literals in with indices between (and including) and with literals from the list. **************************************************************/ { int i; LIST Scan; #ifdef CHECK if (!clause_IsClause(Clause, FlagStore, Precedence)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_ReplaceLiteralSubSet:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } if ((StartIndex < clause_FirstLitIndex()) || (EndIndex > clause_LastLitIndex(Clause))) { misc_ErrorReport("\n In clause_ReplaceLiteralSubSet:"); misc_ErrorReport("\n Illegal input."); misc_ErrorReport("\n Index out of range."); misc_FinishErrorReport(); } if (list_Length(Replacement) != (EndIndex - StartIndex + 1)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_ReplaceLiteralSubSet:"); misc_ErrorReport("\n Illegal input. Replacement list size"); misc_ErrorReport("\n and set size don't match"); misc_FinishErrorReport(); } #endif for (i = StartIndex, Scan = Replacement; i <= EndIndex; i++, Scan = list_Cdr(Scan)) { clause_SetLiteral(Clause, i, list_Car(Scan)); } } BOOL clause_LiteralsCompare(LITERAL Left, LITERAL Right) /************************************************************** INPUT: Two literals. RETURNS: TRUE if Left <= Right, FALSE otherwise. EFFECT: Compares literals by comparing their terms' arities. ***************************************************************/ { #ifdef CHECK if (!(clause_LiteralIsLiteral(Left) && clause_LiteralIsLiteral(Right))) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_LiteralsCompare:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } #endif return term_CompareAbstractLEQ(clause_LiteralSignedAtom(Left), clause_LiteralSignedAtom(Right)); } void clause_FixLiteralSubsetOrder(CLAUSE Clause, int StartIndex, int EndIndex, FLAGSTORE FlagStore, PRECEDENCE Precedence) /************************************************************** INPUT: A clause, a start index, an end index a flag store and a precedence. RETURNS: None. EFFECT: Sorts literals with indices between (and including) and with respect to an abstract list representation of terms that identifies function symbols with their arity. ***************************************************************/ { LIST literals; #ifdef CHECK if ((StartIndex < clause_FirstLitIndex()) || (EndIndex > clause_LastLitIndex(Clause))) { misc_ErrorReport("\n In clause_FixLiteralSubSetOrder:"); misc_ErrorReport("\n Illegal input."); misc_ErrorReport("\n Index out of range."); misc_FinishErrorReport(); } #endif /* Get the literals */ literals = clause_GetLiteralSubSetList(Clause, StartIndex, EndIndex, FlagStore, Precedence); /* Sort them */ literals = list_Sort(literals, (BOOL (*) (POINTER, POINTER)) clause_LiteralsCompare); /* Replace clause literals in subset with sorted literals */ clause_ReplaceLiteralSubSet(Clause, StartIndex, EndIndex, literals, FlagStore, Precedence); list_Delete(literals); } void clause_FixLiteralOrder(CLAUSE Clause, FLAGSTORE FlagStore, PRECEDENCE Precedence) /************************************************************** INPUT: A clause, a flag store, and a precedence. RETURNS: None. EFFECT: Fixes literal order in a . Different literal types are ordered separately. ***************************************************************/ { #ifdef CHECK if (!clause_IsClause(Clause, FlagStore, Precedence)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_FixLiteralOrder:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } #endif /* Fix antecedent literal order */ clause_FixLiteralSubsetOrder(Clause, clause_FirstAntecedentLitIndex(Clause), clause_LastAntecedentLitIndex(Clause), FlagStore, Precedence); /* Fix succedent literal order */ clause_FixLiteralSubsetOrder(Clause, clause_FirstSuccedentLitIndex(Clause), clause_LastSuccedentLitIndex(Clause), FlagStore, Precedence); /* Fix constraint literal order */ clause_FixLiteralSubsetOrder(Clause, clause_FirstConstraintLitIndex(Clause), clause_LastConstraintLitIndex(Clause), FlagStore, Precedence); /* Normalize clause, to get variable names right. */ clause_Normalize(Clause); } static int clause_CompareByWeight(CLAUSE Left, CLAUSE Right) /************************************************************** INPUT: Two clauses. RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. EFFECT: Compares two clauses by their weight. ***************************************************************/ { NAT lweight, rweight; int result; lweight = clause_Weight(Left); rweight = clause_Weight(Right); if (lweight < rweight) { result = -1; } else if (lweight > rweight) { result = 1; } else { result = 0; } return result; } static int clause_CompareByClausePartSize(CLAUSE Left, CLAUSE Right) /************************************************************** INPUT: Two clauses. RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. EFFECT: Compares two clauses by the number of literals in the antecedent, succedent and constraint. ***************************************************************/ { int lsize, rsize; lsize = clause_NumOfAnteLits(Left); rsize = clause_NumOfAnteLits(Right); if (lsize < rsize) return -1; else if (lsize > rsize) return 1; lsize = clause_NumOfSuccLits(Left); rsize = clause_NumOfSuccLits(Right); if (lsize < rsize) return -1; else if (lsize > rsize) return 1; lsize = clause_NumOfConsLits(Left); rsize = clause_NumOfConsLits(Right); if (lsize < rsize) return -1; else if (lsize > rsize) return 1; return 0; } void clause_CountSymbols(CLAUSE Clause) /************************************************************** INPUT: A clause. RETURNS: None. EFFECT: Counts the non-variable symbols in the clause, and increases their counts accordingly. ***************************************************************/ { int i; for (i=clause_FirstLitIndex(); i<=clause_LastLitIndex(Clause); i++) { LITERAL l; TERM t; l = clause_GetLiteral(Clause, i); if (clause_LiteralIsPredicate(l)) { SYMBOL S; S = clause_LiteralPredicate(l); symbol_SetCount(S, symbol_GetCount(S) + 1); } t = clause_GetLiteralAtom(Clause, i); term_CountSymbols(t); } } LIST clause_ListOfPredicates(CLAUSE Clause) /************************************************************** INPUT: A clause. RETURNS: A list of symbols. EFFECT: Creates a list of predicates occurring in the clause. A predicate occurs several times in the list, if it does so in the clause. ***************************************************************/ { LIST preds; int i; preds = list_Nil(); for (i=clause_FirstLitIndex(); i<=clause_LastLitIndex(Clause); i++) { LITERAL l; l = clause_GetLiteral(Clause, i); if (clause_LiteralIsPredicate(l)) { preds = list_Cons((POINTER) clause_LiteralPredicate(l), preds); } } return preds; } LIST clause_ListOfConstants(CLAUSE Clause) /************************************************************** INPUT: A clause. RETURNS: A list of symbols. EFFECT: Creates a list of constants occurring in the clause. A constant occurs several times in the list, if it does so in the clause. ***************************************************************/ { LIST consts; int i; consts = list_Nil(); for (i=clause_FirstLitIndex(); i<=clause_LastLitIndex(Clause); i++) { TERM t; t = clause_GetLiteralAtom(Clause, i); consts = list_Nconc(term_ListOfConstants(t), consts); } return consts; } LIST clause_ListOfVariables(CLAUSE Clause) /************************************************************** INPUT: A clause. RETURNS: A list of variables. EFFECT: Creates a list of variables occurring in the clause. A variable occurs several times in the list, if it does so in the clause. ***************************************************************/ { LIST vars; int i; vars = list_Nil(); for (i=clause_FirstLitIndex(); i<=clause_LastLitIndex(Clause); i++) { TERM t; t = clause_GetLiteralAtom(Clause, i); vars = list_Nconc(term_ListOfVariables(t), vars); } return vars; } LIST clause_ListOfFunctions(CLAUSE Clause) /************************************************************** INPUT: A clause. RETURNS: A list of symbols. EFFECT: Creates a list of functions occurring in the clause. A function occurs several times in the list, if it does so in the clause. ***************************************************************/ { LIST funs; int i; funs = list_Nil(); for (i=clause_FirstLitIndex(); i<=clause_LastLitIndex(Clause); i++) { TERM t; t = clause_GetLiteralAtom(Clause, i); funs = list_Nconc(term_ListOfFunctions(t), funs); } return funs; } static int clause_CompareByPredicateDistribution(CLAUSE Left, CLAUSE Right) /************************************************************** INPUT: Two clauses. RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. EFFECT: Compares two clauses by the frequency of predicates. ***************************************************************/ { LIST lpreds, rpreds; int result; lpreds = clause_ListOfPredicates(Left); rpreds = clause_ListOfPredicates(Right); result = list_CompareMultisetsByElementDistribution(lpreds, rpreds); list_Delete(lpreds); list_Delete(rpreds); return result; } static int clause_CompareByConstantDistribution(CLAUSE Left, CLAUSE Right) /************************************************************** INPUT: Two clauses. RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. EFFECT: Compares two clauses by the frequency of constants. ***************************************************************/ { LIST lconsts, rconsts; int result; lconsts = clause_ListOfConstants(Left); rconsts = clause_ListOfConstants(Right); result = list_CompareMultisetsByElementDistribution(lconsts, rconsts); list_Delete(lconsts); list_Delete(rconsts); return result; } static int clause_CompareByVariableDistribution(CLAUSE Left, CLAUSE Right) /************************************************************** INPUT: Two clauses. RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. EFFECT: Compares two clauses by the frequency of variables. ***************************************************************/ { LIST lvars, rvars; int result; lvars = clause_ListOfVariables(Left); rvars = clause_ListOfVariables(Right); result = list_CompareMultisetsByElementDistribution(lvars, rvars); list_Delete(lvars); list_Delete(rvars); return result; } static int clause_CompareByFunctionDistribution(CLAUSE Left, CLAUSE Right) /************************************************************** INPUT: Two clauses. RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. EFFECT: Compares two clauses by the frequency of functions. ***************************************************************/ { LIST lfuns, rfuns; int result; lfuns = clause_ListOfFunctions(Left); rfuns = clause_ListOfFunctions(Right); result = list_CompareMultisetsByElementDistribution(lfuns, rfuns); list_Delete(lfuns); list_Delete(rfuns); return result; } static int clause_CompareByDepth(CLAUSE Left, CLAUSE Right) /************************************************************** INPUT: Two clauses. RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. EFFECT: Compares two clauses by their depth. ***************************************************************/ { if (clause_Depth(Left) < clause_Depth(Right)) return -1; else if (clause_Depth(Left) > clause_Depth(Right)) return 1; return 0; } static int clause_CompareByMaxVar(CLAUSE Left, CLAUSE Right) /************************************************************** INPUT: Two clauses. RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. EFFECT: Compares two clauses by their maximal variable. ***************************************************************/ { if (clause_MaxVar(Left) < clause_MaxVar(Right)) return -1; else if (clause_MaxVar(Left) > clause_MaxVar(Right)) return 1; return 0; } static int clause_CompareByLiterals(CLAUSE Left, CLAUSE Right) /************************************************************** INPUT: Two clauses. RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. EFFECT: Compares two clauses by comparing their literals from left to right. ***************************************************************/ { int firstlitleft, lastlitleft; int firstlitright, lastlitright; int i, j; int result; result = 0; /* Compare sorted literals from right to left */ firstlitleft = clause_FirstLitIndex(); lastlitleft = clause_LastLitIndex(Left); firstlitright = clause_FirstLitIndex(); lastlitright = clause_LastLitIndex(Right); for (i = lastlitleft, j = lastlitright; i >= firstlitleft && j >= firstlitright; --i, --j) { TERM lterm, rterm; lterm = clause_GetLiteralTerm(Left, i); rterm = clause_GetLiteralTerm(Right, j); result = term_CompareAbstract(lterm, rterm); if (result != 0) break; } if (result == 0) { /* All literals compared equal, so check if someone has uncompared literals left over. */ if ( i > j) { /* Left clause has uncompared literals left over. */ result = 1; } else if (i < j) { /* Right clause has uncompared literals left over. */ result = -1; } } return result; } static int clause_CompareBySymbolOccurences(CLAUSE Left, CLAUSE Right) /************************************************************** INPUT: Two clauses. RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. EFFECT: Compares two clauses by comparing the occurrences of symbols in their respective literals from left to right. If a symbol occurs less frequently than its positional equivalent in the other clause, then the first clause is smaller. ***************************************************************/ { int firstlitleft, lastlitleft; int firstlitright, lastlitright; int i, j; int result; result = 0; /* Compare sorted literals from right to left */ firstlitleft = clause_FirstLitIndex(); lastlitleft = clause_LastLitIndex(Left); firstlitright = clause_FirstLitIndex(); lastlitright = clause_LastLitIndex(Right); for (i = lastlitleft, j = lastlitright; i >= firstlitleft && j >= firstlitright; --i, --j) { TERM lterm, rterm; LITERAL llit, rlit; llit = clause_GetLiteral(Left, i); rlit = clause_GetLiteral(Right, j); if (clause_LiteralIsPredicate(llit)) { if (clause_LiteralIsPredicate(rlit)) { if (symbol_GetCount(clause_LiteralPredicate(llit)) < symbol_GetCount(clause_LiteralPredicate(rlit))) { return -1; } else if (symbol_GetCount(clause_LiteralPredicate(llit)) > symbol_GetCount(clause_LiteralPredicate(rlit))) { return 1; } } } lterm = clause_GetLiteralTerm(Left, i); rterm = clause_GetLiteralTerm(Right, j); result = term_CompareBySymbolOccurences(lterm, rterm); if (result != 0) break; } return result; } int clause_CompareAbstract(CLAUSE Left, CLAUSE Right) /************************************************************** INPUT: Two clauses. RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. EFFECT: Compares two clauses by their weight. If the weight is equal, it compares the clauses by the arity of their literals from right to left. CAUTION: Expects clause literal order to be fixed. ***************************************************************/ { typedef int (*CLAUSE_COMPARE_FUNCTION) (CLAUSE, CLAUSE); static const CLAUSE_COMPARE_FUNCTION clause_compare_functions [] = { clause_CompareByWeight, clause_CompareByDepth, clause_CompareByMaxVar, clause_CompareByClausePartSize, clause_CompareByLiterals, clause_CompareBySymbolOccurences, clause_CompareByPredicateDistribution, clause_CompareByConstantDistribution, clause_CompareByFunctionDistribution, clause_CompareByVariableDistribution, }; int result; int i; int functions; result = 0; functions = sizeof(clause_compare_functions)/sizeof(CLAUSE_COMPARE_FUNCTION); for (i = 0; i < functions; i++) { result = clause_compare_functions[i](Left, Right); if ( result != 0) { return result; } } return 0; } /**************************************************************/ /* Clause functions */ /**************************************************************/ void clause_Init(void) /************************************************************** INPUT: None. RETURNS: Nothing. SUMMARY: Initializes the clause counter and other variables from this module. ***************************************************************/ { int i; clause_SetCounter(1); clause_STAMPID = term_GetStampID(); for (i = 0; i <= clause_MAXWEIGHT; i++) clause_SORT[i] = list_Nil(); } CLAUSE clause_CreateBody(int ClauseLength) /************************************************************** INPUT: The number of literals as integer. RETURNS: A new generated clause node for 'ClauseLength' MEMORY: Allocates a CLAUSE_NODE and the needed array for LITERALs. *************************************************************/ { CLAUSE Result; Result = (CLAUSE)memory_Malloc(sizeof(CLAUSE_NODE)); Result->clausenumber = clause_IncreaseCounter(); Result->maxVar = symbol_GetInitialStandardVarCounter(); Result->flags = 0; Result->depth = 0; Result->splitpotential = 0.0; clause_InitSplitData(Result); Result->weight = clause_WEIGHTUNDEFINED; Result->parentCls = list_Nil(); Result->parentLits = list_Nil(); Result->c = 0; Result->a = 0; Result->s = 0; if (ClauseLength != 0) Result->literals = (LITERAL *)memory_Malloc((ClauseLength) * sizeof(LITERAL)); clause_SetFromInput(Result); return Result; } CLAUSE clause_CreateAux(LIST Constraint, LIST Antecedent, LIST Succedent, FLAGSTORE Flags, PRECEDENCE Precedence, BOOL VarIsConst) /************************************************************** INPUT: Three lists of pointers to atoms, a flag store, a precedence and a flag RETURNS: The new generated clause. MEMORY: Allocates a CLAUSE_NODE and the needed LITERAL_NODEs, uses the terms from the lists, additionally allocates termnodes for the fol_Not() in Const. and Ante. CAUTION: If is TRUE then variables are interpreted as constants *************************************************************/ { CLAUSE Result; int i, c, a, s; Result = (CLAUSE)memory_Malloc(sizeof(CLAUSE_NODE)); Result->clausenumber = clause_IncreaseCounter(); Result->flags = 0; Result->depth = 0; Result->weight = clause_WEIGHTUNDEFINED; Result->splitpotential = 0.0; clause_InitSplitData(Result); Result->parentCls = list_Nil(); Result->parentLits = list_Nil(); Result->c = (c = list_Length(Constraint)); Result->a = (a = list_Length(Antecedent)); Result->s = (s = list_Length(Succedent)); if (!clause_IsEmptyClause(Result)) Result->literals = (LITERAL *) memory_Malloc((c+a+s) * sizeof(LITERAL)); for (i = 0; i < c; i++) { Result->literals[i] = clause_LiteralCreate(term_Create(fol_Not(), list_List((TERM)list_Car(Constraint))),Result); Constraint = list_Cdr(Constraint); } a += c; for ( ; i < a; i++) { Result->literals[i] = clause_LiteralCreate(term_Create(fol_Not(), list_List((TERM)list_Car(Antecedent))), Result); Antecedent = list_Cdr(Antecedent); } s += a; for ( ; i < s; i++) { Result->literals[i] = clause_LiteralCreate((TERM) list_Car(Succedent), Result); Succedent = list_Cdr(Succedent); } if(VarIsConst) clause_PrecomputeOrderingAndReInitSkolem(Result, Flags, Precedence); else clause_PrecomputeOrderingAndReInit(Result, Flags, Precedence); clause_SetFromInput(Result); return Result; } CLAUSE clause_Create(LIST Constraint, LIST Antecedent, LIST Succedent, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: Three lists of pointers to atoms, a flag store and a precedence. RETURNS: The new generated clause. MEMORY: Allocates a CLAUSE_NODE and the needed LITERAL_NODEs, uses the terms from the lists, additionally allocates termnodes for the fol_Not() in Const. and Ante. *************************************************************/ { return clause_CreateAux(Constraint, Antecedent, Succedent, Flags, Precedence, FALSE); } CLAUSE clause_CreateSkolem(LIST Constraint, LIST Antecedent, LIST Succedent, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: Three lists of pointers to atoms, a flag store and a precedence. RETURNS: The new generated clause. MEMORY: Allocates a CLAUSE_NODE and the needed LITERAL_NODEs, uses the terms from the lists, additionally allocates termnodes for the fol_Not() in Const. and Ante. CAUTION: Variables are interpreted to as constants *************************************************************/ { return clause_CreateAux(Constraint, Antecedent, Succedent, Flags, Precedence, TRUE); } CLAUSE clause_CreateCrude(LIST Constraint, LIST Antecedent, LIST Succedent, BOOL Con) /************************************************************** INPUT: Three lists of pointers to literals (!) and a Flag indicating whether the clause comes from the conjecture part of of problem. It is assumed that Constraint and Antecedent literals are negative, whereas Succedent literals are positive. RETURNS: The new generated clause, where a clause_PrecomputeOrderingAndReInit has still to be performed, i.e., variables are not normalized, maximal literal flags not set, equations not oriented, the weight is not set. MEMORY: Allocates a CLAUSE_NODE and the needed LITERAL_NODEs, uses the terms from the lists, additionally allocates termnodes for the fol_Not() in Const. and Ante. ****************************************************************/ { CLAUSE Result; int i,c,a,s; Result = (CLAUSE)memory_Malloc(sizeof(CLAUSE_NODE)); Result->clausenumber = clause_IncreaseCounter(); Result->flags = 0; if (Con) clause_SetFlag(Result, CONCLAUSE); Result->depth = 0; Result->weight = clause_WEIGHTUNDEFINED; Result->splitpotential = 0.0; clause_InitSplitData(Result); Result->parentCls = list_Nil(); Result->parentLits = list_Nil(); Result->c = (c = list_Length(Constraint)); Result->a = (a = list_Length(Antecedent)); Result->s = (s = list_Length(Succedent)); if (!clause_IsEmptyClause(Result)) Result->literals = (LITERAL *)memory_Malloc((c+a+s) * sizeof(LITERAL)); for (i = 0; i < c; i++) { Result->literals[i] = clause_LiteralCreate(list_Car(Constraint),Result); Constraint = list_Cdr(Constraint); } a += c; for ( ; i < a; i++) { Result->literals[i] = clause_LiteralCreate(list_Car(Antecedent), Result); Antecedent = list_Cdr(Antecedent); } s += a; for ( ; i < s; i++) { Result->literals[i] = clause_LiteralCreate(list_Car(Succedent), Result); Succedent = list_Cdr(Succedent); } clause_SetFromInput(Result); return Result; } CLAUSE clause_CreateUnnormalized(LIST Constraint, LIST Antecedent, LIST Succedent) /************************************************************** INPUT: Three lists of pointers to atoms. RETURNS: The new generated clause. MEMORY: Allocates a CLAUSE_NODE and the needed LITERAL_NODEs, uses the terms from the lists, additionally allocates termnodes for the fol_Not() in Const. and Ante. CAUTION: The weight of the clause is not set correctly and equations are not oriented! ****************************************************************/ { CLAUSE Result; int i,c,a,s; Result = (CLAUSE)memory_Malloc(sizeof(CLAUSE_NODE)); Result->clausenumber = clause_IncreaseCounter(); Result->flags = 0; Result->depth = 0; Result->weight = clause_WEIGHTUNDEFINED; Result->splitpotential = 0.0; clause_InitSplitData(Result); Result->parentCls = list_Nil(); Result->parentLits = list_Nil(); Result->c = (c = list_Length(Constraint)); Result->a = (a = list_Length(Antecedent)); Result->s = (s = list_Length(Succedent)); if (!clause_IsEmptyClause(Result)) { Result->literals = (LITERAL *)memory_Malloc((c+a+s) * sizeof(LITERAL)); for (i = 0; i < c; i++) { Result->literals[i] = clause_LiteralCreate(term_Create(fol_Not(), list_List(list_Car(Constraint))), Result); Constraint = list_Cdr(Constraint); } a += c; for ( ; i < a; i++) { Result->literals[i] = clause_LiteralCreate(term_Create(fol_Not(), list_List(list_Car(Antecedent))), Result); Antecedent = list_Cdr(Antecedent); } s += a; for ( ; i < s; i++) { Result->literals[i] = clause_LiteralCreate((TERM)list_Car(Succedent), Result); Succedent = list_Cdr(Succedent); } clause_UpdateMaxVar(Result); } return Result; } CLAUSE clause_CreateFromLiteralLists(LIST Constraint, LIST Antecedent, LIST Succedent, BOOL Conclause, TERM selected) /************************************************************** INPUT: Three lists of literals, a boolean flag indicating whether the clause is a conjecture clause, and a selected term. RETURNS: The new generated clause. EFFECT: The result clause will be normalized and the maximal variable will be set. If the flag is set, the clause will be set as a conjecture clause. If the selected term is not NULL, its corresponding literal will be selected. This function is intended for the parser for creating clauses at a time when the ordering and weight flags aren't determined finally. MEMORY: Allocates a CLAUSE_NODE and the needed LITERAL_NODEs, uses the terms from the lists. ****************************************************************/ { CLAUSE Result; Result = clause_CreateUnnormalized(Constraint, Antecedent, Succedent); if(Conclause) clause_SetFlag(Result, CONCLAUSE); if (selected != (TERM) NULL) { int i; for (i = clause_FirstAntecedentLitIndex(Result); i <= clause_LastAntecedentLitIndex(Result); ++i) { TERM negated; negated = clause_GetLiteralAtom(Result, i); if (negated == selected) { clause_LiteralSetFlag(clause_GetLiteral(Result, i), LITSELECT); clause_SetFlag(Result, CLAUSESELECT); break; } } } clause_Normalize(Result); clause_UpdateMaxVar(Result); clause_SetFromInput(Result); return Result; } CLAUSE clause_CreateFromLiterals(LIST LitList, BOOL Sorts, BOOL Conclause, BOOL Ordering, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A list of literals, three boolean flags indicating whether sort constraint literals should be generated, whether the clause is a conjecture clause, whether the ordering information should be established, a flag store and a precedence. RETURNS: The new generated clause. EFFECT: The result clause will be normalized and the maximal variable will be set. If is FALSE no additional initializations will be done. This mode is intended for the parser for creating clauses at a time when the ordering and weight flags aren't determined finally. Only if is TRUE the equations will be oriented, the maximal literals will be marked and the clause weight will be set correctly. MEMORY: Allocates a CLAUSE_NODE and the needed LITERAL_NODEs, uses the terms from the lists. ****************************************************************/ { CLAUSE Result; LIST Antecedent,Succedent,Constraint; TERM Atom; Antecedent = list_Nil(); Succedent = list_Nil(); Constraint = list_Nil(); while (!list_Empty(LitList)) { if (term_TopSymbol(list_Car(LitList)) == fol_Not()) { Atom = term_FirstArgument(list_Car(LitList)); if (Sorts && symbol_IsBaseSort(term_TopSymbol(Atom)) && term_IsVariable(term_FirstArgument(Atom))) Constraint = list_Cons(list_Car(LitList),Constraint); else Antecedent = list_Cons(list_Car(LitList),Antecedent); } else Succedent = list_Cons(list_Car(LitList),Succedent); LitList = list_Cdr(LitList); } Constraint = list_NReverse(Constraint); Antecedent = list_NReverse(Antecedent); Succedent = list_NReverse(Succedent); Result = clause_CreateCrude(Constraint, Antecedent, Succedent, Conclause); list_Delete(Constraint); list_Delete(Antecedent); list_Delete(Succedent); if (Ordering) clause_PrecomputeOrderingAndReInit(Result, Flags, Precedence); else { clause_Normalize(Result); clause_UpdateMaxVar(Result); } return Result; } void clause_SetSortConstraint(CLAUSE Clause, BOOL Strong, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A clause, a flag indicating whether also negative monadic literals with a real term argument should be put in the sort constraint, a flag store and a precedence. RETURNS: Nothing. EFFECT: Negative monadic literals are put in the sort constraint. ****************************************************************/ { LITERAL ActLit,Help; TERM ActAtom; int i,k,NewConLits; #ifdef CHECK if (!clause_IsUnorderedClause(Clause)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_SetSortConstraint:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } #endif i = clause_LastConstraintLitIndex(Clause); NewConLits = 0; for (k=clause_FirstAntecedentLitIndex(Clause);k<=clause_LastAntecedentLitIndex(Clause);k++) { ActLit = clause_GetLiteral(Clause,k); ActAtom = clause_LiteralAtom(ActLit); if (symbol_IsBaseSort(term_TopSymbol(ActAtom)) && (Strong || term_IsVariable(term_FirstArgument(ActAtom)))) { if (++i != k) { Help = clause_GetLiteral(Clause,i); clause_SetLiteral(Clause,i,ActLit); clause_SetLiteral(Clause,k,Help); } NewConLits++; } } clause_SetNumOfConsLits(Clause, clause_NumOfConsLits(Clause) + NewConLits); clause_SetNumOfAnteLits(Clause, clause_NumOfAnteLits(Clause) - NewConLits); clause_ReInit(Clause, Flags, Precedence); #ifdef CHECK if (!clause_IsUnorderedClause(Clause)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_SetSortConstraint:"); misc_ErrorReport("\n Illegal computations."); misc_FinishErrorReport(); } #endif } void clause_Delete(CLAUSE Clause) /************************************************************** INPUT: A Clause. RETURNS: Nothing. MEMORY: Frees the memory of the clause. ***************************************************************/ { int i, n; #ifdef CHECK if (!clause_IsUnorderedClause(Clause)) { /* Clause may be a byproduct of some hyper rule */ misc_StartErrorReport(); misc_ErrorReport("\n In clause_Delete:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } #endif n = clause_Length(Clause); for (i = 0; i < n; i++) clause_LiteralDelete(clause_GetLiteral(Clause,i)); clause_FreeLitArray(Clause); list_Delete(clause_ParentClauses(Clause)); list_Delete(clause_ParentLiterals(Clause)); #ifdef CHECK if ((Clause->splitfield != NULL) && (Clause->splitfield_length == 0)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_Delete:"); misc_ErrorReport("\n Illegal splitfield_length."); misc_FinishErrorReport(); } if ((Clause->splitfield == NULL) && (Clause->splitfield_length != 0)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_Delete:"); misc_ErrorReport("\n Illegal splitfield."); misc_FinishErrorReport(); } #endif if (Clause->splitfield != NULL) { memory_Free(Clause->splitfield, sizeof(SPLITFIELDENTRY) * Clause->splitfield_length); } clause_Free(Clause); } /**************************************************************/ /* Functions to use the sharing for clauses. */ /**************************************************************/ void clause_InsertIntoSharing(CLAUSE Clause, SHARED_INDEX ShIndex, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A Clause, an index, a flag store and a precedence. RETURNS: Nothing. SUMMARY: Inserts the unsigned atoms of 'Clause' into the sharing index. ***************************************************************/ { int i, litnum; #ifdef CHECK if (!clause_IsClause(Clause, Flags, Precedence)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_Delete:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } clause_Check(Clause, Flags, Precedence); #endif litnum = clause_Length(Clause); for (i = 0; i < litnum; i++) { clause_LiteralInsertIntoSharing(clause_GetLiteral(Clause,i), ShIndex); } } void clause_DeleteFromSharing(CLAUSE Clause, SHARED_INDEX ShIndex, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A Clause, an Index, a flag store and a precedence. RETURNS: Nothing. SUMMARY: Deletes 'Clause' and all its literals from the sharing, frees the memory of 'Clause'. ***************************************************************/ { int i, length; #ifdef CHECK if (!clause_IsClause(Clause, Flags, Precedence)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_DeleteFromSharing:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } #endif length = clause_Length(Clause); for (i = 0; i < length; i++) clause_LiteralDeleteFromSharing(clause_GetLiteral(Clause,i),ShIndex); clause_FreeLitArray(Clause); list_Delete(clause_ParentClauses(Clause)); list_Delete(clause_ParentLiterals(Clause)); #ifdef CHECK if ((Clause->splitfield != NULL) && (Clause->splitfield_length == 0)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_DeleteFromSharing:"); misc_ErrorReport("\n Illegal splitfield_length."); misc_FinishErrorReport(); } if ((Clause->splitfield == NULL) && (Clause->splitfield_length != 0)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_DeleteFromSharing:"); misc_ErrorReport("\n Illegal splitfield."); misc_FinishErrorReport(); } #endif if (Clause->splitfield != NULL) { memory_Free(Clause->splitfield, sizeof(SPLITFIELDENTRY) * Clause->splitfield_length); } clause_Free(Clause); } void clause_MakeUnshared(CLAUSE Clause, SHARED_INDEX ShIndex) /************************************************************** INPUT: A Clause and an Index. RETURNS: Nothing. SUMMARY: Deletes the clauses literals from the sharing and replaces them by unshared copies. ***************************************************************/ { LITERAL ActLit; TERM SharedAtom, AtomCopy; int i,LastAnte,length; #ifdef CHECK if (!clause_IsUnorderedClause(Clause)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_MakeUnshared:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } #endif LastAnte = clause_LastAntecedentLitIndex(Clause); length = clause_Length(Clause); for (i = clause_FirstLitIndex(); i <= LastAnte; i++) { ActLit = clause_GetLiteral(Clause, i); SharedAtom = clause_LiteralAtom(ActLit); AtomCopy = term_Copy(SharedAtom); sharing_Delete(ActLit, SharedAtom, ShIndex); clause_LiteralSetNegAtom(ActLit, AtomCopy); } for ( ; i < length; i++) { ActLit = clause_GetLiteral(Clause, i); SharedAtom = clause_LiteralSignedAtom(ActLit); AtomCopy = term_Copy(SharedAtom); sharing_Delete(ActLit, SharedAtom, ShIndex); clause_LiteralSetPosAtom(ActLit, AtomCopy); } } void clause_MoveSharedClause(CLAUSE Clause, SHARED_INDEX Source, SHARED_INDEX Destination, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A Clause, two indexes, a flag store, and a precedence. RETURNS: Nothing. EFFECT: Deletes from and inserts it into . ***************************************************************/ { LITERAL Lit; TERM Atom,Copy; int i,length; #ifdef CHECK if (!clause_IsClause(Clause, Flags, Precedence)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_MoveSharedClause:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } #endif length = clause_Length(Clause); for (i = clause_FirstLitIndex(); i < length; i++) { Lit = clause_GetLiteral(Clause, i); Atom = clause_LiteralAtom(Lit); Copy = term_Copy(Atom); /* sharing_Insert works destructively on 's superterms */ clause_LiteralSetAtom(Lit, sharing_Insert(Lit, Copy, Destination)); sharing_Delete(Lit, Atom, Source); term_Delete(Copy); } } void clause_DeleteSharedLiteral(CLAUSE Clause, int Indice, SHARED_INDEX ShIndex, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A Clause, a literals indice, an Index, a flag store and a precedence. RETURNS: Nothing. SUMMARY: Deletes the shared literal from the clause. MEMORY: Various. ***************************************************************/ { #ifdef CHECK if (!clause_IsClause(Clause, Flags, Precedence)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_DeleteSharedLiteral:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } #endif clause_MakeUnshared(Clause, ShIndex); clause_DeleteLiteral(Clause, Indice, Flags, Precedence); clause_InsertIntoSharing(Clause, ShIndex, Flags, Precedence); } void clause_DeleteClauseList(LIST ClauseList) /************************************************************** INPUT: A list of unshared clauses. RETURNS: Nothing. SUMMARY: Deletes all clauses in the list and the list. MEMORY: Frees the lists and the clauses' memory. ***************************************************************/ { LIST Scan; for (Scan = ClauseList; !list_Empty(Scan); Scan = list_Cdr(Scan)) if (clause_Exists(list_Car(Scan))) clause_Delete(list_Car(Scan)); list_Delete(ClauseList); } void clause_DeleteSharedClauseList(LIST ClauseList, SHARED_INDEX ShIndex, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A list of clauses, an index, a flag store and a precedence. RETURNS: Nothing. SUMMARY: Deletes all clauses in the list from the sharing. MEMORY: Frees the lists and the clauses' memory. ***************************************************************/ { LIST Scan; for (Scan = ClauseList; !list_Empty(Scan); Scan = list_Cdr(Scan)) clause_DeleteFromSharing(list_Car(Scan), ShIndex, Flags, Precedence); list_Delete(ClauseList); } void clause_DeleteAllIndexedClauses(SHARED_INDEX ShIndex, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: An Index, a flag store and a precedence. RETURNS: Nothing. SUMMARY: Deletes all clauses' terms from the sharing, frees their memory. MEMORY: Frees the memory of all clauses with terms in the index. ***************************************************************/ { LIST TermList,DelList,Scan; TERM NewVar; SYMBOL NewVarSymbol; NewVar = term_CreateStandardVariable(); NewVarSymbol = term_TopSymbol(NewVar); TermList = st_GetInstance(cont_LeftContext(), sharing_Index(ShIndex), NewVar); /* This should yield a list of all terms in the index and thus the sharing. */ while (!list_Empty(TermList)) { DelList = sharing_GetDataList(list_Car(TermList), ShIndex); for (Scan = DelList; !list_Empty(Scan); Scan = list_Cdr(Scan)) list_Rplaca(Scan, clause_LiteralOwningClause(list_Car(Scan))); DelList = list_PointerDeleteDuplicates(DelList); for (Scan = DelList; !list_Empty(Scan); Scan = list_Cdr(Scan)) clause_DeleteFromSharing(list_Car(Scan), ShIndex, Flags, Precedence); list_Delete(TermList); TermList = st_GetInstance(cont_LeftContext(), sharing_Index(ShIndex), NewVar); list_Delete(DelList); } term_Delete(NewVar); symbol_Delete(NewVarSymbol); } void clause_PrintAllIndexedClauses(SHARED_INDEX ShIndex) /************************************************************** INPUT: An Index. RETURNS: Nothing. SUMMARY: Prints all indexed clauses to stdout. ***************************************************************/ { LIST TermList,ClList,PrintList,Scan; TERM NewVar; SYMBOL NewVarSymbol; NewVar = term_CreateStandardVariable(); NewVarSymbol = term_TopSymbol(NewVar); TermList = st_GetInstance(cont_LeftContext(), sharing_Index(ShIndex), NewVar); /* This should yield a list of all terms in the index and thus the sharing. */ PrintList = list_Nil(); while (!list_Empty(TermList)) { ClList = sharing_GetDataList(list_Car(TermList), ShIndex); for (Scan = ClList; !list_Empty(Scan); Scan = list_Cdr(Scan)) list_Rplaca(Scan, clause_LiteralOwningClause(list_Car(Scan))); PrintList = list_NPointerUnion(ClList, PrintList); Scan = TermList; TermList = list_Cdr(TermList); list_Free(Scan); } clause_ListPrint(PrintList); list_Delete(PrintList); term_Delete(NewVar); symbol_Delete(NewVarSymbol); } LIST clause_AllIndexedClauses(SHARED_INDEX ShIndex) /************************************************************** INPUT: An index RETURNS: A list of all the clauses in the index MEMORY: Memory is allocated for the list nodes ***************************************************************/ { LIST clauselist, scan; clauselist = sharing_GetAllSuperTerms(ShIndex); for (scan = clauselist; scan != list_Nil(); scan = list_Cdr(scan)) list_Rplaca(scan, clause_LiteralOwningClause(list_Car(scan))); clauselist = list_PointerDeleteDuplicates(clauselist); return clauselist; } /**************************************************************/ /* Clause Access Functions */ /**************************************************************/ void clause_DeleteLiteralNN(CLAUSE Clause, int Indice) /************************************************************** INPUT: An unshared clause, and a literal index. RETURNS: Nothing. EFFECT: The literal is position is deleted from . The clause isn't reinitialized afterwards. MEMORY: The memory of the literal with the 'Indice' and memory of its atom is freed. ***************************************************************/ { int i, lc, la, length, shift; LITERAL *Literals; #ifdef CHECK if (!clause_IsUnorderedClause(Clause) || (clause_Length(Clause) <= Indice) || Indice < 0) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_DeleteLiteral:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } #endif lc = clause_LastConstraintLitIndex(Clause); la = clause_LastAntecedentLitIndex(Clause); length = clause_Length(Clause); /* Create a new literal array */ if (length > 1) Literals = (LITERAL*) memory_Malloc(sizeof(LITERAL) * (length-1)); else Literals = (LITERAL*) NULL; /* Copy literals to the new array */ shift = 0; length--; /* The loop iterates over the new array */ for (i = 0; i < length; i++) { if (i == Indice) shift = 1; Literals[i] = Clause->literals[i+shift]; } /* Free literal and old array and set new one */ clause_LiteralDelete(clause_GetLiteral(Clause, Indice)); clause_FreeLitArray(Clause); Clause->literals = Literals; /* Update clause */ if (Indice <= lc) clause_SetNumOfConsLits(Clause, clause_NumOfConsLits(Clause) - 1); else if (Indice <= la) clause_SetNumOfAnteLits(Clause, clause_NumOfAnteLits(Clause) - 1); else clause_SetNumOfSuccLits(Clause, clause_NumOfSuccLits(Clause) - 1); /* Mark the weight as undefined */ Clause->weight = clause_WEIGHTUNDEFINED; } void clause_DeleteLiteral(CLAUSE Clause, int Indice, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: An unshared clause, a literals index, a flag store, and a precedence. RETURNS: Nothing. EFFECT: The literal at position is deleted from . In contrast to the function clause_DeleteLiteralNN the clause is reinitialized afterwards. MEMORY: The memory of the literal with the 'Indice' and memory of its atom is freed. ***************************************************************/ { clause_DeleteLiteralNN(Clause, Indice); clause_ReInit(Clause, Flags, Precedence); } void clause_DeleteLiterals(CLAUSE Clause, LIST Indices, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: An unshared clause, a list of literal indices a flag store and a precedence. RETURNS: Nothing. EFFECT: The literals given by are deleted. The clause is reinitialized afterwards. MEMORY: The memory of the literals with the 'Indice' and memory of its atom is freed. ***************************************************************/ { LITERAL *NewLits; intptr_t i; int j, nc, na, ns, lc, la, olength, nlength; #ifdef CHECK LIST Scan; if (!list_IsSetOfPointers(Indices)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_DeleteLiterals:"); misc_ErrorReport(" list contains duplicate indices."); misc_FinishErrorReport(); } /* check the literal indices */ for (Scan = Indices; !list_Empty(Scan); Scan = list_Cdr(Scan)) { i = (intptr_t) list_Car(Scan); if (i < 0 || i > clause_LastLitIndex(Clause)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_DeleteLiterals:"); misc_ErrorReport(" literal index %d is out ", i); misc_ErrorReport(" of bounds"); misc_FinishErrorReport(); } } #endif nc = 0; na = 0; ns = 0; lc = clause_LastConstraintLitIndex(Clause); la = clause_LastAntecedentLitIndex(Clause); olength = clause_Length(Clause); nlength = olength - list_Length(Indices); if (nlength != 0) NewLits = (LITERAL*) memory_Malloc(sizeof(LITERAL) * nlength); else NewLits = (LITERAL*) NULL; for (i=clause_FirstLitIndex(), j=clause_FirstLitIndex(); i < olength; i++) if (list_PointerMember(Indices, (POINTER) i)) clause_LiteralDelete(clause_GetLiteral(Clause,i)); else { NewLits[j++] = clause_GetLiteral(Clause,i); if (i <= lc) nc++; else if (i <= la) na++; else ns++; } clause_FreeLitArray(Clause); Clause->literals = NewLits; clause_SetNumOfConsLits(Clause, nc); clause_SetNumOfAnteLits(Clause, na); clause_SetNumOfSuccLits(Clause, ns); clause_ReInit(Clause, Flags, Precedence); } /**************************************************************/ /* Clause Comparisons */ /**************************************************************/ BOOL clause_IsHornClause(CLAUSE Clause) /************************************************************** INPUT: A clause. RETURNS: The boolean value TRUE if 'Clause' is a hornclause FALSE else. ***************************************************************/ { #ifdef CHECK if (!clause_IsUnorderedClause(Clause)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_IsHornClause:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } #endif return (clause_NumOfSuccLits(Clause) <= 1); } BOOL clause_HasTermSortConstraintLits(CLAUSE Clause) /************************************************************** INPUT: A clause, RETURNS: TRUE iff there is at least one sort constraint atom having a term as its argument ***************************************************************/ { int i,n; #ifdef CHECK if (!clause_IsUnorderedClause(Clause)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_HasTermSortConstraintLits:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } #endif n = clause_LastConstraintLitIndex(Clause); for (i = clause_FirstConstraintLitIndex(Clause); i <= n; i++) if (!term_AllArgsAreVar(clause_GetLiteralAtom(Clause,i))) return TRUE; return FALSE; } BOOL clause_HasOnlySpecDomArgs(CLAUSE Clause) /************************************************************** INPUT: A clause. RETURNS: TRUE iff all non sort constraint literals are of the form x=a, x=y, a=b. ***************************************************************/ { int i,n; #ifdef CHECK if (!clause_IsUnorderedClause(Clause)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_HasOnlySpecDomArgs:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } #endif n = clause_Length(Clause); for (i = clause_FirstAntecedentLitIndex(Clause); i < n; i++) if (!fol_IsEquality(clause_GetLiteralAtom(Clause,i)) || !(term_IsVariable(term_FirstArgument(clause_GetLiteralAtom(Clause,i))) || term_IsConstant(term_FirstArgument(clause_GetLiteralAtom(Clause,i)))) || !(term_IsVariable(term_SecondArgument(clause_GetLiteralAtom(Clause,i))) || term_IsConstant(term_SecondArgument(clause_GetLiteralAtom(Clause,i))))) return FALSE; return TRUE; } BOOL clause_HasSolvedConstraint(CLAUSE Clause) /************************************************************** INPUT: A clause. RETURNS: The boolean value TRUE if 'Clause' has a solved constraint, i.e. only variables as sort arguments, or only equality literals with variable and constant arguments, e.g., x=a, x=y FALSE else. ***************************************************************/ { int i,c; LIST CVars, LitVars; #ifdef CHECK if (!clause_IsUnorderedClause(Clause)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_HasSolvedConstraint:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } #endif CVars = list_Nil(); c = clause_NumOfConsLits(Clause); if (c == 0) return TRUE; if (clause_HasTermSortConstraintLits(Clause) || clause_HasOnlySpecDomArgs(Clause)) return FALSE; for (i = 0; i < c; i++) CVars = list_NPointerUnion(term_VariableSymbols(clause_GetLiteralAtom(Clause, i)), CVars); if (i == c) { c = clause_Length(Clause); LitVars = list_Nil(); for ( ; i < c; i++) LitVars = list_NPointerUnion(LitVars, term_VariableSymbols(clause_GetLiteralAtom(Clause, i))); if (list_Empty(CVars = list_NPointerDifference(CVars, LitVars))) { list_Delete(LitVars); return TRUE; } list_Delete(LitVars); } list_Delete(CVars); return FALSE; } BOOL clause_HasSelectedLiteral(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A Clause, a flag store and a precedence. RETURNS: The boolean value TRUE iff has a selected literal ***************************************************************/ { int i,negs; #ifdef CHECK if (!clause_IsClause(Clause, Flags, Precedence)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_HasSelectedLiteral:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } #endif negs = clause_LastAntecedentLitIndex(Clause); for (i=clause_FirstAntecedentLitIndex(Clause); i <= negs; i++) if (clause_LiteralGetFlag(clause_GetLiteral(Clause,i), LITSELECT)) return TRUE; return FALSE; } BOOL clause_IsDeclarationClause(CLAUSE Clause) /************************************************************** INPUT: A clause. RETURNS: The boolean value TRUE, if 'Clause' has only variables as arguments in constraint literals. ***************************************************************/ { int i,length; LITERAL Lit; #ifdef CHECK if (!clause_IsUnorderedClause(Clause)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_IsDeclarationClause:"); misc_ErrorReport("\n Illegal input."); misc_FinishErrorReport(); } #endif if (!clause_HasSolvedConstraint(Clause)) return FALSE; length = clause_Length(Clause); for (i=clause_FirstSuccedentLitIndex(Clause);i 0 || clause_NumOfSuccLits(Clause) > 1 || !clause_HasSolvedConstraint(Clause)) return FALSE; Lit = clause_GetLiteral(Clause,clause_FirstSuccedentLitIndex(Clause)); if (symbol_IsBaseSort(term_TopSymbol(clause_LiteralSignedAtom(Lit)))) return TRUE; return FALSE; } BOOL clause_IsPotentialSortTheoryClause(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A Clause, a flag store and a precedence. RETURNS: The boolean value TRUE, if 'Clause' has monadic literals only variables as arguments in antecedent/constraint literals, no other antecedent literals and exactly one monadic succedent literal. ***************************************************************/ { LITERAL Lit; int i; #ifdef CHECK if (!clause_IsClause(Clause, Flags, Precedence)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_IsPotentialSortTheoryClause:"); misc_ErrorReport("\n Illegal input. Input not a clause."); misc_FinishErrorReport(); } #endif if (clause_NumOfSuccLits(Clause) != 1) return FALSE; for (i=clause_FirstLitIndex();i) is a subset of vars() * else FALSE * EFFECT: modifies ord_VARCOUNT **********************************************************/ { SYMBOL MaxVarClause, MaxVarTerm; LITERAL Lit; TERM Atom; int i, n; MaxVarClause = clause_MaxVar(Clause); MaxVarTerm = term_MaxVar(Term); if(MaxVarClause > MaxVarTerm) return FALSE; n = clause_Length(Clause); for (i = 0; i <= MaxVarTerm; i++) { ord_VARCOUNT[i][0] = 0; ord_VARCOUNT[i][1] = 0; } for(i = clause_FirstLitIndex(); i < n; i++) { Lit = clause_GetLiteral(Clause, i); Atom = clause_LiteralAtom(Lit); ord_CompareCountVars(Atom, 0); } ord_CompareCountVars(Term, 1); for (i = 0; i <= MaxVarTerm; i++) { if(ord_VARCOUNT[i][1] == 0 && ord_VARCOUNT[i][0] != 0) return FALSE; } return TRUE; } BOOL clause_LiteralIsStrictMaximalLiteralSkolem(CLAUSE Clause, int i, FLAGSTORE Flags, PRECEDENCE Precedence) /********************************************************** * INPUT: A clause and a literal * OUTPUT: TRUE, if Literal of is strictly maximal in . * Consider variables to be (skolem) constants. * EFFECT: modifies ord_VARCOUNT * NOTE: We only need to compare STRICTLY MAXIMAL Literals * of with **********************************************************/ { int ri, last; last = clause_LastLitIndex(Clause); for (ri = clause_FirstLitIndex(); ri <= last; ri++) { if(ri != i && clause_LiteralGetFlag(clause_GetLiteral(Clause, ri),STRICTMAXIMAL) && ord_LiteralCompareAux(clause_GetLiteralTerm(Clause, i), clause_LiteralGetOrderStatus(clause_GetLiteral(Clause,i)), clause_GetLiteralTerm(Clause, ri), clause_LiteralGetOrderStatus(clause_GetLiteral(Clause,ri)), TRUE, TRUE, Flags, Precedence) != ord_GREATER_THAN ) return FALSE; } return TRUE; } BOOL clause_IsTransitivityAxiomExt(CLAUSE Clause, SYMBOL* symb, BOOL* twisted) /********************************************************** * INPUT: A clause, boolean flag, pointer to symbol and a pointer to a flag. * OUTPUT: TRUE, if the clause has the form of a transitivity axiom * (a) x S y, y S z -> x S z * or * (b) y S z , x S y -> x S z * FALSE otherwise * * If the function returns TRUE: * The *symb will be assing the symbol S. * The *twisted will indicate that case (b) and not (a) occured **********************************************************/ { TERM t1, t2, t3; SYMBOL s1, s2, s3; SYMBOL s1a,s1b,s2a,s2b,s3a,s3b; int i; /* check the clause size and "shape" */ if (clause_NumOfConsLits(Clause) != 0 || clause_NumOfAnteLits(Clause) != 2 || clause_NumOfSuccLits(Clause) != 1 ) return FALSE; /* check the literals' top symbols and collect the terms */ i = clause_FirstAntecedentLitIndex(Clause); t1 = clause_LiteralAtom(clause_GetLiteral(Clause,i)); s1 = term_TopSymbol(t1); if (symbol_Arity(s1) != 2) return FALSE; i++; t2 = clause_LiteralAtom(clause_GetLiteral(Clause,i)); s2 = term_TopSymbol(t2); if (!symbol_Equal(s1,s2)) return FALSE; i = clause_FirstSuccedentLitIndex(Clause); t3 = clause_LiteralAtom(clause_GetLiteral(Clause,i)); s3 = term_TopSymbol(t3); if (!symbol_Equal(s1,s3)) return FALSE; /* check that the arguments are variables and collect them */ s1a = term_TopSymbol(term_FirstArgument(t1)); if (!symbol_IsVariable(s1a)) return FALSE; s1b = term_TopSymbol(term_SecondArgument(t1)); if (!symbol_IsVariable(s1b)) return FALSE; s2a = term_TopSymbol(term_FirstArgument(t2)); if (!symbol_IsVariable(s2a)) return FALSE; s2b = term_TopSymbol(term_SecondArgument(t2)); if (!symbol_IsVariable(s2b)) return FALSE; s3a = term_TopSymbol(term_FirstArgument(t3)); if (!symbol_IsVariable(s3a)) return FALSE; s3b = term_TopSymbol(term_SecondArgument(t3)); if (!symbol_IsVariable(s3b)) return FALSE; /* check the variable correspondence - the two negative literals may be in any order!*/ if (symbol_Equal(s1a,s3a) && symbol_Equal(s1b,s2a) && symbol_Equal(s2b,s3b)) { *twisted = FALSE; *symb = s1; return TRUE; } if (symbol_Equal(s2a,s3a) && symbol_Equal(s2b,s1a) && symbol_Equal(s1b,s3b)) { *twisted = TRUE; *symb = s1; return TRUE; } return FALSE; } BOOL clause_IsIrreflexivityAxiomExt(CLAUSE Clause, SYMBOL* Symbol) /********************************************************** * INPUT: A clause, pointers to symbol. * OUTPUT: True if Clause represents a irreflexivity axiom * for symbol Symbol **********************************************************/ { TERM atom; SYMBOL top,v1,v2; /* one negative literal*/ if (clause_NumOfConsLits(Clause) != 0 || clause_NumOfAnteLits(Clause) != 1 || clause_NumOfSuccLits(Clause) != 0 ) return FALSE; atom = clause_LiteralAtom(clause_GetLiteral(Clause,clause_FirstAntecedentLitIndex(Clause))); top = term_TopSymbol(atom); /* binary predicate at the top*/ if (symbol_Arity(top) != 2) return FALSE; /* both arguments are variables */ v1 = term_TopSymbol(term_FirstArgument(atom)); if (!symbol_IsVariable(v1)) return FALSE; v2 = term_TopSymbol(term_SecondArgument(atom)); if (!symbol_IsVariable(v2)) return FALSE; /* actually they should be the same */ if (!symbol_Equal(v1,v2)) return FALSE; *Symbol = top; return TRUE; } BOOL clause_IsTotalityAxiomExt(CLAUSE Clause, SYMBOL* Symbol) /********************************************************** * INPUT: A clause, pointers to symbol. * OUTPUT: True if Clause represents a totality axiom * for symbol Symbol **********************************************************/ { TERM atom1, atom2, atom3, tatom; SYMBOL top1,top2,top3, ttop; SYMBOL v1,v2,t1,t2; int i; /* one positive literals*/ if (clause_NumOfConsLits(Clause) != 0 || clause_NumOfAnteLits(Clause) != 0 || clause_NumOfSuccLits(Clause) != 3 ) return FALSE; /* each has ... */ i = clause_FirstSuccedentLitIndex(Clause); atom1 = clause_LiteralAtom(clause_GetLiteral(Clause,i)); top1 = term_TopSymbol(atom1); /* .. binary top .. */ if (symbol_Arity(top1) != 2) return FALSE; /* .. variable areguments .. */ v1 = term_TopSymbol(term_FirstArgument(atom1)); if (!symbol_IsVariable(v1)) return FALSE; v2 = term_TopSymbol(term_SecondArgument(atom1)); if (!symbol_IsVariable(v2)) return FALSE; /* .. the two variables are different .. */ if (symbol_Equal(v1,v2)) return FALSE; i++; atom2 = clause_LiteralAtom(clause_GetLiteral(Clause,i)); top2 = term_TopSymbol(atom2); /* .. binary top .. */ if (symbol_Arity(top2) != 2) return FALSE; /* .. also variables and the same as last time .. */ t1 = term_TopSymbol(term_FirstArgument(atom2)); if (!symbol_Equal(t1,v1) && !symbol_Equal(t1,v2)) return FALSE; t2 = term_TopSymbol(term_SecondArgument(atom2)); if (!symbol_Equal(t2,v1) && !symbol_Equal(t2,v2)) return FALSE; /* .. the two variables are different .. */ if (symbol_Equal(t1,t2)) return FALSE; i++; atom3 = clause_LiteralAtom(clause_GetLiteral(Clause,i)); top3 = term_TopSymbol(atom3); /* .. binary top .. */ if (symbol_Arity(top3) != 2) return FALSE; /* .. also variables and the same as last time .. */ t1 = term_TopSymbol(term_FirstArgument(atom3)); if (!symbol_Equal(t1,v1) && !symbol_Equal(t1,v2)) return FALSE; t2 = term_TopSymbol(term_SecondArgument(atom3)); if (!symbol_Equal(t2,v1) && !symbol_Equal(t2,v2)) return FALSE; /* .. the two variables are different .. */ if (symbol_Equal(t1,t2)) return FALSE; /* one of them is equality predicate - let's shift that one to front */ if (symbol_Equal(top1,fol_Equality())) { /* no op*/ } else if (symbol_Equal(top2,fol_Equality())) { ttop = top1; top1 = top2; top2 = ttop; tatom = atom1; atom1 = atom2; atom2 = tatom; } else if (symbol_Equal(top3,fol_Equality())) { ttop = top1; top1 = top3; top3 = ttop; tatom = atom1; atom1 = atom3; atom3 = tatom; } else { return FALSE; /* no equality predicate */ } /* the other two share the same non-equality top */ if (!symbol_Equal(top2, top3) || symbol_Equal(top2,fol_Equality())) return FALSE; /*the other two are not the same*/ if (symbol_Equal(term_TopSymbol(term_FirstArgument(atom2)), term_TopSymbol(term_FirstArgument(atom3)))) return FALSE; *Symbol = top2; return TRUE; } /**************************************************************/ /* Clause Input and Output Functions */ /**************************************************************/ void clause_Print(CLAUSE Clause) /************************************************************** INPUT: A Clause. RETURNS: Nothing. SUMMARY: The clause is printed to stdout. ***************************************************************/ { RULE Origin; LITERAL Lit; int i,c,a,s; ord_RESULT ord; #ifdef CHECK if (!clause_IsUnorderedClause(Clause)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_Print:"); misc_ErrorReport("\n Illegal input. Input not a clause."); misc_FinishErrorReport(); } #endif if (!clause_Exists(Clause)) fputs("(CLAUSE)NULL", stdout); else { printf("%zd",clause_Number(Clause)); Origin = clause_Origin(Clause); printf("[%zd:", clause_SplitLevel(Clause)); #ifdef CHECK if (Clause->splitfield_length <= 1) fputs("0.", stdout); else for (i=Clause->splitfield_length-1; i > 0; i--) printf("%lu.", Clause->splitfield[i]); if (Clause->splitfield_length == 0) putchar('1'); else printf("%lu", (Clause->splitfield[0] | 1)); printf(":%c%c:%c:%zu:%zu:%.1f:", clause_GetFlag(Clause, CONCLAUSE) ? 'C' : 'A', clause_GetFlag(Clause, WORKEDOFF) ? 'W' : 'U', clause_GetFlag(Clause, NOPARAINTO) ? 'N' : 'P', clause_Weight(Clause), clause_Depth(Clause), clause_SplitPotential(Clause)); #endif clause_PrintOrigin(Clause); if (Origin == INPUTCLAUSE) { ; } else { putchar(':'); clause_PrintParentClauses(Clause); } putchar(']'); c = clause_NumOfConsLits(Clause); a = clause_NumOfAnteLits(Clause); s = clause_NumOfSuccLits(Clause); for (i = 0; i < c; i++) { putchar(' '); Lit = clause_GetLiteral(Clause, i); clause_LiteralPrintUnsigned(Lit); } fputs(" || ", stdout); a += c; for ( ; i < a; i++) { Lit = clause_GetLiteral(Clause, i); clause_LiteralPrintUnsigned(Lit); if (clause_LiteralIsMaximal(Lit)) { putchar('*'); if (clause_LiteralIsOrientedEquality(Lit)) putchar('*'); if (symbol_HasProperty(term_TopSymbol(clause_LiteralAtom(Lit)), TRANSITIVE) && ((ord = clause_LiteralGetOrderStatus(Lit)) != ord_UNCOMPARABLE)) { switch (ord) { case ord_SMALLER_THAN: putchar('r'); break; case ord_GREATER_THAN: putchar('l'); break; default: /*putchar('e');*/ break; } } } if (clause_LiteralGetFlag(Lit,LITSELECT)) putchar('+'); if (i+1 < a) putchar(' '); } fputs(" -> ",stdout); s += a; for ( ; i < s; i++) { Lit = clause_GetLiteral(Clause, i); clause_LiteralPrintUnsigned(Lit); if (clause_LiteralIsMaximal(Lit)) { putchar('*'); if (clause_LiteralIsOrientedEquality(Lit)) putchar('*'); if (symbol_HasProperty(term_TopSymbol(clause_LiteralAtom(Lit)), TRANSITIVE) && ((ord = clause_LiteralGetOrderStatus(Lit)) != ord_UNCOMPARABLE)) { switch (ord) { case ord_SMALLER_THAN: putchar('r'); break; case ord_GREATER_THAN: putchar('l'); break; default: /*putchar('e');*/ break; } } } #ifdef CHECK if (clause_LiteralGetFlag(Lit,LITSELECT)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_Print: Clause has selected positive literal.\n"); misc_FinishErrorReport(); } #endif if (i+1 < s) putchar(' '); } putchar('.'); } } void clause_PrintSpecial(CLAUSE Clause) /************************************************************** INPUT: A Clause, where parents are the pointers to clauses as used in the tableau module RETURNS: Nothing. SUMMARY: The clause is printed to stdout. For DEBUGGING! ***************************************************************/ { RULE Origin; LITERAL Lit; int i,j,c,a,s; ord_RESULT ord; #ifdef CHECK if (!clause_IsUnorderedClause(Clause)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_PrintSpecial:"); misc_ErrorReport("\n Illegal input. Input not a clause."); misc_FinishErrorReport(); } #endif if (!clause_Exists(Clause)) fputs("(CLAUSE)NULL", stdout); else { printf("%zd",clause_Number(Clause)); Origin = clause_Origin(Clause); printf("[%zd:", clause_SplitLevel(Clause)); fputs("0", stdout); for (i = Clause->splitfield_length-1; i >= 0; i--) if (Clause->splitfield[i] != 0) { for (j = 0; j<=sizeof(SPLITFIELDENTRY)*CHAR_BIT-1; j++) if (Clause->splitfield[i] & ((SPLITFIELDENTRY)1 << j)) printf(",%zd", i*sizeof(SPLITFIELDENTRY)*CHAR_BIT+j); } printf(":%c%c:%c:%zd:%zd:%.1f:", clause_GetFlag(Clause, CONCLAUSE) ? 'C' : 'A', clause_GetFlag(Clause, WORKEDOFF) ? 'W' : 'U', clause_GetFlag(Clause, NOPARAINTO) ? 'N' : 'P', clause_Weight(Clause), clause_Depth(Clause), clause_SplitPotential(Clause)); clause_PrintOrigin(Clause); if (Origin == INPUTCLAUSE) { ; } else { putchar(':'); clause_PrintParentClausesSpecial(Clause); } putchar(']'); c = clause_NumOfConsLits(Clause); a = clause_NumOfAnteLits(Clause); s = clause_NumOfSuccLits(Clause); for (i = 0; i < c; i++) { putchar(' '); Lit = clause_GetLiteral(Clause, i); clause_LiteralPrintUnsigned(Lit); } fputs(" || ", stdout); a += c; for ( ; i < a; i++) { Lit = clause_GetLiteral(Clause, i); clause_LiteralPrintUnsigned(Lit); if (clause_LiteralIsMaximal(Lit)) { putchar('*'); if (clause_LiteralIsOrientedEquality(Lit)) putchar('*'); if (symbol_HasProperty(term_TopSymbol(clause_LiteralAtom(Lit)), TRANSITIVE) && ((ord = clause_LiteralGetOrderStatus(Lit)) != ord_UNCOMPARABLE)) { switch (ord) { case ord_SMALLER_THAN: putchar('r'); break; case ord_GREATER_THAN: putchar('l'); break; default: /*putchar('e');*/ break; } } } if (clause_LiteralGetFlag(Lit,LITSELECT)) putchar('+'); if (i+1 < a) putchar(' '); } fputs(" -> ",stdout); s += a; for ( ; i < s; i++) { Lit = clause_GetLiteral(Clause, i); clause_LiteralPrintUnsigned(Lit); if (clause_LiteralIsMaximal(Lit)) { putchar('*'); if (clause_LiteralIsOrientedEquality(Lit)) putchar('*'); if (symbol_HasProperty(term_TopSymbol(clause_LiteralAtom(Lit)), TRANSITIVE) && ((ord = clause_LiteralGetOrderStatus(Lit)) != ord_UNCOMPARABLE)) { switch (ord) { case ord_SMALLER_THAN: putchar('r'); break; case ord_GREATER_THAN: putchar('l'); break; default: /*putchar('e');*/ break; } } } #ifdef CHECK if (clause_LiteralGetFlag(Lit,LITSELECT)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_Print: Clause has selected positive literal.\n"); misc_FinishErrorReport(); } #endif if (i+1 < s) putchar(' '); } putchar('.'); } } void clause_PrintSplitfield(CLAUSE Clause, NAT MaxLevel) { int i,j; uintptr_t field; short first = 1; for(i=1; i<=MaxLevel; i++) { j = clause_ComputeSplitFieldAddress(i, &field); if((Clause->splitfield[field] & ((SPLITFIELDENTRY)1 << j)) != 0) { if(first==1) { printf("%d", i); first=0; } else { printf(".%d", i); } } } } void clause_PrintSplitfieldOnly(SPLITFIELD SF, int SF_length) { int i,j; NAT k; short first = 1; for(i=0; i ", stdout); s += a; for ( ; i < s; i++) { if (clause_LiteralIsMaximal(clause_GetLiteral(Clause, i))) clause_LiteralPrint(clause_GetLiteral(Clause, i)); if (clause_LiteralGetFlag(clause_GetLiteral(Clause, i),STRICTMAXIMAL)) { clause_LiteralPrint(clause_GetLiteral(Clause, i)); fputs("(strictly)", stdout); } } puts("."); /* with newline */ } void clause_FPrint(FILE* File, CLAUSE Clause) /************************************************************** INPUT: A file and a clause. RETURNS: Nothing. SUMMARY: Prints any clause to the file 'File'. CAUTION: Uses the term_Output functions. ***************************************************************/ { int i, c, a, s; c = clause_NumOfConsLits(Clause); a = clause_NumOfAnteLits(Clause); s = clause_NumOfSuccLits(Clause); for (i = 0; i < c; i++) term_FPrint(File, clause_GetLiteralAtom(Clause, i)); fputs(" || ", stdout); a += c; for ( ; i < a; i++) term_FPrint(File, clause_GetLiteralAtom(Clause, i)); fputs(" -> ", stdout); s += a; for ( ; i < s; i++) term_FPrint(File, clause_GetLiteralAtom(Clause, i)); putc('.', File); } void clause_ListPrint(LIST ClauseList) /************************************************************** INPUT: A list of clauses. RETURNS: Nothing. SUMMARY: Prints the clauses to stdout. CAUTION: Uses the clause_Print function. ***************************************************************/ { while (!(list_Empty(ClauseList))) { clause_Print(list_First(ClauseList)); ClauseList = list_Cdr(ClauseList); if (!list_Empty(ClauseList)) putchar('\n'); } } void clause_PrintParentClauses(CLAUSE Clause) /************************************************************** INPUT: A Clause. RETURNS: Nothing. SUMMARY: Prints the clauses parentclauses and -literals to stdout. ***************************************************************/ { LIST Scan1,Scan2; if (!list_Empty(clause_ParentClauses(Clause))) { Scan1 = clause_ParentClauses(Clause); Scan2 = clause_ParentLiterals(Clause); printf("%zd.%zd", (intptr_t)list_Car(Scan1), (intptr_t)list_Car(Scan2)); for (Scan1 = list_Cdr(Scan1), Scan2 = list_Cdr(Scan2); !list_Empty(Scan1); Scan1 = list_Cdr(Scan1), Scan2 = list_Cdr(Scan2)) printf(",%zd.%zd", (intptr_t)list_Car(Scan1), (intptr_t)list_Car(Scan2)); } } void clause_PrintParentClausesSpecial(CLAUSE Clause) /************************************************************** INPUT: A Clause where parents are clause pointers. RETURNS: Nothing. SUMMARY: Prints the clauses parentclauses and -literals to stdout. ***************************************************************/ { LIST Scan1,Scan2; if (!list_Empty(clause_ParentClauses(Clause))) { Scan1 = clause_ParentClauses(Clause); Scan2 = clause_ParentLiterals(Clause); printf("%zd.%.zd", clause_Number((CLAUSE)list_Car(Scan1)), (intptr_t)list_Car(Scan2)); for (Scan1 = list_Cdr(Scan1), Scan2 = list_Cdr(Scan2); !list_Empty(Scan1); Scan1 = list_Cdr(Scan1), Scan2 = list_Cdr(Scan2)) printf(",%zd.%zd", clause_Number((CLAUSE)list_Car(Scan1)), (intptr_t)list_Car(Scan2)); } } RULE clause_GetOriginFromString(const char* RuleName) /************************************************************** INPUT: A string containing the abbreviated name of a rule. RETURNS: The RULE corresponding to the . ***************************************************************/ { if (string_Equal(RuleName, "App")) return CLAUSE_DELETION; else if (string_Equal(RuleName, "EmS")) return EMPTY_SORT; else if (string_Equal(RuleName, "SoR")) return SORT_RESOLUTION; else if (string_Equal(RuleName, "EqR")) return EQUALITY_RESOLUTION; else if (string_Equal(RuleName, "EqF")) return EQUALITY_FACTORING; else if (string_Equal(RuleName, "MPm")) return MERGING_PARAMODULATION; else if (string_Equal(RuleName, "SpR")) return SUPERPOSITION_RIGHT; else if (string_Equal(RuleName, "SPm")) return PARAMODULATION; else if (string_Equal(RuleName, "OPm")) return ORDERED_PARAMODULATION; else if (string_Equal(RuleName, "SpL")) return SUPERPOSITION_LEFT; else if (string_Equal(RuleName, "Res")) return GENERAL_RESOLUTION; else if (string_Equal(RuleName, "SHy")) return SIMPLE_HYPER; else if (string_Equal(RuleName, "OHy")) return ORDERED_HYPER; else if (string_Equal(RuleName, "URR")) return UR_RESOLUTION; else if (string_Equal(RuleName, "Fac")) return GENERAL_FACTORING; else if (string_Equal(RuleName, "Spt")) return SPLITTING; else if (string_Equal(RuleName, "Inp")) return INPUTCLAUSE; else if (string_Equal(RuleName, "Rew")) return REWRITING; else if (string_Equal(RuleName, "CRw")) return CONTEXTUAL_REWRITING; else if (string_Equal(RuleName, "Con")) return CONDENSING; else if (string_Equal(RuleName, "AED")) return ASSIGNMENT_EQUATION_DELETION; else if (string_Equal(RuleName, "Obv")) return OBVIOUS_REDUCTIONS; else if (string_Equal(RuleName, "SSi")) return SORT_SIMPLIFICATION; else if (string_Equal(RuleName, "MRR")) return MATCHING_REPLACEMENT_RESOLUTION; else if (string_Equal(RuleName, "UnC")) return UNIT_CONFLICT; else if (string_Equal(RuleName, "Def")) return DEFAPPLICATION; else if (string_Equal(RuleName, "Ter")) return TERMINATOR; else if (string_Equal(RuleName, "OCh")) return ORDERED_CHAINING; else if (string_Equal(RuleName, "NCh")) return NEGATIVE_CHAINING; else if (string_Equal(RuleName, "CRe")) return COMPOSITION_RESOLUTION; else { misc_StartErrorReport(); misc_ErrorReport("\nIn clause_GetOriginFromString: Unknown clause origin '%s'.", RuleName); misc_FinishErrorReport(); return CLAUSE_DELETION; /* Just for the compiler, code is not reachable */ } } void clause_FPrintOrigin(FILE* File, CLAUSE Clause) /************************************************************** INPUT: A Clause. RETURNS: Nothing. SUMMARY: Prints the clause's origin to the file. ***************************************************************/ { RULE Result; Result = clause_Origin(Clause); switch(Result) { case CLAUSE_DELETION: fputs("App", File); break; case EMPTY_SORT: fputs("EmS", File); break; case SORT_RESOLUTION: fputs("SoR", File); break; case EQUALITY_RESOLUTION: fputs("EqR", File); break; case EQUALITY_FACTORING: fputs("EqF", File); break; case MERGING_PARAMODULATION: fputs("MPm", File); break; case SUPERPOSITION_RIGHT: fputs("SpR", File); break; case PARAMODULATION: fputs("SPm", File); break; case ORDERED_PARAMODULATION: fputs("OPm", File); break; case SUPERPOSITION_LEFT: fputs("SpL", File); break; case GENERAL_RESOLUTION: fputs("Res", File); break; case SIMPLE_HYPER: fputs("SHy", File); break; case ORDERED_HYPER: fputs("OHy", File); break; case UR_RESOLUTION: fputs("URR", File); break; case GENERAL_FACTORING: fputs("Fac", File); break; case SPLITTING: fputs("Spt", File); break; case INPUTCLAUSE: fputs("Inp", File); break; case REWRITING: fputs("Rew", File); break; case CONTEXTUAL_REWRITING: fputs("CRw", File); break; case CONDENSING: fputs("Con", File); break; case ASSIGNMENT_EQUATION_DELETION: fputs("AED", File); break; case OBVIOUS_REDUCTIONS: fputs("Obv", File); break; case SORT_SIMPLIFICATION: fputs("SSi", File); break; case MATCHING_REPLACEMENT_RESOLUTION: fputs("MRR", File); break; case UNIT_CONFLICT: fputs("UnC", File); break; case DEFAPPLICATION: fputs("Def", File); break; case TERMINATOR: fputs("Ter", File); break; case TEMPORARY: fputs("Temporary", File); break; case ORDERED_CHAINING: fputs("OCh", File); break; case NEGATIVE_CHAINING: fputs("NCh", File); break; case COMPOSITION_RESOLUTION: fputs("CRe", File); break; default: misc_StartErrorReport(); misc_ErrorReport("\n In clause_FPrintOrigin: Clause has no origin."); misc_FinishErrorReport(); } } void clause_PrintOrigin(CLAUSE Clause) /************************************************************** INPUT: A Clause. RETURNS: Nothing. SUMMARY: Prints the clauses origin to stdout. ***************************************************************/ { clause_FPrintOrigin(stdout, Clause); } void clause_PrintVerbose(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A Clause, a flag store and a precedence. RETURNS: Nothing. SUMMARY: Prints almost all the information kept in the clause structure. ***************************************************************/ { int c,a,s; #ifdef CHECK if (!clause_IsClause(Clause, Flags, Precedence)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_PrintVerbose:"); misc_ErrorReport("\n Illegal input. Input not a clause."); misc_FinishErrorReport(); } #endif c = clause_NumOfConsLits(Clause); a = clause_NumOfAnteLits(Clause); s = clause_NumOfSuccLits(Clause); printf(" c = %d a = %d s = %d", c,a,s); printf(" Weight : %zd", clause_Weight(Clause)); printf(" Depth : %zd", clause_Depth(Clause)); printf(" %s %s ", (clause_GetFlag(Clause,WORKEDOFF) ? "WorkedOff" : "Usable"), (clause_GetFlag(Clause,CLAUSESELECT) ? "Selected" : "NotSelected")); clause_Print(Clause); } CLAUSE clause_GetNumberedCl(int number, LIST ClList) /************************************************************** INPUT: RETURNS: CAUTION: ***************************************************************/ { while (!list_Empty(ClList) && clause_Number((CLAUSE)list_Car(ClList)) != number) ClList = list_Cdr(ClList); if (list_Empty(ClList)) return NULL; else return list_Car(ClList); } BOOL clause_NumberLower(CLAUSE A, CLAUSE B) { return (BOOL) (clause_Number(A) < clause_Number(B)); } LIST clause_NumberSort(LIST List) /************************************************************** INPUT: A list of clauses. RETURNS: The same list where the elements are sorted wrt their number. CAUTION: Destructive. ***************************************************************/ { return list_Sort(List, (BOOL (*) (POINTER, POINTER)) clause_NumberLower); } LIST clause_NumberDelete(LIST List, int Number) /************************************************************** INPUT: A list of clauses and an integer. RETURNS: The same list where the clauses with are deleted. CAUTION: Destructive. ***************************************************************/ { LIST Scan1,Scan2; for (Scan1 = List; !list_Empty(Scan1); ) if (clause_Number(list_Car(Scan1))==Number) { Scan2 = Scan1; Scan1 = list_Cdr(Scan1); List = list_PointerDeleteOneElement(List, list_Car(Scan2)); } else Scan1 = list_Cdr(Scan1); return List; } static NAT clause_NumberOfMaxLits(CLAUSE Clause) /************************************************************** INPUT: A clause. RETURNS: The number of maximal literals in a clause. ***************************************************************/ { NAT Result,i,n; Result = 0; n = clause_Length(Clause); for (i = clause_FirstAntecedentLitIndex(Clause); i < n; i++) if (clause_LiteralIsMaximal(clause_GetLiteral(Clause,i))) Result++; return Result; } /* Unused ! */ NAT clause_NumberOfMaxAntecedentLits(CLAUSE Clause) /************************************************************** INPUT: A clause. RETURNS: The number of maximal antecedent literals in a clause. ***************************************************************/ { NAT Result,i,n; Result = 0; n = clause_LastAntecedentLitIndex(Clause); for (i = clause_FirstAntecedentLitIndex(Clause); i <= n; i++) if (clause_LiteralIsMaximal(clause_GetLiteral(Clause,i))) Result++; return Result; } void clause_SelectLiteral(CLAUSE Clause, FLAGSTORE Flags) /************************************************************** INPUT: A clause and a flag store. RETURNS: Nothing. EFFECT: If the clause contains more than 2 maximal literals, at least one antecedent literal, the literal with the highest weight is selected or if selected predicates are set, the first (from left to right) literal with selected predicate Or the user has determined literals to be selected that will then be chosen if they occur in the antecedent. ***************************************************************/ { if (clause_HasSolvedConstraint(Clause) && !clause_GetFlag(Clause,CLAUSESELECT) && clause_NumOfAnteLits(Clause) > 0 && flag_GetFlagIntValue(Flags, flag_SELECT) != flag_SELECTOFF && (flag_GetFlagIntValue(Flags, flag_SELECT) != flag_SELECTIFSEVERALMAXIMAL || clause_NumberOfMaxLits(Clause) > 1)) { NAT i,n; LITERAL Lit; Lit = (LITERAL)NULL; n = clause_LastAntecedentLitIndex(Clause); i = clause_FirstAntecedentLitIndex(Clause); if (flag_GetFlagIntValue(Flags, flag_SELECT) == flag_SELECTFROMLIST) { for ( ; i <= n; i++) if (symbol_HasProperty(term_TopSymbol(clause_LiteralAtom(clause_GetLiteral(Clause,i))), SELECTED)) { Lit = clause_GetLiteral(Clause,i); i = n + 1; } } else { Lit = clause_GetLiteral(Clause,i); i++; if (symbol_HasProperty(term_TopSymbol(clause_LiteralAtom(Lit)), SELECTED)) i = n + 1; for ( ; i <= n; i++) if (symbol_HasProperty(term_TopSymbol(clause_LiteralAtom(clause_GetLiteral(Clause,i))), SELECTED)) { Lit = clause_GetLiteral(Clause,i); i = n + 1; } else if (clause_LiteralWeight(Lit) < clause_LiteralWeight(clause_GetLiteral(Clause,i))) Lit = clause_GetLiteral(Clause,i); } if (Lit != (LITERAL)NULL) { clause_LiteralSetFlag(Lit,LITSELECT); clause_SetFlag(Clause,CLAUSESELECT); } } } void clause_SetSpecialFlags(CLAUSE Clause, BOOL SortDecreasing, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A clause, a flag indicating whether all equations are sort decreasing, a flag store and a precedence. RETURNS: void. EFFECT: If the clause is a sort theory clause and its declaration top symbol is a set declaration sort, i.e., it occurred in a declaration right from the beginning, the paramodulation/superposition steps into the clause are forbidden by setting the NOPARAINTO clause flag ***************************************************************/ { if (SortDecreasing && clause_IsSortTheoryClause(Clause, Flags, Precedence) && symbol_HasProperty(term_TopSymbol(clause_GetLiteralTerm(Clause,clause_FirstSuccedentLitIndex(Clause))), DECLSORT)) clause_SetFlag(Clause,NOPARAINTO); } BOOL clause_ContainsPotPredDef(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence, NAT* Index, LIST* Pair) /************************************************************** INPUT: A clause, a flag store, a precedence and a pointer to an index. RETURNS: TRUE iff a succedent literal of the clause is a predicate having only variables as arguments, the predicate occurs only once in the clause and no other variables but the predicates' occur. In that case Index is set to the index of the predicate and Pair contains two lists : the literals for which positive occurrences must be found and a list of literals for which negative occurrences must be found for a complete definition. ***************************************************************/ { NAT i; #ifdef CHECK if (!clause_IsClause(Clause, Flags, Precedence)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_ContainsPotPredDef:"); misc_ErrorReport("\n Illegal input. Input not a clause."); misc_FinishErrorReport(); } #endif /* Iterate over all succedent literals */ for (i=clause_FirstSuccedentLitIndex(Clause); i < clause_Length(Clause); i++) { LITERAL lit; TERM atom; LIST pair; lit = clause_GetLiteral(Clause, i); atom = clause_LiteralSignedAtom(lit); if (symbol_IsPredicate(term_TopSymbol(atom))) { LIST l; BOOL ok; ok = TRUE; pair = list_PairCreate(list_Nil(), list_Nil()); /* Make sure all arguments of predicate are variables */ for (l=term_ArgumentList(atom); !list_Empty(l); l=list_Cdr(l)) { if (!term_IsStandardVariable((TERM) list_Car(l))) { ok = FALSE; break; } } if (ok) { /* Make sure predicate occurs only once in clause */ NAT j, count; count = 0; for (j=0; (j < clause_Length(Clause)) && (count < 2); j++) { TERM t; t = clause_GetLiteralAtom(Clause, j); if (symbol_Equal(term_TopSymbol(t), term_TopSymbol(atom))) count++; } if (count > 1) ok = FALSE; } if (ok) { /* Build lists of positive and negative literals */ /* At the same time check if other variables than those among the predicates arguments are found */ NAT j; LIST predvars, vars; predvars = fol_FreeVariables(atom); /* Build list of literals for which positive occurrences are required */ for (j=0; (j < clause_FirstSuccedentLitIndex(Clause)) && ok; j++) { list_Rplaca(pair, list_Cons(clause_GetLiteralAtom(Clause, j), list_PairFirst(pair))); vars = fol_FreeVariables(clause_GetLiteralTerm(Clause, j)); for (l = vars; !list_Empty(l); l = list_Cdr(l)) { if (!term_ListContainsTerm(predvars, list_Car(l))) { ok = FALSE; break; } } list_Delete(vars); } /* Build list of literals for which negative occurrences are required */ for (j = clause_FirstSuccedentLitIndex(Clause); (j < clause_Length(Clause)) && ok; j++) { if (j != i) { list_Rplacd(pair, list_Cons(clause_GetLiteralAtom(Clause, j), list_PairSecond(pair))); vars = fol_FreeVariables(clause_GetLiteralAtom(Clause, j)); for (l=vars; !list_Empty(l); l=list_Cdr(l)) { if (!term_ListContainsTerm(predvars, list_Car(l))) { ok = FALSE; break; } } list_Delete(vars); } } list_Delete(predvars); } if (ok) { *Index = i; *Pair = pair; return TRUE; } else { list_Delete(list_PairFirst(pair)); list_Delete(list_PairSecond(pair)); list_PairFree(pair); } } } return FALSE; } BOOL clause_IsPartOfDefinition(CLAUSE Clause, TERM Predicate, intptr_t *Index, LIST Pair) /************************************************************** INPUT: A clause, a term, a pointer to an int and a pair of term lists. RETURNS: TRUE iff the predicate occurs among the negative literals of the clause and the other negative and positive literals are found in the pairs' lists. In that case they are removed from the lists. Index is set to the index of the defined predicate in Clause. ***************************************************************/ { NAT predindex, i; BOOL ok; ok = TRUE; /* Check whether Predicate is among antecedent or constraint literals */ for (predindex=clause_FirstLitIndex(); predindex < clause_FirstSuccedentLitIndex(Clause); predindex++) if (term_Equal(Predicate, clause_GetLiteralAtom(Clause, predindex))) break; if (predindex == clause_FirstSuccedentLitIndex(Clause)) return FALSE; *Index = predindex; /* Check if other negative literals are required for definition */ for (i=clause_FirstLitIndex(); (i < clause_FirstSuccedentLitIndex(Clause)) && ok; i++) { if (i != predindex) if (!term_ListContainsTerm((LIST) list_PairSecond(Pair), clause_GetLiteralAtom(Clause, i))) ok = FALSE; } /* Check if positive literals are required for definition */ for (i=clause_FirstSuccedentLitIndex(Clause); (i < clause_Length(Clause)) && ok; i++) if (!term_ListContainsTerm((LIST) list_PairFirst(Pair), clause_GetLiteralAtom(Clause, i))) ok = FALSE; if (!ok) return FALSE; else { /* Complement for definition found, remove literals from pair lists */ for (i=0; i < clause_FirstSuccedentLitIndex(Clause); i++) if (i != predindex) list_Rplacd(Pair, list_DeleteElement((LIST) list_PairSecond(Pair), clause_GetLiteralAtom(Clause, i), (BOOL (*)(POINTER, POINTER)) term_Equal)); for (i=clause_FirstSuccedentLitIndex(Clause); i < clause_Length(Clause); i++) list_Rplaca(Pair, list_DeleteElement((LIST) list_PairFirst(Pair), clause_GetLiteralAtom(Clause, i), (BOOL (*)(POINTER, POINTER)) term_Equal)); return TRUE; } } void clause_FPrintRule(FILE* File, CLAUSE Clause) /************************************************************** INPUT: A file and a clause. RETURNS: Nothing. SUMMARY: Prints any term of the clause to file in rule format. CAUTION: Uses the term_Output functions. ***************************************************************/ { int i,n; TERM Literal; LIST scan,antecedent,succedent,constraints; n = clause_Length(Clause); constraints = list_Nil(); antecedent = list_Nil(); succedent = list_Nil(); for (i = 0; i < n; i++) { Literal = clause_GetLiteralTerm(Clause,i); if (symbol_Equal(term_TopSymbol(Literal),fol_Not())) { if (symbol_Arity(term_TopSymbol(fol_Atom(Literal))) == 1 && symbol_IsVariable(term_TopSymbol(term_FirstArgument(fol_Atom(Literal))))) constraints = list_Cons(Literal,constraints); else antecedent = list_Cons(Literal,antecedent); } else succedent = list_Cons(Literal,succedent); } for (scan = constraints; !list_Empty(scan); scan = list_Cdr(scan)) { term_FPrint(File, fol_Atom(list_Car(scan))); putc(' ', File); } fputs("||", File); for (scan = antecedent; !list_Empty(scan); scan = list_Cdr(scan)) { putc(' ', File); term_FPrint(File,fol_Atom(list_Car(scan))); if (list_Empty(list_Cdr(scan))) putc(' ', File); } fputs("->", File); for (scan = succedent; !list_Empty(scan); scan = list_Cdr(scan)) { putc(' ', File); term_FPrint(File,list_Car(scan)); } fputs(".\n", File); list_Delete(antecedent); list_Delete(succedent); list_Delete(constraints); } void clause_FPrintOtter(FILE* File, CLAUSE clause) /************************************************************** INPUT: A file and a clause. RETURNS: Nothing. SUMMARY: Prints any clause to File. CAUTION: Uses the other clause_Output functions. ***************************************************************/ { int n,j; LITERAL Lit; TERM Atom; n = clause_Length(clause); if (n == 0) fputs(" $F ", File); else { for (j = 0; j < n; j++) { Lit = clause_GetLiteral(clause,j); Atom = clause_LiteralAtom(Lit); if (clause_LiteralIsNegative(Lit)) putc('-', File); if (fol_IsEquality(Atom)) { if (clause_LiteralIsNegative(Lit)) putc('(', File); term_FPrintOtterPrefix(File,term_FirstArgument(Atom)); fputs(" = ", File); term_FPrintOtterPrefix(File,term_SecondArgument(Atom)); if (clause_LiteralIsNegative(Lit)) putc(')', File); } else term_FPrintOtterPrefix(File,Atom); if (j <= (n-2)) fputs(" | ", File); } } fputs(".\n", File); } void clause_FPrintCnfDFG(FILE* File, BOOL OnlyProductive, LIST Axioms, LIST Conjectures, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A file, a list of axiom clauses and a list of conjecture clauses. A flag indicating whether only potentially productive clauses should be printed. A flag store. A precedence. RETURNS: Nothing. SUMMARY: Prints a the respective clause lists to dependent on . ***************************************************************/ { LIST scan; CLAUSE Clause; if (Axioms) { fputs("list_of_clauses(axioms, cnf).\n", File); for (scan=Axioms;!list_Empty(scan);scan=list_Cdr(scan)) { Clause = (CLAUSE)list_Car(scan); if (!OnlyProductive || (clause_HasSolvedConstraint(Clause) && !clause_HasSelectedLiteral(Clause, Flags, Precedence))) clause_FPrintDFG(File,Clause,FALSE); } fputs("end_of_list.\n\n", File); } if (Conjectures) { fputs("list_of_clauses(conjectures, cnf).\n", File); for (scan=Conjectures;!list_Empty(scan);scan=list_Cdr(scan)) { Clause = (CLAUSE)list_Car(scan); if (!OnlyProductive || (clause_HasSolvedConstraint(Clause) && !clause_HasSelectedLiteral(Clause, Flags, Precedence))) clause_FPrintDFG(File,Clause,FALSE); } fputs("end_of_list.\n\n", File); } } void clause_FPrintCnfDFGProof(FILE* File, BOOL OnlyProductive, LIST Axioms, LIST Conjectures, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A file, a list of axiom clauses and a list of conjecture clauses. A flag indicating whether only potentially productive clauses should be printed. A flag store. A precedence. RETURNS: Nothing. SUMMARY: Prints a the respective clause lists to dependent on . ***************************************************************/ { LIST scan; CLAUSE Clause; if (Axioms) { fputs("list_of_clauses(axioms, cnf).\n", File); for (scan=Axioms;!list_Empty(scan);scan=list_Cdr(scan)) { Clause = (CLAUSE)list_Car(scan); if (!OnlyProductive || (clause_HasSolvedConstraint(Clause) && !clause_HasSelectedLiteral(Clause, Flags, Precedence))) clause_FPrintDFGProof(File,Clause,FALSE); } fputs("end_of_list.\n\n", File); } if (Conjectures) { fputs("list_of_clauses(conjectures, cnf).\n", File); for (scan=Conjectures;!list_Empty(scan);scan=list_Cdr(scan)) { Clause = (CLAUSE)list_Car(scan); if (!OnlyProductive || (clause_HasSolvedConstraint(Clause) && !clause_HasSelectedLiteral(Clause, Flags, Precedence))) clause_FPrintDFGProof(File,Clause,FALSE); } fputs("end_of_list.\n\n", File); } } static void clause_FPrintDescription(FILE* File, const char* Name, const char* Author, const char* Status, const char* Description) { 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", File); } static void clause_FPrintClauseFomulaRelationForClauses(FILE* File, LIST Clauses, HASHMAP ClauseToTermLabelList) /************************************************************** INPUT: A file, a list of axioms, a list of conjectures, and a relationship between clauses and formala names. RETURNS: Nothing. SUMMARY: Prints relationship between clauses and formula names to . ***************************************************************/ { LIST Scan, ValueList; for (Scan=Clauses; !list_Empty(Scan); Scan=list_Cdr(Scan)) { ValueList = hm_Retrieve(ClauseToTermLabelList, list_Car(Scan)); if (!list_Empty(ValueList)) { fprintf(File, "(%zd,", clause_Number(list_Car(Scan))); fputs(list_Car(ValueList), File); ValueList = list_Cdr(ValueList); while (!list_Empty(ValueList)) { fputs(",", File); fputs(list_Car(ValueList), File); ValueList = list_Cdr(ValueList); } fputs(")", File); if (!list_Empty(list_Cdr(Scan))) fputs(",\n ", File); } } } static void clause_FPrintClauseFormulaRelation(FILE* File, LIST Axioms, LIST Conjectures, HASHMAP ClauseToTermLabelList) /************************************************************** INPUT: A file, a list of axioms, a list of conjectures, and a relationship between clauses and formala names. RETURNS: Nothing. SUMMARY: Prints relationship between clauses and formula names to . ***************************************************************/ { fputs("set_ClauseFormulaRelation(", File); clause_FPrintClauseFomulaRelationForClauses(File, Axioms, ClauseToTermLabelList); if (!list_Empty(Conjectures) && !list_Empty(Axioms)) fputs(",\n ", File); clause_FPrintClauseFomulaRelationForClauses(File, Conjectures, ClauseToTermLabelList); fputs(").\n\n\n", File); } static void clause_FPrintSelectedSymbols(FILE* File) /************************************************************** INPUT: A file. RETURNS: Nothing. SUMMARY: Prints selected symbols to . ***************************************************************/ { LIST Scan, SelectedSymbols; SelectedSymbols = symbol_GetAllSymbolsWithProperty(SELECTED); /* Print the selected symbols. */ if (!list_Empty(SelectedSymbols)) { fputs("set_selection(", File); for (Scan = SelectedSymbols; !list_Empty(Scan); Scan = list_Cdr(Scan)) { SYMBOL Symbol; Symbol = (SYMBOL)list_Car(Scan); fputs(symbol_Name(Symbol), File); /* If there are more selected symbols following, add a ',' after the symbol. */ if (!list_Empty(list_Cdr(Scan))) putc(',', File); } fputs(").\n\n\n", File); list_Free(SelectedSymbols); } } void clause_FPrintSettings(FILE* File, LIST Axioms, LIST Conjectures, FLAGSTORE Flags, PRECEDENCE Precedence, HASHMAP ClauseToTermLabelList) /************************************************************** INPUT: A file, a list of axioms, a list of conjectures, a flag store, a precedence, a relationship between clauses and formula names. RETURNS: Nothing. SUMMARY: Prints SPASS settings to . ***************************************************************/ { fputs("list_of_settings(SPASS).\n{*\n", File); if (ClauseToTermLabelList != (HASHMAP)NULL) clause_FPrintClauseFormulaRelation(File, Axioms, Conjectures, ClauseToTermLabelList); /* Print just the necessary flags. */ if (Flags != NULL) { flag_FPrintFlag(File, Flags, flag_ORD); flag_FPrintFlag(File, Flags, flag_SELECT); fputs("\nset_flag(RInput,0).",File); flag_FPrintFlagWithValue(File, Flags, flag_SPLITS, flag_SPLITSOFF, ""); /* spliting is forced off by default */ fputs("\n\n", File); /* Print the selected symbols. */ if(flag_GetFlagIntValue(Flags, flag_SELECT) != flag_SELECTOFF) clause_FPrintSelectedSymbols(File); } if(Precedence != NULL) symbol_FPrintPrecedence(File, Precedence); fputs("*}\nend_of_list.\n\n", File); } static void clause_FPrintClauses(FILE* File, BOOL OnlyProductive, BOOL PrintConjectures, LIST Clauses, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A file, a flag indicating whether only potentially productive clauses should be printed, a flag indicating whether only conjectures or only axioms should be printed, a list of clauses, an optional flag store and an optional precedence. RETURNS: Nothing. SUMMARY: Prints (productive) axiom or conjecture clauses to . ***************************************************************/ { LIST Scan; for (Scan=Clauses;!list_Empty(Scan);Scan=list_Cdr(Scan)) { CLAUSE Clause; Clause = (CLAUSE) list_Car(Scan); if (!OnlyProductive || (clause_HasSolvedConstraint(Clause) && !clause_HasSelectedLiteral(Clause, Flags, Precedence))) if (PrintConjectures == clause_GetFlag(Clause,CONCLAUSE)) clause_FPrintDFG(File,Clause,FALSE); } } void clause_FPrintCnfDFGProblem(FILE* File, BOOL OnlyProductive, const char* Name, const char* Author, const char* Status, const char* Description, LIST Clauses, LIST Conjectures, FLAGSTORE Flags, PRECEDENCE Precedence, HASHMAP ClauseToTermLabelList, BOOL IsModel, BOOL PrintSettings) /************************************************************** INPUT: A file, a flag indicating whether only potentially productive clauses should be printed, the problem's name, author, status and description to be included in the description block given as strings, a list of clauses, an optional additional list of conjectures, an optional flag store, an optional precedence, an optional relationship between clauses and formula names, whether the problem is a model, and whether the settings should be printed. RETURNS: Nothing. SUMMARY: Prints a complete DFG problem clause file to . ***************************************************************/ { fputs("begin_problem(Unknown).\n\n", File); clause_FPrintDescription(File, Name, Author, Status, Description); putc('\n', File); fputs("list_of_symbols.\n", File); symbol_FPrintDFGSignature(File); fputs("end_of_list.\n\n", File); /* Since Clauses can hold both axioms and conjectures, it's * printed in both cases, once just the axioms, the other time * just the conjectures, except when we're printing a model. * If we are printing a model, the conjectures are printed * along with the axioms, to keep prior behaviour. */ fputs("list_of_clauses(axioms, cnf).\n", File); clause_FPrintClauses(File, OnlyProductive, FALSE, Clauses, Flags, Precedence); if(IsModel) clause_FPrintClauses(File, OnlyProductive, TRUE, Clauses, Flags, Precedence); fputs("end_of_list.\n\n", File); fputs("list_of_clauses(conjectures, cnf).\n", File); if(!IsModel) clause_FPrintClauses(File, OnlyProductive, TRUE, Clauses, Flags, Precedence); clause_FPrintClauses(File, OnlyProductive, TRUE, Conjectures, Flags, Precedence); fputs("end_of_list.\n\n", File); if(PrintSettings) clause_FPrintSettings(File, Clauses, Conjectures, Flags, Precedence, ClauseToTermLabelList); fputs("\nend_problem.\n\n", File); } void clause_FPrintCnfFormulasDFGProblem(FILE* File, BOOL OnlyProductive, const char* Name, const char* Author, const char* Status, const char* Description, LIST Axioms, LIST Conjectures, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A file, a list of axiom clauses and a list of conjecture clauses. A flag indicating whether only potentially productive clauses should be printed. A bunch of strings that are printed to the description. A flag store. A precedence. RETURNS: Nothing. SUMMARY: Prints the respective clause lists as a complete DFG formulae output to . ***************************************************************/ { LIST scan; CLAUSE Clause; fputs("begin_problem(Unknown).\n\n", File); clause_FPrintDescription(File, Name, Author, Status, Description); fputs("\nlist_of_symbols.\n", File); symbol_FPrintDFGSignature(File); fputs("end_of_list.\n\n", File); if (Axioms) { fputs("list_of_formulae(axioms).\n", File); for (scan=Axioms; !list_Empty(scan); scan=list_Cdr(scan)) { Clause = (CLAUSE)list_Car(scan); if (!OnlyProductive || (clause_HasSolvedConstraint(Clause) && !clause_HasSelectedLiteral(Clause, Flags, Precedence))) clause_FPrintFormulaDFG(File,Clause,FALSE); } fputs("end_of_list.\n\n", File); } if (Conjectures) { fputs("list_of_formulae(conjectures).\n", File); for (scan=Conjectures; !list_Empty(scan); scan=list_Cdr(scan)) { Clause = (CLAUSE)list_Car(scan); if (!OnlyProductive || (clause_HasSolvedConstraint(Clause) && !clause_HasSelectedLiteral(Clause, Flags, Precedence))) clause_FPrintFormulaDFG(File,Clause,FALSE); } fputs("end_of_list.\n\n", File); } fputs("list_of_settings(SPASS).\n{*\n", File); fol_FPrintPrecedence(File, Precedence); fputs("\n*}\nend_of_list.\n\nend_problem.\n\n", File); } void clause_FPrintCnfOtter(FILE* File, LIST Clauses, FLAGSTORE Flags) /************************************************************** INPUT: A file, a list of clauses and a flag store. RETURNS: Nothing. SUMMARY: Prints the clauses to in a format readable by Otter. ***************************************************************/ { LIST scan; int i; BOOL Equality; CLAUSE Clause; Equality = FALSE; for (scan=Clauses;!list_Empty(scan) && !Equality; scan=list_Cdr(scan)) { Clause = (CLAUSE)list_Car(scan); for (i=clause_FirstAntecedentLitIndex(Clause);i is true then all axiom clauses in are written to . Otherwise all conjecture clauses in are written to . ***************************************************************/ { CLAUSE Clause; while (Clauses) { Clause = (CLAUSE)list_Car(Clauses); if ((Type && !clause_GetFlag(Clause,CONCLAUSE)) || (!Type && clause_GetFlag(Clause,CONCLAUSE))) clause_FPrintDFG(File,Clause,FALSE); Clauses = list_Cdr(Clauses); } } void clause_FPrintDFGStep(FILE* File, CLAUSE Clause, BOOL Justif) /************************************************************** INPUT: A file, a clause and a boolean value. RETURNS: Nothing. SUMMARY: Prints any clause together with a label (the clause number) to File. If is TRUE also the labels of the parent clauses are printed. CAUTION: Uses the other clause_Output functions. ***************************************************************/ { int n,j; LITERAL Lit; TERM Atom; LIST Variables,Iter; n = clause_Length(Clause); fputs(" step(", File); fprintf(File, "%zd,", clause_Number(Clause)); Variables = list_Nil(); for (j = 0; j < n; j++) Variables = list_NPointerUnion(Variables, term_VariableSymbols(clause_GetLiteralAtom(Clause,j))); if (!list_Empty(Variables)) { symbol_FPrint(File, fol_All()); fputs("([", File); for (Iter = Variables; !list_Empty(Iter); Iter = list_Cdr(Iter)) { symbol_FPrint(File, (SYMBOL) list_Car(Iter)); if (!list_Empty(list_Cdr(Iter))) putc(',', File); } fputs("],", File); } symbol_FPrint(File, fol_Or()); putc('(', File); for (j = 0; j < n; j++) { Lit = clause_GetLiteral(Clause,j); Atom = clause_LiteralSignedAtom(Lit); term_FPrintPrefix(File,Atom); if (j+1 < n) putc(',', File); } if (n==0) symbol_FPrint(File,fol_False()); if (!list_Empty(Variables)) { list_Delete(Variables); putc(')', File); } fputs("),", File); clause_FPrintOrigin(File, Clause); fputs(",[", File); for (Iter = clause_ParentClauses(Clause); !list_Empty(Iter); Iter = list_Cdr(Iter)) { fprintf(File, "%zd", (intptr_t)list_Car(Iter)); if (!list_Empty(list_Cdr(Iter))) putc(',', File); } putc(']', File); fprintf(File, ",[splitlevel:%zd]", clause_SplitLevel(Clause)); fputs(").\n", File); } void clause_FPrintDFGProof(FILE* File, CLAUSE Clause, BOOL Justif) /************************************************************** INPUT: A file, a clause and a boolean value. RETURNS: Nothing. SUMMARY: Prints any clause together with a label (the clause number) to File. If Justif is TRUE also the labels of the parent clauses are printed. CAUTION: Uses the other clause_Output functions. ***************************************************************/ { int n,j; LITERAL Lit; TERM Atom; LIST Variables,Iter; n = clause_Length(Clause); fputs(" clause(", File); Variables = list_Nil(); for (j = 0; j < n; j++) Variables = list_NPointerUnion(Variables, term_VariableSymbols(clause_GetLiteralAtom(Clause,j))); if (!list_Empty(Variables)) { symbol_FPrint(File, fol_All()); fputs("([", File); for (Iter = Variables; !list_Empty(Iter); Iter = list_Cdr(Iter)) { symbol_FPrint(File, (SYMBOL) list_Car(Iter)); if (!list_Empty(list_Cdr(Iter))) putc(',', File); } fputs("],", File); } symbol_FPrint(File, fol_Or()); putc('(', File); for (j = 0; j < n; j++) { Lit = clause_GetLiteral(Clause,j); Atom = clause_LiteralSignedAtom(Lit); term_FPrintPrefix(File,Atom); if (j+1 < n) putc(',', File); } if (n==0) symbol_FPrint(File,fol_False()); if (!list_Empty(Variables)) { list_Delete(Variables); putc(')', File); } fprintf(File, "),%zd", clause_Number(Clause)); if (Justif) { putc(',', File); clause_FPrintOrigin(File, Clause); fputs(",[", File); for (Iter = clause_ParentClauses(Clause); !list_Empty(Iter); Iter = list_Cdr(Iter)) { fprintf(File, "%zd", (intptr_t)list_Car(Iter)); if (!list_Empty(list_Cdr(Iter))) putc(',', File); } putc(']', File); fprintf(File, ",%zd", clause_SplitLevel(Clause)); } fputs(").\n", File); } void clause_FPrintDFG(FILE* File, CLAUSE Clause, BOOL Justif) /************************************************************** INPUT: A file, a clause and a boolean value. RETURNS: Nothing. SUMMARY: Prints any clause together with a label (the clause number) to File. If Justif is TRUE also the labels of the parent clauses are printed. CAUTION: Uses the other clause_Output functions. ***************************************************************/ { int n,j,c,a,s; LITERAL Lit; LIST Iter; fputs(" clause(", File); n = clause_Length(Clause); if (n==0) symbol_FPrint(File,fol_False()); else { c = clause_NumOfConsLits(Clause); a = clause_NumOfAnteLits(Clause); s = clause_NumOfSuccLits(Clause); for (j = 0; j < c; j++) { putchar(' '); Lit = clause_GetLiteral(Clause, j); clause_LiteralFPrintUnsigned(File, Lit); if (j+1 < c) putc(' ', File); } fputs(" || ", File); a += c; for ( ; j < a; j++) { Lit = clause_GetLiteral(Clause, j); clause_LiteralFPrintUnsigned(File, Lit); if (clause_LiteralGetFlag(Lit,LITSELECT)) putc('+', File); if (j+1 < a) putc(' ', File); } fputs(" -> ",File); s += a; for ( ; j < s; j++) { Lit = clause_GetLiteral(Clause, j); clause_LiteralFPrintUnsigned(File, Lit); #ifdef CHECK if (clause_LiteralGetFlag(Lit,LITSELECT)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_FPrintDFG: Clause has selected positive literal.\n"); misc_FinishErrorReport(); } #endif if (j+1 < s) putc(' ', File); } } fprintf(File, ",%zd", clause_Number(Clause)); if (Justif) { putc(',', File); clause_FPrintOrigin(File, Clause); fputs(",[", File); for (Iter = clause_ParentClauses(Clause); !list_Empty(Iter); Iter = list_Cdr(Iter)) { fprintf(File, "%zd", (intptr_t)list_Car(Iter)); if (!list_Empty(list_Cdr(Iter))) putc(',', File); } putc(']', File); fprintf(File, ",%zd", clause_SplitLevel(Clause)); } fputs(").\n", File); } void clause_FPrintFormulaDFG(FILE* File, CLAUSE Clause, BOOL Justif) /************************************************************** INPUT: A file, a clause and a boolean value. RETURNS: Nothing. SUMMARY: Prints any clause together with a label (the clause number) as DFG Formula to File. If Justif is TRUE also the labels of the parent clauses are printed. CAUTION: Uses the other clause_Output functions. ***************************************************************/ { int n,j; LITERAL Lit; TERM Atom; LIST Variables,Iter; n = clause_Length(Clause); fputs(" formula(", File); Variables = list_Nil(); for (j = 0; j < n; j++) Variables = list_NPointerUnion(Variables, term_VariableSymbols(clause_GetLiteralAtom(Clause,j))); if (!list_Empty(Variables)) { symbol_FPrint(File, fol_All()); fputs("([", File); for (Iter = Variables; !list_Empty(Iter); Iter = list_Cdr(Iter)) { symbol_FPrint(File, (SYMBOL) list_Car(Iter)); if (!list_Empty(list_Cdr(Iter))) putc(',', File); } fputs("],", File); } if (n>1) { symbol_FPrint(File, fol_Or()); putc('(', File); } for (j = 0; j < n; j++) { Lit = clause_GetLiteral(Clause,j); Atom = clause_LiteralSignedAtom(Lit); term_FPrintPrefix(File,Atom); if (j+1 < n) putc(',', File); } if (n==0) symbol_FPrint(File,fol_False()); if (!list_Empty(Variables)) { list_Delete(Variables); putc(')', File); } if (n>1) fprintf(File, "),%zd", clause_Number(Clause)); else fprintf(File, ",%zd", clause_Number(Clause)); if (Justif) { putc(',', File); clause_FPrintOrigin(File, Clause); fputs(",[", File); for (Iter = clause_ParentClauses(Clause); !list_Empty(Iter); Iter = list_Cdr(Iter)) { fprintf(File, "%zd", (intptr_t)list_Car(Iter)); if (!list_Empty(list_Cdr(Iter))) putc(',', File); } putc(']', File); fprintf(File, ",%zd", clause_SplitLevel(Clause)); } fputs(").\n", File); } void clause_CheckAux(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence, BOOL VarIsConst) /************************************************************** INPUT: A clause, a flag store and a precedence and a flag. RETURNS: Nothing. EFFECT: Checks whether the clause is in a proper state. If not, a core is dumped. CAUTION: If is set to TRUE variables of are interpreted as constants ***************************************************************/ { CLAUSE Copy; if (!clause_Exists(Clause)) return; if (!clause_IsClauseAux(Clause, Flags, Precedence, VarIsConst)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_Check: Clause not consistent !\n"); misc_FinishErrorReport(); } Copy = clause_Copy(Clause); if(VarIsConst) clause_PrecomputeOrderingAndReInitSkolem(Copy, Flags, Precedence); else clause_PrecomputeOrderingAndReInit(Copy, Flags, Precedence); if ((clause_Weight(Clause) != clause_Weight(Copy)) || (clause_MaxVar(Clause) != clause_MaxVar(Copy))) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_Check: Weight or maximal variable not properly set.\n"); misc_FinishErrorReport(); } clause_Delete(Copy); } void clause_Check(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A clause, a flag store and a precedence. RETURNS: Nothing. EFFECT: Checks whether the clause is in a proper state. If not, a core is dumped. ***************************************************************/ { clause_CheckAux(Clause, Flags, Precedence, FALSE); } void clause_CheckSkolem(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A clause, a flag store and a precedence. RETURNS: Nothing. EFFECT: Checks whether the clause is in a proper state. If not, a core is dumped. ***************************************************************/ { clause_CheckAux(Clause, Flags, Precedence, TRUE); } /* The following are output procedures for clauses with parent pointers */ void clause_PParentsFPrintParentClauses(FILE* File, CLAUSE Clause, BOOL ParentPts) /************************************************************** INPUT: A file, a clause and a boolean flag indicating whether the clause's parents are given by numbers or pointers. RETURNS: Nothing. SUMMARY: Prints the clauses parent clauses and -literals to the file. If is TRUE the parent clauses are defined by pointers, else by numbers. ***************************************************************/ { LIST Scan1,Scan2; int length; intptr_t ParentNum; if (!list_Empty(clause_ParentClauses(Clause))) { Scan1 = clause_ParentClauses(Clause); Scan2 = clause_ParentLiterals(Clause); if (ParentPts) ParentNum = clause_Number(list_Car(Scan1)); else ParentNum = (intptr_t)list_Car(Scan1); fprintf(File, "%zd.%zd", ParentNum, (intptr_t)list_Car(Scan2)); if (!list_Empty(list_Cdr(Scan1))) { length = list_Length(Scan1) - 2; putc(',', File); Scan1 = list_Cdr(Scan1); Scan2 = list_Cdr(Scan2); if (ParentPts) ParentNum = clause_Number(list_Car(Scan1)); else ParentNum = (intptr_t)list_Car(Scan1); fprintf(File, "%zd.%zd", ParentNum, (intptr_t)list_Car(Scan2)); for (Scan1 = list_Cdr(Scan1), Scan2 = list_Cdr(Scan2); !list_Empty(Scan1); Scan1 = list_Cdr(Scan1), Scan2 = list_Cdr(Scan2)) { length -= 2; if (ParentPts) ParentNum = clause_Number(list_Car(Scan1)); else ParentNum = (intptr_t)list_Car(Scan1); fprintf(File, ",%zd.%zd", ParentNum, (intptr_t)list_Car(Scan2)); } } } } void clause_PParentsLiteralFPrintUnsigned(FILE* File, LITERAL Literal) /************************************************************** INPUT: A Literal. RETURNS: Nothing. SUMMARY: ***************************************************************/ { #ifdef CHECK if (!clause_LiteralIsLiteral(Literal)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_PParentsLiteralFPrintUnsigned:"); misc_ErrorReport("\n Illegal input. Input not a literal."); misc_FinishErrorReport(); } #endif term_FPrintPrefix(File, clause_LiteralAtom(Literal)); fflush(stdout); } void clause_PParentsFPrintGen(FILE* File, CLAUSE Clause, BOOL ParentPts) /************************************************************** INPUT: A file, a clause, a boolean flag. RETURNS: Nothing. EFFECTS: Prints the clause to file in SPASS format. If is TRUE, the parents of are interpreted as pointers. ***************************************************************/ { LITERAL Lit; int i,c,a,s; if (!clause_Exists(Clause)) fputs("(CLAUSE)NULL", File); else { fprintf(File, "%zd",clause_Number(Clause)); fprintf(File, "[%zd:", clause_SplitLevel(Clause)); #ifdef CHECK if (Clause->splitfield_length <= 1) fputs("0.", File); else for (i=Clause->splitfield_length-1; i > 0; i--) fprintf(File, "%lu.", Clause->splitfield[i]); if (Clause->splitfield_length == 0) putc('1', File); else fprintf(File, "%lu", (Clause->splitfield[0] | 1)); fprintf(File,":%c%c:%c:%zu:%zu:", clause_GetFlag(Clause, CONCLAUSE) ? 'C' : 'A', clause_GetFlag(Clause, WORKEDOFF) ? 'W' : 'U', clause_GetFlag(Clause, NOPARAINTO) ? 'N' : 'P', clause_Weight(Clause), clause_Depth(Clause)); #endif clause_FPrintOrigin(File, Clause); if (!list_Empty(clause_ParentClauses(Clause))) { putc(':', File); clause_PParentsFPrintParentClauses(File, Clause, ParentPts); } putc(']', File); c = clause_NumOfConsLits(Clause); a = clause_NumOfAnteLits(Clause); s = clause_NumOfSuccLits(Clause); for (i = 0; i < c; i++) { Lit = clause_GetLiteral(Clause, i); clause_PParentsLiteralFPrintUnsigned(File, Lit); if (i+1 < c) putc(' ', File); } fputs(" || ", File); a += c; for ( ; i < a; i++) { Lit = clause_GetLiteral(Clause, i); clause_PParentsLiteralFPrintUnsigned(File, Lit); if (clause_LiteralIsMaximal(Lit)) { putc('*', File); if (clause_LiteralIsOrientedEquality(Lit)) putc('*', File); } if (clause_LiteralGetFlag(Lit,LITSELECT)) putc('+', File); if (i+1 < a) putc(' ', File); } fputs(" -> ",File); s += a; for ( ; i < s; i++) { Lit = clause_GetLiteral(Clause, i); clause_PParentsLiteralFPrintUnsigned(File, Lit); if (clause_LiteralIsMaximal(Lit)) { putc('*', File); if (clause_LiteralIsOrientedEquality(Lit)) putc('*', File); } #ifdef CHECK if (clause_LiteralGetFlag(Lit, LITSELECT)) { misc_StartErrorReport(); misc_ErrorReport("\n In clause_PParentsFPrintGen: Clause has selected positive literal.\n"); misc_FinishErrorReport(); } #endif if (i+1 < s) putc(' ', File); } putc('.', File); } } void clause_PParentsFPrint(FILE* File, CLAUSE Clause) /************************************************************** INPUT: A file handle and a clause. RETURNS: Nothing. EFFECTS: Prints out the clause to file in SPASS output format ***************************************************************/ { clause_PParentsFPrintGen(File, Clause, TRUE); } void clause_PParentsListFPrint(FILE* File, LIST L) /************************************************************** INPUT: A file handle, a list of clauses with parent pointers RETURNS: Nothing. EFFECTS: Print the list to . ***************************************************************/ { while (!list_Empty(L)) { clause_PParentsFPrint(File, list_Car(L)); putc('\n', File); L = list_Cdr(L); } } void clause_PParentsPrint(CLAUSE Clause) /************************************************************** INPUT: A clause with parent pointers RETURNS: Nothing. EFFECTS: The clause is printed to stdout. ***************************************************************/ { clause_PParentsFPrint(stdout, Clause); } void clause_PParentsListPrint(LIST L) /************************************************************** INPUT: A file handle, a list of clauses with parent pointers RETURNS: Nothing. EFFECTS: Print the clause list to stdout. ***************************************************************/ { clause_PParentsListFPrint(stdout, L); } LIST clause_MergeMaxLitLists(LIST List1, LIST List2, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: Two sorted lists and of pairs (maxlit,clause) the lists are sorted occording to the max literals of the clauses RETURNS: The merged list ordered with respect to the maximum literals ***************************************************************/ { LIST Scan1, Scan2, Result, ResultStart; if (list_Empty(List1)) return List2; if (list_Empty(List2)) return List1; if (ord_IsSmallerThan(ord_LiteralCompare((TERM)list_PairFirst(list_Car(List1)), ord_UNCOMPARABLE, /* prop literals */ (TERM)list_PairFirst(list_Car(List2)), ord_UNCOMPARABLE, TRUE, Flags, Precedence))) { ResultStart = List1; Scan1 = list_Cdr(List1); Scan2 = List2; } else { ResultStart = List2; Scan1 = List1; Scan2 = list_Cdr(List2); } /* Result is the last element of the merged list. */ Result = ResultStart; while (!list_Empty(Scan1) && !list_Empty(Scan2)) { if (ord_IsSmallerThan(ord_LiteralCompare((TERM)list_PairFirst(list_Car(Scan1)), ord_UNCOMPARABLE, /* prop literals */ (TERM)list_PairFirst(list_Car(Scan2)), ord_UNCOMPARABLE, TRUE, Flags, Precedence))) { list_Rplacd(Result,Scan1); Scan1 = list_Cdr(Scan1); } else { list_Rplacd(Result,Scan2); Scan2 = list_Cdr(Scan2); } Result = list_Cdr(Result); } if (list_Empty(Scan1)) list_Rplacd(Result, Scan2); else list_Rplacd(Result, Scan1); return ResultStart; } LIST clause_MergeSortByMaxLit(LIST L, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A list of pairs (maxlit,clause) a flagstore and precedence maxlit are terms RETURNS: The list sorted with respect the max literals ***************************************************************/ { LIST Result; if (!list_Empty(L) && !list_Empty(list_Cdr(L))) { LIST lowerhalf; LIST greaterhalf; LIST *lowerhalfptr; LIST *greaterhalfptr; lowerhalfptr = &lowerhalf; greaterhalfptr = &greaterhalf; list_Split(L, lowerhalfptr, greaterhalfptr); lowerhalf = clause_MergeSortByMaxLit(lowerhalf, Flags, Precedence); greaterhalf = clause_MergeSortByMaxLit(greaterhalf, Flags, Precedence); Result = clause_MergeMaxLitLists(lowerhalf, greaterhalf, Flags, Precedence); } else { Result = L; } return Result; } BOOL clause_IsPropModelProductive(CLAUSE Clause, HASHMAP hash) /************************************************************** INPUT: A propositional clause and a hash storing true literals; it is assumed that clause has a strictly maximal positive literal and that all smaller literals are decided RETURNS: TRUE iff the clause is productive EFFECTS: None. ***************************************************************/ { int i; for (i=clause_FirstAntecedentLitIndex(Clause);i<=clause_LastAntecedentLitIndex(Clause);i++) if (list_Empty(hm_Retrieve(hash,(POINTER)term_TopSymbol(clause_LiteralAtom(clause_GetLiteral(Clause,i)))))) return FALSE; for (i=clause_FirstSuccedentLitIndex(Clause);i<=clause_LastSuccedentLitIndex(Clause);i++) if (!clause_LiteralIsMaximal(clause_GetLiteral(Clause,i)) && !list_Empty(hm_Retrieve(hash,(POINTER)term_TopSymbol(clause_LiteralAtom(clause_GetLiteral(Clause,i)))))) return FALSE; return TRUE; } LIST clause_ComputePropModel(LIST Clauses, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A saturated, satisfiable, non-redundant (at least using subsumption) list of propositional clases. RETURNS: Returns a list of literals as terms representing the model. EFFECTS: None. ***************************************************************/ { LIST Model,Scan; CLAUSE Clause; TERM Literal; int i; HASHMAP hash; Model = list_Nil(); for(Scan=Clauses;!list_Empty(Scan);Scan=list_Cdr(Scan)) { Clause = list_Car(Scan); for(i=clause_FirstLitIndex();i<=clause_LastLitIndex(Clause);i++) { if (clause_LiteralIsMaximal(clause_GetLiteral(Clause,i))) { /* we are prop so ord is total ! */ Model = list_Cons(list_PairCreate(clause_LiteralSignedAtom(clause_GetLiteral(Clause,i)), Clause), Model); i = clause_LastLitIndex(Clause); } } } Model = clause_MergeSortByMaxLit(Model, Flags, Precedence); /* printf("\n Sorted Clauses:"); */ /* for(Scan=Model;!list_Empty(Scan);Scan=list_Cdr(Scan)) { */ /* printf("\n"); */ /* clause_Print(list_PairSecond(list_Car(Scan))); */ /* } */ Clauses = Model; Model = list_Nil(); hash = hm_Create(4, hm_PointerHash, hm_PointerEqual, FALSE); /* putting an item in hash means its truth value is decided */ Scan = Clauses; while(!list_Empty(Scan)) { Literal = list_PairFirst(list_Car(Scan)); if (fol_IsNegativeLiteral(Literal)) { if (list_Empty(hm_Retrieve(hash, (POINTER)term_TopSymbol(term_FirstArgument(Literal))))) Model = list_Cons(term_Copy(Literal), Model); while(!list_Empty(Scan) && term_Equal(Literal,list_PairFirst(list_Car(Scan)))) Scan = list_Cdr(Scan); } else { while(!list_Empty(Scan) && !clause_IsPropModelProductive(list_PairSecond(list_Car(Scan)), hash) && term_Equal(Literal,list_PairFirst(list_Car(Scan)))) Scan = list_Cdr(Scan); if (!list_Empty(Scan) && clause_IsPropModelProductive(list_PairSecond(list_Car(Scan)), hash)) hm_Insert(hash, (POINTER)term_TopSymbol(Literal), Literal); Model = list_Cons(term_Copy(Literal), Model); while(!list_Empty(Scan) && term_Equal(Literal,list_PairFirst(list_Car(Scan)))) Scan = list_Cdr(Scan); } } list_DeleteWithElement(Clauses, (void (*)(POINTER))list_PairFree); hm_Delete(hash); return Model; } void clause_PrintPropModel(LIST Clauses, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A saturated, satisfiable, non-redundant (at least using subsumption) list of propositional clases. RETURNS: Nothing. EFFECTS: Prints the model with respect to the to . ***************************************************************/ { LIST Model,Scan; TERM Literal; Model = clause_ComputePropModel(Clauses, Flags, Precedence); fputs("SPASS Minimal Model: ", stdout); Scan = Model; while(!list_Empty(Scan)) { Literal = (TERM)list_Car(Scan); if (fol_IsNegativeLiteral(Literal)) { putc('-',stdout); term_PrintPrefix(term_FirstArgument(Literal)); } else term_PrintPrefix(Literal); Scan = list_Cdr(Scan); if (!list_Empty(Scan)) putc(',',stdout); } list_DeleteWithElement(Model, (void (*)(POINTER))term_Delete); } spass-3.9/clause.h000066400000000000000000000647301325017163600141610ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * CLAUSES * */ /* * * */ /* * $Module: CLAUSE * */ /* * * */ /* * 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.15 $ * */ /* $State: Exp $ * */ /* $Date: 2011-11-27 10:57:35 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: clause.h,v $ */ #ifndef _CLAUSE_ #define _CLAUSE_ /**************************************************************/ /* Includes */ /**************************************************************/ #include "sharing.h" #include "foldfg.h" #include "order.h" #include "subst.h" #include "flags.h" #include "symbol.h" #include "hashmap.h" /**************************************************************/ /* Data Structures and Constants */ /**************************************************************/ /* Means weight of literal or clause is undefined */ extern const NAT clause_WEIGHTUNDEFINED; extern int clause_CLAUSECOUNTER; typedef enum {MAXIMAL=1, STRICTMAXIMAL=2, LITSELECT=4} MAXFLAG; typedef enum {CLAUSE_DELETION, EMPTY_SORT, SORT_RESOLUTION, EQUALITY_RESOLUTION, EQUALITY_FACTORING, MERGING_PARAMODULATION, PARAMODULATION, ORDERED_PARAMODULATION, SUPERPOSITION_RIGHT, SUPERPOSITION_LEFT, SIMPLE_HYPER, ORDERED_HYPER, UR_RESOLUTION, GENERAL_RESOLUTION, GENERAL_FACTORING, SPLITTING, INPUTCLAUSE, CONDENSING, ASSIGNMENT_EQUATION_DELETION, OBVIOUS_REDUCTIONS, SORT_SIMPLIFICATION, REWRITING, CONTEXTUAL_REWRITING, MATCHING_REPLACEMENT_RESOLUTION, UNIT_CONFLICT, DEFAPPLICATION, TERMINATOR, TEMPORARY, ORDERED_CHAINING, NEGATIVE_CHAINING, COMPOSITION_RESOLUTION } RULE; typedef unsigned long SPLITFIELDENTRY; typedef SPLITFIELDENTRY* SPLITFIELD; typedef enum {WORKEDOFF=1,CLAUSESELECT=2,DOCCLAUSE=4,CONCLAUSE=8,BLOCKED=16, NOPARAINTO=32, MARKED=64, HIDDEN=128, MARK=256, TRANSAX=512} CLAUSE_FLAGS; /* WORKEDOFF set if it is a worked off clause */ /* MARK is used for marking */ /* TRANSAX means that the clause has the form of transitivity axiom */ /* As there are a lot of implications a clauses properties may have */ /* for the prover, this information should be kept with the clause. */ /* That for a flagfield is foreseen, most likely an integer used */ /* like the sort-Bitfield existing for term, now used for varoccs. */ typedef struct CLAUSE_HELP{ int clausenumber; NAT weight; /* The sum of the weight of all literals */ NAT depth; /* The depth of the clause in the derivation */ NAT validlevel; /* Level of splitting where clause is valid. */ float splitpotential; /* -1 if not splittable, 0 if not tested, k>0 if splittable encoding reduction potential of split at start */ SPLITFIELD splitfield; unsigned splitfield_length; LIST parentCls, parentLits; /* Parents clauses' clause and lit numbers.*/ NAT flags; SYMBOL maxVar; /* The maximal variable symbol in the clause */ struct LITERAL_HELP{ NAT maxLit; /* for clause intern literal ordering */ NAT weight; /* weight of the below */ ord_RESULT ord_stat; /* ordering status for special binary predicates used by chaining */ /* We also encode orientedness of equality predicates here: equality is oriented iff (ord_stat == ord_GREATER_THAN). Note that orienting means switching sides of arguments of equlity when it can be established that (ord_stat == ord_SMALLER_THAN). */ struct CLAUSE_HELP *owningClause; TERM atomWithSign; /* Pointer to the term, where an unshared Term for the sign of negative literals is supplied additionally. */ } **literals; /* An Array of (c+a+s) literalpointers in this order. */ int c; /* number of constraint literals */ int a; /* number of antecedent literals */ int s; /* number of succedent literals */ RULE origin; } *CLAUSE, CLAUSE_NODE; typedef struct LITERAL_HELP *LITERAL, LITERAL_NODE; /**************************************************************/ /* Functions Prototypes */ /**************************************************************/ /**************************************************************/ /* Functions on clauses and literals creation and deletion. */ /**************************************************************/ void clause_Init(void); CLAUSE clause_CreateBody(int); CLAUSE clause_Create(LIST, LIST, LIST, FLAGSTORE, PRECEDENCE); CLAUSE clause_CreateSkolem(LIST, LIST, LIST, FLAGSTORE, PRECEDENCE); CLAUSE clause_CreateCrude(LIST, LIST, LIST, BOOL); CLAUSE clause_CreateUnnormalized(LIST, LIST, LIST); CLAUSE clause_CreateFromLiterals(LIST, BOOL, BOOL, BOOL, FLAGSTORE, PRECEDENCE); CLAUSE clause_CreateFromLiteralLists(LIST, LIST, LIST, BOOL, TERM); void clause_Delete(CLAUSE); LITERAL clause_LiteralCreate(TERM, CLAUSE); LITERAL clause_LiteralCreateNegative(TERM, CLAUSE); /* Unused */ void clause_LiteralDelete(LITERAL); LIST clause_CopyConstraint(CLAUSE); LIST clause_CopyAntecedentExcept(CLAUSE, int); LIST clause_CopySuccedent(CLAUSE); LIST clause_CopySuccedentExcept(CLAUSE, int); /**************************************************************/ /* Functions to use the sharing for clauses and literals. */ /**************************************************************/ void clause_InsertIntoSharing(CLAUSE, SHARED_INDEX, FLAGSTORE, PRECEDENCE); void clause_DeleteFromSharing(CLAUSE, SHARED_INDEX, FLAGSTORE, PRECEDENCE); NAT clause_GetNumberOfInstances(TERM, SHARED_INDEX); void clause_MakeUnshared(CLAUSE, SHARED_INDEX); void clause_MoveSharedClause(CLAUSE, SHARED_INDEX, SHARED_INDEX, FLAGSTORE, PRECEDENCE); void clause_DeleteSharedLiteral(CLAUSE, int, SHARED_INDEX, FLAGSTORE, PRECEDENCE); void clause_LiteralInsertIntoSharing(LITERAL, SHARED_INDEX); void clause_LiteralDeleteFromSharing(LITERAL, SHARED_INDEX); /* Used only in clause.c */ void clause_DeleteClauseList(LIST); void clause_DeleteSharedClauseList(LIST, SHARED_INDEX, FLAGSTORE, PRECEDENCE); void clause_DeleteAllIndexedClauses(SHARED_INDEX, FLAGSTORE, PRECEDENCE); /* Necessary? */ void clause_PrintAllIndexedClauses(SHARED_INDEX); /* For Debugging */ LIST clause_AllIndexedClauses(SHARED_INDEX); /**************************************************************/ /* Clause Comparisons */ /**************************************************************/ BOOL clause_IsHornClause(CLAUSE); int clause_CompareAbstract(CLAUSE, CLAUSE); /**************************************************************/ /* Clause and literal Input and Output Functions */ /**************************************************************/ void clause_Print(CLAUSE); void clause_PrintSpecial(CLAUSE); void clause_PrintSplitfield(CLAUSE, NAT); void clause_PrintSplitfieldOnly(SPLITFIELD, int); void clause_PrintVerbose(CLAUSE, FLAGSTORE, PRECEDENCE); void clause_PrintMaxLitsOnly(CLAUSE, FLAGSTORE, PRECEDENCE); /* For Debugging */ void clause_FPrint(FILE*, CLAUSE); /* For Debugging */ void clause_FPrintRule(FILE*, CLAUSE); void clause_FPrintOtter(FILE*, CLAUSE); /* Unused */ void clause_FPrintCnfDFG(FILE* , BOOL, LIST, LIST, FLAGSTORE, PRECEDENCE); void clause_FPrintCnfDFGProof(FILE* , BOOL, LIST, LIST, FLAGSTORE, PRECEDENCE); void clause_FPrintCnfDFGProblem(FILE* , BOOL, const char*, const char*, const char*, const char*, LIST, LIST, FLAGSTORE, PRECEDENCE, HASHMAP, BOOL, BOOL); void clause_FPrintCnfFormulasDFGProblem(FILE* , BOOL, const char*, const char*, const char*, const char*, LIST, LIST, FLAGSTORE, PRECEDENCE); /* unused */ void clause_FPrintCnfDFGDerivables(FILE*, LIST, BOOL); void clause_FPrintDFG(FILE*, CLAUSE, BOOL); void clause_FPrintDFGProof(FILE*, CLAUSE, BOOL); void clause_FPrintDFGStep(FILE*, CLAUSE, BOOL); void clause_FPrintFormulaDFG(FILE*, CLAUSE, BOOL); void clause_FPrintCnfOtter(FILE*, LIST, FLAGSTORE); void clause_FPrintSettings(FILE*, LIST, LIST, FLAGSTORE, PRECEDENCE, HASHMAP); void clause_LiteralPrint(LITERAL); /* For Debugging */ void clause_LiteralListPrint(LIST); /* For Debugging */ void clause_LiteralPrintUnsigned(LITERAL); /* For Debugging */ void clause_LiteralPrintSigned(LITERAL); /* For Debugging */ void clause_LiteralFPrint(FILE*, LITERAL); /* For Debugging */ void clause_LiteralFPrintUnsigned(FILE*, LITERAL);/* For Debugging */ void clause_ListPrint(LIST); void clause_PrintPropModel(LIST, FLAGSTORE, PRECEDENCE); void clause_PrintParentClauses(CLAUSE); /* For Debugging */ void clause_PrintParentClausesSpecial(CLAUSE); /* For Debugging */ void clause_PrintOrigin(CLAUSE); /* For Debugging */ void clause_FPrintOrigin(FILE*, CLAUSE); /**************************************************************/ /* Specials */ /**************************************************************/ void clause_SetSplitDataFromFather(CLAUSE Result, CLAUSE Father); void clause_SetSplitDataFromList(CLAUSE Result, LIST List); void clause_SetSplitDataFromParents(CLAUSE Result, CLAUSE Mother, CLAUSE Father); void clause_UpdateSplitField(CLAUSE C1, CLAUSE C2); BOOL clause_LiteralIsSort(LITERAL L); TERM clause_LiteralAtom(LITERAL L); CLAUSE clause_Copy(CLAUSE); LITERAL clause_LiteralCopy(LITERAL); LIST clause_CopyClauseList(LIST List); void clause_DeleteLiteral(CLAUSE, int, FLAGSTORE, PRECEDENCE); void clause_DeleteLiteralNN(CLAUSE, int); void clause_DeleteLiterals(CLAUSE, LIST, FLAGSTORE, PRECEDENCE); /* Unused */ LIST clause_GetLiteralSubSetList(CLAUSE, int, int, FLAGSTORE, PRECEDENCE); void clause_ReplaceLiteralSubSet(CLAUSE, int, int, LIST, FLAGSTORE, PRECEDENCE); void clause_FixLiteralOrder(CLAUSE, FLAGSTORE, PRECEDENCE); SYMBOL clause_AtomMaxVar(TERM); void clause_SetMaxLitFlags(CLAUSE, FLAGSTORE, PRECEDENCE); void clause_SetMaxLitFlagsSkolem(CLAUSE, FLAGSTORE, PRECEDENCE); void clause_SetNativeMaxLitFlags(CLAUSE, FLAGSTORE, PRECEDENCE); SYMBOL clause_LiteralMaxVar(LITERAL); /* Used only in clause.c */ SYMBOL clause_SearchMaxVar(CLAUSE); void clause_UpdateMaxVar(CLAUSE); void clause_RenameVarsBiggerThan(CLAUSE, SYMBOL); void clause_Normalize(CLAUSE); void clause_SetSortConstraint(CLAUSE, BOOL, FLAGSTORE, PRECEDENCE); void clause_SubstApply(SUBST, CLAUSE); void clause_ReplaceVariable(CLAUSE, SYMBOL, TERM); void clause_PrecomputeOrdering(CLAUSE, FLAGSTORE, PRECEDENCE); void clause_PrecomputeOrderingSkolem(CLAUSE, FLAGSTORE, PRECEDENCE); NAT clause_NumberOfVarOccs(CLAUSE); NAT clause_NumberOfSymbolOccurrences(CLAUSE, SYMBOL); NAT clause_ComputeWeight(CLAUSE, FLAGSTORE); NAT clause_LiteralComputeWeight(LITERAL, FLAGSTORE); NAT clause_ComputeTermDepth(CLAUSE); NAT clause_MaxTermDepthClauseList(LIST); NAT clause_ComputeSize(CLAUSE); BOOL clause_WeightCorrect(CLAUSE, FLAGSTORE, PRECEDENCE); /* Unused */ LIST clause_MoveBestLiteralToFront(LIST, SUBST, SYMBOL, BOOL (*)(LITERAL, NAT, LITERAL, NAT)); LIST clause_InsertWeighed(CLAUSE, LIST, FLAGSTORE, PRECEDENCE); LIST clause_ListSortWeighed(LIST); BOOL clause_HasTermSortConstraintLits(CLAUSE); BOOL clause_HasOnlySpecDomArgs(CLAUSE); BOOL clause_HasSolvedConstraint(CLAUSE); BOOL clause_HasSelectedLiteral(CLAUSE, FLAGSTORE, PRECEDENCE); BOOL clause_IsDeclarationClause(CLAUSE); BOOL clause_IsSortTheoryClause(CLAUSE, FLAGSTORE, PRECEDENCE); BOOL clause_IsPartOfDefinition(CLAUSE, TERM, intptr_t*, LIST); BOOL clause_IsPotentialSortTheoryClause(CLAUSE, FLAGSTORE, PRECEDENCE); BOOL clause_HasOnlyVarsInConstraint(CLAUSE, FLAGSTORE, PRECEDENCE); BOOL clause_HasSortInSuccedent(CLAUSE, FLAGSTORE, PRECEDENCE); BOOL clause_VarsOfClauseAreInTerm(CLAUSE, TERM); BOOL clause_ContainsPotPredDef(CLAUSE, FLAGSTORE, PRECEDENCE, NAT*, LIST*); BOOL clause_LitsHaveCommonVar(LITERAL, LITERAL); void clause_SelectLiteral(CLAUSE, FLAGSTORE); void clause_SetSpecialFlags(CLAUSE,BOOL, FLAGSTORE, PRECEDENCE); BOOL clause_LiteralIsLiteral(LITERAL); BOOL clause_IsClause(CLAUSE, FLAGSTORE, PRECEDENCE); BOOL clause_IsClauseSkolem(CLAUSE, FLAGSTORE, PRECEDENCE); BOOL clause_IsUnorderedClause(CLAUSE); BOOL clause_ContainsPositiveEquations(CLAUSE); BOOL clause_ContainsNegativeEquations(CLAUSE); int clause_ContainsFolAtom(CLAUSE,BOOL*,BOOL*,BOOL*,BOOL*); BOOL clause_ContainsVariables(CLAUSE); BOOL clause_ContainsFunctions(CLAUSE); BOOL clause_ContainsSymbol(CLAUSE, SYMBOL); void clause_ContainsSortRestriction(CLAUSE,BOOL*,BOOL*); BOOL clause_ImpliesFiniteDomain(CLAUSE); BOOL clause_ImpliesNonTrivialDomain(CLAUSE); LIST clause_FiniteMonadicPredicates(LIST); CLAUSE clause_GetNumberedCl(int, LIST); LIST clause_NumberSort(LIST); LIST clause_NumberDelete(LIST,int); void clause_Check(CLAUSE, FLAGSTORE, PRECEDENCE); void clause_CheckSkolem(CLAUSE, FLAGSTORE, PRECEDENCE); void clause_DeleteFlatFromIndex(CLAUSE, st_INDEX); void clause_InsertFlatIntoIndex(CLAUSE, st_INDEX); void clause_DeleteClauseListFlatFromIndex(LIST, st_INDEX); RULE clause_GetOriginFromString(const char*); void clause_CountSymbols(CLAUSE); LIST clause_ComputePropModel(LIST, FLAGSTORE, PRECEDENCE); LIST clause_ListOfPredicates(CLAUSE); LIST clause_ListOfConstants(CLAUSE); LIST clause_ListOfVariables(CLAUSE); LIST clause_ListOfFunctions(CLAUSE); BOOL clause_LiteralIsStrictMaximalLiteralSkolem(CLAUSE, int, FLAGSTORE, PRECEDENCE); BOOL clause_IsTransitivityAxiomExt(CLAUSE, SYMBOL*, BOOL*); BOOL clause_IsIrreflexivityAxiomExt(CLAUSE, SYMBOL*); BOOL clause_IsTotalityAxiomExt(CLAUSE, SYMBOL*); BOOL clause_IsTransitivityAxiom(CLAUSE Clause); /* special output functions for clauses with parent pointers */ void clause_PParentsFPrint(FILE*, CLAUSE); void clause_PParentsListFPrint(FILE*, LIST L); void clause_PParentsPrint(CLAUSE); void clause_PParentsListPrint(LIST); void clause_PParentsFPrintGen(FILE*, CLAUSE, BOOL); /**************************************************************/ /* Inline Functions */ /**************************************************************/ /**************************************************************/ /* Accessing Literals 1 */ /**************************************************************/ TERM clause_LiteralSignedAtom(LITERAL L); CLAUSE clause_LiteralOwningClause(LITERAL L); void clause_LiteralSetOwningClause(LITERAL L, CLAUSE C); void clause_LiteralSetOrderStatus(LITERAL L, ord_RESULT OS); ord_RESULT clause_LiteralGetOrderStatus(LITERAL L); NAT clause_LiteralWeight(LITERAL L); void clause_UpdateLiteralWeight(LITERAL L, FLAGSTORE Flags); void clause_LiteralFlagReset(LITERAL L); void clause_LiteralFlagResetAndKeepSelFlag(LITERAL L); BOOL clause_LiteralGetFlag(LITERAL L, MAXFLAG Flag); void clause_LiteralSetFlag(LITERAL L, MAXFLAG Flag); void clause_LiteralClearFlag(LITERAL L, MAXFLAG Flag); BOOL clause_LiteralIsMaximal(LITERAL L); BOOL clause_LiteralIsOrientedEquality(LITERAL L); BOOL clause_LiteralIsNotOrientedEquality(LITERAL L); /**************************************************************/ /* Literal Comparison 1 */ /**************************************************************/ BOOL clause_LiteralIsNegative(LITERAL L); BOOL clause_LiteralIsPositive(LITERAL L); BOOL clause_LiteralsAreComplementary(LITERAL L1, LITERAL L2); BOOL clause_HyperLiteralIsBetter(LITERAL Dummy1, NAT S1, LITERAL Dummy2, NAT S2); /**************************************************************/ /* Accessing Literals 2 */ /**************************************************************/ SYMBOL clause_LiteralPredicate(LITERAL L); BOOL clause_LiteralIsPredicate(LITERAL L); BOOL clause_LiteralIsEquality(LITERAL L); void clause_LiteralSetAtom(LITERAL L, TERM A); void clause_LiteralSetNegAtom(LITERAL L, TERM A); void clause_LiteralSetPosAtom(LITERAL L, TERM A); void clause_NLiteralSetLiteral(LITERAL L, TERM LIT); /**************************************************************/ /* Memory management */ /**************************************************************/ void clause_LiteralFree(LITERAL L); /**************************************************************/ /* Functions to access literals. */ /**************************************************************/ LITERAL clause_GetLiteral(CLAUSE C, intptr_t Index); void clause_SetLiteral(CLAUSE C, int Index, LITERAL L); TERM clause_GetLiteralTerm(CLAUSE C, int Index); TERM clause_GetLiteralAtom(CLAUSE C, intptr_t Index); int clause_NumOfConsLits(CLAUSE Clause); int clause_NumOfAnteLits(CLAUSE Clause); int clause_NumOfSuccLits(CLAUSE Clause); void clause_SetNumOfConsLits(CLAUSE Clause, int Number); void clause_SetNumOfAnteLits(CLAUSE Clause, int Number); void clause_SetNumOfSuccLits(CLAUSE Clause, int Number); int clause_Length(CLAUSE Clause); int clause_LastLitIndex(CLAUSE Clause); intptr_t clause_FirstLitIndex(void); int clause_FirstConstraintLitIndex(CLAUSE Clause); intptr_t clause_FirstAntecedentLitIndex(CLAUSE Clause); intptr_t clause_FirstSuccedentLitIndex(CLAUSE Clause); int clause_LastConstraintLitIndex(CLAUSE Clause); int clause_LastAntecedentLitIndex(CLAUSE Clause); int clause_LastSuccedentLitIndex(CLAUSE Clause); LIST clause_GetLiteralList(CLAUSE Clause); LIST clause_GetLiteralListExcept(CLAUSE Clause, int Index); /**************************************************************/ /* Clause Access Macros */ /**************************************************************/ int clause_Counter(void); void clause_SetCounter(int Value); int clause_IncreaseCounter(void); void clause_DecreaseCounter(void); NAT clause_Depth(CLAUSE Clause); void clause_SetDepth(CLAUSE Clause, NAT NewDepth); NAT clause_Weight(CLAUSE Clause); void clause_UpdateWeight(CLAUSE Clause, FLAGSTORE Flags); float clause_SplitPotential(CLAUSE Clause); void clause_SetSplitPotential(CLAUSE Clause, float pot); intptr_t clause_Number(const CLAUSE Clause); void clause_SetNumber(CLAUSE Clause, int Number); void clause_NewNumber(CLAUSE Clause); NAT clause_SplitLevel(CLAUSE Clause); BOOL clause_CheckSplitLevel(CLAUSE Clause); NAT clause_SplitLevelDependencies(CLAUSE Clause); LIST clause_ParentClauses(CLAUSE Clause); LIST clause_ParentLiterals(CLAUSE Clause); SYMBOL clause_MaxVar(CLAUSE Clause); void clause_SetMaxVar(CLAUSE Clause, SYMBOL Variable); RULE clause_Origin(CLAUSE Clause); BOOL clause_Exists(CLAUSE Clause); BOOL clause_LiteralExists(LITERAL L); CLAUSE clause_Null(void); void clause_SetSplitLevel(CLAUSE Clause, NAT Level); void clause_InitSplitData(CLAUSE C); void clause_SetSplitField(CLAUSE Clause, SPLITFIELD B, unsigned Length); NAT clause_ComputeSplitFieldAddress(NAT n, NAT* field); void clause_ExpandSplitField(CLAUSE C, NAT Length); void clause_ClearSplitField(CLAUSE C); void clause_SetSplitFieldBit(CLAUSE Clause, NAT n); BOOL clause_GetFlag(CLAUSE Clause, CLAUSE_FLAGS Flag); void clause_SetFlag(CLAUSE Clause, CLAUSE_FLAGS Flag); void clause_RemoveFlag(CLAUSE Clause, CLAUSE_FLAGS Flag); void clause_ClearFlags(CLAUSE Clause); BOOL clause_DependsOnSplitLevel(CLAUSE C, NAT N); void clause_UpdateSplitDataFromNewSplitting(CLAUSE Result, CLAUSE Father, NAT Level); void clause_UpdateSplitDataFromPartner(CLAUSE Result, CLAUSE Partner); void clause_SetParentClauses(CLAUSE Clause, LIST PClauses); void clause_AddParentClause(CLAUSE Clause, intptr_t PClause); void clause_SetParentLiterals(CLAUSE Clause, LIST PLits); void clause_AddParentLiteral(CLAUSE Clause, intptr_t PLit); BOOL clause_ValidityIsNotSmaller(CLAUSE C1, CLAUSE C2); BOOL clause_IsMoreValid(CLAUSE C1, CLAUSE C2); BOOL clause_CompareAbstractLEQ (CLAUSE Left, CLAUSE Right); BOOL clause_IsFromRewriting(CLAUSE Clause); BOOL clause_IsFromCondensing(CLAUSE Clause); BOOL clause_IsFromObviousReductions(CLAUSE Clause); BOOL clause_IsFromSortSimplification(CLAUSE Clause); BOOL clause_IsFromMatchingReplacementResolution(CLAUSE Clause); BOOL clause_IsFromClauseDeletion(CLAUSE Clause); BOOL clause_IsFromEmptySort(CLAUSE Clause); BOOL clause_IsFromSortResolution(CLAUSE Clause); BOOL clause_IsFromUnitConflict(CLAUSE Clause); BOOL clause_IsFromEqualityResolution(CLAUSE Clause); BOOL clause_IsFromEqualityFactoring(CLAUSE Clause); BOOL clause_IsFromMergingParamodulation(CLAUSE Clause); BOOL clause_IsFromSuperpositionRight(CLAUSE Clause); BOOL clause_IsFromSuperpositionLeft(CLAUSE Clause); BOOL clause_IsFromGeneralResolution(CLAUSE Clause); BOOL clause_IsFromGeneralFactoring(CLAUSE Clause); BOOL clause_IsFromSplitting(CLAUSE Clause); BOOL clause_IsFromDefApplication(CLAUSE Clause); BOOL clause_IsFromTerminator(CLAUSE Clause); BOOL clause_IsTemporary(CLAUSE Clause); BOOL clause_IsFromInput(CLAUSE Clause); BOOL clause_IsFromOrderedChaining(CLAUSE Clause); BOOL clause_IsFromNegativeChaining(CLAUSE Clause); BOOL clause_IsFromCompositionResolution(CLAUSE Clause); BOOL clause_HasReducedPredecessor(CLAUSE Clause); BOOL clause_IsSplitFather(CLAUSE C1, CLAUSE C2); void clause_SetFromRewriting(CLAUSE Clause); void clause_SetFromContextualRewriting(CLAUSE Clause); void clause_SetFromUnitConflict(CLAUSE Clause); void clause_SetFromCondensing(CLAUSE Clause); void clause_SetFromAssignmentEquationDeletion(CLAUSE Clause); void clause_SetFromObviousReductions(CLAUSE Clause); void clause_SetFromSortSimplification(CLAUSE Clause); void clause_SetFromMatchingReplacementResolution(CLAUSE Clause); void clause_SetFromClauseDeletion(CLAUSE Clause); void clause_SetFromEmptySort(CLAUSE Clause); void clause_SetFromSortResolution(CLAUSE Clause); void clause_SetFromEqualityResolution(CLAUSE Clause); void clause_SetFromEqualityFactoring(CLAUSE Clause); void clause_SetFromMergingParamodulation(CLAUSE Clause); void clause_SetFromParamodulation(CLAUSE Clause); void clause_SetFromOrderedParamodulation(CLAUSE Clause); void clause_SetFromSuperpositionRight(CLAUSE Clause); void clause_SetFromSuperpositionLeft(CLAUSE Clause); void clause_SetFromGeneralResolution(CLAUSE Clause); void clause_SetFromOrderedHyperResolution(CLAUSE Clause); void clause_SetFromSimpleHyperResolution(CLAUSE Clause); void clause_SetFromURResolution(CLAUSE Clause); void clause_SetFromGeneralFactoring(CLAUSE Clause); void clause_SetFromSplitting(CLAUSE Clause); void clause_SetFromDefApplication(CLAUSE Clause); void clause_SetFromTerminator(CLAUSE Clause); void clause_SetTemporary(CLAUSE Clause); void clause_SetFromOrderedChaining(CLAUSE Clause); void clause_SetFromNegativeChaining(CLAUSE Clause); void clause_SetFromCompositionResolution(CLAUSE Clause); void clause_SetFromInput(CLAUSE Clause); LITERAL clause_FirstConstraintLit(CLAUSE Clause); LITERAL clause_FirstAntecedentLit(CLAUSE Clause); LITERAL clause_FirstSuccedentLit(CLAUSE Clause); LITERAL clause_LastConstraintLit(CLAUSE Clause); LITERAL clause_LastAntecedentLit(CLAUSE Clause); LITERAL clause_LastSuccedentLit(CLAUSE Clause); BOOL clause_HasEmptyConstraint(CLAUSE Clause); BOOL clause_HasEmptyAntecedent(CLAUSE Clause); BOOL clause_HasEmptySuccedent(CLAUSE Clause); BOOL clause_IsGround(CLAUSE Clause); BOOL clause_IsEmptyClause(CLAUSE C); intptr_t clause_LiteralGetIndex(LITERAL L); BOOL clause_LiteralIsFromConstraint(LITERAL Literal); BOOL clause_LiteralIsFromAntecedent(LITERAL Literal); BOOL clause_LiteralIsFromSuccedent(LITERAL Literal); BOOL clause_IsSimpleSortClause(CLAUSE Clause); BOOL clause_IsSubsortClause(CLAUSE Clause); BOOL clause_HasSuccLits(CLAUSE Clause); BOOL clause_HasGroundSuccLit(CLAUSE Clause); LITERAL clause_GetGroundSuccLit(CLAUSE Clause); void clause_Free(CLAUSE Clause); void clause_ReInit(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence); void clause_ReInitSkolem(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence); void clause_PrecomputeOrderingAndReInit(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence); void clause_PrecomputeOrderingAndReInitSkolem(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence); void clause_SetDataFromFather(CLAUSE Result, CLAUSE Father, int i, FLAGSTORE Flags, PRECEDENCE Precedence); void clause_SetDataFromParents(CLAUSE, CLAUSE, int, CLAUSE, int, FLAGSTORE, PRECEDENCE); SPLITFIELD clause_GetSplitfield(CLAUSE, unsigned *); #endif spass-3.9/clock.c000066400000000000000000000152541325017163600137700ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * CLOCK * */ /* * * */ /* * $Module: CLOCK * */ /* * * */ /* * Copyright (C) 1996, 1999, 2000, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.5 $ * */ /* $State: Exp $ * */ /* $Date: 2011-05-22 11:47:55 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: clock.c,v $ */ #include "clock.h" /**************************************************************/ /* Global Variables */ /**************************************************************/ float clock_Akku[clock_TYPESIZE]; CLOCK_TMS clock_Counters[clock_TYPESIZE]; /**************************************************************/ /* Functions */ /**************************************************************/ void clock_Init(void) /********************************************************* INPUT: None. EFFECT: Initializes the clock Module. RETURNS: None. MEMORY: None. **********************************************************/ { int i; for (i=0;i is initialized. RETURNS: None. MEMORY: None. **********************************************************/ { clock_Akku[ClockCounter] = 0; } void clock_StartCounter(CLOCK_CLOCKS ClockCounter) /********************************************************* INPUT: A clock counter. EFFECT: The clock counter is started. RETURNS: None. MEMORY: None. **********************************************************/ { #ifndef CLOCK_NO_TIMING gettimeofday(&(clock_Counters[ClockCounter]), NULL); #endif /* CLOCK_NO_TIMING */ } void clock_StopPassedTime(CLOCK_CLOCKS ClockCounter) /********************************************************* INPUT: A clock counter. EFFECT: Stores the number of seconds passed since given counter was started in the according accumulator. RETURNS: None. MEMORY: None. **********************************************************/ { #ifndef CLOCK_NO_TIMING CLOCK_TMS newtime; gettimeofday(&newtime, NULL); clock_Akku[ClockCounter] = clock_GetSeconds(ClockCounter); #endif } void clock_StopAddPassedTime(CLOCK_CLOCKS ClockCounter) /********************************************************* INPUT: A clock counter. EFFECT: Adds the number of seconds passed since given counter was started to the according accumulator. RETURNS: None. MEMORY: None. **********************************************************/ { #ifndef CLOCK_NO_TIMING CLOCK_TMS newtime; gettimeofday(&newtime, NULL); clock_Akku[ClockCounter] += clock_GetSeconds(ClockCounter); #endif } float clock_GetAkku(CLOCK_CLOCKS ClockCounter) /********************************************************* INPUT: A clock counter. EFFECT: None. RETURNS: The akkumulated number of seconds stored by the counter as a float. **********************************************************/ { return clock_Akku[ClockCounter]; } float clock_GetSeconds(CLOCK_CLOCKS ClockCounter) /********************************************************* INPUT: A clock counter. EFFECT: Computes the number of seconds spent by the counter. RETURNS: The number of seconds spent by the counter as a float. MEMORY: None. **********************************************************/ { #ifndef CLOCK_NO_TIMING CLOCK_TMS newtime; time_t seconds_passed; long microseconds_passed; gettimeofday(&newtime, NULL); seconds_passed = newtime.tv_sec - clock_Counters[ClockCounter].tv_sec; microseconds_passed = newtime.tv_usec - clock_Counters[ClockCounter].tv_usec; return ((float) seconds_passed + (microseconds_passed /(float)1000000)); #else /* CLOCK_NO_TIMING */ return 0; #endif /* ! CLOCK_NO_TIMING */ } void clock_PrintTime(CLOCK_CLOCKS ClockCounter) /********************************************************* INPUT: A clock counter. EFFECT: The time is printed in format hh:mm:ss.dd to stdout RETURNS: None. MEMORY: None. **********************************************************/ { #ifndef CLOCK_NO_TIMING NAT hours, minutes; float seconds; seconds = clock_Akku[ClockCounter]; hours = (NAT)seconds/3600; seconds -= hours*3600; minutes = (NAT)seconds/60; seconds -= (minutes*60); if (seconds >= 10.0) printf("%zu:%0zu:%2.2f",hours,minutes,seconds); else printf("%zu:%02zu:0%2.2f",hours,minutes,seconds); #else fputs(" No Timing on this machine. ",stdout); #endif } spass-3.9/clock.h000066400000000000000000000057621325017163600140000ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * CLOCK * */ /* * * */ /* * $Module: CLOCK * */ /* * * */ /* * Copyright (C) 1996, 1997, 1999, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.6 $ * */ /* $State: Exp $ * */ /* $Date: 2011-05-22 11:47:56 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: clock.h,v $ */ #ifndef _CLOCK_ #define _CLOCK_ #include "gettimeofday.h" #include "misc.h" #include #include #include typedef enum { clock_BACKTRACK, clock_OVERALL, clock_INPUT, clock_CNF, clock_CNFREDUCTION, clock_REDUCTION, clock_INFERENCE, clock_TRANSL, clock_TYPESIZE } CLOCK_CLOCKS; typedef struct timeval CLOCK_TMS; void clock_Init(void); void clock_InitCounter(CLOCK_CLOCKS); void clock_StartCounter(CLOCK_CLOCKS); void clock_StopPassedTime(CLOCK_CLOCKS); void clock_StopAddPassedTime(CLOCK_CLOCKS); float clock_GetSeconds(CLOCK_CLOCKS); float clock_GetAkku(CLOCK_CLOCKS); void clock_PrintTime(CLOCK_CLOCKS); #endif spass-3.9/closure.c000066400000000000000000000322701325017163600143460ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * CONGRUENCE CLOSURE ALGORITHM * */ /* * * */ /* * $Module: CLOSURE * */ /* * * */ /* * Copyright (C) 1999, 2000, 2001 MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.3 $ * */ /* $State: Exp $ * */ /* $Date: 2011-05-22 11:56:21 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /**************************************************************/ /* Include */ /**************************************************************/ #include "closure.h" /**************************************************************/ /* Global constants and variable */ /**************************************************************/ /* standard initial size of a closure's stacks */ static const int cc_RASSTDSIZE = 64; /* cc_RASSTDSIZE * ld(cc_RASSTDSIZE) */ static const int cc_SIZELDSIZE = 384; /* the virtual term "true" has number 0 */ static const ELEMENT cc_NOOFTRUE = 0; static struct { PARTITION partition; TABLE table; RAS car, cdr, size, pending, combine; } cc_CLOSURE; /* the closure consists of a partition, a signature table, stacks for */ /* (circularly linked) lists of predecessors of equivalence classes (i. e. */ /* terms with direct subterms from this class), for the sizes of these lists, */ /* for pending terms (the ones to be worked off) and for terms to be combined */ /* in the same equivalence class */ /**************************************************************/ /* Inline functions */ /**************************************************************/ PARTITION cc_GetPartition(void) { return cc_CLOSURE.partition; } void cc_SetPartition(PARTITION partition) { cc_CLOSURE.partition = partition; } TABLE cc_GetTable(void) { return cc_CLOSURE.table; } void cc_SetTable(TABLE table) { cc_CLOSURE.table = table; } RAS cc_GetCars(void) { return cc_CLOSURE.car; } TERM cc_GetCar(int stack_index) { return (TERM) ras_Get(cc_GetCars(), stack_index); } void cc_SetCars(RAS car) { cc_CLOSURE.car = car; } RAS cc_GetCdrs(void) { return cc_CLOSURE.cdr; } intptr_t cc_GetCdr(int stack_index) { return (intptr_t) ras_Get(cc_GetCdrs(), stack_index); } void cc_SetCdrs(RAS cdr) { cc_CLOSURE.cdr = cdr; } void cc_SetCdr(int stack_index, intptr_t cdr) { ras_Set(cc_GetCdrs(), stack_index, (POINTER)cdr); } RAS cc_GetSizes(void) { return cc_CLOSURE.size; } intptr_t cc_GetSize(int stack_index) { return (intptr_t) ras_Get(cc_GetSizes(), stack_index); } void cc_SetSizes(RAS size) { cc_CLOSURE.size = size; } void cc_SetSize(int stack_index, intptr_t size) { ras_Set(cc_GetSizes(), stack_index, (POINTER)size); } RAS cc_GetPending(void) { return cc_CLOSURE.pending; } void cc_SetPending(RAS pending) { cc_CLOSURE.pending = pending; } RAS cc_GetCombine(void) { return cc_CLOSURE.combine; } void cc_SetCombine(RAS combine) { cc_CLOSURE.combine = combine; } /**************************************************************/ /* Functions */ /**************************************************************/ static int cc_Number(int actno, TERM term, TERM pred) /*************************************************************** INPUT: the actual number of terms, the term to be numbered and its predecessor (may be the empty term term_Null()) RETURNS: the new number of terms after recursively numbering the term and its subterms EFFECT: stores a term's number as its size, partially initializes its predecessor list and pushes all subterms to the pending stack ***************************************************************/ { LIST terms; #ifdef CHECK if (actno < 0) { misc_StartErrorReport(); misc_ErrorReport("\n In cc_Number: negative actual number of terms."); misc_FinishErrorReport(); } #endif term_SetSize(term, actno++); cc_SetCars(ras_Push(cc_GetCars(), pred)); cc_SetPending(ras_Push(cc_GetPending(), term)); for (terms = term_ArgumentList(term); !list_Empty(terms); terms = list_Cdr(terms)) actno = cc_Number(actno, list_Car(terms), term); return actno; } static void cc_Union(ECLASS c1, ECLASS c2) /*************************************************************** EFFECT: unions c1 and c2, therefore the signatures of the predecessors of one class change, so these predecessors have to be deleted from the signature table and become pending again; sets new class's predecessor list and its size to the concatenation of the old lists resp. the sum of the old sizes ***************************************************************/ { int aux, size; TERM term; #ifdef CHECK if (part_Find(cc_GetPartition(), c1) != c1) { misc_StartErrorReport(); misc_ErrorReport("\n In cc_Union: first class corrupted, i. e. is not "); misc_ErrorReport("the representative."); misc_FinishErrorReport(); } if (part_Find(cc_GetPartition(), c2) != c2) { misc_StartErrorReport(); misc_ErrorReport("\n In cc_Union: second class corrupted, i. e. is not "); misc_ErrorReport("the representative."); misc_FinishErrorReport(); } #endif if (c1 != c2) { /* make c1 the class with the bigger (or at least not smaller) list: */ if (cc_GetSize(c1) < cc_GetSize(c2)) { aux = c1; c1 = c2; c2 = aux; } /* delete c2's predecessors from signature table and add them to pending: */ for (size = cc_GetSize(c2), aux = c2; size > 0; size--) { term = cc_GetCar(aux); aux = cc_GetCdr(aux); table_Delete(cc_GetTable(), term); cc_SetPending(ras_Push(cc_GetPending(), term)); } if (cc_GetSize(c2) > 0) { /* then GetSize(c1) ( >= GetSize(c2) ) > 0 too */ /* union circularly linked lists by exchanging cdrs: */ aux = cc_GetCdr(c1); cc_SetCdr(c1, cc_GetCdr(c2)); cc_SetCdr(c2, aux); cc_SetSize(c1, cc_GetSize(c1) + cc_GetSize(c2)); } part_Union(cc_GetPartition(), c1, c2); } } static void cc_InitData(CLAUSE clause) /*************************************************************** INPUT: the clause to investigate EFFECT: pushes clause's atoms and their subterms on the pending stack, initializes each predecessor list with the list containing only a term's father, and unions the equivalence classes of the terms of the same antecedent equation ***************************************************************/ { int last, actno,ld; intptr_t i; TERM atom; RAS cdr, size; cc_SetCars(ras_InitWithSize(cc_GetCars(), cc_RASSTDSIZE)); cc_SetPending(ras_InitWithSize(cc_GetPending(), cc_RASSTDSIZE)); ras_FastPush(cc_GetCars(), term_Null()); /* "true" has no predecessors */ actno = 1; last = clause_LastLitIndex(clause); for (i = clause_FirstLitIndex(); i <= last; i++) { atom = clause_GetLiteralAtom(clause, i); if (fol_IsEquality(atom)) { actno = cc_Number(actno, term_FirstArgument(atom), term_Null()); actno = cc_Number(actno, term_SecondArgument(atom), term_Null()); } else actno = cc_Number(actno, atom, term_Null()); } cc_SetPartition(part_Init(cc_GetPartition(), actno)); cc_SetTable(table_Init(cc_GetTable(), symbol_ActIndex() - 1, clause_MaxVar(clause), actno - 1)); cdr = ras_InitWithSize(cc_GetCdrs(), actno); size = ras_InitWithSize(cc_GetSizes(), actno); for (i = 0; i < actno; i++) { ras_FastPush(cdr, (POINTER) i); /* form a cycle */ ras_FastPush(size, (POINTER)(cc_GetCar(i) == term_Null()? (intptr_t)0 : (intptr_t)1)); } cc_SetCdrs(cdr); cc_SetSizes(size); /* compute ceil(ld(actno)) avoiding mathbib-logarithm's rounding errors: */ for (ld = 0, i = actno - 1; i > 0; i >>= 1) ld++; cc_SetCombine(ras_InitWithSize(cc_GetCombine(), actno * ld + 1)); /* for every antecedent equation union equivalence classes of its terms */ /* (a non-equational atom is represented as the equation atom = "true"): */ last = clause_LastAntecedentLitIndex(clause); for (i = clause_FirstLitIndex(); i <= last; i++) { atom = clause_GetLiteralAtom(clause, i); if (fol_IsEquality(atom)) cc_Union(term_Size(term_FirstArgument(atom)), /* clause not shared, therefore */ term_Size(term_SecondArgument(atom))); /* here no cc_Find needed */ else cc_Union(term_Size(atom), part_Find(cc_GetPartition(), cc_NOOFTRUE)); } } static BOOL cc_Outit(CLAUSE clause) /*************************************************************** RETURNS: the decision, if the clause is a tautology ***************************************************************/ { int last, i; BOOL result; TERM atom; #ifdef CHECK if (!ras_Empty(cc_GetPending())) { misc_StartErrorReport(); misc_ErrorReport("\n In cc_Outit: there are terms left to work off."); misc_FinishErrorReport(); } #endif last = clause_LastLitIndex(clause); for (i = clause_FirstSuccedentLitIndex(clause), result = FALSE; i <= last && !result; i++) { atom = clause_GetLiteralAtom(clause, i); if (fol_IsEquality(atom)) result = part_Equivalent(cc_GetPartition(), term_Size(term_FirstArgument(atom)), term_Size(term_SecondArgument(atom))); else result = part_Equivalent(cc_GetPartition(), term_Size(atom), cc_NOOFTRUE); } return result; } /**************************************************************/ /* Main functions */ /**************************************************************/ void cc_Init(void) { cc_SetPartition(part_Create(cc_RASSTDSIZE)); cc_SetTable(table_Create(cc_RASSTDSIZE, cc_RASSTDSIZE, cc_RASSTDSIZE)); cc_SetCars(ras_CreateWithSize(cc_RASSTDSIZE)); cc_SetCdrs(ras_CreateWithSize(cc_RASSTDSIZE)); cc_SetSizes(ras_CreateWithSize(cc_RASSTDSIZE)); cc_SetPending(ras_CreateWithSize(cc_RASSTDSIZE)); cc_SetCombine(ras_CreateWithSize(cc_SIZELDSIZE)); } void cc_Free(void) { part_Free(cc_GetPartition()); table_Free(cc_GetTable()); ras_Free(cc_GetCars()); ras_Free(cc_GetCdrs()); ras_Free(cc_GetSizes()); ras_Free(cc_GetPending()); ras_Free(cc_GetCombine()); } BOOL cc_Tautology(CLAUSE clause) /*************************************************************** INPUT: the clause to test RETURNS: the decision, if the clause - where all variables are regarded as skolem constants - is a tautology, using the congruence closure algorithm of Downey, Sethi and Tarjan CAUTION: overrides the sizes of the clause's terms ***************************************************************/ { TERM term, query; cc_InitData(clause); while (!ras_Empty(cc_GetPending())) { /* propagate the closure: */ while (!ras_Empty(cc_GetPending())) { term = ras_Pop(cc_GetPending()); query = table_QueryAndEnter(cc_GetTable(), cc_GetPartition(), term); if (query != term_Null()) { ras_FastPush(cc_GetCombine(), term); ras_FastPush(cc_GetCombine(), query); } } while (!ras_Empty(cc_GetCombine())) cc_Union(part_Find(cc_GetPartition(), term_Size(ras_Pop(cc_GetCombine()))), part_Find(cc_GetPartition(), term_Size(ras_Pop(cc_GetCombine())))); } return cc_Outit(clause); } spass-3.9/closure.h000066400000000000000000000054311325017163600143520ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * CONGRUENCE CLOSURE ALGORITHM * */ /* * * */ /* * $Module: CLOSURE * */ /* * * */ /* * Copyright (C) 1999, 2000, 2001 MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.2 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:57 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ #ifndef _CLOSURE_ #define _CLOSURE_ /**************************************************************/ /* Includes */ /**************************************************************/ #include "clause.h" #include "table.h" #include "ras.h" /**************************************************************/ /* Prototype */ /**************************************************************/ void cc_Init(void); void cc_Free(void); BOOL cc_Tautology(CLAUSE); #endif spass-3.9/cmdline.c000066400000000000000000000320051325017163600143010ustar00rootroot00000000000000 /**************************************************************/ /* ********************************************************** */ /* * * */ /* * COMMAND LINE PARSER * */ /* * * */ /* * $Module: CMDLNE * */ /* * * */ /* * Copyright (C) 1996, 1997, 1998, 1999, 2000 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.5 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:57 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: cmdline.c,v $ */ /***************************************************************/ #include "cmdline.h" /**************************************************************/ /* Local variables and types */ /**************************************************************/ const char* cmdlne_InputFile; const char* cmdlne_OutputFile; static LIST cmdlne_ArgumentsList; /**************************************************************/ /* Functions */ /**************************************************************/ void cmdlne_Init() /************************************************************** INPUT: NONE RETURNS: Nothing. EFFECT: Initializes command line module ***************************************************************/ { cmdlne_InputFile = (char*)NULL; cmdlne_OutputFile = (char*)NULL; cmdlne_ArgumentsList = NULL; } void cmdlne_PrintSPASSNames() /************************************************************** INPUT: None RETURNS: Nothing EFFECT: Prints all options in three rows ***************************************************************/ { int i,j; for (i=0; i < flag_GetMaxFlag(); i=i+4) { for (j =0; j <=3; j++) if (i+j < flag_GetMaxFlag() && !flag_IsUndefined(i+j)) { printf("%-18s ", flag_Name(i+j)); } putchar('\n'); } } void cmdlne_FreePair(LIST Pair) /*************************************************************** INPUT: a Pair RETURNS: Nothing. EFFECT: Free the Pair and its elements. ********************* ******************************************/ { string_StringFree(list_PairFirst(Pair)); string_StringFree(list_PairSecond(Pair)); list_PairFree(Pair); } void cmdlne_Free() /**************************************************************** INPUT: NONE RETURNS: Nothing. EFFECT: Free memory of module ***************************************************************/ { list_DeleteWithElement(cmdlne_ArgumentsList, (void (*) (POINTER)) cmdlne_FreePair); } const char* cmdlne_GetInputFile() /**************************************************************** INPUT: None RETURNS: Pointer to the name of input file ****************************************************************/ { return cmdlne_InputFile; } const char* cmdlne_GetOutputFile() /**************************************************************** INPUT: None RETURNS: Pointer to the name of output file *****************************************************************/ { return cmdlne_OutputFile; } BOOL cmdlne_SetFlags(FLAGSTORE flagstore) /**************************************************************** INPUT: a FLAGSTORE RETURNS: TRUE if all arguments of are valid arguments and the respective flags of could be set and FALSE otherwise. EFFECT: Set flags of according to arguments stored in *****************************************************************/ { int id, tk; LIST Scan; BOOL found; for(Scan=cmdlne_ArgumentsList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { found = FALSE; for (id=0; id < flag_GetMaxFlag() && !found; id++) { if (!flag_IsUndefined(id) && string_Equal(flag_Name(id), (char*) list_PairFirst(list_Car(Scan))) ) { if (flag_IsOfValueType(id, flag_INTEGER)) { if(!string_StringIsInteger(list_PairSecond(list_Car(Scan)))){ misc_StartUserErrorReport(); misc_UserErrorReport("\nError: Argument of option %s must be an integer.\n\n", flag_Name(id)); misc_FinishUserErrorReport(); return FALSE; } tk = atoi((char*) list_PairSecond(list_Car(Scan))); flag_SetFlagIntValue(flagstore, id, tk); } else { if (!flag_ValueIsClean(flagstore, id) && flag_GetFlagStringValue(flagstore, id) != (char *) NULL) string_StringFree(flag_GetFlagStringValue(flagstore, id)); flag_SetFlagStringValue(flagstore, id, string_StringCopy((char*)list_PairSecond(list_Car(Scan)))); } found = TRUE; } } if(!found) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Unrecognized option %s\n\n", (char*) list_PairFirst(list_Car(Scan))); misc_FinishUserErrorReport(); return FALSE; } } return TRUE; } BOOL cmdlne_SetArgument(const char* token, const char* value) /************************************************************** INPUT: two pointers RETURNS: TRUE if the argument has not been added to the list of arguments before and FALSE otherwise. EFFECT: Adds argument with value to list of arguments () CAUTION: has to be a character pointer pointing to a string representing an integer ***************************************************************/ { LIST Pair; LIST Scan; /* Check if Argument has already been defined */ for(Scan=cmdlne_ArgumentsList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { if(string_Equal(list_PairFirst(list_Car(Scan)),token)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Option %s is multiply defined.\n\n", token); misc_FinishUserErrorReport(); return FALSE; } } /* Add to argument list with value */ Pair = list_PairCreate(string_StringCopy(token), string_StringCopy(value)); cmdlne_ArgumentsList = list_Cons(Pair, cmdlne_ArgumentsList); return TRUE; } BOOL cmdlne_HandleShortArg(TOKEN token) /****************************************************************** INPUT: FLAGSTORE, a TOKEN RETURNS: TRUE if a flag with name exists in . FALSE otherwise EFFECT: Adds argument with default value to list of arguments *******************************************************************/ { return cmdlne_SetArgument(token, cmdlne_DEFAULTARGVALUE); } BOOL cmdlne_HandleArg(TOKEN token1, TOKEN token2) /***************************************************************** INPUT: FLAGSTORE, two TOKEN's RETURNS: TRUE if a flag with name exists in FALSE otherwise EFFECT: Adds argument with name and value to list of agrguments. CAUTION: cmdlne_HandleArg assumes that is the representation of an integer ******************************************************************/ { return cmdlne_SetArgument(token1, token2); } BOOL cmdlne_isArgSym(const char c) /***************************************************************** INPUT: a char constant RETURNS: TRUE if is a character symbol allowed to occur in a string argument of a commandline option ****************************************************************/ { if(isalnum(c)|| c == '.' || c == '-' || c == '+' || c == '/' || c == '\\' || c == '_') { return TRUE; } else return FALSE; } BOOL cmdlne_LexScan(const char* string) /***************************************************************** INPUT: FLAGSTORE, a string containing program parameter data RETURNS: TRUE iff contains a valid option and returns FALSE if is not a valid option EFFECT: Scan the cmdlne arguments ****************************************************************/ { int cp,tp1,tp2,tp3; char c; char token1[cmdlne_MAXTOKENLENGTH]; char token2[cmdlne_MAXTOKENLENGTH]; tp1 = tp2 = tp3 = 0; if (string[0] == '-') { cp = 1; c = string[cp]; if (isalpha(c)) { while(isalpha(c)) { token1[tp1] = c; tp1++; cp++; c = string[cp]; } if (c == '\0') { token1[tp1] = '\0'; if(cmdlne_HandleShortArg(token1)) { return TRUE; } else { misc_StartUserErrorReport(); misc_UserErrorReport("\nUnrecognized option: -%s\n\n",token1); misc_FinishUserErrorReport(); return FALSE; } } else if (c == '=') { /*For long type of arguments*/ cp++; c = string[cp]; token1[tp1] = '\0'; if (cmdlne_isArgSym(c)) { token2[tp2]= c; tp2++; cp++; c=string[cp]; while (cmdlne_isArgSym(c)) { token2[tp2]=c; tp2++; cp++; c = string[cp]; } if(c == '\0') { token2[tp2] = '\0'; if(cmdlne_HandleArg(token1, token2)) { return TRUE; } else { misc_StartUserErrorReport(); misc_UserErrorReport("\nUnrecognized option: -%s=%s\n\n",token1, token2); misc_FinishUserErrorReport(); return FALSE; } } else { misc_StartUserErrorReport(); misc_UserErrorReport("\nError: Invalid argument of option %s.\n\n", token1); misc_FinishUserErrorReport(); return FALSE; } } else { misc_StartUserErrorReport(); misc_UserErrorReport("\n Invalid argument of option %s.\n\n", token1); misc_FinishUserErrorReport(); return FALSE; } } else { while (!c == '\0') { token1[tp1]=c; tp1++; cp++; c = string[cp]; } token1[tp1] = '\0'; printf("\nUnrecognized option: -%s\n\n",token1); return FALSE; } } else { while (!c == '\0') { token1[tp1]=c; tp1++; cp++; c = string[cp]; } token1[tp1] = '\0'; printf("\nUnrecognized option: -%s\n\n",token1); return FALSE; } } else { if(cmdlne_InputFile == (char*)NULL) { cmdlne_InputFile = string; /*printf("\nInput File: %s", cmdlne_InputFile);*/ return TRUE; } else if(cmdlne_OutputFile == (char*)NULL) { cmdlne_OutputFile = string; /*printf("\nOutput File: %s", cmdlne_OutputFile);*/ return TRUE; } } /* This function should never execute this code */ misc_StartUserErrorReport(); misc_UserErrorReport("\n Parse error in cmdlne_LexScan.\n\n"); misc_FinishUserErrorReport(); return FALSE; } BOOL cmdlne_Read(int argc, const char *argv[]) /*************************************************************** INPUT: number of commandline argument, command line arguments RETURNS: TRUE if options are in correct syntax and no option is defined multiple times. EFFECT: The options, specified by the commandline arguments, and their arguments are stored in . The respective flags can be set with cmdline_SetFlags. ***************************************************************/ { int iterator; iterator = 1; while(iterator < argc) { if(!cmdlne_LexScan(argv[iterator])) { return FALSE; } iterator++; } return TRUE; } spass-3.9/cmdline.h000066400000000000000000000063111325017163600143070ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * COMMAND LINE PARSER * */ /* * * */ /* * $Module: CMDLNE * */ /* * * */ /* * Copyright (C) 1996, 1997, 1998, 1999, 2000 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.3 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:57 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: cmdline.h,v $ */ #ifndef _CMDLNE_ #define _CMDLNE_ #include #include #include #include "misc.h" #include "flags.h" #include "flags.h" #include "list.h" #include "strings.h" /**************************************************************/ /* Data Types and Constants */ /**************************************************************/ #define cmdlne_MAXTOKENLENGTH 100 #define cmdlne_DEFAULTARGVALUE "1" typedef char* TOKEN; /**************************************************************/ /* Functions */ /**************************************************************/ BOOL cmdlne_Read(int, const char **); BOOL cmdlne_SetFlags(FLAGSTORE); const char* cmdlne_GetInputFile(); const char* cmdlne_GetOutputFile(); void cmdlne_Init(); void cmdlne_Free(); void cmdlne_PrintSPASSNames(); #endif spass-3.9/cnf.c000066400000000000000000005343201325017163600134430ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * CNF TRANSLATOR * */ /* * * */ /* * $Module: CNF * */ /* * * */ /* * 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.13 $ * */ /* $State: Exp $ * */ /* $Date: 2011-11-27 11:05:40 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: cnf.c,v $ */ #include "cnf.h" #include "rules-inf.h" #include "rules-red.h" /******************************************************* *Previously inlined functions * ********************************************************/ BOOL cnf_LabelEqual(const char* l1, const char* l2) /******************************************************** INPUT: Two labels. RETURNS: TRUE, if the labels are equal, FALSE otherwise. *********************************************************/ { return string_Equal(l1, l2); } LIST cnf_DeleteDuplicateLabelsFromList(LIST Labels) /******************************************************** INPUT: A list of labels. RETURNS: The list where duplicate labels are removed. EFFECTS: The duplicate labels are not freed. *********************************************************/ { return list_DeleteDuplicates(Labels, (BOOL (*)(POINTER,POINTER))cnf_LabelEqual); } /******************************************************* *Previously inlined functions ends here * ********************************************************/ static TERM cnf_AntiPrenexPath(TERM, TERM); static TERM cnf_ApplyDefinitionInternOnce(TERM, TERM, TERM, TERM, BOOL*); static SYMBOL cnf_GetDualSymbol(SYMBOL symbol); static TERM cnf_IsDefinition(TERM); static void cnf_OptimizedSkolemFormula(PROOFSEARCH, TERM, char*, BOOL, TERM, LIST*, LIST*, BOOL, HASHMAP, int); int cnf_PredicateOccurrences(TERM, SYMBOL); static void cnf_RplacVar(TERM, LIST, LIST); static LIST cnf_SatUnit(PROOFSEARCH, LIST); static LIST cnf_SkolemFunctionFormula(TERM, LIST, LIST, PRECEDENCE); /* For every variable the depth in the current term, required for */ /* strong skolemization */ static int* cnf_VARIABLEDEPTHARRAY; /* Holds a copy of the ProofSearch--Object built by cnf_Flotter */ /* during cnf_QueryFlotter */ static PROOFSEARCH cnf_SEARCHCOPY; /* Proofsearch--Object for the function cnf_HaveProof. We need this */ /* to reduce the number of term stamps required. */ static PROOFSEARCH cnf_HAVEPROOFPS; void cnf_Init(FLAGSTORE Flags) /*************************************************************** INPUT: A flag store. RETURNS: None. SUMMARY: Initializes the CNF Module. EFFECTS: Initializes global variables. CAUTION: MUST BE CALLED BEFORE ANY OTHER CNF-FUNCTION. ***************************************************************/ { /* If strong skolemization is performed, allocate array for variable depth */ if (flag_GetFlagIntValue(Flags, flag_CNFSTRSKOLEM)) cnf_VARIABLEDEPTHARRAY = (int*) memory_Malloc(sizeof(int[symbol__MAXSTANDARDVAR + 1])); else cnf_VARIABLEDEPTHARRAY = NULL; cnf_SEARCHCOPY = prfs_Create(); cnf_HAVEPROOFPS = prfs_Create(); } void cnf_Free(FLAGSTORE Flags) /************************************************************** INPUT: A flag store. RETURNS: None. SUMMARY: Frees the CNF Module. ***************************************************************/ { /* If strong skolemization is performed, free array for variable depth */ if (flag_GetFlagIntValue(Flags, flag_CNFSTRSKOLEM)) { memory_Free(cnf_VARIABLEDEPTHARRAY, sizeof(int[symbol__MAXSTANDARDVAR + 1])); cnf_VARIABLEDEPTHARRAY = NULL; } prfs_Delete(cnf_SEARCHCOPY); cnf_SEARCHCOPY = NULL; prfs_Delete(cnf_HAVEPROOFPS); cnf_HAVEPROOFPS = NULL; } static int cnf_GetFormulaPolarity(TERM term, TERM subterm) /********************************************************** INPUT: Two terms term and subterm where subterm is a subterm of term. RETURNS: The polarity of subterm in term. ********************************************************/ { LIST scan; TERM term1; intptr_t polterm1; int bottom; bottom = vec_ActMax(); vec_Push((POINTER) 1); vec_Push(term); do { term1 = (TERM)vec_PopResult(); polterm1 = (intptr_t)vec_PopResult(); if (term1 == subterm) { vec_SetMax(bottom); return polterm1; }else if (symbol_Equal(term_TopSymbol(term1),fol_Not())) { vec_Push((POINTER) (- polterm1)); vec_Push(list_Car(term_ArgumentList(term1))); } if (symbol_Equal(term_TopSymbol(term1),fol_Exist()) || symbol_Equal(term_TopSymbol(term1),fol_All())) { vec_Push((POINTER)polterm1); vec_Push(list_Second(term_ArgumentList(term1))); } else if (symbol_Equal(term_TopSymbol(term1),fol_Implies())) { vec_Push((POINTER) (- polterm1)); vec_Push(list_Car(term_ArgumentList(term1))); vec_Push((POINTER) polterm1); vec_Push(list_Second(term_ArgumentList(term1))); } else if (symbol_Equal(term_TopSymbol(term1),fol_Equiv())) { vec_Push(0); vec_Push(list_Car(term_ArgumentList(term1))); vec_Push(0); vec_Push(list_Second(term_ArgumentList(term1))); } else if (symbol_Equal(term_TopSymbol(term1),fol_And()) || symbol_Equal(term_TopSymbol(term1),fol_Or())) { for (scan = term_ArgumentList(term1); !list_Empty(scan); scan = list_Cdr(scan)) { vec_Push((POINTER) polterm1); vec_Push(list_Car(scan)); } } } while (bottom != vec_ActMax()); vec_SetMax(bottom); misc_StartErrorReport(); misc_ErrorReport("\n In cnf_GetFormulaPolarity: Wrong arguments !\n"); misc_FinishErrorReport(); return -2; } static BOOL cnf_ContainsDefinitionIntern(TERM TopDef, TERM Def, int Polarity, TERM* FoundPred) /********************************************************** INPUT: A term TopDef which is the top level term of the recursion. A term Def which is searched for a definition. A pointer to a term into which the predicate of the definition is stored if it is found. RETURNS: TRUE if Def contains a definition that can be converted to standard form. ********************************************************/ { /* AND / OR */ /* In these cases Def cannot be converted to standard form */ if ((symbol_Equal(term_TopSymbol(Def),fol_And()) && (Polarity == 1)) || (symbol_Equal(term_TopSymbol(Def),fol_Or()) && (Polarity == -1))) return FALSE; if (symbol_Equal(term_TopSymbol(Def), fol_And()) || symbol_Equal(term_TopSymbol(Def),fol_Or())) { /* Polarity is ok */ LIST l; for (l=term_ArgumentList(Def); !list_Empty(l); l=list_Cdr(l)) if (cnf_ContainsDefinitionIntern(TopDef, list_Car(l), Polarity, FoundPred)) return TRUE; return FALSE; } /* Quantifiers */ if (fol_IsQuantifier(term_TopSymbol(Def))) return cnf_ContainsDefinitionIntern(TopDef, term_SecondArgument(Def), Polarity, FoundPred); /* Negation */ if (symbol_Equal(term_TopSymbol(Def),fol_Not())) return cnf_ContainsDefinitionIntern(TopDef, term_FirstArgument(Def), -Polarity, FoundPred); /* Implication */ if (symbol_Equal(term_TopSymbol(Def),fol_Implies())) { if (Polarity==1) { if (cnf_ContainsDefinitionIntern(TopDef, term_FirstArgument(Def), -Polarity, FoundPred)) return TRUE; return cnf_ContainsDefinitionIntern(TopDef, term_SecondArgument(Def), Polarity, FoundPred); } return FALSE; } /* Equivalence */ if (symbol_Equal(term_TopSymbol(Def),fol_Equiv()) && (Polarity==1)) { /* Check if equivalence itself is in correct form */ TERM defpredicate; defpredicate = cnf_IsDefinition(Def); if (defpredicate != (TERM) NULL) { LIST predicate_vars, l, defpath; BOOL allquantifierfound; TERM super; intptr_t pol; /* Check if predicate occurs several times in TopDef */ /* if (cnf_PredicateOccurrences(TopDef, term_TopSymbol(defpredicate)) > 1) {} puts("\n Predicate occurs more than once."); return FALSE; */ /* Now make sure that the variables of the predicate are */ /* all--quantified and not in the scope of an exist quantifier */ /* predicate_vars = list_Copy(term_ArgumentList(defpredicate)); */ predicate_vars = term_ListOfVariables(defpredicate); predicate_vars = term_DeleteDuplicatesFromList(predicate_vars); /* So far (going bottom--up) no all-quantifier was found for */ /* a variable of the predicates' arguments */ allquantifierfound = FALSE; /* Build defpath here by going bottom up */ /* At first, list of superterms on path is top down */ defpath = list_Nil(); super = Def; while (super != (TERM) NULL) { defpath = list_Cons(super, defpath); super = term_Superterm(super); } /* No go top down and add polarities */ pol = 1; for (l=defpath; !list_Empty(l); l=list_Cdr(l)) { list_Rplaca(l, list_PairCreate((TERM) list_Car(l), (LIST) pol)); if (symbol_Equal(term_TopSymbol((TERM) list_Car(l)), fol_Not())) pol = -pol; else { if (symbol_Equal(term_TopSymbol((TERM) list_Car(l)), fol_Implies()) && (term_FirstArgument((TERM) list_Car(l)) == (TERM) list_Car(list_Cdr(l)))) pol = -pol; else if (symbol_Equal(term_TopSymbol((TERM) list_Car(l)), fol_Equiv())) pol = 0; } } /* is now a list of pairs (term, polarity) */ for (l=defpath; !list_Empty(l) && !list_Empty(predicate_vars); l=list_Cdr(l)) { LIST pair; TERM t; intptr_t p; /* Pair Term t / Polarity p */ pair = (LIST) list_Car(l); t = (TERM) list_PairFirst(pair); p = (intptr_t) list_PairSecond(pair); if (fol_IsQuantifier(term_TopSymbol(t))) { /* Variables of the predicate that are universally quantified are no problem */ if ((symbol_Equal(term_TopSymbol(t), fol_All()) && (p==1)) || (symbol_Equal(term_TopSymbol(t), fol_Exist()) && (p==-1))) { LIST scan; allquantifierfound = TRUE; for (scan=fol_QuantifierVariables(t); !list_Empty(scan); scan=list_Cdr(scan)) predicate_vars = list_DeleteElement(predicate_vars,(TERM) list_Car(scan), (BOOL (*)(POINTER,POINTER))term_Equal); } else { /* Check if allquantified variables of the predicate are in scope of an exist--quantifier */ /* We already found an all quantified variable */ if (allquantifierfound) { list_Delete(predicate_vars); list_DeletePairList(defpath); return FALSE; } else { LIST scan; /* Check if a variable of the predicate is exist--quantified */ for (scan=fol_QuantifierVariables(t); !list_Empty(scan); scan=list_Cdr(scan)) { if (term_ListContainsTerm(predicate_vars, list_Car(scan))) { list_Delete(predicate_vars); list_DeletePairList(defpath); return FALSE; } } } } } } #ifdef CHECK if (!list_Empty(predicate_vars)) { list_Delete(predicate_vars); misc_StartErrorReport(); misc_ErrorReport("\n In cnf_ContainsDefinitionIntern: Definition has free variables.\n"); misc_FinishErrorReport(); } #endif list_DeletePairList(defpath); *FoundPred = defpredicate; return TRUE; } } return FALSE; } BOOL cnf_ContainsDefinition(TERM Def, TERM* FoundPred) /********************************************************** INPUT: A term Def which is searched for a definition of a predicate. A pointer to a term into which the predicate of the definition is stored if it is found. RETURNS: TRUE if Def contains a definition that can be converted to standard form. ***********************************************************/ { BOOL result; #ifdef CHECK fol_CheckFatherLinks(Def); #endif result = cnf_ContainsDefinitionIntern(Def, Def, 1, FoundPred); #ifdef CHECK fol_CheckFatherLinks(Def); #endif return result; } static TERM cnf_IsDefinition(TERM Def) /********************************************************** INPUT: A term Def. RETURNS: The Def term where the arguments of the equivalence are exchanged iff the first one is not a predicate. **********************************************************/ { LIST l,freevars, predicatevars; #ifdef CHECK if (Def == NULL) { misc_StartErrorReport(); misc_ErrorReport("\n In cnf_IsDefinition: Empty formula.\n"); misc_FinishErrorReport(); } if (!symbol_Equal(term_TopSymbol(Def),fol_Equiv())) { misc_StartErrorReport(); misc_ErrorReport("\n In cnf_IsDefinition: Formula is no equivalence.\n"); misc_FinishErrorReport(); } #endif /* If the predicate is the second argument of the equivalence, exchange them */ if (!symbol_IsPredicate(term_TopSymbol(term_FirstArgument(Def)))) { TERM arg1; arg1 = term_FirstArgument(Def); term_RplacFirstArgument(Def, term_SecondArgument(Def)); term_RplacSecondArgument(Def, arg1); } /* Check if the first argument is a predicate */ if (!symbol_IsPredicate(term_TopSymbol(term_FirstArgument(Def)))) return NULL; /* Check if first argument is a predicate and not fol_Equality */ /* if (!symbol_IsPredicate(term_TopSymbol(term_FirstArgument(Def))) || symbol_Equal(term_TopSymbol(term_FirstArgument(Def)), fol_Equality()))) { return NULL; }*/ /* The free variables of the non-predicate term must occur in the predicate term */ freevars = fol_FreeVariables(term_SecondArgument(Def)); freevars = term_DeleteDuplicatesFromList(freevars); predicatevars = term_ListOfVariables(term_FirstArgument(Def)); predicatevars = term_DeleteDuplicatesFromList(predicatevars); for (l=predicatevars; !list_Empty(l); l=list_Cdr(l)) freevars = list_DeleteElement(freevars, list_Car(l), (BOOL (*)(POINTER,POINTER))term_Equal); if (!list_Empty(freevars)) { list_Delete(freevars); list_Delete(predicatevars); return NULL; } list_Delete(predicatevars); return term_FirstArgument(Def); } static BOOL cnf_ContainsPredicateIntern(TERM Target, SYMBOL Predicate, int Polarity, TERM* TargetPredicate, TERM* ToTopLevel, LIST* TargetVars, LIST* VarsForTopLevel) /********************************************************** INPUT: A term (sub--) Target A symbol Predicate which is searched in the target term. The polarity of the subterm. A pointer to the term TargetPredicate into which the found predicate term is stored. A pointer to the list TargetVars into which the variables found in the predicates' arguments are stored. A pointer to a list VarsForTopLevel into which all variables are stored that are all--quantified and can be moved to top level. RETURNS: TRUE if Formula contains the predicate for which a definition was found. ********************************************************/ { /* AND / OR */ /* In these cases the predicate (if it exists) can not be moved to a higher level */ if ((symbol_Equal(term_TopSymbol(Target),fol_And()) && Polarity == 1) || (symbol_Equal(term_TopSymbol(Target),fol_Or()) && Polarity == -1) || (symbol_Equal(term_TopSymbol(Target),fol_Implies()) && Polarity != 1) || symbol_Equal(term_TopSymbol(Target), fol_Equiv())) { TERM s; LIST l; /* Try to find Predicate in Target */ s = term_FindSubterm(Target, Predicate); if (s == NULL) return FALSE; /* Store variables found in the predicates arguments */ for (l=term_ArgumentList(s); !list_Empty(l); l = list_Cdr(l)) *TargetVars = list_Nconc(fol_FreeVariables((TERM) list_Car(l)), *TargetVars); *TargetVars = term_DeleteDuplicatesFromList(*TargetVars); /* Keep found predicate */ *TargetPredicate = s; *ToTopLevel = Target; return TRUE; } /* AND / OR continued */ if (symbol_Equal(term_TopSymbol(Target),fol_And()) || symbol_Equal(term_TopSymbol(Target),fol_Or())) { /* The polarity is ok here */ LIST l; for (l=term_ArgumentList(Target); !list_Empty(l); l = list_Cdr(l)) if (cnf_ContainsPredicateIntern((TERM) list_Car(l), Predicate, Polarity, TargetPredicate, ToTopLevel, TargetVars, VarsForTopLevel)) return TRUE; return FALSE; } /* Quantifiers */ if (fol_IsQuantifier(term_TopSymbol(Target))) { if (cnf_ContainsPredicateIntern(term_SecondArgument(Target), Predicate, Polarity, TargetPredicate, ToTopLevel, TargetVars, VarsForTopLevel)) { /* Quantifiers for free variables of the predicate should be moved to top level to make the proof easier */ if ((symbol_Equal(term_TopSymbol(Target), fol_All()) && Polarity == 1) || (symbol_Equal(term_TopSymbol(Target), fol_Exist()) && Polarity == -1)) { LIST l; /* Check for all variables found in the predicates arguments */ for (l = *TargetVars; !list_Empty(l); l=list_Cdr(l)) { if (term_ListContainsTerm(fol_QuantifierVariables(Target),list_Car(l))) *VarsForTopLevel = list_Cons(list_Car(l), *VarsForTopLevel); } } return TRUE; } return FALSE; } /* Negation */ if (symbol_Equal(term_TopSymbol(Target),fol_Not())) return cnf_ContainsPredicateIntern(term_FirstArgument(Target), Predicate, -Polarity, TargetPredicate, ToTopLevel, TargetVars, VarsForTopLevel); /* Implication */ if (symbol_Equal(term_TopSymbol(Target),fol_Implies())) { /* In this case the predicate (if it exists) can be moved to a higher level */ if (cnf_ContainsPredicateIntern(term_FirstArgument(Target), Predicate, -Polarity, TargetPredicate, ToTopLevel, TargetVars, VarsForTopLevel)) return TRUE; return cnf_ContainsPredicateIntern(term_SecondArgument(Target), Predicate, Polarity, TargetPredicate, ToTopLevel, TargetVars, VarsForTopLevel); } /* Found the predicate */ if (symbol_Equal(term_TopSymbol(Target), Predicate)) { LIST l; for (l = term_ArgumentList(Target); !list_Empty(l); l = list_Cdr(l)) *TargetVars = list_Nconc(fol_FreeVariables((TERM) list_Car(l)), *TargetVars); *TargetVars = term_DeleteDuplicatesFromList(*TargetVars); *TargetPredicate = Target; *ToTopLevel = Target; return TRUE; } /* In all other cases the predicate was not found */ return FALSE; } BOOL cnf_ContainsPredicate(TERM Target, SYMBOL Predicate, TERM* TargetPredicate, TERM* ToTopLevel, LIST* TargetVars, LIST* VarsForTopLevel) /********************************************************** INPUT: A term Target without implications. A symbol Predicate which is searched in the target term. A pointer to the predicate found in TargetTerm is recorded. A pointer to the term TargetPredicate into which the found predicate term is stored. A pointer to the list TargetVars into which the variables found in the predicates' arguments are stored. A pointer to a list VarsForTopLevel into which all variables are stored that are all--quantified and can be moved to top level. RETURNS: TRUE if Formula contains the predicate for which a definition was found. ********************************************************/ { BOOL result; #ifdef CHECK fol_CheckFatherLinks(Target); #endif result = cnf_ContainsPredicateIntern(Target, Predicate, 1, TargetPredicate, ToTopLevel, TargetVars, VarsForTopLevel); #ifdef CHECK fol_CheckFatherLinks(Target); #endif return result; } int cnf_PredicateOccurrences(TERM Term, SYMBOL P) /**************************************************** INPUT: A term and a predicate symbol. RETURNS: The number of occurrences of the predicate symbol in Term **************************************************/ { /* Quantifiers */ if (fol_IsQuantifier(term_TopSymbol(Term))) return cnf_PredicateOccurrences(term_SecondArgument(Term), P); /* Junctors and NOT */ if (fol_IsJunctor(term_TopSymbol(Term)) || symbol_Equal(term_TopSymbol(Term),fol_Not())) { LIST scan; int count; count = 0; for (scan=term_ArgumentList(Term); !list_Empty(scan); scan=list_Cdr(scan)) { count += cnf_PredicateOccurrences(list_Car(scan), P); /* Only the cases count==1 and count>1 are important */ if (count > 1) return count; } return count; } if (symbol_Equal(term_TopSymbol(Term), P)) return 1; return 0; } static TERM cnf_NegationNormalFormulaPath(TERM Term, TERM PredicateTerm) /********************************************************** INPUT: A term and a predicate term which is a subterm of term RETURNS: The negation normal form of the term along the path. CAUTION: The term is destructively changed. This works only if the superterm member of Term and its subterms are set. ********************************************************/ { TERM subterm, termL, term1; LIST scan; SYMBOL symbol; BOOL set; term1 = Term; while (term1 != NULL) { set = FALSE; if (symbol_Equal(term_TopSymbol(term1),fol_Not())) { subterm = term_FirstArgument(term1); if (symbol_Equal(term_TopSymbol(subterm),fol_Not())) { LIST l; term_RplacTop(term1,term_TopSymbol(term_FirstArgument(subterm))); list_Delete(term_ArgumentList(term1)); term_RplacArgumentList(term1,term_ArgumentList(term_FirstArgument(subterm))); term_Free(term_FirstArgument(subterm)); list_Delete(term_ArgumentList(subterm)); term_Free(subterm); /* Set superterm member to new superterm */ for (l=term_ArgumentList(term1); !list_Empty(l); l=list_Cdr(l)) term_RplacSuperterm(list_Car(l), term1); /* term1 weiter betrachten */ set = TRUE; } else { if (fol_IsQuantifier(term_TopSymbol(subterm))) { LIST l; symbol = (SYMBOL)cnf_GetDualSymbol(term_TopSymbol(subterm)); termL = term_CreateAddFather(fol_Not(), list_List(term_SecondArgument(subterm))); list_RplacSecond(term_ArgumentList(subterm), termL); term_RplacSuperterm(termL, subterm); term_RplacTop(term1,symbol); list_Delete(term_ArgumentList(term1)); term_RplacArgumentList(term1, term_ArgumentList(subterm)); for (l=term_ArgumentList(term1); !list_Empty(l); l = list_Cdr(l)) term_RplacSuperterm(list_Car(l), term1); term_RplacArgumentList(subterm, list_Nil()); term_Delete(subterm); term1 = termL; /* Next term to check is not(subterm) */ set = TRUE; } else { if (symbol_Equal(term_TopSymbol(subterm),fol_Or()) || (symbol_Equal(term_TopSymbol(subterm),fol_And()))) { LIST l; symbol = (SYMBOL)cnf_GetDualSymbol(term_TopSymbol(subterm)); for (scan = term_ArgumentList(subterm); !list_Empty(scan); scan = list_Cdr(scan)) { TERM new; termL = list_Car(scan); new = term_CreateAddFather(fol_Not(),list_List(termL)); list_Rplaca(scan, new); term_RplacSuperterm(new, subterm); } term_RplacTop(term1,symbol); list_Delete(term_ArgumentList(term1)); term_RplacArgumentList(term1,term_ArgumentList(subterm)); for (l = term_ArgumentList(term1); !list_Empty(l); l=list_Cdr(l)) term_RplacSuperterm(list_Car(l), term1); term_RplacArgumentList(subterm, list_Nil()); term_Delete(subterm); } } } } if (!set) { if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) if (term_HasProperSuperterm(PredicateTerm, list_Car(scan))) { term1 = list_Car(scan); set = TRUE; break; } if (!set) term1 = NULL; } } return Term; } TERM cnf_ApplyDefinitionOnce(TERM Predicate, TERM Formula, TERM TargetTerm, TERM TargetPredicate, FLAGSTORE Flags) /********************************************************* INPUT: A term Predicate which is a predicate found in a definition. A term Formula which is a term equivalent to the predicate. A term TargetTerm in which one occurrence of the predicate may be replaced by the Formula. A term TargetPredicate which is the subterm of the TargetTerm to be replaced. A flag store. RETURNS: The changed TargetTerm. *************************************************************/ { SYMBOL maxvar, maxvar_temp; LIST bound, scan; BOOL success; /* Init varcounter */ maxvar = term_MaxVar(TargetTerm); maxvar_temp = term_MaxVar(Formula); if (maxvar_temp > maxvar) maxvar = maxvar_temp; symbol_SetStandardVarCounter(maxvar); /* Find bound variables in formula for renaming them */ bound = fol_BoundVariables(Formula); for (scan=bound; !list_Empty(scan); scan=list_Cdr(scan)) { /* Bound variable in definition is already used in term */ if (term_ContainsSymbol(TargetTerm, term_TopSymbol(list_Car(scan)))) term_ExchangeVariable(Formula, term_TopSymbol(list_Car(scan)), symbol_CreateStandardVariable()); } list_Delete(bound); TargetTerm = cnf_ApplyDefinitionInternOnce(Predicate, Formula, TargetTerm, TargetPredicate,&success); if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { if (success) { fputs("\nTarget after applying def:\n", stdout); fol_PrettyPrint(TargetTerm); puts("\n"); } } return TargetTerm; } static TERM cnf_ApplyDefinitionInternOnce(TERM Predicate, TERM Formula, TERM TargetTerm, TERM TargetPredicate, BOOL* Success) /********************************************************** INPUT: A term Predicate which is equivalence to Formula and Term RETURNS: The term in which all occurrences of P(..) are replaced by Formula modulo the proper bindings CAUTION: Term is destructively changed! ***********************************************************/ { /* Quantifiers */ if (fol_IsQuantifier(term_TopSymbol(TargetTerm))) { term_RplacSecondArgument(TargetTerm, cnf_ApplyDefinitionInternOnce(Predicate, Formula, term_SecondArgument(TargetTerm), TargetPredicate, Success)); term_RplacSuperterm(term_SecondArgument(TargetTerm), TargetTerm); return TargetTerm; } /* Junctors and NOT */ if (fol_IsJunctor(term_TopSymbol(TargetTerm)) || symbol_Equal(term_TopSymbol(TargetTerm),fol_Not())) { LIST scan; for (scan=term_ArgumentList(TargetTerm); !list_Empty(scan); scan=list_Cdr(scan)) { list_Rplaca(scan, cnf_ApplyDefinitionInternOnce(Predicate, Formula, list_Car(scan), TargetPredicate, Success)); term_RplacSuperterm((TERM) list_Car(scan), TargetTerm); } return TargetTerm; } if (symbol_Equal(term_TopSymbol(TargetTerm), term_TopSymbol(Predicate))) { if (TargetTerm == TargetPredicate) { TERM result; result = Formula; cnf_RplacVar(result, term_ArgumentList(Predicate), term_ArgumentList(TargetTerm)); term_AddFatherLinks(result); term_Delete(TargetTerm); *Success = TRUE; return result; } } return TargetTerm; } static TERM cnf_RemoveEquivImplFromFormula(TERM term) /********************************************************** INPUT: A term. RETURNS: The term with replaced implications and equivalences. CAUTION: The term is destructively changed. ********************************************************/ { TERM term1,termL,termR,termLneg,termRneg; LIST scan; int bottom,pol; bottom = vec_ActMax(); vec_Push(term); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (symbol_Equal(term_TopSymbol(term1),fol_Implies())) { term_RplacTop(term1, fol_Or()); list_Rplaca(term_ArgumentList(term1), term_Create(fol_Not(), list_List(list_Car(term_ArgumentList(term1))))); }else if (symbol_Equal(term_TopSymbol(term1),fol_Equiv())) { pol = cnf_GetFormulaPolarity(term,term1); termL = (TERM)list_Car(term_ArgumentList(term1)); termR = (TERM)list_Second(term_ArgumentList(term1)); termLneg = term_Create(fol_Not(),list_List(term_Copy(termL))); termRneg = term_Create(fol_Not(),list_List(term_Copy(termR))); if (pol == 1 || pol == 0) { term_RplacTop(term1, fol_And()); list_Rplaca(term_ArgumentList(term1), term_Create(fol_Or(),list_Cons(termLneg,list_List(termR)))); list_RplacSecond(term_ArgumentList(term1),term_Create(fol_Or(),list_Cons(termRneg,list_List(termL)))); }else if (pol == -1) { term_RplacTop(term1, fol_Or()); list_Rplaca(term_ArgumentList(term1), term_Create(fol_And(),list_Cons(termLneg,list_List(termRneg)))); list_RplacSecond(term_ArgumentList(term1), term_Create(fol_And(),list_Cons(termL,list_List(termR)))); } } if (!list_Empty(term_ArgumentList(term1)) && !symbol_IsPredicate(term_TopSymbol(term1))) { for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); } } vec_SetMax(bottom); return term; } static TERM cnf_MovePredicateVariablesUp(TERM Term, TERM TargetPredicateTerm, LIST VarsForTopLevel) /********************************************************** INPUT: A term and a predicate term which is a subterm of term an equivalence. RETURNS: The term where the free variables of the equivalence, which must be allquantified and not in the scope of an exist quantifier, are moved to toplevel. CAUTION: The term is destructively changed. ********************************************************/ { TERM term1; LIST scan; int bottom; bottom = vec_ActMax(); vec_Push(Term); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) { TERM arg; arg = (TERM) list_Car(scan); if (term_HasProperSuperterm(TargetPredicateTerm, arg)) { if (symbol_Equal(term_TopSymbol(arg), fol_All())) { LIST predicatevarscan, quantifiervars; quantifiervars = fol_QuantifierVariables(arg); for (predicatevarscan=VarsForTopLevel; !list_Empty(predicatevarscan); predicatevarscan = list_Cdr(predicatevarscan)) quantifiervars = list_DeleteElementFree(quantifiervars, (TERM) list_Car(predicatevarscan), (BOOL (*)(POINTER,POINTER))term_Equal, (void (*)(POINTER))term_Delete); if (!list_Empty(quantifiervars)) term_RplacArgumentList(term_FirstArgument(arg), quantifiervars); else { TERM subterm; subterm = term_SecondArgument(arg); term_Free(term_FirstArgument(arg)); list_Delete(term_ArgumentList(arg)); term_Free(arg); list_Rplaca(scan, subterm); term_RplacSuperterm(subterm, term1); } } vec_Push((TERM) list_Car(scan)); } } } for (scan=VarsForTopLevel; !list_Empty(scan); scan = list_Cdr(scan)) list_Rplaca(scan, term_Copy((TERM) list_Car(scan))); if (symbol_Equal(term_TopSymbol(Term), fol_All())) { LIST vars; vars = fol_QuantifierVariables(Term); vars = list_Nconc(vars, list_Copy(VarsForTopLevel)); vars = term_DestroyDuplicatesInList(vars); term_RplacArgumentList(term_FirstArgument(Term), vars); } else { TERM newtop; newtop = fol_CreateQuantifier(fol_All(), list_Copy(VarsForTopLevel), list_List(Term)); term_RplacSuperterm(Term, newtop); Term = newtop; } vec_SetMax(bottom); return Term; } static TERM cnf_RemoveImplFromFormulaPath(TERM Term, TERM PredicateTerm) /********************************************************** INPUT: A term and a predicate term which is a subterm of term RETURNS: The term where implications along the path to PredicateTerm are replaced. CAUTION: The term is destructively changed. This works only if the superterm member of Term and its subterms are set. ********************************************************/ { TERM term1; LIST scan; int bottom; bottom = vec_ActMax(); vec_Push(Term); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (term_HasProperSuperterm(PredicateTerm, term1)) { if (symbol_Equal(term_TopSymbol(term1),fol_Implies())) { TERM newterm; term_RplacTop(term1, fol_Or()); newterm = term_CreateAddFather(fol_Not(), list_List(list_Car(term_ArgumentList(term1)))); list_Rplaca(term_ArgumentList(term1), newterm); term_RplacSuperterm(newterm, term1); } if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); } } vec_SetMax(bottom); return Term; } static SYMBOL cnf_GetDualSymbol(SYMBOL symbol) /******************************************************** INPUT: A predefined symbol. RETURNS: The dual symbol. ********************************************************/ { SYMBOL dual; dual = symbol; if (symbol_Equal(symbol,fol_All())) dual = fol_Exist(); else if (symbol_Equal(symbol,fol_Exist())) dual = fol_All(); else if (symbol_Equal(symbol,fol_Or())) dual = fol_And(); else if (symbol_Equal(symbol,fol_And())) dual = fol_Or(); return dual; } TERM cnf_NegationNormalFormula(TERM term) /******************************************************** INPUT: A term. RETURNS: The negation normal form of the term. CAUTION: The term is destructively changed. ********************************************************/ { TERM term1,subterm,termL; LIST scan; SYMBOL symbol; int bottom; bottom = vec_ActMax(); vec_Push(term); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (symbol_Equal(term_TopSymbol(term1),fol_Not())) { subterm = (TERM)list_Car(term_ArgumentList(term1)); if (symbol_Equal(term_TopSymbol(subterm),fol_Not())) { term_RplacTop(term1,term_TopSymbol(term_FirstArgument(subterm))); list_Delete(term_ArgumentList(term1)); term_RplacArgumentList(term1,term_ArgumentList(term_FirstArgument(subterm))); term_Free(term_FirstArgument(subterm)); list_Delete(term_ArgumentList(subterm)); term_Free(subterm); vec_Push(term1); }else if (fol_IsQuantifier(term_TopSymbol(subterm))) { symbol = (SYMBOL)cnf_GetDualSymbol(term_TopSymbol(subterm)); termL = term_Create(fol_Not(), list_List(term_SecondArgument(subterm))); list_RplacSecond(term_ArgumentList(subterm), termL); term_RplacTop(term1,symbol); list_Delete(term_ArgumentList(term1)); term_RplacArgumentList(term1,term_CopyTermList(term_ArgumentList(subterm))); term_Delete(subterm); } else if (symbol_Equal(term_TopSymbol(subterm),fol_Or()) || symbol_Equal(term_TopSymbol(subterm),fol_And())) { symbol = (SYMBOL)cnf_GetDualSymbol(term_TopSymbol(subterm)); for (scan = term_ArgumentList(subterm); !list_Empty(scan); scan = list_Cdr(scan)) { termL = (TERM)list_Car(scan); list_Rplaca(scan, term_Create(fol_Not(),list_List(termL))); } term_RplacTop(term1,symbol); list_Delete(term_ArgumentList(term1)); term_RplacArgumentList(term1,term_CopyTermList(term_ArgumentList(subterm))); term_Delete(subterm); } } if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); } vec_SetMax(bottom); return term; } static TERM cnf_QuantMakeOneVar(TERM term) /************************************************************** INPUT: A term. RETURNS: The term where all quantifiers quantify over only one variable. CAUTION: The term is destructively changed. ***************************************************************/ { TERM term1,termL; SYMBOL quantor; LIST scan,varlist; int bottom; bottom = vec_ActMax(); vec_Push(term); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (fol_IsQuantifier(term_TopSymbol(term1))) { quantor = term_TopSymbol(term1); if (list_Length(term_ArgumentList(term_FirstArgument(term1))) > 1) { varlist = list_Copy(list_Cdr(term_ArgumentList(term_FirstArgument(term1)))); for (scan=varlist;!list_Empty(scan);scan=list_Cdr(scan)) { termL = term_SecondArgument(term1); term_RplacSecondArgument(term1, fol_CreateQuantifier(quantor,list_List(list_Car(scan)),list_List(termL))); } for (scan=varlist;!list_Empty(scan);scan=list_Cdr(scan)) { term_RplacArgumentList(term_FirstArgument(term1), list_PointerDeleteElement(term_ArgumentList(term_FirstArgument(term1)),list_Car(scan))); } list_Delete(varlist); } } if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); } vec_SetMax(bottom); return term; } static LIST cnf_GetSymbolList(LIST varlist) /************************************************************** INPUT: A list of variables RETURNS: The list of the symbols of the variables. ***************************************************************/ { LIST scan,result; result = list_Nil(); for (scan=varlist;!list_Empty(scan);scan=list_Cdr(scan)) result = list_Cons((POINTER)term_TopSymbol((TERM)list_Car(scan)),result); return result; } static BOOL cnf_TopIsAnd(LIST termlist) /************************************************************** INPUT: A list of terms. RETURNS: True if one term in termlist is a conjunction. ***************************************************************/ { LIST scan; for (scan=termlist;!list_Empty(scan);scan=list_Cdr(scan)) if (term_TopSymbol(list_Car(scan)) == fol_And()) return TRUE; return FALSE; } static TERM cnf_MakeOneOr(TERM term) /************************************************************** INPUT: A term. RETURNS: Takes all arguments of an or together. CAUTION: The term is destructively changed. ***************************************************************/ { LIST scan; if (symbol_Equal(term_TopSymbol(term),fol_Or())) { TERM argterm; scan=term_ArgumentList(term); while (!list_Empty(scan)) { argterm = (TERM)list_Car(scan); cnf_MakeOneOr(argterm); if (symbol_Equal(term_TopSymbol(argterm),fol_Or())) { scan = list_Cdr(scan); term_RplacArgumentList(term, list_Nconc(term_ArgumentList(argterm),list_PointerDeleteElement(term_ArgumentList(term),argterm))); term_Free(argterm); } else scan = list_Cdr(scan); } } else if (!symbol_IsPredicate(term_TopSymbol(term))) for (scan=term_ArgumentList(term);!list_Empty(scan);scan=list_Cdr(scan)) cnf_MakeOneOr(list_Car(scan)); return term; } static TERM cnf_MakeOneOrPredicate(TERM term) /************************************************************** INPUT: A term. RETURNS: Takes all predicates and negated predicates as arguments of an or together. CAUTION: The term is destructively changed. ***************************************************************/ { LIST scan,scan1,predlist; if (cnf_TopIsAnd(term_ArgumentList(term))) { for (scan1=term_ArgumentList(term); !(list_Empty(scan1) || symbol_Equal(term_TopSymbol(list_Car(scan1)),fol_And())); scan1=list_Cdr(scan1)); if (!list_Empty(scan1)) { predlist = list_Nil(); for (scan=scan1; !list_Empty(scan); scan=list_Cdr(scan)) { if (symbol_IsPredicate(term_TopSymbol(list_Car(scan))) || fol_IsNegativeLiteral(list_Car(scan))) { predlist = list_Cons(list_Car(scan),predlist); } } for (scan=predlist;!list_Empty(scan);scan=list_Cdr(scan)) term_RplacArgumentList(term, list_PointerDeleteElement(term_ArgumentList(term),list_Car(scan))); if (!list_Empty(predlist)) term_RplacArgumentList(term, list_Nconc(predlist,term_ArgumentList(term))); } } return term; } static TERM cnf_MakeOneOrTerm(TERM term) /************************************************************** INPUT: A term. RETURNS: Takes all predicates as arguments of an or together. CAUTION: The term is destructively changed. ***************************************************************/ { return cnf_MakeOneOrPredicate(cnf_MakeOneOr(term)); } static TERM cnf_MakeOneAnd(TERM term) /************************************************************** INPUT: A term. RETURNS: Takes all arguments of an and together. CAUTION: The term is destructively changed. ***************************************************************/ { LIST scan; if (symbol_Equal(term_TopSymbol(term),fol_And())) { TERM argterm; scan=term_ArgumentList(term); while (!list_Empty(scan)) { argterm = (TERM)list_Car(scan); cnf_MakeOneAnd(argterm); if (symbol_Equal(term_TopSymbol(argterm),fol_And())) { scan = list_Cdr(scan); term_RplacArgumentList(term, list_Nconc(term_ArgumentList(argterm),list_PointerDeleteElement(term_ArgumentList(term),argterm))); term_Free(argterm); } else scan = list_Cdr(scan); } } else if (!symbol_IsPredicate(term_TopSymbol(term))) for (scan=term_ArgumentList(term);!list_Empty(scan);scan=list_Cdr(scan)) cnf_MakeOneAnd(list_Car(scan)); return term; } static TERM cnf_MakeOneAndPredicate(TERM term) /************************************************************** INPUT: A term. RETURNS: Takes all predicates as arguments of one or together. CAUTION: The term is destructively changed. ***************************************************************/ { LIST scan,scan1,predlist; for (scan1=term_ArgumentList(term); !(list_Empty(scan1) || symbol_Equal(term_TopSymbol(list_Car(scan1)),fol_Or())); scan1=list_Cdr(scan1)); if (!list_Empty(scan1)) { /* The car of scan1 points to a term with topsymbol 'or' */ predlist = list_Nil(); for (scan=scan1; !list_Empty(scan); scan=list_Cdr(scan)) { if (symbol_IsPredicate(term_TopSymbol(list_Car(scan))) && fol_IsNegativeLiteral(list_Car(scan))) { predlist = list_Cons(list_Car(scan),predlist); } } for (scan=predlist; !list_Empty(scan); scan=list_Cdr(scan)) term_RplacArgumentList(term, list_PointerDeleteElement(term_ArgumentList(term),list_Car(scan))); if (!list_Empty(predlist)) term_RplacArgumentList(term, list_Nconc(predlist,term_ArgumentList(term))); } return term; } static TERM cnf_MakeOneAndTerm(TERM term) /************************************************************** INPUT: A term. RETURNS: Takes all predicates as arguments of an or together. CAUTION: The term is destructively changed. ***************************************************************/ { return cnf_MakeOneAndPredicate(cnf_MakeOneAnd(term)); } BOOL cnf_FlattenToSimpleORTerm(TERM Term) /************************************************************** INPUT: A term RETURNS: Traverse the term tree using BFS, and flatten the cascated OR Term to flat ones. Return True if it is a flat OR Term after all, returns FALSE if it contains any AND SubTerm EFFECTS: The input Term will be flattened on each level, as long as it contains no AND subTerm. The sub Terms of the AND Terms are no more flattened, even if it might contains cascated OR Terms as sub Terms. CAUTION: The term is changed. ***************************************************************/ { LIST Scan1,Scan2; BOOL SimpleOrTerm, SimpleOrSubTerm; SimpleOrTerm = FALSE; if (symbol_Equal(term_TopSymbol(Term), fol_Or())) { TERM Argterm; SimpleOrSubTerm = TRUE; Scan1 =term_ArgumentList(Term); while (!list_Empty(Scan1)) { Argterm = (TERM)list_Car(Scan1); Scan2 = list_Cdr(Scan1); if (symbol_Equal(term_TopSymbol(Argterm),fol_Or())) { SimpleOrSubTerm = cnf_FlattenToSimpleORTerm(Argterm); if (!SimpleOrSubTerm) SimpleOrTerm = FALSE; list_NInsert(Scan1,list_Cdr(term_ArgumentList(Argterm))); /* Be efficient ... */ list_Rplaca(Scan1,list_Car(term_ArgumentList(Argterm))); list_Free(term_ArgumentList(Argterm)); term_Free(Argterm); } else if (symbol_Equal(term_TopSymbol(Argterm),fol_And())) { SimpleOrTerm = FALSE; } Scan1 = Scan2; } } return SimpleOrTerm; } TERM cnf_ScanTree(TERM Tree) /************************************************************** INPUT: The input complex Term, which need to be transformed to CNF RETURNS: Traverse the term tree using BFS, and put the "or" subtree pointer into the stacks. CAUTION: The term is not changed. ***************************************************************/ { SYMBOL Symbol; LIST Temp; BOOL SimpleOrTerm; SimpleOrTerm = cnf_FlattenToSimpleORTerm(Tree); Symbol = term_TopSymbol(Tree); if (symbol_Equal(Symbol,fol_Or()) && (!SimpleOrTerm)) { stack_Push(Tree); } for (Temp=term_ArgumentList(Tree);!list_Empty(Temp);Temp=list_Cdr(Temp)) { cnf_ScanTree(list_Car(Temp)); } return Tree; } TERM cnf_CombineORTerms(TERM Term1, TERM Term2) /********************************************************** INPUT: Two OR Terms RETURNS: A big "OR" Term. Both argument lists are combined to be the new argument list of Term1. Term1 will be returned. MEMORY: Term2 will be freed. ***********************************************************/ { list_Nconc(term_ArgumentList(Term1), term_ArgumentList(Term2)); term_Free(Term2); return Term1; } TERM cnf_AddAtomToORTerm(TERM AtomTerm, TERM OrTerm) /********************************************************** INPUT: First arg is an Atom Term, second arg is an OR Term RETURNS: Atom Term will be added into the argumentlist of OR Term CAUTION: Atom Term is used, no copy or creation occured ***********************************************************/ { LIST ArgumentList; ArgumentList = list_Cons(AtomTerm, term_ArgumentList(OrTerm)); term_RplacArgumentList(OrTerm, ArgumentList); return OrTerm; } TERM cnf_BuildORTermFromAtoms(TERM Atom1, TERM Atom2) /********************************************************** INPUT: Two atom Terms RETURNS: An OR Term containing the input atom Terms as subterms MEMORY: One new list created, one new Term created. ***********************************************************/ { LIST ArgumentList; ArgumentList = list_List(Atom1); ArgumentList = list_Cons(Atom2, ArgumentList); return term_Create(fol_Or(), ArgumentList); } LIST cnf_List_MultiCons(LIST TempResultList, LIST RightCNFAndArgument) /********************************************************** INPUT: Two list of CNF list. RETURNS: One big CNF list after "multiplications" CAUTION: Both input lists will be destructed and deleted afterwards The content of these lists are reused in the result. New list is generated for the result ***********************************************************/ { LIST NewResult, Scan1, Scan2; TERM NewTerm, Term1, Term2; SYMBOL Symbol1, Symbol2; BOOL BreakOut; NewResult = list_Nil(); BreakOut = FALSE; for (Scan1=TempResultList;!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) { for (Scan2=RightCNFAndArgument;!list_Empty(Scan2);Scan2=list_Cdr(Scan2)) { Term1 = list_Car(Scan1); Term2 = list_Car(Scan2); if (!list_Empty(list_Cdr(Scan2))) { Term1 = term_Copy(Term1); } if (!list_Empty(list_Cdr(Scan1))) { Term2 = term_Copy(Term2); } Symbol1 = term_TopSymbol(Term1); Symbol2 = term_TopSymbol(Term2); /*Case analysis:*/ if (symbol_Equal(Symbol1,fol_Or()) && symbol_Equal(Symbol2,fol_Or())) { if((!list_Empty(list_Cdr(Scan1))) && list_Empty(list_Cdr(Scan2))) { NewTerm = cnf_CombineORTerms(Term2, Term1); } else { NewTerm = cnf_CombineORTerms(Term1, Term2); } } else if ((symbol_Equal(Symbol1,fol_Or())) && (!symbol_Equal(Symbol2,fol_Or()))) { NewTerm = cnf_AddAtomToORTerm(Term2, Term1); } else if ((!symbol_Equal(Symbol1,fol_Or())) && (symbol_Equal(Symbol2,fol_Or()))) { NewTerm = cnf_AddAtomToORTerm(Term1, Term2); } else { NewTerm = cnf_BuildORTermFromAtoms(Term1, Term2); } NewResult = list_Cons( NewTerm, NewResult); } } /* The list is not yet deleted*/ list_Delete(RightCNFAndArgument); list_Delete(TempResultList); NewResult = term_DestroyDuplicatesInList(NewResult); /*Debugging Code*/ /* printf("\nAfter multiplication, the new Result contains:"); for (Scan1= NewResult; !list_Empty(Scan1); Scan1=list_Cdr(Scan1)) { printf("\n"); term_Print(list_Car(Scan1));fflush(stdout); } */ return NewResult; } void cnf_SeparateAndTermsFromArgList(LIST* Input, LIST* AndList, LIST* AtomList, LIST* AndTail, LIST* AtomTail) /************************************************************** INPUT: A Pointer to Input Argument List A Pointer to AndList, which will be filled with And subterms A Pointer to AtomList,which will be filled with Atom subterms A Pointer to AndTail, the last element of AndList A Pointer to AtomTail, the last element of AtomList EFFECTS: All the arguments will be initialised. The given Input List (Argumentst) will be separated to AndList and AtomList. MEMORY: No memory allocation occurs here. The input argumentlist might become either AndList or AtomList, depending on the head element of it. ***************************************************************/ { LIST Scan1,Scan2; Scan1=*Input; while(!list_Empty(Scan1)) { Scan2 = list_Cdr(Scan1); list_Rplacd(Scan1,list_Nil()); if (symbol_Equal(term_TopSymbol(list_Car(Scan1)), fol_And())) { if (list_Empty(*AndList)){ *AndList = Scan1; } else { list_Rplacd(*AndTail,Scan1); } *AndTail = Scan1; } else { if (list_Empty(*AtomList)){ *AtomList = Scan1; } else { list_Rplacd(*AtomTail,Scan1); } *AtomTail = Scan1; } Scan1=Scan2; } /*Debugging Code*/ /* printf("\nAfter cnf_SeparateAtomOrAndTermsFrom:."); printf("\nAnd list:."); for (Scan1= *AndList; !list_Empty(Scan1); Scan1=list_Cdr(Scan1)) { printf("\n"); term_Print(list_Car(Scan1));fflush(stdout); } printf("\nAtom list:."); for (Scan1= *AtomList; !list_Empty(Scan1); Scan1=list_Cdr(Scan1)) { printf("\n"); term_Print(list_Car(Scan1));fflush(stdout); } printf("\nInput list:."); for (Scan1= *Input; !list_Empty(Scan1); Scan1=list_Cdr(Scan1)) { printf("\n"); term_Print(list_Car(Scan1));fflush(stdout); } */ } LIST cnf_MakeBigAndList(LIST AndList) /************************************************************** INPUT: Build the list of OR SubTerms of a big AND Term RETURNS: The argumentlist of the big AND Term CAUTION: The content of the big AND list will be reused but the list itself is no more useful. The input list is deleted here. ***************************************************************/ { LIST Result, Scan; Result = term_ArgumentList(list_Car(AndList)); for (Scan=list_Cdr(AndList);!list_Empty(Scan);Scan=list_Cdr(Scan)) { Result = cnf_List_MultiCons(Result, term_ArgumentList(list_Car(Scan))); term_Free(list_Car(Scan)); } term_Free(list_Car(AndList)); list_Delete(AndList); return Result; } void cnf_AttachAtomList(LIST* ResultCandidate, LIST AtomList) /************************************************************** INPUT: A candidate list containing either flattened OR Terms or atom Terms; A list containing only Atom Terms EFFECT: The candidate list will be manipulated, so that all subTerms are extended with the AtomList. CAUTION: Destructive on candidate list. The AtomList is useful afterwards, i.e. shouldn't be deleted. ***************************************************************/ { LIST Scan, Temp, AttachAtomList; for (Scan = *ResultCandidate;!list_Empty(Scan);Scan=list_Cdr(Scan)){ if (!list_Empty(list_Cdr(Scan))) { AttachAtomList = term_CopyTermList(AtomList); } else { AttachAtomList = AtomList; } if(symbol_Equal(term_TopSymbol(list_Car(Scan)), fol_Or())) {/*OR subterm*/ Temp = term_ArgumentList(list_Car(Scan)); Temp = list_Nconc(Temp, AttachAtomList); Temp = term_DestroyDuplicatesInList(Temp); term_RplacArgumentList(list_Car(Scan), Temp); } else {/*single atom*/ Temp = list_Cons(list_Car(Scan), AttachAtomList); Temp = term_DestroyDuplicatesInList(Temp); list_Rplaca(Scan, term_Create(fol_Or(), Temp)); } } } void cnf_TransformTree(NAT StackBottom) /************************************************************** INPUT: The NAT flag of stack bottom. EFFECTS: Go through the "or" subtrees bottom up by processing the Stack and convert the poped out subtree to CNF subtree CAUTION: The poped out subterm and the overall Term is distructively changed. ***************************************************************/ { TERM Term; LIST Result, Scan, ArgList, AtomList, AndList, AtomTail, AndTail; while (!stack_Empty(StackBottom)) { Term = stack_PopResult(); for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) { cnf_Flatten(list_Car(Scan), fol_And()); } AndList = list_Nil(); AtomList = list_Nil(); AndTail = list_Nil(); AtomTail = list_Nil(); ArgList = term_ArgumentList(Term); cnf_SeparateAndTermsFromArgList(&ArgList , &AndList, &AtomList,&AndTail, &AtomTail ); if (!list_Empty(AndList)) {/*The Term is not a simple OR Term, contains And subterms*/ Result = cnf_MakeBigAndList(AndList); if (!list_Empty(AtomList)) {/*The Term contains both AND and Atom sub terms */ cnf_AttachAtomList(&Result, AtomList); } term_RplacTop(Term, fol_And()); term_RplacArgumentList(Term,Result); } /* printf("\nSubOrTerm-After-Transformation: \n"); term_Print(Term);fflush(stdout); */ } } static TERM cnf_DistributiveFormula(TERM Formula) /************************************************************** INPUT: A Formula in NNF which consists only of disjunctions and conjunctions. RETURNS: The Formula where the distributivity rule is exhaustively applied and all disjunctions and the top level conjunction are grouped. CAUTION: The Formula is destructively changed. ***************************************************************/ { NAT StackBottom; if (symbol_Equal(term_TopSymbol(Formula), fol_Or()) || symbol_Equal(term_TopSymbol(Formula), fol_And())) { StackBottom = stack_Bottom(); cnf_ScanTree(Formula); cnf_TransformTree(StackBottom); cnf_Flatten(Formula, fol_And()); } return Formula; } void cnf_FPrintClause(TERM term, FILE* file) /************************************************************** INPUT: A term and a file pointer. RETURNS: Nothing. EFFECT: Print the term which contains only disjunctions to file. The disjunctions represent a clause. ***************************************************************/ { TERM term1; LIST scan; int bottom; bottom = vec_ActMax(); vec_Push(term); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (symbol_Equal(term_TopSymbol(term1),fol_Or())) { for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); }else term_FPrint(file,term1); } fputs(".\n", file); vec_SetMax(bottom); } void cnf_FPrint(TERM term, FILE* file) /************************************************************** INPUT: A term and a file pointer. RETURNS: Nothing. EFFECT: Print the term (in negation normal form) which contains only conjunctions of disjunctions to file. The conjunctions are interpreted to represent different clauses. ***************************************************************/ { TERM term1; LIST scan; int bottom; bottom = vec_ActMax(); vec_Push(term); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (symbol_Equal(term_TopSymbol(term1),fol_And())) { for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); }else if (symbol_Equal(term_TopSymbol(term1),fol_Or()) || symbol_IsPredicate(term_TopSymbol(term1)) || symbol_Equal(term_TopSymbol(term1),fol_Not())) cnf_FPrintClause(term1,file); } vec_SetMax(bottom); } void cnf_StdoutPrint(TERM term) /************************************************************** INPUT: A term. RETURNS: Nothing. EFFECT: Print the term (in negation normal form) which contains only conjunctions of disjunctions to standard out. The conjunctions are interpreted to represent different clauses. ***************************************************************/ { LIST termlist,scan,scan1; for (scan=term_ArgumentList(term); !list_Empty(scan); scan=list_Cdr(scan)) { termlist = list_Nil(); if (!(symbol_IsPredicate(term_TopSymbol(list_Car(scan))) || fol_IsNegativeLiteral(list_Car(scan)))) termlist = term_ArgumentList(list_Car(scan)); if (!list_Empty(termlist)) { for (scan1=termlist;!list_Empty(scan1);scan1=list_Cdr(scan1)) term_Print(list_Car(scan1)); puts("."); }else{ term_Print(list_Car(scan)); puts("."); } } } void cnf_FilePrint(TERM term, FILE* file) /************************************************************** INPUT: A term and a file. RETURNS: Nothing. EFFECT: Print the term (in negation normal form) which contains only conjunctions of disjunctions to file. The conjunctions are interpreted to represent different clauses. ***************************************************************/ { LIST termlist,scan,scan1; for (scan=term_ArgumentList(term); !list_Empty(scan); scan=list_Cdr(scan)) { termlist = list_Nil(); if (!(symbol_IsPredicate(term_TopSymbol(list_Car(scan))) || fol_IsNegativeLiteral(list_Car(scan)))) termlist = term_ArgumentList(list_Car(scan)); if (!list_Empty(termlist)) { for (scan1=termlist;!list_Empty(scan1);scan1=list_Cdr(scan1)) term_FPrint(file,list_Car(scan1)); fputs(".\n", file); }else{ term_FPrint(file,list_Car(scan)); fputs(".\n", file); } } } void cnf_FilePrintPrefix(TERM term, FILE* file) /************************************************************** INPUT: A term and a file pointer. RETURNS: Nothing. EFFECT: Prefix Print the term (in negation normal form) which contains only conjunctions of disjunctions to file. The conjunctions are interpreted to represent different clauses. ***************************************************************/ { LIST termlist,scan,scan1; for (scan=term_ArgumentList(term);!list_Empty(scan);scan=list_Cdr(scan)) { termlist = list_Nil(); if (!(symbol_IsPredicate(term_TopSymbol(list_Car(scan))) || fol_IsNegativeLiteral(list_Car(scan)))) termlist = term_ArgumentList(list_Car(scan)); if (!list_Empty(termlist)) { for (scan1=termlist;!list_Empty(scan1);scan1=list_Cdr(scan1)) { term_FPrintPrefix(file,list_Car(scan1)); if (!list_Empty(list_Cdr(scan1))) fputs(" | ", file); } fputs(".\n", file); } else { term_FPrintPrefix(file,list_Car(scan)); fputs(".\n", file); } } } static LIST cnf_SubsumeClauseList(FLAGSTORE Flags, LIST clauselist) /********************************************************** INPUT: A list of clauses. RETURNS: The list of clauses without subsumed clauses. EFFECT: Checks the clock cnf_REDUCTION with respect to the value of flag_CNFREDTIME to permit subsumption reductions. CAUTION: The list is destructively changed. ***********************************************************/ { LIST scan; st_INDEX stindex; CLAUSE actclause; stindex = st_IndexCreate(); for (scan = clauselist; !list_Empty(scan); scan=list_Cdr(scan)) res_InsertClauseIndex(list_Car(scan),stindex); scan=clauselist; while (!list_Empty(scan)) { actclause = list_Car(scan); res_DeleteClauseIndex(actclause,stindex); if (res_BackSubWithLength(actclause,stindex)) { clause_Delete(actclause); list_Rplaca(scan,(POINTER)NULL); } else res_InsertClauseIndex(actclause,stindex); if (flag_GetFlagIntValue(Flags,flag_CNFREDTIMELIMIT) != flag_CNFREDTIMELIMITUNLIMITED && flag_GetFlagIntValue(Flags,flag_CNFREDTIMELIMIT) <= ceil(clock_GetSeconds(clock_CNFREDUCTION))) scan = list_Nil(); else scan = list_Cdr(scan); } clauselist = list_PointerDeleteElement(clauselist, (POINTER)NULL); st_IndexDelete(stindex); return clauselist; } static LIST cnf_MakeClauseList(TERM term, BOOL Sorts, BOOL Conclause, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A term in cnf and two boolean values indicating whether sorts should be generated and whether the generated clauses are Conclauses, a flag store and a precedence. RETURNS: A list of clauses with respect to term. The terms in the new clauses are the copied subterms from term. EFFECT: The flag store and the precedence are not changed, but they're needed for creating clauses. Checks the clock cnf_REDUCTION with respect to the value of flag_CNFREDTIME to permit condesing and subsumption reductions. ***************************************************************/ { LIST termlist,scan,clauselist,condlist; CLAUSE clause; int j; termlist = list_Nil(); clauselist = list_Nil(); if (fol_IsTrue(term)) return clauselist; if (fol_IsNegativeLiteral(term) || symbol_IsPredicate(term_TopSymbol(term))) { termlist = list_List(term_Copy(term)); clause = clause_CreateFromLiterals(termlist, Sorts, Conclause,TRUE, Flags, Precedence); clauselist = list_Nconc(clauselist,list_List(clause)); term_StartMinRenaming(); term_Rename(clause_GetLiteralTerm(clause,0)); list_Delete(termlist); return clauselist; } term = cnf_MakeOneAndTerm(term); if (symbol_Equal(term_TopSymbol(term), fol_And())) { for (scan=term_ArgumentList(term); !list_Empty(scan); scan=list_Cdr(scan)) { list_Rplaca(scan, cnf_MakeOneOrTerm(list_Car(scan))); termlist = list_Nil(); if (!(symbol_IsPredicate(term_TopSymbol(list_Car(scan))) || fol_IsNegativeLiteral(list_Car(scan)))) { termlist = term_CopyTermList(term_ArgumentList(list_Car(scan))); termlist = term_DestroyDuplicatesInList(termlist); } else termlist = list_List(term_Copy(list_Car(scan))); if (!list_Empty(termlist)) { clause = clause_CreateFromLiterals(termlist, Sorts, Conclause, TRUE, Flags, Precedence); term_StartMinRenaming(); for (j = 0; j < clause_Length(clause); j++) term_Rename(clause_GetLiteralTerm(clause,j)); clauselist = list_Cons(clause,clauselist); list_Delete(termlist); } } } else { /* Here the term is a disjunction, i.e. there is only one clause */ term = cnf_MakeOneOrTerm(term); if (!(symbol_IsPredicate(term_TopSymbol(term)) || fol_IsNegativeLiteral(term))) { termlist = term_CopyTermList(term_ArgumentList(term)); termlist = term_DestroyDuplicatesInList(termlist); } else termlist = list_List(term_Copy(term)); if (!list_Empty(termlist)) { clause = clause_CreateFromLiterals(termlist, Sorts, Conclause, TRUE, Flags, Precedence); term_StartMinRenaming(); for (j = 0; j < clause_Length(clause); j++) term_Rename(clause_GetLiteralTerm(clause,j)); clauselist = list_Cons(clause,clauselist); list_Delete(termlist); } } for (scan=clauselist; !list_Empty(scan); scan=list_Cdr(scan)) { clause = (CLAUSE)list_Car(scan); if (res_HasTautology(clause)) { clause_Delete(clause); list_Rplaca(scan, (POINTER)NULL); } else if (flag_GetFlagIntValue(Flags, flag_CNFCON) == flag_ON) { condlist = cond_CondFast(clause); if (!list_Empty(condlist)) clause_DeleteLiterals(clause, condlist, Flags, Precedence); list_Delete(condlist); } if (flag_GetFlagIntValue(Flags,flag_CNFREDTIMELIMIT) != flag_CNFREDTIMELIMITUNLIMITED && flag_GetFlagIntValue(Flags,flag_CNFREDTIMELIMIT) <= ceil(clock_GetSeconds(clock_CNFREDUCTION))) { flag_SetFlagIntValue(Flags, flag_CNFCON, flag_OFF); flag_SetFlagIntValue(Flags, flag_CNFSUB, flag_OFF); } } clauselist = list_PointerDeleteElement(clauselist, (POINTER)NULL); if (flag_GetFlagIntValue(Flags, flag_CNFSUB) == flag_ON) clauselist = cnf_SubsumeClauseList(Flags, clauselist); return clauselist; } TERM cnf_Flatten(TERM Term, SYMBOL Symbol) /************************************************************** INPUT: A and that is assumed to be associative. RETURNS: If the top symbol of is the is flattened as long as it contains further direct subterms starting with CAUTION: The term is destructively changed. ***************************************************************/ { LIST Scan1,Scan2; if (symbol_Equal(term_TopSymbol(Term), Symbol)) { TERM Argterm; Scan1 =term_ArgumentList(Term); while (!list_Empty(Scan1)) { Argterm = (TERM)list_Car(Scan1); Scan2 = list_Cdr(Scan1); if (symbol_Equal(term_TopSymbol(Argterm),Symbol)) { cnf_Flatten(Argterm,Symbol); list_NInsert(Scan1,list_Cdr(term_ArgumentList(Argterm))); /* Be efficient ... */ list_Rplaca(Scan1,list_Car(term_ArgumentList(Argterm))); list_Free(term_ArgumentList(Argterm)); term_Free(Argterm); } Scan1 = Scan2; } } return Term; } static TERM cnf_FlattenPath(TERM Term, TERM PredicateTerm) /************************************************************** INPUT: A and that is assumed to be associative, and a predicate term which is a subterm of term RETURNS: If the top symbol of is the is flattened as long as it contains further direct subterms starting with CAUTION: The term is destructively changed. ***************************************************************/ { TERM subterm; subterm = Term; while (symbol_Equal(term_TopSymbol(subterm), fol_All())) subterm = term_SecondArgument(subterm); if (symbol_Equal(term_TopSymbol(subterm), fol_Or())) { TERM Argterm; LIST scan1; scan1 = term_ArgumentList(subterm); while (!list_Empty(scan1)) { LIST scan2; Argterm = (TERM)list_Car(scan1); scan2 = list_Cdr(scan1); if (term_HasProperSuperterm(PredicateTerm, Argterm)) { if (symbol_Equal(term_TopSymbol(Argterm),fol_Or())) { LIST l; cnf_Flatten(Argterm,fol_Or()); for (l=term_ArgumentList(Argterm); !list_Empty(l); l=list_Cdr(l)) term_RplacSuperterm((TERM) list_Car(l), subterm); list_NInsert(scan1,list_Cdr(term_ArgumentList(Argterm))); /* Be efficient ... */ list_Rplaca(scan1,list_Car(term_ArgumentList(Argterm))); list_Free(term_ArgumentList(Argterm)); term_Free(Argterm); } } scan1 = scan2; } } return Term; } static void cnf_DistrQuantorNoVarSub(TERM Term) /************************************************************** INPUT: A formula in negation normal form starting with a universal (existential) quantifier and a disjunction (conjunction) as argument. EFFECT: The Quantor is distributed if possible. CAUTION: The term is destructively changed. ***************************************************************/ { LIST Variables,Subformulas,Scan1,Scan2,Rest; TERM Subterm,Var,NewForm; SYMBOL Subtop,Top; Top = term_TopSymbol(Term); Variables = list_Copy(fol_QuantifierVariables(Term)); Subterm = term_SecondArgument(Term); Subtop = term_TopSymbol(Subterm); Subterm = cnf_Flatten(Subterm,Subtop); for (Scan1=Variables;!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) { Subformulas = list_Nil(); Var = (TERM)list_Car(Scan1); for (Scan2=term_ArgumentList(Subterm);!list_Empty(Scan2);Scan2=list_Cdr(Scan2)) if (!fol_VarOccursFreely(Var,list_Car(Scan2))) Subformulas = list_Cons(list_Car(Scan2),Subformulas); if (!list_Empty(Subformulas)) { Rest = list_NPointerDifference(term_ArgumentList(Subterm),Subformulas); if (list_Empty(list_Cdr(Rest))) { /* One subformula */ if (symbol_Equal(Top,term_TopSymbol(list_Car(Rest)))) { /* Optimization: quantifier still exist */ NewForm = (TERM)list_Car(Rest); term_RplacArgumentList(term_FirstArgument(NewForm), list_Cons((POINTER)Var,fol_QuantifierVariables(NewForm))); list_Delete(Rest); } else NewForm = fol_CreateQuantifier(Top,list_List((POINTER)Var),Rest); } else NewForm = fol_CreateQuantifier(Top,list_List((POINTER)Var),list_List(term_Create(Subtop,Rest))); term_RplacArgumentList(Subterm,list_Cons(NewForm,Subformulas)); term_RplacArgumentList(term_FirstArgument(Term), list_PointerDeleteElement(fol_QuantifierVariables(Term),(POINTER)Var)); } } if (list_Empty(fol_QuantifierVariables(Term))) { /* All variables moved inside */ term_Free(term_FirstArgument(Term)); list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,Subtop); term_RplacArgumentList(Term,term_ArgumentList(Subterm)); term_Free(Subterm); } list_Delete(Variables); } static TERM cnf_AntiPrenex(TERM Term) /************************************************************** INPUT: A formula in negation normal form. RETURNS: The term after application of anti-prenexing. Quantifiers are moved inside as long as possible. CAUTION: The term is destructively changed. ***************************************************************/ { LIST Scan; SYMBOL Top; Top = term_TopSymbol(Term); if (fol_IsQuantifier(Top)) { TERM Subterm,Actterm; SYMBOL DistrSymb,Subtop; /* The junctor the respective quantifier distributes over */ Subterm = term_SecondArgument(Term); Subtop = term_TopSymbol(Subterm); if (!symbol_IsPredicate(Subtop) && !symbol_Equal(Subtop,fol_Not())) { /* Formula in NNF: No Literals or Atoms */ if (symbol_Equal(Top,fol_All())) DistrSymb = fol_And(); else DistrSymb = fol_Or(); if (fol_IsQuantifier(Subtop)) { cnf_AntiPrenex(Subterm); Subtop = term_TopSymbol(Subterm); } if (symbol_Equal(Subtop,DistrSymb)) { LIST Variables; LIST NewVars; Variables = fol_QuantifierVariables(Term); Subterm = cnf_Flatten(Subterm,DistrSymb); for (Scan=term_ArgumentList(Subterm);!list_Empty(Scan);Scan=list_Cdr(Scan)) { Actterm = (TERM)list_Car(Scan); NewVars = list_NIntersect(fol_FreeVariables(Actterm),Variables, (BOOL (*)(POINTER,POINTER))term_Equal); if (!list_Empty(NewVars)) { if (symbol_Equal(Top,term_TopSymbol(Actterm))) { /* Quantor already there */ term_CopyTermsInList(NewVars); term_RplacArgumentList(term_FirstArgument(Actterm), list_Nconc(fol_QuantifierVariables(Actterm), NewVars)); } else { term_CopyTermsInList(NewVars); list_Rplaca(Scan,fol_CreateQuantifier(Top, NewVars, list_List(Actterm))); } } } term_Delete(term_FirstArgument(Term)); /* Delete old variable list */ list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,DistrSymb); term_RplacArgumentList(Term,term_ArgumentList(Subterm)); term_Free(Subterm); for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) list_Rplaca(Scan,cnf_AntiPrenex(list_Car(Scan))); } else if (!fol_IsQuantifier(Subtop)) { cnf_DistrQuantorNoVarSub(Term); for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) cnf_AntiPrenex(list_Car(Scan)); } } } else if (!symbol_Equal(Top,fol_Not()) && !symbol_IsPredicate(Top)) for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) cnf_AntiPrenex(list_Car(Scan)); return Term; } static void cnf_DistrQuantorNoVarSubPath(TERM Term, TERM PredicateTerm) /************************************************************** INPUT: A formula in negation normal form starting with a universal (existential) quantifier and a disjunction (conjunction) as argument and a predicate term which is a subterm of term. CAUTION: The term is destructively changed. ***************************************************************/ { LIST Variables,Subformulas,Scan1,Scan2,Rest; TERM Subterm,Var,NewForm; SYMBOL Subtop,Top; /*fputs("\nAN0:\t",stdout);term_Print(Term);*/ Top = term_TopSymbol(Term); Variables = list_Copy(fol_QuantifierVariables(Term)); Subterm = term_SecondArgument(Term); Subtop = term_TopSymbol(Subterm); Subterm = cnf_Flatten(Subterm,Subtop); /*fputs("\nAN1:\t",stdout);term_Print(Subterm);*/ for (Scan1=Variables;!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) { Subformulas = list_Nil(); Var = (TERM)list_Car(Scan1); /* Find subterms in which the variable does not occur freely */ for (Scan2=term_ArgumentList(Subterm);!list_Empty(Scan2);Scan2=list_Cdr(Scan2)) if (!fol_VarOccursFreely(Var,list_Car(Scan2))) Subformulas = list_Cons(list_Car(Scan2),Subformulas); if (!list_Empty(Subformulas)) { /* Rest is the list of those subterms where the variable does occur freely */ Rest = list_NPointerDifference(term_ArgumentList(Subterm),Subformulas); if (list_Empty(list_Cdr(Rest))) { /* One subformula */ if (symbol_Equal(Top,term_TopSymbol(list_Car(Rest)))) { /* Optimization: quantifier still exist */ NewForm = (TERM)list_Car(Rest); /* Move one variable down */ term_RplacArgumentList(term_FirstArgument(NewForm), list_Cons((POINTER)Var,fol_QuantifierVariables(NewForm))); list_Delete(Rest); } else { NewForm = fol_CreateQuantifierAddFather(Top,list_List((POINTER)Var), Rest); } } else { TERM t; t = term_CreateAddFather(Subtop,Rest); NewForm = fol_CreateQuantifierAddFather(Top,list_List((POINTER)Var),list_List(t)); } if (term_HasProperSuperterm(PredicateTerm, NewForm)) NewForm = cnf_AntiPrenexPath(NewForm, PredicateTerm); term_RplacArgumentList(Subterm,list_Cons(NewForm,Subformulas)); term_RplacSuperterm(NewForm, Subterm); term_RplacArgumentList(term_FirstArgument(Term), list_PointerDeleteElement(fol_QuantifierVariables(Term),(POINTER)Var)); } } if (list_Empty(fol_QuantifierVariables(Term))) { /* All variables moved inside */ LIST l; term_Free(term_FirstArgument(Term)); list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,Subtop); term_RplacArgumentList(Term,term_ArgumentList(Subterm)); term_Free(Subterm); for (l=term_ArgumentList(Term); !list_Empty(l); l=list_Cdr(l)) term_RplacSuperterm((TERM) list_Car(l), Term); } list_Delete(Variables); } static TERM cnf_AntiPrenexPath(TERM Term, TERM PredicateTerm) /************************************************************** INPUT: A formula in negation normal form and a predicate term which is a subterm of term. RETURNS: The term after application of anti-prenexing. Quantifiers are moved inside along the path as long as possible. CAUTION: The term is destructively changed. ***************************************************************/ { LIST Scan; SYMBOL Top; Top = term_TopSymbol(Term); if (fol_IsQuantifier(Top)) { TERM Subterm,Actterm; SYMBOL DistrSymb,Subtop; /* The junctor the respective quantifier distributes over */ Subterm = term_SecondArgument(Term); Subtop = term_TopSymbol(Subterm); if (!symbol_Equal(Subtop,fol_Not()) && !symbol_IsPredicate(Subtop)) { /* No Literals or Atoms */ if (symbol_Equal(Top,fol_All())) DistrSymb = fol_And(); else DistrSymb = fol_Or(); if (fol_IsQuantifier(Subtop)) { cnf_AntiPrenexPath(Subterm, PredicateTerm); Subtop = term_TopSymbol(Subterm); } if (symbol_Equal(Subtop,DistrSymb)) { LIST Variables; LIST NewVars; Variables = fol_QuantifierVariables(Term); Subterm = cnf_Flatten(Subterm,DistrSymb); term_AddFatherLinks(Subterm); /* for (l=term_ArgumentList(Subterm); !list_Empty(l); l=list_Cdr(l)) term_RplacSuperterm((TERM) list_Car(l), Subterm); */ for (Scan=term_ArgumentList(Subterm);!list_Empty(Scan);Scan=list_Cdr(Scan)) { Actterm = (TERM)list_Car(Scan); NewVars = list_NIntersect(fol_FreeVariables(Actterm),Variables, (BOOL (*)(POINTER,POINTER))term_Equal); if (!list_Empty(NewVars)) { if (symbol_Equal(Top,term_TopSymbol(Actterm))) { /* Quantor already there */ term_CopyTermsInList(NewVars); term_RplacArgumentList(term_FirstArgument(Actterm), list_Nconc(fol_QuantifierVariables(Actterm), NewVars)); } else { term_CopyTermsInList(NewVars); list_Rplaca(Scan,fol_CreateQuantifierAddFather(Top, NewVars, list_List(Actterm))); } } } term_Delete(term_FirstArgument(Term)); /* Delete old variable list */ list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,DistrSymb); term_RplacArgumentList(Term,term_ArgumentList(Subterm)); term_Free(Subterm); term_AddFatherLinks(Term); for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) { term_RplacSuperterm((TERM) list_Car(Scan), Term); if (term_HasPointerSubterm((TERM) list_Car(Scan), PredicateTerm)) { puts("\ncheck1"); list_Rplaca(Scan,cnf_AntiPrenexPath(list_Car(Scan), PredicateTerm)); term_RplacSuperterm((TERM) list_Car(Scan), Term); } } } else if (!fol_IsQuantifier(Subtop)) { cnf_DistrQuantorNoVarSubPath(Term, PredicateTerm); for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) { if (term_HasPointerSubterm(list_Car(Scan), PredicateTerm)) cnf_AntiPrenexPath(list_Car(Scan), PredicateTerm); } } } } else if (!symbol_Equal(Top,fol_Not()) && !symbol_IsPredicate(Top)) for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) if (term_HasProperSuperterm(PredicateTerm, (TERM) list_Car(Scan))) cnf_AntiPrenexPath(list_Car(Scan), PredicateTerm); term_AddFatherLinks(Term); return Term; } static TERM cnf_RemoveTrivialOperators(TERM Term) /************************************************************** INPUT: A formula. RETURNS: The formula after removal of "or" and "and" with only one argument CAUTION: The term is destructively changed. ***************************************************************/ { SYMBOL Top; LIST Scan; Top = term_TopSymbol(Term); if (symbol_IsPredicate(Top)) return Term; if ((symbol_Equal(Top,fol_And()) || symbol_Equal(Top,fol_Or())) && list_Empty(list_Cdr(term_ArgumentList(Term)))) { TERM Result; Result = term_FirstArgument(Term); term_RplacSuperterm(Result, term_Superterm(Term)); list_Delete(term_ArgumentList(Term)); term_Free(Term); return cnf_RemoveTrivialOperators(Result); } for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) { list_Rplaca(Scan,cnf_RemoveTrivialOperators(list_Car(Scan))); term_RplacSuperterm((TERM) list_Car(Scan), Term); } return Term; } static TERM cnf_SimplifyQuantors(TERM Term) /************************************************************** INPUT: A formula. RETURNS: The formula after removal of bindings of variables that don't occur in the respective subformula and possible mergings of quantors CAUTION: The term is destructively changed. ***************************************************************/ { SYMBOL Top; LIST Scan; Top = term_TopSymbol(Term); if (symbol_IsPredicate(Top) || symbol_Equal(Top,fol_Varlist())) return Term; if (fol_IsQuantifier(Top)) { LIST Vars; TERM Var,Subterm,Aux; Vars = list_Nil(); Subterm = term_SecondArgument(Term); while (symbol_Equal(term_TopSymbol(Subterm),Top)) { term_RplacArgumentList(term_FirstArgument(Term), list_Nconc(fol_QuantifierVariables(Term),fol_QuantifierVariables(Subterm))); term_Free(term_FirstArgument(Subterm)); Aux = term_SecondArgument(Subterm); list_Delete(term_ArgumentList(Subterm)); term_Free(Subterm); list_Rplaca(list_Cdr(term_ArgumentList(Term)),Aux); Subterm = Aux; } for (Scan=fol_QuantifierVariables(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) { Var = (TERM)list_Car(Scan); if (!fol_VarOccursFreely(Var,Subterm)) Vars = list_Cons(Var,Vars); } if (!list_Empty(Vars)) { Subterm = term_FirstArgument(Term); term_RplacArgumentList(Subterm,list_NPointerDifference(term_ArgumentList(Subterm),Vars)); term_DeleteTermList(Vars); if (list_Empty(term_ArgumentList(Subterm))) { Subterm = term_SecondArgument(Term); term_Delete(term_FirstArgument(Term)); list_Delete(term_ArgumentList(Term)); term_Free(Term); return cnf_SimplifyQuantors(Subterm); } } } for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) list_Rplaca(Scan,cnf_SimplifyQuantors(list_Car(Scan))); return Term; } TERM cnf_RemoveTrivialAtoms(TERM Term) /************************************************************** INPUT: A formula. RETURNS: The formula where occurrences of the atoms "true" and "false" are propagated and eventually removed. CAUTION: The term is destructively changed. ***************************************************************/ { SYMBOL Top,Subtop; LIST Scan; TERM Result; BOOL Update; if (!term_IsComplex(Term)) return Term; Top = term_TopSymbol(Term); Update = FALSE; if (symbol_Equal(Top,fol_And())) { Scan = term_ArgumentList(Term); while (!list_Empty(Scan)) { Result = cnf_RemoveTrivialAtoms(list_Car(Scan)); Subtop = term_TopSymbol(Result); if (symbol_Equal(Subtop,fol_True())) Update = TRUE; else if (symbol_Equal(Subtop,fol_False())) { term_RplacTop(Term,fol_False()); term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term,list_Nil()); return Term; } Scan = list_Cdr(Scan); } if (Update) { term_RplacArgumentList(Term,fol_DeleteTrueTermFromList(term_ArgumentList(Term))); if (list_Empty(term_ArgumentList(Term))) { term_RplacTop(Term,fol_True()); return Term; } } } else if (symbol_Equal(Top,fol_Or())) { Scan = term_ArgumentList(Term); while (!list_Empty(Scan)) { Result = cnf_RemoveTrivialAtoms(list_Car(Scan)); Subtop = term_TopSymbol(Result); if (symbol_Equal(Subtop,fol_False())) Update = TRUE; else if (symbol_Equal(Subtop,fol_True())) { term_RplacTop(Term,fol_True()); term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term,list_Nil()); return Term; } Scan = list_Cdr(Scan); } if (Update) { term_RplacArgumentList(Term,fol_DeleteFalseTermFromList(term_ArgumentList(Term))); if (list_Empty(term_ArgumentList(Term))) { term_RplacTop(Term,fol_False()); return Term; } } } else if (fol_IsQuantifier(Top) || symbol_Equal(Top,fol_Not())) { if (fol_IsQuantifier(Top)) Result = cnf_RemoveTrivialAtoms(term_SecondArgument(Term)); else Result = cnf_RemoveTrivialAtoms(term_FirstArgument(Term)); Subtop = term_TopSymbol(Result); if ((symbol_Equal(Subtop,fol_False()) && symbol_Equal(Top,fol_Not())) || (symbol_Equal(Subtop,fol_True()) && fol_IsQuantifier(Top))) { term_RplacTop(Term,fol_True()); term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term,list_Nil()); return Term; } else if ((symbol_Equal(Subtop,fol_True()) && symbol_Equal(Top,fol_Not())) || (symbol_Equal(Subtop,fol_False()) && fol_IsQuantifier(Top))) { term_RplacTop(Term,fol_False()); term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term,list_Nil()); return Term; } } else if (symbol_Equal(Top,fol_Implies())) { Result = cnf_RemoveTrivialAtoms(term_FirstArgument(Term)); Subtop = term_TopSymbol(Result); if (symbol_Equal(Subtop,fol_False())) { term_RplacTop(Term,fol_True()); term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term,list_Nil()); return Term; } else if (symbol_Equal(Subtop,fol_True())) { term_Delete(Result); Result = term_SecondArgument(Term); list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,term_TopSymbol(Result)); term_RplacArgumentList(Term,term_ArgumentList(Result)); term_Free(Result); return cnf_RemoveTrivialAtoms(Term); } Result = cnf_RemoveTrivialAtoms(term_SecondArgument(Term)); Subtop = term_TopSymbol(Result); if (symbol_Equal(Subtop,fol_True())) { term_RplacTop(Term,fol_True()); term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term,list_Nil()); return Term; } else if (symbol_Equal(Subtop,fol_False())) { term_RplacTop(Term,fol_Not()); term_RplacArgumentList(Term,fol_DeleteFalseTermFromList(term_ArgumentList(Term))); } } else if (symbol_Equal(Top,fol_Equiv())) { Result = cnf_RemoveTrivialAtoms(term_FirstArgument(Term)); Subtop = term_TopSymbol(Result); if (symbol_Equal(Subtop,fol_False())) { term_RplacTop(Term,fol_Not()); term_RplacArgumentList(Term,fol_DeleteFalseTermFromList(term_ArgumentList(Term))); if (list_Empty(term_ArgumentList(Term))) { term_RplacTop(Term, fol_True()); return Term; } return cnf_RemoveTrivialAtoms(Term); } else if (symbol_Equal(Subtop,fol_True())) { term_Delete(Result); Result = term_SecondArgument(Term); list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,term_TopSymbol(Result)); term_RplacArgumentList(Term,term_ArgumentList(Result)); term_Free(Result); return cnf_RemoveTrivialAtoms(Term); } Result = cnf_RemoveTrivialAtoms(term_SecondArgument(Term)); Subtop = term_TopSymbol(Result); if (symbol_Equal(Subtop,fol_False())) { term_RplacTop(Term,fol_Not()); term_RplacArgumentList(Term,fol_DeleteFalseTermFromList(term_ArgumentList(Term))); } else if (symbol_Equal(Subtop,fol_True())) { term_Delete(Result); Result = term_FirstArgument(Term); list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,term_TopSymbol(Result)); term_RplacArgumentList(Term,term_ArgumentList(Result)); term_Free(Result); } } return Term; } TERM cnf_ObviousSimplifications(TERM Term) /************************************************************** INPUT: A formula. RETURNS: The formula after performing the following simplifications: - remove "or" and "and" with only one argument - remove bindings of variables that don't occur in the respective subformula - merge quantors CAUTION: The term is destructively changed. ***************************************************************/ { Term = cnf_RemoveTrivialAtoms(Term); Term = cnf_RemoveTrivialOperators(Term); Term = cnf_SimplifyQuantors(Term); return Term; } /* EK: warum wird Term zurueckgegeben, wenn er destruktiv geaendert wird??? */ static TERM cnf_SkolemFormula(TERM Term, FLAGSTORE Flags, PRECEDENCE Precedence, LIST* Symblist) /************************************************************** INPUT: A formula in negation normal form, a precedence and pointer to a list used as return value. RETURNS: The skolemized term and the list of introduced Skolem functions. CAUTION: The term is destructively changed. The precedence of the new Skolem functions is set in . ***************************************************************/ { SYMBOL Top,SkolemSymbol; TERM Subterm,SkolemTerm; LIST Varlist,Scan; NAT Arity; Top = term_TopSymbol(Term); if (fol_IsQuantifier(term_TopSymbol(Term))) { if (symbol_Equal(Top,fol_All())) { 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)); term_Free(Subterm); return cnf_SkolemFormula(Term, Flags, Precedence, Symblist); } else { /* exist quantifier */ /* Implementation of the quantifier exchange operator of Ohlbach & * Schmidt for the functional translation of modal logics K, KD. * Constants are introduced during Skolemisation */ if (flag_GetFlagIntValue(Flags, flag_CNFQUANTEXCH)) { Varlist = list_Nil(); Arity = 0; } else { Varlist = fol_FreeVariables(Term); Arity = list_Length(Varlist); } for (Scan=fol_QuantifierVariables(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) { SkolemSymbol = symbol_CreateSkolemFunction(Arity, Precedence); *Symblist = list_Cons((POINTER)SkolemSymbol, *Symblist); SkolemTerm = term_Create(SkolemSymbol,Varlist); /* Caution: Sharing of Varlist ! */ fol_ReplaceVariable(term_SecondArgument(Term),term_TopSymbol(list_Car(Scan)),SkolemTerm); term_Free(SkolemTerm); } list_Delete(Varlist); 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)); term_Free(Subterm); return cnf_SkolemFormula(Term, Flags, Precedence, Symblist); } } else if (symbol_Equal(Top,fol_And()) || symbol_Equal(Top,fol_Or())) for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) cnf_SkolemFormula(list_Car(Scan), Flags, Precedence, Symblist); return Term; } static TERM cnf_Cnf(TERM Term, FLAGSTORE Flags, PRECEDENCE Precedence, LIST* Symblist) /************************************************************** INPUT: A formula, a precedence and a pointer to a list of symbols used as return value. RETURNS: The term is transformed to conjunctive normal form. EFFECT: The term is destructively changed and not normalized. The precedence of new Skolem symbols is set in . ***************************************************************/ { /* Necessary because ren_Rename crashes if a e.g. and() has only one argument */ Term = cnf_ObviousSimplifications(Term); term_AddFatherLinks(Term); Term = ren_Rename(Term, Precedence, Symblist, FALSE, FALSE, flag_GetFlagIntValue(Flags, flag_CNFRENAMING)); Term = cnf_RemoveEquivImplFromFormula(Term); Term = cnf_NegationNormalFormula(Term); Term = cnf_SkolemFormula(cnf_AntiPrenex(Term), Flags, Precedence, Symblist); Term = cnf_DistributiveFormula(Term); return Term; } static LIST cnf_GetUsedTerms(CLAUSE C, PROOFSEARCH Search, HASHMAP InputClauseToTermLabellist) /************************************************************** INPUT: RETURNS: ***************************************************************/ { LIST UsedTerms, Used2, Scan; UsedTerms = list_Copy(hm_Retrieve(InputClauseToTermLabellist, C)); UsedTerms = cnf_DeleteDuplicateLabelsFromList(UsedTerms); if (!list_Empty(UsedTerms)) return UsedTerms; for (Scan = clause_ParentClauses(C); !list_Empty(Scan); Scan = list_Cdr(Scan)) { CLAUSE P; int ClauseNumber; ClauseNumber = (intptr_t)list_Car(Scan); P = clause_GetNumberedCl(ClauseNumber, prfs_WorkedOffClauses(Search)); if (P == NULL) { P = clause_GetNumberedCl(ClauseNumber, prfs_UsableClauses(Search)); if (P == NULL) P = clause_GetNumberedCl(ClauseNumber, prfs_DocProofClauses(Search)); } Used2 = cnf_GetUsedTerms(P, Search, InputClauseToTermLabellist); UsedTerms = list_Nconc(UsedTerms, Used2); } return UsedTerms; } static BOOL cnf_HaveProofOptSkolem(PROOFSEARCH Search, TERM topterm, char* toplabel, TERM term2, LIST* UsedTerms, LIST* Symblist, HASHMAP InputClauseToTermLabellist) /************************************************************** INPUT: RETURNS: ??? EK ***************************************************************/ { LIST ConClauses, EmptyClauses; LIST scan; BOOL found; LIST Usables; FLAGSTORE Flags; PRECEDENCE Precedence; Flags = prfs_Store(Search); Precedence = prfs_Precedence(Search); ConClauses = list_Nil(); found = FALSE; /* List of clauses from term2 */ term_AddFatherLinks(term2); term2 = cnf_Cnf(term2, Flags, Precedence, Symblist); Usables = cnf_MakeClauseList(term2, FALSE, FALSE, Flags, Precedence); term_Delete(term2); for (scan=Usables; !list_Empty(scan); scan = list_Cdr(scan)) { clause_SetFlag(list_Car(scan), CONCLAUSE); if (flag_GetFlagIntValue(Flags, flag_FPFCR) || flag_GetFlagIntValue(Flags, flag_DOCPROOF)) { hm_InsertListInsertUnique(InputClauseToTermLabellist, list_Car(scan), toplabel); #ifdef CHECK_CNF fputs("\nUsable : ", stdout); clause_Print(list_Car(scan)); printf(" Label %s", toplabel); #endif } } EmptyClauses = cnf_SatUnit(Search, Usables); if (!list_Empty(EmptyClauses)) { found = TRUE; #ifdef CHECK_CNF fputs("\nHaveProof : Empty Clause : ", stdout); clause_Print((CLAUSE) list_Car(EmptyClauses)); putchar('\n'); #endif if (flag_GetFlagIntValue(Flags, flag_FPFCR) || flag_GetFlagIntValue(Flags, flag_DOCPROOF)) *UsedTerms = list_Nconc(*UsedTerms, cnf_GetUsedTerms((CLAUSE) list_Car(EmptyClauses), Search, InputClauseToTermLabellist)); EmptyClauses = list_PointerDeleteDuplicates(EmptyClauses); clause_DeleteClauseList(EmptyClauses); } /* Removing ConClauses from UsablesIndex */ ConClauses = list_Copy(prfs_UsableClauses(Search)); for (scan = ConClauses; !list_Empty(scan); scan = list_Cdr(scan)) if (flag_GetFlagIntValue(Flags, flag_DOCPROOF)) prfs_MoveUsableDocProof(Search, (CLAUSE) list_Car(scan)); else prfs_DeleteUsable(Search, (CLAUSE) list_Car(scan)); list_Delete(ConClauses); return found; } BOOL cnf_HaveProof(LIST TermList, TERM ToProve, FLAGSTORE InputFlags, PRECEDENCE InputPrecedence) /************************************************************** INPUT: A list of terms, a term to prove, a flag store and a precedence. The arguments are not changed. RETURNS: True if the termlist implies ToProve CAUTION: All terms are copied. ***************************************************************/ { PROOFSEARCH search; LIST scan, usables, symblist, emptyclauses; BOOL found; FLAGSTORE Flags; PRECEDENCE Precedence; /* Use global PROOFSEARCH object to avoid stamp overflow */ search = cnf_HAVEPROOFPS; usables = symblist = list_Nil(); /* Initialize search object's flag store */ Flags = prfs_Store(search); flag_CleanStore(Flags); flag_InitFlotterSubproofFlags(InputFlags, Flags); /* Initialize search object's precedence */ Precedence = prfs_Precedence(search); symbol_TransferPrecedence(InputPrecedence, Precedence); /* Build list of clauses from the termlist */ for (scan=TermList; !list_Empty(scan); scan=list_Cdr(scan)) { TERM t; t = term_Copy(list_Car(scan)); t = cnf_Cnf(t, Flags, Precedence, &symblist); usables = list_Nconc(cnf_MakeClauseList(t,FALSE,FALSE,Flags,Precedence), usables); term_Delete(t); } /* Build clauses from negated term to prove */ ToProve = term_Create(fol_Not(), list_List(term_Copy(ToProve))); term_AddFatherLinks(ToProve); ToProve = cnf_Cnf(ToProve, Flags, Precedence, &symblist); usables = list_Nconc(cnf_MakeClauseList(ToProve,FALSE,FALSE,Flags,Precedence), usables); term_Delete(ToProve); /* SatUnit requires the CONCLAUSE flag */ for (scan=usables;!list_Empty(scan); scan = list_Cdr(scan)) clause_SetFlag(list_Car(scan), CONCLAUSE); emptyclauses = cnf_SatUnit(search, usables); if (!list_Empty(emptyclauses)) { found = TRUE; emptyclauses = list_PointerDeleteDuplicates(emptyclauses); clause_DeleteClauseList(emptyclauses); } else found = FALSE; prfs_Clean(search); symbol_DeleteSymbolList(symblist); return found; } static void cnf_RplacVarsymbFunction(TERM term, SYMBOL varsymb, TERM function) /********************************************************** INPUT: A term, a variable symbol and a function. EFFECT: The variable with the symbol varsymb in the term is replaced by the function function. CAUTION: The term is destructively changed. ***********************************************************/ { int bottom; TERM term1; LIST scan; bottom = vec_ActMax(); vec_Push(term); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (symbol_Equal(term_TopSymbol(term1),varsymb)) { term_RplacTop(term1,term_TopSymbol(function)); term_RplacArgumentList(term1,term_CopyTermList(term_ArgumentList(function))); }else if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); } vec_SetMax(bottom); } static void cnf_RplacVar(TERM Term, LIST Varlist, LIST Termlist) /********************************************************** INPUT: A term,a variable symbol and a function. RETURNS: The variable with the symbol varsymb in the term is replaced by the function function. CAUTION: The term is destructively changed. ***********************************************************/ { int bottom; TERM term1; LIST scan,scan2; bottom = vec_ActMax(); vec_Push(Term); while (bottom != vec_ActMax()) { term1 = vec_PopResult(); if (symbol_IsVariable(term_TopSymbol(term1))) { BOOL done; done = FALSE; for (scan=Varlist, scan2=Termlist; !list_Empty(scan) && !done; scan = list_Cdr(scan), scan2 = list_Cdr(scan2)) { if (symbol_Equal(term_TopSymbol(term1),term_TopSymbol(list_Car(scan)))) { term_RplacTop(term1,term_TopSymbol((TERM) list_Car(scan2))); term_RplacArgumentList(term1, term_CopyTermList(term_ArgumentList(list_Car(scan2)))); done = TRUE; } } } else if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); } vec_SetMax(bottom); } static TERM cnf_MakeSkolemFunction(LIST varlist, PRECEDENCE Precedence) /************************************************************** INPUT: A list of variables and a precedence. RETURNS: The new term oskf... (oskc...) which is a function with varlist as arguments. EFFECT: The precedence of the new Skolem function is set in . ***************************************************************/ { TERM term; SYMBOL skolem; skolem = symbol_CreateSkolemFunction(list_Length(varlist), Precedence); term = term_Create(skolem, term_CopyTermList(varlist)); return term; } static void cnf_PopAllQuantifier(TERM term) /******************************************************** INPUT: A term whose top symbol is fol_all. RETURNS: Nothing. EFFECT: Removes the quantifier ********************************************************/ { TERM SubTerm; LIST VarList; #ifdef CHECK if (!symbol_Equal(term_TopSymbol(term), fol_All())) { misc_StartErrorReport(); misc_ErrorReport("\n In cnf_PopAllQuantifier: Top symbol is not fol_All !\n"); misc_FinishErrorReport(); } #endif VarList = term_ArgumentList(term_FirstArgument(term)); term_DeleteTermList(VarList); term_Free(term_FirstArgument(term)); SubTerm = term_SecondArgument(term); list_Delete(term_ArgumentList(term)); term_RplacTop(term,term_TopSymbol(SubTerm)); term_RplacArgumentList(term,term_ArgumentList(SubTerm)); term_Free(SubTerm); } static TERM cnf_QuantifyAndNegate(TERM term, LIST VarList, LIST FreeList) /**************************************************************** INPUT: A term, a list of variables to be exist-quantified, a list of variables to be all-quantified RETURNS: not(forall[FreeList](exists[VarList](term))) MEMORY: The term, the lists and their arguments are copied. ***************************************************************/ { TERM Result; TERM TermCopy; LIST VarListCopy; LIST FreeListCopy; TermCopy = term_Copy(term); VarListCopy = term_CopyTermList(VarList); Result = fol_CreateQuantifier(fol_Exist(),VarListCopy,list_List(TermCopy)); FreeListCopy = list_Nil(); FreeList = fol_FreeVariables(Result); if (!list_Empty(FreeList)) { FreeListCopy = term_CopyTermList(FreeList); list_Delete(FreeList); Result = fol_CreateQuantifier(fol_All(), FreeListCopy, list_List(Result)); } Result = term_Create(fol_Not(), list_List(Result)); return Result; } static TERM cnf_MoveProvedTermToTopLevel(TERM Term, TERM Term1, TERM Proved, LIST VarList, LIST FreeList, PRECEDENCE Precedence) /******************************************************************** INPUT: A top-level term, which must be a conjunction, a subterm of , a subterm of , a list of existence quantified variables , a list of free variables and a precedence. is of the form exists[...](t1 and t2 and ... and Proved and ..) RETURNS: A new term, where is removed from the arguments of . EFFECT: The precedence of new Skolem functions is set in *******************************************************************/ { TERM termR; TERM skolemfunction; SYMBOL varsymb; LIST scan; termR = term_SecondArgument(Term1); /* t1 and t2 and ... and Proved ... */ term_RplacArgumentList(termR, list_PointerDeleteElement(term_ArgumentList(termR), Proved)); if (list_Length(term_ArgumentList(termR)) < 2) { TERM termRL = term_FirstArgument(termR); /* t1 */ list_Delete(term_ArgumentList(termR)); term_RplacTop(termR, term_TopSymbol(termRL)); term_RplacArgumentList(termR,term_ArgumentList(termRL)); term_Free(termRL); } for (scan = VarList; scan != list_Nil(); scan = list_Cdr(scan)) { varsymb = term_TopSymbol(list_Car(scan)); skolemfunction = cnf_MakeSkolemFunction(FreeList, Precedence); cnf_RplacVarsymbFunction(termR,varsymb,skolemfunction); cnf_RplacVarsymbFunction(Proved,varsymb,skolemfunction); term_Delete(skolemfunction); } if (!list_Empty(FreeList)) { Proved = fol_CreateQuantifier(fol_All(), term_CopyTermList(FreeList), list_List(Proved)); if (list_Length(FreeList) > 1) Proved = cnf_QuantMakeOneVar(Proved); } term_Delete(term_FirstArgument(Term1)); /* Variables of "exists" */ list_Delete(term_ArgumentList(Term1)); term_RplacTop(Term1,term_TopSymbol(termR)); term_RplacArgumentList(Term1,term_ArgumentList(termR)); term_Free(termR); term_RplacArgumentList(Term, list_Cons(Proved, term_ArgumentList(Term))); return Proved; } static void cnf_Skolemize(TERM Term, LIST FreeList, PRECEDENCE Precedence) /******************************************************** INPUT: A existence quantified term, the list of free variables and a precedence. RETURNS: Nothing. EFFECT: The term is destructively changed, i.e. the existence quantifier is removed by skolemization. The precedence of new Skolem functions is set in . *********************************************************/ { LIST exlist; TERM subterm; LIST symblist; symblist = list_Nil(); exlist = cnf_GetSymbolList(term_ArgumentList(term_FirstArgument(Term))); 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)); term_Free(subterm); symblist = cnf_SkolemFunctionFormula(Term, FreeList, exlist, Precedence); list_Delete(exlist); list_Delete(symblist); } static LIST cnf_FreeVariablesBut(TERM Term, LIST Symbols) /******************************************************** INPUT: A term and a list of symbols RETURNS: A list of all free variable terms in Term whose symbols are not in Symbols *********************************************************/ { LIST follist, Scan; follist = fol_FreeVariables(Term); for (Scan = follist; !list_Empty(Scan); Scan = list_Cdr(Scan)) if (list_Member(Symbols, (POINTER)term_TopSymbol(list_Car(Scan)), (BOOL (*)(POINTER,POINTER))symbol_Equal)) list_Rplaca(Scan,NULL); follist = list_PointerDeleteElement(follist,NULL); return follist; } static void cnf_SkolemFunctionFormulaMapped(TERM term, LIST allist, LIST map) /************************************************************** INPUT: A term term and a list allist of variables and a list map of pairs (variable symbols, function symbol) RETURNS: None. CAUTION: The term is destructively changed. All variable symbols in map which appear in term are replaced by the skolem functions with respect to allist which contains the universally quantified variables. ***************************************************************/ { TERM term1; LIST scan,scan1; SYMBOL skolem, symbol; int bottom; bottom = vec_ActMax(); for (scan1=map; !list_Empty(scan1); scan1=list_Cdr(scan1)) { vec_Push(term); symbol = (SYMBOL) list_PairFirst((LIST) list_Car(scan1)); skolem = (SYMBOL) list_PairSecond((LIST) list_Car(scan1)); #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(flag_PSTRSKOLEM)) { fputs("\nVariable : ", stdout); symbol_Print(symbol); fputs("\nFunction : ", stdout); symbol_Print(skolem); } #endif while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (symbol_Equal(term_TopSymbol(term1),symbol)) { term_RplacTop(term1,skolem); list_Delete(term_ArgumentList(term1)); term_RplacArgumentList(term1,term_CopyTermList(allist)); } if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) { vec_Push(list_Car(scan)); } } } vec_SetMax(bottom); } static BOOL cnf_HasDeeperVariable(LIST List1, LIST List2) /****************************************************************** INPUT: Two lists of variable terms RETURNS: TRUE if a variable in the first list is deeper than all variables in the second list, FALSE otherwise. NOTE: If cnf_VARIABLEDEPTHARRAY is not allocated this will crash If new variables are introduced by strong skolemization, their depth is -1. *******************************************************************/ { LIST scan; int maxdepth1; /* Determine maximum depth of variables in List1 */ maxdepth1 = 0; for (scan=List1; !list_Empty(scan); scan=list_Cdr(scan)) { int i; i = cnf_VARIABLEDEPTHARRAY[term_TopSymbol((TERM) list_Car(scan))]; #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(flag_PSTRSKOLEM)) { fputs("\nFor variable ", stdout); symbol_Print(term_TopSymbol((TERM) list_Car(scan))); printf(" depth is %d.", i); } #endif if (i > maxdepth1) maxdepth1 = i; } /* Compare with depth of variables in List2 */ for (scan=List2; !list_Empty(scan); scan=list_Cdr(scan)) { int i; i = cnf_VARIABLEDEPTHARRAY[term_TopSymbol((TERM) list_Car(scan))]; #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(flag_PSTRSKOLEM)) { fputs("\nFor variable ", stdout); symbol_Print(term_TopSymbol((TERM) list_Car(scan))); printf(" depth is %d.", i); } #endif if (i >= maxdepth1) return FALSE; } return TRUE; } static void cnf_StrongSkolemization(PROOFSEARCH Search, TERM Topterm, char* Toplabel, BOOL TopAnd, TERM Term, LIST* UsedTerms, LIST* Symblist, BOOL Result1, HASHMAP InputClauseToTermLabellist, int Depth) /****************************************************************** INPUT: An existence quantified formula. ??? EK RETURNS: Nothing. EFFECT: The existence quantifier is removed by strong skolemization. The precedence of new Skolem symbols is set in the precedence of the search object. *******************************************************************/ { LIST exlist; /* Variable symbols bound by exists[]() */ LIST pairlist; /* List of pairs (Subterm of AND, free variable symbols not in exlist) */ LIST allfreevariables; LIST newvariables; /* w2..wn*/ LIST mapping; /* List of pairs */ int numberofallfreevariables, acc_length, i; LIST pair, pairscan, pairscan_pred, scan, accumulatedvariables; TERM subterm, w; BOOL strskolemsuccess; /* Indicates whether strong skolemization was possible */ FLAGSTORE Flags; PRECEDENCE Precedence; Flags = prfs_Store(Search); Precedence = prfs_Precedence(Search); /* Necessary so that new variables really are new ! */ if (flag_GetFlagIntValue(Flags, flag_CNFSTRSKOLEM)) symbol_SetStandardVarCounter(term_MaxVar(Topterm)); /* Get list of quantified variable symbols x_k */ exlist = cnf_GetSymbolList(term_ArgumentList(term_FirstArgument(Term))); /* Pop quantifier */ 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)); term_Free(subterm); /* Now for every argument get the list of free variables whose symbols are not in exlist */ pairlist = list_Nil(); for (scan=term_ArgumentList(Term); !list_Empty(scan); scan = list_Cdr(scan)) { pair = list_PairCreate((TERM) list_Car(scan), cnf_FreeVariablesBut((TERM) list_Car(scan), exlist)); if (list_Empty(pairlist)) pairlist = list_List(pair); else { /* First sort subterms by number of free variables */ int pairlength, currentlength; pairlength = list_Length((LIST) list_PairSecond(pair)); pairscan = pairlist; pairscan_pred = list_Nil(); currentlength = 0; while (!list_Empty(pairscan)) { currentlength = list_Length((LIST) list_PairSecond((LIST) list_Car(pairscan))); if (currentlength < pairlength) { pairscan_pred = pairscan; pairscan = list_Cdr(pairscan); } else if (currentlength == pairlength) { /* If both subterms have the same number of free variables compare depth of variables */ if (cnf_HasDeeperVariable((LIST) list_PairSecond((LIST) list_Car(pairscan)), /* in list */ (LIST) list_PairSecond(pair))) { /* new pair */ #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(flag_PSTRSKOLEM)) { fputs("\nTerm ", stdout); term_Print((TERM) list_PairFirst((LIST) list_Car(pairscan))); fputs("\n has deeper variable than ", stdout); term_Print((TERM) list_PairFirst(pair)); } #endif pairscan_pred = pairscan; pairscan = list_Cdr(pairscan); } else break; } else break; } /* New pair has more variables than all others in list */ if (list_Empty(pairscan)) list_Rplacd(pairscan_pred, list_List(pair)); /* New pair is inserted between pairscan_pred and pairscan */ else if (currentlength >= pairlength) { /* Head of list */ if (list_Empty(pairscan_pred)) pairlist = list_Cons(pair, pairlist); else list_InsertNext(pairscan_pred, pair); } /* The case for the same number of variables is not yet implemented */ } } #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(flag_PSTRSKOLEM)) { for (pairscan=pairlist; !list_Empty(pairscan); pairscan = list_Cdr(pairscan)) { LIST l; fputs("\nSubterm ", stdout); term_Print((TERM) list_PairFirst((LIST) list_Car(pairscan))); fputs("\n has free variables ", stdout); for (l=(LIST) list_PairSecond((LIST) list_Car(pairscan)); !list_Empty(l); l = list_Cdr(l)) { term_Print((TERM) list_Car(l)); fputs(" ", stdout); } } } #endif /* Determine number of all free variablein and()--term whose symbols are not in exlist */ /* Create map from ex_variables tp skolem symbols */ allfreevariables = cnf_FreeVariablesBut(Term, exlist); numberofallfreevariables = list_Length(allfreevariables); mapping = list_Nil(); for (scan = exlist; !list_Empty(scan); scan = list_Cdr(scan)) { SYMBOL skolem; skolem = symbol_CreateSkolemFunction(numberofallfreevariables, Precedence); *Symblist = list_Cons((POINTER)skolem,*Symblist); mapping = list_Cons(list_PairCreate(list_Car(scan), (POINTER)skolem), mapping); } list_Delete(allfreevariables); /* Create new variables */ newvariables = list_Nil(); for (i=0; i < numberofallfreevariables; i++) { w = term_CreateStandardVariable(); newvariables = list_Cons(w, newvariables); } #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(flag_PSTRSKOLEM)) { LIST l; fputs("\nNew variables : ", stdout); for (l=newvariables; !list_Empty(l); l = list_Cdr(l)) { term_Print((TERM) list_Car(l)); fputs(" ", stdout); } } #endif /* Now do the replacing */ accumulatedvariables = list_Nil(); acc_length = 0; strskolemsuccess = FALSE; for (pairscan=pairlist; !list_Empty(pairscan); pairscan=list_Cdr(pairscan)) { LIST allist; /* Add bound variables for this subterm */ accumulatedvariables = list_Nconc(accumulatedvariables, (LIST) list_PairSecond((LIST) list_Car(pairscan))); accumulatedvariables = term_DeleteDuplicatesFromList(accumulatedvariables); /* Remove new variables not (no longer) needed */ for (i=0; i < list_Length(accumulatedvariables) - acc_length; i++) { term_Delete((TERM) list_Top(newvariables)); newvariables = list_Pop(newvariables); } acc_length = list_Length(accumulatedvariables); #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(flag_PSTRSKOLEM)) { LIST l; fputs("\n\nSubterm is ", stdout); term_Print((TERM) list_PairFirst((LIST) list_Car(pairscan))); fputs("\nFree variables : ", stdout); for (l=accumulatedvariables; !list_Empty(l); l = list_Cdr(l)) { term_Print((TERM) list_Car(l)); fputs(" ", stdout); } } #endif if (!list_Empty(newvariables)) strskolemsuccess = TRUE; allist = list_Nconc(list_Copy(accumulatedvariables), list_Copy(newvariables)); cnf_SkolemFunctionFormulaMapped((TERM) list_PairFirst((LIST) list_Car(pairscan)), allist, mapping); #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(flag_PSTRSKOLEM)) { fputs("\nSubterm after skolemization : ", stdout); term_Print(list_PairFirst((LIST) list_Car(pairscan))); } #endif list_Delete(allist); cnf_OptimizedSkolemFormula(Search, Topterm, Toplabel, TopAnd, (TERM) list_PairFirst((LIST) list_Car(pairscan)), UsedTerms, Symblist, Result1, InputClauseToTermLabellist, Depth); } while (!list_Empty(newvariables)) { term_Delete((TERM) list_Top(newvariables)); newvariables = list_Pop(newvariables); } list_Delete(accumulatedvariables); /* Only pairs and pairlist left */ list_DeletePairList(pairlist); list_Delete(exlist); list_DeletePairList(mapping); if (flag_GetFlagIntValue(Flags, flag_PSTRSKOLEM) && strskolemsuccess) { fputs("\nStrong skolemization applied", stdout); } } static void cnf_OptimizedSkolemFormula(PROOFSEARCH Search, TERM topterm, char* toplabel, BOOL TopAnd, TERM term, LIST* UsedTerms, LIST* Symblist, BOOL Result1, HASHMAP InputClauseToTermLabellist, int Depth) /************************************************************** INPUT: Two terms in negation normal form. ??? EK RETURNS: The skolemized term with the optimized skolemization due to Ohlbach and Weidenbach of and further improvements. is used as additional, conjunctively added information. EFFECT: The symbol precedence of the search object is changed because new Skolem symbols are defined. Checks the clock cnf_REDUCTION with respect to the value of flag_CNFREDTIME to permit optimized Skolemization steps. CAUTION: The term is destructively changed. ***************************************************************/ { TERM termL2, provedterm; LIST freevariables, scan, varlist; SYMBOL top; BOOL result2; BOOL optimized; FLAGSTORE Flags; PRECEDENCE Precedence; result2 = FALSE; freevariables = list_Nil(); Flags = prfs_Store(Search); Precedence = prfs_Precedence(Search); top = term_TopSymbol(term); if (fol_IsQuantifier(top)) { if (symbol_Equal(top,fol_All())) { /* For quantified variables store depth if strong skolemization is performed */ if (flag_GetFlagIntValue(Flags, flag_CNFSTRSKOLEM)) { LIST variables; variables = term_ArgumentList(term_FirstArgument(term)); for (scan=variables; !list_Empty(scan); scan=list_Cdr(scan)) { #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(Flags, flag_PSTRSKOLEM)) { if (cnf_VARIABLEDEPTHARRAY[term_TopSymbol(list_Car(scan))] != -1) { fputs("\nFor variable ", stderr); term_Print((TERM) list_Car(scan)); printf(" depth is already set to %d, now setting it to %d", cnf_VARIABLEDEPTHARRAY[term_TopSymbol(list_Car(scan))],Depth); } } #endif #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(Flags, flag_PSTRSKOLEM)) { fputs("\nVariable ", stdout); term_Print((TERM) list_Car(scan)); printf(" has depth %d in term\n ", Depth); term_Print(term); } #endif cnf_VARIABLEDEPTHARRAY[term_TopSymbol(list_Car(scan))] = Depth; } Depth++; } cnf_PopAllQuantifier(term); cnf_OptimizedSkolemFormula(Search,topterm, toplabel, TopAnd, term, UsedTerms, Symblist, Result1, InputClauseToTermLabellist, Depth); return; } freevariables = fol_FreeVariables(term); optimized = FALSE; if (symbol_Equal(term_TopSymbol(term_SecondArgument(term)), fol_And())) { if (flag_GetFlagIntValue(Flags, flag_CNFOPTSKOLEM)) { scan = term_ArgumentList(term_SecondArgument(term)); varlist = term_ArgumentList(term_FirstArgument(term)); while (!list_Empty(scan) && !optimized) { if (!Result1) { if (TopAnd) { if (flag_GetFlagIntValue(Flags, flag_POPTSKOLEM)) { fputs("\nHaveProof not necessary", stdout); } result2 = TRUE; } else { termL2 = cnf_QuantifyAndNegate((TERM) list_Car(scan), varlist, freevariables); result2 = cnf_HaveProofOptSkolem(Search, topterm, toplabel, termL2, UsedTerms, Symblist, InputClauseToTermLabellist); if (flag_GetFlagIntValue(Flags,flag_CNFREDTIMELIMIT) != flag_CNFREDTIMELIMITUNLIMITED && flag_GetFlagIntValue(Flags,flag_CNFREDTIMELIMIT) <= ceil(clock_GetSeconds(clock_CNFREDUCTION))) flag_SetFlagIntValue(Flags, flag_CNFOPTSKOLEM, flag_OFF); #ifdef CHECK_OPTSKOLEM if (flag_GetFlagIntValue(Flags, flag_POPTSKOLEM)) { fputs("\nHaveProof result : ", stdout); if (result2) fputs("TRUE", stdout); else fputs("FALSE", stdout); } #endif } } if (Result1 || result2) { optimized = TRUE; if (flag_GetFlagIntValue(Flags, flag_POPTSKOLEM)) { fputs("\nIn term ", stdout); term_Print(topterm); fputs("\n subterm ", stdout); term_Print((TERM) list_Car(scan)); puts(" is moved to toplevel."); } provedterm = cnf_MoveProvedTermToTopLevel(topterm, term, list_Car(scan), varlist, freevariables, Precedence); if (flag_GetFlagIntValue(Flags, flag_POPTSKOLEM)) { fputs("Result : ", stdout); term_Print(topterm); putchar('\n'); } /* provedterm is argument of top AND term */ cnf_OptimizedSkolemFormula(Search, topterm, toplabel, TRUE, provedterm,UsedTerms, Symblist, Result1, InputClauseToTermLabellist, Depth); } else scan = list_Cdr(scan); } } if (!optimized) { /* Optimized skolemization not enabled or not possible */ if (flag_GetFlagIntValue(Flags, flag_CNFSTRSKOLEM)) { optimized = TRUE; /* Strong Skolemization is always possible after exists[..](and(..)) */ cnf_StrongSkolemization(Search, topterm, toplabel, TopAnd, term, UsedTerms, Symblist, Result1, InputClauseToTermLabellist, Depth); } } } else TopAnd = FALSE; if (!optimized) { /* Optimized skolemization not enabled or not possible */ /* Strong skolemization not enabled or not possible */ cnf_Skolemize(term, freevariables, Precedence); } list_Delete(freevariables); cnf_OptimizedSkolemFormula(Search, topterm, toplabel, TopAnd, term,UsedTerms, Symblist,Result1,InputClauseToTermLabellist,Depth); return; } else { if (symbol_Equal(top,fol_And()) || symbol_Equal(top,fol_Or())) { if (symbol_Equal(top,fol_Or())) TopAnd = FALSE; for (scan=term_ArgumentList(term);!list_Empty(scan); scan=list_Cdr(scan)) cnf_OptimizedSkolemFormula(Search, topterm, toplabel, TopAnd, (TERM) list_Car(scan), UsedTerms, Symblist, Result1, InputClauseToTermLabellist, Depth); } } return; } static LIST cnf_SkolemFunctionFormula(TERM term, LIST allist, LIST exlist, PRECEDENCE Precedence) /************************************************************** INPUT: A term , a list of variables, a list of variable symbols and a precedence. RETURNS: The list of new Skolem functions. EFFECT: The term is destructively changed. All variable symbols in which appear in are replaced by skolem functions with respect to which contains the universally quantified variables. New Skolem functions are created and their precedence is set in . ***************************************************************/ { TERM term1; LIST scan, scan1, Result; SYMBOL skolem; int bottom,n; Result = list_Nil(); bottom = vec_ActMax(); n = list_Length(allist); for (scan1=exlist; !list_Empty(scan1); scan1=list_Cdr(scan1)) { vec_Push(term); skolem = symbol_CreateSkolemFunction(n, Precedence); Result = list_Cons((POINTER)skolem, Result); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (symbol_Equal(term_TopSymbol(term1),(SYMBOL)list_Car(scan1))) { term_RplacTop(term1,skolem); list_Delete(term_ArgumentList(term1)); term_RplacArgumentList(term1,term_CopyTermList(allist)); } if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); } } vec_SetMax(bottom); return Result; } static LIST cnf_OptimizedSkolemization(PROOFSEARCH Search, TERM Term, char* Label, LIST* UsedTerms, LIST* Symblist, BOOL result, BOOL Conjecture, HASHMAP InputClauseToTermLabellist) /************************************************************** INPUT: A term, a shared index and a list of non-ConClauses. ??? EK RETURNS: The list of clauses derived from Term. EFFECT: The term is skolemized using optimized skolemization wrt ShIndex. **************************************************************/ { LIST Clauses; TERM FirstArg; int i; FLAGSTORE Flags; PRECEDENCE Precedence; #ifdef CHECK if (Term == NULL) { misc_StartErrorReport(); misc_ErrorReport("\n In cnf_OptimizedSkolemization: Input term is NULL.\n"); misc_FinishErrorReport(); } #endif Flags = prfs_Store(Search); Precedence = prfs_Precedence(Search); FirstArg = Term; if (flag_GetFlagIntValue(Flags, flag_CNFSTRSKOLEM)) { /* Initializing array */ for (i = 1; i <= symbol__MAXSTANDARDVAR; i++) cnf_VARIABLEDEPTHARRAY[i] = -1; } if (flag_GetFlagIntValue(Flags, flag_POPTSKOLEM) || flag_GetFlagIntValue(Flags, flag_PSTRSKOLEM)) { fputs("\nTerm before skolemization : \n ", stdout); fol_PrettyPrintDFG(Term); } if (!fol_IsLiteral(Term)) { if (flag_GetFlagIntValue(Flags, flag_CNFOPTSKOLEM) || flag_GetFlagIntValue(Flags, flag_CNFSTRSKOLEM)) { if (flag_GetFlagIntValue(Flags, flag_CNFOPTSKOLEM)) Term = term_Create(fol_And(), list_List(Term)); /* CW hack: definitions are added on top level*/ cnf_OptimizedSkolemFormula(Search, Term, Label, TRUE, FirstArg, UsedTerms, Symblist, result, InputClauseToTermLabellist, 0); } else { LIST Symbols; Symbols = list_Nil(); Term = cnf_SkolemFormula(Term, Flags, Precedence, &Symbols); list_Delete(Symbols); } } if (flag_GetFlagIntValue(Flags, flag_POPTSKOLEM) || flag_GetFlagIntValue(Flags, flag_PSTRSKOLEM)) { fputs("\nTerm after skolemization : ", stdout); term_Print(Term); } Term = cnf_DistributiveFormula(Term); Clauses = cnf_MakeClauseList(Term, FALSE, Conjecture, Flags, Precedence); term_Delete(Term); return Clauses; } LIST cnf_GetSkolemFunctions(TERM Term, LIST ArgList, LIST* SkolToExVar) /************************************************************** INPUT: A term, the argumentlist of a skolem function, a mapping from a skolem function to a variable RETURNS: The longest argumentlist of all skolem functions found so far. EFFECT: Computes information for renaming variables and replacing skolem functions during de-skolemization. **************************************************************/ { LIST Scan; SYMBOL Top; Top = term_TopSymbol(Term); if (fol_IsQuantifier(Top)) return cnf_GetSkolemFunctions(term_SecondArgument(Term), ArgList, SkolToExVar); if (symbol_IsFunction(Top) && symbol_HasProperty(Top, SKOLEM)) { BOOL found; SYMBOL Var = 0; int Arity; found = FALSE; /* Keep longest argument list of all skolem functions in the clause for renaming */ /* Delete all other argument lists */ Arity = list_Length(term_ArgumentList(Term)); if (Arity > list_Length(ArgList)) { term_DeleteTermList(ArgList); ArgList = term_ArgumentList(Term); } else term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term, NULL); /* Replace skolem function by variable */ if (list_Length(*SkolToExVar) > Arity) { NAT i; LIST SkolScan = *SkolToExVar; for (i = 0; i < Arity; i++) SkolScan = list_Cdr(SkolScan); for (SkolScan = (LIST) list_Car(SkolScan); (SkolScan != list_Nil()) && !found; SkolScan = list_Cdr(SkolScan)) { SYMBOL Skol; Skol = (SYMBOL) list_PairFirst((LIST) list_Car(SkolScan)); if (Skol == term_TopSymbol(Term)) { Var = (SYMBOL) list_PairSecond((LIST) list_Car(SkolScan)); found = TRUE; } } } if (!found) { LIST Pair; NAT i; LIST SkolScan; SkolScan = *SkolToExVar; for (i = 0; i < Arity; i++) { if (list_Cdr(SkolScan) == list_Nil()) list_Rplacd(SkolScan, list_List(NULL)); SkolScan = list_Cdr(SkolScan); } Var = symbol_CreateStandardVariable(); Pair = list_PairCreate((POINTER) term_TopSymbol(Term), (POINTER) Var); if (list_Car(SkolScan) == list_Nil()) list_Rplaca(SkolScan, list_List(Pair)); else list_Rplaca(SkolScan, list_Nconc((LIST) list_Car(SkolScan), list_List(Pair))); } term_RplacTop(Term, Var); } else { for (Scan = term_ArgumentList(Term); Scan != list_Nil(); Scan = list_Cdr(Scan)) ArgList = cnf_GetSkolemFunctions((TERM) list_Car(Scan), ArgList, SkolToExVar); } return ArgList; } void cnf_ReplaceVariable(TERM Term, SYMBOL Old, SYMBOL New) /************************************************************** INPUT: A term, two symbols that are variables EFFECT: In term every occurrence of Old is replaced by New **************************************************************/ { LIST Scan; #ifdef CHECK if (!symbol_IsVariable(Old)) { misc_StartErrorReport(); misc_ErrorReport("\n In cnf_ReplaceVariable: Illegal input symbol.\n"); misc_FinishErrorReport(); } #endif if (symbol_Equal(term_TopSymbol(Term), Old)) term_RplacTop(Term, New); else for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) cnf_ReplaceVariable(list_Car(Scan), Old, New); } LIST cnf_RemoveSkolemFunctions(CLAUSE Clause, LIST* SkolToExVar, LIST Vars) /************************************************************** INPUT: A clause, a list which is a mapping from skolem functions to variables and a list of variables for forall-quantification. RETURNS: A list of terms derived from the clause using deskolemization EFFECT: Arguments of skolem functions are renamed consistently. Skolemfunctions are replaced by variables. **************************************************************/ { LIST Scan; LIST TermScan, TermList, ArgList; TERM Term; int i; TermList = list_Nil(); ArgList = list_Nil(); for (i = 0; i < clause_Length(Clause); i++) { Term = term_Copy(clause_GetLiteralTerm(Clause, i)); ArgList = cnf_GetSkolemFunctions(Term, ArgList, SkolToExVar); TermList = list_Cons(Term, TermList); } if (list_Empty(ArgList)) return TermList; /* Rename variables */ for (Scan = ArgList; Scan != list_Nil(); Scan = list_Cdr(Scan)) { for (TermScan = TermList; TermScan != list_Nil(); TermScan = list_Cdr(TermScan)) { Term = (TERM) list_Car(TermScan); cnf_ReplaceVariable(Term, term_TopSymbol((TERM) list_Car(Scan)), (SYMBOL) list_Car(Vars)); } if (list_Cdr(Vars) == list_Nil()) { SYMBOL New = symbol_CreateStandardVariable(); Vars = list_Nconc(Vars, list_List((POINTER) New)); } Vars = list_Cdr(Vars); } term_DeleteTermList(ArgList); return TermList; } TERM cnf_DeSkolemFormula(LIST Clauses) /************************************************************** INPUT: A list of clauses. RETURNS: A formula built from the clauses. EFFECT: All skolem functions are removed from the clauses. **************************************************************/ { LIST Scan, SkolToExVar, Vars, FreeVars, FreeVarsCopy, VarScan, TermList; TERM VarListTerm, TopTerm, Term; BOOL First; SkolToExVar = list_List(NULL); Vars = list_List((POINTER) symbol_CreateStandardVariable()); TopTerm = term_Create(fol_And(), NULL); for (Scan = Clauses; Scan != list_Nil(); Scan = list_Cdr(Scan)) { TermList = cnf_RemoveSkolemFunctions((CLAUSE) list_Car(Scan), &SkolToExVar, Vars); Term = term_Create(fol_Or(), TermList); FreeVars = fol_FreeVariables(Term); if (!list_Empty(FreeVars)) { FreeVarsCopy = term_CopyTermList(FreeVars); list_Delete(FreeVars); Term = fol_CreateQuantifier(fol_All(), FreeVarsCopy, list_List(Term)); } term_RplacArgumentList(TopTerm, list_Cons(Term, term_ArgumentList(TopTerm))); } VarScan = Vars; First = TRUE; for (Scan = SkolToExVar; Scan != list_Nil(); Scan = list_Cdr(Scan)) { if (list_Empty(list_Car(Scan))) { if (term_TopSymbol(TopTerm) == fol_All()) term_RplacArgumentList(TopTerm, list_Cons(term_Create((SYMBOL) list_Car(VarScan), NULL), term_ArgumentList(TopTerm))); if (!First) TopTerm = fol_CreateQuantifier(fol_All(), list_List(term_Create((SYMBOL) list_Car(VarScan), NULL)), list_List(TopTerm)); } else { LIST ExVarScan; LIST ExVars = list_Nil(); for (ExVarScan = list_Car(Scan); ExVarScan != list_Nil(); ExVarScan = list_Cdr(ExVarScan)) { if (ExVars == list_Nil()) ExVars = list_List(term_Create((SYMBOL) list_PairSecond((LIST) list_Car(ExVarScan)), NULL)); else ExVars = list_Cons(term_Create((SYMBOL) list_PairSecond((LIST) list_Car(ExVarScan)), NULL), ExVars); list_PairFree((LIST) list_Car(ExVarScan)); } list_Delete((LIST) list_Car(Scan)); list_Rplaca(Scan, NULL); if (term_TopSymbol(TopTerm) == fol_Exist()) { VarListTerm = (TERM) list_Car(term_ArgumentList(TopTerm)); term_RplacArgumentList(VarListTerm, list_Nconc(term_ArgumentList(VarListTerm), ExVars)); } else TopTerm = fol_CreateQuantifier(fol_Exist(), ExVars, list_List(TopTerm)); ExVars = list_Nil(); if (!First) TopTerm = fol_CreateQuantifier(fol_All(), list_List(term_Create((SYMBOL) list_Car(VarScan), NULL)), list_List(TopTerm)); } if (!First) VarScan = list_Cdr(VarScan); else First = FALSE; } list_Delete(SkolToExVar); list_Delete(Vars); return TopTerm; } #ifdef OPTCHECK /* Currently unused */ /*static */ LIST cnf_CheckOptimizedSkolemization(LIST* AxClauses, LIST* ConClauses, TERM AxTerm, TERM ConTerm, LIST NonConClauses, LIST* SkolemPredicates, SHARED_INDEX ShIndex, BOOL result) /********************************************************** EFFECT: Used to check the correctness of optimized skolemization ***********************************************************/ { TERM DeSkolemizedAxOpt, DeSkolemizedConOpt, DeSkolemizedAx, DeSkolemizedCon; TERM TopOpt, Top, ToProve; LIST SkolemFunctions2; if (*AxClauses != list_Nil()) { DeSkolemizedAxOpt = cnf_DeSkolemFormula(*AxClauses); if (*ConClauses != list_Nil()) { DeSkolemizedConOpt = cnf_DeSkolemFormula(*ConClauses); TopOpt = term_Create(fol_And(), list_Cons(DeSkolemizedAxOpt, list_List(DeSkolemizedConOpt))); } else TopOpt = DeSkolemizedAxOpt; } else { DeSkolemizedConOpt = cnf_DeSkolemFormula(*ConClauses); TopOpt = DeSkolemizedConOpt; } clause_DeleteClauseList(*AxClauses); clause_DeleteClauseList(*ConClauses); *AxClauses = list_Nil(); *ConClauses = list_Nil(); flag_SetFlagIntValue(flag_CNFOPTSKOLEM, flag_CNFOPTSKOLEMOFF); if (AxTerm) { *AxClauses = cnf_OptimizedSkolemization(term_Copy(AxTerm), ShIndex, NonConClauses, result,FALSE, ClauseToTermLabellist); } if (ConTerm) { *ConClauses = cnf_OptimizedSkolemization(term_Copy(ConTerm), ShIndex, NonConClauses, result,TRUE, ClauseToTermLabellist); } if (*AxClauses != list_Nil()) { DeSkolemizedAx = cnf_DeSkolemFormula(*AxClauses); if (*ConClauses != list_Nil()) { DeSkolemizedCon = cnf_DeSkolemFormula(*ConClauses); Top = term_Create(fol_And(), list_Cons(DeSkolemizedAx, list_List(DeSkolemizedCon))); } else Top = DeSkolemizedAx; } else { DeSkolemizedCon = cnf_DeSkolemFormula(*ConClauses); Top = DeSkolemizedCon; } clause_DeleteClauseList(*AxClauses); clause_DeleteClausList(*ConClauses); *AxClauses = list_Nil(); *ConClauses = list_Nil(); ToProve = term_Create(fol_Equiv(), list_Cons(TopOpt, list_List(Top))); ToProve = term_Create(fol_Not(), list_List(ToProve)); fol_NormalizeVars(ToProve); ToProve = cnf_ObviousSimplifications(ToProve); term_AddFatherLinks(ToProve); ToProve = ren_Rename(ToProve,SkolemPredicates,FALSE); ToProve = cnf_RemoveEquivImplFromFormula(ToProve); ToProve = cnf_NegationNormalFormula(ToProve); ToProve = cnf_AntiPrenex(ToProve); SkolemFunctions2 = list_Nil(); ToProve = cnf_SkolemFormula(ToProve, &SkolemFunctions2); ToProve = cnf_DistributiveFormula(ToProve); *ConClauses = cnf_MakeClauseList(ToProve); if (ToProve) term_Delete(ToProve); *AxClauses = list_Nil(); return SkolemFunctions2; } #endif PROOFSEARCH cnf_Flotter(LIST AxiomList, LIST ConjectureList, LIST* AxClauses, LIST* AllLabels, HASHMAP TermLabelToClauselist, HASHMAP ClauseToTermLabellist, FLAGSTORE InputFlags, PRECEDENCE InputPrecedence, LIST* Symblist) /************************************************************** INPUT: A list of axiom formulae, a list of conjecture formulae, a pointer to a list in which clauses derived from axiom formulae are stored, a pointer to a list in which clauses derived from conjecture formulae are stored, ??? a pointer to a list of all termlabels, a hashmap in which for every term label the list of clauses derived from the term is stored (if DocProof is set), a hashmap in which for every clause the list of labels of the terms used for deriving the clause is stored (if DocProof is set), a flag store, a precedence a pointer to a list of symbols which have to be deleted later if the ProofSearch object is kept. RETURNS: If KeepProofSearch ??? is TRUE, then the ProofSearch object is not freed but returned. Else, NULL is returned. EFFECT: Initializes and checks the clock_CNFREDUCTION clock with respect to the flag_CNFREDTIME value for usable reduction time including optimized Skolemization, condensing and subsumption testing. The precedence of new skolem symbols is set in . ***************************************************************/ { LIST Scan, Scan2, FormulaClauses,SkolemFunctions; LIST SkolemPredicates, EmptyClauses, AllFormulae; LIST UsedTerms; TERM AxTerm,Formula; BOOL Result; PROOFSEARCH Search; PRECEDENCE Precedence; FLAGSTORE Flags; NAT Count; HASHMAP InputClauseToTermLabellist; clock_InitCounter(clock_CNFREDUCTION); Search = prfs_Create(); /* Initialize the flagstore for the CNF transformation */ Flags = prfs_Store(Search); flag_CleanStore(Flags); flag_InitFlotterFlags(InputFlags, Flags); /* Initialize the precedence */ Precedence = prfs_Precedence(Search); symbol_TransferPrecedence(InputPrecedence, Precedence); if (flag_GetFlagIntValue(Flags, flag_DOCPROOF)) prfs_AddDocProofSharingIndex(Search); AxTerm = (TERM)NULL; SkolemPredicates = list_Nil(); Result = FALSE; if (flag_GetFlagIntValue(Flags, flag_FPFCR) || flag_GetFlagIntValue(Flags, flag_DOCPROOF)) InputClauseToTermLabellist = hm_Create(0, hm_PointerHash, hm_PointerEqual, FALSE); else InputClauseToTermLabellist = NULL; symbol_ReinitGenericNameCounters(); for (Scan = AxiomList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { LIST Pair; Pair = list_Car(Scan); AxTerm = (TERM) list_PairSecond(Pair); fol_RemoveImplied(AxTerm); AxTerm = fol_RemoveXorNorNand(AxTerm); term_AddFatherLinks(AxTerm); fol_NormalizeVars(AxTerm); if (flag_GetFlagIntValue(Flags, flag_CNFFEQREDUCTIONS)) cnf_PropagateSubstEquations(AxTerm); AxTerm = cnf_ObviousSimplifications(AxTerm); if (flag_GetFlagIntValue(Flags, flag_CNFRENAMING)) { term_AddFatherLinks(AxTerm); AxTerm = ren_Rename(AxTerm, Precedence, &SkolemPredicates, flag_GetFlagIntValue(Flags, flag_CNFPRENAMING), flag_GetFlagIntValue(Flags, flag_CNFRENMATCH), flag_GetFlagIntValue(Flags, flag_CNFRENAMING)); } AxTerm = cnf_RemoveEquivImplFromFormula(AxTerm); AxTerm = cnf_NegationNormalFormula(AxTerm); AxTerm = cnf_AntiPrenex(AxTerm); list_Rplacd(Pair, (LIST) AxTerm); } AllFormulae = AxiomList; /* At this point the list contains max. 1 element, which is a pair of the label NULL and the negated conjunction of all conjecture formulae. */ Count = 0; for (Scan = ConjectureList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { TERM ConTerm; char* Label; char buf[100]; /* Add label */ if (list_PairFirst(list_Car(Scan)) == NULL) { sprintf(buf, "conjecture%zu", Count); Label = string_StringCopy(buf); list_Rplaca((LIST) list_Car(Scan), Label); if ((flag_GetFlagIntValue(Flags, flag_DOCPROOF) || flag_GetFlagIntValue(Flags, flag_FLOTTER)) && flag_GetFlagIntValue(Flags, flag_PLABELS)) { printf("\nAdded label %s for conjecture", Label); fol_PrettyPrintDFG((TERM) list_PairSecond(list_Car(Scan))); } } ConTerm = (TERM) list_PairSecond((LIST) list_Car(Scan)); fol_RemoveImplied(ConTerm); ConTerm = fol_RemoveXorNorNand(ConTerm); term_AddFatherLinks(ConTerm); fol_NormalizeVars(ConTerm); if (flag_GetFlagIntValue(Flags, flag_CNFFEQREDUCTIONS)) cnf_PropagateSubstEquations(ConTerm); ConTerm = cnf_ObviousSimplifications(ConTerm); if (flag_GetFlagIntValue(Flags, flag_CNFRENAMING)) { term_AddFatherLinks(ConTerm); ConTerm = ren_Rename(ConTerm, Precedence, &SkolemPredicates, flag_GetFlagIntValue(Flags, flag_CNFPRENAMING), flag_GetFlagIntValue(Flags, flag_CNFRENMATCH), flag_GetFlagIntValue(Flags, flag_CNFRENAMING)); } /* fputs("\nRen:\t",stdout);term_Print(ConTerm);putchar('\n'); */ ConTerm = cnf_RemoveEquivImplFromFormula(ConTerm); ConTerm = cnf_NegationNormalFormula(ConTerm); /* fputs("\nAn:\t",stdout);term_Print(ConTerm);putchar('\n'); */ ConTerm = cnf_AntiPrenex(ConTerm); /* fputs("\nPr:\t",stdout);term_Print(ConTerm);putchar('\n'); */ /* Insert changed term into pair */ list_Rplacd((LIST) list_Car(Scan), (LIST) ConTerm); Count++; } AllFormulae = list_Append(ConjectureList, AllFormulae); for (Scan = ConjectureList;!list_Empty(Scan); Scan = list_Cdr(Scan)) list_Rplaca(Scan,list_PairSecond(list_Car(Scan))); FormulaClauses = list_Nil(); SkolemFunctions = list_Nil(); Count = 0; clock_StartCounter(clock_CNFREDUCTION); if (flag_GetFlagIntValue(Flags, flag_CNFOPTSKOLEM) == flag_ON) { for (Scan = AllFormulae; !list_Empty(Scan); Scan = list_Cdr(Scan), Count++) { LIST FormulaClausesTemp; Formula = term_Copy((TERM) list_PairSecond(list_Car(Scan))); #ifdef CHECK_CNF fputs("\nInputFormula : ",stdout); term_Print(Formula); printf("\nLabel : %s\n", (char*) list_PairFirst(list_Car(Scan))); #endif Formula = cnf_SkolemFormula(Formula,Flags,Precedence,&SkolemFunctions); Formula = cnf_DistributiveFormula(Formula); FormulaClausesTemp = cnf_MakeClauseList(Formula,FALSE,FALSE,Flags,Precedence); if (flag_GetFlagIntValue(Flags, flag_FPFCR) || flag_GetFlagIntValue(Flags, flag_DOCPROOF)) { for (Scan2 = FormulaClausesTemp; !list_Empty(Scan2); Scan2 = list_Cdr(Scan2)) { hm_InsertListInsertUnique(InputClauseToTermLabellist, list_Car(Scan2), list_PairFirst(list_Car(Scan))); } } FormulaClauses = list_Nconc(FormulaClauses, FormulaClausesTemp); term_Delete(Formula); } /* red_SatUnit works only on conclauses */ for (Scan = FormulaClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) clause_SetFlag((CLAUSE) list_Car(Scan), CONCLAUSE); /* For FormulaClauses a full saturation */ /* List is deleted in red_SatUnit ! */ EmptyClauses = red_SatUnit(Search, FormulaClauses); if (!list_Empty(EmptyClauses)) { /* Set now to FALSE because formula clause relationship for subsequent */ /* optimized Skolemization steps is then not properly set. However, this */ /* may cause performance problems */ Result = FALSE; /*puts("\nPROOF in FormulaClauses");*/ clause_DeleteClauseList(EmptyClauses); } /* Move all usables to workedoff */ FormulaClauses = list_Copy(prfs_UsableClauses(Search)); for (Scan = FormulaClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) prfs_MoveUsableWorkedOff(Search, (CLAUSE) list_Car(Scan)); list_Delete(FormulaClauses); FormulaClauses = list_Nil(); } #ifdef CHECK /*cnf_CheckClauseListsConsistency(ShIndex); */ #endif *Symblist = list_Nil(); for (Scan = AllFormulae; !list_Empty(Scan); Scan = list_Cdr(Scan)) { LIST Ax, Pair; UsedTerms = list_Nil(); Pair = list_Car(Scan); #ifdef CHECK_CNF fputs("\nFormula : ", stdout); term_Print((TERM) list_PairSecond(Pair)); printf("\nLabel : %s", (char*) list_PairFirst(Pair)); #endif Ax = cnf_OptimizedSkolemization(Search, term_Copy((TERM)list_PairSecond(Pair)), (char*) list_PairFirst(Pair), &UsedTerms, Symblist,Result,FALSE,InputClauseToTermLabellist); clock_StopAddPassedTime(clock_CNFREDUCTION); /* Set CONCLAUSE flag for clauses derived from conjectures */ if (list_PointerMember(ConjectureList,list_PairSecond(Pair))) { LIST l; for (l = Ax; !list_Empty(l); l = list_Cdr(l)) clause_SetFlag((CLAUSE) list_Car(l), CONCLAUSE); } if (flag_GetFlagIntValue(Flags, flag_FPFCR) || flag_GetFlagIntValue(Flags, flag_DOCPROOF)) { hm_InsertListAppend(TermLabelToClauselist, list_PairFirst(Pair),list_Copy(Ax)); UsedTerms = list_Cons(list_PairFirst(Pair), UsedTerms); UsedTerms = cnf_DeleteDuplicateLabelsFromList(UsedTerms); for (Scan2 = Ax; !list_Empty(Scan2); Scan2 = list_Cdr(Scan2)) { hm_InsertListAppend(ClauseToTermLabellist, list_Car(Scan2), list_Copy(UsedTerms)); hm_InsertListAppend(InputClauseToTermLabellist, list_Car(Scan2), list_Copy(UsedTerms)); } } *AxClauses = list_Nconc(Ax, *AxClauses); list_Delete(UsedTerms); } /* Transfer precedence of new skolem symbols into */ symbol_TransferPrecedence(Precedence, InputPrecedence); list_Delete(ConjectureList); if (flag_GetFlagIntValue(Flags, flag_FPFCR) || flag_GetFlagIntValue(Flags, flag_DOCPROOF)) hm_DeleteList(InputClauseToTermLabellist); if (!flag_GetFlagIntValue(Flags, flag_INTERACTIVE)) { list_Delete(*Symblist); } *AllLabels = list_Nil(); for (Scan = AllFormulae; !list_Empty(Scan); Scan = list_Cdr(Scan)) { LIST Pair; Pair = list_Car(Scan); term_Delete((TERM) list_PairSecond(Pair)); *AllLabels = list_Cons(list_PairFirst(Pair), *AllLabels); list_PairFree(Pair); } list_Delete(AllFormulae); list_Delete(SkolemFunctions); list_Delete(SkolemPredicates); if (!flag_GetFlagIntValue(Flags, flag_INTERACTIVE)) { symbol_ResetSkolemIndex(); prfs_Delete(Search); return NULL; } else { /* Delete DocProof clauses */ prfs_DeleteDocProof(Search); return Search; } } LIST cnf_QueryFlotter(PROOFSEARCH Search, TERM Term, LIST* Symblist) /************************************************************** INPUT: A term to derive clauses from, using optimized skolemization, and a ProofSearch object. RETURNS: A list of derived clauses. EFFECT: ??? EK The precedence of new skolem symbols is set in . ***************************************************************/ { LIST SkolemPredicates, SkolemFunctions, IndexedClauses, Scan; LIST ResultClauses, Dummy, EmptyClauses; TERM TermCopy; int Formulae2Clause; BOOL Result; FLAGSTORE Flags, SubProofFlags; PRECEDENCE Precedence; Flags = prfs_Store(Search); Precedence = prfs_Precedence(Search); /* Initialize the flagstore of the cnf_SEARCHCOPY object with default values */ /* and copy the value of flag_DOCPROOF from the global Proofserach object. */ SubProofFlags = prfs_Store(cnf_SEARCHCOPY); flag_InitStoreByDefaults(SubProofFlags); flag_TransferFlag(Flags, SubProofFlags, flag_DOCPROOF); /* Transfer the precedence into the local search object */ symbol_TransferPrecedence(Precedence, prfs_Precedence(cnf_SEARCHCOPY)); SkolemPredicates = SkolemFunctions = list_Nil(); Result = FALSE; prfs_CopyIndices(Search, cnf_SEARCHCOPY); Term = term_Create(fol_Not(), list_List(Term)); fol_NormalizeVars(Term); Term = cnf_ObviousSimplifications(Term); if (flag_GetFlagIntValue(Flags, flag_CNFRENAMING)) { term_AddFatherLinks(Term); Term = ren_Rename(Term, Precedence, &SkolemPredicates, flag_GetFlagIntValue(Flags, flag_CNFPRENAMING), flag_GetFlagIntValue(Flags, flag_CNFRENMATCH), flag_GetFlagIntValue(Flags, flag_CNFRENAMING)); } Term = cnf_RemoveEquivImplFromFormula(Term); Term = cnf_NegationNormalFormula(Term); Term = cnf_AntiPrenex(Term); TermCopy = term_Copy(Term); TermCopy = cnf_SkolemFormula(TermCopy, Flags, Precedence, &SkolemFunctions); TermCopy = cnf_DistributiveFormula(TermCopy); IndexedClauses = cnf_MakeClauseList(TermCopy,FALSE,FALSE,Flags,Precedence); term_Delete(TermCopy); /* red_SatUnit works only on conclauses */ for (Scan = IndexedClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) clause_SetFlag((CLAUSE) list_Car(Scan), CONCLAUSE); EmptyClauses = red_SatUnit(cnf_SEARCHCOPY, IndexedClauses); if (!list_Empty(EmptyClauses)) { Result = TRUE; clause_DeleteClauseList(EmptyClauses); } while (!list_Empty(prfs_UsableClauses(cnf_SEARCHCOPY))) { prfs_MoveUsableWorkedOff(cnf_SEARCHCOPY, (CLAUSE) list_Car(prfs_UsableClauses(cnf_SEARCHCOPY))); } /* Works only if DOCPROOF is false. Otherwise we need labels */ Dummy = list_Nil(); if (flag_GetFlagIntValue(SubProofFlags, flag_DOCPROOF)) Formulae2Clause = TRUE; else Formulae2Clause = FALSE; flag_SetFlagIntValue(SubProofFlags, flag_DOCPROOF, flag_DOCPROOFOFF); ResultClauses = cnf_OptimizedSkolemization(cnf_SEARCHCOPY, term_Copy(Term), NULL, &Dummy, Symblist, Result, FALSE, NULL); if (Formulae2Clause) flag_SetFlagIntValue(SubProofFlags, flag_DOCPROOF, flag_DOCPROOFON); term_Delete(Term); list_Delete(SkolemPredicates); list_Delete(SkolemFunctions); prfs_Clean(cnf_SEARCHCOPY); /* All result clauses of queries are conjecture clauses */ for (Scan=ResultClauses; !list_Empty(Scan); Scan=list_Cdr(Scan)) clause_SetFlag((CLAUSE) list_Car(Scan), CONCLAUSE); return ResultClauses; } #ifdef CHECK /* Currently unused */ /*static*/ void cnf_CheckClauseListsConsistency(SHARED_INDEX ShIndex) /************************************************************** INPUT: A shared index and a list of non-ConClauses. EFFECT: When this function is called all clauses in the index must be non-ConClauses, which must also be members of the list. **************************************************************/ { LIST AllClauses, scan; AllClauses = clause_AllIndexedClauses(ShIndex); for (scan = AllClauses; scan != list_Nil(); scan = list_Cdr(scan)) { if (clause_GetFlag((CLAUSE) list_Car(scan), CONCLAUSE)) { misc_StartErrorReport(); misc_ErrorReport("\n In cnf_CheckClauseListsConsistency: Clause is a CONCLAUSE.\n"); misc_FinishErrorReport(); } if (clause_GetFlag((CLAUSE) list_Car(scan), BLOCKED)) { misc_StartErrorReport(); misc_ErrorReport("\n In cnf_CheckClauseListsConsistency: Clause is BLOCKED.\n"); misc_FinishErrorReport(); } } list_Delete(AllClauses); } #endif static LIST cnf_SatUnit(PROOFSEARCH Search, LIST ClauseList) /********************************************************* INPUT: A list of unshared clauses, proof search object RETURNS: A possibly empty list of empty clauses. **********************************************************/ { CLAUSE Given; LIST Scan, Derivables, EmptyClauses, BackReduced; NAT n, Derived; FLAGSTORE Flags; PRECEDENCE Precedence; Flags = prfs_Store(Search); Precedence = prfs_Precedence(Search); Derived = flag_GetFlagIntValue(Flags, flag_CNFPROOFSTEPS); EmptyClauses = list_Nil(); ClauseList = clause_ListSortWeighed(ClauseList); while (!list_Empty(ClauseList) && list_Empty(EmptyClauses)) { Given = (CLAUSE)list_NCar(&ClauseList); Given = red_CompleteReductionOnDerivedClause(Search, Given, red_ALL); if (Given) { if (clause_IsEmptyClause(Given)) EmptyClauses = list_List(Given); else { /*fputs("\n\nGiven: ",stdout);clause_Print(Given);*/ BackReduced = red_BackReduction(Search, Given, red_USABLE); if (Derived != 0) { Derivables = inf_BoundedDepthUnitResolution(Given, prfs_UsableSharingIndex(Search), FALSE, Flags, Precedence); Derivables = list_Nconc(Derivables, inf_BoundedDepthUnitResolution(Given,prfs_WorkedOffSharingIndex(Search), FALSE, Flags, Precedence)); n = list_Length(Derivables); if (n > Derived) Derived = 0; else Derived -= n; } else Derivables = list_Nil(); Derivables = list_Nconc(BackReduced,Derivables); Derivables = split_ExtractEmptyClauses(Derivables, &EmptyClauses); prfs_InsertUsableClause(Search, Given, TRUE); for (Scan = Derivables; !list_Empty(Scan); Scan = list_Cdr(Scan)) ClauseList = clause_InsertWeighed(list_Car(Scan), ClauseList, Flags, Precedence); list_Delete(Derivables); } } } clause_DeleteClauseList(ClauseList); return EmptyClauses; } TERM cnf_DefTargetConvert(TERM Target, TERM ToTopLevel, TERM ToProveDef, LIST DefPredArgs, LIST TargetPredArgs, LIST TargetPredVars, LIST VarsForTopLevel, FLAGSTORE Flags, PRECEDENCE Precedence, BOOL* LocallyTrue) /********************************************************** INPUT: A term Target which contains a predicate that might be replaced by its definition. A term ToTopLevel which is the highest level subterm in Target that contains the predicate and can be moved to top level or(). A term ToProveDef which must hold if the definition is to be applied. (IS DESTROYED AND FREED) A list DefPredArgs of the arguments of the predicate in the Definition. A list TargetPredArgs of the arguments of the predicate in Target. A list TargetPredVars of the variables occurring in the arguments of the predicate in Target. A list VarsForTopLevel containing the variables that should be all-quantified at top level to make the proof easier. A flag store. A pointer to a boolean LocallyTrue which is set to TRUE iff the definition can be applied. RETURNS: The Target term which is brought into standard form. **********************************************************/ { TERM orterm, targettoprove; SYMBOL maxvar; /* For normalizing terms */ LIST l1, l2; LIST freevars, vars; /* Free variables in targettoprove */ if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { puts("\nTarget :"); fol_PrettyPrint(Target); } #ifdef CHECK fol_CheckFatherLinks(Target); #endif /* No proof found yet */ *LocallyTrue = FALSE; /* Remove implications from path */ Target = cnf_RemoveImplFromFormulaPath(Target, ToTopLevel); /* Move negations as far down as possible */ Target = cnf_NegationNormalFormulaPath(Target, ToTopLevel); /* Move quantifiers as far down as possible */ Target = cnf_AntiPrenexPath(Target, ToTopLevel); /* Move all-quantified variables from the predicates' arguments to top level */ Target = cnf_MovePredicateVariablesUp(Target, ToTopLevel, VarsForTopLevel); /* Flatten top or() */ Target = cnf_FlattenPath(Target, ToTopLevel); /* Now make sure that all variables in the top forall quantifier are in TargetPredVars */ /* Not necessary, according to CW */ if (symbol_Equal(term_TopSymbol(Target), fol_All())) { targettoprove = term_Copy(term_SecondArgument(Target)); orterm = term_SecondArgument(Target); } else { targettoprove = term_Copy(Target); orterm = Target; } /* Find argument of targettoprove that contains the predicate and remove it */ if (symbol_Equal(term_TopSymbol(targettoprove), fol_Or())) { /* Find subterm that contains the predicate */ LIST arglist; arglist = term_ArgumentList(targettoprove); for (l1=arglist, l2=term_ArgumentList(orterm); !list_Empty(l1); l1 = list_Cdr(l1), l2 = list_Cdr(l2)) { if (term_HasProperSuperterm(ToTopLevel, (TERM) list_Car(l2)) || (ToTopLevel == (TERM) list_Car(l2))) { arglist = list_PointerDeleteElementFree(arglist, list_Car(l1), (void (*)(POINTER))term_Delete); break; } } term_RplacArgumentList(targettoprove, arglist); /* Nothing left for the proof ? */ if (list_Empty(term_ArgumentList(targettoprove))) { term_Delete(targettoprove); term_Delete(ToProveDef); #ifdef CHECK fol_CheckFatherLinks(Target); #endif return Target; } } else { /* Nothing left for the proof */ term_Delete(targettoprove); term_Delete(ToProveDef); #ifdef CHECK fol_CheckFatherLinks(Target); #endif return Target; } /* Normalize variables in ToProveDef with respect to targettoprove */ maxvar = term_MaxVar(targettoprove); symbol_SetStandardVarCounter(maxvar); vars = fol_BoundVariables(ToProveDef); vars = term_DeleteDuplicatesFromList(vars); for (l1=vars; !list_Empty(l1); l1=list_Cdr(l1)) term_ExchangeVariable(ToProveDef, term_TopSymbol(list_Car(l1)), symbol_CreateStandardVariable()); list_Delete(vars); /* Replace arguments of predicate in condition of definition by matching arguments of predicate in target term */ for (l1=DefPredArgs, l2=TargetPredArgs; !list_Empty(l1); l1=list_Cdr(l1), l2=list_Cdr(l2)) term_ReplaceVariable(ToProveDef, term_TopSymbol((TERM) list_Car(l1)), (TERM) list_Car(l2)); targettoprove = term_Create(fol_Not(), list_List(targettoprove)); targettoprove = cnf_NegationNormalFormula(targettoprove); targettoprove = term_Create(fol_Implies(), list_Cons(targettoprove, list_List(ToProveDef))); /* At this point ToProveDef must not be accessed again ! */ /* Add all--quantifier to targettoprove */ freevars = fol_FreeVariables(targettoprove); term_CopyTermsInList(freevars); targettoprove = fol_CreateQuantifier(fol_All(), freevars, list_List(targettoprove)); if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { puts("\nConverted to :"); fol_PrettyPrint(Target); } targettoprove = cnf_NegationNormalFormula(targettoprove); if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { puts("\nToProve for this target :"); fol_PrettyPrint(targettoprove); } *LocallyTrue = cnf_HaveProof(list_Nil(), targettoprove, Flags, Precedence); term_Delete(targettoprove); #ifdef CHECK fol_CheckFatherLinks(Target); #endif return Target; } static TERM cnf_RemoveQuantFromPathAndFlatten(TERM TopTerm, TERM SubTerm) /********************************************************** INPUT: Two terms, must be a subterm of . Superterm of must be an equivalence. Along the path to SubTerm there are only quantifiers or disjunctions. All free variables in the equivalence are free variables in . All free variables in are bound by a universal quantifier (with polarity 1). RETURN: The destructively changed . EFFECT: Removes all quantifiers not binding a variable in from 's path. Moves all universal quantifiers binding free variable in up. is transformed into the form forall([X1,...,Xn],or (equiv(,psi),phi)). **********************************************************/ { TERM Term1, Term2, Flat, Variable; LIST Scan1, Scan2, FreeVars; #ifdef CHECK if (!fol_CheckFormula(TopTerm) || !term_HasPointerSubterm(TopTerm, SubTerm)) { misc_StartErrorReport(); misc_ErrorReport("\nIn cnf_RemoveQuantFromPathAndFlatten: Illegal input."); misc_FinishErrorReport(); } #endif TopTerm = cnf_SimplifyQuantors(TopTerm); term_AddFatherLinks(TopTerm); Term1 = term_Superterm(SubTerm); while (Term1 != TopTerm) { while (symbol_Equal(fol_Or(), term_TopSymbol(Term1)) && (TopTerm != Term1)) { Term1 = term_Superterm(Term1); } if (fol_IsQuantifier(term_TopSymbol(Term1))) { Flat = term_SecondArgument(Term1); Flat = cnf_Flatten(Flat, fol_Or()); Scan1 = fol_QuantifierVariables(Term1); while (!list_Empty(Scan1)) { Variable = (TERM)list_Car(Scan1); if (fol_VarOccursFreely(Variable, SubTerm)) { Scan2 = list_Cdr(Scan1); fol_DeleteQuantifierVariable(Term1, term_TopSymbol(list_Car(Scan1))); Scan1 = Scan2; } else { Scan1 = list_Cdr(Scan1); } } if (fol_IsQuantifier(term_TopSymbol(Term1))) { /* still variables, but not binding a variable in the equivalence term */ LIST ArgList; term_RplacArgumentList(Flat, list_PointerDeleteOneElement(term_ArgumentList(Flat), SubTerm)); ArgList = term_ArgumentList(Term1); term_RplacArgumentList(Term1, list_Nil()); Term2 = term_Create(term_TopSymbol(Term1), ArgList); term_RplacArgumentList(Term1, list_Cons(SubTerm, list_List(Term2))); term_RplacTop(Term1, fol_Or()); Scan1 = term_ArgumentList(Term1); while (!list_Empty(Scan1)) { term_RplacSuperterm((TERM)list_Car(Scan1), Term1); Scan1 = list_Cdr(Scan1); } } } else { #ifdef CHECK if (!symbol_Equal(term_TopSymbol(Term1), fol_Or())) { misc_StartErrorReport(); misc_ErrorReport("\nIn cnf_RemoveQuantFromPathAndFlatten: Illegal term Term1"); misc_FinishErrorReport(); } #endif Term1 = cnf_Flatten(Term1, fol_Or()); } } FreeVars = fol_FreeVariables(Term1); if (!list_Empty(FreeVars)) { term_CopyTermsInList(FreeVars); TopTerm = fol_CreateQuantifier(fol_All(), FreeVars, list_List(Term1)); } return TopTerm; } TERM cnf_DefConvert(TERM Def, TERM FoundPredicate, TERM* ToProve) /********************************************************* INPUT: A term Def which is an equivalence (P(x1,..,xn) <=> Formula) that can be converted to standard form. The subterm that holds the defined predicate. A pointer to a term ToProve into which a term is stored that has to be proved before applying the definition. RETURNS: The converted definition : forall([..], or(equiv(..,..), ..)) ************************************************************/ { TERM orterm; #ifdef CHECK fol_CheckFatherLinks(Def); #endif Def = cnf_RemoveImplFromFormulaPath(Def, FoundPredicate); /* Remove implications along the path */ Def = cnf_NegationNormalFormulaPath(Def, FoundPredicate); /* Move not's as far down as possible */ #ifdef CHECK if (!fol_CheckFormula(Def)) { misc_StartErrorReport(); misc_ErrorReport("\nIn cnf_DefConvert: Illegal input Formula.\n"); misc_FinishErrorReport(); } if (!term_HasPointerSubterm(Def, FoundPredicate)) { misc_StartErrorReport(); misc_ErrorReport("\nIn cnf_DefConvert: Illegal input SubTerm.\n"); misc_FinishErrorReport(); } #endif Def = cnf_RemoveQuantFromPathAndFlatten(Def, term_Superterm(FoundPredicate)); term_AddFatherLinks(Def); #ifdef CHECK if (!fol_CheckFormula(Def)) { misc_StartErrorReport(); misc_ErrorReport("\nIn cnf_DefConvert: Illegal term Def."); misc_FinishErrorReport(); } if (!term_HasPointerSubterm(Def, FoundPredicate)) { misc_StartErrorReport(); misc_ErrorReport("\nIn cnf_DefConvert: Illegal term FoundPredicate."); misc_FinishErrorReport(); } #endif /* Find top level or() */ if (symbol_Equal(term_TopSymbol(Def), fol_All())) { /* Make sure there are several arguments */ if (symbol_Equal(term_TopSymbol(term_SecondArgument(Def)), fol_Or()) && (list_Length(term_ArgumentList(term_SecondArgument(Def))) == 1)) { TERM t; t = term_SecondArgument(Def); term_RplacSecondArgument(Def, term_FirstArgument(term_SecondArgument(Def))); term_Free(t); orterm = NULL; term_RplacSuperterm(term_SecondArgument(Def), Def); } else orterm = term_SecondArgument(Def); } else { /* Make sure there are several arguments */ if (symbol_Equal(term_TopSymbol(Def), fol_Or()) && (list_Length(term_ArgumentList(Def)) == 1)) { TERM t; t = Def; Def = term_FirstArgument(Def); term_Free(t); orterm = NULL; term_RplacSuperterm(term_SecondArgument(Def), Def); } else orterm = Def; } /* If there is something to prove */ if (orterm != (TERM) NULL) { TERM equiv; LIST args; equiv = (TERM) NULL; /* In pell 10 there are no conditions for the equivalence */ if (symbol_Equal(term_TopSymbol(orterm), fol_Equiv())) { equiv = orterm; *ToProve = NULL; } else { TERM t; /* First find equivalence term among arguments */ args = term_ArgumentList(orterm); equiv = term_Superterm(FoundPredicate); /* Delete equivalence from list */ args = list_PointerDeleteElement(args, equiv); term_RplacArgumentList(orterm, args); /* ToProve consists of all the definitions arguments except the equivalence */ *ToProve = term_Copy(orterm); /* Now not(*ToProve) implies the equivalence */ /* Negate *ToProve */ *ToProve = term_Create(fol_Not(), list_List(*ToProve)); *ToProve = cnf_NegationNormalFormula(*ToProve); term_AddFatherLinks(*ToProve); /* Now convert definition to implication form */ term_RplacTop(orterm, fol_Implies()); t = term_Create(fol_Not(), list_List(term_Create(fol_Or(), term_ArgumentList(orterm)))); term_RplacArgumentList(orterm, list_Cons(t, list_List(equiv))); Def = cnf_NegationNormalFormula(Def); term_AddFatherLinks(Def); } } #ifdef CHECK fol_CheckFatherLinks(Def); #endif return Def; } LIST cnf_HandleDefinition(PROOFSEARCH Search, LIST Pair, LIST Axioms, LIST Sorts, LIST Conjectures) /******************************************************************* INPUT: A PROOFSEARCH object, a pair (label, term) and 3 lists of pairs. If the term in pair is a definition, the defined predicate is expanded in all the lists and added to the proofsearch object. RETURNS: The pair with the converted definition: forall([..], or(equiv(..,..), .......)) ********************************************************************/ { TERM definition, defpredicate, equivterm; BOOL alwaysapplicable; /* Is set to TRUE iff the definition can always be applied */ FLAGSTORE Flags; PRECEDENCE Precedence; Flags = prfs_Store(Search); Precedence = prfs_Precedence(Search); /* The axiomlist consists of (label, formula) pairs */ definition = list_PairSecond(Pair); /* Test if Definition contains a definition */ defpredicate = (TERM) NULL; if (cnf_ContainsDefinition(definition, &defpredicate)) { TERM toprove; LIST allformulae, scan; /* Create list of all formula pairs */ /* Check if definition may be applied to each formula */ allformulae = list_Copy(Axioms); allformulae = list_Nconc(allformulae, list_Copy(Sorts)); allformulae = list_Nconc(allformulae, list_Copy(Conjectures)); #ifdef CHECK for (scan=allformulae; !list_Empty(scan); scan=list_Cdr(scan)) { if (!list_Empty((LIST) list_Car(scan))) { if (!term_IsTerm((TERM) list_PairSecond((LIST) list_Car(scan)))) fol_CheckFatherLinks((TERM) list_PairSecond((LIST) list_Car(scan))); } } #endif /* Convert definition to standard form */ if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { fputs("\nPredicate : ", stdout); symbol_Print(term_TopSymbol(defpredicate)); } definition = cnf_DefConvert(definition, defpredicate, &toprove); if (toprove == NULL) alwaysapplicable = TRUE; else alwaysapplicable = FALSE; prfs_SetDefinitions(Search, list_Cons(term_Copy(definition), prfs_Definitions(Search))); if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { if (alwaysapplicable) { fputs("\nAlways Applicable : ", stdout); fol_PrettyPrint(definition); } } /* Definition is converted to a form where the equivalence is the first argument of the disjunction */ equivterm = term_SecondArgument(term_Superterm(defpredicate)); scan = allformulae; while (!list_Empty(scan)) { BOOL localfound; LIST pair, targettermvars; /* Pair label / term */ pair = list_Car(scan); /* Pair may be NULL if it is a definition that could be deleted */ if ((pair != NULL) && (definition != (TERM) list_PairSecond(pair))) { TERM target, targetpredicate, totoplevel; LIST varsfortoplevel; target = (TERM) list_PairSecond(pair); targettermvars = varsfortoplevel = list_Nil(); /* If definition is not always applicable, check if it is applicable for this formula */ localfound = FALSE; if (!alwaysapplicable) { if (cnf_ContainsPredicate(target, term_TopSymbol(defpredicate), &targetpredicate, &totoplevel, &targettermvars, &varsfortoplevel)) { TERM toprovecopy; toprovecopy = term_Copy(toprove); target = cnf_DefTargetConvert(target, totoplevel, toprovecopy, term_ArgumentList(defpredicate), term_ArgumentList(targetpredicate), targettermvars, varsfortoplevel, Flags, Precedence, &localfound); list_Delete(targettermvars); list_Delete(varsfortoplevel); targettermvars = varsfortoplevel = list_Nil(); list_Rplacd(pair, (LIST) target); if (localfound) list_Rplacd(pair, (LIST) cnf_ApplyDefinitionOnce(defpredicate, equivterm, list_PairSecond(pair), targetpredicate, Flags)); } } else { if (cnf_ContainsPredicate(target, term_TopSymbol(defpredicate), &targetpredicate, &totoplevel, &targettermvars, &varsfortoplevel)) list_Rplacd(pair, (LIST) cnf_ApplyDefinitionOnce(defpredicate, equivterm, list_PairSecond(pair), targetpredicate, Flags)); else scan = list_Cdr(scan); list_Delete(targettermvars); list_Delete(varsfortoplevel); targettermvars = varsfortoplevel = list_Nil(); } } else scan = list_Cdr(scan); } list_Delete(allformulae); /* toprove can be NULL if the definition can always be applied */ if (toprove != (TERM) NULL) term_Delete(toprove); list_Rplacd(Pair, (LIST) definition); } return Pair; } LIST cnf_ApplyDefinitionToClause(CLAUSE Clause, TERM Predicate, TERM Expansion, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A clause, two terms and a flag store and a precedence. RETURNS: The list of clauses where each occurrence of Predicate is replaced by Expansion. ***************************************************************/ { NAT i; BOOL changed; LIST args, scan, symblist; TERM clauseterm, argument; changed = FALSE; /* Build term from clause */ args = list_Nil(); for (i = 0; i < clause_Length(Clause); i++) { argument = clause_GetLiteralTerm(Clause, i); /* with sign */ args = list_Cons(term_Copy(argument), args); } clauseterm = term_Create(fol_Or(), args); for (scan=term_ArgumentList(clauseterm); !list_Empty(scan); scan=list_Cdr(scan)) { BOOL isneg; argument = (TERM) list_Car(scan); if (symbol_Equal(term_TopSymbol(argument), fol_Not())) { argument = term_FirstArgument(argument); isneg = TRUE; } else isneg = FALSE; /* Try to match with predicate */ cont_StartBinding(); if (unify_Match(cont_LeftContext(), Predicate, argument)) { SUBST subst; TERM newargument; subst = subst_ExtractMatcher(); newargument = subst_Apply(subst, term_Copy(Expansion)); subst_Free(subst); if (isneg) newargument = term_Create(fol_Not(), list_List(newargument)); term_Delete((TERM) list_Car(scan)); list_Rplaca(scan, newargument); changed = TRUE; } cont_BackTrack(); } if (changed) { /* Build term and derive list of clauses */ LIST result; if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { puts("\nClause before applying def :"); clause_Print(Clause); puts("\nPredicate :"); fol_PrettyPrint(Predicate); puts("\nExpansion :"); fol_PrettyPrint(Expansion); } symblist = list_Nil(); clauseterm = cnf_Cnf(clauseterm, Flags, Precedence, &symblist); result = cnf_MakeClauseList(clauseterm,FALSE,FALSE,Flags,Precedence); list_Delete(symblist); term_Delete(clauseterm); if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { LIST l; puts("\nClauses derived by expanding definition :"); for (l = result; !list_Empty(l); l=list_Cdr(l)) { clause_Print((CLAUSE) list_Car(l)); fputs("\n", stdout); } } return result; } else { term_Delete(clauseterm); return list_Nil(); } } BOOL cnf_PropagateSubstEquations(TERM StartTerm) /************************************************************* INPUT: A term where we assume that father links are established and that no variable is bound by more than one quantifier. RETURNS: TRUE, if any substitutions were made, FALSE otherwise. EFFECT: Function looks for equations of the form x=t where x does not occur in t. If x=t occurs negatively and disjunctively below a universal quantifier binding x or if x=t occurs positively and conjunctively below an existential quantifier binding x, all occurrences of x are replaced by t in . **************************************************************/ { LIST Subequ; TERM QuantorTerm, Equation, EquationTerm; SYMBOL Variable; BOOL Hit, Substituted; #ifdef CHECK if (fol_VarBoundTwice(StartTerm)) { misc_StartErrorReport(); misc_ErrorReport("\n In cnf_PropagateSubstEquations: Variables of"); misc_ErrorReport("\n input term are not normalized."); misc_FinishErrorReport(); } #endif Substituted = FALSE; Subequ = fol_GetSubstEquations(StartTerm); for ( ; !list_Empty(Subequ); Subequ = list_Pop(Subequ)) { Hit = FALSE; Equation = list_Car(Subequ); Variable = symbol_Null(); QuantorTerm = term_Null(); EquationTerm = term_Null(); if (term_IsVariable(term_FirstArgument(Equation)) && !term_ContainsVariable(term_SecondArgument(Equation), term_TopSymbol(term_FirstArgument(Equation)))) { Variable = term_TopSymbol(term_FirstArgument(Equation)); QuantorTerm = fol_GetBindingQuantifier(Equation, Variable); EquationTerm = term_SecondArgument(Equation); Hit = fol_PolarCheck(Equation, QuantorTerm); } if (!Hit && term_IsVariable(term_SecondArgument(Equation)) && !term_ContainsVariable(term_FirstArgument(Equation), term_TopSymbol(term_SecondArgument(Equation)))) { Variable = term_TopSymbol(term_SecondArgument(Equation)); QuantorTerm = fol_GetBindingQuantifier(Equation, Variable); EquationTerm = term_FirstArgument(Equation); Hit = fol_PolarCheck(Equation, QuantorTerm); } if (Hit) { fol_DeleteQuantifierVariable(QuantorTerm,Variable); term_ReplaceVariable(StartTerm, Variable, EquationTerm); /* We replace everythere ! */ term_AddFatherLinks(StartTerm); if (symbol_Equal(term_TopSymbol(QuantorTerm),fol_Equality())) /* Trivial Formula */ fol_SetTrue(QuantorTerm); else fol_SetTrue(Equation); Substituted = TRUE; } } /* was freed in the loop. */ return Substituted; } spass-3.9/cnf.h000066400000000000000000000101641325017163600134430ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * NAIVE CNF TRANSLATOR * */ /* * * */ /* * $Module: CNF * */ /* * * */ /* * Copyright (C) 1996, 1997, 1998, 1999, 2000 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.4 $ * */ /* $State: Exp $ * */ /* $Date: 2011-11-27 11:05:41 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: cnf.h,v $ */ /**************************************************************/ /* Includes */ /**************************************************************/ #ifndef _CNF_ #define _CNF_ #include "hashmap.h" #include "renaming.h" #include "resolution.h" #include "search.h" #include "flags.h" #include /**************************************************************/ /* Functions */ /**************************************************************/ BOOL cnf_LabelEqual(const char* l1, const char* l2); LIST cnf_DeleteDuplicateLabelsFromList(LIST Labels); TERM cnf_ApplyDefinitionOnce(TERM, TERM, TERM, TERM, FLAGSTORE); LIST cnf_ApplyDefinitionToClause(CLAUSE, TERM, TERM,FLAGSTORE,PRECEDENCE); BOOL cnf_ContainsDefinition(TERM, TERM*); BOOL cnf_ContainsPredicate(TERM, SYMBOL, TERM*, TERM*, LIST*, LIST*); TERM cnf_DeSkolemFormula(LIST); TERM cnf_DefConvert(TERM, TERM, TERM*); void cnf_FilePrint(TERM, FILE*); TERM cnf_DefTargetConvert(TERM, TERM, TERM, LIST, LIST, LIST, LIST, FLAGSTORE, PRECEDENCE, BOOL*); void cnf_FilePrintPrefix(TERM, FILE*); void cnf_FPrint(TERM, FILE*); TERM cnf_Flatten(TERM, SYMBOL); PROOFSEARCH cnf_Flotter(LIST, LIST, LIST*, LIST*, HASHMAP, HASHMAP, FLAGSTORE, PRECEDENCE, LIST*); void cnf_Free(FLAGSTORE); LIST cnf_HandleDefinition(PROOFSEARCH, LIST, LIST, LIST, LIST); void cnf_Init(FLAGSTORE); TERM cnf_NegationNormalFormula(TERM); TERM cnf_ObviousSimplifications(TERM); LIST cnf_QueryFlotter(PROOFSEARCH, TERM, LIST*); void cnf_StdoutPrint(TERM); BOOL cnf_PropagateSubstEquations(TERM); BOOL cnf_HaveProof(LIST, TERM, FLAGSTORE, PRECEDENCE); #endif spass-3.9/component.c000066400000000000000000000232351325017163600146750ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * COMPONENTS OF CLAUSES * */ /* * * */ /* * $Module: COMPONENT * */ /* * * */ /* * Copyright (C) 1996, 1998, 2000, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.3 $ * */ /* $State: Exp $ * */ /* $Date: 2011-05-22 12:06:19 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: component.c,v $ */ #include "term.h" #include "component.h" /************************************************************** *Previously Inlined Function * * ***********************************************************/ BOOL literal_GetUsed(CLITERAL C) { return C->used; } int literal_GetLitIndex(CLITERAL C) { return C->litindex; } LIST literal_GetLitVarList(CLITERAL C) { return C->litvarlist; } void literal_PutUsed(CLITERAL C,BOOL Bool) { C->used = Bool; } void literal_PutLitIndex(CLITERAL C, int I) { C->litindex = I; } void literal_PutLitVarList(CLITERAL C, LIST L) { C->litvarlist = L; } CLITERAL litptr_Literal(LITPTR C, intptr_t I) { return C->litptr[I]; } void litptr_SetLiteral(LITPTR LP, int I, CLITERAL CL) { LP->litptr[I] = CL; } int litptr_Length(LITPTR C) { return C->length; } void litptr_SetLength(LITPTR C, int n) { C->length = n; } void litptr_IncLength(LITPTR C) { (C->length)++; } void literal_Free(CLITERAL Lit) { memory_Free(Lit, sizeof(CLITERAL_NODE)); } /************************************************************** *Previously Inlined Functions Ends here * * ***********************************************************/ CLITERAL literal_Create(BOOL used, int literal_index, LIST varlist) /********************************************************** INPUT: A boolean used, an integer index and a list varlist. RETURNS: A LITERAL is created. MEMORY: The boolean, integer and varlist are no copies. ************************************************************/ { CLITERAL literal; literal = (CLITERAL)memory_Malloc(sizeof(CLITERAL_NODE)); literal_PutUsed(literal,used); literal_PutLitIndex(literal,literal_index); literal_PutLitVarList(literal,varlist); return literal; } void literal_Delete(CLITERAL literal) /********************************************************** INPUT: A literal. RETURNS: None. MEMORY: Deletes the LITERAL and frees the storage. ***********************************************************/ { list_Delete(literal_GetLitVarList(literal)); literal_Free(literal); } LITPTR litptr_Create(LIST Indexlist, LIST Termsymblist) /********************************************************** INPUT: A list of indexes and a list of terms, i.e. a list of integers. RETURNS: A LITPTR structure is created. MEMORY: The integers in the created structure are the integers in indexList, no copies. ***********************************************************/ { LITPTR lit_ptr; LIST Scan,varlist; CLITERAL literal; intptr_t literal_index; int n,k; n = list_Length(Indexlist); lit_ptr = (LITPTR)memory_Malloc(sizeof(LITPTR_NODE)); litptr_SetLength(lit_ptr, n); if (n > 0) { lit_ptr->litptr = (CLITERAL *)memory_Malloc(n * sizeof(CLITERAL)); k = 0; for (Scan = Indexlist; !list_Empty(Scan); Scan = list_Cdr(Scan)) { literal_index = (intptr_t)list_Car(Scan); varlist = (LIST)list_Car(Termsymblist); Termsymblist = list_Cdr(Termsymblist); literal = literal_Create(FALSE,literal_index,varlist); litptr_SetLiteral(lit_ptr, k, literal); k++; } } else lit_ptr->litptr = NULL; return lit_ptr; } void litptr_Delete(LITPTR lit_ptr) /********************************************************** INPUT: A pointer to LITPTR. MEMORY: Deletes the LITPTR and frees the storage. ***********************************************************/ { int n,i; n = litptr_Length(lit_ptr); if (n > 0) { for (i = 0; i < n; i++) literal_Delete(litptr_Literal(lit_ptr,i)); memory_Free(lit_ptr->litptr, sizeof(CLITERAL) * n); memory_Free(lit_ptr, sizeof(LITPTR_NODE)); } else memory_Free(lit_ptr, sizeof(LITPTR_NODE)); } void litptr_Print(LITPTR lit_ptr) /************************************************************** INPUT: A term. RETURNS: void. SUMMARY: Prints any term to stdout. CAUTION: Uses the other term_Output functions. ***************************************************************/ { int i,n; n = litptr_Length(lit_ptr); /*n = lit_ptr->length;*/ if (n > 0) { printf("\nlength of LITPTR: %d\n",n); for (i = 0; i < n; i++) { printf("Entries of literal %d : \n",i); puts("----------------------"); fputs("used:\t\t", stdout); if (literal_GetUsed(litptr_Literal(lit_ptr,i))) /*if (lit_ptr->litptr[i]->used)*/ puts("TRUE"); else puts("FALSE"); printf("litindex:\t%d\n", literal_GetLitIndex(litptr_Literal(lit_ptr,i))); fputs("litvarlist:\t", stdout); list_Apply((void (*)(POINTER)) symbol_Print, literal_GetLitVarList(litptr_Literal(lit_ptr,i))); puts("\n"); } }else puts("No entries in litptr structure"); } BOOL litptr_AllUsed(LITPTR lit_ptr) /************************************************************** INPUT: A LITPTR. RETURNS: TRUE if every literal in the LITPTR is used and FALSE otherwise. ***************************************************************/ { int n,i; n = litptr_Length(lit_ptr); for (i = 0; i < n; i++) if (!(literal_GetUsed(litptr_Literal(lit_ptr,i)))) return FALSE; return TRUE; } LIST subs_CompList(LITPTR litptr) /********************************************************** INPUT: A pointer litptr. RETURNS: A list with indexes which represents the first component of with respect to the actual bindings and to litptr. CAUTION: The structure to which litptr points to is changed destructively in the used slot. ***********************************************************/ { BOOL found,hasinter; LIST scan,complist,compindexlist; int n,lit; intptr_t i,j; compindexlist = list_Nil(); /* the result will be placed into this list */ complist = list_Nil(); /* added afterwards */ n = litptr_Length(litptr); if (n > 0) { for (j = 0; j < n; j++) { printf("\nj = %zd\n",j); if (!literal_GetUsed(litptr_Literal(litptr,j))){ complist = list_Nil(); complist = list_Cons((POINTER)j,complist); compindexlist = list_Cons((POINTER)(litptr->litptr[j]->litindex), compindexlist); literal_PutUsed(litptr_Literal(litptr,j), TRUE); j = n+1; printf("\nj == %zd\n",j); } } if (j == n){ list_Delete(complist); /* There is no more component */ return compindexlist; /* should be empty here */ } found = TRUE; while (found) { found = FALSE; for (scan = complist; !list_Empty(scan); scan = list_Cdr(scan)) { lit = (intptr_t)list_Car(scan); for (i = 0; i < n; i++) { if (!literal_GetUsed(litptr_Literal(litptr,i))) { printf("lit = %d\n",lit); printf("i = %zd\n",i); hasinter = list_HasIntersection(litptr->litptr[lit]->litvarlist, litptr->litptr[i]->litvarlist); if (hasinter) { puts("hasinter = TRUE"); complist = list_Cons((POINTER)i,complist); compindexlist = list_Cons((POINTER)(litptr->litptr[i]->litindex),compindexlist); literal_PutUsed(litptr_Literal(litptr,i), TRUE); found = TRUE; } } } } if (!found) { /* one component is finished */ list_Delete(complist); found = FALSE; } } } return compindexlist; } spass-3.9/component.h000066400000000000000000000104221325017163600146740ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * COMPONENTS OF CLAUSES * */ /* * * */ /* * $Module: COMPONENT * */ /* * * */ /* * Copyright (C) 1996, 2000, 2001 MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.3 $ * */ /* $State: Exp $ * */ /* $Date: 2011-05-22 12:06:19 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: component.h,v $ */ #ifndef _COMPONENT_ #define _COMPONENT_ /**************************************************************/ /* Includes */ /**************************************************************/ #include "list.h" /**************************************************************/ /* Structures */ /**************************************************************/ typedef struct cliteral { BOOL used; /* Flag if the index is already used */ intptr_t litindex; /* Index of the literal in the original clause */ LIST litvarlist; /* List of variables of the literal */ } *CLITERAL, CLITERAL_NODE; typedef struct litptr { CLITERAL *litptr; /* Array of Pointer to literals */ int length; /* Number of literal in the array *litptr */ } *LITPTR, LITPTR_NODE; /**************************************************************/ /* Macros */ /**************************************************************/ BOOL literal_GetUsed(CLITERAL C); int literal_GetLitIndex(CLITERAL C); LIST literal_GetLitVarList(CLITERAL C); void literal_PutUsed(CLITERAL C,BOOL Bool); void literal_PutLitIndex(CLITERAL C, int I); void literal_PutLitVarList(CLITERAL C, LIST L); CLITERAL litptr_Literal(LITPTR C, intptr_t I); void litptr_SetLiteral(LITPTR LP, int I, CLITERAL CL); int litptr_Length(LITPTR C); void litptr_SetLength(LITPTR C, int n); void litptr_IncLength(LITPTR C); void literal_Free(CLITERAL Lit); /**************************************************************/ /* Functions on a Component and on a Literal */ /**************************************************************/ CLITERAL literal_Create(BOOL, int, LIST); void literal_Delete(CLITERAL); LITPTR litptr_Create(LIST, LIST); void litptr_Delete(LITPTR); void litptr_Print(LITPTR); BOOL litptr_AllUsed(LITPTR); #endif spass-3.9/condensing.c000066400000000000000000000067461325017163600150320ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * CONDENSATION OF CLAUSES * */ /* * * */ /* * $Module: CONDENSING * */ /* * * */ /* * Copyright (C) 1996, 1997, 2001 MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.3 $ * */ /* $State: Exp $ * */ /* $Date: 2011-05-22 12:08:25 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: condensing.c,v $ */ #include "subsumption.h" #include "misc.h" #include "condensing.h" LIST cond_CondFast(CLAUSE c) /********************************************************** INPUT: A clause c. RETURNS: A list with indexes with respect to c that can be deleted due to condensing. CAUTION: None. ***********************************************************/ { int vec, j; intptr_t i,k; LIST indexlist; indexlist = list_Nil(); vec = vec_ActMax(); for (i = 0; i < clause_Length(c); i++) { vec_Push((POINTER) i); } for (k = clause_Length(c) - 1; k >= 0; k--) { for (i = vec; i < vec_ActMax(); i++) { if ((intptr_t)vec_GetNth(i) != k) { cont_StartBinding(); if (unify_Match(cont_LeftContext(), clause_GetLiteralTerm(c,k), clause_GetLiteralTerm(c,(intptr_t)vec_GetNth(i)))) { cont_BackTrack(); for (j = vec; j < vec_ActMax(); j++) { if (k == (intptr_t)vec_GetNth(j)) { vec_Swap((vec_ActMax() -1) ,j); j = vec_ActMax(); } } if (subs_IdcRes(c,vec,(vec_ActMax() -1))) { indexlist = list_Cons((POINTER)k,indexlist); vec_Pop(); } i = vec_ActMax()+1; } else cont_BackTrack(); } } } vec_SetMax(vec); return indexlist; } spass-3.9/condensing.h000066400000000000000000000053641325017163600150320ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * CONDENSATION OF CLAUSES * */ /* * * */ /* * $Module: CONDENSING * */ /* * * */ /* * Copyright (C) 1996, 2001 MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.2 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:57 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: condensing.h,v $ */ #ifndef _CONDENSING_ #define _CONDENSING_ /**************************************************************/ /* Includes */ /**************************************************************/ #include "unify.h" /**************************************************************/ /* Function Prototypes */ /**************************************************************/ LIST cond_CondFast(CLAUSE); #endif spass-3.9/context.c000066400000000000000000001301171325017163600143550ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * VARCONTS FOR VARIABLES * */ /* * * */ /* * $Module: VARCONT * */ /* * * */ /* * Copyright (C) 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.6 $ * */ /* $State: Exp $ * */ /* $Date: 2011-11-27 11:18:18 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: context.c,v $ */ #include "context.h" /******************************************************* *Previously inlined functions * ********************************************************/ VARCONT cont_LeftContext(void) { return cont_LEFTVARCONT; } VARCONT cont_RightContext(void) { return cont_RIGHTVARCONT; } VARCONT cont_InstanceContext(void) { return cont_INSTANCEVARCONT; } void cont_StackInit(void) { cont_STACKPOINTER = 1; } void cont_StackPush(int Entry) { #ifdef CHECK if (cont_STACKPOINTER >= cont__STACKSIZE) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_StackPush: Context stack overflow!\n"); misc_FinishErrorReport(); } #endif cont_STACK[cont_STACKPOINTER++] = Entry; } void cont_StackPop(void) { --cont_STACKPOINTER; } int cont_StackPopResult(void) { return cont_STACK[--cont_STACKPOINTER]; } void cont_StackNPop(int N) { cont_STACKPOINTER -= N; } intptr_t cont_StackTop(void) { return cont_STACK[cont_STACKPOINTER - 1]; } int cont_StackNthTop(int N) { return cont_STACK[cont_STACKPOINTER - (1 + N)]; } void cont_StackRplacTop(int Entry) { cont_STACK[cont_STACKPOINTER - 1] = Entry; } void cont_StackRplacNthTop(int N, int Entry) { cont_STACK[cont_STACKPOINTER - (1 + N)] = Entry; } void cont_StackRplacNth(int N, int Entry) { cont_STACK[N] = Entry; } intptr_t cont_StackBottom(void) { return cont_STACKPOINTER; } void cont_StackSetBottom(int Pointer) { cont_STACKPOINTER = Pointer; } BOOL cont_StackEmpty(int Pointer) { return cont_STACKPOINTER == Pointer; } void cont_StartBinding(void) { cont_StackPush(cont_BINDINGS); cont_BINDINGS = 0; } int cont_BindingsSinceLastStart(void) { return cont_BINDINGS; } void cont_StopAndStartBinding(void) { cont_StackRplacTop(cont_StackTop() + cont_BINDINGS); cont_BINDINGS = 0; } VARCONT cont_Binding(VARCONT C, SYMBOL Var) { return &(C)[Var]; } VARCONT cont_BindingLink(VARCONT B) { return B->link; } void cont_SetBindingLink(VARCONT B, VARCONT L) { B->link = L; } TERM cont_BindingTerm(VARCONT B) { return B->term; } void cont_SetBindingTerm(VARCONT B, TERM T) { B->term = T; } SYMBOL cont_BindingSymbol(VARCONT B) { return B->symbol; } void cont_SetBindingSymbol(VARCONT B, SYMBOL S) { B->symbol = S; } SYMBOL cont_BindingRenaming(VARCONT B) { return B->renaming; } void cont_SetBindingRenaming(VARCONT B, SYMBOL S) { B->renaming = S; } VARCONT cont_BindingContext(VARCONT B) { return B->context; } void cont_SetBindingContext(VARCONT B, VARCONT C) { B->context = C; } VARCONT cont_ContextBindingLink(VARCONT C,SYMBOL Var) { return C[Var].link; } TERM cont_ContextBindingTerm(VARCONT C,SYMBOL Var) { return C[Var].term; } void cont_SetContextBindingTerm(VARCONT C, SYMBOL Var, TERM t) { C[Var].term = t; } SYMBOL cont_ContextBindingSymbol(VARCONT C,SYMBOL Var) { return C[Var].symbol; } SYMBOL cont_ContextBindingRenaming(VARCONT C,SYMBOL Var) { return C[Var].renaming; } void cont_SetContextBindingRenaming(VARCONT C, SYMBOL Var, SYMBOL R) { C[Var].renaming = R; } VARCONT cont_ContextBindingContext(VARCONT C,SYMBOL Var) { return C[Var].context; } /**************************************************************/ /* Predicates */ /**************************************************************/ BOOL cont_VarIsBound(VARCONT C, SYMBOL Var) { return cont_ContextBindingTerm(C,Var) != (TERM) NULL; } BOOL cont_VarIsUsed(VARCONT C, SYMBOL Var) { return cont_ContextBindingContext(C,Var) != (VARCONT) NULL; } BOOL cont_VarIsLinked(VARCONT C, SYMBOL Var) { return cont_ContextBindingLink(C,Var) != (VARCONT) NULL; } BOOL cont_VarIsRenamed(VARCONT C, SYMBOL Var) { return cont_ContextBindingRenaming(C, Var) != symbol_Null(); } BOOL cont_VarIsClosed(VARCONT C,SYMBOL Var) { return !cont_VarIsBound(C,Var) && cont_VarIsUsed(C,Var); } BOOL cont_BindingIsBound(VARCONT B) { return cont_BindingTerm(B) != (TERM) NULL; } BOOL cont_BindingIsUsed(VARCONT B) { return cont_BindingContext(B) != (VARCONT) NULL; } BOOL cont_IsBoundToVar(VARCONT C) { return term_IsStandardVariable(cont_BindingTerm(C)); } /**************************************************************/ /* Aux functions for backtracking */ /**************************************************************/ VARCONT cont_LastBinding(void) { return cont_LASTBINDING; } void cont_SetLastBinding(VARCONT B) { cont_LASTBINDING = B; } TERM cont_LastBindingTerm(void) { return cont_BindingTerm(cont_LastBinding()); } SYMBOL cont_LastBindingSymbol(void) { return cont_BindingSymbol(cont_LastBinding()); } VARCONT cont_LastBindingContext(void) { return cont_BindingContext(cont_LastBinding()); } BOOL cont_LastIsBound(void) { return cont_BindingIsBound(cont_LastBinding()); } BOOL cont_LastIsUsed(void) { return cont_LastBindingContext() != (VARCONT) NULL; } BOOL cont_LastIsClosed(void) { return !cont_LastIsBound() && cont_LastIsUsed(); } BOOL cont_IsInContext(VARCONT C, SYMBOL Var, VARCONT B) { return cont_Binding(C, Var) == B; } /**************************************************************/ /* Initialization */ /**************************************************************/ void cont_InitContext(VARCONT C) { int i; for (i = 0; i < cont__SIZE; i++) cont_InitBinding(C, i); } /**************************************************************/ /* Creation and deletion of contexts */ /**************************************************************/ VARCONT cont_Create(void) { VARCONT Result; Result = (VARCONT)memory_Malloc(cont__SIZE*sizeof(VARCONT_NODE)); cont_InitContext(Result); cont_LISTOFVARCONTS = list_Cons(Result, cont_LISTOFVARCONTS); cont_NOOFVARCONTS++; return Result; } void cont_Delete(VARCONT C) { #ifdef CHECK if ((cont_NOOFVARCONTS == 0) || !list_PointerMember(cont_LISTOFVARCONTS, C)) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_Delete: Context %ld not registered.\n", (unsigned long)C); misc_FinishErrorReport(); } #endif cont_LISTOFVARCONTS = list_PointerDeleteOneElement(cont_LISTOFVARCONTS, C); cont_NOOFVARCONTS--; memory_Free(C, cont__SIZE*sizeof(VARCONT_NODE)); } void cont_ResetIndexVarScanner(void) { cont_INDEXVARSCANNER = symbol_GetInitialIndexVarCounter(); } /**************************************************************/ /* Output bindings */ /**************************************************************/ void cont_PrintCurrentTrail(void) { fputs("\nPrint bindings:", stdout); cont_CURRENTBINDING = cont_LastBinding(); while (cont_CURRENTBINDING) { cont_BindingOutput(cont_ContextOfBinding(cont_CURRENTBINDING), cont_BindingSymbol(cont_CURRENTBINDING)); cont_CURRENTBINDING = cont_BindingLink(cont_CURRENTBINDING); if (cont_CURRENTBINDING) putchar('\n'); } fflush(stdout); } /**************************************************************/ /* Check Current Trail */ /**************************************************************/ BOOL cont_OnlyVariablesInCoDomOfCurrentTrail() { cont_CURRENTBINDING = cont_LastBinding(); while(cont_CURRENTBINDING){ #ifdef CHECK if(cont_BindingSymbol(cont_CURRENTBINDING) != cont_ContextBindingSymbol(cont_ContextOfBinding(cont_CURRENTBINDING), cont_BindingSymbol(cont_CURRENTBINDING))) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_OnlyVariablesInCoDomOfCurrentTrail: Wrong Trail.\n"); misc_FinishErrorReport(); } #endif if(symbol_IsStandardVariable(cont_BindingSymbol(cont_CURRENTBINDING)) && !cont_IsBoundToVar(cont_CURRENTBINDING)) { return FALSE; } cont_CURRENTBINDING = cont_BindingLink(cont_CURRENTBINDING); } return TRUE; } /**************************************************************/ /* Close bindings */ /**************************************************************/ void cont_CloseBindingHelp(VARCONT C, SYMBOL Var) { cont_SetContextBindingTerm(C, Var, NULL); } void cont_CloseBindingBindingHelp(VARCONT B) { cont_SetBindingTerm(B, NULL); } #if SHOWBINDINGS void cont_CloseBinding(VARCONT C, SYMBOL Var) { fputs("\nClose binding from ", stdout); cont_BindingOutput(C, Var); cont_CloseBindingHelp(C, Var); } #else void cont_CloseBinding(VARCONT C, SYMBOL Var) { cont_CloseBindingHelp(C, Var); } #endif void cont_CloseBindingBinding(VARCONT B) { cont_CloseBindingBindingHelp(B); } /**************************************************************/ /* Establish bindings */ /**************************************************************/ #if SHOWBINDINGS int cont_CreateBinding(VARCONT C, SYMBOL Var, VARCONT CTerm, TERM Term) { cont_CreateBindingHelp(C,Var,CTerm,Term); fputs("\nEstablish binding from ", stdout); cont_BindingOutput(C, Var); return ++cont_BINDINGS; } int cont_CreateClosedBinding(VARCONT C, SYMBOL Var) { cont_CreateBindingHelp(C, Var, C, NULL); fputs("\nEstablish closed binding from ", stdout); cont_BindingOutput(C,Var); return ++cont_BINDINGS; } #else int cont_CreateBinding(VARCONT C, SYMBOL Var, VARCONT CTerm, TERM Term) { cont_CreateBindingHelp(C,Var,CTerm,Term); return ++cont_BINDINGS; } int cont_CreateClosedBinding(VARCONT C, SYMBOL Var) { cont_CreateBindingHelp(C, Var, C, NULL); return ++cont_BINDINGS; } #endif /**************************************************************/ /* Backtracking */ /**************************************************************/ #if SHOWBINDINGS void cont_BackTrackLastBinding(void) { VARCONT LastContext; SYMBOL LastSymbol; LastContext = cont_ContextOfBinding(cont_LastBinding()); LastSymbol = cont_LastBindingSymbol(); fputs("\nBacktrack binding from ", stdout); cont_BindingOutput(LastContext, LastSymbol); cont_BackTrackLastBindingHelp(); } int cont_BackTrack(void) { printf("\nBacktrack %d bindings:", cont_BINDINGS); while (cont_BINDINGS > 0) cont_BackTrackLastBinding(); if (!cont_StackEmpty(0)) cont_BINDINGS = cont_StackPopResult(); fflush(stdout); return 0; } int cont_StopAndBackTrack(void) { #ifdef CHECK if (cont_BINDINGS > 0) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_StopAndBackTrack: Bindings not reset!\n"); misc_FinishErrorReport(); } else if (cont_StackEmpty(0)) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_StopAndBackTrack: No bindings on stack!\n"); misc_FinishErrorReport(); } #endif cont_BINDINGS = cont_StackPopResult(); printf("\nStop and Backtrack %d bindings:", cont_BINDINGS); while (cont_BINDINGS > 0) cont_BackTrackLastBinding(); fflush(stdout); return 0; } int cont_BackTrackAndStart(void) { printf("\nBacktrack %d bindings:", cont_BINDINGS); while (cont_BINDINGS > 0) cont_BackTrackLastBinding(); fflush(stdout); return 0; } void cont_Reset(void) { fputs("\nReset bindings:", stdout); while (cont_LastBinding()) cont_BackTrackLastBinding(); cont_BINDINGS = 0; cont_StackInit(); cont_ResetIndexVarScanner(); fflush(stdout); } #else void cont_BackTrackLastBinding(void) { cont_BackTrackLastBindingHelp(); } int cont_BackTrack(void) { while (cont_BINDINGS > 0) cont_BackTrackLastBinding(); if (!cont_StackEmpty(0)) cont_BINDINGS = cont_StackPopResult(); return 0; } int cont_StopAndBackTrack(void) { #ifdef CHECK if (cont_BINDINGS > 0) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_StopAndBackTrack: Bindings not reset!\n"); misc_FinishErrorReport(); } else if (cont_StackEmpty(0)) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_StopAndBackTrack: No bindings on stack!\n"); misc_FinishErrorReport(); } #endif cont_BINDINGS = cont_StackPopResult(); while (cont_BINDINGS > 0) cont_BackTrackLastBinding(); return 0; } int cont_BackTrackAndStart(void) { while (cont_BINDINGS > 0) cont_BackTrackLastBinding(); return 0; } void cont_Reset(void) { while (cont_LastBinding()) cont_BackTrackLastBinding(); cont_BINDINGS = 0; cont_StackInit(); cont_ResetIndexVarScanner(); } #endif /* Stack operations */ void cont_CheckStackInit(void) { cont_CHECKSTACKPOINTER = cont__CHECKSTACKEMPTY; } void cont_CheckStackPush(POINTER Entry) { #ifdef CHECK if (cont_CHECKSTACKPOINTER >= cont__STACKSIZE) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_CheckStackPush: Context check stack overflow!\n"); misc_FinishErrorReport(); } #endif cont_CHECKSTACK[cont_CHECKSTACKPOINTER++] = Entry; } void cont_CheckStackPop(void) { --cont_CHECKSTACKPOINTER; } POINTER cont_CheckStackPopResult(void) { return cont_CHECKSTACK[--cont_CHECKSTACKPOINTER]; } void cont_CheckStackNPop(int N) { cont_CHECKSTACKPOINTER -= N; } POINTER cont_CheckStackTop(void) { return cont_CHECKSTACK[cont_CHECKSTACKPOINTER - 1]; } POINTER cont_CheckStackNthTop(int N) { return cont_CHECKSTACK[cont_CHECKSTACKPOINTER - (1 + N)]; } void cont_CheckStackRplacTop(POINTER Entry) { cont_CHECKSTACK[cont_CHECKSTACKPOINTER - 1] = Entry; } void cont_CheckStackRplacNthTop(int N, POINTER Entry) { cont_CHECKSTACK[cont_CHECKSTACKPOINTER - (1 + N)] = Entry; } void cont_CheckStackRplacNth(int N, POINTER Entry) { cont_CHECKSTACK[N] = Entry; } int cont_CheckStackBottom(void) { return cont_CHECKSTACKPOINTER; } void cont_CheckStackSetBottom(int Pointer) { cont_CHECKSTACKPOINTER = Pointer; } BOOL cont_CheckStackEmpty(int Pointer) { return cont_CHECKSTACKPOINTER == Pointer; } extern VARCONT cont_STATELASTBINDING; /* Storage to save state of trails. */ extern int cont_STATEBINDINGS; /* Storage to save number of current bindings. */ extern int cont_STATESTACK; /* Storage to save state of stack. */ extern int cont_STATETOPSTACK; /* Storage to save state of the top element of the stack. */ BOOL cont_CheckLastBinding(VARCONT Check, int Bindings) { VARCONT Scan; BOOL Result; Scan = cont_LastBinding(); while (Bindings > 0) { Scan = cont_BindingLink(Scan); Bindings--; } if (Check == Scan) Result = TRUE; else Result = FALSE; return Result; } void cont_CheckState(void) { if (cont_CheckStackEmpty(cont__CHECKSTACKEMPTY)) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_CheckState: No states saved.\n"); misc_FinishErrorReport(); } cont_STATETOPSTACK = (intptr_t)cont_CheckStackPopResult(); cont_STATESTACK = (intptr_t)cont_CheckStackPopResult(); cont_STATEBINDINGS = (intptr_t)cont_CheckStackPopResult(); cont_STATELASTBINDING = (VARCONT)cont_CheckStackPopResult(); if ((cont_STATELASTBINDING != cont_LastBinding()) || (cont_STATEBINDINGS != cont_BINDINGS) || (!cont_StackEmpty(cont_STATESTACK)) || (cont_STATETOPSTACK != cont_StackTop())) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_CheckState: State of contexts does not match saved state."); misc_ErrorReport("\nTrail: Saved state: %ld; current state: %ld.", (long)cont_STATELASTBINDING, (long)cont_LastBinding()); misc_ErrorReport("\nNumber of bindings: Saved state: %d; current state: %d.", cont_STATEBINDINGS, cont_BINDINGS); misc_ErrorReport("\nBinding stack pointer: Saved state: %d; current state: %d.", cont_STATESTACK, cont_StackBottom()); misc_ErrorReport("\nNumber of bindings on top of stack: Saved state: %d; current state: %d.\n\n", cont_STATETOPSTACK, cont_StackTop()); misc_FinishErrorReport(); } } void cont_SaveState(void) { cont_CheckStackPush((POINTER)cont_LastBinding()); cont_CheckStackPush((POINTER)cont_BINDINGS); cont_CheckStackPush((POINTER)cont_StackBottom()); cont_CheckStackPush((POINTER)cont_StackTop()); } BOOL cont_IsContextEmpty(const VARCONT Check) { int i; for (i = 0; i < cont__SIZE; i++) if (cont_VarIsBound(Check, i) || cont_VarIsUsed(Check, i) || cont_VarIsLinked(Check, i) || cont_VarIsRenamed(Check, i)) return FALSE; return TRUE; } /**************************************************************/ /* Generation of index variables */ /**************************************************************/ SYMBOL cont_NextIndexVariable(const VARCONT IndexContext) { if (symbol_Equal(cont_INDEXVARSCANNER, symbol_LastIndexVariable())) cont_INDEXVARSCANNER = symbol_CreateIndexVariable(); else for (;;) { cont_INDEXVARSCANNER = symbol_NextIndexVariable(cont_INDEXVARSCANNER); if (!cont_VarIsUsed(IndexContext, cont_INDEXVARSCANNER)) break; else if (symbol_Equal(cont_INDEXVARSCANNER, symbol_LastIndexVariable())) { cont_INDEXVARSCANNER = symbol_CreateIndexVariable(); break; } } return cont_INDEXVARSCANNER; } /**************************************************************/ /* Dereferencing of terms wrt. contexts */ /**************************************************************/ TERM cont_SymbolDeref(VARCONT* Context, SYMBOL Symbol) /************************************************************** INPUT: A call-by-ref context and a variable symbol. RETURNS: The dereferenced term and the corresponding context, NULL if the symbol is not bound SUMMARY: Dereferences bindings of variables. CAUTION: In general, the context of the returned term is different to the input context. ***************************************************************/ { TERM Term; Term = (TERM)NULL; while (symbol_IsVariable(Symbol) && *Context != cont_InstanceContext()) { if (cont_VarIsBound(*Context, Symbol)) { VARCONT HelpContext; HelpContext = cont_ContextBindingContext(*Context, Symbol); Term = cont_ContextBindingTerm(*Context, Symbol); *Context = HelpContext; Symbol = term_TopSymbol(Term); } else return Term; } return Term; } /**************************************************************/ /* Global Variables */ /**************************************************************/ int cont_NOOFVARCONTS; LIST cont_LISTOFVARCONTS; intptr_t cont_BINDINGS; SYMBOL cont_INDEXVARSCANNER; VARCONT cont_LASTBINDING; /* The last binding made. */ VARCONT cont_CURRENTBINDING; /* Help variable. */ VARCONT cont_LEFTVARCONT; VARCONT cont_RIGHTVARCONT; VARCONT cont_INSTANCEVARCONT; cont_STACK_TYPE cont_STACK; int cont_STACKPOINTER; cont_CHECKSTACK_TYPE cont_CHECKSTACK; int cont_CHECKSTACKPOINTER; VARCONT cont_STATELASTBINDING; /* Storage to save state of trails. */ int cont_STATEBINDINGS; /* Storage to save number of current bindings. */ int cont_STATESTACK; /* Storage to save state of stack. */ int cont_STATETOPSTACK; /* Storage to save state of the top element of the stack. */ /**************************************************************/ /* ********************************************************** */ /* * * */ /* * INITIALIZATION * */ /* * * */ /* ********************************************************** */ /**************************************************************/ void cont_Init(void) /********************************************************** INPUT: None. RETURNS: None. EFFECT: Initializes the unify module. ********************************************************/ { cont_LASTBINDING = (VARCONT)NULL; cont_ResetIndexVarScanner(); cont_NOOFVARCONTS = 0; cont_LISTOFVARCONTS = list_Nil(); cont_BINDINGS = 0; cont_INSTANCEVARCONT = (VARCONT)memory_Malloc(sizeof(VARCONT_NODE)); cont_LEFTVARCONT = cont_Create(); cont_RIGHTVARCONT = cont_Create(); cont_StackInit(); cont_StackPush(0); cont_StackPop(); } void cont_Check(void) /********************************************************** INPUT: None. RETURNS: None. EFFECT: Frees internal structures of the unify module. ********************************************************/ { #ifdef CHECK if (cont_LASTBINDING || (cont_BINDINGS != 0) || !symbol_Equal(cont_INDEXVARSCANNER, symbol_GetInitialIndexVarCounter())) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_Check: There are variable bindings not reset.\n"); misc_FinishErrorReport(); } #endif } void cont_Free(void) /********************************************************** INPUT: None. RETURNS: None. EFFECT: Frees internal structures of the unify module. ********************************************************/ { cont_Check(); while (cont_NOOFVARCONTS > 0) cont_Delete(list_Car(cont_LISTOFVARCONTS)); /* Decreases NOOFVARCONTS */ cont_BINDINGS = 0; memory_Free(cont_INSTANCEVARCONT, sizeof(VARCONT_NODE)); } void cont_InitBinding(VARCONT C, SYMBOL Var) /********************************************************** INPUT: A context and a variable. RETURNS: Nothing. EFFECT: Initializes a binding of variable in the given context. ********************************************************/ { cont_CURRENTBINDING = cont_Binding(C, Var); cont_SetBindingLink(cont_CURRENTBINDING, (VARCONT)NULL); cont_SetBindingTerm(cont_CURRENTBINDING, (TERM)NULL); cont_SetBindingSymbol(cont_CURRENTBINDING, Var); cont_SetBindingRenaming(cont_CURRENTBINDING, symbol_Null()); cont_SetBindingContext(cont_CURRENTBINDING, (VARCONT)NULL); } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * TERM EQUALITY WITH RESPECT TO BOUND VARIABLES * */ /* * * */ /* ********************************************************** */ /**************************************************************/ BOOL cont_TermEqual(VARCONT GlobalContext1, VARCONT TermContext1, TERM Term1, VARCONT GlobalContext2, VARCONT 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 and are bound in and respectively and the index variables are bound in and 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; } BOOL cont_TermEqualModuloBindings(VARCONT IndexContext, VARCONT CtL, TERM TermL, VARCONT 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)) { VARCONT 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)) { VARCONT 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; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * APPLY BINDINGS * */ /* * * */ /* ********************************************************** */ /**************************************************************/ TERM cont_CopyAndApplyBindings(VARCONT TermContext, TERM Term) { while (term_IsVariable(Term)) { SYMBOL TermTop; TermTop = term_TopSymbol(Term); if (cont_VarIsBound(TermContext, TermTop)) { VARCONT HelpContext; HelpContext = cont_ContextBindingContext(TermContext, TermTop); Term = cont_ContextBindingTerm(TermContext, TermTop); TermContext = HelpContext; } else break; } if (term_IsComplex(Term)) { LIST Scan, ArgumentList; for (Scan = ArgumentList = list_Copy(term_ArgumentList(Term)); !list_Empty(Scan); Scan = list_Cdr(Scan)) list_Rplaca(Scan, cont_CopyAndApplyBindings(TermContext, list_Car(Scan))); return term_Create(term_TopSymbol(Term), ArgumentList); } else return term_Create(term_TopSymbol(Term), list_Nil()); } TERM cont_SymbolApplyBindings(VARCONT TermContext, SYMBOL Symbol) /************************************************************** INPUT: A call-by-ref context and a variable symbol. RETURNS: The recursively dereferenced term and the corresponding context, NULL if the symbol is not bound SUMMARY: Dereferences bindings of variables. CAUTION: In general, the context of the returned term is different to the input context. ***************************************************************/ { TERM Term; Term = (TERM)NULL; while (symbol_IsVariable(Symbol)) { if (cont_VarIsBound(TermContext, Symbol)) { VARCONT HelpContext; HelpContext = cont_ContextBindingContext(TermContext, Symbol); Term = cont_ContextBindingTerm(TermContext, Symbol); TermContext = HelpContext; Symbol = term_TopSymbol(Term); } else break; } if (Term != (TERM)NULL && term_IsComplex(Term)) { LIST Scan, ArgumentList; for (Scan = ArgumentList = list_Copy(term_ArgumentList(Term)); !list_Empty(Scan); Scan = list_Cdr(Scan)) list_Rplaca(Scan, cont_CopyAndApplyBindings(TermContext, list_Car(Scan))); return term_Create(term_TopSymbol(Term), ArgumentList); } return Term; } TERM cont_CopyAndApplyBindingsCom(const VARCONT Context, TERM Term) { while (term_IsVariable(Term) && cont_VarIsBound(Context, term_TopSymbol(Term))) Term = cont_ContextBindingTerm(Context, term_TopSymbol(Term)); if (term_IsComplex(Term)) { LIST Scan, ArgumentList; for (Scan = ArgumentList = list_Copy(term_ArgumentList(Term)); !list_Empty(Scan); Scan = list_Cdr(Scan)) list_Rplaca(Scan, cont_CopyAndApplyBindingsCom(Context, list_Car(Scan))); return term_Create(term_TopSymbol(Term), ArgumentList); } else return term_Create(term_TopSymbol(Term), list_Nil()); } TERM cont_ApplyBindingsModuloMatching(const VARCONT Context, TERM Term, BOOL VarCheck) /********************************************************** INPUT: A context, a term, and a boolean flag. RETURNS: is destructively changed with respect to established bindings in the context. If is true, all variables in must be bound in the context. When compiled with "CHECK" on, this condition is in fact checked. This function only makes sense after a matching operation. ***********************************************************/ { TERM RplacTerm; LIST Arglist; SYMBOL Top; #ifdef CHECK if (VarCheck && symbol_IsVariable(term_TopSymbol(Term)) && !cont_VarIsBound(Context, term_TopSymbol(Term))) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_ApplyBindingsModuloMatching:"); misc_ErrorReport(" Used in forbidden context.\n"); misc_FinishErrorReport(); } #endif Top = term_TopSymbol(Term); if (symbol_IsVariable(Top)) { if (cont_VarIsBound(Context, Top)) { RplacTerm = cont_ContextBindingTerm(Context, Top); Arglist = term_CopyTermList(term_ArgumentList(RplacTerm)); term_RplacTop(Term, term_TopSymbol(RplacTerm)); term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term, Arglist); } } else { for (Arglist = term_ArgumentList(Term); !list_Empty(Arglist); Arglist = list_Cdr(Arglist)) cont_ApplyBindingsModuloMatching(Context, list_Car(Arglist), VarCheck); } return Term; } static TERM cont_CopyAndApplyIndexVariableBindings(const VARCONT Context, TERM Term) { SYMBOL TermTop; #ifdef CHECK if (symbol_IsIndexVariable(term_TopSymbol(Term)) && !cont_VarIsBound(Context, term_TopSymbol(Term))) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_CopyAndApplyIndexVariableBindings:"); misc_ErrorReport(" Expected bound index variable."); misc_FinishErrorReport(); } #endif TermTop = term_TopSymbol(Term); while (symbol_IsIndexVariable(TermTop)) { if (cont_VarIsBound(Context, TermTop)) { Term = cont_ContextBindingTerm(Context, TermTop); TermTop = term_TopSymbol(Term); } } if (term_IsComplex(Term)) { LIST Scan, ArgumentList; for (Scan = ArgumentList = list_Copy(term_ArgumentList(Term)); !list_Empty(Scan); Scan = list_Cdr(Scan)) list_Rplaca(Scan, cont_CopyAndApplyIndexVariableBindings(Context, list_Car(Scan))); return term_Create(TermTop, ArgumentList); } else return term_Create(TermTop, list_Nil()); } TERM cont_ApplyBindingsModuloMatchingReverse(const VARCONT Context, TERM Term) /********************************************************** INPUT: A term. RETURNS: is destructively changed with respect to established bindings in the leftmost context. This function only make sense after a matching operation (reverse). ***********************************************************/ { TERM RplacTerm; LIST Arglist; SYMBOL Top; #ifdef CHECK if (symbol_IsVariable(term_TopSymbol(Term)) && !cont_VarIsBound(Context, term_TopSymbol(Term))) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_ApplyBindingsModuloMatchingReverse:"); misc_ErrorReport(" Used in forbidden context.\n"); misc_FinishErrorReport(); } #endif Top = term_TopSymbol(Term); if (symbol_IsVariable(Top)) { if (cont_VarIsBound(Context, Top)) { RplacTerm = cont_CopyAndApplyIndexVariableBindings(Context, cont_ContextBindingTerm(Context, Top)); term_RplacTop(Term, term_TopSymbol(RplacTerm)); term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term, term_ArgumentList(RplacTerm)); term_Free(RplacTerm); } } else { for (Arglist = term_ArgumentList(Term); !list_Empty(Arglist); Arglist = list_Cdr(Arglist)) cont_ApplyBindingsModuloMatchingReverse(Context, list_Car(Arglist)); } return Term; } BOOL cont_BindingsAreRenamingModuloMatching(const VARCONT RenamingContext) { VARCONT Context; #ifdef CHECK if (!cont_IsContextEmpty(RenamingContext)) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_BindingsAreRenamingModuloMatching:"); misc_ErrorReport(" Renaming context contains bindings.\n"); misc_FinishErrorReport(); } #endif cont_StartBinding(); Context = cont_LastBinding(); while (Context) { if (!symbol_IsIndexVariable(cont_BindingSymbol(Context))) { SYMBOL CodomainSymbol; CodomainSymbol = term_TopSymbol(cont_BindingTerm(Context)); if (symbol_IsVariable(CodomainSymbol)) { if (cont_VarIsRenamed(RenamingContext, CodomainSymbol)) { cont_BackTrack(); return FALSE; } else { cont_CreateBinding(RenamingContext, CodomainSymbol, NULL, NULL); cont_SetContextBindingRenaming(RenamingContext, CodomainSymbol, CodomainSymbol); } } else { cont_BackTrack(); return FALSE; } } Context = cont_BindingLink(Context); } cont_BackTrack(); return TRUE; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * MISC FUNCTIONS * */ /* * * */ /* ********************************************************** */ /**************************************************************/ void cont_CreateBindingHelp(VARCONT C, SYMBOL Var, VARCONT CTerm, TERM Term) { #ifdef CHECK if (cont_VarIsBound(C, Var)) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_CreateBindingHelp: Variable already bound.\n"); misc_FinishErrorReport(); } #endif cont_CURRENTBINDING = cont_Binding(C,Var); cont_SetBindingTerm(cont_CURRENTBINDING, Term); cont_SetBindingContext(cont_CURRENTBINDING, CTerm); cont_SetBindingLink(cont_CURRENTBINDING, cont_LastBinding()); cont_SetLastBinding(cont_CURRENTBINDING); } VARCONT cont_ContextOfBinding(VARCONT B) { VARCONT Result; LIST Scan; for (Result = NULL, Scan = cont_LISTOFVARCONTS; list_Exist(Scan); Scan = list_Cdr(Scan)) { if (cont_IsInContext(list_Car(Scan), cont_BindingSymbol(B), B)) { Result = list_Car(Scan); break; } } #ifdef CHECK if (Result == NULL) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_ContextOfBinding: Unknown context.\n"); misc_FinishErrorReport(); } #endif return Result; } void cont_BindingOutput(VARCONT C, SYMBOL Var) { symbol_Print(cont_ContextBindingSymbol(C, Var)); putchar(':'); symbol_Print(Var); fputs(" -> ", stdout); if (cont_VarIsBound(C, Var)) { term_PrintPrefix(cont_ContextBindingTerm(C, Var)); } else fputs("unbound", stdout); fputs(" in ", stdout); if (cont_VarIsUsed(C, Var)) { printf("%ld", (unsigned long)cont_ContextBindingContext(C, Var)); } else fputs("NULL (unused)", stdout); fputs(". ", stdout); if (cont_VarIsClosed(C, Var)) { fputs("(closed)", stdout); } if (!cont_VarIsBound(C, Var) && !cont_VarIsUsed(C, Var)) { fputs(",(free)", stdout); } if (cont_VarIsRenamed(C, Var)) { fputs(",(renamed): ", stdout); symbol_Print(Var); fputs(" -> ", stdout); symbol_Print(cont_ContextBindingRenaming(C, Var)); } fflush(stdout); } void cont_BackTrackLastBindingHelp(void) { cont_CURRENTBINDING = cont_LastBinding(); cont_SetLastBinding(cont_BindingLink(cont_CURRENTBINDING)); cont_SetBindingTerm(cont_CURRENTBINDING, NULL); cont_SetBindingContext(cont_CURRENTBINDING, NULL); cont_SetBindingRenaming(cont_CURRENTBINDING, symbol_Null()); cont_SetBindingLink(cont_CURRENTBINDING, NULL); cont_BINDINGS--; } SYMBOL cont_TermMaxVar(VARCONT GlobalContext, VARCONT TermContext, TERM Term) /********************************************************* INPUT: A global Context where Index variables are bound a context and a term RETURNS: The maximal variable in with respect to the bindings in CAUTION: Variables of are bound in and the index variables are bound in ********************************************************/ { LIST scan; SYMBOL result; #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_TermMaxVar: Input term is corrupted.\n"); misc_FinishErrorReport(); } #endif Term = cont_Deref(GlobalContext,&TermContext,Term); result = symbol_Null(); if (term_IsStandardVariable(Term)) { if (term_TopSymbol(Term) > result) result = term_TopSymbol(Term); } else { for (scan = term_ArgumentList(Term); !list_Empty(scan); scan = list_Cdr(scan)) { SYMBOL max = cont_TermMaxVar(GlobalContext, TermContext, list_Car(scan)); if (max > result) result = max; } } return result; } NAT cont_TermSize(VARCONT GlobalContext, VARCONT TermContext, TERM Term) /********************************************************* INPUT: A global context where index variables are bound a context and a term. RETURNS: The number of symbols in with respect to the bindings in CAUTION: Variables of are bound in and the index variables are bound in ********************************************************/ { NAT result; LIST scan; Term = cont_Deref(GlobalContext, &TermContext, Term); result = 1; for (scan = term_ArgumentList(Term); !list_Empty(scan); scan = list_Cdr(scan)) result += cont_TermSize(GlobalContext, TermContext, list_Car(scan)); return result; } BOOL cont_TermContainsSymbol(VARCONT GlobalContext, VARCONT TermContext, TERM Term, SYMBOL Symbol) /********************************************************* INPUT: A global context where index varibles are bound a context, a term and a symbol. RETURNS: TRUE, if occurs in with respect to the bindings in , FALSE otherwise. ********************************************************/ { LIST scan; Term = cont_Deref(GlobalContext, &TermContext, Term); if (symbol_Equal(term_TopSymbol(Term), Symbol)) return TRUE; else for (scan = term_ArgumentList(Term); !list_Empty(scan); scan = list_Cdr(scan)) { if (cont_TermContainsSymbol(GlobalContext, TermContext, list_Car(scan), Symbol)) return TRUE; } return FALSE; } TERM cont_Deref(VARCONT GlobalContext, VARCONT* TermContext, TERM Term) /****************************************************************** INPUT: A global context where the Index variables are bound, a term and a call-by-ref context for . RETURNS: The dereferenced term and the corresponding context. SUMMARY: Dereferences bindings of variables. CAUTION: In general, the context of the returned term is different to the input context. ASSUMPTION: All Index variables occuring in have to be bound in , no Index variable is mapped to another index variable *******************************************************************/ { if(term_IsIndexVariable(Term)) { SYMBOL TermTop; TermTop = term_TopSymbol(Term); #ifdef CHECK if(!cont_VarIsBound(GlobalContext, TermTop) || term_IsIndexVariable(cont_ContextBindingTerm(GlobalContext, TermTop))) { misc_StartErrorReport(); misc_ErrorReport("\ncont_Deref: Illegal Context!"); misc_FinishErrorReport(); } #endif Term = cont_ContextBindingTerm(GlobalContext, TermTop); *TermContext = cont_ContextBindingContext(GlobalContext, TermTop); } while (term_IsVariable(Term) && *TermContext != cont_InstanceContext()) { SYMBOL TermTop; TermTop = term_TopSymbol(Term); if (cont_VarIsBound(*TermContext, TermTop)) { VARCONT HelpContext; HelpContext = cont_ContextBindingContext(*TermContext, TermTop); Term = cont_ContextBindingTerm(*TermContext, TermTop); *TermContext = HelpContext; } else return Term; } return Term; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * OUTPUT * */ /* * * */ /* ********************************************************** */ /**************************************************************/ void cont_TermPrintPrefix(VARCONT GlobalContext, VARCONT TermContext, TERM Term) /************************************************************** INPUT: A global context where index variables are bound, a context and a term. RETURNS: none. SUMMARY: Prints the term modulo the context to stdout. CAUTION: Variables of are bound in and the index variables are bound in ***************************************************************/ { Term = cont_Deref(GlobalContext,&TermContext, Term); symbol_Print(term_TopSymbol(Term)); if (term_IsComplex(Term)) { LIST List; putchar('('); for (List = term_ArgumentList(Term); !list_Empty(List); List = list_Cdr(List)) { cont_TermPrintPrefix(GlobalContext, TermContext, list_Car(List)); if (!list_Empty(list_Cdr(List))) putchar(','); } putchar(')'); } } spass-3.9/context.h000066400000000000000000000323531325017163600143650ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * VARCONTS FOR VARIABLES * */ /* * * */ /* * $Module: VARCONT * */ /* * * */ /* * Copyright (C) 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.7 $ * */ /* $State: Exp $ * */ /* $Date: 2011-11-27 11:18:20 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: context.h,v $ */ #define SHOWBINDINGS 0 #ifndef _VARCONT_ #define _VARCONT_ /**************************************************************/ /* Includes */ /**************************************************************/ #include "term.h" #include "symbol.h" #include "list.h" /**************************************************************/ /* Structures */ /**************************************************************/ /* Set 'SHOWBINDINGS' to non-zero value to enable debug output. */ /* #define SHOWBINDINGS 1 */ #define cont__SIZE symbol__MAXVARIABLES extern int cont_NOOFVARCONTS; extern LIST cont_LISTOFVARCONTS; extern intptr_t cont_BINDINGS; /* An array to remember bindings for the variables. The array */ /* is indexed by the variable index and holds the binding term. */ typedef struct binding { SYMBOL symbol; SYMBOL renaming; TERM term; struct binding *context; struct binding *link; } *VARCONT, VARCONT_NODE; extern VARCONT cont_LASTBINDING; /* The last binding made. */ extern VARCONT cont_CURRENTBINDING; /* Help variable. */ extern SYMBOL cont_INDEXVARSCANNER; /* Two contexts are allocated by default */ extern VARCONT cont_LEFTVARCONT; extern VARCONT cont_RIGHTVARCONT; extern VARCONT cont_INSTANCEVARCONT; /* This context is used as a label only (dummy context) */ VARCONT cont_LeftContext(void); VARCONT cont_RightContext(void); VARCONT cont_InstanceContext(void); /**************************************************************/ /* Binding Functions */ /**************************************************************/ void cont_BackTrackLastBindingHelp(void); VARCONT cont_ContextOfBinding(VARCONT); void cont_CreateBindingHelp(VARCONT, SYMBOL, VARCONT, TERM); void cont_BindingOutput(VARCONT C, SYMBOL Var); /**************************************************************/ /* A stack for the number of established bindings */ /**************************************************************/ #define cont__STACKSIZE 1000 typedef int cont_STACK_TYPE[cont__STACKSIZE]; extern cont_STACK_TYPE cont_STACK; extern int cont_STACKPOINTER; /* Stack operations */ void cont_StackInit(void); void cont_StackPush(int Entry); void cont_StackPop(void); int cont_StackPopResult(void); void cont_StackNPop(int N); intptr_t cont_StackTop(void); int cont_StackNthTop(int N); void cont_StackRplacTop(int Entry); void cont_StackRplacNthTop(int N, int Entry); void cont_StackRplacNth(int N, int Entry); intptr_t cont_StackBottom(void); void cont_StackSetBottom(int Pointer); BOOL cont_StackEmpty(int Pointer); void cont_StartBinding(void); int cont_BindingsSinceLastStart(void); void cont_StopAndStartBinding(void); /**************************************************************/ /* Access */ /**************************************************************/ VARCONT cont_Binding(VARCONT C, SYMBOL Var); VARCONT cont_BindingLink(VARCONT B); void cont_SetBindingLink(VARCONT B, VARCONT L); TERM cont_BindingTerm(VARCONT B); void cont_SetBindingTerm(VARCONT B, TERM T); SYMBOL cont_BindingSymbol(VARCONT B); void cont_SetBindingSymbol(VARCONT B, SYMBOL S); SYMBOL cont_BindingRenaming(VARCONT B); void cont_SetBindingRenaming(VARCONT B, SYMBOL S); VARCONT cont_BindingContext(VARCONT B); void cont_SetBindingContext(VARCONT B, VARCONT C); VARCONT cont_ContextBindingLink(VARCONT C,SYMBOL Var); TERM cont_ContextBindingTerm(VARCONT C,SYMBOL Var); void cont_SetContextBindingTerm(VARCONT C, SYMBOL Var, TERM t); SYMBOL cont_ContextBindingSymbol(VARCONT C,SYMBOL Var); SYMBOL cont_ContextBindingRenaming(VARCONT C,SYMBOL Var); void cont_SetContextBindingRenaming(VARCONT C, SYMBOL Var, SYMBOL R); VARCONT cont_ContextBindingContext(VARCONT C,SYMBOL Var); /**************************************************************/ /* Predicates */ /**************************************************************/ BOOL cont_VarIsBound(VARCONT C, SYMBOL Var); BOOL cont_VarIsUsed(VARCONT C, SYMBOL Var); BOOL cont_VarIsLinked(VARCONT C, SYMBOL Var); BOOL cont_VarIsRenamed(VARCONT C, SYMBOL Var); BOOL cont_VarIsClosed(VARCONT C,SYMBOL Var); BOOL cont_BindingIsBound(VARCONT B); BOOL cont_BindingIsUsed(VARCONT B); BOOL cont_IsBoundToVar(VARCONT C); /**************************************************************/ /* Aux functions for backtracking */ /**************************************************************/ VARCONT cont_LastBinding(void); void cont_SetLastBinding(VARCONT B); TERM cont_LastBindingTerm(void); SYMBOL cont_LastBindingSymbol(void); VARCONT cont_LastBindingContext(void); BOOL cont_LastIsBound(void); BOOL cont_LastIsUsed(void); BOOL cont_LastIsClosed(void); BOOL cont_IsInContext(VARCONT C, SYMBOL Var, VARCONT B); /**************************************************************/ /* Initialization */ /**************************************************************/ void cont_InitBinding(VARCONT C, SYMBOL Var); void cont_InitContext(VARCONT C); /**************************************************************/ /* Creation and deletion of contexts */ /**************************************************************/ VARCONT cont_Create(void); void cont_Delete(VARCONT C); void cont_ResetIndexVarScanner(void); /**************************************************************/ /* Output bindings */ /**************************************************************/ void cont_PrintCurrentTrail(void); /**************************************************************/ /* Check Current Trail */ /**************************************************************/ BOOL cont_OnlyVariablesInCoDomOfCurrentTrail(); /**************************************************************/ /* Close bindings */ /**************************************************************/ void cont_CloseBindingHelp(VARCONT C, SYMBOL Var); void cont_CloseBindingBindingHelp(VARCONT B); void cont_CloseBinding(VARCONT C, SYMBOL Var); void cont_CloseBinding(VARCONT C, SYMBOL Var); void cont_CloseBindingBinding(VARCONT B); /**************************************************************/ /* Establish bindings */ /**************************************************************/ int cont_CreateBinding(VARCONT C, SYMBOL Var, VARCONT CTerm, TERM Term); int cont_CreateClosedBinding(VARCONT C, SYMBOL Var); int cont_CreateBinding(VARCONT C, SYMBOL Var, VARCONT CTerm, TERM Term); int cont_CreateClosedBinding(VARCONT C, SYMBOL Var); /**************************************************************/ /* Backtracking */ /**************************************************************/ void cont_BackTrackLastBinding(void); int cont_BackTrack(void); int cont_StopAndBackTrack(void); int cont_BackTrackAndStart(void); void cont_Reset(void); void cont_BackTrackLastBinding(void); int cont_BackTrack(void); int cont_StopAndBackTrack(void); int cont_BackTrackAndStart(void); void cont_Reset(void); /**************************************************************/ /* Check state of bindings */ /**************************************************************/ #define cont__CHECKSTACKSIZE 1000 #define cont__CHECKSTACKEMPTY 0 typedef POINTER cont_CHECKSTACK_TYPE[cont__CHECKSTACKSIZE]; extern cont_CHECKSTACK_TYPE cont_CHECKSTACK; extern int cont_CHECKSTACKPOINTER; /* Stack operations */ void cont_CheckStackInit(void); void cont_CheckStackPush(POINTER Entry); void cont_CheckStackPop(void); POINTER cont_CheckStackPopResult(void); void cont_CheckStackNPop(int N); POINTER cont_CheckStackTop(void); POINTER cont_CheckStackNthTop(int N); void cont_CheckStackRplacTop(POINTER Entry); void cont_CheckStackRplacNthTop(int N, POINTER Entry); void cont_CheckStackRplacNth(int N, POINTER Entry); int cont_CheckStackBottom(void); void cont_CheckStackSetBottom(int Pointer); BOOL cont_CheckStackEmpty(int Pointer); extern VARCONT cont_STATELASTBINDING; /* Storage to save state of trails. */ extern int cont_STATEBINDINGS; /* Storage to save number of current bindings. */ extern int cont_STATESTACK; /* Storage to save state of stack. */ extern int cont_STATETOPSTACK; /* Storage to save state of the top element of the stack. */ BOOL cont_CheckLastBinding(VARCONT Check, int Bindings); void cont_CheckState(void); void cont_SaveState(void); BOOL cont_IsContextEmpty(const VARCONT Check); SYMBOL cont_NextIndexVariable(const VARCONT IndexContext); TERM cont_SymbolDeref(VARCONT* Context, SYMBOL Symbol); /**************************************************************/ /* Functions for Initialization and Controlling */ /**************************************************************/ void cont_Init(void); void cont_Check(void); void cont_Free(void); /**************************************************************/ /* Functions for Term Equality Test with respect to Bindings */ /**************************************************************/ BOOL cont_TermEqual(VARCONT, VARCONT, TERM, VARCONT, VARCONT, TERM); BOOL cont_TermEqualModuloBindings(VARCONT, VARCONT, TERM, VARCONT, TERM); /**************************************************************/ /* Dereferencing of terms wrt. contexts */ /**************************************************************/ TERM cont_Deref(VARCONT, VARCONT*, TERM); /**************************************************************/ /* Functions for Applying Bindings */ /**************************************************************/ TERM cont_CopyAndApplyBindings(VARCONT, TERM); TERM cont_CopyAndApplyBindingsCom(const VARCONT, TERM); TERM cont_ApplyBindingsModuloMatching(const VARCONT, TERM, BOOL); TERM cont_ApplyBindingsModuloMatchingReverse(const VARCONT, TERM); BOOL cont_BindingsAreRenamingModuloMatching(const VARCONT); /**************************************************************/ /* Misc Functions */ /**************************************************************/ SYMBOL cont_TermMaxVar(VARCONT, VARCONT, TERM); NAT cont_TermSize(VARCONT, VARCONT, TERM); BOOL cont_TermContainsSymbol(VARCONT, VARCONT, TERM, SYMBOL); /**************************************************************/ /* Functions for Output */ /**************************************************************/ void cont_TermPrintPrefix(VARCONT, VARCONT, TERM); #endif spass-3.9/defs.c000066400000000000000000001353421325017163600136170ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * DEFINITIONS * */ /* * * */ /* * $Module: DEFS * */ /* * * */ /* * Copyright (C) 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.4 $ * */ /* $State: Exp $ * */ /* $Date: 2011-05-22 12:16:58 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: defs.c,v $ */ #include "cnf.h" #include "defs.h" #include "foldfg.h" /******************************************************* *Previously inlined functions * ********************************************************/ TERM def_Expansion(DEF D) { return D->expansion; } void def_RplacExp(DEF D, TERM E) { D->expansion = E; } TERM def_Predicate(DEF D) { return D->predicate; } void def_RplacPred(DEF D, TERM Pred) { D->predicate = Pred; } TERM def_ToProve(DEF D) { return D->toprove; } void def_RplacToProve(DEF D, TERM ToProve) { D->toprove = ToProve; } LIST def_ClauseNumberList(DEF D) { return list_PairFirst(D->parentclauses); } void def_RplacClauseNumberList(DEF D, LIST L) { list_Rplaca(D->parentclauses, L); } LIST def_ClauseLitsList(DEF D) { return list_PairSecond(D->parentclauses); } void def_RplacClauseLitsList(DEF D, LIST L) { list_Rplacd(D->parentclauses, L); } const char* def_Label(DEF D) { return D->label; } void def_RplacLabel(DEF D, const char* L) { D->label = L; } BOOL def_Conjecture(DEF D) { return D->conjecture; } void def_SetConjecture(DEF D) { D->conjecture = TRUE; } void def_AddAttribute(DEF D, DEF_ATTRIBUTES Attribute) { D->attributes = D->attributes | Attribute; } NAT def_HasAttribute(DEF D, DEF_ATTRIBUTES Attribute) { return (D->attributes & Attribute); } void def_RemoveAttribute(DEF D, DEF_ATTRIBUTES Attribute) { if (D->attributes & Attribute) D->attributes = D->attributes - Attribute; } BOOL def_HasGuard(DEF D) { return (def_ToProve(D)!=term_Null()); } /******************************************************* *Previously inlined functions ends * ********************************************************/ static void def_DeleteFromClauses(DEF); static void def_DeleteFromTerm(DEF); DEF def_CreateFromClauses(TERM ExpTerm, TERM PredTerm, LIST Clauses, LIST Lits, BOOL Con) /********************************************************** INPUT: Two terms, a list of clausenumbers, a list of literal indices and a boolean saying whether all clauses derived by expanding the predicate should be conclauses. RETURNS: A definition consisting of the 2 terms as expansion term and predicate term and the list of parent clause numbers and a list of the indices of the defined predicate in the parent clauses. ToProve and label are set to NULL. ********************************************************/ { DEF result; #ifdef CHECK if (!term_IsTerm(ExpTerm) || !term_IsTerm(PredTerm)) { misc_StartErrorReport(); misc_ErrorReport("\n In def_CreateFromClause: Illegal input."); misc_FinishErrorReport(); } if (list_Empty(Clauses)) { misc_StartErrorReport(); misc_ErrorReport("\n In def_CreateFromClause: No parent clause given."); misc_FinishErrorReport(); } #endif result = (DEF) memory_Malloc(sizeof(DEF_NODE)); result->expansion = ExpTerm; result->predicate = PredTerm; result->toprove = (TERM) NULL; result->parentclauses = list_PairCreate(Clauses, Lits); result->label = (const char*) NULL; result->conjecture = Con; return result; } DEF def_CreateFromTerm(TERM ExpTerm, TERM PredTerm, TERM ToProve, const char* Label) /********************************************************** INPUT: 3 terms and a term label. RETURNS: A definition consisting of the 3 terms as expansion term, predicate term and term to prove before applying the definition and the label of the parent term. The list of clausenumbers is set to NULL. ********************************************************/ { DEF result; #ifdef CHECK if (!term_IsTerm(ExpTerm) || !term_IsTerm(PredTerm)) { misc_StartErrorReport(); misc_ErrorReport("\n In def_CreateFromTerm: Illegal input."); misc_FinishErrorReport(); } if (Label == NULL) { misc_StartErrorReport(); misc_ErrorReport("\n In def_CreateFromTerm: No parent clause given."); misc_FinishErrorReport(); } #endif result = (DEF) memory_Malloc(sizeof(DEF_NODE)); result->expansion = ExpTerm; result->predicate = PredTerm; result->toprove = ToProve; result->parentclauses = list_PairCreate(list_Nil(), list_Nil()); result->label = Label; result->conjecture = FALSE; return result; } static void def_DeleteFromClauses(DEF D) /********************************************************** INPUT: A definition derived from clauses. EFFECT: The definition is deleted, INCLUDING THE TERMS AND THE LIST OF CLAUSE NUMBERS. ********************************************************/ { #ifdef CHECK if (!term_IsTerm(def_Expansion(D)) || !term_IsTerm(def_Predicate(D))) { misc_StartErrorReport(); misc_ErrorReport("\n In def_DeleteFormClauses: Illegal input."); misc_FinishErrorReport(); } #endif /* ToProve and Label are NULL */ term_Delete(def_Expansion(D)); term_Delete(def_Predicate(D)); list_Delete(def_ClauseNumberList(D)); list_Delete(def_ClauseLitsList(D)); list_PairFree(D->parentclauses); memory_Free(D, sizeof(DEF_NODE)); } static void def_DeleteFromTerm(DEF D) /********************************************************** INPUT: A definition derived from a term. EFFECT: The definition is deleted, INCLUDING THE TERMS. THE LABEL IS NOT FREED. ********************************************************/ { #ifdef CHECK if (!term_IsTerm(def_Expansion(D)) || !term_IsTerm(def_Predicate(D))) { misc_StartErrorReport(); misc_ErrorReport("\n In def_DeleteFromTerm: Illegal input."); misc_FinishErrorReport(); } #endif /* List of clausenumbers is NULL */ term_Delete(def_Expansion(D)); term_Delete(def_Predicate(D)); if (def_ToProve(D) != (TERM) NULL) term_Delete(def_ToProve(D)); list_PairFree(D->parentclauses); memory_Free(D, sizeof(DEF_NODE)); } void def_Delete(DEF D) /********************************************************** INPUT: A definition derived from a term. EFFECT: The definition is deleted. CAUTION: All elements of the definition except of the label are freed. ********************************************************/ { if (!list_Empty(def_ClauseNumberList(D))) def_DeleteFromClauses(D); else def_DeleteFromTerm(D); } int def_PredicateOccurrences(TERM Term, SYMBOL P) /**************************************************** INPUT: A term and a predicate symbol. RETURNS: The number of occurrences of the predicate symbol in Term **************************************************/ { /* Quantifiers */ if (fol_IsQuantifier(term_TopSymbol(Term))) return def_PredicateOccurrences(term_SecondArgument(Term), P); /* Junctors and NOT */ if (fol_IsJunctor(term_TopSymbol(Term)) || symbol_Equal(term_TopSymbol(Term),fol_Not())){ LIST scan; int count; count = 0; for (scan=term_ArgumentList(Term); !list_Empty(scan); scan=list_Cdr(scan)) { count += def_PredicateOccurrences((TERM) list_Car(scan), P); /* Only the cases count==1 and count>1 are important */ if (count > 1) return count; } return count; } if (symbol_Equal(term_TopSymbol(Term), P)) return 1; return 0; } LIST def_ExtractDefsFromTerm(TERM Term, const char* Label) /************************************************************** INPUT: A term and its label. RETURNS: A list of definitions found in the term. NOTE: The Term is not changed, the definitions contain copies. ***************************************************************/ { TERM andterm; BOOL found; int pol; LIST univars, termlist, defslist, scan; /* First check if there is a top level and() so that the Term may contain several definitions */ andterm = Term; found = FALSE; pol = 1; univars = list_Nil(); /* Traverse top down universal quantifiers */ while (!found) { if ((symbol_Equal(term_TopSymbol(andterm), fol_All()) && (pol == 1)) || (symbol_Equal(term_TopSymbol(andterm), fol_Exist()) && (pol == -1))) { univars = list_Nconc(univars, list_Copy(fol_QuantifierVariables(andterm))); andterm = term_SecondArgument(andterm); } else { if (symbol_Equal(term_TopSymbol(andterm), fol_Not())) { pol = -pol; andterm = term_FirstArgument(andterm); } else found = TRUE; } } termlist = list_Nil(); /* Check if conjunction was found */ if ((symbol_Equal(term_TopSymbol(andterm), fol_And()) && (pol == 1)) || (symbol_Equal(term_TopSymbol(andterm), fol_Or()) && (pol == -1))) { LIST l; /* Flatten nested and/or */ /* Make copy of relevant subterm */ andterm = cnf_Flatten(term_Copy(andterm), term_TopSymbol(andterm)); for (l=term_ArgumentList(andterm); !list_Empty(l); l=list_Cdr(l)) { TERM newterm; newterm = fol_CreateQuantifierAddFather(fol_All(), term_CopyTermList(univars), list_List(list_Car(l))); termlist = list_Cons(newterm, termlist); } /* Arguments are used in new terms */ list_Delete(term_ArgumentList(andterm)); term_Free(andterm); } else termlist = list_List(term_Copy(Term)); list_Delete(univars); /* Now we have a list of terms that may contain definitions */ defslist = list_Nil(); for (scan=termlist; !list_Empty(scan); scan=list_Cdr(scan)) { TERM cand; TERM foundpred, toprove; /* Candidate from list */ cand = (TERM) list_Car(scan); term_AddFatherLinks(cand); if (cnf_ContainsDefinition(cand, &foundpred)) { DEF def; #ifdef CHECK if (!fol_CheckFormula(cand)) { misc_StartErrorReport(); misc_ErrorReport("\n In def_ExtractDefsFromTerm: Illegal term cand"); misc_FinishErrorReport(); } #endif cand = cnf_DefConvert(cand, foundpred, &toprove); #ifdef CHECK if (!fol_CheckFormula(cand)) { misc_StartErrorReport(); misc_ErrorReport("\n In def_ExtractDefsFromTerm: Illegal term cand"); misc_FinishErrorReport(); } #endif def = def_CreateFromTerm(term_Copy(term_SecondArgument(term_Superterm(foundpred))), term_Copy(foundpred), toprove, Label); if (def_PredicateOccurrences(cand, term_TopSymbol(foundpred)) > 1) def_RemoveAttribute(def, PREDOCCURONCE); else def_AddAttribute(def, PREDOCCURONCE); if (symbol_Equal(term_TopSymbol(foundpred), fol_Equality())) def_AddAttribute(def, ISEQUALITY); else def_RemoveAttribute(def, ISEQUALITY); defslist = list_Cons(def, defslist); } term_Delete(cand); } list_Delete(termlist); return defslist; } void def_ExtractDefsFromClauselist(PROOFSEARCH Search, LIST Clauselist) /************************************************************** INPUT: A proofsearch object and a list of clauses RETURNS: Nothing. EFFECT: The definitions found in the clauselist object are stored in the proofsearch object. NOTE: The clause list is not changed. The old list of definitions in the proofsearch object is overwritten. ***************************************************************/ { LIST scan, defslist; FLAGSTORE FlagStore; PRECEDENCE Precedence; defslist = list_Nil(); FlagStore = prfs_Store(Search); Precedence = prfs_Precedence(Search); for (scan=Clauselist; !list_Empty(scan); scan=list_Cdr(scan)) { CLAUSE Clause; NAT literal_index; LIST pair; Clause = (CLAUSE) list_Car(scan); /* Check if clause contains a predicate that may be part of a definition */ if (clause_ContainsPotPredDef(Clause, FlagStore, Precedence, &literal_index, &pair)) { LIST l, compl, compllits; BOOL done; compl = compllits = list_Nil(); done = FALSE; /* Search for complement clauses */ for (l=Clauselist; !list_Empty(l) && !done; l=list_Cdr(l)) { intptr_t predindex; if (clause_IsPartOfDefinition((CLAUSE) list_Car(l), clause_GetLiteralTerm(Clause, literal_index), &predindex, pair)) { compl = list_Cons(list_Car(l), compl); compllits = list_Cons((POINTER)predindex, compllits); if (list_Empty(list_PairFirst(pair)) && list_Empty(list_PairSecond(pair))) done = TRUE; } } /* All complements found ? */ if (done) { LIST l2, clausenumbers, args; DEF def; NAT i; TERM defterm, predterm; BOOL con; clausenumbers = list_Nil(); con = clause_GetFlag(Clause, CONCLAUSE); for (l2=compl; !list_Empty(l2); l2=list_Cdr(l2)) { clausenumbers = list_Cons((POINTER) clause_Number((CLAUSE) list_Car(l2)), clausenumbers); if (clause_GetFlag((CLAUSE) list_Car(l2), CONCLAUSE)) con = TRUE; } clausenumbers = list_Cons((POINTER) clause_Number(Clause), clausenumbers); compllits = list_Cons((POINTER) literal_index, compllits); /* Build definition term */ predterm = term_Copy(clause_GetLiteralTerm(Clause, literal_index)); args = list_Nil(); for (i = 0; i < clause_Length(Clause); i++) if (i != literal_index) args = list_Cons(term_Copy(clause_GetLiteralTerm(Clause, i)), args); defterm = term_CreateAddFather(fol_Or(), args); /* The expansion is negative here, so it must be inverted */ defterm = term_Create(fol_Not(), list_List(defterm)); defterm = cnf_NegationNormalFormula(defterm); def = def_CreateFromClauses(defterm, predterm, clausenumbers, compllits, con); defslist = list_Cons(def, defslist); if (flag_GetFlagIntValue(FlagStore, flag_PAPPLYDEFS)) { fputs("\nNew definition found :", stdout); def_Print(def); } } else { list_Delete(compllits); list_Delete(list_PairSecond(pair)); list_Delete(list_PairFirst(pair)); } list_Delete(compl); list_PairFree(pair); } } if (flag_GetFlagIntValue(FlagStore, flag_PAPPLYDEFS)) { if (!list_Empty(defslist)) { fputs("\nFound definitions :\n", stdout); for (scan = defslist; !list_Empty(scan); scan = list_Cdr(scan)) { def_Print((DEF) list_Car(scan)); fputs("\n---\n", stdout); } } } for (scan=defslist; !list_Empty(scan); scan=list_Cdr(scan)) symbol_AddProperty(term_TopSymbol(def_Predicate((DEF) list_Car(scan))), ISDEF); prfs_SetDefinitions(Search, list_Nconc(prfs_Definitions(Search), defslist)); } TERM def_ApplyDefToTermOnce(DEF Def, TERM Term, FLAGSTORE FlagStore, PRECEDENCE Precedence, BOOL* Complete) /************************************************************** INPUT: A DEF structure, a term and a boolean that is set to TRUE if no occurrences of the defined predicate remain in the term. A flag store and a precedence. RETURNS: A term where all occurrences of the definitions predicate are expanded if possible. NOTE: The Term is not changed. ***************************************************************/ { TERM newtarget, oldtarget, targetpredicate, totoplevel, toprove; LIST targettermvars, varsfortoplevel; BOOL applicable; oldtarget = Term; *Complete = TRUE; while (TRUE) { newtarget = term_Copy(oldtarget); term_AddFatherLinks(newtarget); targettermvars = varsfortoplevel = list_Nil(); if (cnf_ContainsPredicate(newtarget, term_TopSymbol(def_Predicate(Def)), &targetpredicate, &totoplevel, &targettermvars, &varsfortoplevel)) { *Complete = FALSE; applicable = FALSE; /* Check if definition is not always applicable */ if (term_Equal(def_ToProve(Def), term_Null())) { applicable = TRUE; newtarget = cnf_ApplyDefinitionOnce(def_Predicate(Def), term_Copy(def_Expansion(Def)), newtarget, targetpredicate, FlagStore); if (oldtarget != Term) term_Delete(oldtarget); oldtarget = newtarget; list_Delete(targettermvars); list_Delete(varsfortoplevel); } else { toprove = term_Copy(def_ToProve(Def)); newtarget = cnf_DefTargetConvert(newtarget, totoplevel, toprove, term_ArgumentList(def_Predicate(Def)), term_ArgumentList(targetpredicate), targettermvars, varsfortoplevel, FlagStore, Precedence, &applicable); list_Delete(targettermvars); list_Delete(varsfortoplevel); if (applicable) { newtarget = cnf_ApplyDefinitionOnce(def_Predicate(Def), term_Copy(def_Expansion(Def)), newtarget, targetpredicate, FlagStore); if (oldtarget != Term) term_Delete(oldtarget); oldtarget = newtarget; } else { /* Predicate still exists but cannot be expanded */ term_Delete(newtarget); if (oldtarget == Term) return NULL; else { oldtarget = cnf_ObviousSimplifications(oldtarget); return oldtarget; } } } } else { *Complete = TRUE; /* Predicate does no longer exist */ term_Delete(newtarget); /* No expansion possible */ if (oldtarget == Term) return NULL; else { oldtarget = cnf_ObviousSimplifications(oldtarget); return oldtarget; } } } return NULL; /* Unreachable */ } TERM def_ApplyDefToTermExhaustive(PROOFSEARCH Search, TERM Term) /************************************************************** INPUT: A proofsearch object and a term. RETURNS: An expanded term. NOTE: All occurences of defined predicates are expanded in the term, until no further changes are possible. CAUTION: If cyclic definitions exist, this will crash. ***************************************************************/ { TERM oldterm, newterm; BOOL done, complete; FLAGSTORE FlagStore; PRECEDENCE Precedence; done = FALSE; oldterm = Term; FlagStore = prfs_Store(Search); Precedence = prfs_Precedence(Search); while (!done) { LIST l; done = TRUE; /* Apply all definitions to term until no more changes occur */ for (l=prfs_Definitions(Search); !list_Empty(l); l=list_Cdr(l)) { newterm = def_ApplyDefToTermOnce((DEF) list_Car(l), oldterm, FlagStore, Precedence, &complete); if (newterm != NULL) { if (oldterm != Term) term_Delete(oldterm); oldterm = newterm; done = FALSE; } } } if (oldterm == Term) return NULL; else return oldterm; } LIST def_ApplyDefToClauseOnce(DEF Def, CLAUSE Clause, FLAGSTORE FlagStore, PRECEDENCE Precedence) /************************************************************** INPUT: A DEF structure, a clause, a flag store and a precedence. RETURNS: A list of new clauses. NOTE: The clause is not changed. All occurences of the defined predicate are expanded in the clause and in the derived clauses. ***************************************************************/ { LIST result, l; result = list_List(Clause); for (l = result; !list_Empty(l); l = list_Cdr(l)) { if (clause_ContainsSymbol((CLAUSE) list_Car(l), term_TopSymbol(def_Predicate(Def)))) { result = list_Nconc(result, cnf_ApplyDefinitionToClause((CLAUSE) list_Car(l), def_Predicate(Def), def_Expansion(Def), FlagStore, Precedence)); /* Remove temporary clause */ if ((CLAUSE) list_Car(l) != Clause) clause_Delete((CLAUSE) list_Car(l)); list_Rplaca(l, NULL); } } result = list_PointerDeleteElement(result, NULL); /* Make sure the original clause is no longer in the list */ if (!list_Empty(result)) if (list_First(result) == Clause) result = list_Pop(result); for (l = result; !list_Empty(l); l=list_Cdr(l)) { CLAUSE c; c = (CLAUSE) list_Car(l); if (def_Conjecture(Def)) clause_SetFlag((CLAUSE) list_Car(l), CONCLAUSE); clause_SetFromDefApplication(c); clause_SetParentClauses(c, list_Cons((POINTER) clause_Number(Clause), list_Copy(def_ClauseNumberList(Def)))); /* Parent literal is not available, as the predicate may occur several times in the target clause */ clause_SetParentLiterals(c, list_Cons((POINTER) 0, list_Copy(def_ClauseLitsList(Def)))); } return result; } LIST def_ApplyDefToClauseExhaustive(PROOFSEARCH Search, CLAUSE Clause) /************************************************************** INPUT: A proofsearch object and a clause. RETURNS: A list of derived clauses. NOTE: All occurences of defined predicates are expanded in the clause. until no further changes are possible. CAUTION: If cyclic definitions exist, this will crash. ***************************************************************/ { LIST newclauses, scan, result; CLAUSE orig; FLAGSTORE FlagStore; PRECEDENCE Precedence; orig = clause_Copy(Clause); newclauses = list_List(orig); result = list_Nil(); FlagStore = prfs_Store(Search); Precedence = prfs_Precedence(Search); while (!list_Empty(newclauses)) { /* Check all clauses */ LIST l, nextlist; /* List of clauses derived from newclauses by expanding predicates */ nextlist = list_Nil(); for (l=newclauses; !list_Empty(l); l=list_Cdr(l)) { LIST clauses; CLAUSE c; c = (CLAUSE) list_Car(l); /* Apply all definitions to the clause */ /* List of clauses derived from one clause in newclauses by */ /* expanding all possible predicates */ clauses = list_Nil(); for (scan=prfs_Definitions(Search); !list_Empty(scan); scan=list_Cdr(scan)) clauses = list_Nconc(clauses, def_ApplyDefToClauseOnce((DEF) list_Car(scan), c, FlagStore, Precedence)); /* If expansions were made delete old clause */ if (!list_Empty(clauses)) { /* DOCPROOF ? */ if (c != Clause) { if (flag_GetFlagIntValue(FlagStore, flag_DOCPROOF)) { prfs_InsertDocProofClause(Search, c); } else clause_Delete(c); } nextlist = list_Nconc(nextlist, clauses); } else { /* No more expansions possible for this clause */ /* If it is not the original clause, add it to the result list */ if (c != Clause) result = list_Cons(c, result); } } list_Delete(newclauses); newclauses = nextlist; } return result; } void def_Print(DEF D) /************************************************************** INPUT: A DEF structure. RETURNS: None. EFFECT: Prints the definition to stdout. ***************************************************************/ { LIST scan, scan2; fputs("\n\nAtom: ", stdout); fol_PrettyPrint(def_Predicate(D)); fputs("\nExpansion: \n", stdout); fol_PrettyPrint(def_Expansion(D)); if (!list_Empty(def_ClauseNumberList(D))) { fputs("\nParent clauses: ", stdout); for (scan = def_ClauseNumberList(D), scan2 = def_ClauseLitsList(D); !list_Empty(scan); scan = list_Cdr(scan), scan2 = list_Cdr(scan2)) printf("%zu.%zu ", (NAT) list_Car(scan), (NAT) list_Car(scan2)); if (D->conjecture) fputs("\nDerived from conjecture clauses.", stdout); else fputs("\nNot derived from conjecture clauses.", stdout); } else { fputs("\nLabel: ", stdout); fputs(def_Label(D), stdout); puts("\nGuard:"); if (def_ToProve(D) != NULL) fol_PrettyPrint(def_ToProve(D)); else fputs("Nothing.", stdout); } fputs("\nAttributes: ", stdout); if (def_HasAttribute(D, ISEQUALITY) || def_HasAttribute(D, PREDOCCURONCE)) { if (def_HasAttribute(D, ISEQUALITY)) fputs(" Equality ", stdout); if (def_HasAttribute(D, PREDOCCURONCE)) fputs(" No Multiple Occurrences ", stdout); } else { fputs(" None ", stdout); } } LIST def_ApplyDefToClauselist(PROOFSEARCH Search, DEF Def, LIST Clauselist, BOOL Destructive) /************************************************************** INPUT: A proofsearch object, a DEF structure, a list of unshared clauses and a boolean saying whether the parent clause of an expansion should be deleted. RETURNS: None. EFFECT: For each occurrence of the defined predicate in a clause in the list, a new clause with expanded predicate is added to the list. ***************************************************************/ { LIST l, newclauses, allnew; FLAGSTORE FlagStore; PRECEDENCE Precedence; allnew = list_Nil(); FlagStore = prfs_Store(Search); Precedence = prfs_Precedence(Search); for (l = Clauselist; !list_Empty(l); l = list_Cdr(l)) { newclauses = def_ApplyDefToClauseOnce(Def, (CLAUSE) list_Car(l), FlagStore, Precedence); /* Expansions were possible, delete the original clause */ if (Destructive && !list_Empty(newclauses)) { if (flag_GetFlagIntValue(FlagStore, flag_DOCPROOF)) prfs_InsertDocProofClause(Search, (CLAUSE) list_Car(l)); else clause_Delete((CLAUSE) list_Car(l)); list_Rplaca(l, NULL); } allnew = list_Nconc(allnew, newclauses); } if (Destructive) Clauselist = list_PointerDeleteElement(Clauselist, NULL); if (flag_GetFlagIntValue(FlagStore, flag_PAPPLYDEFS)) { if (!list_Empty(allnew)) { fputs("\nNew clauses after applying definitions : \n", stdout); clause_ListPrint(allnew); } } Clauselist = list_Nconc(Clauselist, allnew); return Clauselist; } LIST def_ApplyDefToTermlist(DEF Def, LIST Termlist, FLAGSTORE FlagStore, PRECEDENCE Precedence, BOOL* Complete, BOOL Destructive) /************************************************************** INPUT: A DEF structure and a list of pairs (label, term), a flag store, a precedence and a pointer to a boolean. If Destructive is TRUE the father of an expanded term is deleted. RETURNS: The changed list of terms. EFFECT: For each occurrence of the defined predicate in a term in the list, a new term with expanded predicate is added to the list. If every occurrence of the predicate could be expanded, Complete is set to TRUE. ***************************************************************/ { LIST l, newterms; newterms = list_Nil(); *Complete = TRUE; for (l=Termlist; !list_Empty(l); l=list_Cdr(l)) { TERM newterm; TERM oldterm; BOOL complete; oldterm = list_PairSecond(list_Car(l)); newterm = def_ApplyDefToTermOnce(Def, oldterm, FlagStore, Precedence, &complete); if (!complete) *Complete = FALSE; /* destructive part of function */ if (newterm != NULL) { newterms = list_Cons(list_PairCreate(NULL, newterm),newterms); if (Destructive) { /* Delete oldterm from Termlist */ term_Delete(list_PairSecond(list_Car(l))); if (list_PairFirst(list_Car(l)) != NULL) string_StringFree(list_PairFirst(list_Car(l))); list_PairFree(list_Car(l)); list_Rplaca(l, NULL); } } } Termlist = list_PointerDeleteElement(Termlist, NULL); if (flag_GetFlagIntValue(FlagStore, flag_PAPPLYDEFS)) { if (!list_Empty(newterms)) { fputs("\n\nNew terms after applying definitions : \n", stdout); for (l=newterms; !list_Empty(l); l=list_Cdr(l)) { fputs("\n", stdout); fol_PrettyPrint(list_PairSecond(list_Car(l))); } } } Termlist = list_Nconc(Termlist, newterms); return Termlist; } void def_ExtractDefsFromTermlist(PROOFSEARCH Search, LIST Axioms, LIST Conj) /************************************************************** INPUT: A proofsearch object and 2 lists of pairs label/term. RETURNS: None. EFFECT: Add all found definitions to the proofsearch object. The old list of definitions in the proofsearch object is overwritten. ***************************************************************/ { LIST l, deflist; FLAGSTORE FlagStore; deflist = list_Nil(); FlagStore = prfs_Store(Search); for (l=Axioms; !list_Empty(l); l=list_Cdr(l)) { fol_NormalizeVars(list_PairSecond(list_Car(l))); /* Is needed for proper variable match ! */ deflist = list_Nconc(deflist, def_ExtractDefsFromTerm(list_PairSecond(list_Car(l)), list_PairFirst(list_Car(l)))); } for (l=Conj; !list_Empty(l); l=list_Cdr(l)) { fol_NormalizeVars(list_PairSecond(list_Car(l))); /* Is needed for proper variable match ! */ deflist = list_Nconc(deflist, def_ExtractDefsFromTerm(list_PairSecond(list_Car(l)), list_PairFirst(list_Car(l)))); } for (l=deflist; !list_Empty(l); l=list_Cdr(l)) symbol_AddProperty(term_TopSymbol(def_Predicate(list_Car(l))), ISDEF); prfs_SetDefinitions(Search, list_Nconc(prfs_Definitions(Search), deflist)); if (flag_GetFlagIntValue(FlagStore, flag_PAPPLYDEFS)) { if (!list_Empty(deflist)) { fputs("\nFound definitions :\n", stdout); for (l = prfs_Definitions(Search); !list_Empty(l); l = list_Cdr(l)) { def_Print(list_Car(l)); fputs("\n---\n", stdout); } } } } LIST def_FlattenWithOneDefinition(PROOFSEARCH Search, DEF Def) /************************************************************** INPUT: A proofsearch object and one definition. RETURNS: The list of new definitions. EFFECT: For every occurrence of the defined predicate among the other definitions an expansion is attempted. A new definition is only created if the result of the expansion is again a definition. The proofsearch object is not changed. ***************************************************************/ { LIST newdefinitions; FLAGSTORE FlagStore; PRECEDENCE Precedence; newdefinitions = list_Nil(); FlagStore = prfs_Store(Search); Precedence = prfs_Precedence(Search); if (def_ToProve(Def) == NULL) { LIST definitions, l; definitions = prfs_Definitions(Search); for (l = definitions; !list_Empty(l); l=list_Cdr(l)) { DEF d; d = (DEF) list_Car(l); if (d != Def) { /* Expansion possible */ if (term_ContainsSymbol(def_Expansion(d), term_TopSymbol(def_Predicate(Def)))) { /* Resulting term is still a definition */ if (!term_ContainsSymbol(def_Expansion(Def), term_TopSymbol(def_Predicate(d)))) { TERM newexpansion; BOOL complete; DEF newdef; newexpansion = def_ApplyDefToTermOnce(Def, def_Expansion(d), FlagStore, Precedence, &complete); newdef = def_CreateFromTerm(newexpansion, term_Copy(def_Predicate(d)), term_Copy(def_ToProve(d)), def_Label(d)); newdefinitions = list_Cons(newdef, newdefinitions); } } } } } return newdefinitions; } void def_FlattenWithOneDefinitionDestructive(PROOFSEARCH Search, DEF Def) /************************************************************** INPUT: A proofsearch object and one definition. RETURNS: None. EFFECT: If the definition is always applicable, every occurrence of the defined predicate among the other definitions is expanded in place. If the resulting term is no longer a definition, it is deleted from the proofsearch object. Def is deleted. CAUTION: This function changes the list entries in the list of definitions in the proofsearch object, so do not call it from a loop over all definitions. ***************************************************************/ { FLAGSTORE FlagStore; PRECEDENCE Precedence; FlagStore = prfs_Store(Search); Precedence = prfs_Precedence(Search); if (def_ToProve(Def) == NULL) { LIST definitions, l; definitions = prfs_Definitions(Search); for (l = definitions; !list_Empty(l); l = list_Cdr(l)) { DEF d; d = (DEF) list_Car(l); if (d != Def) { /* Expansion possible */ if (term_ContainsSymbol(def_Expansion(d), term_TopSymbol(def_Predicate(Def)))) { /* Resulting term is still a definition */ if (!term_ContainsSymbol(def_Expansion(Def), term_TopSymbol(def_Predicate(d)))) { TERM newexpansion; BOOL complete; newexpansion = def_ApplyDefToTermOnce(Def, def_Expansion(d), FlagStore, Precedence, &complete); term_Delete(def_Expansion(d)); def_RplacExp(d, newexpansion); } else { symbol_RemoveProperty(term_TopSymbol(def_Predicate(d)), ISDEF); def_Delete(d); list_Rplaca(l, NULL); } } } else { /* Remove given definition */ list_Rplaca(l, NULL); } } symbol_RemoveProperty(term_TopSymbol(def_Predicate(Def)), ISDEF); def_Delete(Def); definitions = list_PointerDeleteElement(definitions, NULL); prfs_SetDefinitions(Search, definitions); } } void def_FlattenWithOneDefinitionSemiDestructive(PROOFSEARCH Search, DEF Def) /************************************************************** INPUT: A proofsearch object and one definition. RETURNS: Nothing. EFFECT: If the definition can be applied to another definition in the search object, that definition is destructively changed. If the resulting term is no longer a definition, it is deleted to prevent cycles. The applied definition Def is NOT deleted. CAUTION: After calling this function some entries of the definitions list in the proofsearch object may be NULL. ***************************************************************/ { FLAGSTORE FlagStore; PRECEDENCE Precedence; FlagStore = prfs_Store(Search); Precedence = prfs_Precedence(Search); if (def_ToProve(Def) == NULL) { LIST definitions, l; definitions = prfs_Definitions(Search); for (l = definitions; !list_Empty(l); l=list_Cdr(l)) { DEF d; d = (DEF) list_Car(l); if (d != Def) { /* Expansion possible */ if (term_ContainsSymbol(def_Expansion(d), term_TopSymbol(def_Predicate(Def)))) { /* Resulting term is still a definition */ if (!term_ContainsSymbol(def_Expansion(Def), term_TopSymbol(def_Predicate(d)))) { TERM newexpansion; BOOL complete; newexpansion = def_ApplyDefToTermOnce(Def, def_Expansion(d), FlagStore, Precedence, &complete); term_Delete(def_Expansion(d)); def_RplacExp(d, newexpansion); } else { symbol_RemoveProperty(term_TopSymbol(def_Predicate(d)), ISDEF); def_Delete(d); list_Rplaca(l, NULL); } } } } } } void def_FlattenDefinitionsDestructive(PROOFSEARCH Search) /************************************************************** INPUT: A proofsearch object. RETURNS: None. EFFECT: For every definition that is always applicable try to expand the predicate in other definitions if possible. ***************************************************************/ { LIST l; for (l = prfs_Definitions(Search); !list_Empty(l); l=list_Cdr(l)) { DEF d; d = (DEF) list_Car(l); fol_PrettyPrintDFG(def_Predicate(d)); if (d != NULL) def_FlattenWithOneDefinitionSemiDestructive(Search, d); } prfs_SetDefinitions(Search, list_PointerDeleteElement(prfs_Definitions(Search), NULL)); } LIST def_GetTermsForProof(TERM Term, TERM SubTerm, int Polarity) /************************************************************** INPUT: Two formulas, and which must be subformula of ,an int which is the polarity of in its superterm and a list of variables . RETURN: A list of formulas that are used to prove the guard of Atom. COMMENT: Helpfunction of def_FindProofFor Guard. CAUTION: Father links must be set. Free variables may exist in terms of return list. Terms are copied. ***************************************************************/ { TERM SuperTerm, AddToList; SYMBOL Top; LIST Scan1, NewList; term_AddFatherLinks(Term); #ifdef CHECK if (!fol_CheckFormula(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In def_GetTermsForProof: Illegal input Term."); misc_FinishErrorReport(); } #endif if (Term == SubTerm) return list_Nil(); SuperTerm = term_Superterm(SubTerm); Top = term_TopSymbol(SuperTerm); NewList = list_Nil(); AddToList = term_Null(); if (symbol_Equal(Top, fol_Not())) return def_GetTermsForProof(Term, SuperTerm, -1*Polarity); if (symbol_Equal(Top, fol_Or()) && Polarity == 1) { /* Get and store AddToList */ for (Scan1 = term_ArgumentList(SuperTerm); !list_Empty(Scan1); Scan1 = list_Cdr(Scan1)) { if (!term_HasPointerSubterm(list_Car(Scan1), SubTerm)) NewList = list_Cons(term_Create(fol_Not(),list_List(term_Copy(list_Car(Scan1)))), NewList); /* NewList's elements have the form not(term) */ } if (list_Length(NewList) == 1) { AddToList = list_Car(NewList); list_Delete(NewList); } else { AddToList = term_Create(fol_And(), NewList); } return list_Cons(AddToList, def_GetTermsForProof(Term, SuperTerm, Polarity)); } if (symbol_Equal(Top, fol_And()) && Polarity == -1) { /* Get and store AddToList */ if (list_Length(term_ArgumentList(SuperTerm)) == 2) { if (!term_HasPointerSubterm(term_FirstArgument(SuperTerm), SubTerm)) { AddToList = term_Copy(term_FirstArgument(SuperTerm)); } else { AddToList = term_Copy(term_SecondArgument(SuperTerm)); } } else if (list_Length(term_ArgumentList(SuperTerm)) > 2) { for (Scan1 = term_ArgumentList(SuperTerm); !list_Empty(Scan1); Scan1 = list_Cdr(Scan1)) { if (!term_HasPointerSubterm(list_Car(Scan1), SubTerm)) NewList = list_Cons(term_Copy(list_Car(Scan1)), NewList); } AddToList = term_Create(fol_And(), NewList); } else { /* Only one argument */ AddToList = term_Copy(term_FirstArgument(SuperTerm)); } return list_Cons(AddToList, def_GetTermsForProof(Term, SuperTerm, Polarity)); } if (symbol_Equal(Top, fol_Implies())) { if (term_HasPointerSubterm(term_SecondArgument(SuperTerm), SubTerm) && Polarity == 1) { AddToList = term_Copy(term_FirstArgument(SuperTerm)); return list_Cons(AddToList, def_GetTermsForProof(Term, SuperTerm, Polarity)); } if (term_HasPointerSubterm(term_FirstArgument(SuperTerm), SubTerm) && Polarity == -1) { AddToList = term_Copy(term_SecondArgument(SuperTerm)); AddToList = term_Create(fol_Not(), list_List(AddToList)); return list_Cons(AddToList, def_GetTermsForProof(Term, SuperTerm, -1*Polarity)); } } if (symbol_Equal(Top, fol_Implied())) { /* symmetric to fol_Implies */ if (term_HasPointerSubterm(term_SecondArgument(SuperTerm), SubTerm) && Polarity == -1) { AddToList = term_Copy(term_FirstArgument(SuperTerm)); AddToList = term_Create(fol_Not(), list_List(AddToList)); return list_Cons(AddToList, def_GetTermsForProof(Term, SuperTerm, -1*Polarity)); } if (term_HasPointerSubterm(term_FirstArgument(SuperTerm), SubTerm) && Polarity == 1) { AddToList = term_Copy(term_SecondArgument(SuperTerm)); return list_Cons(AddToList, def_GetTermsForProof(Term, SuperTerm, Polarity)); } } if (fol_IsQuantifier(Top)) return def_GetTermsForProof(Term, SuperTerm, Polarity); /* In all other cases, SubTerm is the top level term in which Atom occurs disjunctively */ return list_Nil(); } BOOL def_FindProofForGuard(TERM Term, TERM Atom, TERM Guard, FLAGSTORE FlagStore, PRECEDENCE Precedence) /************************************************************************** INPUT: A formula Term, an atom Atom, a term Guard a flag store and a precedence. RETURNS: True iff a proof can be found for Guard in Term. ***************************************************************************/ { BOOL LocallyTrue; TERM ToProve, Conjecture; LIST ArgList, FreeVars; ArgList = list_Nil(); FreeVars = list_Nil(); ToProve = term_Null(); Conjecture = term_Copy(Term); #ifdef CHECK if (!fol_CheckFormula(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In def_FindProofForGuard: No correct formula term."); misc_FinishErrorReport(); } if (!term_HasPointerSubterm(Term, Atom)) { misc_StartErrorReport(); misc_ErrorReport("\n In def_FindProofForGuard: Illegal input."); misc_FinishErrorReport(); } #endif ArgList = def_GetTermsForProof(Term, Atom, 1); if (!list_Empty(ArgList)) { ToProve = term_Create(fol_And(), ArgList); FreeVars = list_Nconc(fol_FreeVariables(ToProve), fol_FreeVariables(Guard)); FreeVars = term_DeleteDuplicatesFromList(FreeVars); term_CopyTermsInList(FreeVars); ArgList = list_List(term_Copy(Guard)); ArgList = list_Cons(ToProve, ArgList); ToProve = term_Create(fol_Implies(), ArgList); ToProve = fol_CreateQuantifier(fol_All(), FreeVars, list_List(ToProve)); /* Now ToProve has the form */ /* puts("\n*ToProve: "); fol_PrettyPrintDFG(ToProve); */ #ifdef CHECK if (!fol_CheckFormula(ToProve)) { misc_StartErrorReport(); misc_ErrorReport("\n In def_FindProofForGuard: No correct formula ToProve."); misc_FinishErrorReport(); } #endif LocallyTrue = cnf_HaveProof(list_Nil(), ToProve, FlagStore, Precedence); term_Delete(ToProve); term_Delete(Conjecture); if (LocallyTrue) return TRUE; } else { /* empty list */ term_DeleteTermList(ArgList); term_Delete(Conjecture); } return FALSE; } LIST def_ApplyDefinitionToTermList(LIST Defs, LIST Terms, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************************** INPUT: A list of definitions and a list of pairs (Label.Formula), the maximal number of expansions, a flag store and a precedence. RETURNS: The possibly destructively changed list . EFFECT: In all formulas of Terms any definition of Defs is applied exactly once if possible. The terms are changed destructively if the expanded def_predicate is not an equality. **************************************************************************/ { TERM ActTerm; /* Actual term in Terms */ TERM DefPredicate; /* Actual definition predicate out of Defs */ TERM Expansion; /* Expansion term of the definition */ TERM Target; /* Target predicate to be replaced */ LIST TargetList, Scan1, Scan2, Scan3; BOOL Apply; int Applics; Apply = TRUE; TargetList = list_Nil(); Applics = flag_GetFlagIntValue(Flags, flag_APPLYDEFS); while (Apply && Applics != 0) { Apply = FALSE; for (Scan1=Defs; !list_Empty(Scan1) && Applics != 0; Scan1=list_Cdr(Scan1)) { DefPredicate = term_Copy(def_Predicate(list_Car(Scan1))); /* puts("\n----\nDefPred:"); fol_PrettyPrintDFG(DefPredicate);*/ for (Scan2=Terms; !list_Empty(Scan2) && Applics != 0; Scan2=list_Cdr(Scan2)) { ActTerm = list_PairSecond(list_Car(Scan2)); TargetList = term_FindAllAtoms(ActTerm, term_TopSymbol(DefPredicate)); term_AddFatherLinks(ActTerm); /* puts("\nActTerm:"); fol_PrettyPrintDFG(ActTerm);*/ for (Scan3=TargetList; !list_Empty(Scan3) && Applics != 0; Scan3=list_Cdr(Scan3)) { Target = list_Car(Scan3); cont_StartBinding(); /* puts("\nTarget:"); fol_PrettyPrintDFG(Target);*/ if (unify_Match(cont_LeftContext(), DefPredicate, Target)) { cont_BackTrack(); Expansion = term_Copy(def_Expansion(list_Car(Scan1))); fol_NormalizeVarsStartingAt(ActTerm, term_MaxVar(Expansion)); unify_Match(cont_LeftContext(), DefPredicate, Target); if (fol_ApplyContextToTerm(cont_LeftContext(), Expansion)) { /* Matcher applied on Expansion */ if (!def_HasGuard(list_Car(Scan1))) { Applics--; Apply = TRUE; /* puts("\n*no Guard!");*/ term_RplacTop(Target, term_TopSymbol(Expansion)); term_DeleteTermList(term_ArgumentList(Target)); term_RplacArgumentList(Target, term_ArgumentList(Expansion)); term_RplacArgumentList(Expansion, list_Nil()); term_AddFatherLinks(ActTerm); #ifdef CHECK if (!fol_CheckFormula(ActTerm)) { misc_StartErrorReport(); misc_ErrorReport("\n In def_ApplyDefinitionToTermList:"); misc_ErrorReport(" No correct formula ActTerm."); misc_FinishErrorReport(); } #endif if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { puts("\nApplied definition for"); fol_PrettyPrintDFG(def_Predicate(list_Car(Scan1))); puts("\nNew formula:"); fol_PrettyPrintDFG(ActTerm); } } else { /* check guard */ TERM Guard; Guard = term_Copy(def_ToProve(list_Car(Scan1))); if (fol_ApplyContextToTerm(cont_LeftContext(), Guard)) { cont_BackTrack(); if (def_FindProofForGuard(ActTerm, Target,Guard, Flags, Precedence)) { Applics--; Apply = TRUE; term_RplacTop(Target, term_TopSymbol(Expansion)); term_DeleteTermList(term_ArgumentList(Target)); term_RplacArgumentList(Target, term_ArgumentList(Expansion)); term_RplacArgumentList(Expansion, list_Nil()); term_AddFatherLinks(ActTerm); #ifdef CHECK if (!fol_CheckFormula(ActTerm)) { misc_StartErrorReport(); misc_ErrorReport("\n In def_ApplyDefinitionToTermList:"); misc_ErrorReport(" No correct formula ActTerm"); misc_FinishErrorReport(); } #endif if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { puts("\nApplied definition for"); fol_PrettyPrintDFG(def_Predicate(list_Car(Scan1))); puts("\nNew formula:"); fol_PrettyPrintDFG(ActTerm); } } } term_Delete(Guard); } } term_Delete(Expansion); } cont_BackTrack(); } list_Delete(TargetList); } term_Delete(DefPredicate); } } return Terms; } spass-3.9/defs.h000066400000000000000000000131511325017163600136150ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * Definitions * */ /* * * */ /* * $Module: DEFS * */ /* * * */ /* * Copyright (C) 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.3 $ * */ /* $State: Exp $ * */ /* $Date: 2011-05-22 12:16:59 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: defs.h,v $ */ #ifndef _DEFS_ #define _DEFS_ /**************************************************************/ /* Includes */ /**************************************************************/ #include "clause.h" #include "term.h" #include "list.h" #include "search.h" /**************************************************************/ /* Structures */ /**************************************************************/ typedef enum { PREDOCCURONCE = 1, /* whether predicate occurs only once */ ISEQUALITY = 2 /* whether predicate is equality */ } DEF_ATTRIBUTES; typedef struct DEF_HELP { TERM expansion; /* The definition of the predicate term*/ TERM predicate; /* The predicate which is defined*/ TERM toprove; LIST parentclauses; /* List of clause numbers plus list of literal indices */ const char *label; /* The label of the predicate term*/ BOOL conjecture; NAT attributes; /* The attributes of the predicate*/ } *DEF, DEF_NODE; /**************************************************************/ /* Inline functions */ /**************************************************************/ TERM def_Expansion(DEF D); void def_RplacExp(DEF D, TERM E); TERM def_Predicate(DEF D); void def_RplacPred(DEF D, TERM Pred); TERM def_ToProve(DEF D); void def_RplacToProve(DEF D, TERM ToProve); LIST def_ClauseNumberList(DEF D); void def_RplacClauseNumberList(DEF D, LIST L); LIST def_ClauseLitsList(DEF D); void def_RplacClauseLitsList(DEF D, LIST L); const char* def_Label(DEF D); void def_RplacLabel(DEF D, const char* L); BOOL def_Conjecture(DEF D); void def_SetConjecture(DEF D); void def_AddAttribute(DEF D, DEF_ATTRIBUTES Attribute); NAT def_HasAttribute(DEF D, DEF_ATTRIBUTES Attribute); void def_RemoveAttribute(DEF D, DEF_ATTRIBUTES Attribute); BOOL def_HasGuard(DEF D); /**************************************************************/ /* Functions */ /**************************************************************/ DEF def_CreateFromClauses(TERM, TERM, LIST, LIST, BOOL); DEF def_CreateFromTerm(TERM, TERM, TERM, const char*); LIST def_ExtractDefsFromTerm(TERM, const char*); void def_ExtractDefsFromTermlist(PROOFSEARCH, LIST, LIST); void def_ExtractDefsFromClauselist(PROOFSEARCH, LIST); TERM def_ApplyDefToTermOnce(DEF, TERM, FLAGSTORE, PRECEDENCE, BOOL*); TERM def_ApplyDefToTermExhaustive(PROOFSEARCH, TERM); LIST def_ApplyDefToTermlist(DEF, LIST, FLAGSTORE, PRECEDENCE, BOOL*, BOOL); LIST def_ApplyDefinitionToTermList(LIST, LIST, FLAGSTORE, PRECEDENCE); /* LIST def_GetTermsForProof(TERM, TERM, int); BOOL def_FindProofForGuard(TERM, TERM, TERM, FLAGSTORE); */ LIST def_ApplyDefToClauseOnce(DEF, CLAUSE, FLAGSTORE, PRECEDENCE); LIST def_ApplyDefToClauseExhaustive(PROOFSEARCH, CLAUSE); LIST def_ApplyDefToClauselist(PROOFSEARCH, DEF, LIST, BOOL); LIST def_FlattenWithOneDefinition(PROOFSEARCH, DEF); void def_FlattenWithOneDefinitionSemiDestructive(PROOFSEARCH, DEF); void def_FlattenWithOneDefinitionDestructive(PROOFSEARCH, DEF); void def_FlattenDefinitionsDestructive(PROOFSEARCH); void def_Delete(DEF); void def_Print(DEF); int def_PredicateOccurrences(TERM, SYMBOL); #endif spass-3.9/description.c000066400000000000000000000155651325017163600152250ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * PROBLEM DESCRIPTION * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /**************************************************************/ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /**************************************************************/ #include "description.h" /**************************************************************/ /* Functions */ /**************************************************************/ DFGDESCRIPTION desc_Create(void) /************************************************************** INPUT: Nothing. RETURNS: Newly allocated problem description instance. ***************************************************************/ { DFGDESCRIPTION problem; problem = (DFGDESCRIPTION)memory_Malloc(sizeof(DFGDESCRIPTION_NODE)); memset(problem,0,sizeof(DFGDESCRIPTION_NODE)); problem->status = DFG_UNKNOWNSTATE; return problem; } void desc_Delete(DFGDESCRIPTION Description) /************************************************************** INPUT: Problem description instance. RETURNS: Nothing. EFFECT: Frees memory used by the problem description. ***************************************************************/ { if (Description->name != NULL) string_StringFree(Description->name); if (Description->author != NULL) string_StringFree(Description->author); if (Description->version != NULL) string_StringFree(Description->version); if (Description->logic != NULL) string_StringFree(Description->logic); if (Description->description != NULL) string_StringFree(Description->description); if(Description->date != NULL) string_StringFree(Description->date); memory_Free(Description,sizeof(DFGDESCRIPTION_NODE)); } const char* desc_Name(DFGDESCRIPTION Description) /************************************************************** INPUT: Problem description instance. RETURNS: The problem's name from the description section. ***************************************************************/ { return Description->name; } const char* desc_Author(DFGDESCRIPTION Description) /************************************************************** INPUT: Problem description instance. RETURNS: The problem's author from the description section. ***************************************************************/ { return Description->author; } const char* desc_Version(DFGDESCRIPTION Description) /************************************************************** INPUT: Problem description instance. RETURNS: The problem's version from the description section. ***************************************************************/ { return Description->version; } const char* desc_Logic(DFGDESCRIPTION Description) /************************************************************** INPUT: Problem description instance. RETURNS: The problem's logic from the description section. ***************************************************************/ { return Description->logic; } DFG_STATE desc_Status(DFGDESCRIPTION Description) /************************************************************** INPUT: Problem description instance. RETURNS: The problem's status from the description section. ***************************************************************/ { return Description->status; } const char* desc_StatusString(DFGDESCRIPTION Description) /************************************************************** INPUT: Problem description instance. RETURNS: The string representation of the problem's status. ***************************************************************/ { const char* result = ""; switch (Description->status) { case DFG_SATISFIABLE: result = "satisfiable"; break; case DFG_UNSATISFIABLE: result = "unsatisfiable"; break; case DFG_UNKNOWNSTATE: result = "unknown"; break; default: misc_StartErrorReport(); misc_ErrorReport("\n In desc_StatusString: Invalid status.\n"); misc_FinishErrorReport(); } return result; } const char* desc_Description(DFGDESCRIPTION Description) /************************************************************** INPUT: Problem description instance. RETURNS: The problem's description from the description section. ***************************************************************/ { return Description->description; } const char* desc_Date(DFGDESCRIPTION Description) /************************************************************** INPUT: Problem description instance. RETURNS: The problem's date from the description section. ***************************************************************/ { return Description->date; } void desc_FPrintDescription(DFGDESCRIPTION Description, FILE* File) /************************************************************** INPUT: Problem description instance and a file stream. RETURNS: Nothing. EFFECT: The description section from the input file is printed to 'File'. You must call the parser first before calling this function. ***************************************************************/ { fputs("list_of_descriptions.\n name(", File); if (Description->name != NULL) fputs(Description->name, File); else fputs("{* *}", File); fputs(").\n author(", File); if (Description->author != NULL) fputs(Description->author, File); else fputs("{* *}", File); fputs(").\n", File); if (Description->version != NULL) { fputs(" version(", File); fputs(Description->version, File); fputs(").\n", File); } if (Description->logic != NULL) { fputs(" logic(", File); fputs(Description->logic, File); fputs(").\n", File); } fputs(" status(", File); fputs(desc_StatusString(Description), File); fputs(").\n description(", File); if (Description->description != NULL) fputs(Description->description, File); else fputs("{* *}", File); fputs(").\n", File); if (Description->date != NULL) { fputs(" date(", File); fputs(Description->date, File); fputs(").\n", File); } fputs("end_of_list.", File); } spass-3.9/description.h000066400000000000000000000051071325017163600152210ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * PROBLEM DESCRIPTION * */ /* * * */ /* ********************************************************** */ /**************************************************************/ #ifndef _DESC_ #define _DESC_ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /**************************************************************/ /* Includes */ /**************************************************************/ #include #include "memory.h" #include "strings.h" /**************************************************************/ /* Structures */ /**************************************************************/ typedef enum { DFG_SATISFIABLE, DFG_UNSATISFIABLE, DFG_UNKNOWNSTATE } DFG_STATE; /* Used for the texts from description section. */ typedef struct DFGDESCRIPTION_HELP { char* name; char* author; char* version; char* logic; DFG_STATE status; char* description; char* date; } DFGDESCRIPTION_NODE; typedef DFGDESCRIPTION_NODE* DFGDESCRIPTION; /**************************************************************/ /* Functions */ /**************************************************************/ DFGDESCRIPTION desc_Create(void); void desc_Delete(DFGDESCRIPTION); /* Functions for accessing description information */ const char* desc_Name(DFGDESCRIPTION); const char* desc_Author(DFGDESCRIPTION); const char* desc_Version(DFGDESCRIPTION); const char* desc_Logic(DFGDESCRIPTION); const char* desc_StatusString(DFGDESCRIPTION); DFG_STATE desc_Status(DFGDESCRIPTION); const char* desc_Description(DFGDESCRIPTION); const char* desc_Date(DFGDESCRIPTION); void desc_FPrintDescription(DFGDESCRIPTION, FILE*); #endif spass-3.9/dfg.h000066400000000000000000000100051325017163600134270ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * INTERFACE FOR THE DFG PARSER * */ /* * * */ /* * $Module: DFG * */ /* * * */ /* * Copyright (C) 1997, 1999, 2000, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.9 $ * */ /* $State: Exp $ * */ /* $Date: 2016-03-23 13:30:31 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: dfg.h,v $ */ #ifndef _DFG_ #define _DFG_ #include #include "list.h" #include "flags.h" #include "clause.h" #include "description.h" /* Parser functions */ void dfg_ParserInit(void); //TODO: add to top.c void dfg_InitGlobalArrays(void); void dfg_DeleteGlobalArrays(void); void dfg_CleanGloabalArrays(void); void dfg_InitExplicitParser(void); LIST dfg_DFGParserIncludesExplicit(FILE*, FLAGSTORE, PRECEDENCE, DFGDESCRIPTION, BOOL, LIST*, LIST*, LIST*, LIST*, LIST*, LIST*, LIST*, BOOL*); ARRAY dfg_DFGParserIncludesExplicitA(FILE*, FLAGSTORE, PRECEDENCE, DFGDESCRIPTION, BOOL, ARRAY*, ARRAY*, ARRAY*, LIST*, LIST*, LIST*, ARRAY*, BOOL*); LIST dfg_DFGParser(FILE*, char *, FLAGSTORE, PRECEDENCE, DFGDESCRIPTION, LIST*, LIST*, LIST*, LIST*, LIST*, LIST*, BOOL*); LIST dfg_ProofParser(FILE*, FLAGSTORE, PRECEDENCE, DFGDESCRIPTION); LIST dfg_TermParser(FILE*, FLAGSTORE, PRECEDENCE, DFGDESCRIPTION); /* Misc functions */ void dfg_DeleteFormulaPairList(LIST); void dfg_DeleteFormulaPairArray(ARRAY); void dfg_DeleteIncludePairList(LIST); void dfg_DeleteIncludePairArray(ARRAY); void dfg_StripLabelsFromList(LIST); void dfg_DeleteProofList(LIST); void dfg_DeleteClAxRelation(LIST); void dfg_FilterClausesBySelection(LIST*, LIST*, LIST); void dfg_FilterClausesBySelectionA(ARRAY*, LIST*, LIST); CLAUSE dfg_CreateClauseFromTerm(TERM, BOOL, FLAGSTORE, PRECEDENCE); void dfg_CreateClausesFromTerms(LIST*, LIST*, LIST*, BOOL, FLAGSTORE, PRECEDENCE); void dfg_CreateClausesFromTermsA(ARRAY*, ARRAY*, LIST*, LIST*, BOOL, FLAGSTORE, PRECEDENCE); FILE* dfg_OpenFile(const char *, char *, char ** const); #endif spass-3.9/dfg2ascii.c000066400000000000000000000160721325017163600145270ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * DFG2ASCII * */ /* * * */ /* * $Module: DFG2ASCII * */ /* * * */ /* * Copyright (C) 1999, 2000, 2001 MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.9 $ * */ /* $State: Exp $ * */ /* $Date: 2016-03-23 13:26:14 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: dfg2ascii.c,v $ */ /**************************************************************/ /* Includes */ /**************************************************************/ #include "dfg.h" #include "clause.h" #include "foldfg.h" #include "flags.h" #include "cmdline.h" #include "eml.h" #include "description.h" #include #define DFG2ASCII__VERSION "0.48" /**************************************************************/ /* Main Function */ /**************************************************************/ int main(int argc, const char* argv[]) { LIST Clauses,Axioms,Conjectures,Sorts,Scan, UserPrecedence,UserSelection,ClAxRelation; FILE *Input; CLAUSE Clause; const char *Filename; char * IncludePath; FLAGSTORE Flags; PRECEDENCE Precedence; BOOL HasPlainClauses; DFGDESCRIPTION Description; memory_Init(memory__UNLIMITED); atexit(memory_FreeAllMem); symbol_Init(TRUE); stack_Init(); term_Init(); flag_Init(flag_SPASS); cmdlne_Init(); Flags = flag_CreateStore(); flag_InitStoreByDefaults(Flags); Precedence = symbol_CreatePrecedence(); Description = desc_Create(); fol_Init(TRUE, Precedence); clause_Init(); dfg_ParserInit(); if (argc < 2 || !cmdlne_Read(argc, argv)) { fputs("\n\t dfg2ascii Version ", stdout); fputs(DFG2ASCII__VERSION, stdout); puts("\n\t Usage: dfg2ascii \n"); return EXIT_FAILURE; } if (!cmdlne_SetFlags(Flags)) return EXIT_FAILURE; Axioms = list_Nil(); Conjectures = list_Nil(); Sorts = list_Nil(); UserPrecedence = list_Nil(); UserSelection = list_Nil(); ClAxRelation = list_Nil(); IncludePath = flag_GetFlagStringValue(Flags,flag_IncludePath); Filename = cmdlne_GetInputFile(); Input = misc_OpenFile(Filename, "r"); Clauses = dfg_DFGParser(Input, IncludePath, Flags, Precedence, Description, &Axioms, &Conjectures, &Sorts, &UserPrecedence, &UserSelection, &ClAxRelation, &HasPlainClauses); misc_CloseFile(Input,Filename); Axioms = list_Nconc(Axioms, Sorts); if (!list_Empty(Axioms) || !list_Empty(Conjectures)) { puts("\n\n\t\t Axioms:\n"); if (list_Empty(Axioms)) puts("None.\n"); else for (Scan=Axioms; !list_Empty(Scan);Scan=list_Cdr(Scan)) { if (list_PairFirst(list_Car(Scan)) != NULL) printf("%s:\n",(char *)list_PairFirst(list_Car(Scan))); fol_PrettyPrintDFG(list_PairSecond(list_Car(Scan))); puts("\n"); } puts("\n\n\t\t Conjectures:\n"); if (list_Empty(Conjectures)) puts("None.\n"); else for (Scan=Conjectures; !list_Empty(Scan);Scan=list_Cdr(Scan)) { if (list_PairFirst(list_Car(Scan)) != NULL) printf("%s:\n",(char *)list_PairFirst(list_Car(Scan))); fol_PrettyPrintDFG(list_PairSecond(list_Car(Scan))); puts("\n"); } } else { BOOL SetExist; LIST ClauseScan; /* Before we sort the clauses, we need to make sure that they have been assigned a weight. */ for (ClauseScan = Clauses; !list_Empty(ClauseScan); ClauseScan = list_Cdr(ClauseScan)) { clause_UpdateWeight((CLAUSE) list_Car(ClauseScan), Flags); } Clauses = clause_ListSortWeighed(Clauses); clause_SetCounter(1); for (Scan = Clauses;!list_Empty(Scan);Scan=list_Cdr(Scan)) { Clause = (CLAUSE)list_Car(Scan); clause_SetSortConstraint(Clause, FALSE, Flags, Precedence); clause_NewNumber(Clause); clause_PrecomputeOrderingAndReInit(Clause, Flags, Precedence); } puts("\n\n\t\t Axiom Clauses:\n"); SetExist = FALSE; for (Scan = Clauses;!list_Empty(Scan);Scan=list_Cdr(Scan)) { Clause = (CLAUSE)list_Car(Scan); if (!clause_GetFlag(Clause,CONCLAUSE)) { SetExist = TRUE; clause_Print(Clause); putchar('\n'); } } if (SetExist) SetExist = FALSE; else puts("None.\n"); puts("\n\n\t\t Conjecture Clauses:\n"); for (Scan = Clauses;!list_Empty(Scan);Scan=list_Cdr(Scan)) { Clause = (CLAUSE)list_Car(Scan); if (clause_GetFlag(Clause,CONCLAUSE)) { SetExist = TRUE; clause_Print(Clause); putchar('\n'); } } if (SetExist) SetExist = FALSE; else puts("None.\n"); } clause_DeleteClauseList(Clauses); dfg_StripLabelsFromList(Axioms); dfg_StripLabelsFromList(Conjectures); term_DeleteTermList(Axioms); term_DeleteTermList(Conjectures); if(flag_GetFlagIntValue(Flags, flag_EML)){ eml_Free(); } flag_DeleteStore(Flags); symbol_DeletePrecedence(Precedence); list_Delete(UserPrecedence); list_Delete(UserSelection); dfg_DeleteClAxRelation(ClAxRelation); desc_Delete(Description); /*symbol_Dump();*/ cmdlne_Free(); fol_Free(); symbol_FreeAllSymbols(); #ifdef CHECK memory_Print(); #endif return 0; } spass-3.9/dfg2dfg.c000066400000000000000000000217171325017163600142010ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * GENERATING APPROXIMATIONS * */ /* * * */ /* * $Module: DFG2DFG * */ /* * * */ /* * Copyright (C) 2000, 2001 MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.9 $ * */ /* $State: Exp $ * */ /* $Date: 2016-03-23 13:28:00 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: dfg2dfg.c,v $ */ #include "dfg.h" #include "cmdline.h" #include "approx.h" #include "eml.h" #include "description.h" #define DFG2DFG__VERSION "1.6" static void dfg2dfg_ResetSelectedLiterals(LIST Clauses) /********************************************************** INPUT: A list of clauses. RETURNS: Nothing. ***********************************************************/ { LIST Scan; for (Scan = Clauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) { NAT i; CLAUSE Clause; Clause = (CLAUSE) list_Car(Scan); /* For each clause in the list, if the clause contains selected literals, remove the selected status of the literals. */ if (clause_GetFlag(Clause, CLAUSESELECT)) { for (i = clause_FirstAntecedentLitIndex(Clause); i <= clause_LastAntecedentLitIndex(Clause); i++) clause_LiteralClearFlag(clause_GetLiteral(Clause, i), LITSELECT); clause_RemoveFlag(Clause, CLAUSESELECT); } } } int main(int argc, const char* argv[]) { LIST Clauses, Axioms, Conjectures, SortDecls, UserPrecedence, UserSelection, ClAxRelation; const char *Filename; char * IncludePath; const char *Creator = "{* dfg2dfg Version " DFG2DFG__VERSION " *}"; FILE *File; int value; FLAGSTORE Flags; PRECEDENCE Precedence; BOOL HasPlainClauses; DFGDESCRIPTION Description; /* Initialization */ memory_Init(memory__UNLIMITED); atexit(memory_FreeAllMem); symbol_Init(TRUE); stack_Init(); term_Init(); flag_Init(flag_SPASS); flag_Init(flag_DFG2DFG); Flags = flag_CreateStore(); flag_InitStoreByDefaults(Flags); Precedence = symbol_CreatePrecedence(); Description = desc_Create(); fol_Init(TRUE, Precedence); clause_Init(); approx_Init(); cmdlne_Init(flag_SPASS); cmdlne_Init(flag_DFG2DFG); dfg_ParserInit(); if (!cmdlne_Read(argc, argv) || cmdlne_GetInputFile() == (char*)NULL) { /* print options */ fputs("\n\t dfg2dfg Version ", stdout); fputs(DFG2DFG__VERSION, stdout); fputs("\nUsage: dfg2dfg [-horn] [-linear] [-monadic[=n]]", stdout); puts(" [-shallow[=m]] input [output]\n"); puts("See the man page or the postscript documentation for more details."); return EXIT_FAILURE; } if (!cmdlne_SetFlags(Flags)) return EXIT_FAILURE; Filename = cmdlne_GetInputFile(); File = misc_OpenFile(Filename, "r"); /* Call the parser */ Axioms = list_Nil(); Conjectures = list_Nil(); SortDecls = list_Nil(); UserPrecedence = list_Nil(); UserSelection = list_Nil(); ClAxRelation = list_Nil(); IncludePath = flag_GetFlagStringValue(Flags,flag_IncludePath); Clauses = dfg_DFGParser(File,IncludePath,Flags,Precedence,Description,&Axioms,&Conjectures, &SortDecls, &UserPrecedence, &UserSelection, &ClAxRelation, &HasPlainClauses); misc_CloseFile(File, Filename); /* Formulae are ignored */ dfg_DeleteFormulaPairList(Axioms); dfg_DeleteFormulaPairList(Conjectures); dfg_DeleteFormulaPairList(SortDecls); if (list_Empty(Clauses)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n No clauses found in input file!\n"); misc_FinishUserErrorReport(); } /* Apply some approximations */ /* 1. the transformation to horn clauses */ if (flag_GetFlagIntValue(Flags, flag_DFG2DFGHORN) == flag_ON) { Conjectures = list_Nil(); for ( ; !list_Empty(Clauses); Clauses = list_Pop(Clauses)) { Axioms = approx_MakeHorn(list_Car(Clauses), Flags, Precedence); if (list_Empty(Axioms)) Conjectures = list_Nconc(Conjectures, list_List(list_Car(Clauses))); else { clause_Delete(list_Car(Clauses)); Conjectures = list_Nconc(Conjectures, Axioms); } } Clauses = Conjectures; } /* 2. the transformation to monadic literals */ if (flag_GetFlagIntValue(Flags, flag_DFG2DFGMONADIC) != flag_OFF) { if (flag_GetFlagIntValue(Flags, flag_DFG2DFGMONADIC) == flag_DFG2DFGMONADICPROJECT) { Conjectures = approx_MonadicByProjection(Clauses, Flags, Precedence); clause_DeleteClauseList(Clauses); Clauses = Conjectures; } else if (flag_GetFlagIntValue(Flags, flag_DFG2DFGMONADIC) == flag_DFG2DFGMONADICTERM) { Conjectures = approx_MonadicByTermEncoding(Clauses, Flags, Precedence); clause_DeleteClauseList(Clauses); Clauses = Conjectures; } else { misc_StartUserErrorReport(); misc_UserErrorReport("\nError: argument of option 'monadic' must be 0, 1 or 2\n"); misc_FinishUserErrorReport(); } } /* 3. the linear transformation */ if (flag_GetFlagIntValue(Flags, flag_DFG2DFGLINEAR) == flag_ON) { Conjectures = approx_MonadicMakeLinear(Clauses, Flags, Precedence); clause_DeleteClauseList(Clauses); Clauses = Conjectures; } /* 4. the shallow transformation */ if (flag_GetFlagIntValue(Flags, flag_DFG2DFGSHALLOW) != flag_OFF) { BOOL flag1, flag2; flag1 = flag2 = TRUE; value = flag_GetFlagIntValue(Flags, flag_DFG2DFGSHALLOW); if (value == 2) flag1 = FALSE; else if (value == 3) flag1 = flag2 = FALSE; else if (value != 0 && value != 1) { misc_StartUserErrorReport(); misc_UserErrorReport("Error: argument of option 'shallow' must be 0, 1, 2 or 3\n"); misc_FinishUserErrorReport(); } if (value != 0) { Conjectures = list_Nil(); for ( ; !list_Empty(Clauses); Clauses = list_Pop(Clauses)) { Axioms = approx_HornMonadicFlattenHeads(list_Car(Clauses), flag1, flag2, Flags, Precedence); if (list_Empty(Axioms)) Conjectures = list_Nconc(Conjectures, list_List(list_Car(Clauses))); else { clause_Delete(list_Car(Clauses)); Conjectures = list_Nconc(Conjectures, Axioms); } } Clauses = Conjectures; } } /* Print transformed clauses to stdout by default */ File = stdout; if (cmdlne_GetOutputFile()) { /* Name of output file is given */ File = misc_OpenFile(cmdlne_GetOutputFile(), "w"); } /* Do not print the selected status of the literals. */ dfg2dfg_ResetSelectedLiterals(Clauses); clause_FPrintCnfDFGProblem(File, FALSE, "{**}", Creator, "unknown", "{**}", Clauses, NULL, Flags, Precedence, NULL, FALSE, FALSE); if (cmdlne_GetOutputFile()) { /* Name of output file is given */ misc_CloseFile(File, cmdlne_GetOutputFile()); } clause_DeleteClauseList(Clauses); if(flag_GetFlagIntValue(Flags, flag_EML)){ eml_Free(); } flag_DeleteStore(Flags); symbol_DeletePrecedence(Precedence); list_Delete(UserPrecedence); list_Delete(UserSelection); dfg_DeleteClAxRelation(ClAxRelation); desc_Delete(Description); cmdlne_Free(); fol_Free(); symbol_FreeAllSymbols(); #ifdef CHECK memory_Print(); memory_PrintLeaks(); #endif putchar('\n'); return 0; } spass-3.9/dfg2dimacs.c000066400000000000000000000216361325017163600147010ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * CONVERTER FROM DFG SYNTAX TO DIMACS SYNTAX * */ /* * * */ /* * $Module: DFG2OTTER * */ /* * * */ /* * 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.5 $ * */ /* $State: Exp $ * */ /* $Date: 2016-03-23 13:28:31 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: dfg2dimacs.c,v $ */ /*** MAINLOOP *************************************************/ /**************************************************************/ /* Includes */ /**************************************************************/ #include "dfg.h" #include "foldfg.h" #include "clause.h" #include "cmdline.h" #include "eml.h" #include "description.h" #include void dimacs_PrintCnfDimacs(FILE* Output, LIST Clauses, FLAGSTORE Flags) { fprintf(Output,"p cnf %d %zu\n", symbol_ActIndex()-1, list_Length(Clauses)); while (list_Exist(Clauses)) { int i,n; CLAUSE Clause = (CLAUSE)list_Car(Clauses); n = clause_Length(Clause); for (i = clause_FirstLitIndex(); i < n; i++) { LITERAL Lit = clause_GetLiteral(Clause, i); if (clause_LiteralIsNegative(Lit)) fprintf(Output,"-"); fprintf(Output,"%d ",symbol_Index(clause_LiteralPredicate(Lit))); } fprintf(Output,"0\n"); Clauses = list_Cdr(Clauses); } } /**************************************************************/ /* Main Function */ /**************************************************************/ int main(int argc, const char* argv[]) { LIST Scan, Scan1, Clauses, AxiomList,ConjectureList, SortList, UserPrecedence,UserSelection,ClAxRelation; FILE *Output,*Input; const char *Filename; char * IncludePath; char ConLabel[] = "Conjecture"; FLAGSTORE Flags; PRECEDENCE Precedence; BOOL HasPlainClauses; DFGDESCRIPTION Description; memory_Init(memory__UNLIMITED); atexit(memory_FreeAllMem); symbol_Init(TRUE); stack_Init(); term_Init(); flag_Init(flag_SPASS); Flags = flag_CreateStore(); flag_InitStoreByDefaults(Flags); Precedence = symbol_CreatePrecedence(); Description = desc_Create(); fol_Init(TRUE, Precedence); clause_Init(); cmdlne_Init(); dfg_ParserInit(); if (!cmdlne_Read(argc, argv)) return EXIT_FAILURE; if (!cmdlne_SetFlags(Flags)) return EXIT_FAILURE; if (!flag_GetFlagIntValue(Flags, flag_STDIN) && (cmdlne_GetInputFile() == (char*)NULL || cmdlne_GetOutputFile() == (char*)NULL )) { fputs("\n\t dfg2dimacs ", stdout); puts("\n\t Usage: dfg2dimacs [options] \n"); return EXIT_FAILURE; } AxiomList = list_Nil(); ConjectureList = list_Nil(); SortList = list_Nil(); UserPrecedence = list_Nil(); UserSelection = list_Nil(); ClAxRelation = list_Nil(); IncludePath = flag_GetFlagStringValue(Flags,flag_IncludePath); if (!flag_GetFlagIntValue(Flags, flag_STDIN)) { Input = misc_OpenFile(cmdlne_GetInputFile(),"r"); Clauses = dfg_DFGParser(Input,IncludePath,Flags,Precedence,Description,&AxiomList,&ConjectureList, &SortList, &UserPrecedence, &UserSelection, &ClAxRelation, &HasPlainClauses); misc_CloseFile(Input,cmdlne_GetInputFile()); if (flag_GetFlagIntValue(Flags, flag_EML)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n The input file contains EML formulae. Please perfrom a translation to FOL by FLOTTER first!\n\n"); misc_FinishUserErrorReport(); } AxiomList = list_Nconc(AxiomList, SortList); if (!list_Empty(ConjectureList)) { /* Build conjecture formula and negate it: conjectures are taken disjunctively!!*/ for (Scan = ConjectureList; !list_Empty(Scan); Scan = list_Cdr(Scan)) list_Rplacd(list_Car(Scan), (LIST)term_Create(fol_Not(), list_List(list_PairSecond(list_Car(Scan))))); if (!list_Empty(list_Cdr(ConjectureList))) { for (Scan = ConjectureList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { Scan1 = list_Car(Scan); list_Rplaca(Scan, list_PairSecond(list_Car(Scan))); if (list_PairFirst(Scan1) != NULL) string_StringFree(list_PairFirst(Scan1)); /* Free the label */ list_PairFree(Scan1); /* Free the pair */ } ConjectureList = list_List(list_PairCreate(string_StringCopy(ConLabel), term_Create(fol_Or(), ConjectureList))); } } AxiomList = list_Nconc(ConjectureList, AxiomList); Filename = cmdlne_GetOutputFile(); Output = misc_OpenFile(Filename,"w"); if (list_Empty(AxiomList)) dimacs_PrintCnfDimacs(Output, Clauses, Flags); else { misc_StartErrorReport(); misc_ErrorReport("\n Only clause files are supported. \n"); misc_FinishErrorReport(); } dfg_DeleteFormulaPairList(AxiomList); misc_CloseFile(Output,Filename); } else { Clauses = dfg_DFGParser(stdin,IncludePath,Flags,Precedence,Description,&AxiomList,&ConjectureList, &SortList, &UserPrecedence, &UserSelection, &ClAxRelation, &HasPlainClauses); if (flag_GetFlagIntValue(Flags, flag_EML)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n The input file contains EML formulae. Please perfrom a translation to FOL by FLOTTER first!\n"); misc_FinishUserErrorReport(); } AxiomList = list_Nconc(AxiomList, SortList); if (!list_Empty(ConjectureList)) { /* Build conjecture formula and negate it: conjectures are taken disjunctively!!*/ for (Scan = ConjectureList; !list_Empty(Scan); Scan = list_Cdr(Scan)) list_Rplacd(list_Car(Scan), (LIST)term_Create(fol_Not(), list_List(list_PairSecond(list_Car(Scan))))); if (!list_Empty(list_Cdr(ConjectureList))) { for (Scan = ConjectureList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { Scan1 = list_Car(Scan); list_Rplaca(Scan, list_PairSecond(list_Car(Scan))); if (list_PairFirst(Scan1) != NULL) string_StringFree(list_PairFirst(Scan1)); /* Free the label */ list_PairFree(Scan1); /* Free the pair */ } ConjectureList = list_List(list_PairCreate(string_StringCopy(ConLabel), term_Create(fol_Or(), ConjectureList))); } } AxiomList = list_Nconc(ConjectureList, AxiomList); Output = stdout; if (list_Empty(AxiomList)) dimacs_PrintCnfDimacs(Output, Clauses, Flags); else { misc_StartErrorReport(); misc_ErrorReport("\n Only clause files are supported. \n"); misc_FinishErrorReport(); } dfg_DeleteFormulaPairList(AxiomList); } clause_DeleteClauseList(Clauses); /*symbol_Dump();*/ if(flag_GetFlagIntValue(Flags, flag_EML)){ eml_Free(); } flag_DeleteStore(Flags); symbol_DeletePrecedence(Precedence); list_Delete(UserPrecedence); list_Delete(UserSelection); dfg_DeleteClAxRelation(ClAxRelation); desc_Delete(Description); cmdlne_Free(); fol_Free(); symbol_FreeAllSymbols(); #ifdef CHECK memory_Print(); #endif return 0; } spass-3.9/dfg2otter.c000066400000000000000000000207461325017163600145770ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * CONVERTER FROM DFG SYNTAX TO OTTER SYNTAX * */ /* * * */ /* * $Module: DFG2OTTER * */ /* * * */ /* * 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.9 $ * */ /* $State: Exp $ * */ /* $Date: 2016-03-23 13:28:33 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: dfg2otter.c,v $ */ /*** MAINLOOP *************************************************/ /**************************************************************/ /* Includes */ /**************************************************************/ #include "dfg.h" #include "foldfg.h" #include "clause.h" #include "cmdline.h" #include "eml.h" #include "description.h" #include #define DFG2OTTER__VERSION "0.9" /**************************************************************/ /* Main Function */ /**************************************************************/ int main(int argc, const char* argv[]) { LIST Scan, Scan1, Clauses, AxiomList,ConjectureList, SortList, UserPrecedence,UserSelection,ClAxRelation; FILE *Output,*Input; const char *Filename; char * IncludePath; char ConLabel[] = "Conjecture"; FLAGSTORE Flags; PRECEDENCE Precedence; BOOL HasPlainClauses; DFGDESCRIPTION Description; memory_Init(memory__UNLIMITED); atexit(memory_FreeAllMem); symbol_Init(TRUE); stack_Init(); term_Init(); flag_Init(flag_SPASS); Flags = flag_CreateStore(); flag_InitStoreByDefaults(Flags); Precedence = symbol_CreatePrecedence(); Description = desc_Create(); fol_Init(TRUE, Precedence); clause_Init(); cmdlne_Init(); dfg_ParserInit(); if (!cmdlne_Read(argc, argv)) return EXIT_FAILURE; if (!cmdlne_SetFlags(Flags)) return EXIT_FAILURE; if (!flag_GetFlagIntValue(Flags, flag_STDIN) && (cmdlne_GetInputFile() == (char*)NULL || cmdlne_GetOutputFile() == (char*)NULL )) { fputs("\n\t dfg2otter Version ", stdout); fputs(DFG2OTTER__VERSION, stdout); puts("\n\t Usage: dfg2otter [options] \n"); return EXIT_FAILURE; } AxiomList = list_Nil(); ConjectureList = list_Nil(); SortList = list_Nil(); UserPrecedence = list_Nil(); UserSelection = list_Nil(); ClAxRelation = list_Nil(); IncludePath = flag_GetFlagStringValue(Flags,flag_IncludePath); if (!flag_GetFlagIntValue(Flags, flag_STDIN)) { Input = misc_OpenFile(cmdlne_GetInputFile(),"r"); Clauses = dfg_DFGParser(Input,IncludePath,Flags,Precedence,Description,&AxiomList,&ConjectureList, &SortList, &UserPrecedence, &UserSelection, &ClAxRelation, &HasPlainClauses); misc_CloseFile(Input,cmdlne_GetInputFile()); if (flag_GetFlagIntValue(Flags, flag_EML)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n The input file contains EML formulae. Please perfrom a translation to FOL by FLOTTER first!\n\n"); misc_FinishUserErrorReport(); } AxiomList = list_Nconc(AxiomList, SortList); if (!list_Empty(ConjectureList)) { /* Build conjecture formula and negate it: conjectures are taken disjunctively!!*/ for (Scan = ConjectureList; !list_Empty(Scan); Scan = list_Cdr(Scan)) list_Rplacd(list_Car(Scan), (LIST)term_Create(fol_Not(), list_List(list_PairSecond(list_Car(Scan))))); if (!list_Empty(list_Cdr(ConjectureList))) { for (Scan = ConjectureList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { Scan1 = list_Car(Scan); list_Rplaca(Scan, list_PairSecond(list_Car(Scan))); if (list_PairFirst(Scan1) != NULL) string_StringFree(list_PairFirst(Scan1)); /* Free the label */ list_PairFree(Scan1); /* Free the pair */ } ConjectureList = list_List(list_PairCreate(string_StringCopy(ConLabel), term_Create(fol_Or(), ConjectureList))); } } AxiomList = list_Nconc(ConjectureList, AxiomList); Filename = cmdlne_GetOutputFile(); Output = misc_OpenFile(Filename,"w"); fputs("\n% Generated by dfg2otter ", Output); fputs(DFG2OTTER__VERSION, Output); if (list_Empty(AxiomList)) clause_FPrintCnfOtter(Output, Clauses, Flags); else fol_FPrintOtter(Output, AxiomList, flag_GetFlagIntValue(Flags, flag_TDFG2OTTEROPTIONS)); dfg_DeleteFormulaPairList(AxiomList); misc_CloseFile(Output,Filename); } else { Clauses = dfg_DFGParser(stdin,IncludePath,Flags,Precedence,Description,&AxiomList,&ConjectureList, &SortList, &UserPrecedence, &UserSelection, &ClAxRelation, &HasPlainClauses); if (flag_GetFlagIntValue(Flags, flag_EML)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n The input file contains EML formulae. Please perfrom a translation to FOL by FLOTTER first!\n"); misc_FinishUserErrorReport(); } AxiomList = list_Nconc(AxiomList, SortList); if (!list_Empty(ConjectureList)) { /* Build conjecture formula and negate it: conjectures are taken disjunctively!!*/ for (Scan = ConjectureList; !list_Empty(Scan); Scan = list_Cdr(Scan)) list_Rplacd(list_Car(Scan), (LIST)term_Create(fol_Not(), list_List(list_PairSecond(list_Car(Scan))))); if (!list_Empty(list_Cdr(ConjectureList))) { for (Scan = ConjectureList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { Scan1 = list_Car(Scan); list_Rplaca(Scan, list_PairSecond(list_Car(Scan))); if (list_PairFirst(Scan1) != NULL) string_StringFree(list_PairFirst(Scan1)); /* Free the label */ list_PairFree(Scan1); /* Free the pair */ } ConjectureList = list_List(list_PairCreate(string_StringCopy(ConLabel), term_Create(fol_Or(), ConjectureList))); } } AxiomList = list_Nconc(ConjectureList, AxiomList); Output = stdout; fputs("\n% Generated by dfg2otter ", Output); fputs(DFG2OTTER__VERSION, Output); if (list_Empty(AxiomList)) clause_FPrintCnfOtter(Output, Clauses, Flags); else fol_FPrintOtter(Output, AxiomList, flag_GetFlagIntValue(Flags, flag_TDFG2OTTEROPTIONS)); dfg_DeleteFormulaPairList(AxiomList); } clause_DeleteClauseList(Clauses); /*symbol_Dump();*/ if(flag_GetFlagIntValue(Flags, flag_EML)){ eml_Free(); } flag_DeleteStore(Flags); symbol_DeletePrecedence(Precedence); list_Delete(UserPrecedence); list_Delete(UserSelection); dfg_DeleteClAxRelation(ClAxRelation); desc_Delete(Description); cmdlne_Free(); fol_Free(); symbol_FreeAllSymbols(); #ifdef CHECK memory_Print(); #endif return 0; } spass-3.9/dfg2tptp.c000066400000000000000000000355121325017163600144260ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * DFG2TPTP * */ /* * * */ /* * $Module: DFG2TPTP * */ /* * * */ /* * Copyright (C) 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.12 $ * */ /* $State: Exp $ * */ /* $Date: 2016-03-23 13:29:31 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: weidenb@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: dfg2tptp.c,v $ */ /**************************************************************/ /* Includes */ /**************************************************************/ #include "dfg.h" #include "clause.h" #include "foldfg.h" #include "eml.h" #include "cmdline.h" #include "description.h" #include #define DFG2TPTP__VERSION "0.52" static void TPTPOutput(FILE* File, TERM Term); static void TPTPSymbolOutput(FILE* File, SYMBOL Symbol) { if (symbol_Equal(Symbol,fol_All())) { fputs("\n!", File); return; } if (symbol_Equal(Symbol,fol_Exist())) { fputs("\n?", File); return; } if (symbol_Equal(Symbol,fol_Implies())) { fputs("=>\n", File); return; } if (symbol_Equal(Symbol,fol_Equiv())) { fputs("<=>\n", File); return; } if (symbol_Equal(Symbol,fol_Not())) { fputs("~", File); return; } if (symbol_Equal(Symbol,fol_And())) { fputs("&\n", File); return; } if (symbol_Equal(Symbol,fol_Or())) { fputs("|\n", File); return; } if (symbol_Equal(Symbol,fol_False())) { fputs("$false\n", File); return; } if (symbol_Equal(Symbol,fol_True())) { fputs("$true\n", File); return; } if (symbol_Equal(Symbol,fol_Equality())) { fputs(" = ", File); return; } if (symbol_Equal(Symbol,fol_Xor())) { fputs(" <~> ", File); return; } if (symbol_Equal(Symbol,fol_Nor())) { fputs(" ~| ", File); return; } if (symbol_Equal(Symbol,fol_Nand())) { fputs(" ~& ", File); return; } if (symbol_Equal(Symbol,fol_Implied())) { fputs(" <= ", File); return; } symbol_FPrintTPTP(File,Symbol); return; } static void TPTPListOutput(FILE* File, LIST List) /************************************************************** INPUT: A list of terms. RETURNS: Nothing. ***************************************************************/ { for (; !list_Empty(List); List=list_Cdr(List)) { TPTPOutput(File,list_Car(List)); if (!list_Empty(list_Cdr(List))) putc(',', File); } } static void TPTPOutput(FILE* File, TERM Term) /************************************************************** INPUT: A file and a term. RETURNS: Nothing. SUMMARY: Prints the term in prefix notation to the file. ***************************************************************/ { SYMBOL Top; Top = term_TopSymbol(Term); if (term_IsComplex(Term)) { if (fol_IsQuantifier(Top)) { TPTPSymbolOutput(File,Top); fputs(" [", File); TPTPListOutput(File,fol_QuantifierVariables(Term)); fputs("] : ", File); TPTPOutput(File, term_SecondArgument(Term)); } else if (symbol_Equal(Top,fol_And()) || symbol_Equal(Top,fol_Or()) || symbol_Equal(Top,fol_Implies()) || symbol_Equal(Top,fol_Equiv()) || symbol_Equal(Top,fol_Implied()) || symbol_Equal(Top,fol_Xor()) || symbol_Equal(Top,fol_Nand()) || symbol_Equal(Top,fol_Nor()) ) { LIST Scan; fputs("(", File); for (Scan = term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) { TPTPOutput(File,list_Car(Scan)); if (!list_Empty(list_Cdr(Scan))) { putc(' ', File); TPTPSymbolOutput(File,Top); putc(' ', File); } } putc(')', File); } else if( symbol_Equal(Top,fol_Equality())) { /*putc('(', File);*/ TPTPOutput(File, term_FirstArgument(Term)); TPTPSymbolOutput(File,Top); TPTPOutput(File, term_SecondArgument(Term)); /*putc(')', File);*/ } else { TPTPSymbolOutput(File,Top); putc('(', File); TPTPListOutput(File,term_ArgumentList(Term)); putc(')', File); } } else TPTPSymbolOutput(File,Top); } void TPTPCommentOutput(FILE *File, const char* String) /************************************************************** INPUT: A file and a comment string. RETURNS: none. SUMMARY: Prints the comment string to the file: if string contains a new line character it is automatically followed by a '%' and some space according to TPTP standards ***************************************************************/ { int i; for (i = 0; String[i] != '\0'; i++) if (String[i] == 10 && String[i+1] != '%') { putc(String[i], File); fputs("% ",File); } else putc(String[i], File); } static void TPTPFPrintInclude(FILE* File, char* filename, LIST selection) /************************************************************** INPUT: A file, name of file included, list of formule secelection. EFFECTS: Print a line in DFG format denoting the given inclusion. **************************************************************/ { int len; fputs("\tinclude('",File); len = strlen(filename); if ((len >= 4) && (filename[len-1] == 'g') && (filename[len-2] == 'f') && (filename[len-3] == 'd') && (filename[len-4] == '.') ) { /*changing *.dfg to *.p */ filename[len-3] = '\0'; fputs(filename,File); fputs("p",File); filename[len-3] = 'd'; } else { fputs(filename,File); } fputs("'",File); if (list_Exist(selection)) { fputs(",[",File); fputs((char*)list_Car(selection),File); selection = list_Cdr(selection); while(list_Exist(selection)) { fputs(",",File); fputs((char*)list_Car(selection),File); selection = list_Cdr(selection); } fputs("]",File); } fputs(").\n",File); } /**************************************************************/ /* Main Function */ /**************************************************************/ int main(int argc, const char* argv[]) { LIST Clauses,Axioms,Conjectures,Sorts,Scan, UserPrecedence,UserSelection,ClAxRelation,Includes; FILE *Output,*Input; char * IncludePath; int i; CLAUSE Clause; const char *Filename,*Outname; FLAGSTORE FlagStore; PRECEDENCE Precedence; BOOL HasPlainClauses; DFGDESCRIPTION Description; memory_Init(memory__UNLIMITED); symbol_Init(TRUE); stack_Init(); term_Init(); flag_Init(flag_SPASS); flag_Init(flag_DFG2TPTP); /* declare include flag */ FlagStore = flag_CreateStore(); flag_InitStoreByDefaults(FlagStore); Precedence = symbol_CreatePrecedence(); Description = desc_Create(); fol_Init(TRUE, Precedence); clause_Init(); cmdlne_Init(); dfg_ParserInit(); if (!cmdlne_Read(argc, argv) || cmdlne_GetInputFile() == (char*)NULL || cmdlne_GetOutputFile() == (char*)NULL) { fputs("\n\t dfg2tptp Version ", stdout); fputs(DFG2TPTP__VERSION, stdout); puts("\n\t Usage: dfg2tptp [-include] \n"); puts("-include makes the parser parse the files in include directive,"); puts("\tby default the directives are just translated."); return EXIT_FAILURE; } if (!cmdlne_SetFlags(FlagStore)) return EXIT_FAILURE; Axioms = list_Nil(); Conjectures = list_Nil(); Sorts = list_Nil(); UserPrecedence = list_Nil(); UserSelection = list_Nil(); ClAxRelation = list_Nil(); Includes = list_Nil(); Filename = cmdlne_GetInputFile(); Input = misc_OpenFile(Filename, "r"); IncludePath = flag_GetFlagStringValue(FlagStore,flag_IncludePath); if (flag_GetFlagIntValue(FlagStore, flag_INCLUDE) == flag_INCLUDEON) { Clauses = dfg_DFGParser(Input, IncludePath, FlagStore, Precedence, Description, &Axioms, &Conjectures, &Sorts, &UserPrecedence, &UserSelection, &ClAxRelation, &HasPlainClauses); } else { dfg_InitExplicitParser(); Clauses = dfg_DFGParserIncludesExplicit(Input, FlagStore, Precedence, Description, FALSE, &Axioms, &Conjectures, &Sorts, &UserPrecedence, &UserSelection, &ClAxRelation, &Includes, &HasPlainClauses); } misc_CloseFile(Input,Filename); if (flag_GetFlagIntValue(FlagStore, flag_EML)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n The input file contains EML formulae. Please perfrom a translation to FOL by FLOTTER first!\n\n"); misc_FinishUserErrorReport(); } Axioms = list_Nconc(Axioms, Sorts); dfg_StripLabelsFromList(Axioms); dfg_StripLabelsFromList(Conjectures); symbol_LowerSignature(); Outname = cmdlne_GetOutputFile(); Output = misc_OpenFile(Outname, "w"); if (!list_Empty(Axioms) || !list_Empty(Conjectures)) { const char * status; if (desc_Status(Description)== DFG_UNSATISFIABLE) if (list_Empty(Conjectures)) status = "Unsatisfiable"; else status = "Theorem"; else if (desc_Status(Description)== DFG_SATISFIABLE) if (list_Empty(Conjectures)) status = "Satisfiable"; else status = "CounterSatisfiable"; else status = "Unknown"; fprintf(Output,"%%--------------------------------------------------------------------------"); fprintf(Output,"\n%% File : No information"); fprintf(Output,"\n%% Domain : No information"); fprintf(Output,"\n%% Problem : %s",Filename); fprintf(Output,"\n%% Version : No information"); fprintf(Output,"\n%% English : No information"); fprintf(Output,"\n\n%% Refs : No information"); fprintf(Output,"\n%% Source : No information"); fprintf(Output,"\n%% Names : No information"); fprintf(Output,"\n\n%% Status : %s",status); fprintf(Output,"\n%% Rating : ?"); fprintf(Output,"\n%% Syntax : No information"); fprintf(Output,"\n\n%% Comments : File generated by dfg2tptp Version "); fprintf(Output, DFG2TPTP__VERSION); fprintf(Output,"\n%%--------------------------------------------------------------------------"); i=1; for (Scan = Axioms;!list_Empty(Scan);Scan=list_Cdr(Scan)) { fprintf(Output,"\nfof(ax%d,axiom,(\n\t",i++); TPTPOutput(Output,list_Car(Scan)); fputs(")).", Output); } i=1; for (Scan = Conjectures;!list_Empty(Scan);Scan=list_Cdr(Scan)) { fprintf(Output,"\nfof(co%d,conjecture,(\n\t",i++); TPTPOutput(Output,list_Car(Scan)); fputs(")).\n", Output); } fprintf(Output,"%%--------------------------------------------------------------------------\n"); } else { fprintf(Output,"%%--------------------------------------------------------------------------"); fprintf(Output,"\n%% File : No information"); fprintf(Output,"\n%% Domain : No information"); fprintf(Output,"\n%% Problem : %s",Filename); fprintf(Output,"\n%% Version : No information"); fprintf(Output,"\n%% English : No information"); fprintf(Output,"\n\n%% Refs : No information"); fprintf(Output,"\n%% Source : No information"); fprintf(Output,"\n%% Names : No information"); fprintf(Output,"\n\n%% Status : %s",( desc_Status(Description)== DFG_UNSATISFIABLE ? "Unsatisfiable" : ( desc_Status(Description)== DFG_SATISFIABLE ? "Satisfiable" : "Unknown"))); fprintf(Output,"\n%% Rating : ?"); fprintf(Output,"\n%% Syntax : No information"); fprintf(Output,"\n\n%% Comments : File generated by dfg2tptp Version "); fprintf(Output, DFG2TPTP__VERSION); fprintf(Output,"\n%%--------------------------------------------------------------------------"); for (Scan = Clauses;!list_Empty(Scan);Scan=list_Cdr(Scan)) { Clause = (CLAUSE)list_Car(Scan); fprintf(Output,"\ncnf(clause%zd,%s,\n\t",clause_Number(Clause), (clause_GetFlag(Clause,CONCLAUSE) ? "negated_conjecture" : "axiom")); putc('(', Output); for (i=clause_FirstLitIndex();i #include #include #include #include "misc.h" #include "dfg_diagnostic.h" void dfg_UserErrorReportF(pos_t const* const pos, char const* const fmt, ...) { FILE* const o = misc_USERERROROUT; if (pos) { if(pos->name){ fprintf(o,"\n In file %s ", pos->name); }else{ fprintf(o,"\n In the input "); } if (pos->line != 0) { fprintf(o, "at line %u,", pos->line); if (pos->col != 0) { fprintf(o, "column %u", pos->col); } } fputs(": ", o); } va_list ap; va_start(ap, fmt); vfprintf(o, fmt, ap); va_end(ap); fputc('\n', o); } void dfg_UserErrorReportHeader(pos_t const* const pos) { FILE* const o = misc_USERERROROUT; if (pos) { fprintf(o,"In file %s ", pos->name); if (pos->line != 0) { fprintf(o, "at line %u,", pos->line); if (pos->col != 0) { fprintf(o, "column %u", pos->col); } } fputs(": ", o); } } spass-3.9/dfg_diagnostic.h000066400000000000000000000054341325017163600156450ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * DFG PARSER DIAGNOSTICS * */ /* * * */ /* * $Module: DFG_DIAGNOSTIC_H * */ /* * * */ /* * 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.0 $ * */ /* $State: Exp $ * */ /* $Date: 2016/03/23 16:52:37 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ #ifndef DFG_DIAGNOSTIC_H #define DFG_DIAGNOSTIC_H #include #include "misc.h" #include "dfg_pos.h" /** * Print a formatted error message optionally with position information. * * The format is: * In at line , column : */ void dfg_UserErrorReportF(pos_t const* pos, char const* fmt, ...); /** * Print an error message header. * * The format is: * In at line , column : */ void dfg_UserErrorReportHeader(pos_t const* pos); #endif spass-3.9/dfg_pos.h000066400000000000000000000050501325017163600143140ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * DFG PARSER POSITION * */ /* * * */ /* * $Module: DFG_POS_H * */ /* * * */ /* * 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.0 $ * */ /* $State: Exp $ * */ /* $Date: 2016/03/23 16:54:37 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ #ifndef DFG_POS_H #define DFG_POS_H /** * Source position information. */ typedef struct pos_t { char const* name; /**< The name of the input. */ unsigned line; /**< The line number. */ unsigned col; /**< The column number. */ } pos_t; #endif spass-3.9/dfg_string_table.c000066400000000000000000000124741325017163600161730ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * DFG LEXER STRING TABLE * */ /* * * */ /* * $Module: DFG_STRING_TABLE_H * */ /* * * */ /* * 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.0 $ * */ /* $State: Exp $ * */ /* $Date: 2016/03/23 16:54:37 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ #include "dfg_string_table.h" #include "dfg_util.h" #define DEBUG_HASH 0 #define BLOCK_SIZE (1024 * 1024) /** * Internal state of the string table. */ static struct { string_t* table; /* The hash table of strings. */ size_t capacity; /* The capacity of the string hash table. Must be a power of 2. */ size_t size; /* The number of used slots of the string hash table. */ char* buf; size_t gap; } strings; /** * Calculate a hash value of the string s. * * @return The hash for the string s. */ static u4 string_hash(char const* const s) { #if 0 size_t hash = 0; for (char const* i = s; *i != '\0'; ++i) { # if 1 hash = (hash + (unsigned char)*i) * 17; # else hash = (hash ^ (unsigned char)*i) * 31; #endif } #else u4 hash = 2166136261U; for (char const* i = s; *i != '\0'; ++i) { #if 1 // FNV-1a hash = (hash ^ (unsigned char)*i) * 16777619U; #else // FNV-1 hash = hash * 16777619U ^ (unsigned char)*i; #endif } #endif return hash; } string_t const* string_table_insert(char const* const s, size_t const size, int const kind) { /* The string table uses quadratic probing to resolve collisions. */ /* Double the size of the hash table and rehash all entries of it is two * thirds full. */ if (strings.size * 3 >= strings.capacity * 2) { size_t const new_cap = strings.capacity * 2; string_t* const new_tab = MALLOCNZ(string_t, new_cap); #if DEBUG_HASH size_t max_coll = 0; size_t sum_coll = 0; size_t n_strings = 0; #endif for (string_t* i = strings.table, *const end = i + strings.capacity; i != end; ++i) { if (i->text) { for (u4 k = i->hash, step = 0;; k += ++step) { string_t* const entry = &new_tab[k & (new_cap - 1)]; if (!entry->text) { *entry = *i; #if DEBUG_HASH sum_coll += step; n_strings += 1; if (max_coll < step) max_coll = step; #endif break; } } } } #if DEBUG_HASH fprintf(stderr, "---> rehash #strings %7zu max %2zu avg %f\n", n_strings, max_coll, (double)sum_coll / n_strings); #endif free(strings.table); strings.capacity = new_cap; strings.table = new_tab; } u4 const hash = string_hash(s); for (u4 i = hash, step = 0;; i += ++step) { string_t* const entry = &strings.table[i & (strings.capacity - 1)]; if (!entry->text) { /* The string is not in the string table. * Enter it into the table and return the new entry. */ if (strings.gap < size) { strings.gap = size > BLOCK_SIZE ? size : BLOCK_SIZE; strings.buf = MALLOCN(char, strings.gap); } entry->text = memcpy(strings.buf, s, size); strings.buf += size; strings.gap -= size; entry->kind = kind; entry->hash = hash; ++strings.size; return entry; } else if (entry->hash == hash && streq(entry->text, s)) { /* The string is already in the string table. * Return the existing entry. */ return entry; } } } void string_table_init(void) { strings.size = 0; strings.capacity = 256; strings.table = MALLOCNZ(string_t, strings.capacity); strings.buf = 0; strings.gap = 0; } spass-3.9/dfg_string_table.h000066400000000000000000000062361325017163600161770ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * DFG LEXER STRING TABLE * */ /* * * */ /* * $Module: DFG_STRING_TABLE_H * */ /* * * */ /* * 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.0 $ * */ /* $State: Exp $ * */ /* $Date: 2016/03/23 16:54:37 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ #ifndef DFG_STRING_TABLE_H #define DFG_STRING_TABLE_H #include "dfg_token.h" #include "dfg_util.h" typedef struct string_t { char* text; /**< The text representation of the string. */ int kind; /**< The token kind associated with the string. */ u4 hash; } string_t; /** * Find or insert the string s in(to) the string table. * * If the string is in the table already, then return the existing entry. * In particular the given kind is discarded in this case. * This is used to identify keywords by adding them to the table beforehand. * * If the string is not in the table, enter it with the given kind. * The string s is copied and needs not be retained. * * @return The existing or new string. */ string_t const* string_table_insert(char const* s, size_t size, int kind); /** * Initialize the string table. */ void string_table_init(void); #endif spass-3.9/dfg_token.c000066400000000000000000000052061325017163600146310ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * DFG LEXER TOKEN * */ /* * * */ /* * $Module: DFG_TOKEN_H * */ /* * * */ /* * 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.0 $ * */ /* $State: Exp $ * */ /* $Date: 2016/03/23 16:55:37 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ #include #include "dfg_token.h" #include "dfg_util.h" char const* token_kind2str(token_kind_t const kind) { switch (kind) { #define KEYWORD(name) case T_##name: return "'" #name "'"; #define TOKEN(kind, text) case T_##kind: return "'" text "'"; #include "tokens.inc" #undef TOKEN #undef KEYWORD } PANIC("invalid token kind"); } spass-3.9/dfg_token.h000066400000000000000000000057551325017163600146470ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * DFG LEXER TOKEN * */ /* * * */ /* * $Module: DFG_TOKEN_H * */ /* * * */ /* * 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.0 $ * */ /* $State: Exp $ * */ /* $Date: 2016/03/23 16:55:37 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ #ifndef DFG_TOKEN_H #define DFG_TOKEN_H #include "dfg_pos.h" /** * Enumeration of token kinds. * * The enumeration is generated automatically from the tokens.inc. */ typedef enum token_kind_t { #define KEYWORD(name) T_##name, #define TOKEN(kind, text) T_##kind, #include "tokens.inc" #undef TOKEN #undef KEYWORD } token_kind_t; /** * Returns the string representation of the given token kind. */ char const* token_kind2str(token_kind_t); typedef struct token_t { token_kind_t kind; /**< The kind of the token. */ char const* text; /**< The text of the token. */ pos_t pos; /**< The source position of the token. */ } token_t; extern token_t token; /**< The current token. */ #endif spass-3.9/dfg_util.h000066400000000000000000000057531325017163600145020ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * DFG PARSER AND LEXER UTILITIES * */ /* * * */ /* * $Module: DFG_UTIL_H * */ /* * * */ /* * 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.0 $ * */ /* $State: Exp $ * */ /* $Date: 2016/03/23 16:56:37 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ #ifndef DFG_UTIL_H #define DFG_UTIL_H #include #include #include #include typedef unsigned u4; /** * Allocate n objects of the given type. */ #define MALLOCN(type, n) ((type*)malloc((n) * sizeof(type))) /** * Allocate n objects of the given type and zero them out. */ #define MALLOCNZ(type, n) ((type*)calloc((n), sizeof(type))) /** * Determine whether the strings a and b are equal. * * This is an easier to use wrapper around strcmp(). */ static inline bool streq(char const* const a, char const* const b) { return strcmp(a, b) == 0; } /** * Print the message and abort the program. */ #define PANIC(msg) (fputs((msg), stderr), abort()) #endif spass-3.9/dfglexer.c000066400000000000000000000235221325017163600144720ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * DFG LEXER * */ /* * * */ /* * $Module: DFG_LEXER_H * */ /* * * */ /* * 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.0 $ * */ /* $State: Exp $ * */ /* $Date: 2016/03/23 16:53:37 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ #include #include "dfg_diagnostic.h" #include "dfglexer.h" #include "dfg_string_table.h" #include "dfg_util.h" token_t token; /** * Internal state of the lexer. */ static struct { FILE* f; /**< The input stream. */ char* buf; char const* cur; char const* end; int c; /**< The current input character. */ pos_t pos; /**< The position in the input. */ char* text; /**< Text buffer for lexing words. */ size_t capacity; /**< Capacity of the text buffer. */ size_t size; /**< Size of the word in the text buffer. */ } input; /** * Append the char c to the text buffer. */ static inline void text_append(char const c) { /* Resize the text buffer, if it is full. */ if (input.size == input.capacity) { input.text = realloc(input.text, input.capacity *= 2); } input.text[input.size++] = c; } #define BUF_SIZE (4 * 1024) /** * Get the next character from the input. * * Includes the current column by one. */ static inline int input_get(void) { input.pos.col += 1; if (input.cur == input.end) { size_t const res = fread(input.buf, 1, BUF_SIZE, input.f); input.cur = input.buf; input.end = input.buf + res; if (res == 0) { if (ferror(input.f)) { misc_StartUserErrorReport(); dfg_UserErrorReportF(&input.pos, "Error in File"); misc_FinishUserErrorReport(); } return EOF; } } return *input.cur++; } void lexer_set_input(FILE* const f, char const* const name) { input.f = f; if (!input.buf) input.buf = MALLOCNZ(char, BUF_SIZE); input.pos.name = name; input.pos.line = 1; input.pos.col = 0; input.c = input_get(); } enum { CHAR_NONE = 0, CHAR_DIGIT = 1U << 0, CHAR_LETTER = 1U << 1, CHAR_SPECIAL = 1U << 2, CHAR_RESVAR = 1U << 3 }; static unsigned char char_class[256]; /** * Checks whether the character c is a digit. */ static inline bool is_digit(int const c) { return '0' <= c && c <= '9'; } /** * Checks whether the character c may start an identifier. */ static inline bool is_ident(int const c) { return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || c == '_'; } /** * Set the kind and text of the current token. */ static inline void set_token(token_kind_t const kind, char const* const text) { token.kind = kind; token.text = text; } void lexer_lextext(void) { char c; text_append('{'); text_append('*'); c = input.c; for (;;) { if (c == '*') { text_append(c); c = input_get(); if (c == '}') { text_append(c); input.c = input_get(); text_append('\0'); set_token(T_TEXT, input.text); input.size = 0; return; } else if (c == EOF) { goto unterminated_comment; } } else if (c == EOF) { unterminated_comment: misc_StartUserErrorReport(); dfg_UserErrorReportF(&token.pos, "unterminated text"); misc_FinishUserErrorReport(); break; } if(c == '\n'){ input.pos.line += 1; input.pos.col = 0; } text_append(c); c = input_get(); } } void lexer_next(void) { int c = input.c; for (;;) { token.pos = input.pos; switch (c) { char invalid; case EOF: set_token(T_EOF, "EOF"); return; case '\n': input.pos.line += 1; input.pos.col = 0; /* FALLTHROUGH */ case ' ': case '\f': case '\r': case '\t': case '\v': /* Skip whitespace. */ c = input_get(); continue; case '\'': for (;;) { c = input_get(); if (c == '\'') { input.c = input_get(); text_append('\0'); set_token(T_FILENAME, input.text); input.size = 0; return; } else if (c == T_EOF) { misc_StartUserErrorReport(); dfg_UserErrorReportF(&token.pos, "unterminated filename"); misc_FinishUserErrorReport(); break; } text_append(c); } continue; case '{': input.c = input_get(); if (input.c == '*') { set_token(T_LPARSTAR, "{*"); input.c = input_get(); } else { set_token(T_LCBRACE, "{"); } return; case '}': set_token(T_RCBRACE, "}"); input.c = input_get(); return; case '*': c = input_get(); if (c == '}') { set_token(T_RPARSTAR, "*}"); input.c = input_get(); return; } else { invalid = '*'; goto invalid_char; } case '%': do { c = input_get(); } while (c != '\n' && c != EOF); continue; case '-': c = input_get(); if (c == '>') { set_token(T_MINUS_GREATER, "->"); input.c = input_get(); } else if (is_digit(c)) { text_append('-'); goto number; } else { invalid = 'c'; goto invalid_char; } return; case '|': c = input_get(); if (c == '|') { set_token(T_PIPE_PIPE, "||"); input.c = input_get(); return; } else { invalid = 'c'; goto invalid_char; } case '(': set_token(T_LPAREN, "("); input.c = input_get(); return; case ')': set_token(T_RPAREN, ")"); input.c = input_get(); return; case ',': set_token(T_COMMA, ","); input.c = input_get(); return; case '.': set_token(T_PERIOD, "."); input.c = input_get(); return; case ':': set_token(T_COLON, ":"); input.c = input_get(); return; case '[': set_token(T_LBRACKET, "["); input.c = input_get(); return; case ']': set_token(T_RBRACKET, "]"); input.c = input_get(); return; default: { if (is_digit(c)) { /* Read a number. */ number: do { text_append(c); c = input_get(); } while (is_digit(c)); if (char_class[c] & (CHAR_LETTER | CHAR_SPECIAL) && input.text[0] != '-') goto ident; /* Append the terminating NUL character to the text buffer. */ text_append('\0'); set_token(T_NUMBER, input.text); } else if (char_class[c] & (CHAR_LETTER | CHAR_SPECIAL)) { /* Read an identifier or keyword or reserved variable. */ ident: text_append(c); c = input_get(); while (c != EOF && char_class[c] & (CHAR_DIGIT | CHAR_LETTER | CHAR_SPECIAL)){ text_append(c); c = input_get(); } /* Append the terminating NUL character to the text buffer. */ text_append('\0'); /* Find or insert the current string in(to) the string table. * If the string is not in the table yet, it is inserted as T_IDENTIFIER. * If it is contained already, the kind is not changed. * This is used to identify keywords by inserting them into the string table beforehand in lexer_init(). */ string_t const* const s = string_table_insert(input.text, input.size, T_IDENTIFIER); set_token(s->kind, s->text); } else { invalid = c; invalid_char: if (isprint(invalid)) { misc_StartUserErrorReport(); dfg_UserErrorReportF(&token.pos, "invalid char '%c' in input", (char)invalid); misc_FinishUserErrorReport(); } else { misc_StartUserErrorReport(); dfg_UserErrorReportF(&token.pos, "invalid char '\\x%02X' in input", (char)invalid); misc_FinishUserErrorReport(); } c = input_get(); continue; } input.c = c; /* Reset the text buffer. */ input.size = 0; return; } } } } void lexer_init(void) { /* Initialize the text buffer. */ input.capacity = 16; input.text = MALLOCNZ(char, input.capacity); for (size_t i = '0'; i <= '9'; ++i) { char_class[i] |= CHAR_DIGIT; } for (size_t i = 'A'; i <= 'Z'; ++i) { char_class[i] |= CHAR_LETTER; } for (size_t i = 'a'; i <= 'z'; ++i) { char_class[i] |= CHAR_LETTER; } for (size_t i = 'u'; i <= 'z'; ++i) { char_class[i] |= CHAR_RESVAR; } char_class['_'] |= CHAR_SPECIAL; /* Prime the string table with keywords. */ #define KEYWORD(name) string_table_insert(#name, sizeof(#name), T_##name); #define TOKEN(kind, text) #include "tokens.inc" #undef TOKEN #undef KEYWORD } spass-3.9/dfglexer.h000066400000000000000000000055641325017163600145050ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * DFG LEXER * */ /* * * */ /* * $Module: DFG_LEXER_H * */ /* * * */ /* * 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.0 $ * */ /* $State: Exp $ * */ /* $Date: 2016/03/23 16:53:37 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ #ifndef DFG_LEXER_H #define DFG_LEXER_H #include #include "dfg_token.h" /** * Initialize the lexer. */ void lexer_init(void); /** * Set the input stream and name used by the lexer. * * The name is used for source position information. */ void lexer_set_input(FILE* f, char const* name); /** * Read stream until "*}" is reached. * * The resulting T_TEXT token is stored in the global variable token. */ void lexer_lextext(void); /** * Read the next token from the input. * * The token is stored in the global variable token. */ void lexer_next(void); #endif spass-3.9/dfgparser.c000066400000000000000000004671051325017163600146600ustar00rootroot00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * PARSER FOR DFG SYNTAX * */ /* * * */ /* * $Module: DFG * */ /* * * */ /* * Copyright (C) 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 FreeBSD * */ /* * Licence. * */ /* * * */ /* * 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.15 $ * */ /* $State: Exp $ * */ /* $Date: 2016-03-23 16:54:37 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ #include "dfgparser.h" /* Used for delayed parsing of plain clauses */ typedef struct { LIST constraint; LIST antecedent; LIST succedent; TERM selected; } DFG_PLAINCLAUSEHELP, *DFG_PLAINCLAUSE; static DFGDESCRIPTION dfg_DESC; static ARRAY dfg_AXIOMARRAY; static ARRAY dfg_CONJECARRAY; static LIST dfg_SORTDECLLIST; static ARRAY dfg_INCLUDEARRAY; /* symbol precedence explicitly defined by user */ static LIST dfg_USERPRECEDENCE; static LIST dfg_USERSELECTION; static LIST dfg_CLAXRELATION; static LIST dfg_PLAINCLAXAX; static LIST dfg_PLAINCLAXCON; static LIST dfg_CLAXAXIOMS; static ARRAY dfg_AXCLAUSES; static ARRAY dfg_CONCLAUSES; static ARRAY dfg_PLAINAXCLAUSES; /* array of DFG_PLAINCLAUSE */ static ARRAY dfg_PLAINCONCLAUSES; /* array of DFG_PLAINCLAUSE */ static ARRAY dfg_DECLARATIONS; static ARRAY dfg_TERM_STACK; /* array used for parsing terms */ static ARRAY dfg_FORMULA_STACK;/* array used for parsing formulas*/ static LIST dfg_PROOFLIST; /* list_of_proofs */ static LIST dfg_TERMLIST; /* list_of_terms */ static TERM dfg_SELECTED_LITERAL; /* last selected literal */ static BOOL dfg_IGNORE; /* tokens are ignored while TRUE */ static BOOL dfg_IGNORESETTINGS; /* issue a warning for included file with SPASS settings */ static FLAGSTORE dfg_FLAGS; static PRECEDENCE dfg_PRECEDENCE; /* used in iascanner */ NAT dfg_LINENUMBER; /* used also in the scanner */ BOOL dfg_IGNORETEXT; char* dfg_CurrentFilename = NULL; static void dfg_SymbolDecl(int, char*, int); static SYMBOL dfg_Symbol(char*, intptr_t); static void dfg_TranslPairDecl(char*, char*); TERM dfg_TermCreate(char* Name, LIST Arguments) /*************************************************************** INPUT: A string and a list of terms . RETURNS: Does a symbol lookup for and creates out of the found or otherwise created new symbol and a new term. CAUTION: Deletes the string . ***************************************************************/ { SYMBOL s; NAT arity; arity = list_Length(Arguments); s = dfg_Symbol(Name, arity); /* Frees the string */ if (!symbol_IsVariable(s) && !symbol_IsFunction(s)) { misc_StartUserErrorReport(); dfg_UserErrorReportHeader(& token.pos); misc_UserErrorReport(" is not a function.\n"); misc_FinishUserErrorReport(); } return term_Create(s, Arguments); } TERM dfg_AtomCreate(char* Name, LIST Arguments) /* Look up the symbol, check its arity and create the atom term */ { SYMBOL s; s = dfg_Symbol(Name, list_Length(Arguments)); /* Frees the string */ if (symbol_IsVariable(s) || !symbol_IsPredicate(s)) { misc_StartUserErrorReport(); dfg_UserErrorReportHeader(& token.pos); misc_UserErrorReport(" Symbol is not a predicate.\n"); misc_FinishUserErrorReport(); } return term_Create(s, Arguments); } void dfg_DeleteStringList(LIST List) { list_DeleteWithElement(List, (void (*)(POINTER)) string_StringFree); } /**************************************************************/ /* Functions that handle symbols with unspecified arity */ /**************************************************************/ /* The symbol list holds all symbols whose arity wasn't */ /* specified in the symbol declaration section. */ /* If the arity of a symbol was not specified in this section */ /* it is first set to 0. If the symbol occurs with always the */ /* same arity 'A' the arity of this symbol is set to 'A'. */ static LIST dfg_SYMBOLLIST; static void dfg_SymAdd(SYMBOL); static void dfg_SymCheck(SYMBOL, NAT); static void dfg_SymCleanUp(void); /**************************************************************/ /* Functions that handle variable names */ /**************************************************************/ /* List of quantified variables in the current input formula. */ /* This list is used to find symbols that by mistake weren't */ /* declared in the symbol declaration section */ /* --> free variables */ /* This is a list of lists, since each time a quantifier is */ /* reached, a new list is added to the global list. */ typedef struct { char* name; SYMBOL symbol; } DFG_VARENTRY, *DFG_VAR; static HASHMAP dfg_VARSCOPE; static LIST dfg_VARLIST; static BOOL dfg_VARDECL; static void dfg_VarStart(void); static void dfg_VarStop(void); static void dfg_VarBacktrack(void); static void dfg_VarCheck(void); static SYMBOL dfg_VarLookup(char*,pos_t); static DFG_PLAINCLAUSE dfg_PlainClauseCreate(void); static void dfg_PlainClauseFree(DFG_PLAINCLAUSE Clause); static void dfg_Init(FILE* Input, FLAGSTORE Flags, PRECEDENCE Precedence, DFGDESCRIPTION Description) /************************************************************** INPUT: The input file stream for the parser, a flag store, a precedence and a problem description store. RETURNS: Nothing. EFFECT: The parser and scanner are initialized. The parser will use the flag store and the precedence to memorize the settings from the input file. ***************************************************************/ { dfg_SORTDECLLIST = list_Nil(); dfg_USERPRECEDENCE = list_Nil(); dfg_USERSELECTION = list_Nil(); dfg_CLAXRELATION = list_Nil(); dfg_PLAINCLAXAX = list_Nil(); dfg_PLAINCLAXCON = list_Nil(); dfg_CLAXAXIOMS = list_Nil(); dfg_PROOFLIST = list_Nil(); dfg_TERMLIST = list_Nil(); dfg_SYMBOLLIST = list_Nil(); dfg_VARLIST = list_Nil(); dfg_VARSCOPE = hm_Create(4,(HM_GET_HASH_FUNCTION)hm_StringHash, (HM_KEY_EQUAL_FUNCTION)string_Equal,FALSE); dfg_SELECTED_LITERAL = (TERM) NULL; dfg_VARDECL = FALSE; dfg_IGNORE = FALSE; dfg_FLAGS = Flags; dfg_PRECEDENCE = Precedence; dfg_DESC = Description; flag_SetFlagIntValue(dfg_FLAGS, flag_EML, flag_EMLOFF); } static void dfg_Free(FLAGSTORE Flags, PRECEDENCE Precedence, DFGDESCRIPTION Description) /************************************************************** INPUT: The a flag store, a precedence and a problem description store. RETURNS: Nothing. EFFECT: The parser and scanner are freed. ***************************************************************/ { hm_Delete(dfg_VARSCOPE); } void dfg_InitGlobalArrays(void) /************************************************************** INPUT: Nothing RETURNS: Nothing. EFFECT: The global arrays are initialized. ***************************************************************/ { dfg_AXIOMARRAY = array_Create(256,100); dfg_CONJECARRAY = array_Create(256,100); dfg_AXCLAUSES = array_Create(256,100); dfg_CONCLAUSES = array_Create(256,100); dfg_PLAINAXCLAUSES = array_Create(256,100); dfg_PLAINCONCLAUSES = array_Create(256,100); dfg_DECLARATIONS = array_Create(256,100); dfg_INCLUDEARRAY = array_Create(256,100); dfg_TERM_STACK = array_Create(16,100); dfg_FORMULA_STACK = array_Create(16,100); } void dfg_CleanGlobalArrays(void) /************************************************************** INPUT: Nothing RETURNS: Nothing. EFFECT: The global arrays are cleaned. ***************************************************************/ { dfg_AXIOMARRAY = array_Clean(dfg_AXIOMARRAY); dfg_CONJECARRAY = array_Clean(dfg_CONJECARRAY); dfg_AXCLAUSES = array_Clean(dfg_AXCLAUSES); dfg_CONCLAUSES = array_Clean(dfg_CONCLAUSES); dfg_PLAINAXCLAUSES = array_Clean(dfg_PLAINAXCLAUSES); dfg_PLAINCONCLAUSES = array_Clean(dfg_PLAINCONCLAUSES); dfg_DECLARATIONS = array_Clean(dfg_DECLARATIONS); dfg_INCLUDEARRAY = array_Clean(dfg_INCLUDEARRAY); } void dfg_DeleteGlobalArrays(void) /************************************************************** INPUT: Nothing RETURNS: Nothing. EFFECT: The global arrays are deleted. ***************************************************************/ { array_Delete(dfg_AXIOMARRAY); array_Delete(dfg_CONJECARRAY); array_Delete(dfg_AXCLAUSES); array_Delete(dfg_CONCLAUSES); array_Delete(dfg_PLAINAXCLAUSES); array_Delete(dfg_PLAINCONCLAUSES); array_Delete(dfg_DECLARATIONS); array_Delete(dfg_INCLUDEARRAY); array_Delete(dfg_TERM_STACK); array_Delete(dfg_FORMULA_STACK); } void dfg_DeleteClAxRelation(LIST ClAxRelation) { LIST Scan1, Scan2; for (Scan1=ClAxRelation;!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) { for (Scan2=list_Cdr(list_Car(Scan1));!list_Empty(Scan2);Scan2=list_Cdr(Scan2)) string_StringFree((char *)list_Car(Scan2)); list_Delete(list_Car(Scan1)); } list_Delete(ClAxRelation); } FILE* dfg_OpenFile(const char * FileName, char* IncludePath, char ** const DiscoveredName) /************************************************************** INPUT: A string filename, a string IncludePath, and a pointer to char pointer to hold the fullpath name of the file that was opened in the end (can be null). RETURNS: A opened file. EFFECT: Opens a file for reading. The file is searched for using the extended search mechanism. If the parameter IncludePath has non-trivial value, its value is used, otherwise we use the SPASSINPUT environment variable. ***************************************************************/ { if(dfg_CurrentFilename != NULL){ string_StringFree(dfg_CurrentFilename); dfg_CurrentFilename = NULL; } dfg_CurrentFilename = string_StringCopy(FileName); if (IncludePath != NULL && strlen(IncludePath)>0) return misc_OpenFileExt(FileName,"r",IncludePath,DiscoveredName); else return misc_OpenFileEnv(FileName,"r","SPASSINPUT",DiscoveredName); } static LIST dfg_TestList; /* list of strings used in nonmember tests */ static BOOL dfg_LabelFormulaPairIsNonmember(POINTER pair) { if (list_PairFirst(pair) == NULL) return TRUE; return !list_Member(dfg_TestList,list_PairFirst(pair),(BOOL (*)(POINTER, POINTER))string_Equal); } static void dfg_DeleteLabelTermPair(POINTER pair) { term_Delete(list_PairSecond(pair)); if (list_PairFirst(pair) != NULL) string_StringFree(list_PairFirst(pair)); /* Free the label */ list_PairFree(pair); } void dfg_FilterClausesBySelection(LIST* Clauses, LIST* ClAxRelation, LIST selection) /************************************************************** INPUT: A pointer to a clause list, a pointer to a ClAxRelation list and a char* list. RETURNS: Nothing. EFFECT: The clause list is filtered in such a way that clauses with names not in the selection list are deleted. The name for the clauses is found in the ClAxRelation structure. And the corresponding entry in ClAxRelation is also deleted if the clause is. The clause list and the ClAxRelation list are assumed to be coherent. NOTE: The coherence is assured when the lists come from an included file, because in includes settings sections are forbidden and so the user cannot specify ClAxRelation herself. ***************************************************************/ { /* result lists */ LIST RClauses; LIST RClAxRelation; /* pointers to last element in the result */ LIST RLClauses = list_Nil(); LIST RLClAxRelation = list_Nil(); RClauses = list_Nil(); RClAxRelation = list_Nil(); /* Performs parallel tranversal of Clauses and ClAxRelation. Either deleting from both or keeping both for the result. */ while (!list_Empty(*Clauses)) { CLAUSE Clause; LIST ClAx; LIST Labels; char* Label; /* current list elements */ LIST CClause; LIST CClAxRelation; CClause = *Clauses; CClAxRelation = *ClAxRelation; Clause = (CLAUSE) list_Car(CClause); #ifdef CHECK if (list_Empty(CClAxRelation)) { misc_StartUserErrorReport(); misc_ErrorReport("\n In dfg_FilterClausesBySelection: ClAxRelation too short!\n"); misc_FinishUserErrorReport(); } #endif ClAx = (LIST) list_Car(CClAxRelation); #ifdef CHECK if ((intptr_t)list_Car(ClAx) != clause_Number(Clause)) { misc_StartUserErrorReport(); misc_ErrorReport("\n In dfg_FilterClausesBySelection: Incompatible ClAxRelation!\n"); misc_FinishUserErrorReport(); } #endif Labels = list_Cdr(ClAx); if (list_Empty(Labels)) Label = NULL; else Label = (char*)list_Car(Labels); /*and we can already move on*/ *Clauses = list_Cdr(*Clauses); *ClAxRelation = list_Cdr(*ClAxRelation); if (!Label || !list_Member(selection,Label,(BOOL (*)(POINTER, POINTER))string_Equal)) { /* deleting */ if (RClauses) { /*if RClauses exists so does RLClauses and RLClAxRelation*/ list_Rplacd(RLClauses,*Clauses); list_Rplacd(RLClAxRelation,*ClAxRelation); } clause_Delete(Clause); list_DeleteWithElement(Labels,(void (*)(POINTER))string_StringFree); list_Free(ClAx); list_Free(CClause); list_Free(CClAxRelation); } else { /* keeping */ if (!RClauses) { /* the result will contain at least one element */ RClauses = CClause; RClAxRelation = CClAxRelation; } /* if we delete the next, whis will need to be updated */ RLClauses = CClause; RLClAxRelation = CClAxRelation; } } *Clauses = RClauses; *ClAxRelation = RClAxRelation; } void dfg_FilterClausesBySelectionA(ARRAY* Clauses, LIST* ClAxRelation, LIST selection) /************************************************************** INPUT: A pointer to a clause list, a pointer to a ClAxRelation list and a char* list. RETURNS: Nothing. EFFECT: The clause list is filtered in such a way that clauses with names not in the selection list are deleted. The name for the clauses is found in the ClAxRelation structure. And the corresponding entry in ClAxRelation is also deleted if the clause is. The clause list and the ClAxRelation list are assumed to be coherent. NOTE: The coherence is assured when the lists come from an included file, because in includes settings sections are forbidden and so the user cannot specify ClAxRelation herself. ***************************************************************/ { /* result lists */ LIST RClAxRelation; /* pointers to last element in the result */ LIST RLClAxRelation; int i, j; RClAxRelation = list_Nil(); RLClAxRelation = list_Nil(); /* Performs parallel tranversal of Clauses and ClAxRelation. Either deleting from both or keeping both for the result. */ j = 0; for(i = 0; i and are deleted. ***************************************************************/ { SYMBOL s1, s2; TERM varterm, t1, t2, term; s1 = dfg_Symbol(Name1, 1); /* Should be unary predicates */ s2 = dfg_Symbol(Name2, 1); if (!symbol_IsPredicate(s1)) { misc_StartUserErrorReport(); dfg_UserErrorReportF(&pos1,"Symbol is not a sort predicate."); misc_FinishUserErrorReport(); } if (!symbol_IsPredicate(s2)) { misc_StartUserErrorReport(); dfg_UserErrorReportF(&pos2,"Symbol is not a sort predicate."); misc_FinishUserErrorReport(); } varterm = term_Create(symbol_CreateStandardVariable(), list_Nil()); symbol_ResetStandardVarCounter(); t1 = term_Create(s1, list_List(varterm)); t2 = term_Create(s2, list_List(term_Copy(varterm))); term = term_Create(fol_Implies(), list_Cons(t1, list_List(t2))); term = fol_CreateQuantifier(fol_All(), list_List(term_Copy(varterm)), list_List(term)); dfg_DECLARATIONS = array_Add(dfg_DECLARATIONS, (intptr_t)list_PairCreate(NULL,term)); } LIST dfg_DFGParserIncludesExplicit(FILE* File, FLAGSTORE Flags, PRECEDENCE Precedence, DFGDESCRIPTION Description, BOOL AppendImplicitClAx, LIST* Axioms, LIST* Conjectures, LIST* SortDecl, LIST* UserDefinedPrecedence, LIST* UserDefinedSelection, LIST* ClAxRelation, LIST* Includes, BOOL* HasPlainClauses) /************************************************************** INPUT: The input file containing clauses or formulae in DFG syntax, a flag store, a precedence used to memorize settings from the file, and Description to store problem description. Boolean flag determinig whether the implicit ClAxRelation from Clauses should be appended to the explicit one coming from settings. Axioms, Conjectures, SortDecl, UserDefinedPrecedence UserDefinedSelection, and ClAxRelation, and Includes are pointers to lists used as return values. HasPlainClauses is a return value to indicate if the problem had clauses in the plain format. RETURNS: The list of clauses from File. EFFECT: Reads formulae and clauses from the input file. The axioms, conjectures, sort declarations, user-defined precedences, and includes are appended to the respective lists, the lists are not deleted! The Includes list contains pairs (filename, selection), where selection is a list of names of formulas chosen to include. All lists except the returned clause list contain pairs (label, term), where