def get_proof_term(self, thy, t): if is_times(t) and is_binary(t.arg): return all_conv().get_proof_term(thy, t) elif is_binary(t): return rewr_conv("mult_1_left", sym=True).get_proof_term(thy, t) else: return rewr_conv("mult_1_right", sym=True).get_proof_term(thy, t)
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): 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(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 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): 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(self): invC = Const("inv", TFun(gcl.stateT, BoolType)) transC = Const("trans", TFun(gcl.stateT, gcl.stateT, BoolType)) s1 = Var("s1", gcl.stateT) s2 = Var("s2", gcl.stateT) prop = Thm([], Implies(invC(s1), transC(s1, s2), invC(s2))) # print(printer.print_thm(prop)) trans_pt = ProofTerm.assume(transC(s1, s2)) # print(printer.print_thm(trans_pt.th)) P = Implies(invC(s1), invC(s2)) ind_pt = apply_theorem("trans_cases", inst=Inst(a1=s1, a2=s2, P=P)) # print(printer.print_thm(ind_pt.th)) ind_As, ind_C = ind_pt.prop.strip_implies() for ind_A in ind_As[1:-1]: # print("ind_A: ", ind_A) vars, As, C = logic.strip_all_implies(ind_A, ["s", "k"]) # for A in As: # print("A: ", A) # print("C: ", C) eq1 = ProofTerm.assume(As[0]) eq2 = ProofTerm.assume(As[1]) guard = ProofTerm.assume(As[2]) inv_pre = ProofTerm.assume(As[3]).on_arg(rewr_conv(eq1)).on_prop( rewr_conv("inv_def")) C_goal = ProofTerm.assume(C).on_arg(rewr_conv(eq2)).on_prop( rewr_conv("inv_def"))
def get_proof_term(self, thy, t): if t.arg == one: return rewr_conv("mult_1_right").get_proof_term(thy, t) elif t.arg1 == one: return rewr_conv("mult_1_left").get_proof_term(thy, t) else: return all_conv().get_proof_term(thy, t)
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 get_proof_term(self, t): pt = refl(t) if t.is_times() and t.arg1.is_number(): return pt elif t.is_number(): # c to c * 1 return pt.on_rhs(rewr_conv('real_mul_rid', sym=True)) else: # x to 1 * x return pt.on_rhs(rewr_conv('real_mul_lid', sym=True))
def get_proof_term(self, t): pt = refl(t) if t.arg.is_conj(): return pt.on_rhs(rewr_conv('conj_assoc'), arg1_conv(rewr_conv('conj_comm')), rewr_conv('conj_assoc', sym=True)) else: return pt.on_rhs(rewr_conv('conj_comm'))
def get_proof_term(self, t): pt = refl(t) if t.arg.is_one(): return pt.on_rhs(rewr_conv("mult_1_right")) elif t.arg1.is_one(): return pt.on_rhs(rewr_conv("mult_1_left")) else: return pt
def get_proof_term(self, t): pt = refl(t) if t.is_times() and t.arg.is_number(): return pt elif t.is_number(): return pt.on_rhs(rewr_conv("mult_1_left", sym=True)) else: return pt.on_rhs(rewr_conv("mult_1_right", sym=True))
def get_proof_term(self, t): pt = refl(t) if t.arg1.is_times(): return pt.on_rhs(rewr_conv("mult_assoc"), arg_conv(rewr_conv("mult_comm")), rewr_conv("mult_assoc", sym=True)) else: return pt.on_rhs(rewr_conv("mult_comm"))
def get_proof_term(self, thy, t): if is_plus(t.arg1): return every_conv(rewr_conv("add_assoc"), arg_conv(rewr_conv("add_comm")), rewr_conv("add_assoc", sym=True)).get_proof_term(thy, t) else: return rewr_conv("add_comm").get_proof_term(thy, t)
def eval_Sem(c, st): """Evaluates the effect of program c on state st.""" T = st.get_type() if c.is_const("Skip"): return apply_theorem("Sem_Skip", inst=Inst(s=st)) elif c.is_comb("Assign", 2): a, b = c.args Ta = a.get_type() Tb = b.get_type().range_type() pt = apply_theorem("Sem_Assign", inst=Inst(a=a, b=b, s=st)) return pt.on_arg(arg_conv(norm_cv)) elif c.is_comb("Seq", 2): c1, c2 = c.args pt1 = eval_Sem(c1, st) pt2 = eval_Sem(c2, pt1.prop.arg) pt = apply_theorem("Sem_seq", pt1, pt2) return pt.on_arg(function.fun_upd_norm_one_conv()) elif c.is_comb("Cond", 3): b, c1, c2 = c.args b_st = beta_norm(b(st)) b_eval = norm_cond_cv.get_proof_term(b_st) if b_eval.prop.arg == true: b_res = b_eval.on_prop(rewr_conv("eq_true", sym=True)) pt1 = eval_Sem(c1, st) return apply_theorem("Sem_if1", b_res, pt1, concl=Sem(T)(c, st, pt1.prop.arg)) else: b_res = b_eval.on_prop(rewr_conv("eq_false", sym=True)) pt2 = eval_Sem(c2, st) return apply_theorem("Sem_if2", b_res, pt2, concl=Sem(T)(c, st, pt2.prop.arg)) elif c.is_comb("While", 3): b, inv, body = c.args b_st = beta_norm(b(st)) b_eval = norm_cond_cv.get_proof_term(b_st) if b_eval.prop.arg == true: b_res = b_eval.on_prop(rewr_conv("eq_true", sym=True)) pt1 = eval_Sem(body, st) pt2 = eval_Sem(c, pt1.prop.arg) pt = apply_theorem("Sem_while_loop", b_res, pt1, pt2, concl=Sem(T)(c, st, pt2.prop.arg), inst=Inst(s3=pt1.prop.arg)) return pt.on_arg(function.fun_upd_norm_one_conv()) else: b_res = b_eval.on_prop(rewr_conv("eq_false", sym=True)) return apply_theorem("Sem_while_skip", b_res, concl=Sem(T)(c, st, st)) else: raise NotImplementedError
def norm_mult(t, pts): """Normalization of mult. Assume two sides are in normal form.""" pt = refl(t) if t.arg1.is_plus(): return pt.on_rhs(rewr_conv('real_add_rdistrib')) elif t.arg.is_plus(): return pt.on_rhs(rewr_conv('real_add_ldistrib')) else: return pt.on_rhs(norm_mult_monomials(pts))
def get_proof_term(self, tm): if not ((tm.is_compares() or tm.is_equals()) and \ tm.arg1.is_constant() and tm.arg.is_constant()): return refl(tm) pt = ProofTerm("int_const_ineq", tm) if pt.prop.is_not(): return pt.on_prop(rewr_conv("eq_false")) else: return pt.on_prop(rewr_conv("eq_true"))
def get_proof_term(self, goal, pts): assert len(pts) == 0 and self.can_eval(goal), "nat_const_less_eq_macro" m, n = goal.args assert m.dest_number() <= n.dest_number() p = Nat(n.dest_number() - m.dest_number()) eq = refl(m + p).on_rhs(norm_full()).symmetric() goal2 = rewr_conv('less_eq_exist').eval(goal).prop.rhs ex_eq = apply_theorem('exI', eq, concl=goal2) return ex_eq.on_prop(rewr_conv('less_eq_exist', sym=True))
def get_proof_term(self, t): if not t.is_disj(): return refl(t) nnf_pt = nnf_conv().get_proof_term(Not(t)) norm_neg_disj_pt = sort_conj().get_proof_term(nnf_pt.rhs) nnf_pt_norm = nnf_pt.transitive(norm_neg_disj_pt) return nnf_pt_norm.on_prop(rewr_conv('neg_iff_both_sides'), arg1_conv(rewr_conv('double_neg')), arg_conv(nnf_conv()))
def get_proof_term(self, t): pt = refl(t) if t.arg.is_zero(): return pt.on_rhs(rewr_conv("nat_one_def", sym=True)) elif t.arg.is_one(): return pt.on_rhs(rewr_conv("one_Suc")) elif is_bit0(t.arg): return pt.on_rhs(rewr_conv("bit0_Suc")) else: return pt.on_rhs(rewr_conv("bit1_Suc"), arg_conv(self))
def get_proof_term(self, thy, t): if is_neg(t): if t.arg == true: return rewr_conv("not_true").get_proof_term(thy, t) elif t.arg == false: return rewr_conv("not_false").get_proof_term(thy, t) else: return refl(t) else: return refl(t)
def get_proof_term(self, thy, t): n = t.arg # remove Suc if n == zero: return all_conv().get_proof_term(thy, t) elif n == one: return rewr_conv("one_Suc").get_proof_term(thy, t) elif n.head == bit0: return rewr_conv("bit0_Suc").get_proof_term(thy, t) else: return then_conv(rewr_conv("bit1_Suc"), arg_conv(self)).get_proof_term(thy, t)
def encode(t): """Given a propositional formula t, compute its Tseitin encoding. The theorem is structured as follows: Each of the assumptions, except the last, is an equality, where the right side is either an atom or a logical operation between atoms. We call these assumptions As. The last assumption is the original formula. We call it F. The conclusion is in CNF. Each clause except the last is an expansion of one of As. The last clause is obtained by performing substitutions of As on F. """ # Mapping from subterms to newly introduced variables subterm_dict = dict() for i, subt in enumerate(logic_subterms(t)): subterm_dict[subt] = Var('x' + str(i + 1), BoolType) # Collect list of equations eqs = [] for subt in subterm_dict: r = subterm_dict[subt] if not is_logical(subt): eqs.append(Eq(r, subt)) elif subt.is_not(): r1 = subterm_dict[subt.arg] eqs.append(Eq(r, Not(r1))) else: r1 = subterm_dict[subt.arg1] r2 = subterm_dict[subt.arg] eqs.append(Eq(r, subt.head(r1, r2))) # Form the proof term eq_pts = [ProofTerm.assume(eq) for eq in eqs] encode_pt = ProofTerm.assume(t) for eq_pt in eq_pts: encode_pt = encode_pt.on_prop(top_conv(rewr_conv(eq_pt, sym=True))) for eq_pt in eq_pts: if is_logical(eq_pt.rhs): encode_pt = logic.apply_theorem('conjI', eq_pt, encode_pt) # Rewrite using Tseitin rules encode_thms = [ 'encode_conj', 'encode_disj', 'encode_imp', 'encode_eq', 'encode_not' ] for th in encode_thms: encode_pt = encode_pt.on_prop(top_conv(rewr_conv(th))) # Normalize the conjuncts return encode_pt.on_prop(logic.conj_norm())
def get_proof_term(self, prevs, goal_lit): disj, *lit_pts = prevs pt_conj = lit_pts[0] for i in range(len(lit_pts)): pt = lit_pts[i] if not pt.prop.is_not(): lit_pts[i] = pt.on_prop(rewr_conv('double_neg', sym=True)) def conj_right_assoc(pts): """ Give a sequence of proof terms: ⊢ A, ⊢ B, ⊢ C, return ⊢ A ∧ (B ∧ C) """ if len(pts) == 1: return pts[0] else: return apply_theorem('conjI', pts[0], conj_right_assoc(pts[1:])) # get a /\ b /\ c pt_conj = conj_right_assoc(lit_pts) other_lits = [ l.prop.arg if l.prop.is_not() else Not(l.prop) for l in lit_pts ] # use de Morgan pt_conj1 = pt_conj.on_prop( bottom_conv(rewr_conv('de_morgan_thm2', sym=True))) # if len(other_lits) == 1 and other_lits[0].is_not(): # pt_conj1 = pt_conj.on_prop(rewr_conv('double_neg', sym=True)) # Equality for two disjunctions which literals are the same, but order is different. eq_pt = imp_disj_iff(Eq(disj.prop, Or(goal_lit, *other_lits))) new_disj_pt = disj.on_prop(top_conv(replace_conv(eq_pt))) # A \/ B --> ~B --> A pt = ProofTerm.theorem('force_disj_true1') A, B = pt.prop.strip_implies()[0] C = pt.prop.strip_implies()[1] inst1 = matcher.first_order_match(C, goal_lit) inst2 = matcher.first_order_match(A, Or(goal_lit, *other_lits), inst=inst1) inst3 = matcher.first_order_match(B, pt_conj1.prop, inst=inst2) pt_implies = apply_theorem('force_disj_true1', new_disj_pt, pt_conj1, inst=inst3) return pt_implies.on_prop(try_conv(rewr_conv('double_neg')))
def reverse_inequality(pt): """Convert an inequality of the form x </<= y to y >/>= x, and vice versa.""" if pt.prop.is_less_eq(): return pt.on_prop(rewr_conv('real_geq_to_leq', sym=True)) elif pt.prop.is_less(): return pt.on_prop(rewr_conv('real_ge_to_le', sym=True)) elif pt.prop.is_greater_eq(): return pt.on_prop(rewr_conv('real_geq_to_leq')) elif pt.prop.is_greater(): return pt.on_prop(rewr_conv('real_ge_to_le')) else: raise AssertionError('reverse_inequality')
def real_solver(self, args): refl_pt = conv.refl(args).on_rhs( conv.top_conv(conv.rewr_conv("real_ge_le_same_num")), conv.top_conv(conv.rewr_conv("de_morgan_thm1")), conv.top_conv(real.norm_neg_real_ineq_conv()), conv.top_conv(real.real_simplex_form()), conv.top_conv(real.real_const_compares()), proplogic.norm_full()) if refl_pt.rhs == true: return refl_pt.on_prop(conv.rewr_conv("eq_true", sym=True)) pt_result = real_th_lemma([refl_pt.rhs]) return refl_pt.symmetric().equal_elim(pt_result)
def get_proof_term(self, t): pt = refl(t) if t.arg.is_one(): return pt.on_rhs(rewr_conv('real_mul_rid')) elif t.arg1.is_one(): return pt.on_rhs(rewr_conv('real_mul_lid')) elif t.arg.is_zero(): return pt.on_rhs(rewr_conv('real_mul_rzero')) elif t.arg1.is_zero(): return pt.on_rhs(rewr_conv('real_mul_lzero')) else: return pt
def get_proof_term(self, t): pt = refl(t) if t.is_comb('exp', 1): return pt elif t.is_nat_power() and t.arg.is_one(): return pt.on_rhs(rewr_conv('real_pow_1')) elif t.is_real_power() and t.arg.is_one(): return pt.on_rhs(rewr_conv('rpow_1')) elif t.is_real_power() and t.arg.is_zero(): return pt.on_rhs(rewr_conv('rpow_0')) else: return pt
def get_proof_term(self, tm): if not tm.is_not() or not is_real_ineq(tm.arg): raise ConvException("Invalid term: %s" % str(tm)) pt = refl(tm) if tm.arg.is_less(): return pt.on_rhs(rewr_conv("real_neg_lt")) elif tm.arg.is_greater(): return pt.on_rhs(rewr_conv("real_not_gt")) elif tm.arg.is_less_eq(): return pt.on_rhs(rewr_conv("real_not_leq")) else: return pt.on_rhs(rewr_conv("real_not_geq"))