public static FormulaNode nnfNegate(FormulaNode formula) { FormulaNode result = new FormulaNode(LogicOperator.NOT); result.SetChildren(formula, null); return(result.NNF()); }
/* * <au> is an elementary formula of the form EX(ER(p,q)) */ private FormulaNode ComputeAUFragment(FormulaNode au, FormulaNode stateSet, SymbolicState state) { #if DEBUG Console.WriteLine("Computing fragment for " + au); #endif FormulaNode frag = FormulaParser.Parse("~TRUE"); FormulaNode notLeft = new FormulaNode(LogicOperator.NOT, au[0][0], null); FormulaNode notRight = new FormulaNode(LogicOperator.NOT, au[0][1], null); while (true) { string nextName = "succ" + uniqueId.GetTicket().ToString(); SymbolicState next = new SymbolicState(elementary, nextName); FormulaNode transition = GenTransition(state, next); FormulaNode memberOf = SymbolicState.Substitute(stateSet, state, next); FormulaNode nextFrag = SymbolicState.Substitute(frag, state, next); FormulaNode newFrag = new FormulaNode(LogicOperator.AND, transition, memberOf); newFrag = new FormulaNode(LogicOperator.AND, newFrag, nextFrag); newFrag = next.Quantify(LogicOperator.EXISTS, newFrag); newFrag = new FormulaNode(LogicOperator.AND, state.ValueOf(notLeft.NNF()), newFrag); // Add the big conjunction needed for fragAU List <FormulaNode> fragTerms = new List <FormulaNode>(); foreach (FormulaNode el in elementary) { if (el.GetLogicOperator() != LogicOperator.EX) { continue; } nextName = "succ" + uniqueId.GetTicket().ToString(); next = new SymbolicState(elementary, nextName); transition = GenTransition(state, next); memberOf = SymbolicState.Substitute(stateSet, state, next); nextFrag = SymbolicState.Substitute(frag, state, next); FormulaNode lhs = state.ValueOf(el); FormulaNode rhs = new FormulaNode(LogicOperator.AND, transition, memberOf); rhs = new FormulaNode(LogicOperator.AND, rhs, nextFrag); rhs = new FormulaNode(LogicOperator.AND, rhs, next.ValueOf(SymbolicState.Substitute(el[0], state, next))); rhs = next.Quantify(LogicOperator.EXISTS, rhs); fragTerms.Add(new FormulaNode(LogicOperator.IMP, lhs, rhs)); } newFrag = new FormulaNode(LogicOperator.AND, newFrag, JoinTerms(LogicOperator.AND, fragTerms)); newFrag = new FormulaNode(LogicOperator.OR, state.ValueOf(notRight.NNF()), newFrag); if (IsFixpoint(newFrag, frag, state)) { return(frag); } frag = newFrag; } }
// We assume that the formula is in QBF // (But no other assumption) public static bool QBFSAT(FormulaNode formula) { // First convert the formula to PNF formula = formula.NNF().PNF(); // Then convert it to QBCNF QBCNFormula qbcnf = ConvertToCNF(formula); return(QBFSolver.Solve(qbcnf)); }
// Trnasfer the node to PNF (the formula is assumed to be in NNF) // We assume that the formula also has no temporal operators public FormulaNode PNF() { if (this.logicOp == LogicOperator.VAR) { return(new FormulaNode(this.name)); } FormulaNode res = null, left = null, right = null; ISet <string> leftSet, rightSet; string varname; if (this.logicOp == LogicOperator.NOT) { res = new FormulaNode(LogicOperator.NOT); res.SetChildren(new FormulaNode(this.childNodes[0].name), null); return(res); } if (this.logicOp == LogicOperator.EXISTS || this.logicOp == LogicOperator.ALL) { res = new FormulaNode(this.logicOp, this.name); res.SetChildren(this.childNodes[0].PNF(), null); return(res); } // Since we assume NNF, all NOT nodes are next to variables // Thus all of the remaining operators are binary left = this.childNodes[0].PNF(); right = this.childNodes[1].PNF(); leftSet = left.GetVariables(); rightSet = right.GetVariables(); if (this.logicOp == LogicOperator.AND || this.logicOp == LogicOperator.OR) { FormulaNode temp; if (left.logicOp == LogicOperator.EXISTS || left.logicOp == LogicOperator.ALL) { if (rightSet.Contains(left.name)) { varname = UniquePNFVariable(); left = left.Substitute(left.name, varname); } res = new FormulaNode(left.logicOp, left.name); temp = new FormulaNode(this.logicOp); temp.SetChildren(left.childNodes[0], right); res.SetChildren(temp.PNF(), null); } else if (right.logicOp == LogicOperator.EXISTS || right.logicOp == LogicOperator.ALL) { if (leftSet.Contains(right.name)) { varname = UniquePNFVariable(); right = right.Substitute(right.name, varname); } res = new FormulaNode(right.logicOp, right.name); temp = new FormulaNode(this.logicOp); temp.SetChildren(left, right.childNodes[0]); res.SetChildren(temp.PNF(), null); } else { res = new FormulaNode(this.logicOp); res.SetChildren(left, right); } } // For convenience, we get rid of "->" operators if (this.logicOp == LogicOperator.IMP) { res = new FormulaNode(LogicOperator.OR); res.SetChildren(new FormulaNode(LogicOperator.NOT), right); res.childNodes[0].SetChildren(left, null); res = res.NNF().PNF(); } return(res); }
// Transfer the node to NNF public FormulaNode NNF() { if (this.logicOp == LogicOperator.VAR) { return(new FormulaNode(this.name)); } FormulaNode res = null, left = null, right = null; if (this.logicOp != LogicOperator.NOT) { res = new FormulaNode(this.logicOp, this.name); if (this.childNodes[0] != null) { left = this.childNodes[0].NNF(); } if (this.childNodes[1] != null) { right = this.childNodes[1].NNF(); } res.SetChildren(left, right); return(res); } // If we reached here, our node is "~" and hence we should // rearrange the formula tree // We note that a "~" should be unary and hence it only // has a left child switch (this.childNodes[0].logicOp) { case LogicOperator.EXISTS: res = new FormulaNode(LogicOperator.ALL, this.childNodes[0].name); break; case LogicOperator.ALL: res = new FormulaNode(LogicOperator.EXISTS, this.childNodes[0].name); break; case LogicOperator.AND: res = new FormulaNode(LogicOperator.OR); break; case LogicOperator.OR: res = new FormulaNode(LogicOperator.AND); break; case LogicOperator.NOT: return(this.childNodes[0].childNodes[0].NNF()); case LogicOperator.IMP: // ~(a->b) == a & ~b res = new FormulaNode(LogicOperator.AND); left = this.childNodes[0].childNodes[0].NNF(); right = new FormulaNode(LogicOperator.NOT); right.SetChildren(this.childNodes[0].childNodes[1].NNF(), null); res.SetChildren(left, right.NNF()); return(res); case LogicOperator.EF: res = new FormulaNode(LogicOperator.AG); break; case LogicOperator.AF: res = new FormulaNode(LogicOperator.EG); break; case LogicOperator.EG: res = new FormulaNode(LogicOperator.AF); break; case LogicOperator.AG: res = new FormulaNode(LogicOperator.EF); break; case LogicOperator.AX: res = new FormulaNode(LogicOperator.EX); break; case LogicOperator.EX: res = new FormulaNode(LogicOperator.AX); break; case LogicOperator.EU: res = new FormulaNode(LogicOperator.AR); break; case LogicOperator.AU: res = new FormulaNode(LogicOperator.ER); break; case LogicOperator.ER: res = new FormulaNode(LogicOperator.AU); break; case LogicOperator.AR: res = new FormulaNode(LogicOperator.EU); break; case LogicOperator.VAR: res = new FormulaNode(LogicOperator.NOT); res.SetChildren(new FormulaNode(this.childNodes[0].name), null); return(res); default: res = null; break; } if (this.childNodes[0].childNodes[0] != null) { left = new FormulaNode(LogicOperator.NOT); left.SetChildren(this.childNodes[0].childNodes[0].NNF(), null); left = left.NNF(); } if (this.childNodes[0].childNodes[1] != null) { right = new FormulaNode(LogicOperator.NOT); right.SetChildren(this.childNodes[0].childNodes[1].NNF(), null); right = right.NNF(); } res.SetChildren(left, right); return(res); }