static CLAUSE inf_CreateURUnitResolvent(CLAUSE Clause, int i, SUBST Subst, LIST FoundMap, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A non-unit clause, a literal index from the clause, a substitution, a list of pairs (l1, l2) of literals, where l1 is from the non-unit clause and l2 is from a unit clause, a flag store and a precedence. RETURNS: The resolvent of this UR resolution inference. The clause consists of the literal at index <i> in <Clause> after application of <Subst>. EFFECT: The flag store and the precedence are needed to create the new clause. ***************************************************************/ { CLAUSE Result, PClause; LITERAL Lit; TERM Atom; LIST Parents; NAT depth; /* Create atom for resolvent */ Atom = subst_Apply(Subst, term_Copy(clause_GetLiteralAtom(Clause, i))); /* Create clause */ Parents = list_List(Atom); if (i <= clause_LastConstraintLitIndex(Clause)) Result = clause_Create(Parents, list_Nil(), list_Nil(), Flags, Precedence); else if (i <= clause_LastAntecedentLitIndex(Clause)) Result = clause_Create(list_Nil(), Parents, list_Nil(), Flags, Precedence); else Result = clause_Create(list_Nil(), list_Nil(), Parents, Flags, Precedence); list_Delete(Parents); /* Get parent clauses and literals, calculate depth of resolvent */ Parents = list_List(Clause); depth = clause_Depth(Clause); for ( ; !list_Empty(FoundMap); FoundMap = list_Cdr(FoundMap)) { Lit = list_PairSecond(list_Car(FoundMap)); /* Literal from unit */ PClause = clause_LiteralOwningClause(Lit); Parents = list_Cons(PClause, Parents); depth = misc_Max(depth, clause_Depth(PClause)); clause_AddParentClause(Result, clause_Number(PClause)); clause_AddParentLiteral(Result, clause_LiteralGetIndex(Lit)); Lit = list_PairFirst(list_Car(FoundMap)); /* Is from <Clause> */ clause_AddParentClause(Result, clause_Number(Clause)); clause_AddParentLiteral(Result, clause_LiteralGetIndex(Lit)); } clause_SetFromURResolution(Result); clause_SetDepth(Result, depth+1); clause_SetSplitDataFromList(Result, Parents); list_Delete(Parents); return Result; }
static CLAUSE red_CreateTerminatorEmptyClause(LIST FoundMap, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A list of pairs (l1, l2), where l1 and l2 are unifiable literals with complementary sign and a flag store. More accurately, a substitution s exists, such that l1 s = l2 s for all pairs (l1,l2) in <FoundMap>. For all literals l from the involved clauses there exists one pair (l1,l2) in <FoundMap> with l1=l or l2=l. The flags store and the precedence are needed to create the new clause. RETURNS: A newly created empty clause, where the data (parents,...) is set according to <FoundMap>. ***************************************************************/ { CLAUSE Result, PClause; LITERAL Lit; LIST Parents; NAT depth; Result = clause_Create(list_Nil(), list_Nil(), list_Nil(), Flags, Precedence); Parents = list_Nil(); depth = 0; for (; !list_Empty(FoundMap); FoundMap = list_Cdr(FoundMap)) { Lit = list_PairSecond(list_Car(FoundMap)); PClause = clause_LiteralOwningClause(Lit); Parents = list_Cons(PClause, Parents); depth = misc_Max(depth, clause_Depth(PClause)); clause_AddParentClause(Result, clause_Number(PClause)); clause_AddParentLiteral(Result, clause_LiteralGetIndex(Lit)); Lit = list_PairFirst(list_Car(FoundMap)); PClause = clause_LiteralOwningClause(Lit); Parents = list_Cons(PClause, Parents); depth = misc_Max(depth, clause_Depth(PClause)); clause_AddParentClause(Result, clause_Number(PClause)); clause_AddParentLiteral(Result, clause_LiteralGetIndex(Lit)); } clause_SetFromTerminator(Result); clause_SetDepth(Result, depth+1); clause_SetSplitDataFromList(Result, Parents); list_Delete(Parents); return Result; }
static void tab_ToSeqProofOrdered(TABLEAU T, LIST* Proof) /************************************************************** INPUT: A tableau <T>, a list of clauses <Proof> representing a proof by reference RETURNS: The sequential proof corresponding to the tableau. ***************************************************************/ { LIST Scan; BOOL RightSplitRead, LeftSplitRead; if (tab_IsEmpty(T)) return; Scan = tab_Clauses(T); RightSplitRead = LeftSplitRead = FALSE; while (!list_Empty(Scan)) { /* insert left and right splits and descendants controlled by clause number */ if (!RightSplitRead && !tab_RightBranchIsEmpty(T) && clause_Number(list_Car(Scan)) < clause_Number(list_Car(tab_RightSplitClauses(T)))) { tab_ToSeqProofOrdered(tab_RightBranch(T), Proof); RightSplitRead = TRUE; } if (!LeftSplitRead && !tab_LeftBranchIsEmpty(T) && clause_Number(list_Car(Scan)) < clause_Number(tab_LeftSplitClause(T))) { tab_ToSeqProofOrdered(tab_LeftBranch(T), Proof); LeftSplitRead = TRUE; } (*Proof) = list_Cons(list_Car(Scan), *Proof); Scan = list_Cdr(Scan); } /* if a split clause with descendants has not been inserted yet, it been generated after all other clauses */ if (!RightSplitRead) tab_ToSeqProofOrdered(tab_RightBranch(T), Proof); if (!LeftSplitRead) tab_ToSeqProofOrdered(tab_LeftBranch(T), Proof); }
void tab_GetEarliestEmptyClauses(TABLEAU T, LIST* L) /************************************************************** INPUT : A tableau, a list of clauses by reference RETURNS: Nothing. EFFECTS: For each leaf node, adds empty clauses in leaf nodes to <L>. If the leaf node contains only one empty clause, it is added to <L> anyway. If the leaf node contains more than one empty clause, the earliest derived empty clause is added to <L>. ***************************************************************/ { CLAUSE FirstEmpty; LIST Scan; if (tab_IsEmpty(T)) return; if (tab_IsLeaf(T)) { FirstEmpty = clause_Null(); for (Scan = tab_Clauses(T); !list_Empty(Scan); Scan = list_Cdr(Scan)) { if (clause_IsEmptyClause(list_Car(Scan))) { if (FirstEmpty == clause_Null()) FirstEmpty = list_Car(Scan); else if (clause_Number(FirstEmpty) > clause_Number(list_Car(Scan))) FirstEmpty = list_Car(Scan); } } if (FirstEmpty != clause_Null()) (*L) = list_Cons(FirstEmpty, *L); } tab_GetEarliestEmptyClauses(tab_LeftBranch(T), L); tab_GetEarliestEmptyClauses(tab_RightBranch(T), L); }
void ana_AnalyzeProblem(PROOFSEARCH Search, LIST Clauses) /************************************************************** INPUT: A proofsearch object and a list of clauses. RETURNS: Void. EFFECT: Analyzes the clauses and sets the analyze variables. Recomputes the weight for the clauses. <Search> is modified according to clauses: non trivial domain number is set ***************************************************************/ { CLAUSE Clause; ana_EQUATIONS = FALSE; ana_PEQUATIONS = FALSE; /* Defaults for properties */ ana_NEQUATIONS = FALSE; ana_FUNCTIONS = FALSE; ana_FINDOMAIN = FALSE; ana_NONTRIVDOMAIN = FALSE; ana_MONADIC = FALSE; ana_NONMONADIC = FALSE; ana_PROP = FALSE; ana_GROUND = FALSE; ana_SORTRES = FALSE; ana_USORTRES = FALSE; ana_NONUNIT = FALSE; ana_CONGROUND = TRUE; ana_AXIOMCLAUSES = 0; ana_CONCLAUSES = 0; ana_NONHORNCLAUSES = 0; list_Delete(ana_FINITEMONADICPREDICATES); ana_FINITEMONADICPREDICATES = list_Nil(); if (list_Empty(Clauses)) return; ana_FINITEMONADICPREDICATES = clause_FiniteMonadicPredicates(Clauses); while (!list_Empty(Clauses)) { Clause = (CLAUSE)list_Car(Clauses); clause_UpdateWeight(Clause, prfs_Store(Search)); if (clause_GetFlag(Clause,CONCLAUSE)) ana_CONCLAUSES++; else ana_AXIOMCLAUSES++; if (clause_NumOfSuccLits(Clause) > 1) ana_NONHORNCLAUSES++; if (ana_CONGROUND && clause_GetFlag(Clause,CONCLAUSE) && clause_MaxVar(Clause) != symbol_GetInitialStandardVarCounter()) ana_CONGROUND = FALSE; if (!ana_PEQUATIONS && clause_ContainsPositiveEquations(Clause)) { ana_PEQUATIONS = TRUE; } if (!ana_NEQUATIONS && clause_ContainsNegativeEquations(Clause)) { ana_NEQUATIONS = TRUE; } if (!ana_MONADIC || !ana_NONMONADIC || !ana_PROP || !ana_GROUND) clause_ContainsFolAtom(Clause,&ana_PROP,&ana_GROUND,&ana_MONADIC,&ana_NONMONADIC); if (!ana_FUNCTIONS && clause_ContainsFunctions(Clause)) { ana_FUNCTIONS = TRUE; } if (!ana_FINDOMAIN && clause_ImpliesFiniteDomain(Clause)) { ana_FINDOMAIN = TRUE; } if (!ana_NONTRIVDOMAIN && clause_ImpliesNonTrivialDomain(Clause)) { prfs_SetNonTrivClauseNumber(Search, clause_Number(Clause)); ana_NONTRIVDOMAIN = TRUE; } if (!ana_NONUNIT && clause_Length(Clause) > 1) { ana_NONUNIT = TRUE; } if (!ana_SORTRES || !ana_USORTRES) clause_ContainsSortRestriction(Clause,&ana_SORTRES,&ana_USORTRES); Clauses = list_Cdr(Clauses); } ana_PUREEQUATIONAL = ((ana_PEQUATIONS || ana_NEQUATIONS) && !ana_MONADIC && !ana_NONMONADIC && !ana_PROP && !ana_GROUND); ana_EQUATIONS = (ana_PEQUATIONS || ana_NEQUATIONS); ana_PUREPROPOSITIONAL = (!ana_PEQUATIONS && !ana_NEQUATIONS &&!ana_MONADIC && !ana_NONMONADIC && ana_PROP); }
LIST split_Backtrack(PROOFSEARCH PS, CLAUSE EmptyClause, CLAUSE* SplitClause) /************************************************************** INPUT: A proofsearch object, an empty clause and a pointer to a clause used as return value. RETURNS: A list of clauses deleted in the backtracked split levels. <*SplitClause> is set to the split clause for the right branch of the splitting step, or NULL, if the tableau is finished. EFFECT: Backtracks the top of the split stack wrt the empty clause's level ***************************************************************/ { SPLIT ActBacktrackSplit; LIST RecoverList, Scan; int Backtracklevel; ActBacktrackSplit = (SPLIT)NULL; RecoverList = split_RemoveUnnecessarySplits(PS, EmptyClause); Backtracklevel = clause_SplitLevel(EmptyClause); *SplitClause = NULL; /* Backtrack all split levels bigger than the level of the empty clause */ while (!prfs_SplitStackEmpty(PS) && (prfs_ValidLevel(PS) > Backtracklevel)) { ActBacktrackSplit = prfs_SplitStackTop(PS); prfs_SplitStackPop(PS); if (prfs_SplitFatherClause(ActBacktrackSplit) != (CLAUSE)NULL) { RecoverList = list_Cons(prfs_SplitFatherClause(ActBacktrackSplit), RecoverList); prfs_SplitSetFatherClause(ActBacktrackSplit, NULL); } RecoverList = list_Nconc(prfs_SplitDeletedClauses(ActBacktrackSplit), RecoverList); clause_DeleteClauseList(prfs_SplitBlockedClauses(ActBacktrackSplit)); prfs_SplitFree(ActBacktrackSplit); prfs_DecValidLevel(PS); } /* Backtrack further for all right branches on top of the stack */ while (!prfs_SplitStackEmpty(PS) && list_Empty(prfs_SplitBlockedClauses(prfs_SplitStackTop(PS)))) { ActBacktrackSplit = prfs_SplitStackTop(PS); prfs_SplitStackPop(PS); if (prfs_SplitFatherClause(ActBacktrackSplit) != (CLAUSE)NULL) RecoverList = list_Cons(prfs_SplitFatherClause(ActBacktrackSplit), RecoverList); RecoverList = list_Nconc(prfs_SplitDeletedClauses(ActBacktrackSplit), RecoverList); prfs_SplitFree(ActBacktrackSplit); prfs_DecValidLevel(PS); } if (!prfs_SplitStackEmpty(PS)) { /* Enter the right branch of the splitting step */ int SplitMinus1; LIST RightClauses; SplitMinus1 = prfs_ValidLevel(PS) - 1; ActBacktrackSplit = prfs_SplitStackTop(PS); RecoverList = list_Nconc(prfs_SplitDeletedClauses(ActBacktrackSplit), RecoverList); prfs_SplitSetDeletedClauses(ActBacktrackSplit, list_Nil()); RecoverList = split_DeleteInvalidClausesFromList(PS, SplitMinus1, RecoverList); RightClauses = prfs_SplitBlockedClauses(ActBacktrackSplit); prfs_SplitSetBlockedClauses(ActBacktrackSplit, list_Nil()); for (Scan = RightClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) { if (clause_Number(list_Car(Scan)) == 0) { /* Found the right clause, the negation clauses have number -1. */ #ifdef CHECK if (*SplitClause != NULL) { misc_StartErrorReport(); misc_ErrorReport("\n In split_Backtrack:"); misc_ErrorReport(" Found two blocked clauses "); misc_ErrorReport("\n with clause number 0 (this marks the clause "); misc_ErrorReport("\n for the right branch of the tableau)."); misc_FinishErrorReport(); } #endif *SplitClause = list_Car(Scan); } clause_NewNumber((CLAUSE) list_Car(Scan)); clause_AddParentClause((CLAUSE) list_Car(Scan), clause_Number(EmptyClause)); clause_AddParentLiteral((CLAUSE) list_Car(Scan), 0); /* dummy literal */ } #ifdef CHECK if (*SplitClause == NULL) { misc_StartErrorReport(); misc_ErrorReport("\n In split_Backtrack: Didn´t find a blocked clause"); misc_ErrorReport("\n with clause number 0. (this marks the clause "); misc_ErrorReport("\n for the right branch of the tableau)."); misc_FinishErrorReport(); } #endif RecoverList = list_Nconc(RightClauses, RecoverList); /* Then, delete clauses from current level (Hack) */ prfs_DecValidLevel(PS); prfs_MoveInvalidClausesDocProof(PS); split_DeleteInvalidClausesFromStack(PS); prfs_IncValidLevel(PS); } else { /* Don't delete clauses from current level (split is top level) */ prfs_MoveInvalidClausesDocProof(PS); for (Scan = RecoverList; !list_Empty(Scan); Scan = list_Cdr(Scan)) prfs_InsertDocProofClause(PS, list_Car(Scan)); list_Delete(RecoverList); RecoverList = list_Nil(); } prfs_SetLastBacktrackLevel(PS, prfs_ValidLevel(PS)); return RecoverList; }
LIST dp_PrintProof(PROOFSEARCH Search, LIST Clauses, const char *FilePrefix) /********************************************************* INPUT: A proofsearch object, a list of empty clauses and the prefix of the output file name. RETURNS: The list of clauses required for the proof. MEMORY: The returned list must be freed. EFFECT: The proof is printed both to standard output and to the file <FilePrefix>.prf. **********************************************************/ { LIST ProofClauses,Scan,EmptyClauses,AllClauses, ReducedProof; LIST Missing, Incomplete, SplitClauses; FLAGSTORE Flags; Flags = prfs_Store(Search); Missing = pcheck_ConvertParentsInSPASSProof(Search, Clauses); if (!list_Empty(Missing)) { puts("\nNOTE: clauses with following numbers have not been found:"); for (; !list_Empty(Missing); Missing = list_Pop(Missing)) printf("%d ", (int)list_Car(Missing)); putchar('\n'); } EmptyClauses = list_Copy(Clauses); ProofClauses = list_Nil(); AllClauses = list_Nconc(list_Copy(prfs_DocProofClauses(Search)), list_Nconc(list_Copy(prfs_UsableClauses(Search)), list_Copy(prfs_WorkedOffClauses(Search)))); /* * collect proof clauses by noodling upward in the * proof tree, starting from <EmptyClauses>. * Before, add all splitting clauses to avoid gaps in split tree */ SplitClauses = list_Nil(); for (Scan = AllClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) if (clause_IsFromSplitting(list_Car(Scan))) SplitClauses = list_Cons(list_Car(Scan), SplitClauses); /* mark all needed clauses */ pcheck_ClauseListRemoveFlag(EmptyClauses, MARKED); pcheck_ClauseListRemoveFlag(AllClauses, MARKED); pcheck_MarkRecursive(EmptyClauses); pcheck_MarkRecursive(SplitClauses); /* collect all marked clauses */ ProofClauses = list_Nil(); for (Scan = AllClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) { if (clause_GetFlag(list_Car(Scan), MARKED)) ProofClauses = list_Cons(list_Car(Scan), ProofClauses); } /* build reduced proof */ ProofClauses = list_Nconc(ProofClauses, list_Copy(EmptyClauses)); ProofClauses = pcheck_ClauseNumberMergeSort(ProofClauses); ReducedProof = pcheck_ReduceSPASSProof(ProofClauses); dp_SetProofDepth(pcheck_SeqProofDepth(ReducedProof)); pcheck_ParentPointersToParentNumbers(AllClauses); pcheck_ParentPointersToParentNumbers(Clauses); /* check reduced proof for clauses whose parents have been marked as incomplete (HIDDEN flag) by ConvertParentsInSPASSProof */ Incomplete = list_Nil(); for (Scan = ReducedProof; !list_Empty(Scan); Scan = list_Cdr(Scan)) { if (clause_GetFlag(list_Car(Scan), HIDDEN)) Incomplete = list_Cons(list_Car(Scan), Incomplete); } if (!list_Empty(Incomplete)) { puts("NOTE: Following clauses in reduced proof have incomplete parent sets:"); for (Scan = Incomplete; !list_Empty(Scan); Scan = list_Cdr(Scan)) printf("%d ", clause_Number(list_Car(Scan))); putchar('\n'); } printf("\n\nHere is a proof with depth %d, length %d :\n", dp_ProofDepth(), list_Length(ReducedProof)); clause_ListPrint(ReducedProof); if (flag_GetFlagValue(Flags, flag_FPDFGPROOF)) dp_FPrintDFGProof(ReducedProof, FilePrefix, Flags, prfs_Precedence(Search)); fflush(stdout); list_Delete(EmptyClauses); list_Delete(AllClauses); list_Delete(ProofClauses); list_Delete(SplitClauses); list_Delete(Incomplete); return ReducedProof; }