Example #1
0
def compute_wp(thy, T, c, Q):
    """Compute the weakest precondition for the given command
    and postcondition. The computation is by case analysis on
    the form of c. Returns the validity theorem.

    """
    if c.head.is_const_name("Assign"):  # Assign a b
        a, b = c.args
        s = Var("s", T)
        P2 = Term.mk_abs(s, Q(function.mk_fun_upd(s, a, b(s).beta_conv())))
        return apply_theorem(thy,
                             "assign_rule",
                             inst={"b": b},
                             concl=Valid(T)(P2, c, Q))
    elif c.head.is_const_name("Seq"):  # Seq c1 c2
        c1, c2 = c.args
        wp1 = compute_wp(thy, T, c2, Q)  # Valid Q' c2 Q
        wp2 = compute_wp(thy, T, c1, wp1.prop.args[0])  # Valid Q'' c1 Q'
        return apply_theorem(thy, "seq_rule", wp2, wp1)
    elif c.head.is_const_name("While"):  # While b I c
        _, I, _ = c.args
        pt = apply_theorem(thy, "while_rule", concl=Valid(T)(I, c, Q))
        pt0 = ProofTerm.assume(pt.assums[0])
        pt1 = vcg(thy, T, pt.assums[1])
        return ProofTerm.implies_elim(pt, pt0, pt1)
    else:
        raise NotImplementedError
Example #2
0
    def get_proof_term(self, thy, goal, *, args=None, prevs=None):
        assert isinstance(prevs,
                          list) and len(prevs) == 1, "rewrite_goal_with_prev"
        pt = prevs[0]

        init_As = goal.hyps
        C = goal.prop
        cv = then_conv(top_sweep_conv(rewr_conv(pt, match_vars=False)),
                       top_conv(beta_conv()))

        eq_th = cv.eval(thy, C)
        new_goal = eq_th.prop.rhs

        new_As = list(set(eq_th.hyps) - set(init_As))
        new_As_pts = [ProofTerm.sorry(Thm(init_As, A)) for A in new_As]
        if Term.is_equals(new_goal) and new_goal.lhs == new_goal.rhs:
            return ProofTermDeriv('rewrite_goal_with_prev',
                                  thy,
                                  args=C,
                                  prevs=[pt] + new_As_pts)
        else:
            new_goal_pts = ProofTerm.sorry(Thm(init_As, new_goal))
            return ProofTermDeriv('rewrite_goal_with_prev',
                                  thy,
                                  args=C,
                                  prevs=[pt, new_goal_pts] + new_As_pts)
Example #3
0
    def get_proof_term(self, thy, args, pts):
        dct = dict()

        def traverse_A(pt):
            # Given proof term showing a conjunction, put proof terms
            # showing atoms of the conjunction in dct.
            if is_conj(pt.prop):
                traverse_A(apply_theorem(thy, 'conjD1', pt))
                traverse_A(apply_theorem(thy, 'conjD2', pt))
            else:
                dct[pt.prop] = pt

        def traverse_C(t):
            # Return proof term with conclusion t
            if is_conj(t):
                left = traverse_C(t.arg1)
                right = traverse_C(t.arg)
                return apply_theorem(thy, 'conjI', left, right)
            else:
                assert t in dct.keys(), 'imp_conj_macro'
                return dct[t]

        As, C = args.strip_implies()
        assert len(As) == 1, 'imp_conj_macro'
        A = As[0]

        traverse_A(ProofTerm.assume(A))
        concl = traverse_C(C)
        return ProofTerm.implies_intr(A, concl)
Example #4
0
    def get_proof_term(self, thy, goal, *, args=None, prevs=None):
        assert isinstance(prevs, list) and len(prevs) == 1, "apply_prev"
        pt = prevs[0]

        assert pt.concl == goal.prop, "apply_prev"
        As_pts = [ProofTerm.sorry(Thm(goal.hyps, A)) for A in pt.assums]
        return ProofTerm.implies_elim(pt, *As_pts)
Example #5
0
    def get_proof_term(self, thy, args, pts):
        As, C = args.strip_implies()
        assert C in As, "trivial_macro"

        pt = ProofTerm.assume(C)
        for A in reversed(As):
            pt = ProofTerm.implies_intr(A, pt)
        return pt
Example #6
0
 def get_proof_term(self, thy, args, prevs):
     assert len(prevs) >= 2, "intros_macro"
     pt, intros = prevs[-1], prevs[:-1]
     for intro in reversed(intros):
         if intro.th.is_reflexive():
             pt = ProofTerm.forall_intr(intro.prop.rhs, pt)
         else:
             pt = ProofTerm.implies_intr(intro.prop, pt)
     return pt
Example #7
0
    def get_proof_term(self, thy, goal, *, args=None, prevs=None):
        assert isinstance(args, Term), "cases"

        As = goal.hyps
        C = goal.prop
        goal1 = ProofTerm.sorry(Thm(goal.hyps, Term.mk_implies(args, C)))
        goal2 = ProofTerm.sorry(
            Thm(goal.hyps, Term.mk_implies(logic.neg(args), C)))
        return apply_theorem(thy, 'classical_cases', goal1, goal2)
Example #8
0
    def testExport(self):
        """Basic case."""
        pt1 = ProofTerm.assume(Term.mk_equals(x, y))
        pt2 = ProofTerm.assume(Term.mk_equals(y, z))
        pt3 = ProofTerm.transitive(pt1, pt2)

        prf = pt3.export()
        self.assertEqual(len(prf.items), 3)
        self.assertEqual(thy.check_proof(prf), pt3.th)
Example #9
0
    def testExport2(self):
        """Repeated theorems."""
        pt1 = ProofTerm.assume(Term.mk_equals(x, y))
        pt2 = ProofTerm.reflexive(f)
        pt3 = ProofTerm.combination(pt2, pt1)  # f x = f y
        pt4 = ProofTerm.combination(pt3, pt1)  # f x x = f y y

        prf = pt4.export()
        self.assertEqual(len(prf.items), 4)
        self.assertEqual(thy.check_proof(prf), pt4.th)
Example #10
0
    def get_proof_term(self, thy, goal, pts):
        assert len(pts) == 0, "nat_norm_macro"
        assert goal.is_equals(), "nat_norm_macro: goal is not an equality."

        t1, t2 = goal.args
        pt1 = norm_full().get_proof_term(thy, t1)
        pt2 = norm_full().get_proof_term(thy, t2)
        assert pt1.prop.rhs == pt2.prop.rhs, "nat_norm_macro: normalization is not equal."

        return ProofTerm.transitive(pt1, ProofTerm.symmetric(pt2))
Example #11
0
    def get_proof_term(self, thy, goal, *, args=None, prevs=None):
        if args is None:
            var_names = []
        else:
            var_names = args

        vars, As, C = logic.strip_all_implies(goal.prop, var_names)

        pt = ProofTerm.sorry(Thm(list(goal.hyps) + As, C))
        ptAs = [ProofTerm.assume(A) for A in As]
        ptVars = [ProofTerm.variable(var.name, var.T) for var in vars]
        return ProofTermDeriv('intros', thy, None, ptVars + ptAs + [pt])
Example #12
0
    def testExport3(self):
        """Case with atoms."""
        pt1 = ProofTerm.atom(0, Thm.mk_equals(x, y))
        pt2 = ProofTerm.atom(1, Thm.mk_equals(y, z))
        pt3 = ProofTerm.transitive(pt1, pt2)

        prf = Proof()
        prf.add_item(0, rule="sorry", th=Thm.mk_equals(x, y))
        prf.add_item(1, rule="sorry", th=Thm.mk_equals(y, z))
        pt3.export(prf=prf)

        self.assertEqual(thy.check_proof(prf), Thm.mk_equals(x, z))
Example #13
0
def get_encode_proof(th):
    """Given resulting theorem for an encoding, obtain the proof
    of the theorem.

    The theorem is structured as follows:

    Each of the assumptions, except the last, is an equality, where
    the right side is either an atom or a logical operation between
    atoms. We call these assumptions As.

    The last assumption is the original formula. We call it F.

    The conclusion is in CNF. Each clause except the last is an
    expansion of one of As. The last clause is obtained by performing
    substitutions of As on F.

    """
    As, F = th.hyps[:-1], th.hyps[-1]

    # Obtain the assumptions
    ptAs = [ProofTerm.assume(A) for A in As]
    ptF = ProofTerm.assume(F)

    # Obtain the expansion of each As to a non-atomic term.
    pts = []
    for ptA in ptAs:
        rhs = ptA.prop.rhs
        if logic.is_conj(rhs):
            pts.append(ptA.on_prop(thy, rewr_conv("encode_conj")))
        elif logic.is_disj(rhs):
            pts.append(ptA.on_prop(thy, rewr_conv("encode_disj")))
        elif rhs.is_implies():
            pts.append(ptA.on_prop(thy, rewr_conv("encode_imp")))
        elif rhs.is_equals():
            pts.append(ptA.on_prop(thy, rewr_conv("encode_eq")))
        elif logic.is_neg(rhs):
            pts.append(ptA.on_prop(thy, rewr_conv("encode_not")))

    # Obtain the rewrite of the original formula.
    cvs = [
        top_conv(rewr_conv(ProofTerm.symmetric(ptA), match_vars=False))
        for ptA in ptAs
    ]
    cv = every_conv(*cvs)

    pts.append(ptF.on_prop(thy, cv))

    pt = pts[0]
    for pt2 in pts[1:]:
        pt = logic_macro.apply_theorem(thy, 'conjI', pt, pt2)

    return pt.on_prop(thy, logic.norm_conj_assoc())
Example #14
0
    def get_proof_term(self, thy, t):
        if t.ty != Term.COMB:
            raise ConvException()
        pt1 = self.cv1.get_proof_term(thy, t.fun)
        pt2 = self.cv2.get_proof_term(thy, t.arg)

        # Obtain some savings if one of pt1 and pt2 is reflexivity:
        if pt1.th.is_reflexive():
            return ProofTerm.arg_combination(thy, pt1.prop.rhs, pt2)
        elif pt2.th.is_reflexive():
            return ProofTerm.fun_combination(thy, pt2.prop.rhs, pt1)
        else:
            return ProofTerm.combination(pt1, pt2)
Example #15
0
 def testInduct(self):
     n = Var('n', natT)
     goal = Thm([], Term.mk_equals(plus(n, zero), n))
     induct_tac = tactic.var_induct()
     pt = induct_tac.get_proof_term(thy, ProofTerm.sorry(goal), args=('nat_induct', n))
     prf = pt.export()
     self.assertEqual(thy.check_proof(prf), goal)
Example #16
0
 def testRule(self):
     A = Var('A', boolT)
     B = Var('B', boolT)
     goal = Thm([], conj(B, A))
     pt = tactic.rule().get_proof_term(thy, ProofTerm.sorry(goal), args='conjI')
     prf = pt.export()
     self.assertEqual(thy.check_proof(prf), goal)
Example #17
0
def apply_theorem(thy, th_name, *pts, concl=None, tyinst=None, inst=None):
    """Wrapper for apply_theorem and apply_theorem_for macros.

    The function takes optional arguments concl, tyinst, and inst. Matching
    always starts with tyinst and inst. If conclusion is specified, it is
    matched next. Finally, the assumptions are matched.

    """
    if concl is None and tyinst is None and inst is None:
        # Normal case, can use apply_theorem
        return ProofTermDeriv("apply_theorem", thy, th_name, pts)
    else:
        pt = ProofTerm.theorem(thy, th_name)
        if tyinst is None:
            tyinst = dict()
        if inst is None:
            inst = dict()
        if concl is not None:
            matcher.first_order_match_incr(pt.concl, concl, (tyinst, inst))
        pt = ProofTermDeriv("apply_theorem_for", thy, (th_name, tyinst, inst),
                            pts)
        if pt.prop.beta_norm() == pt.prop:
            return pt
        else:
            return ProofTermDeriv("beta_norm", thy, None, [pt])
Example #18
0
 def testRewrite(self):
     n = Var('n', natT)
     goal = Thm.mk_equals(plus(zero, n), n)
     rewrite_tac = tactic.rewrite()
     pt = rewrite_tac.get_proof_term(thy, ProofTerm.sorry(goal), args='plus_def_1')
     prf = pt.export()
     self.assertEqual(thy.check_proof(prf), goal)
Example #19
0
 def testRule4(self):
     n = Var('n', natT)
     goal = Thm([], Term.mk_equals(plus(n, zero), n))
     inst = {'P': Term.mk_abs(n, goal.prop), 'x': n}
     pt = tactic.rule().get_proof_term(thy, ProofTerm.sorry(goal), args=('nat_induct', ({}, inst)))
     prf = pt.export()
     self.assertEqual(thy.check_proof(prf), goal)
Example #20
0
 def testRule3(self):
     A = Var('A', boolT)
     B = Var('B', boolT)
     goal = Thm([], disj(B, A))
     prev = ProofTermAtom(0, Thm.assume(B))
     pt = tactic.rule().get_proof_term(thy, ProofTerm.sorry(goal), args='disjI1', prevs=[prev])
     prf = pt.export(prefix=(1,), subproof=False)
     self.assertEqual(prf.items[0], ProofItem(1, 'apply_theorem_for', args=('disjI1', {}, {'A': B, 'B': A}), prevs=[0]))
Example #21
0
 def testRule2(self):
     A = Var('A', boolT)
     B = Var('B', boolT)
     goal = Thm([], disj(B, A))
     prev = ProofTermAtom(0, Thm.assume(disj(A, B)))
     pt = tactic.rule().get_proof_term(thy, ProofTerm.sorry(goal), args='disjE', prevs=[prev])
     prf = pt.export(prefix=(1,), subproof=False)
     self.assertEqual(prf.items[2], ProofItem(3, 'apply_theorem', args='disjE', prevs=[0, 1, 2]))
Example #22
0
    def get_proof_term(self, thy, args, pts):
        assert len(pts) == 1 and isinstance(
            args, str), "rewrite_fact_macro: signature"

        th_name = args
        eq_pt = ProofTerm.theorem(thy, th_name)
        cv = then_conv(top_sweep_conv(rewr_conv(eq_pt)), top_conv(beta_conv()))
        return pts[0].on_prop(thy, cv)
Example #23
0
    def get_proof_term(self, thy, t):
        if t.ty != Term.ABS:
            raise ConvException()

        # Find a new variable x and substitute for body
        v = Var(t.var_name, t.var_T)
        t2 = t.subst_bound(v)
        return ProofTerm.abstraction(self.cv.get_proof_term(thy, t2), v)
Example #24
0
def vcg_solve(thy, goal):
    """Compute the verification conditions for a hoare triple, then
    solves the verification conditions using SMT.
    
    """
    pt = ProofTermDeriv("vcg", thy, goal, [])
    vc_pt = [ProofTermDeriv("z3", thy, vc, []) for vc in pt.assums]
    return ProofTerm.implies_elim(pt, *vc_pt)
Example #25
0
 def testCases(self):
     A = Var('A', boolT)
     B = Var('B', boolT)
     C = Var('C', boolT)
     cases_tac = tactic.cases()
     pt = cases_tac.get_proof_term(thy, ProofTerm.sorry(Thm([B], C)), args=A)
     prf = pt.export()
     self.assertEqual(thy.check_proof(prf), Thm([B], C))
Example #26
0
    def get_proof_term(self, thy, t):
        if isinstance(self.pt, str):
            self.pt = ProofTerm.theorem(thy, self.pt)
            if self.sym:
                self.pt = ProofTerm.symmetric(self.pt)

        # Deconstruct th into assumptions and conclusion
        As, C = self.pt.assums, self.pt.concl
        assert Term.is_equals(C), "rewr_conv: theorem is not an equality."

        tyinst, inst = dict(), dict()

        if self.match_vars:
            try:
                matcher.first_order_match_incr(C.lhs, t, (tyinst, inst))
            except matcher.MatchException:
                raise ConvException()
        elif C.lhs != t:
            raise ConvException()

        pt = ProofTerm.substitution(inst,
                                    ProofTerm.subst_type(tyinst, self.pt))
        if self.conds is not None:
            pt = ProofTerm.implies_elim(pt, *self.conds)

        As = pt.assums
        for A in As:
            pt = ProofTerm.implies_elim(pt, ProofTerm.assume(A))
        return pt
Example #27
0
 def get_proof_term(self, thy, goal, pts):
     f, (P, c, Q) = goal.strip_comb()
     T = Q.get_type().domain_type()
     pt = vcg(thy, T, goal)
     for A in reversed(pt.hyps):
         pt = ProofTerm.implies_intr(A, pt)
     return pt.on_assums(thy, rewr_conv("Entail_def"),
                         top_conv(beta_conv()),
                         top_conv(function.fun_upd_eval_conv()))
Example #28
0
 def testIntros(self):
     Ta = TVar('a')
     x = Var('x', Ta)
     P = Var('P', TFun(Ta, boolT))
     Q = Var('Q', TFun(Ta, boolT))
     goal = Thm([], Term.mk_all(x, Term.mk_implies(P(x), Q(x))))
     intros_tac = tactic.intros()
     pt = intros_tac.get_proof_term(thy, ProofTerm.sorry(goal), args=['x'])
     prf = pt.export()
     self.assertEqual(thy.check_proof(prf), goal)
Example #29
0
    def apply_to_pt(self, thy, pt, pos=None):
        """Apply to the given proof term."""

        # First, handle some position instructions
        if pos == "arg":
            return arg_conv(self).apply_to_pt(thy, pt)
        elif pos == "assums":
            return assums_conv(self).apply_to_pt(thy, pt)

        eq_pt = self.get_proof_term(thy, pt.prop)
        return ProofTerm.equal_elim(eq_pt, pt)
Example #30
0
 def testRewrite2(self):
     Ta = TVar("a")
     a = Var("a", Ta)
     b = Var("b", Ta)
     eq_a = Term.mk_equals(a, a)
     goal = Thm.mk_equals(mk_if(eq_a, b, a), b)
     rewrite_tac = tactic.rewrite()
     pt = rewrite_tac.get_proof_term(thy, ProofTerm.sorry(goal), args='if_P')
     prf = pt.export()
     self.assertEqual(prf.items[0], ProofItem(0, 'sorry', th=Thm.mk_equals(a, a)))
     self.assertEqual(thy.check_proof(prf), goal)