blob: 3de67aa457e34f96650cf1c6f6e53de69e21a299 [file] [log] [blame]
/**************************************************************/
/* ********************************************************** */
/* * * */
/* * 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 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 "rules-inf.h"
#include "rules-red.h"
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, HASH, int);
static 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_GetFlagValue(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_GetFlagValue(Flags, flag_CNFSTRSKOLEM)) {
memory_Free(cnf_VARIABLEDEPTHARRAY, sizeof(int) * (symbol__NOOFSTANDARDVAR + 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;
int polterm1,bottom;
bottom = vec_ActMax();
vec_Push((POINTER) 1);
vec_Push(term);
do {
term1 = (TERM)vec_PopResult();
polterm1 = (int)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;
int 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;
}
}
/* <defpath> 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;
int p;
/* Pair Term t / Polarity p */
pair = (LIST) list_Car(l);
t = (TERM) list_PairFirst(pair);
p = (int) 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;
}
static 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_GetFlagValue(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)))
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));
}
LIST cnf_ComputeLiteralLists(TERM Term)
/**********************************************************
INPUT: A term in negation normal form without quantifiers.
RETURNS: The list of all literal lists corresponding to the
CNF of Term.
***********************************************************/
{
LIST Scan, Scan1, Scan2, Help, Result, List1, List2, NewResult;
SYMBOL Symbol;
Symbol = term_TopSymbol(Term);
Result = list_Nil();
if (symbol_Equal(Symbol,fol_Or())) {
Result = cnf_ComputeLiteralLists(list_Car(term_ArgumentList(Term)));
for (Scan=list_Cdr(term_ArgumentList(Term));!list_Empty(Scan);Scan=list_Cdr(Scan)) {
Help = cnf_ComputeLiteralLists(list_Car(Scan));
NewResult = list_Nil();
for (Scan1=Help;!list_Empty(Scan1);Scan1=list_Cdr(Scan1))
for (Scan2=Result;!list_Empty(Scan2);Scan2=list_Cdr(Scan2)) {
List1 = list_Car(Scan1);
List2 = list_Car(Scan2);
if (!list_Empty(list_Cdr(Scan2)))
List1 = term_CopyTermList(List1);
if (!list_Empty(list_Cdr(Scan1)))
List2 = term_CopyTermList(List2);
NewResult = list_Cons(term_DestroyDuplicatesInList(list_Nconc(List1,List2)),
NewResult);
}
list_Delete(Help);
list_Delete(Result);
Result = NewResult;
}
return Result;
}
if (symbol_Equal(Symbol,fol_And())) {
Result = cnf_ComputeLiteralLists(list_Car(term_ArgumentList(Term)));
for (Scan=list_Cdr(term_ArgumentList(Term));!list_Empty(Scan);Scan=list_Cdr(Scan)) {
Result = list_Nconc(cnf_ComputeLiteralLists(list_Car(Scan)), Result);
}
return Result;
}
if (symbol_Equal(Symbol,fol_Not()) || symbol_IsPredicate(Symbol))
return list_List(list_List(term_Copy(Term)));
misc_StartErrorReport();
misc_ErrorReport("\n In cnf_ComputeLiteralLists: Unexpected junctor in input Formula!\n");
misc_FinishErrorReport();
return Result;
}
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.
***************************************************************/
{
TERM Result;
LIST Scan, Lists;
Lists = cnf_ComputeLiteralLists(Formula);
for (Scan= Lists; !list_Empty(Scan); Scan=list_Cdr(Scan))
list_Rplaca(Scan,term_Create(fol_Or(), list_Car(Scan)));
Result = term_Create(fol_And(), Lists);
term_Delete(Formula);
return Result;
}
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(LIST clauselist)
/**********************************************************
INPUT: A list of clauses.
RETURNS: The list of clauses without subsumed clauses.
CAUTION: The list is destructively changed.
***********************************************************/
{
LIST scan,result;
st_INDEX stindex;
CLAUSE actclause;
stindex = st_IndexCreate();
result = list_Nil();
for (scan = clauselist; !list_Empty(scan); scan=list_Cdr(scan))
res_InsertClauseIndex(list_Car(scan),stindex);
for (scan=clauselist; !list_Empty(scan); scan=list_Cdr(scan)) {
actclause = list_Car(scan);
res_DeleteClauseIndex(actclause,stindex);
if (!res_BackSubWithLength(actclause,stindex)) {
res_InsertClauseIndex(actclause,stindex);
result = list_Cons(actclause,result);
}
}
if (list_Length(result) != list_Length(clauselist)) {
for (scan = result; !list_Empty(scan); scan=list_Cdr(scan))
clauselist = list_PointerDeleteElement(clauselist,list_Car(scan));
if (!list_Empty(result))
clause_DeleteClauseList(clauselist);
}else
list_Delete(clauselist);
st_IndexDelete(stindex);
return result;
}
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.
***************************************************************/
{
LIST termlist,scan,clauselist,newclauselist,delclauselist,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;
}
delclauselist = list_Nil();
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)) {
condlist = cond_CondFast(list_Car(scan));
if (!list_Empty(condlist))
clause_DeleteLiterals(list_Car(scan), condlist, Flags, Precedence);
list_Delete(condlist);
}
clauselist = cnf_SubsumeClauseList(clauselist);
newclauselist = list_Nil();
while (!list_Empty(clauselist)) {
clause = res_SelectLightestClause(clauselist);
newclauselist = list_Nconc(newclauselist,list_List(clause));
clauselist = list_PointerDeleteElement(clauselist,clause);
}
list_Delete(clauselist);
for (scan=newclauselist; !list_Empty(scan); scan=list_Cdr(scan)) {
if (res_HasTautology(list_Car(scan)))
delclauselist = list_Cons(list_Car(scan),delclauselist);
}
for (scan=delclauselist; !list_Empty(scan); scan=list_Cdr(scan))
newclauselist = list_PointerDeleteElement(newclauselist,list_Car(scan));
clause_DeleteClauseList(delclauselist);
return newclauselist;
}
TERM cnf_Flatten(TERM Term, SYMBOL Symbol)
/**************************************************************
INPUT: A <Term> and <Symbol> that is assumed to be associative.
RETURNS: If the top symbol of <Term> is <Symbol> the <Term> is flattened
as long as it contains further direct subterms starting with <Symbol>
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 <Term> and <Symbol> that is assumed to be associative,
and a predicate term which is a subterm of term
RETURNS: If the top symbol of <Term> is <Symbol> the <Term> is flattened
as long as it contains further direct subterms starting with <Symbol>
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, 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 <Precedence>.
***************************************************************/
{
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, Precedence, Symblist);
}
else { /* exist quantifier */
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, 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), Precedence, Symblist);
return Term;
}
static TERM cnf_Cnf(TERM Term, 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 <Precedence>.
***************************************************************/
{
/* 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);
Term = cnf_RemoveEquivImplFromFormula(Term);
Term = cnf_NegationNormalFormula(Term);
Term = cnf_SkolemFormula(cnf_AntiPrenex(Term), Precedence, Symblist);
Term = cnf_DistributiveFormula(Term);
return Term;
}
static LIST cnf_GetUsedTerms(CLAUSE C, PROOFSEARCH Search,
HASH InputClauseToTermLabellist)
/**************************************************************
INPUT:
RETURNS:
***************************************************************/
{
LIST UsedTerms, Used2, Scan;
UsedTerms = list_Copy(hsh_Get(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 = (int) 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,
HASH 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, 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_GetFlagValue(Flags, flag_DOCPROOF)) {
#ifdef CHECK
hsh_Check(InputClauseToTermLabellist);
#endif
hsh_Put(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_GetFlagValue(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_GetFlagValue(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, 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, 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 <Precedence>.
***************************************************************/
{
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 <Term1> of <Term>, a subterm <Proved> of <Term1>,
a list of existence quantified variables <VarList>,
a list of free variables <FreeList> and a precedence.
<Term1> is of the form
exists[...](t1 and t2 and ... and Proved and ..)
RETURNS: A new term, where <Proved> is removed from the arguments
of <Term1>.
EFFECT: The precedence of new Skolem functions is set in <Precedence>
*******************************************************************/
{
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 <Precedence>.
*********************************************************/
{
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_GetFlagValue(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_GetFlagValue(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_GetFlagValue(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,
HASH 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_GetFlagValue(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_GetFlagValue(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_GetFlagValue(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_GetFlagValue(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_GetFlagValue(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_GetFlagValue(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_GetFlagValue(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,
HASH 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 <term> and further improvements.
<rest> is used as additional, conjunctively added information.
EFFECT: The symbol precedence of the search object is changed
because new Skolem symbols are defined.
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_GetFlagValue(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_GetFlagValue(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_GetFlagValue(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_GetFlagValue(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_GetFlagValue(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);
#ifdef CHECK_OPTSKOLEM
if (flag_GetFlagValue(Flags, flag_POPTSKOLEM)) {
fputs("\nHaveProof result : ", stdout);
if (result2)
fputs("TRUE", stdout);
else
fputs("FALSE", stdout);
}
#endif
}
}
if (Result1 || result2) {
optimized = TRUE;
if (flag_GetFlagValue(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_GetFlagValue(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_GetFlagValue(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 <term>, a list <allist> of variables, a list <exlist>
of variable symbols and a precedence.
RETURNS: The list of new Skolem functions.
EFFECT: The term is destructively changed. All variable symbols
in <exlist> which appear in <term> are replaced by skolem functions
with respect to <allist> which contains the universally quantified
variables.
New Skolem functions are created and their precedence is set
in <Precedence>.
***************************************************************/
{
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,
HASH 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_GetFlagValue(Flags, flag_CNFSTRSKOLEM)) {
/* Initializing array */
for (i = 1; i <= symbol__MAXSTANDARDVAR; i++)
cnf_VARIABLEDEPTHARRAY[i] = -1;
}
if (flag_GetFlagValue(Flags, flag_POPTSKOLEM) ||
flag_GetFlagValue(Flags, flag_PSTRSKOLEM)) {
fputs("\nTerm before skolemization : \n ", stdout);
fol_PrettyPrintDFG(Term);
}
if (!fol_IsLiteral(Term)) {
if (flag_GetFlagValue(Flags, flag_CNFOPTSKOLEM) ||
flag_GetFlagValue(Flags, flag_CNFSTRSKOLEM)) {
if (flag_GetFlagValue(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, Precedence, &Symbols);
list_Delete(Symbols);
}
}
if (flag_GetFlagValue(Flags, flag_POPTSKOLEM) ||
flag_GetFlagValue(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_SetFlagValue(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, HASH TermLabelToClauselist,
HASH 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 hasharray in which for every term label the list of clauses
derived from the term is stored (if DocProof is set),
a hasharray 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: ??? EK
The precedence of new skolem symbols is set in <InputPrecedence>.
***************************************************************/
{
LIST Scan, Scan2, FormulaClauses,SkolemFunctions;
LIST SkolemPredicates, EmptyClauses, AllFormulae;
LIST UsedTerms;
TERM AxTerm,Formula;
BOOL Result;
PROOFSEARCH Search;
PRECEDENCE Precedence;
FLAGSTORE Flags;
NAT Count;
HASH InputClauseToTermLabellist;
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_GetFlagValue(Flags, flag_DOCPROOF))
prfs_AddDocProofSharingIndex(Search);
AxTerm = (TERM)NULL;
SkolemPredicates = list_Nil();
Result = FALSE;
if (flag_GetFlagValue(Flags, flag_DOCPROOF))
InputClauseToTermLabellist = hsh_Create();
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);
term_AddFatherLinks(AxTerm);
fol_NormalizeVars(AxTerm);
if (flag_GetFlagValue(Flags, flag_CNFFEQREDUCTIONS))
cnf_PropagateSubstEquations(AxTerm);
AxTerm = cnf_ObviousSimplifications(AxTerm);
if (flag_GetFlagValue(Flags, flag_CNFRENAMING)) {
term_AddFatherLinks(AxTerm);
AxTerm = ren_Rename(AxTerm, Precedence, &SkolemPredicates,
flag_GetFlagValue(Flags, flag_CNFPRENAMING), TRUE);
}
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%d", Count);
Label = string_StringCopy(buf);
list_Rplaca((LIST) list_Car(Scan), Label);
if (flag_GetFlagValue(Flags, flag_DOCPROOF) &&
flag_GetFlagValue(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);
term_AddFatherLinks(ConTerm);
fol_NormalizeVars(ConTerm);
if (flag_GetFlagValue(Flags, flag_CNFFEQREDUCTIONS))
cnf_PropagateSubstEquations(ConTerm);
ConTerm = cnf_ObviousSimplifications(ConTerm);
if (flag_GetFlagValue(Flags, flag_CNFRENAMING)) {
term_AddFatherLinks(ConTerm);
ConTerm = ren_Rename(ConTerm, Precedence, &SkolemPredicates,
flag_GetFlagValue(Flags, flag_CNFPRENAMING),TRUE);
}
/* 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;
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", (char*) list_PairFirst(list_Car(Scan)));
#endif
Formula = cnf_SkolemFormula(Formula,Precedence,&SkolemFunctions);
Formula = cnf_DistributiveFormula(Formula);
FormulaClausesTemp = cnf_MakeClauseList(Formula,FALSE,FALSE,Flags,Precedence);
if (flag_GetFlagValue(Flags, flag_DOCPROOF)) {
for (Scan2 = FormulaClausesTemp; !list_Empty(Scan2); Scan2 = list_Cdr(Scan2)) {
hsh_Put(InputClauseToTermLabellist, list_Car(Scan2), list_PairFirst(list_Car(Scan)));
}
}
FormulaClauses = list_Nconc(FormulaClauses, FormulaClausesTemp);
term_Delete(Formula);
}
/* Trage nun Formula Clauses modulo Reduktion in einen Index ein */
/* 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)) {
Result = TRUE;
/*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);
/* 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_GetFlagValue(Flags, flag_DOCPROOF)) {
hsh_PutListWithCompareFunc(TermLabelToClauselist, list_PairFirst(Pair),
list_Copy(Ax),
(BOOL (*)(POINTER,POINTER))cnf_LabelEqual,
(unsigned long (*)(POINTER))hsh_StringHashKey);
UsedTerms = list_Cons(list_PairFirst(Pair), UsedTerms);
UsedTerms = cnf_DeleteDuplicateLabelsFromList(UsedTerms);
for (Scan2 = Ax; !list_Empty(Scan2); Scan2 = list_Cdr(Scan2)) {
hsh_PutList(ClauseToTermLabellist, list_Car(Scan2), list_Copy(UsedTerms));
hsh_PutList(InputClauseToTermLabellist, list_Car(Scan2), list_Copy(UsedTerms));
}
}
*AxClauses = list_Nconc(*AxClauses, Ax);
list_Delete(UsedTerms);
}
/* Transfer precedence of new skolem symbols into <InputPrecedence> */
symbol_TransferPrecedence(Precedence, InputPrecedence);
list_Delete(ConjectureList);
if (flag_GetFlagValue(Flags, flag_DOCPROOF))
hsh_Delete(InputClauseToTermLabellist);
if (!flag_GetFlagValue(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_GetFlagValue(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 <Search>.
***************************************************************/
{
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_GetFlagValue(Flags, flag_CNFRENAMING)) {
term_AddFatherLinks(Term);
Term = ren_Rename(Term, Precedence, &SkolemPredicates,
flag_GetFlagValue(Flags,flag_CNFPRENAMING), TRUE);
}
Term = cnf_RemoveEquivImplFromFormula(Term);
Term = cnf_NegationNormalFormula(Term);
Term = cnf_AntiPrenex(Term);
TermCopy = term_Copy(Term);
TermCopy = cnf_SkolemFormula(TermCopy, 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_GetFlagValue(SubProofFlags, flag_DOCPROOF))
Formulae2Clause = TRUE;
else
Formulae2Clause = FALSE;
flag_SetFlagValue(SubProofFlags, flag_DOCPROOF, flag_DOCPROOFOFF);
ResultClauses = cnf_OptimizedSkolemization(cnf_SEARCHCOPY, term_Copy(Term),
NULL, &Dummy, Symblist, Result,
FALSE, NULL);
if (Formulae2Clause)
flag_SetFlagValue(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_GetFlagValue(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);
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_GetFlagValue(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_GetFlagValue(Flags, flag_PAPPLYDEFS)) {
puts("\nConverted to :");
fol_PrettyPrint(Target);
}
targettoprove = cnf_NegationNormalFormula(targettoprove);
if (flag_GetFlagValue(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, <SubTerm> must be a subterm of <TopTerm>.
Superterm of <SubTerm> 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 <SubTerm>.
All free variables in <SubTerm> are bound by a universal quantifier
(with polarity 1).
RETURN: The destructively changed <TopTerm>.
EFFECT: Removes all quantifiers not binding a variable in <SubTerm>
from <subTerm>'s path.
Moves all universal quantifiers binding free variable
in <SubTerm> up.
<TopTerm> is transformed into the form
forall([X1,...,Xn],or (equiv(<SubTerm>,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_GetFlagValue(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_GetFlagValue(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_GetFlagValue(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, Precedence, &symblist);
result = cnf_MakeClauseList(clauseterm,FALSE,FALSE,Flags,Precedence);
list_Delete(symblist);
term_Delete(clauseterm);
if (flag_GetFlagValue(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 <StartTerm>.
**************************************************************/
{
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;
}
}
/* <Subequ> was freed in the loop. */
return Substituted;
}