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)
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())
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
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
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)
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
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)
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])
def get_proof(self): invC = Const("inv", TFun(gcl.stateT, boolT)) transC = Const("trans", TFun(gcl.stateT, gcl.stateT, boolT)) s1 = Var("s1", gcl.stateT) s2 = Var("s2", gcl.stateT) prop = Thm.mk_implies(invC(s1), transC(s1, s2), invC(s2)) # print(printer.print_thm(self.thy, prop)) trans_pt = ProofTerm.assume(transC(s1, s2)) # print(printer.print_thm(self.thy, trans_pt.th)) P = Term.mk_implies(invC(s1), invC(s2)) ind_pt = apply_theorem(self.thy, "trans_cases", inst={ "a1": s1, "a2": s2, "P": P }) # print(printer.print_thm(self.thy, ind_pt.th)) ind_As, ind_C = ind_pt.prop.strip_implies() for ind_A in ind_As[1:-1]: # print("ind_A: ", printer.print_term(self.thy, ind_A)) vars, As, C = logic.strip_all_implies(ind_A, ["s", "k"]) # for A in As: # print("A: ", printer.print_term(self.thy, A)) # print("C: ", printer.print_term(self.thy, C)) eq1 = ProofTerm.assume(As[0]) eq2 = ProofTerm.assume(As[1]) guard = ProofTerm.assume(As[2]) inv_pre = ProofTerm.assume(As[3]).on_arg(self.thy, rewr_conv(eq1)) \ .on_prop(self.thy, rewr_conv("inv_def")) C_goal = ProofTerm.assume(C).on_arg(self.thy, rewr_conv(eq2)) \ .on_prop(self.thy, rewr_conv("inv_def"))
def vcg(thy, T, goal): """Compute the verification conditions for the goal.""" P, c, Q = goal.args pt = compute_wp(thy, T, c, Q) entail_P = ProofTerm.assume(Entail(T)(P, pt.prop.args[0])) return apply_theorem(thy, "pre_rule", entail_P, pt)