def get_proof_term(self, goal, *, args=None, prevs=None): assert isinstance(prevs, list) and len(prevs) == 1, "rewrite_goal_with_prev" pt = prevs[0] C = goal.prop # In general, we assume pt.th has forall quantification. # First, obtain the patterns new_names = logic.get_forall_names(pt.prop) new_vars, prev_As, prev_C = logic.strip_all_implies(pt.prop, new_names) # Fact used must be an equality assert len( prev_As) == 0 and prev_C.is_equals(), "rewrite_goal_with_prev" for new_var in new_vars: pt = pt.forall_elim(new_var) # Check whether rewriting using the theorem has an effect assert has_rewrite(pt.th, C), "rewrite_goal_with_prev" cv = then_conv(top_sweep_conv(rewr_conv(pt)), beta_norm_conv()) eq_th = cv.eval(C) new_goal = eq_th.prop.rhs prevs = list(prevs) if not new_goal.is_reflexive(): prevs.append(ProofTerm.sorry(Thm(goal.hyps, new_goal))) return ProofTerm('rewrite_goal_with_prev', args=C, prevs=prevs)
def direct_contr_pt(self, lower, upper): """When lower and upper's comparisons don't contain constant, we need to treat them carefully. """ def norm_pt(pt): """If comparison in pt's prop does not contain constant, add a zero on the tail.""" tm = factoid_to_term(self.vars, term_to_factoid(self.vars, pt.prop)) pt1 = integer.omega_form_conv().get_proof_term(tm).symmetric() return pt.on_prop(conv.top_sweep_conv(conv.rewr_conv(pt1))) if lower.prop.arg.is_times(): lower = norm_pt(lower) if upper.prop.arg.is_times(): upper = norm_pt(upper) pos, neg = lower.prop.arg.arg1, upper.prop.arg.arg1 pt_eq = integer.omega_simp_full_conv().get_proof_term(neg).\ transitive(integer.omega_simp_full_conv().get_proof_term(term.Int(-1) * pos).symmetric()) pt1 = lower pt2 = upper.on_prop(conv.top_sweep_conv(conv.rewr_conv(pt_eq))) lower_bound, upper_bound = -term.Int( integer.int_eval(lower.prop.arg.arg)), term.Int( integer.int_eval(upper.prop.arg.arg)) pt3 = proofterm.ProofTerm( 'int_const_ineq', term.greater(term.IntType)(lower_bound, upper_bound)) return logic.apply_theorem('int_comp_contr', pt1, pt2, pt3)
def get_proof_term(self, args, pts): assert isinstance(args, Term), "rewrite_goal_macro: signature" goal = args eq_pt = pts[0] new_names = get_forall_names(eq_pt.prop) new_vars, _, _ = strip_all_implies(eq_pt.prop, new_names) for new_var in new_vars: eq_pt = eq_pt.forall_elim(new_var) pts = pts[1:] cv = then_conv(top_sweep_conv(rewr_conv(eq_pt, sym=self.sym)), beta_norm_conv()) pt = cv.get_proof_term(goal) # goal = th.prop pt = pt.symmetric() # th.prop = goal if pt.prop.lhs.is_reflexive(): pt = pt.equal_elim(refl(pt.prop.lhs.rhs)) else: pt = pt.equal_elim(pts[0]) pts = pts[1:] for A in pts: pt = pt.implies_intr(A.prop).implies_elim(A) return pt
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 get_proof_term(self, goal, *, args=None, prevs=None): th_name = args C = goal.prop # Check whether rewriting using the theorem has an effect assert has_rewrite(th_name, C, sym=self.sym, conds=prevs), \ "rewrite: unable to apply theorem." cv = then_conv( top_sweep_conv(rewr_conv(th_name, sym=self.sym, conds=prevs)), beta_norm_conv()) eq_th = cv.eval(C) new_goal = eq_th.prop.rhs if self.sym: macro_name = 'rewrite_goal_sym' else: macro_name = 'rewrite_goal' if new_goal.is_equals() and new_goal.lhs == new_goal.rhs: return ProofTerm(macro_name, args=(th_name, C), prevs=prevs) else: new_goal = ProofTerm.sorry(Thm(goal.hyps, new_goal)) assert new_goal.prop != goal.prop, "rewrite: unable to apply theorem" return ProofTerm(macro_name, args=(th_name, C), prevs=[new_goal] + prevs)
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)
def testTopSweepConv(self): f = Const("f", TFun(natT, natT)) x = Var("x", natT) th0 = eq(x, f(x)) cv = top_sweep_conv(rewr_conv(ProofTerm.atom(0, th0), match_vars=False)) prf = Proof() prf.add_item(0, "sorry", th=th0) cv.get_proof_term(thy, f(x)).export(prf=prf) self.assertEqual(thy.check_proof(prf), eq(f(x), f(f(x))))
def search(self, state, id, prevs): if len(prevs) != 2: return [] eq_th, prev_th = [state.get_proof_item(prev).th for prev in prevs] if not eq_th.prop.is_equals(): return [] cv = top_sweep_conv( rewr_conv(ProofTermAtom(prevs[0], eq_th), match_vars=False)) th = cv.eval(state.thy, prev_th.prop) new_fact = th.prop.rhs if prev_th.prop != new_fact: return [{}] else: return []
def search(self, state, id, prevs): if len(prevs) != 1: return [] prev_th = state.get_proof_item(prevs[0]).th 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_sweep_conv(rewr_conv(th_name)) th = cv.eval(thy, prev_th.prop) new_fact = th.prop.rhs if prev_th.prop != new_fact: results.append({"theorem": th_name, "_fact": [new_fact]}) return sorted(results, key=lambda d: d['theorem'])
def get_proof_term(self, args, pts): assert isinstance(args, str), "rewrite_fact_macro: signature" th_name = args eq_pt = ProofTerm.theorem(th_name) assert len(pts) == len(eq_pt.assums) + 1, "rewrite_fact_macro: signature" # Check rewriting using the theorem has an effect if not has_rewrite(th_name, pts[0].prop, sym=self.sym, conds=pts[1:]): raise InvalidDerivationException("rewrite_fact using %s" % th_name) cv = then_conv(top_sweep_conv(rewr_conv(eq_pt, sym=self.sym, conds=pts[1:])), beta_norm_conv()) res = pts[0].on_prop(cv) if res == pts[0]: raise InvalidDerivationException("rewrite_fact using %s" % th_name) return res
def gcd_pt(self, vars, pt): fact = term_to_factoid(vars, pt.prop) g = functools.reduce(gcd, fact[:-1]) assert g > 1 pt1 = proofterm.ProofTerm('int_const_ineq', term.Int(g) > term.Int(0)) pt2 = pt elim_gcd_fact = [floor(i / g) for i in fact] if int(fact[-1] / g) != fact[-1] / g: elim_gcd_no_constant = sum( [c * v for c, v in zip(elim_gcd_fact[1:-1], vars[1:])], elim_gcd_fact[0] * vars[0]) original_no_constant = sum( [c * v for c, v in zip(fact[1:-1], vars[1:])], fact[0] * vars[0]) elim_gcd_no_constant = integer.int_norm_conv().get_proof_term( elim_gcd_no_constant).rhs original_no_constant = integer.int_norm_conv().get_proof_term( original_no_constant).rhs pt3 = integer.int_norm_conv().get_proof_term( g * elim_gcd_no_constant).transitive( integer.int_norm_conv().get_proof_term( original_no_constant).symmetric()) n = floor(-fact[-1] / g) pt4 = proofterm.ProofTerm('int_const_ineq', term.Int(g) * term.Int(n) + fact[-1] < 0) pt5 = proofterm.ProofTerm( 'int_const_ineq', term.Int(g) * (term.Int(n) + term.Int(1)) + fact[-1] > 0) pt6 = integer.int_eval_conv().get_proof_term(-(term.Int(n) + term.Int(1))) return logic.apply_theorem( 'int_gcd', pt1, pt2, pt3, pt4, pt5).on_prop(conv.top_sweep_conv(conv.rewr_conv(pt6)), conv.arg_conv(integer.omega_simp_full_conv())) else: elim_gcd_term = factoid_to_term(vars, elim_gcd_fact) pt3 = integer.omega_simp_full_conv().get_proof_term(pt.prop.arg).transitive(\ integer.omega_simp_full_conv().get_proof_term(term.Int(g) * elim_gcd_term.arg).symmetric()) return logic.apply_theorem('int_gcd_1', pt1, pt2, pt3)
def get_proof_term(self, thy, args, pts): assert isinstance(args, Term), "rewrite_goal_macro: signature" goal = args eq_pt = pts[0] pts = pts[1:] if self.backward: eq_pt = ProofTerm.symmetric(eq_pt) cv = then_conv(top_sweep_conv(rewr_conv(eq_pt, match_vars=False)), top_conv(beta_conv())) pt = cv.get_proof_term(thy, goal) # goal = th.prop pt = ProofTerm.symmetric(pt) # th.prop = goal if Term.is_equals(pt.prop.lhs) and pt.prop.lhs.lhs == pt.prop.lhs.rhs: pt = ProofTerm.equal_elim(pt, ProofTerm.reflexive(pt.prop.lhs.rhs)) else: pt = ProofTerm.equal_elim(pt, pts[0]) pts = pts[1:] for A in pts: pt = ProofTerm.implies_elim(ProofTerm.implies_intr(A.prop, pt), A) return pt
def get_proof_term(self, args, pts): assert isinstance(args, tuple) and len(args) == 2 and \ isinstance(args[0], str) and isinstance(args[1], Term), "rewrite_goal: signature" name, goal = args eq_pt = ProofTerm.theorem(name) if len(pts) == len(eq_pt.assums): rewr_cv = rewr_conv(eq_pt, sym=self.sym, conds=pts) else: assert len(pts) == len(eq_pt.assums) + 1, "rewrite_goal: wrong number of prevs" rewr_cv = rewr_conv(eq_pt, sym=self.sym, conds=pts[1:]) cv = then_conv(top_sweep_conv(rewr_cv), beta_norm_conv()) pt = cv.get_proof_term(goal) # goal = th.prop pt = pt.symmetric() # th.prop = goal if pt.prop.lhs.is_equals() and pt.prop.lhs.lhs == pt.prop.lhs.rhs: pt = pt.equal_elim(refl(pt.prop.lhs.lhs)) else: pt = pt.equal_elim(pts[0]) # goal return pt
def get_proof_term(self, args, pts): assert len(pts) == 2, "rewrite_fact_with_prev" eq_pt, pt = pts # In general, we assume eq_pt has forall quantification # First, obtain the patterns new_names = get_forall_names(eq_pt.prop) new_vars, eq_As, eq_C = strip_all_implies(eq_pt.prop, new_names) # First fact must be an equality assert len(eq_As) == 0 and eq_C.is_equals(), "rewrite_fact_with_prev" for new_var in new_vars: eq_pt = eq_pt.forall_elim(new_var) # Check rewriting using eq_pt has an effect cv1 = top_sweep_conv(rewr_conv(eq_pt)) assert not cv1.eval(pt.prop).is_reflexive(), "rewrite_fact_with_prev" cv = then_conv(cv1, beta_norm_conv()) return pt.on_prop(cv)
def search(self, state, id, prevs): if len(prevs) != 1: return [] prev_th = state.get_proof_item(prevs[0]).th cur_th = state.get_proof_item(id).th if not prev_th.prop.is_equals(): return [] pt = ProofTermAtom(prevs[0], prev_th) cv = then_conv(top_sweep_conv(rewr_conv(pt, match_vars=False)), top_conv(beta_conv())) eq_th = cv.eval(state.thy, cur_th.prop) new_goal = eq_th.prop.rhs new_As = list(set(eq_th.hyps) - set(cur_th.hyps)) if cur_th.prop != new_goal: if Term.is_equals(new_goal) and new_goal.lhs == new_goal.rhs: return [{"_goal": new_As}] else: return [{"_goal": [new_goal] + new_As}] else: return []
def get_proof_term(self, thy, args, pts): eq_pt, pt = pts cv = then_conv(top_sweep_conv(rewr_conv(eq_pt, match_vars=False)), top_conv(beta_conv())) return pt.on_prop(thy, cv)
def norm_pt(pt): """If comparison in pt's prop does not contain constant, add a zero on the tail.""" tm = factoid_to_term(self.vars, term_to_factoid(self.vars, pt.prop)) pt1 = integer.omega_form_conv().get_proof_term(tm).symmetric() return pt.on_prop(conv.top_sweep_conv(conv.rewr_conv(pt1)))
def get_proof_term(self, t): if not t.is_conj(): return refl(t) d_pos = dict() d_neg = dict() qu = deque([ProofTerm.assume(t)]) # collect each conjunct's proof term in conjuntion while qu: pt = qu.popleft() if pt.prop.is_conj(): conj1, conj2 = pt.prop.arg1, pt.prop.arg pt_conj1, pt_conj2 = apply_theorem('conjD1', pt), apply_theorem( 'conjD2', pt) if conj1 == false: th = ProofTerm.theorem("falseE") inst = matcher.first_order_match(th.prop.arg, t) pt_false_implies_conj = th.substitution(inst) return ProofTerm.equal_intr(pt_conj1.implies_intr(t), pt_false_implies_conj) elif conj2 == false: th = ProofTerm.theorem("falseE") inst = matcher.first_order_match(th.prop.arg, t) pt_false_implies_conj = th.substitution(inst) return ProofTerm.equal_intr(pt_conj2.implies_intr(t), pt_false_implies_conj) if conj1.is_conj(): qu.appendleft(pt_conj1) else: if conj1.is_not(): d_neg[conj1] = pt_conj1 else: d_pos[conj1] = pt_conj1 if conj2.is_conj(): qu.appendleft(pt_conj2) else: if conj2.is_not(): d_neg[conj2] = pt_conj2 else: d_pos[conj2] = pt_conj2 else: if pt.prop.is_not(): d_neg[pt.prop] = pt else: d_pos[pt.prop] = pt # first check if there are opposite terms in conjunctions, if there exists, return a false proof term for key in d_pos: if Not(key) in d_neg: pos_pt, neg_pt = d_pos[key], d_neg[Not(key)] pt_conj_pos_neg = apply_theorem("conjI", pos_pt, neg_pt) pt_conj_implies_false = pt_conj_pos_neg.on_prop( rewr_conv("conj_pos_neg")).implies_intr(t) th = ProofTerm.theorem("falseE") inst = matcher.first_order_match(th.prop.arg, t) pt_false_implies_conj = th.substitution(inst) return ProofTerm.equal_intr(pt_conj_implies_false, pt_false_implies_conj) d_pos.update(d_neg) d = d_pos def right_assoc(ts): l = len(ts) if l == 1: return d[ts[0]] elif l == 2: return apply_theorem('conjI', d[ts[0]], d[ts[1]]) else: return apply_theorem('conjI', d[ts[0]], right_assoc(ts[1:])) # pt_right = functools.reduce(lambda x, y: apply_theorem('conjI', x, d[y]), sorted(d.keys()), d[sorted(d.keys())[0]]) if true not in d: sorted_keys = term_ord.sorted_terms(d.keys()) else: d_keys_without_true = term_ord.sorted_terms( [k for k in d if k != true]) sorted_keys = [true] + d_keys_without_true sorted_keys_num = len(sorted_keys) pt_right = functools.reduce(lambda x, y: apply_theorem('conjI', d[sorted_keys[sorted_keys_num - y - 2]], x), \ range(sorted_keys_num - 1), d[sorted_keys[-1]]) # pt_right = right_assoc(sorted_keys) # order implies original dd = dict() norm_conj = And(*sorted_keys) norm_conj_pt = ProofTerm.assume(norm_conj) for k in sorted_keys: if k != sorted_keys[-1]: dd[k] = apply_theorem('conjD1', norm_conj_pt) norm_conj_pt = apply_theorem('conjD2', norm_conj_pt) else: dd[k] = norm_conj_pt def traverse(t): if not t.is_conj(): return dd[t] else: return apply_theorem('conjI', traverse(t.arg1), traverse(t.arg)) pt_left = traverse(t) pt_final = ProofTerm.equal_intr(pt_right.implies_intr(t), pt_left.implies_intr(norm_conj)) if true in d: return pt_final.on_rhs(rewr_conv("conj_true_left"), top_sweep_conv(sort_disj())) else: return pt_final.on_rhs(top_sweep_conv(sort_disj()))