def testUncheckedExtend(self): """Unchecked extension.""" id_const = Const("id", TFun(Ta,Ta)) id_def = Abs("x", Ta, Bound(0)) exts = [ extension.Constant("id", TFun(Ta, Ta)), extension.Theorem("id_def", Thm([], Eq(id_const, id_def))), extension.Theorem("id.simps", Thm([], Eq(id_const, x))) ] self.assertEqual(theory.thy.unchecked_extend(exts), None) self.assertEqual(theory.thy.get_term_sig("id"), TFun(Ta, Ta)) self.assertEqual(theory.get_theorem("id_def", svar=False), Thm([], Eq(id_const, id_def))) self.assertEqual(theory.get_theorem("id.simps", svar=False), Thm([], Eq(id_const, x)))
def get_proof_term(self, args, pts): if self.with_inst: name, inst = args else: name = args inst = Inst() th = theory.get_theorem(name) As, C = th.prop.strip_implies() assert len(pts) <= len(As), "apply_theorem: too many prevs." # First attempt to match type variables svars = th.prop.get_svars() for v in svars: if v.name in inst: v.T.match_incr(inst[v.name].get_type(), inst.tyinst) pats = As[:len(pts)] ts = [pt.prop for pt in pts] inst = matcher.first_order_match_list(pats, ts, inst) pt = ProofTerm.theorem(name) pt = pt.subst_type(inst.tyinst).substitution(inst) if pt.prop.beta_norm() != pt.prop: pt = pt.on_prop(beta_norm_conv()) pt = pt.implies_elim(*pts) assert len(pt.prop.get_stvars()) == 0, "apply_theorem: unmatched type variables." vars = pt.prop.get_svars() for v in reversed(vars): pt = pt.forall_intr(v) return pt
def __init__(self, rule, args, prevs=None, th=None): typecheck.checkinstance('ProofTerm', rule, str) self.rule = rule if prevs is None: prevs = [] prev_ths = [prev.th for prev in prevs] if rule == 'atom': assert th is not None, "ProofTerm: must provide th for atom." self.th = th elif rule == 'sorry': assert th is not None, "ProofTerm: must provide th for sorry." self.th = th elif rule == 'variable': nm, T = args self.th = Thm.mk_VAR(Var(nm, T)) elif rule == 'theorem': self.th = theory.get_theorem(args) elif rule in primitive_deriv: rule_fun, _ = primitive_deriv[rule] self.th = rule_fun(*prev_ths) if args is None else rule_fun(args, *prev_ths) else: macro = theory.get_macro(rule) if th is None: self.th = macro.eval(args, prev_ths) else: self.th = th self.args = args self.prevs = prevs if self.rule == 'sorry': self.gaps = [self.th] else: self.gaps = list(set(sum([prev.gaps for prev in self.prevs], [])))
def get_proof_term(self, goal): th = theory.get_theorem(self.th_name) assum = th.assums[0] cond = self.cond if cond is None: # Find cond by matching with goal.hyps one by one for hyp in goal.hyps: try: inst = matcher.first_order_match(th.assums[0], hyp, self.inst) cond = hyp break except matcher.MatchException: pass if cond is None: raise TacticException('elim: cannot match assumption') try: inst = matcher.first_order_match(th.concl, goal.prop, inst) except matcher.MatchException: raise TacticException('elim: matching failed') if any(v.name not in inst for v in th.prop.get_svars()): raise TacticException('elim: not all variables are matched') pt = ProofTerm.theorem(self.th_name).substitution(inst).on_prop( beta_norm_conv()) pt = pt.implies_elim(ProofTerm.assume(cond)) for assum in pt.assums: pt = pt.implies_elim(ProofTerm.sorry(Thm(goal.hyps, assum))) return pt
def eval(self, args, prevs): if self.with_inst: name, inst = args else: name = args inst = Inst() th = theory.get_theorem(name) As, C = th.prop.strip_implies() assert len(prevs) <= len(As), "apply_theorem: too many prevs." # First attempt to match type variables svars = th.prop.get_svars() for v in svars: if v.name in inst: v.T.match_incr(inst[v.name].get_type(), inst.tyinst) pats = As[:len(prevs)] ts = [prev_th.prop for prev_th in prevs] inst = matcher.first_order_match_list(pats, ts, inst) As, C = th.prop.subst_norm(inst).strip_implies() new_prop = Implies(*(As[len(prevs):] + [C])) prev_hyps = sum([prev.hyps for prev in prevs], ()) th = Thm(th.hyps + prev_hyps, new_prop) assert len(new_prop.get_stvars()) == 0, "apply_theorem: unmatched type variables." vars = new_prop.get_svars() for v in reversed(vars): th = Thm.forall_intr(v, th) return th
def testCheckedExtend(self): """Checked extension: adding an axiom.""" id_simps = Eq(Comb(Const("id", TFun(Ta,Ta)), x), x) exts = [extension.Theorem("id.simps", Thm([], id_simps))] ext_report = theory.thy.checked_extend(exts) self.assertEqual(theory.get_theorem("id.simps", svar=False), Thm([], id_simps)) self.assertEqual(ext_report.get_axioms(), [("id.simps", Thm([], id_simps))])
def get_proof_term(self, goal, args, prevs): assert isinstance(args, str) and len(prevs) == 1, "resolve: type" th_name = args th = theory.get_theorem(th_name) assert th.prop.is_not(), "resolve: prop is not a negation" # Checking that the theorem matches the fact is done here. return ProofTerm('resolve_theorem', (args, goal.prop), prevs)
def get_proof_term(self, goal, *, args=None, prevs=None): th_name, var = args P = Lambda(var, goal.prop) th = theory.get_theorem(th_name) f, args = th.concl.strip_comb() if len(args) != 1: raise NotImplementedError inst = matcher.first_order_match(args[0], var) inst[f.name] = P return rule().get_proof_term(goal, args=(th_name, inst))
def get_proof_term(self, goal, *, args=None, prevs=None): if isinstance(args, tuple): th_name, inst = args else: th_name, inst = args, None assert isinstance(th_name, str), "rule: theorem name must be a string" if prevs is None: prevs = [] th = theory.get_theorem(th_name) As, C = th.assums, th.concl # Length of prevs is at most length of As assert len(prevs) <= len(As), "rule: too many previous facts" if inst is None: inst = Inst() # Match the conclusion and assumptions. Either the conclusion # or the list of assumptions must be a first-order pattern. if matcher.is_pattern(C, []): inst = matcher.first_order_match(C, goal.prop, inst) for pat, prev in zip(As, prevs): inst = matcher.first_order_match(pat, prev.prop, inst) else: for pat, prev in zip(As, prevs): inst = matcher.first_order_match(pat, prev.prop, inst) inst = matcher.first_order_match(C, goal.prop, inst) # Check that every variable in the theorem has an instantiation. unmatched_vars = [ v.name for v in term.get_svars(As + [C]) if v.name not in inst ] if unmatched_vars: raise theory.ParameterQueryException( list("param_" + name for name in unmatched_vars)) # Substitute and normalize As, _ = th.prop.subst_norm(inst).strip_implies() goal_Alen = len(goal.assums) if goal_Alen > 0: As = As[:-goal_Alen] pts = prevs + [ ProofTerm.sorry(Thm(goal.hyps, A)) for A in As[len(prevs):] ] # Determine whether it is necessary to provide instantiation # to apply_theorem. if set(term.get_svars(th.assums)) != set(th.prop.get_svars()) or \ set(term.get_stvars(th.assums)) != set(th.prop.get_stvars()) or \ not matcher.is_pattern_list(th.assums, []): return apply_theorem(th_name, *pts, inst=inst) else: return apply_theorem(th_name, *pts)
def get_proof_term(self, goal): th = theory.get_theorem(self.th_name) try: inst = matcher.first_order_match(th.concl, goal.prop, self.inst) except matcher.MatchException: raise TacticException('rule: matching failed') if any(v.name not in inst for v in th.prop.get_svars()): raise TacticException('rule: not all variables are matched') pt = ProofTerm.theorem(self.th_name).substitution(inst).on_prop( beta_norm_conv()) for assum in pt.assums: pt = pt.implies_elim(ProofTerm.sorry(Thm(goal.hyps, assum))) return pt
def has_rewrite(th, t, *, sym=False, conds=None): """Returns whether a rewrite is possible on a subterm of t. This can serve as a pre-check for top_sweep_conv, top_conv, and bottom_conv applied to rewr_conv. th -- either the name of a theorem, or the theorem itself. t -- target of rewriting. conds -- optional list of theorems matching assumptions of th. """ if isinstance(th, str): th = theory.get_theorem(th) if sym: th = Thm.symmetric(th) As, C = th.prop.strip_implies() if conds is None: conds = [] if not C.is_equals() or len(As) != len(conds): return False if set(term.get_svars(As + [C.lhs])) != set(term.get_svars(As + [C])): return False ts = [cond.prop for cond in conds] inst = Inst() try: inst = matcher.first_order_match_list(As, ts, inst) except matcher.MatchException: return False def rec(t): if not t.is_open() and matcher.can_first_order_match(C.lhs, t, inst): return True if t.is_comb(): return rec(t.fun) or rec(t.arg) elif t.is_abs(): _, body = t.dest_abs() return rec(body) else: return False return rec(t)
def apply(self, state, id, data, prevs): inst = Inst() with context.fresh_context(vars=state.get_vars(id)): for key, val in data.items(): if key.startswith("param_"): if val != '': inst[key[6:]] = parser.parse_term(val) th = theory.get_theorem(data['theorem']) # Check whether to ask for parameters As, C = th.prop.strip_implies() match_svars = term.get_svars(As[:len(prevs)]) all_svars = th.prop.get_svars() param_svars = [ v for v in all_svars if v not in match_svars and 'param_' + v.name not in data ] if param_svars: raise theory.ParameterQueryException( list("param_" + v.name for v in param_svars)) # First test apply_theorem prev_ths = [state.get_proof_item(prev).th for prev in prevs] macro = logic.apply_theorem_macro(with_inst=True) res_th = macro.eval((data['theorem'], inst), prev_ths) state.add_line_before(id, 1) if inst: state.set_line(id, 'apply_theorem_for', args=(data['theorem'], inst), prevs=prevs) else: state.set_line(id, 'apply_theorem', args=data['theorem'], prevs=prevs) id2 = id.incr_id(1) new_id = state.find_goal(state.get_proof_item(id2).th, id2) if new_id is not None: state.replace_id(id2, new_id)
def solve_fun(goal, pts): for th_name in th_names: if theory.thy.has_theorem(th_name): th = theory.get_theorem(th_name) try: inst = matcher.first_order_match(th.concl, goal) except matcher.MatchException: continue As, _ = th.prop.subst_norm(inst).strip_implies() try: pts = [solve(A, pts) for A in As] except TacticException: continue return apply_theorem(th_name, *pts, concl=goal) # Not solved raise TacticException
def get_proof_term(self, prevs, args): assert isinstance(prevs, ProofTerm) and prevs.prop.arg1.is_int( ) and prevs.prop.arg.is_zero(), "Unexpected %s" % str(prevs) assert isinstance( args, Term) and (args.is_less() or args.is_less_eq() or args.is_greater or args.is_greater_eq()) th_names = [ 'int_pos_mul_less', 'int_neg_mul_less', 'int_pos_mul_less_eq', 'int_neg_mul_less_eq', 'int_pos_mul_greater', 'int_neg_mul_greater', 'int_pos_mul_greater_eq', 'int_neg_mul_greater_eq' ] for th in th_names: try: th1 = get_theorem(th) inst = matcher.first_order_match(th1.prop.arg.lhs, args) pt_concl = apply_theorem(th, prevs, inst=inst) return pt_concl except: continue raise NotImplementedError
def norm_fun(t, pts): for th_name in th_names: if theory.thy.has_theorem(th_name): th = theory.get_theorem(th_name) else: continue try: inst = matcher.first_order_match(th.concl.lhs, t) except matcher.MatchException: continue As, C = th.prop.subst_norm(inst).strip_implies() try: pts = [solve(A, pts) for A in As] except TacticException: continue return apply_theorem(th_name, *pts, concl=C) # No rewriting available return refl(t)
def testCheckedExtend2(self): """Checked extension: proved theorem.""" id_const = Const("id", TFun(Ta,Ta)) id_def = Abs("x", Ta, Bound(0)) id_simps = Eq(id_const(x), x) # Proof of |- id x = x from |- id = (%x. x) prf = Proof() prf.add_item(0, "theorem", args="id_def") # id = (%x. x) prf.add_item(1, "subst_type", args=TyInst(a=TVar('a')), prevs=[0]) # id = (%x. x) prf.add_item(2, "reflexive", args=x) # x = x prf.add_item(3, "combination", prevs=[1, 2]) # id x = (%x. x) x prf.add_item(4, "beta_conv", args=id_def(x)) # (%x. x) x = x prf.add_item(5, "transitive", prevs=[3, 4]) # id x = x exts = [ extension.Constant("id", TFun(Ta, Ta)), extension.Theorem("id_def", Thm([], Eq(id_const, id_def))), extension.Theorem("id.simps", Thm([], id_simps), prf) ] ext_report = theory.thy.checked_extend(exts) self.assertEqual(theory.get_theorem("id.simps", svar=False), Thm([], id_simps)) self.assertEqual(ext_report.get_axioms(), [('id_def', Thm([], Eq(id_const, id_def)))])