public static void RunFormula(string formula) { FormulaNode parsedFormula = null; PrintLine(); Console.WriteLine("formula: " + formula); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); try { parsedFormula = FormulaParser.Parse(formula); } catch (Exception e) { Console.WriteLine("Parsing error: " + e.Message); return; } CTLSatisfiabilityChecker checker = new CTLSatisfiabilityChecker(parsedFormula); bool res = checker.Check(); stopwatch.Stop(); double time = ((double)stopwatch.ElapsedMilliseconds / 1000.0); Console.WriteLine("iterations: " + checker.Iterations); Console.WriteLine("time: " + time); Console.WriteLine("result: " + ConvSAT(res)); PrintLine(); }
/* Generates a formula representing the fact that for <state> either * the eventuality is not promised or that if it is, then there * exists a fragment of <stateSet> rooted at <state> such that * all the frontier nodes satisfy the eventuallity */ private FormulaNode GenA(FormulaNode stateSet, SymbolicState state) { List <FormulaNode> terms = new List <FormulaNode>(); foreach (var e in elementary) { if (e.GetLogicOperator() != LogicOperator.EX) { continue; } if (e[0].GetLogicOperator() != LogicOperator.ER) { continue; } FormulaNode frag = ComputeAUFragment(e, stateSet, state); FormulaNode promised = state.ValueOf(e); FormulaNode res = new FormulaNode(LogicOperator.OR, promised, state.ValueOf(e[0][0])); res = new FormulaNode(LogicOperator.OR, res, frag); terms.Add(res); } return(JoinTerms(LogicOperator.AND, terms)); }
public static FormulaNode JoinTerms(LogicOperator op, List <FormulaNode> terms) { FormulaNode result; if (terms.Count == 0) { if (op == LogicOperator.AND) { return(new FormulaNode(FormulaNode.TRUE_LITERAL)); } if (op == LogicOperator.OR) { // Build FALSE as ~TRUE result = new FormulaNode(LogicOperator.NOT); result.SetChildren(new FormulaNode(FormulaNode.TRUE_LITERAL), null); return(result); } throw new Exception("Join with unsupported logic operator"); } if (terms.Count == 1) { return(terms[0]); } result = new FormulaNode(op, terms[0], terms[1]); foreach (var t in terms.GetRange(2, terms.Count - 2)) { result = new FormulaNode(op, result, t); } return(result); }
/* Generates a formula representing the fact that for <state> either * the eventuality is not promised or that if it is, then there * exists a fragment of <stateSet> rooted at <state> that has * a frontier node who satisfied the eventuallity */ private FormulaNode GenE(FormulaNode stateSet, SymbolicState state) { ComputeEUFragments(stateSet, state); List <FormulaNode> terms = new List <FormulaNode>(); foreach (var e in elementary) { if (e.GetLogicOperator() != LogicOperator.EX) { continue; } if (e[0].GetLogicOperator() != LogicOperator.EU) { continue; } FormulaNode notPromised = new FormulaNode(LogicOperator.NOT); notPromised.SetChildren(state.ValueOf(e), null); FormulaNode res = new FormulaNode(LogicOperator.OR); res.SetChildren(notPromised, new FormulaNode(LogicOperator.NOT)); res[1].SetChildren(state.ValueOf(e[0][0]), null); FormulaNode frag = fragEU[e[0]]; res = new FormulaNode(LogicOperator.OR, res, frag); terms.Add(res); } return(JoinTerms(LogicOperator.AND, terms)); }
public static FormulaNode nnfNegate(FormulaNode formula) { FormulaNode result = new FormulaNode(LogicOperator.NOT); result.SetChildren(formula, null); return(result.NNF()); }
private FormulaNode GenLC1(FormulaNode stateSet, SymbolicState state) { List <FormulaNode> terms = new List <FormulaNode>(); foreach (var e in elementary) { if (e.GetLogicOperator() != LogicOperator.EX) { continue; } string nextName = "succ" + uniqueId.GetTicket().ToString(); SymbolicState next = new SymbolicState(elementary, nextName); FormulaNode existsInState = state.ValueOf(e); FormulaNode notExistsInState = new FormulaNode(LogicOperator.NOT, existsInState, null); FormulaNode nextValid = SymbolicState.Substitute(stateSet, state, next); FormulaNode transition = GenTransition(state, next); FormulaNode body = e[0]; FormulaNode occursNext = next.ValueOf(body); FormulaNode hasSucc = new FormulaNode(LogicOperator.AND, nextValid, transition); hasSucc = new FormulaNode(LogicOperator.AND, hasSucc, occursNext); hasSucc = next.Quantify(LogicOperator.EXISTS, hasSucc); terms.Add(new FormulaNode(LogicOperator.OR, notExistsInState, hasSucc)); } return(JoinTerms(LogicOperator.AND, terms)); }
/* Check if we reached a fixpoint. That is, if there are no states in <largeSet> * which are absent from <smallSet>. */ private bool IsFixpoint(FormulaNode largeSet, FormulaNode smallSet, SymbolicState v) { FormulaNode notNew = new FormulaNode(LogicOperator.NOT, smallSet, null); FormulaNode stateRemoved = new FormulaNode(LogicOperator.AND, largeSet, notNew); stateRemoved = v.Quantify(LogicOperator.EXISTS, stateRemoved); return(!FormulaCNF.QBFSAT(stateRemoved)); }
/* * <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)); }
/* Generates a formula representing the fact that <state> has a * successor in <stateSet>. Does not guarantee that <state> itself * belongs to the set. */ private FormulaNode GenSucc(FormulaNode stateSet, SymbolicState state) { 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 result = new FormulaNode(LogicOperator.AND, transition, memberOf); result = next.Quantify(LogicOperator.EXISTS, result); return(result); }
public FormulaNode Quantify(LogicOperator quantifier, FormulaNode formula) { FormulaNode result = formula; foreach (string name in elementaryNames.Values) { result = new FormulaNode(quantifier, result, null); result.SetName(name); } return(result); }
// For a PNF formula, return the non-quanitifed part public FormulaNode GetPropositional() { FormulaNode res = this; while (res.logicOp == LogicOperator.EXISTS || res.logicOp == LogicOperator.ALL) { res = res.childNodes[0]; } return(res); }
public static FormulaNode CreateTestFormula() { FormulaNode result = new FormulaNode(LogicOperator.EX); result.SetChildren(null, new FormulaNode("b")); result = new FormulaNode(LogicOperator.EU); FormulaNode a = new FormulaNode(LogicOperator.AG); a.SetChildren(new FormulaNode("p"), null); result.SetChildren(a, new FormulaNode("q")); return(result); }
public static ISet <FormulaNode> positiveElementary(FormulaNode formula) { ISet <FormulaNode> allElementary = elementaryFormulas(formula); HashSet <FormulaNode> result = new HashSet <FormulaNode>(); foreach (var f in allElementary) { if (f.GetLogicOperator() == LogicOperator.VAR || f.GetLogicOperator() == LogicOperator.EX) { result.Add(f); } } return(result); }
/* Replace the variables describing the state <from> with the ones that describe * state <to> */ public static FormulaNode Substitute(FormulaNode formula, SymbolicState from, SymbolicState to) { if (formula.GetLogicOperator() == LogicOperator.VAR) { if (from.nameToElementary.Keys.Contains(formula.GetName())) { // this variable represents an elementary formula var elementary = from.nameToElementary[formula.GetName()]; return(new FormulaNode(to.elementaryNames[elementary])); } else { return(new FormulaNode(formula.GetName())); } } if (formula.GetLogicOperator() == LogicOperator.ALL || formula.GetLogicOperator() == LogicOperator.EXISTS) { FormulaNode result = new FormulaNode(formula.GetLogicOperator()); if (from.nameToElementary.Keys.Contains(formula.GetName())) { // this variable represents an elementary formula var elementary = from.nameToElementary[formula.GetName()]; result.SetName(to.elementaryNames[elementary]); } else { result.SetName(formula.GetName()); } result.SetChildren(Substitute(formula[0], from, to), null); return(result); } FormulaNode res = new FormulaNode(formula.GetLogicOperator()); FormulaNode left = Substitute(formula[0], from, to); FormulaNode right = null; if (formula[1] != null) { right = Substitute(formula[1], from, to); } res.SetChildren(left, right); return(res); }
// replace ->, AF, AG, EF and EG with simpler operators public FormulaNode ImplementComplexOperators() { FormulaNode leftChild = null; FormulaNode rightChild = null; FormulaNode trueFormula = new FormulaNode(TRUE_LITERAL); FormulaNode falseFormula = new FormulaNode(LogicOperator.NOT, trueFormula, null); FormulaNode result; if (this[0] != null) { leftChild = this[0].ImplementComplexOperators(); } if (this[1] != null) { rightChild = this[1].ImplementComplexOperators(); } switch (logicOp) { // (a -> b) is (~a | b) case LogicOperator.IMP: FormulaNode left = new FormulaNode(LogicOperator.NOT, leftChild, null); return(new FormulaNode(LogicOperator.OR, left, rightChild)); // EF(f) is EU(TRUE, f) case LogicOperator.EF: return(new FormulaNode(LogicOperator.EU, trueFormula, leftChild)); // EG(f) is ER(FALSE, f) case LogicOperator.EG: return(new FormulaNode(LogicOperator.ER, falseFormula, leftChild)); // AF(f) is AU(TRUE, f) case LogicOperator.AF: return(new FormulaNode(LogicOperator.AU, trueFormula, leftChild)); // AG(f) is AU(FALSE, f) case LogicOperator.AG: return(new FormulaNode(LogicOperator.AR, falseFormula, leftChild)); default: result = new FormulaNode(logicOp, name); result.SetChildren(leftChild, rightChild); return(result); } }
private void ComputeEUFragments(FormulaNode stateSet, SymbolicState state) { #if DEBUG Console.WriteLine("Compute fragments"); #endif foreach (var e in elementary) { if (e.GetLogicOperator() != LogicOperator.EX) { continue; } if (e[0].GetLogicOperator() != LogicOperator.EU) { continue; } #if DEBUG Console.WriteLine("Computing fragment for " + e); #endif FormulaNode frag = FormulaParser.Parse("~TRUE"); 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(e[0][0]), newFrag); newFrag = new FormulaNode(LogicOperator.OR, state.ValueOf(e[0][1]), newFrag); if (IsFixpoint(newFrag, frag, state)) { break; } frag = newFrag; } fragEU[e[0]] = frag; } }
// For a node subformula, assign a number n and return the block // xn <-> l op r private static TseytinBlock GetTseytinBlocks(FormulaNode node, ISet <TseytinBlock> blockSet) { if (node.GetLogicOperator() == LogicOperator.VAR) { return(null); } int ticket = ticketMachine.GetTicket(); string left = "", right = ""; TseytinBlock temp; temp = GetTseytinBlocks(node[0], blockSet); if (temp == null) { left = node[0].GetName(); } else { left = temp.ticket.ToString(); } if (node[1] != null) { temp = GetTseytinBlocks(node[1], blockSet); if (temp == null) { right = node[1].GetName(); } else { right = temp.ticket.ToString(); } } TseytinBlock res = new TseytinBlock(ticket, left, right, node.GetLogicOperator()); blockSet.Add(res); return(res); }
// Get a propositional formula and return its (raw) CNF form // addedVars: the names of the new variables introduced by the transformation private static ISet <ISet <string> > TseytinTransformation(FormulaNode formula, out ISet <string> addedVars) { ISet <ISet <string> > res = new HashSet <ISet <string> >(); ISet <TseytinBlock> blockSet = new HashSet <TseytinBlock>(); ticketMachine.Reset(); TseytinBlock top = GetTseytinBlocks(formula, blockSet); if (top == null) { // The formula is simply a variable - no Tseitin blocks required res.Add(new HashSet <string> { formula.GetName() }); } else { // Create a conjunction of all Tseitin blocks foreach (TseytinBlock block in blockSet) { res.UnionWith(TseytinBlockToCNF(block)); } // Add the requirement that the topmost formula is true ISet <string> topClause = new HashSet <string>(); topClause.Add(top.ticket.ToString()); res.Add(topClause); } addedVars = new HashSet <string>(); foreach (TseytinBlock block in blockSet) { addedVars.Add(block.ticket.ToString()); } // Force the TRUE variable to true res.Add(new HashSet <string> { FormulaNode.TRUE_LITERAL }); return(res); }
/* Generate the transition relation R */ private FormulaNode GenTransition(SymbolicState from, SymbolicState to) { List <FormulaNode> terms = new List <FormulaNode>(); foreach (var e in elementary) { if (e.GetLogicOperator() != LogicOperator.EX) { continue; } // if e = EX(g), generate the term "e(from) | ~g(to)" FormulaNode body = e[0]; // the formula inside the EX FormulaNode notBody = CTLUtils.nnfNegate(body); FormulaNode left = from.ValueOf(e); FormulaNode right = to.ValueOf(notBody); terms.Add(new FormulaNode(LogicOperator.OR, left, right)); } return(JoinTerms(LogicOperator.AND, terms)); }
private static void AssertSat(string formulaString, bool expected) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); bool Completed = ExecuteWithTimeLimit(TimeSpan.FromMilliseconds(timelimit), () => { FormulaNode formula = FormulaParser.Parse(formulaString); Console.WriteLine("\nTEST: " + formulaString); var checker = new CTLSatisfiabilityChecker(formula); bool result = checker.Check(); Console.WriteLine("Done"); if (result != expected) { throw new Exception("Wrong SAT value for " + formulaString); } }); stopwatch.Stop(); double time = (double)stopwatch.ElapsedMilliseconds / 1000.0; Console.WriteLine("TIME: " + time); }
public bool Check() { SymbolicState v = new SymbolicState(elementary, "v"); // initially, all possible states belong to the structure FormulaNode states = new FormulaNode(FormulaNode.TRUE_LITERAL); FormulaNode oldStates; while (true) { iterations++; #if DEBUG Console.WriteLine("Iteration " + iterations.ToString()); #endif oldStates = states; FormulaNode succ = GenSucc(states, v); FormulaNode lc1 = GenLC1(states, v); FormulaNode e = GenE(states, v); FormulaNode a = GenA(states, v); states = new FormulaNode(LogicOperator.AND, states, succ); states = new FormulaNode(LogicOperator.AND, states, lc1); states = new FormulaNode(LogicOperator.AND, states, e); states = new FormulaNode(LogicOperator.AND, states, a); if (IsFixpoint(oldStates, states, v)) { break; } } #if DEBUG Console.WriteLine("Reached fixpoint. Checking for satisfying state"); #endif FormulaNode formulaValue = v.ValueOf(normalized); FormulaNode formulaAndValid = new FormulaNode(LogicOperator.AND, states, formulaValue); FormulaNode sat = v.Quantify(LogicOperator.EXISTS, formulaAndValid); return(FormulaCNF.QBFSAT(sat)); }
// Change f[x] to f[x/x'] public FormulaNode Substitute(string original, string replacement) { if (this.logicOp == LogicOperator.VAR) { if (this.name == original) { return(new FormulaNode(replacement)); } else { return(new FormulaNode(this.name)); } } FormulaNode res = new FormulaNode(this.logicOp, this.name); if ((this.logicOp == LogicOperator.EXISTS || this.logicOp == LogicOperator.ALL) && (this.name == original)) { res.name = replacement; } FormulaNode left = null, right = null; if (this.childNodes[0] != null) { left = this.childNodes[0].Substitute(original, replacement); } if (this.childNodes[1] != null) { right = this.childNodes[1].Substitute(original, replacement); } res.SetChildren(left, right); return(res); }
public void SetChildren(FormulaNode left, FormulaNode right) { this.childNodes[0] = left; this.childNodes[1] = right; this.variableSet = null; }
// Get a PNF formula and return its QBCNF public static QBCNFormula ConvertToCNF(FormulaNode formula) { QBCNFormula res = new QBCNFormula(); FormulaNode node = formula; ISet <string> addedVars; res.quantifiers = new List <string>(); while (node.GetLogicOperator() == LogicOperator.EXISTS || node.GetLogicOperator() == LogicOperator.ALL) { if (node.GetLogicOperator() == LogicOperator.EXISTS) { res.quantifiers.Add("e" + node.GetName()); } else { res.quantifiers.Add("a" + node.GetName()); } node = node[0]; } if (res.quantifiers.Count != formula.GetVariables().Count) { throw new Exception("Non-quantified variables in formula!"); } res.propositional = TseytinTransformation(node, out addedVars); //Replace strings with numbers ISet <string> literals = res.GetLiterals(); Dictionary <string, string> changes = new Dictionary <string, string>(); foreach (string literal in literals) { int n; bool isNum = int.TryParse(literal, out n); if (!changes.ContainsKey(literal) & !isNum) { int ticket = ticketMachine.GetTicket(); if (literal[0] != '-') { changes.Add(literal, ticket.ToString()); changes.Add("-" + literal, (-ticket).ToString()); } else { changes.Add(literal, (-ticket).ToString()); changes.Add(literal.Substring(1), ticket.ToString()); } } } res.ReplaceLiterals(changes); // Quantify the Tseytin variables with EXISTS foreach (string var in addedVars) { res.quantifiers.Add("e" + var); } return(res); }
private static FormulaNode Parse(List <Token> tokens) { FormulaNode result = null; List <Token> rightSide = new List <Token>(); BinaryToken lastOp = null; // the input is a single token - must be an atom or an unparsed string if (tokens.Count == 1) { var tok = tokens[0] as LiteralToken; if (tok.type == TokenType.ATOM) { return(new FormulaNode(tok.value)); } return(Parse(ToplevelTokenize(tok.value))); } int minPrecedence = MAX_PRECEDENCE; for (int i = 0; i < tokens.Count; i++) { if (tokens[i] is BinaryToken) { var op = tokens[i] as BinaryToken; minPrecedence = Math.Min(minPrecedence, op.precedence); } } if (minPrecedence == MAX_PRECEDENCE) { // the input didn't contain any toplevel binary operators var opToken = tokens[0] as UnaryToken; result = new FormulaNode(opToken.logicOperator); var operand = Parse(tokens.GetRange(1, tokens.Count - 1)); if (untilOperators.Contains(opToken.logicOperator)) { result.SetChildren(operand[0], operand[1]); } else if (quanitifers.Contains(opToken.logicOperator)) { result.SetName(operand[0].GetName()); result.SetChildren(operand[1], null); } else { result.SetChildren(operand, null); } return(result); } // if we got here - split by lowest-precedence binary operator foreach (Token t in tokens) { if (t is BinaryToken) { var op = t as BinaryToken; if (op.precedence == minPrecedence) { if (result == null) { result = Parse(rightSide); } else { var leftSide = result; result = new FormulaNode(lastOp.logicOperator); result.SetChildren(leftSide, Parse(rightSide)); } rightSide = new List <Token>(); lastOp = op; continue; } } rightSide.Add(t); } if (rightSide.Count != 0) { var leftSide = result; result = new FormulaNode(lastOp.logicOperator); result.SetChildren(leftSide, Parse(rightSide)); } return(result); }
// 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); }
/* Assumes the formula is in NNF form */ public static ISet <FormulaNode> elementaryFormulas(FormulaNode formula) { HashSet <FormulaNode> result = new HashSet <FormulaNode>(); switch (formula.GetLogicOperator()) { case LogicOperator.AU: case LogicOperator.AR: // AX(f) is elementary FormulaNode ax_f = new FormulaNode(LogicOperator.AX); ax_f.SetChildren(formula, null); result.Add(ax_f); result.Add(nnfNegate(ax_f)); result.UnionWith(elementaryFormulas(formula[0])); result.UnionWith(elementaryFormulas(formula[1])); break; case LogicOperator.EU: case LogicOperator.ER: // EX(f) is elementary FormulaNode ex_f = new FormulaNode(LogicOperator.EX); ex_f.SetChildren(formula, null); result.Add(ex_f); result.Add(nnfNegate(ex_f)); result.UnionWith(elementaryFormulas(formula[0])); result.UnionWith(elementaryFormulas(formula[1])); break; case LogicOperator.EX: case LogicOperator.AX: // the formula itself is elementary result.Add(formula); result.Add(nnfNegate(formula)); result.UnionWith(elementaryFormulas(formula[0])); break; case LogicOperator.OR: case LogicOperator.AND: result.UnionWith(elementaryFormulas(formula[0])); result.UnionWith(elementaryFormulas(formula[1])); break; case LogicOperator.NOT: Debug.Assert(formula[0].GetLogicOperator() == LogicOperator.VAR, "Input to elementaryFormulas must be in NNF form"); result.UnionWith(elementaryFormulas(formula[0])); break; case LogicOperator.VAR: if (formula.GetName() != FormulaNode.TRUE_LITERAL) { result.Add(formula); result.Add(nnfNegate(formula)); } break; default: throw new Exception("Not implemented"); } return(result); }
public FormulaNode(LogicOperator logicOp, FormulaNode left, FormulaNode right) { this.logicOp = logicOp; childNodes[0] = left; childNodes[1] = right; }
// 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); }