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)
def testAllConj(self): """Proof of (!x. A x & B x) --> (!x. A x) & (!x. B x).""" thy = basic.load_theory('logic_base') Ta = TVar("a") A = Var("A", TFun(Ta, boolT)) B = Var("B", TFun(Ta, boolT)) x = Var("x", Ta) all_conj = Term.mk_all(x, logic.mk_conj(A(x), B(x))) all_A = Term.mk_all(x, A(x)) all_B = Term.mk_all(x, B(x)) conj_all = logic.mk_conj(all_A, all_B) prf = Proof(all_conj) prf.add_item(1, "forall_elim", args=x, prevs=[0]) prf.add_item(2, "theorem", args="conjD1") prf.add_item(3, "substitution", args={"A": A(x), "B": B(x)}, prevs=[2]) prf.add_item(4, "implies_elim", prevs=[3, 1]) prf.add_item(5, "forall_intr", args=x, prevs=[4]) prf.add_item(6, "theorem", args="conjD2") prf.add_item(7, "substitution", args={"A": A(x), "B": B(x)}, prevs=[6]) prf.add_item(8, "implies_elim", prevs=[7, 1]) prf.add_item(9, "forall_intr", args=x, prevs=[8]) prf.add_item(10, "theorem", args="conjI") prf.add_item(11, "substitution", args={ "A": all_A, "B": all_B }, prevs=[10]) prf.add_item(12, "implies_elim", prevs=[11, 5]) prf.add_item(13, "implies_elim", prevs=[12, 9]) prf.add_item(14, "implies_intr", args=all_conj, prevs=[13]) th = Thm.mk_implies(all_conj, conj_all) self.assertEqual(thy.check_proof(prf), th)
def testInferType(self): test_data = [ # A1 --> A2 (Const("implies", None)(Var("A1", None), Var("A2", None)), Term.mk_implies(Var("A1", boolT), Var("A2", boolT))), # A1 = A2 (Const("equals", None)(Var("A1", boolT), Var("A2", None)), Term.mk_equals(Var("A1", boolT), Var("A2", boolT))), # a = b (Const("equals", None)(Var("a", None), Var("b", None)), Const("equals", TFun(Ta, Ta, boolT))(Var("a", Ta), Var("b", Ta))), # %x. P x (Abs("x", None, Var("P", None)(Bound(0))), Abs("x", Ta, Var("P", TFun(Ta, boolT))(Bound(0)))), # %x y. x = y (Abs("x", Ta, Abs("y", None, Const("equals", None)(Bound(1), Bound(0)))), Abs( "x", Ta, Abs("y", Ta, Const("equals", TFun(Ta, Ta, boolT))(Bound(1), Bound(0))))), # [a] (Const("cons", None)(Var("a", None), Const("nil", None)), list.cons(Ta)(Var("a", Ta), Const("nil", listT(Ta)))), ] for t, res in test_data: self.assertEqual(type_infer(thy, ctxt, t), res)
def testInferPrintedType(self): t = Const("nil", listT(Ta)) infer_printed_type(thy, t) self.assertTrue(hasattr(t, "print_type")) t = list.cons(Ta)(Var("a", Ta)) infer_printed_type(thy, t) self.assertFalse(hasattr(t.fun, "print_type")) t = Term.mk_equals(Const("nil", listT(Ta)), Const("nil", listT(Ta))) infer_printed_type(thy, t) self.assertFalse(hasattr(t.fun.fun, "print_type")) self.assertTrue(hasattr(t.arg1, "print_type")) self.assertFalse(hasattr(t.arg, "print_type")) t = Term.mk_equals(list.mk_append(list.nil(Ta), list.nil(Ta)), list.nil(Ta)) infer_printed_type(thy, t) self.assertTrue(hasattr(t.arg1.arg1, "print_type")) self.assertFalse(hasattr(t.arg1.arg, "print_type")) self.assertFalse(hasattr(t.arg, "print_type")) t = Term.mk_abs(Var("x", Ta), Term.mk_equals(Var("x", Ta), Var("x", Ta))) infer_printed_type(thy, t)
def testApplyInduction(self): thy = basic.load_theory('nat') n = Var("n", nat.natT) state = ProofState.init_state(thy, [n], [], Term.mk_equals(nat.plus(n, nat.zero), n)) state.apply_induction(0, "nat_induct", "n") self.assertEqual(state.check_proof(), Thm([], Term.mk_equals(nat.plus(n, nat.zero), n))) self.assertEqual(len(state.prf.items), 3)
def testSubstitution(self): x_eq_y = Term.mk_equals(x, y) th = Thm([x_eq_y], x_eq_y) y_eq_x = Term.mk_equals(y, x) self.assertEqual(Thm.substitution({ "x": y, "y": x }, th), Thm([y_eq_x], y_eq_x))
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)
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 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)
def testRewriteGoalWithAssum(self): Ta = TVar("a") a = Var("a", Ta) b = Var("b", Ta) eq_a = Term.mk_equals(a, a) if_t = logic.mk_if(eq_a, b, a) state = ProofState.init_state(thy, [a, b], [], Term.mk_equals(if_t, b)) state.rewrite_goal(0, "if_P") state.set_line(0, "reflexive", args=a) self.assertEqual(state.check_proof(no_gaps=True), Thm.mk_equals(if_t, b))
def testIntroduction3(self): Ta = TVar("a") A = Var("A", TFun(Ta, boolT)) B = Var("B", TFun(Ta, boolT)) x = Var("x", Ta) state = ProofState.init_state(thy, [A, B], [], Term.mk_all(x, imp(A(x), B(x)))) state.introduction(0, ["x"]) self.assertEqual(state.check_proof(), Thm([], Term.mk_all(x, imp(A(x), B(x))))) self.assertEqual(len(state.prf.items), 1) self.assertEqual(len(state.prf.items[0].subproof.items), 4)
def testCheckTerm(self): test_data = [ x, Term.mk_equals(x, y), Term.mk_equals(f, f), Term.mk_implies(A, B), Abs("x", Ta, Term.mk_equals(x, y)), ] for t in test_data: self.assertEqual(thy.check_term(t), None)
def run_test(self, thy_name, pat, t, *, vars=None, svars=None, tyinst=None, inst=None, failed=None): context.set_context(thy_name, vars=vars, svars=svars) pat, t = Term(pat), Term(t) inst = Inst((nm, Term(s)) for nm, s in inst.items()) if inst is not None else Inst() if tyinst is not None: inst.tyinst = TyInst((nm, Type(s)) for nm, s in tyinst.items()) if failed is not None: self.assertRaises(failed, first_order_match, pat, t) return self.assertEqual(first_order_match(pat, t), inst)
def testRewrConvWithAssum(self): x = Const("x", natT) y = Const("y", natT) x_eq_y = Term.mk_equals(x, y) th = Thm([], Term.mk_implies(x_eq_y, x_eq_y)) cv = arg_conv(rewr_conv(ProofTerm.atom(0, th))) f = Const("f", TFun(natT, natT)) res = Thm([x_eq_y], Term.mk_equals(f(x), f(y))) self.assertEqual(cv.eval(thy, f(x)), res) prf = Proof() prf.add_item(0, "sorry", th=th) cv.get_proof_term(thy, f(x)).export(prf=prf) self.assertEqual(thy.check_proof(prf), res)
def testCheckProof3(self): """Proof of [x = y, y = z] |- f z = f x.""" x_eq_y = Term.mk_equals(x,y) y_eq_z = Term.mk_equals(y,z) prf = Proof(x_eq_y, y_eq_z) prf.add_item(2, "transitive", prevs=[0, 1]) prf.add_item(3, "symmetric", prevs=[2]) prf.add_item(4, "reflexive", args=f) prf.add_item(5, "combination", prevs=[4, 3]) rpt = ProofReport() th = Thm([x_eq_y, y_eq_z], Term.mk_equals(f(z),f(x))) self.assertEqual(thy.check_proof(prf, rpt), th) self.assertEqual(rpt.steps, 6)
def testAbsConv(self): nat0 = Const("zero", natT) nat1 = Const("one", natT) f = Const("f", TFun(natT, natT)) g = Const("g", TFun(natT, natT)) x = Var("x", natT) thy.add_theorem("f_eq_g", eq(f(x), g(x))) t = Term.mk_abs(x, f(x)) cv = abs_conv(rewr_conv("f_eq_g")) res_th = eq(t, Term.mk_abs(x, g(x))) self.assertEqual(cv.eval(thy, t), res_th) prf = cv.get_proof_term(thy, t).export() self.assertEqual(thy.check_proof(prf), res_th)
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)
def testArgCombination(self): thy = basic.load_theory('logic_base') macro = logic_macro.arg_combination_macro() x_eq_y = Term.mk_equals(x, y) fx_eq_fy = Term.mk_equals(f(x), f(y)) th = Thm.assume(x_eq_y) res = Thm([x_eq_y], fx_eq_fy) self.assertEqual(macro.eval(thy, f, [th]), res) prf = Proof(x_eq_y) prf.add_item(1, "arg_combination", args=f, prevs=[0]) rpt = ProofReport() self.assertEqual(thy.check_proof(prf, rpt), res) self.assertEqual(rpt.macros_expand, {"arg_combination"}) self.assertEqual(rpt.prim_steps, 3)
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 testFunCombination(self): thy = basic.load_theory('logic_base') macro = logic_macro.fun_combination_macro() f_eq_g = Term.mk_equals(f, g) fx_eq_gx = Term.mk_equals(f(x), g(x)) th = Thm.assume(f_eq_g) res = Thm([f_eq_g], fx_eq_gx) self.assertEqual(macro.eval(thy, x, [th]), res) prf = Proof(f_eq_g) prf.add_item(1, "fun_combination", args=x, prevs=[0]) rpt = ProofReport() self.assertEqual(thy.check_proof(prf, rpt), res) self.assertEqual(rpt.macros_expand, {"fun_combination"}) self.assertEqual(rpt.prim_steps, 3)
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 mk_exists(x, body): """Given a variable x and a term t possibly depending on x, return the term ?x. t. """ exists_t = Const("exists", TFun(TFun(x.T, boolT), boolT)) return exists_t(Term.mk_abs(x, body))
def testAddZeroRightWithMacro(self): """Proof of n + 0 = n by induction, using macros.""" thy = basic.load_theory('nat') n = Var("n", nat.natT) eq = Term.mk_equals plus = nat.plus zero = nat.zero S = nat.Suc prf = Proof() prf.add_item(0, "reflexive", args=zero) prf.add_item(1, "rewrite_goal", args=("plus_def_1", eq(plus(zero, zero), zero)), prevs=[0]) prf.add_item(2, "assume", args=eq(plus(n, zero), n)) prf.add_item(3, "arg_combination", args=S, prevs=[2]) prf.add_item(4, "rewrite_goal", args=("plus_def_2", eq(plus(S(n), zero), S(n))), prevs=[3]) prf.add_item(5, "implies_intr", args=eq(plus(n, zero), n), prevs=[4]) prf.add_item(6, "forall_intr", args=n, prevs=[5]) prf.add_item(7, "apply_theorem_for", args=("nat_induct", {}, { "P": Term.mk_abs(n, eq(plus(n, zero), n)), "x": n }), prevs=[1, 6]) th = Thm.mk_equals(plus(n, zero), n) self.assertEqual(thy.check_proof(prf), th)
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)
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 search(self, state, id, prevs): cur_th = state.get_proof_item(id).th if cur_th.prop.is_all(): return [] thy = state.thy results = [] for th_name, th in thy.get_data("theorems").items(): if 'hint_rewrite' not in thy.get_attributes(th_name): continue cv = top_conv(rewr_conv(th_name)) th = cv.eval(thy, cur_th.prop) new_goal = th.prop.rhs new_As = list(th.hyps) if cur_th.prop != new_goal: if Term.is_equals(new_goal) and new_goal.lhs == new_goal.rhs: results.append({"theorem": th_name, "_goal": new_As}) else: results.append({ "theorem": th_name, "_goal": [new_goal] + new_As }) return sorted(results, key=lambda d: d['theorem'])
def from_json(cls, json_item): context = list(map(Binding.from_json, json_item['context'])) # FIXME that is weird! if json_item['arity']['type'] == "template": arity = Term.from_json(json_item['arity']['arity']) else: arity = Term.from_json(json_item['arity']['arity']) ind = cls( json_item['name'], context, arity, list( map(MutInductive.Constructor.from_json, json_item['constructors']))) ind.raw_arity = Term.from_json(json_item['arity']['arity']) return ind
def testPrintThmHighlight(self): """Test printing of theorems with highlight.""" # 0, 1, 2, 3 = NORMAL, BOUND, VAR, TVAR A = Var('A', boolT) B = Var('B', boolT) A_to_B = Term.mk_implies(A, B) th = Thm([A, A_to_B], B) res = printer.print_thm(thy, th, highlight=True) self.assertEqual(res, [('A',2),(', ',0),('A',2),(' --> ',0),('B',2),(' ',0),('|-',0),(' ',0),('B',2)])
def get_proof_term(self, thy, goal, *, args=None, prevs=None): th_name, var = args P = Term.mk_abs(var, goal.prop) th = thy.get_theorem(th_name) f, args = th.concl.strip_comb() if len(args) != 1: raise NotImplementedError inst = {f.name: P, args[0].name: var} return rule().get_proof_term(thy, goal, args=(th_name, ({}, inst)))
def solve(t): """Solve the given goal using Z3.""" s = z3.Solver() # First strip foralls from t. while Term.is_all(t): t = t.arg.subst_bound(Var(t.arg.var_name, t.arg.var_T)) s.add(z3.Not(convert(t))) return str(s.check()) == 'unsat'