def get_proof_term(self, t): pt = refl(t).on_rhs(binop_conv(to_exponent_form())) if pt.rhs.arg1.is_comb('exp', 1) and pt.rhs.arg.is_comb('exp', 1): # Both sides are exponentials return pt.on_rhs(rewr_conv('real_exp_add', sym=True), arg_conv(auto.auto_conv(self.conds))) elif pt.rhs.arg1.is_nat_power() and pt.rhs.arg.is_nat_power(): # Both sides are natural number powers, simply add return pt.on_rhs(rewr_conv('real_pow_add', sym=True), arg_conv(nat.nat_conv())) else: # First check that x > 0 can be proved. If not, just return # without change. x = pt.rhs.arg1.arg1 try: x_gt_0 = auto.solve(x > 0, self.conds) except TacticException: return refl(t) # Convert both sides to real powers if pt.rhs.arg1.is_nat_power(): pt = pt.on_rhs(arg1_conv(rewr_conv('rpow_pow', sym=True))) if pt.rhs.arg.is_nat_power(): pt = pt.on_rhs(arg_conv(rewr_conv('rpow_pow', sym=True))) pt = pt.on_rhs(rewr_conv('rpow_add', sym=True, conds=[x_gt_0]), arg_conv(real_eval_conv())) # Simplify back to nat if possible if pt.rhs.arg.is_comb('of_nat', 1): pt = pt.on_rhs(rewr_conv('rpow_pow'), arg_conv(rewr_conv('nat_of_nat_def', sym=True))) return pt.on_rhs(from_exponent_form())
def get_proof_term(self, t): assert t.is_equals() or t.is_less_eq() or t.is_less()\ or t.is_greater_eq() or t.is_greater(), "%s is not an equality term" % t pt1 = refl(t) # a = b <==> a = b if t.is_equals(): pt2 = pt1.on_rhs(rewr_conv('int_sub_move_0_r', sym=True)) # a = b <==> a - b = 0 eq_refl = ProofTerm.reflexive(equals(IntType)) elif t.is_less_eq(): pt2 = pt1.on_rhs(rewr_conv('int_leq')) eq_refl = ProofTerm.reflexive(less_eq(IntType)) elif t.is_less(): pt2 = pt1.on_rhs(rewr_conv('int_less')) eq_refl = ProofTerm.reflexive(less(IntType)) elif t.is_greater_eq(): pt2 = pt1.on_rhs(rewr_conv('int_geq')) eq_refl = ProofTerm.reflexive(greater_eq(IntType)) elif t.is_greater(): pt2 = pt1.on_rhs(rewr_conv('int_gt')) eq_refl = ProofTerm.reflexive(greater(IntType)) pt3 = simp_full().get_proof_term( pt2.prop.arg.arg1) # a - b = a + (-1) * b pt4 = ProofTerm.combination(eq_refl, pt3) pt5 = ProofTerm.combination(pt4, refl(Const( 'zero', IntType))) # a - b = 0 <==> a + (-1)*b = 0 return pt2.transitive(pt5) # a = b <==> a + (-1) * b = 0
def get_proof_term(self, t): if not is_real_ineq(t): return refl(t) pt_refl = refl(t).on_rhs(real_norm_comparison()) left_expr = pt_refl.rhs.arg1 summands = integer.strip_plus(left_expr) first = summands[0] if not left_expr.is_plus() or not first.is_constant(): return pt_refl first_value = real_eval(first) if pt_refl.rhs.is_greater_eq(): pt_th = ProofTerm.theorem("real_sub_both_sides_geq") elif pt_refl.rhs.is_greater(): pt_th = ProofTerm.theorem("real_sub_both_sides_gt") elif pt_refl.rhs.is_less_eq(): pt_th = ProofTerm.theorem("real_sub_both_sides_leq") elif pt_refl.rhs.is_less(): pt_th = ProofTerm.theorem("real_sub_both_sides_le") else: raise NotImplementedError(str(t)) inst = matcher.first_order_match(pt_th.lhs, pt_refl.rhs, inst=matcher.Inst(c=first)) return pt_refl.transitive(pt_th.substitution(inst=inst)).on_rhs( auto.auto_conv())
def get_proof_term(self, t): if t.get_type() != RealType: return refl(t) simp_t = Real(real_eval(t)) if simp_t == t: return refl(t) return ProofTerm('real_eval', Eq(t, simp_t))
def get_proof_term(self, goal): assert isinstance(goal, Term), "%s should be a hol term" % str(goal) assert goal.is_less() or goal.is_less_eq() or goal.is_greater() or goal.is_greater_eq(),\ "%s should be an inequality term" % str(goal) norm_ineq_pt = norm_eq().get_proof_term(goal) # find the first monomial first_monomial = norm_ineq_pt.rhs while not first_monomial.is_times() and not first_monomial.is_number(): first_monomial = first_monomial.arg1 coeff = first_monomial.arg1 if first_monomial.is_times( ) else first_monomial assert coeff.is_int() coeff_value = int_eval(coeff) # normalize if norm_ineq_pt.rhs.is_greater_eq(): return norm_ineq_pt elif norm_ineq_pt.rhs.is_greater(): return norm_ineq_pt.on_rhs(rewr_conv('int_great_to_geq')) else: if norm_ineq_pt.rhs.is_less(): pt_great = norm_ineq_pt.on_rhs(rewr_conv('int_less_to_geq')) elif norm_ineq_pt.rhs.is_less_eq(): pt_great = norm_ineq_pt.on_rhs(rewr_conv('int_leq_to_geq')) pt_norm_lhs = refl(pt_great.rhs.arg1).on_rhs( omega_simp_full_conv()) return pt_great.transitive( refl(pt_great.rhs.head).combination(pt_norm_lhs).combination( refl(pt_great.rhs.arg)))
def get_proof_term(self, t): if t.get_type() != IntType: return refl(t) simp_t = Int(int_eval(t)) if simp_t == t: return refl(t) else: return ProofTerm('int_eval', Eq(t, int_eval(t)))
def get_proof_term(self, goal, prevs): assert goal.is_equals(), "int_eq_norm, %s is not equation" % goal # Get normal form on both sides. pt1 = refl(goal.lhs).on_rhs(norm_eq()) pt2 = refl(goal.rhs).on_rhs(norm_eq()) assert pt1.rhs == pt2.rhs return pt1.transitive(pt2.symmetric())
def get_proof_term(self, t): if t.is_not(): if t.arg == true: return rewr_conv("not_true").get_proof_term(t) elif t.arg == false: return rewr_conv("not_false").get_proof_term(t) else: return refl(t) else: return refl(t)
def get_proof_term(self, goal): assert goal.is_equals() and goal.lhs.is_compares( ) and goal.rhs.is_compares() pt1 = refl(goal.lhs).on_rhs(omega_form_conv()) pt2 = refl(goal.rhs).on_rhs(omega_form_conv()) if pt1.rhs != pt2.rhs: raise ConvException(str(goal)) return pt1.transitive(pt2.symmetric())
def get_proof_term(self, t): if not t.is_equals(): return refl(t) a, b = t.args if not (a.is_number() and b.is_number()): return refl(t) if a == b: return refl(a).on_prop(rewr_conv("eq_true")) else: return nat_const_ineq(a, b).on_prop(rewr_conv("eq_false"))
def get_proof_term(self, goal, prevs=[]): assert goal.is_equals() and goal.lhs.is_compares( ) and goal.rhs.is_compares() comp1, comp2 = goal.lhs, goal.rhs pt_refl1, pt_refl2 = refl(goal.lhs).on_rhs(real_norm_comparison()), \ refl(goal.rhs).on_rhs(real_norm_comparison()) assert pt_refl1.rhs == pt_refl2.rhs return pt_refl1.transitive(pt_refl2.symmetric())
def get_proof_term(self, t): """Unfold powers of 2 and 3, leave other powers unexpanded.""" a, p = t.args # Exponent is 2, apply real_add_ldistrib to avoid folding back. if p.is_number() and p.dest_number() == 2 and a.is_plus(): return refl(t).on_rhs(rewr_conv('real_pow_2'), rewr_conv('real_add_ldistrib')) # Exponent is 3 elif p.is_number() and p.dest_number() == 3 and a.is_plus(): return refl(t).on_rhs(rewr_conv('real_pow_3'), rewr_conv('real_add_ldistrib')) return refl(t)
def get_proof_term(self, t): pt = refl(t) if t.arg.is_times(): return pt.on_rhs(rewr_conv("mult_assoc", sym=True), arg1_conv(norm_mult_monomial()), norm_mult_atom()) else: return pt.on_rhs(norm_mult_atom())
def get_proof_term(self, t): pt = refl(t) if t.is_plus(): if t.arg1.is_zero(): return pt.on_rhs(rewr_conv('int_add_0_left')) elif t.arg.is_zero(): return pt.on_rhs(rewr_conv('int_add_0_right')) elif t.arg.is_plus(): # t is of form a + (b + c) return pt.on_rhs( rewr_conv('int_add_assoc'), # (a + b) + c arg1_conv(self), # merge terms in b into a norm_add_monomial()) # merge c into a + b elif t.arg.is_minus(): # t is of form a + (b - c) return pt.on_rhs( arg_conv(norm_add_monomial()), # a + b + (-1) * c arg1_conv(self), norm_add_polynomial()) else: return pt.on_rhs(norm_add_monomial()) elif t.is_minus(): if t.arg.is_plus(): # t is of form a - (b + c) return pt.on_rhs( rewr_conv('int_sub_add_distr'), # a - b - c arg1_conv(self), # merge terms in b into a norm_add_monomial() # merge c into a - b ) elif t.arg.is_minus(): # t is of form a - (b - c) return pt.on_rhs( rewr_conv('int_sub_sub_distr'), # a - b + c arg1_conv(self), # merge terms in b into c norm_add_monomial() # merge c into a - b ) else: return pt.on_rhs(norm_add_monomial(), )
def get_proof_term(self, t): pt = refl(t) if t.arg1.is_times(): # t is of form (a * b) * c cp = compare_atom(t.arg1.arg, t.arg) # compare b with c by their base if cp > 0: # if b > c, need to swap b with c return pt.on_rhs( swap_mult_r(), # (a * c) * b arg1_conv(self)) # possibly move c further inside a elif cp == 0: # if b and c have the same base, combine the exponents return pt.on_rhs( rewr_conv('int_mult_assoc', sym=True), # a * (b^e1 * b^e2) arg_conv(rewr_conv('int_power_add', sym=True)), # a * (b^(e1 + e2)) arg_conv(arg_conv(int_eval_conv()))) # evaluate e1 + e2 else: # if b < c, atoms already ordered since we assume b is ordered. return pt else: # t is of the form a * b cp = compare_atom(t.arg1, t.arg) # compare a with b by their base if cp > 0: # if a > b, need to swap a and b return pt.on_rhs(rewr_conv('int_mult_comm')) elif cp == 0: # if a and b have the same base, combine the exponents return pt.on_rhs(rewr_conv('int_power_add', sym=True), arg_conv(int_eval_conv())) else: return pt
def norm_divides(t, pts): """Normalization of divides.""" pt = refl(t) if t.is_number(): return pt.on_rhs(real_eval_conv()) else: return pt.on_rhs(rewr_conv('real_divide_def'))
def get_proof_term(self, t): pt = refl(t) if t.arg1.is_zero(): return pt.on_rhs(rewr_conv("nat_times_def_1")) elif t.arg.is_zero(): return pt.on_rhs(rewr_conv("mult_0_right")) elif t.arg1.is_one(): return pt.on_rhs(rewr_conv("mult_1_left")) elif t.arg.is_one(): return pt.on_rhs(rewr_conv("mult_1_right")) elif t.arg1.is_times(): cp = compare_atom(t.arg1.arg, t.arg) if cp > 0: return pt.on_rhs(swap_times_r(), arg1_conv(norm_mult_atom())) elif cp == 0: if t.arg.is_number() and has_binary_thms(): return pt.on_rhs(rewr_conv("mult_assoc"), arg_conv(nat_conv())) else: return pt else: return pt else: cp = compare_atom(t.arg1, t.arg) if cp > 0: return pt.on_rhs(rewr_conv("mult_comm")) elif cp == 0: if t.arg.is_number() and has_binary_thms(): return pt.on_rhs(nat_conv()) else: return pt else: return pt
def get_proof_term(self, t): pt = refl(t) if t.is_conj(): return pt.on_rhs(binop_conv(self), norm_conj_conjunction()) elif t.is_disj(): return pt.on_rhs(binop_conv(self), norm_disj_disjunction()) elif t.is_equals(): lhs, rhs = t.lhs, t.rhs if lhs == rhs: return pt.on_rhs(rewr_conv('eq_mean_true')) elif lhs == true: # (true ⟷ P) ⟷ P return pt.on_rhs(rewr_conv('eq_sym_eq'), rewr_conv('eq_true', sym=True)) elif rhs == true: # (P ⟷ true) ⟷ P return pt.on_rhs(rewr_conv('eq_true', sym=True)) elif lhs == false: # (false ⟷ P) ⟷ ¬P return pt.on_rhs(rewr_conv('eq_sym_eq'), rewr_conv('eq_false', sym=True)) elif rhs == true: # (P ⟷ false) ⟷ ¬P return pt.on_rhs(rewr_conv('eq_false', sym=True)) else: return pt.on_rhs(binop_conv(self)) elif t.is_not() and (t.arg.is_conj() or t.arg.is_disj() or t.arg.is_not() or t.arg == true or t.arg == false): return pt.on_rhs(nnf_conv(), self) elif t.is_not() and t.arg.is_equals(): return pt.on_rhs(nnf_conv()) else: return pt
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, t): pt = refl(t) if theory.thy.has_theorem('mult_comm'): # Full conversion, with or without binary numbers if t.is_number(): return pt elif t.is_comb('Suc', 1): return pt.on_rhs(rewr_conv("add_1_right", sym=True), norm_full()) elif t.is_plus(): return pt.on_rhs(binop_conv(norm_full()), norm_add_polynomial()) elif t.is_times(): return pt.on_rhs(binop_conv(norm_full()), norm_mult_polynomial()) else: return pt elif theory.thy.has_theorem('add_assoc'): # Conversion using only AC rules for addition if t.is_number(): return pt elif t.is_comb('Suc', 1): return pt.on_rhs(rewr_conv("add_1_right", sym=True), norm_full()) elif t.is_plus(): return pt.on_rhs(binop_conv(norm_full()), norm_add_1()) else: return pt else: return pt
def get_proof_term(self, t): pt = refl(t) if t.arg.is_plus(): return pt.on_rhs(rewr_conv('real_add_assoc'), arg1_conv(self), norm_add_monomial()) else: return pt.on_rhs(norm_add_monomial())
def get_proof_term(self, t): pt = refl(t) if t.arg1.is_zero(): return pt.on_rhs(rewr_conv("real_add_lid")) elif t.arg.is_zero(): return pt.on_rhs(rewr_conv("real_add_rid")) elif t.arg1.is_plus(): # Left side has more than one term. Compare last term with a m1, m2 = dest_monomial(t.arg1.arg), dest_monomial(t.arg) if m1 == m2: pt = pt.on_rhs(rewr_conv('real_add_assoc', sym=True), arg_conv(combine_monomial())) if pt.rhs.arg.is_zero(): pt = pt.on_rhs(rewr_conv('real_add_rid')) return pt elif atom_less(m1, m2): return pt else: pt = pt.on_rhs(swap_add_r(), arg1_conv(self)) if pt.rhs.arg1.is_zero(): pt = pt.on_rhs(rewr_conv('real_add_lid')) return pt else: # Left side is an atom. Compare two sides m1, m2 = dest_monomial(t.arg1), dest_monomial(t.arg) if m1 == m2: return pt.on_rhs(combine_monomial()) elif atom_less(m1, m2): return pt else: return pt.on_rhs(rewr_conv('real_add_comm'))
def get_proof_term(self, t): pt = refl(t) if t.arg1.is_one(): return pt.on_rhs(rewr_conv('real_mul_lid')) elif t.arg.is_one(): return pt.on_rhs(rewr_conv('real_mul_rid')) elif t.arg1.is_times(): # Left side has more than one atom. Compare last atom with b m1, m2 = dest_atom(t.arg1.arg), dest_atom(t.arg) if m1 == m2: pt = pt.on_rhs(rewr_conv('real_mult_assoc', sym=True), arg_conv(combine_atom(self.conds))) if pt.rhs.arg.is_one(): pt = pt.on_rhs(rewr_conv('real_mul_rid')) return pt elif atom_less(m1, m2): return pt else: pt = pt.on_rhs(swap_mult_r(), arg1_conv(self)) if pt.rhs.arg1.is_one(): pt = pt.on_rhs(rewr_conv('real_mul_lid')) return pt else: # Left side is an atom. Compare two sides m1, m2 = dest_atom(t.arg1), dest_atom(t.arg) if m1 == m2: return pt.on_rhs(combine_atom(self.conds)) elif atom_less(m1, m2): return pt else: return pt.on_rhs(rewr_conv('real_mult_comm'))
def get_proof_term(self, t): pt = refl(t) if t.arg.is_times(): return pt.on_rhs(rewr_conv('real_mult_assoc'), arg1_conv(self), norm_mult_atom(self.conds)) else: return pt.on_rhs(norm_mult_atom(self.conds))
def get_proof_term(self, t): if not t.is_compares() or not t.arg1.get_type() == IntType: raise ConvException(str(t)) pt = refl(t) # first move all terms in rhs to lhs and normalize lhs if t.is_greater(): pt1 = pt.on_rhs(rewr_conv('int_gt_to_geq'), rewr_conv('int_geq'), arg1_conv(omega_simp_full_conv())) elif t.is_greater_eq(): pt1 = pt.on_rhs(rewr_conv('int_geq'), arg1_conv(omega_simp_full_conv())) elif t.is_less(): pt1 = pt.on_rhs(rewr_conv('int_less_to_leq'), rewr_conv('int_leq'), arg1_conv(omega_simp_full_conv())) elif t.is_less_eq(): pt1 = pt.on_rhs(rewr_conv('int_leq'), arg1_conv(omega_simp_full_conv())) else: raise NotImplementedError # move all constant term on lhs to rhs lhs = pt1.rhs.arg1 if lhs.is_number() or lhs.is_times() or lhs.arg.is_times(): return pt1 elif pt1.rhs.is_greater_eq() and lhs.arg.is_number(): return pt1.on_rhs(rewr_conv('int_geq_shift'), arg_conv(int_eval_conv())) elif pt1.rhs.is_less_eq() and lhs.arg.is_number(): return pt1.on_rhs(rewr_conv('int_leq_shift'), arg_conv(int_eval_conv())) else: raise NotImplementedError
def get_proof_term(self, t): pt = refl(t) is_l_atom = (dest_monomial(t.arg1) == t.arg1) is_r_atom = (dest_monomial(t.arg) == t.arg) if is_l_atom and is_r_atom: return pt.on_rhs(norm_mult_monomial(self.conds)) elif is_l_atom and not is_r_atom: if t.arg.is_number(): return pt.on_rhs(rewr_conv('real_mult_comm'), try_conv(rewr_conv('real_mul_rid')), try_conv(rewr_conv('real_mul_lzero'))) else: return pt.on_rhs(arg_conv(rewr_conv('real_mult_comm')), rewr_conv('real_mult_assoc'), rewr_conv('real_mult_comm'), arg_conv(norm_mult_monomial(self.conds))) elif not is_l_atom and is_r_atom: if t.arg1.is_number(): return pt.on_rhs(try_conv(rewr_conv('real_mul_rid')), try_conv(rewr_conv('real_mul_lzero'))) else: return pt.on_rhs(rewr_conv('real_mult_assoc', sym=True), arg_conv(norm_mult_monomial(self.conds))) else: return pt.on_rhs( binop_conv(to_coeff_form()), # (c_1 * m_1) * (c_2 * m_2) rewr_conv('real_mult_assoc'), # (c_1 * m_1 * c_2) * m_2 arg1_conv(swap_mult_r()), # (c_1 * c_2 * m_1) * m_2 arg1_conv(arg1_conv(real_eval_conv())), # (c_1c_2 * m_1) * m_2 rewr_conv('real_mult_assoc', sym=True), # c_1c_2 * (m_1 * m_2) arg_conv(norm_mult_monomial(self.conds)), from_coeff_form())
def get_proof_term(self, t): pt = refl(t) if t.arg1.is_disj(): return pt.on_rhs(rewr_conv('disj_assoc_eq', sym=True), arg_conv(self), norm_disj_atom()) else: return pt.on_rhs(norm_disj_atom())
def norm_uminus(t, pts): """Normalization of uminus.""" pt = refl(t) if t.is_number(): return pt.on_rhs(real_eval_conv()) else: return pt.on_rhs(rewr_conv('real_poly_neg1'))
def get_proof_term(self, t): if t.is_comb(): return comb_conv(self.cv).get_proof_term(t) elif t.is_abs(): return abs_conv(self.cv).get_proof_term(t) else: return refl(t)
def get_proof_term(self, t): pt = refl(t) if t.arg.is_plus(): return pt.on_rhs(rewr_conv("add_assoc", sym=True), arg1_conv(norm_add_1()), norm_add_atom_1()) else: return pt.on_rhs(norm_add_atom_1())