def rewrite_release(node): """ rewrites release into its until equivalent >>> syntactic_equivalent(rewrite_release(parse("a R b")), parse("~(~a U ~b)")) True """ for n in node.children: rewrite_release(n) if node.type == Type.Release: node.type = Type.BoolNot node.children = [Until(BoolNot(node.left), BoolNot(node.right))] return node
def rewrite_globally(node): """ rewrites globally into the until equivalent >>> syntactic_equivalent(rewrite_globally(parse("G p")), parse("~(True U ~p)")) True >>> syntactic_equivalent(rewrite_globally(parse("G F p")), parse("~(True U ~(F p))")) True >>> syntactic_equivalent(rewrite_globally(rewrite_finally(parse("G F p"))), parse("~(True U ~(true U p))")) True >>> syntactic_equivalent(rewrite_globally(rewrite_finally(parse("G F p"))), rewrite_finally(rewrite_globally(parse("G F p")))) True """ for n in node.children: rewrite_globally(n) if node.type == Type.Globally: node.type = Type.BoolNot node.children = [Until(CTrue(), BoolNot(node.left))] return node
def rewrite_equivalent(node): """ rewrites equivalent (<->) into its and/or equivalent >>> syntactic_equivalent(rewrite_equivalent(Equivalent(Identifier("p"), Identifier("q"))), BoolAnd(BoolOr(BoolNot(Identifier("p")), Identifier("q")), BoolOr(Identifier("p"), BoolNot(Identifier("q"))))) True """ for n in node.children: rewrite_equivalent(n) if node.type == Type.Equivalent: node.type = Type.BoolAnd node.children = [ BoolOr(BoolNot(node.left), node.right), BoolOr(node.left, BoolNot(node.right)) ] return node
def rewrite_xor(node): """ rewrites xor to the and/or equivalent >>> syntactic_equivalent(rewrite_xor(BoolXor(Identifier("p"), Identifier("q"))), BoolAnd(BoolOr(BoolNot(Identifier("p")), BoolNot(Identifier("q"))), BoolOr(Identifier("p"), Identifier("q")))) True """ for n in node.children: rewrite_xor(n) if node.type == Type.BoolXor: node.type = Type.BoolAnd node.children = [ BoolOr(BoolNot(node.left), BoolNot(node.right)), BoolOr(node.left, node.right) ] return node
def rewrite_implies(node): """ rewrites implies (->) to the or equivalent >>> syntactic_equivalent(rewrite_implies(Implies(Identifier("p"), Identifier("q"))), BoolOr(BoolNot(Identifier("p")), Identifier("q"))) True """ for n in node.children: rewrite_implies(n) if node.type == Type.Implies: node.type = Type.BoolOr node.children = [BoolNot(node.left), node.right] return node
def neg(expr): """ >>> syntactic_equivalent(neg(CTrue()), CFalse()) True >>> syntactic_equivalent(neg(Identifier("p")), BoolNot(Identifier("p"))) True >>> syntactic_equivalent(neg(BoolNot(Identifier("q"))), Identifier("q")) True >>> syntactic_equivalent(neg(CFalse()), CTrue()) True """ if expr.type == Type.BoolNot: return expr.left elif expr.type == Type.Constant: if expr.value == CTrue().value: return CFalse() else: return CTrue() else: return BoolNot(expr)
def d_bool_not(t): ''' expr : ('not'|'!'|'~') instmode expr $right 2000 ''' return BoolNot(t[2], instmode=t[1])
def d_trace_neg_lit(t): ''' trace_neg_lit : '!' identifier ''' return BoolNot(t[1])
def rewrite_nnf(node): """ rewrites to negational normal form (all not operators which are not in front of an atom are pushed inside). >>> syntactic_equivalent(rewrite_nnf(parse("!(p and q)")), parse("!p or !q")) True >>> syntactic_equivalent(rewrite_nnf(parse("!(p or q)")), parse("!p && !q")) True >>> syntactic_equivalent(rewrite_nnf(parse("!!p")), parse("p")) True >>> syntactic_equivalent(rewrite_nnf(parse("!(p -> q)")), parse("p && !q")) True >>> syntactic_equivalent(rewrite_nnf(parse("!(A -> (B && !(C || D)))")), parse("A && (!B || (C || D))")) True >>> syntactic_equivalent(rewrite_nnf(parse("!(p <-> q)")), parse("(!p || !q) && (p || q)")) True >>> syntactic_equivalent(rewrite_nnf(parse("!G(f)")), parse("True U !f")) True >>> syntactic_equivalent(rewrite_nnf(parse("!F(f)")), parse("false R !f")) True >>> syntactic_equivalent(rewrite_nnf(parse("!(a U b)")), parse("!a R !b")) True >>> syntactic_equivalent(rewrite_nnf(parse("!(a R b)")), parse("!a U !b")) True >>> syntactic_equivalent(rewrite_nnf(parse("!(X a)")), parse("X !a")) True >>> syntactic_equivalent(rewrite_nnf(parse("!(a W b)")), parse("(!a R !b) && (True U !a)")) True """ while node.type == Type.BoolNot and node.left.type == Type.BoolNot: replace(node, node.left.left) if node.type == Type.BoolNot: inner = node.left if inner.type == Type.Identifier or inner.type == Type.Constant: pass elif inner.type == Type.BoolAnd: node.type = Type.BoolOr node.children = [BoolNot(inner.left), BoolNot(inner.right)] elif inner.type == Type.BoolOr: node.type = Type.BoolAnd node.children = [BoolNot(inner.left), BoolNot(inner.right)] elif inner.type == Type.Implies: node.type = Type.BoolAnd node.children = [inner.left, BoolNot(inner.right)] elif inner.type == Type.Equivalent: node.type = Type.BoolAnd node.children = [ BoolOr(BoolNot(inner.left), BoolNot(inner.right)), BoolOr(inner.left, inner.right) ] elif inner.type == Type.Globally: node.type = Type.Until node.children = [CTrue(), BoolNot(inner.left)] elif inner.type == Type.Finally: node.type = Type.Release node.children = [CFalse(), BoolNot(inner.left)] elif inner.type == Type.Until: node.type = Type.Release node.children = [BoolNot(inner.left), BoolNot(inner.right)] elif inner.type == Type.Release: node.type = Type.Until node.children = [BoolNot(inner.left), BoolNot(inner.right)] elif inner.type == Type.Next: node.type = Type.Next node.children = [BoolNot(inner.left)] elif inner.type == Type.WeakUntil: node.type = Type.BoolAnd node.children = [ Release(BoolNot(inner.left), BoolNot(inner.right)), Until(CTrue(), BoolNot(inner.left)) ] for n in node.children: rewrite_nnf(n) return node