def formulaDistributeDisjunctions(f): """ Convert a Skolemized formula in prefix-NNF form into Conjunctive Normal Form. """ arg1 = None arg2 = None if f.isQuantified(): arg1 = f.child1 arg2 = formulaDistributeDisjunctions(f.child2) f = Formula(f.op, arg1, arg2) elif f.isLiteral(): pass else: if f.hasSubform1(): arg1 = formulaDistributeDisjunctions(f.child1) if f.hasSubform2(): arg2 = formulaDistributeDisjunctions(f.child2) f = Formula(f.op, arg1, arg2) if f.op == "|": if f.child1.op == "&": # (P&Q)|R -> (P|R) & (Q|R) arg1 = Formula("|", f.child1.child1, f.child2) arg2 = Formula("|", f.child1.child2, f.child2) f = Formula("&", arg1, arg2) f = formulaDistributeDisjunctions(f) elif f.child2.op == "&": # (R|(P&Q) -> (R|P) & (R|Q) arg1 = Formula("|", f.child1, f.child2.child1) arg2 = Formula("|", f.child1, f.child2.child2) f = Formula("&", arg1, arg2) f = formulaDistributeDisjunctions(f) return f
def formulaRekSkolemize(f, variables, subst): """ Perform Skolemization of f, which is assumed to be in the scope of the list of variables provided. """ if f.isLiteral(): child = f.child1.instantiate(subst) f = Formula("", child) elif f.op == "?": var = f.child1 skTerm = skolemGenerator(variables) oldbinding = subst.modifyBinding((var, skTerm)) f = formulaRekSkolemize(f.child2, variables, subst) subst.modifyBinding((var, oldbinding)) elif f.op == "!": var = f.child1 variables.append(var) handle = formulaRekSkolemize(f.child2, variables, subst) f = Formula("!", var, handle) variables.pop() else: arg1 = None arg2 = None if f.hasSubform1(): arg1 = formulaRekSkolemize(f.child1, variables, subst) if f.hasSubform2(): arg2 = formulaRekSkolemize(f.child2, variables, subst) f = Formula(f.op, arg1, arg2) return f
def formulaMiniScope(f): """ Perform miniscoping, i.e. move quantors in as far as possible, so that their scope is only the smallest subformula in which the variable occurs. """ res = False if f.isQuantified(): op = f.child2.op quant = f.op var = f.child1 subf = f.child2 if op == "&" or op == "|": if not var in subf.child1.collectFreeVars(): # q[X]:(P op Q) -> P op (q[X]:Q) if X not free in P arg2 = Formula(quant, var, subf.child2) arg1 = subf.child1 f = Formula(op, arg1, arg2) res = True elif not var in subf.child2.collectFreeVars(): # q[X]:(P op Q) -> (q[X]:P) op Q if X not free in Q arg1 = Formula(quant, var, subf.child1) arg2 = subf.child2 f = Formula(op, arg1, arg2) res = True else: if op == "&" and quant == "!": # ![X]:(P&Q) -> ![X]:P & ![X]:Q arg1 = Formula("!", var, subf.child1) arg2 = Formula("!", var, subf.child2) f = Formula("&", arg1, arg2) res = True elif op == "|" and quant == "?": # ?[X]:(P|Q) -> ?[X]:P | ?[X]:Q arg1 = Formula("?", var, subf.child1) arg2 = Formula("?", var, subf.child2) f = Formula("|", arg1, arg2) res = True arg1 = f.child1 arg2 = f.child2 modified = False if f.hasSubform1(): arg1, m = formulaMiniScope(f.child1) modified |= m if f.hasSubform2(): arg2, m = formulaMiniScope(f.child2) modified |= m if modified: f = Formula(f.op, arg1, arg2) f, m = formulaMiniScope(f) res = True return f, res
def formulaVarRename(f, subst=None): """ Rename variables in f so that all bound variables are unique. """ if subst == None: subst = Substitution() if f.isQuantified(): # New scope of a variable -> add a new binding to a new # variable. Store potential old binding to restore when # leaving the scope later var = f.child1 newvar = freshVar() oldbinding = subst.modifyBinding((var, newvar)) if f.isLiteral(): # Create copy with the new variables recorded in subst child = f.child1.instantiate(subst) f = Formula("", child) else: # This is a composite formula. Rename it... arg1 = None arg2 = None if f.isQuantified(): # Apply new renaming locally to the bound variable and # recusively to the subformula arg1 = newvar arg2 = formulaVarRename(f.child2, subst) else: # Apply renaming to all subformulas if f.hasSubform1(): arg1 = formulaVarRename(f.child1, subst) if f.hasSubform2(): arg2 = formulaVarRename(f.child2, subst) f = Formula(f.op, arg1, arg2) if f.isQuantified(): # We are leaving the scope of the quantifier, so restore # substitution. subst.modifyBinding((var, oldbinding)) return f