blob: 51be4b6cb420f90658164fc2942b76f7722b8325 [file] [log] [blame]
/**************************************************************/
/* ********************************************************** */
/* * * */
/* * 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 GNU * */
/* * General Public License as published by the Free * */
/* * Software Foundation; either version 2 of the License, * */
/* * or (at your option) any later version. * */
/* * * */
/* * This program is distributed in the hope that it will * */
/* * be useful, but WITHOUT ANY WARRANTY; without even * */
/* * the implied warranty of MERCHANTABILITY or FITNESS * */
/* * FOR A PARTICULAR PURPOSE. See the GNU General Public * */
/* * License for more details. * */
/* * * */
/* * You should have received a copy of the GNU General * */
/* * Public License along with this program; if not, write * */
/* * to the Free Software Foundation, Inc., 59 Temple * */
/* * Place, Suite 330, Boston, MA 02111-1307 USA * */
/* * * */
/* * * */
/* $Revision$ * */
/* $State$ * */
/* $Date$ * */
/* $Author$ * */
/* * * */
/* * Contact: * */
/* * Christoph Weidenbach * */
/* * MPI fuer Informatik * */
/* * Stuhlsatzenhausweg 85 * */
/* * 66123 Saarbruecken * */
/* * Email: weidenb@mpi-sb.mpg.de * */
/* * Germany * */
/* * * */
/* ********************************************************** */
/**************************************************************/
/* $RCSfile$ */
#include "cnf.h"
#include "defs.h"
#include "foldfg.h"
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 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, &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)) {
int predindex;
if (clause_IsPartOfDefinition((CLAUSE) list_Car(l),
clause_GetLiteralTerm(Clause, 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) index, compllits);
/* Build definition term */
predterm = term_Copy(clause_GetLiteralTerm(Clause, index));
args = list_Nil();
for (i = 0; i < clause_Length(Clause); i++)
if (i != 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_GetFlagValue(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_GetFlagValue(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_GetFlagValue(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("%d.%d ", (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_GetFlagValue(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_GetFlagValue(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_GetFlagValue(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_GetFlagValue(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, <Term> and <SubTerm> which must be subformula
of <Term>,an int which is the polarity of <SubTerm> in its
superterm and a list of variables <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 <forall[]: A implies Guard> */
/* 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 <Defs> and a list of pairs (Label.Formula),
the maximal number <Applics> of expansions, a flag store and a
precedence.
RETURNS: The possibly destructively changed list <Terms>.
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_GetFlagValue(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_GetFlagValue(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_GetFlagValue(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;
}