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 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 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 forall_intr(x, th): """Derivation rule FORALL_INTR: A |- t ------------ A |- !x. t where x does not occur in A. """ if any(hyp.occurs_var(x) for hyp in th.hyps): raise InvalidDerivationException("forall_intr") elif x.ty != Term.VAR: raise InvalidDerivationException("forall_intr") else: return Thm(th.hyps, Term.mk_all(x, th.prop))
def testAllConjWithMacro(self): """Proof of (!x. A x & B x) --> (!x. A x) & (!x. B x), using macros.""" 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, "apply_theorem", args="conjD1", prevs=[1]) prf.add_item(3, "forall_intr", args=x, prevs=[2]) prf.add_item(4, "apply_theorem", args="conjD2", prevs=[1]) prf.add_item(5, "forall_intr", args=x, prevs=[4]) prf.add_item(6, "apply_theorem", args="conjI", prevs=[3, 5]) prf.add_item(7, "implies_intr", args=all_conj, prevs=[6]) th = Thm.mk_implies(all_conj, conj_all) self.assertEqual(thy.check_proof(prf), th)
def add_induct_predicate(name, T, props): """Add the given inductive predicate. The inductive predicate is specified by the name and type of the predicate, and a list of introduction rules, where each introduction rule must be given a name. """ exts = TheoryExtension() exts.add_extension(AxConstant(name, T)) for th_name, prop in props: exts.add_extension(Theorem(th_name, Thm([], prop))) exts.add_extension(Attribute(th_name, "hint_backward")) # Case rule Targs, _ = T.strip_type() vars = [] for i, Targ in enumerate(Targs): vars.append(Var("_a" + str(i + 1), Targ)) P = Var("P", boolT) pred = Const(name, T) assum0 = pred(*vars) assums = [] for th_name, prop in props: As, C = prop.strip_implies() assert C.head == pred, "add_induct_predicate: wrong form of prop." eq_assums = [ Term.mk_equals(var, arg) for var, arg in zip(vars, C.args) ] assum = Term.mk_implies(*(eq_assums + As), P) prop_vars = term.get_vars(prop) for var in reversed(term.get_vars(prop)): assum = Term.mk_all(var, assum) assums.append(assum) prop = Term.mk_implies(*([assum0] + assums + [P])) exts.add_extension(Theorem(name + "_cases", Thm([], prop))) return exts
def add_induct_type(name, targs, constrs): """Add the given inductive type to the theory. The inductive type is specified by name, arity (as list of default names of type arguments), and a list of constructors (triple consisting of name of the constant, type of the constant, and a list of suggested names of the arguments). For example, the natural numbers is specified by: (nat, [], [(0, nat, []), (Suc, nat => nat, ["n"])]). List type is specified by: (list, ["a"], [(nil, 'a list, []), (cons, 'a => 'a list => 'a list, ["x", "xs"])]). """ exts = TheoryExtension() # Add to type and term signature. exts.add_extension(AxType(name, len(targs))) for cname, cT, _ in constrs: exts.add_extension(AxConstant(cname, cT)) # Add non-equality theorems. for (cname1, cT1, vars1), (cname2, cT2, vars2) in itertools.combinations(constrs, 2): # For each A x_1 ... x_m and B y_1 ... y_n, get the theorem # ~ A x_1 ... x_m = B y_1 ... y_n. argT1, _ = cT1.strip_type() argT2, _ = cT2.strip_type() lhs_vars = [Var(nm, T) for nm, T in zip(vars1, argT1)] rhs_vars = [Var(nm, T) for nm, T in zip(vars2, argT2)] A = Const(cname1, cT1) B = Const(cname2, cT2) lhs = A(*lhs_vars) rhs = B(*rhs_vars) neq = logic.neg(Term.mk_equals(lhs, rhs)) th_name = name + "_" + cname1 + "_" + cname2 + "_neq" exts.add_extension(Theorem(th_name, Thm([], neq))) # Add injectivity theorems. for cname, cT, vars in constrs: # For each A x_1 ... x_m with m > 0, get the theorem # A x_1 ... x_m = A x_1' ... x_m' --> x_1 = x_1' & ... & x_m = x_m' if vars: argT, _ = cT.strip_type() lhs_vars = [Var(nm, T) for nm, T in zip(vars, argT)] rhs_vars = [Var(nm + "'", T) for nm, T in zip(vars, argT)] A = Const(cname, cT) assum = Term.mk_equals(A(*lhs_vars), A(*rhs_vars)) concls = [ Term.mk_equals(var1, var2) for var1, var2 in zip(lhs_vars, rhs_vars) ] concl = logic.mk_conj(*concls) if len(concls) > 1 else concls[0] th_name = name + "_" + cname + "_inject" exts.add_extension(Theorem(th_name, Thm.mk_implies(assum, concl))) # Add the inductive theorem. tvars = [TVar(targ) for targ in targs] T = Type(name, *tvars) var_P = Var("P", TFun(T, boolT)) ind_assums = [] for cname, cT, vars in constrs: A = Const(cname, cT) argT, _ = cT.strip_type() args = [Var(nm, T2) for nm, T2 in zip(vars, argT)] C = var_P(A(*args)) As = [var_P(Var(nm, T2)) for nm, T2 in zip(vars, argT) if T2 == T] ind_assum = Term.mk_implies(*(As + [C])) for arg in reversed(args): ind_assum = Term.mk_all(arg, ind_assum) ind_assums.append(ind_assum) ind_concl = var_P(Var("x", T)) th_name = name + "_induct" exts.add_extension( Theorem(th_name, Thm.mk_implies(*(ind_assums + [ind_concl])))) exts.add_extension(Attribute(th_name, "var_induct")) return exts
def testForallElimFail2(self): P = Var("P", TFun(Ta, boolT)) th = Thm([], Term.mk_all(x, P(x))) self.assertRaises(InvalidDerivationException, Thm.forall_elim, A, th)
def testForallElim(self): P = Var("P", TFun(Ta, boolT)) th = Thm([], Term.mk_all(x, P(x))) self.assertEqual(Thm.forall_elim(y, th), Thm([], P(y)))
def testForallIntr2(self): """Also OK if the variable does not appear in theorem.""" th = Thm.mk_equals(x, y) t_res = Term.mk_all(z, Term.mk_equals(x, y)) self.assertEqual(Thm.forall_intr(z, th), Thm([], t_res))
def testForallIntr(self): th = Thm.mk_equals(x, y) t_res = Term.mk_all(x, Term.mk_equals(x, y)) self.assertEqual(Thm.forall_intr(x, th), Thm([], t_res))