Пример #1
0
    def handle_leq_stage2(self, pt_upper_bound, pts, delta):
        # get ⊢ x_i ≤ -δ, for i = 1...n
        leq_pt = []
        pt_b = pt_upper_bound

        for i in range(len(pts)):
            if i != len(pts) - 1:
                pt = logic.apply_theorem("both_leq_max", pt_b)
                pt_1, pt_2 = logic.apply_theorem("conjD1",
                                                 pt), logic.apply_theorem(
                                                     "conjD2", pt)
            else:
                pt_2 = pt_b

            ineq = pt_2.prop

            if ineq.arg1.is_minus() and ineq.arg1.arg.is_number():
                num = ineq.arg1.arg
                expr = less_eq(ineq.arg1.arg1, num - delta)

            else:
                expr = less_eq(ineq.arg1, Real(0) - delta)

            pt_eq_comp = ProofTerm("real_eq_comparison", Eq(ineq, expr))
            leq_pt.insert(0, pt_2.on_prop(replace_conv(pt_eq_comp)))
            if i != len(pts) - 1:
                pt_b = pt_1

        return leq_pt
Пример #2
0
 def get_proof_term(self, t):
     if eval_hol_expr(t.arg1) <= eval_hol_expr(t.arg):
         return apply_theorem('real_max_eq_right',
                              auto.auto_solve(real.less_eq(t.arg1, t.arg)))
     else:
         return apply_theorem('real_max_eq_left',
                              auto.auto_solve(real.greater(t.arg1, t.arg)))
Пример #3
0
    def handle_geq_stage2(self, pt_lower_bound, pts, delta):
        # get ⊢ x_i ≥ δ, i = 1...n
        geq_pt = []
        pt_a = pt_lower_bound
        d = set()

        for i in range(len(pts)):
            if i != len(pts) - 1:
                pt = logic.apply_theorem("both_geq_min", pt_a)
                pt_1, pt_2 = logic.apply_theorem("conjD1",
                                                 pt), logic.apply_theorem(
                                                     "conjD2", pt)
            else:
                pt_2 = pt_a

            ineq = pt_2.prop

            if ineq.arg1.is_minus() and ineq.arg1.arg.is_number():
                # move all constant term from left to right in pt_2's prop
                num = ineq.arg1.arg
                expr = greater_eq(ineq.arg1.arg1, num + delta)

            else:
                expr = greater_eq(ineq.arg1, Real(0) + delta)

            pt_eq_comp = ProofTerm("real_eq_comparison", Eq(ineq, expr))
            geq_pt.insert(0, pt_2.on_prop(replace_conv(pt_eq_comp)))

            if i != len(pts) - 1:
                pt_a = pt_1

        return geq_pt
Пример #4
0
 def ineq_mul_const(c, pt):
     assert c != 0
     pt_c = get_const_comp_pt(c)
     if c > 0:
         return logic.apply_theorem('int_geq_zero_mul_pos', pt_c, pt)
     else:
         return logic.apply_theorem('int_geq_zero_mul_neg', pt_c, pt)
Пример #5
0
def interval_union_subset(t):
    """Given t of the form I1 Un I2, return a theorem of the form
    I1 Un I2 SUB I.

    """
    assert t.is_comb('union', 2), "interval_union_subset"

    I1, I2 = t.args
    a, b = I1.args
    c, d = I2.args
    if is_closed_interval(I1) and is_closed_interval(I2):
        pt = apply_theorem('closed_interval_union',
                           inst=Inst(a=a, b=b, c=c, d=d))
        return pt.on_prop(
            arg_conv(
                then_conv(arg1_conv(const_min_conv()),
                          arg_conv(const_max_conv()))))
    elif is_open_interval(I1) and is_ropen_interval(I2):
        if eval_hol_expr(c) <= eval_hol_expr(a):
            pt = apply_theorem('open_ropen_interval_union1',
                               auto.auto_solve(real.less_eq(c, a)),
                               inst=Inst(b=b, d=d))
        else:
            pt = apply_theorem('open_ropen_interval_union2',
                               auto.auto_solve(real.less(a, c)),
                               inst=Inst(b=b, d=d))
        return pt.on_prop(arg_conv(arg_conv(const_max_conv())))
    else:
        raise NotImplementedError

    return pt
Пример #6
0
 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:]))
Пример #7
0
Файл: nat.py Проект: bzhan/holpy
def ineq_one_proof_term(n):
    """Returns the inequality n ~= 1."""
    assert n != 1, "ineq_one_proof_term: n = 1"
    if n == 0:
        return apply_theorem("ineq_sym", ProofTerm.theorem("one_nonzero"))
    elif n % 2 == 0:
        return apply_theorem("bit0_neq_one", inst=Inst(m=Binary(n // 2)))
    else:
        return apply_theorem("bit1_neq_one", ineq_zero_proof_term(n // 2))
Пример #8
0
Файл: nat.py Проект: bzhan/holpy
def ineq_zero_proof_term(n):
    """Returns the inequality n ~= 0."""
    assert n != 0, "ineq_zero_proof_term: n = 0"
    if n == 1:
        return ProofTerm.theorem("one_nonzero")
    elif n % 2 == 0:
        return apply_theorem("bit0_nonzero", ineq_zero_proof_term(n // 2))
    else:
        return apply_theorem("bit1_nonzero", inst=Inst(m=Binary(n // 2)))
Пример #9
0
    def get_proof_term(self, goal, pts):
        assert len(pts) == 1 and hol_set.is_mem(pts[0].prop) and pts[0].prop.arg1.is_var(), \
            "interval_inequality"
        var_name = pts[0].prop.arg1.name
        var_range = {var_name: pts[0]}

        if goal.is_not() and goal.arg.is_equals():
            if expr.is_polynomial(expr.holpy_to_expr(goal.arg.arg1)):
                factored = expr.expr_to_holpy(
                    expr.factor_polynomial(expr.holpy_to_expr(goal.arg.arg1)))
                if factored.is_times() and factored != goal.arg.arg1:
                    eq_pt = auto.auto_solve(Eq(factored, goal.arg.arg1))
                    pt1 = get_bounds_proof(factored, var_range).on_prop(
                        arg1_conv(rewr_conv(eq_pt)))
                else:
                    pt1 = get_bounds_proof(goal.arg.arg1, var_range)
            else:
                pt1 = get_bounds_proof(goal.arg.arg1, var_range)
            pt2 = get_bounds_proof(goal.arg.arg, var_range)
            try:
                pt = combine_interval_bounds(pt1, pt2)
                if pt.prop.is_less_eq():
                    raise TacticException
                pt = apply_theorem('real_lt_neq', pt)
            except TacticException:
                pt = combine_interval_bounds(pt2, pt1)
                if pt.prop.is_less_eq():
                    raise TacticException
                pt = apply_theorem('real_gt_neq', reverse_inequality(pt))
            return pt
        else:
            pt1 = get_bounds_proof(goal.arg1, var_range)
            pt2 = get_bounds_proof(goal.arg, var_range)
            if goal.is_less_eq():
                pt = combine_interval_bounds(pt1, pt2)
                if pt.prop.is_less():
                    pt = apply_theorem('real_lt_imp_le', pt)
                return pt
            elif goal.is_less():
                pt = combine_interval_bounds(pt1, pt2)
                if pt.prop.is_less_eq():
                    raise TacticException
                return pt
            elif goal.is_greater_eq():
                pt = combine_interval_bounds(pt2, pt1)
                if pt.prop.is_less():
                    pt = apply_theorem('real_lt_imp_le', pt)
                return reverse_inequality(pt)
            elif goal.is_greater():
                pt = combine_interval_bounds(pt2, pt1)
                if pt.prop.is_less_eq():
                    raise TacticException
                return reverse_inequality(pt)
            else:
                raise AssertionError('interval_inequality')
Пример #10
0
    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)
Пример #11
0
    def __call__(self, item):
        if not isinstance(item, FactItem):
            return None

        prop = item.prop
        if not prop.is_conj():
            return None
        else:
            return [
                FactItem(logic.apply_theorem('conjD1', item.pt)),
                FactItem(logic.apply_theorem('conjD2', item.pt))
            ]
Пример #12
0
    def get_proof_term(self, tm):
        if not tm.is_equals() or not int_eval(tm.lhs) != 0 or not int_eval(
                tm.rhs) == 0:
            raise ConvException(str(tm))

        lhs_value = int_eval(tm.lhs)
        if lhs_value > 0:
            premise_pt = ProofTerm("int_const_ineq",
                                   greater(IntType)(Int(lhs_value), Int(0)))
            return apply_theorem("int_pos_neq_zero", premise_pt)
        else:
            premise_pt = ProofTerm("int_const_ineq",
                                   less(IntType)(Int(lhs_value), Int(0)))
            return apply_theorem("int_neg_neq_zero", premise_pt)
Пример #13
0
    def get_proof_term(self, args, pts):

        # First, find the pair i, j such that B_j = ~A_i or A_i = ~B_j, the
        # variable side records the side of the positive literal.
        pt1, pt2 = pts
        disj1 = strip_num(pt1.prop, args[0])
        disj2 = strip_num(pt2.prop, args[1])
        side = None
        for i, t1 in enumerate(disj1):
            for j, t2 in enumerate(disj2):
                if t2 == Not(t1):
                    side = 'left'
                    break
                elif t1 == Not(t2):
                    side = 'right'
                    break
            if side is not None:
                break

        assert side is not None, "resolution: literal not found"

        # If side is wrong, just swap:
        if side == 'right':
            return self.get_proof_term([args[1], args[0]], [pt2, pt1])

        # Move items i and j to the front
        disj1 = [disj1[i]] + disj1[:i] + disj1[i + 1:]
        disj2 = [disj2[j]] + disj2[:j] + disj2[j + 1:]
        eq_pt1 = logic.imp_disj_iff(Eq(pt1.prop, Or(*disj1)))
        eq_pt2 = logic.imp_disj_iff(Eq(pt2.prop, Or(*disj2)))
        pt1 = eq_pt1.equal_elim(pt1)
        pt2 = eq_pt2.equal_elim(pt2)

        if len(disj1) > 1 and len(disj2) > 1:
            pt = logic.apply_theorem('resolution', pt1, pt2)
        elif len(disj1) > 1 and len(disj2) == 1:
            pt = logic.apply_theorem('resolution_left', pt1, pt2)
        elif len(disj1) == 1 and len(disj2) > 1:
            pt = logic.apply_theorem('resolution_right', pt1, pt2)
        else:
            pt = logic.apply_theorem('negE', pt2, pt1)

        # return pt.on_prop(disj_norm())
        disj_new = set(disj1[1:] + disj2[1:])
        # eq_pt_norm = logic.imp_disj_iff(Eq(pt.prop, Or(*disj_new)))
        implies_pt_norm = ProofTerm("imp_disj",
                                    Implies(pt.prop, Or(*disj_new)))
        pt_final = implies_pt_norm.implies_elim(pt)
        self.arity = len(disj_new)
        return pt_final.on_prop(conv.top_conv(conv.rewr_conv("double_neg")))
Пример #14
0
def inequality_trans(pt1, pt2):
    """Given two inequalities of the form x </<= y and y </<= z, combine
    to form x </<= z.

    """
    if pt1.prop.is_less_eq() and pt2.prop.is_less_eq():
        return apply_theorem('real_le_trans', pt1, pt2)
    elif pt1.prop.is_less_eq() and pt2.prop.is_less():
        return apply_theorem('real_let_trans', pt1, pt2)
    elif pt1.prop.is_less() and pt2.prop.is_less_eq():
        return apply_theorem('real_lte_trans', pt1, pt2)
    elif pt1.prop.is_less() and pt2.prop.is_less():
        return apply_theorem('real_lt_trans', pt1, pt2)
    else:
        raise AssertionError("inequality_trans")
Пример #15
0
    def get_proof_term(self, args, prevs):
        pt0 = prevs[0]
        goal = args[0]

        pt1 = pt0.on_prop(rewr_conv("de_morgan_thm2"))
        pt2 = pt1
        while pt2.prop != goal:
            pt_l = logic.apply_theorem("conjD1", pt2)
            pt_r = logic.apply_theorem("conjD2", pt2)
            if pt_l.prop == goal:
                pt2 = pt_l
                break
            else:
                pt2 = pt_r

        return pt2
Пример #16
0
    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)
Пример #17
0
    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"))
Пример #18
0
 def helper(t):
     if t.head == N:
         n, = t.args
         return apply_theorem("avalI_const", concl=avalI(s, N(n), n))
     elif t.head == V:
         x, = t.args
         pt = apply_theorem("avalI_var", concl=avalI(s, V(x), s(x)))
         return pt.on_arg(function.fun_upd_eval_conv())
     elif t.head == Plus:
         a1, a2 = t.args
         pt = apply_theorem("avalI_plus", helper(a1), helper(a2))
         return pt.on_arg(nat.nat_conv())
     elif t.head == Times:
         a1, a2 = t.args
         pt = apply_theorem("avalI_times", helper(a1), helper(a2))
         return pt.on_arg(nat.nat_conv())
Пример #19
0
Файл: nat.py Проект: bzhan/holpy
 def get_proof_term(self, goal, pts):
     assert isinstance(goal, Term)
     assert len(pts) == 0, "nat_const_less_macro"
     m, n = goal.args
     assert m.dest_number() < n.dest_number()
     less_eq_pt = nat_const_less_eq_macro().get_proof_term(m <= n, [])
     ineq_pt = nat_const_ineq_macro().get_proof_term(Not(Eq(m, n)), [])
     return apply_theorem("less_lesseqI", less_eq_pt, ineq_pt)
Пример #20
0
    def get_proof_term(self, goal, *, args=None, prevs=None):
        assert isinstance(args, Term), "cases"

        As = goal.hyps
        C = goal.prop
        goal1 = ProofTerm.sorry(Thm(goal.hyps, Implies(args, C)))
        goal2 = ProofTerm.sorry(Thm(goal.hyps, Implies(Not(args), C)))
        return apply_theorem('classical_cases', goal1, goal2)
Пример #21
0
def vcg(T, goal):
    """Compute the verification conditions for the goal. Here the
    goal is of the form Valid P c Q. The function returns a proof term
    showing [] |- Valid P c Q.
    
    """
    P, c, Q = goal.args
    pt = compute_wp(T, c, Q)
    entail_P = ProofTerm.assume(Entail(T)(P, pt.prop.args[0]))
    return apply_theorem("pre_rule", entail_P, pt)
Пример #22
0
Файл: nat.py Проект: bzhan/holpy
    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))
Пример #23
0
 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:]))
Пример #24
0
 def get_proof_term(self, goal, prevs=None):
     """{(not (= x_1 y_1)) ... (not (= x_n y_n)) (not (p x_1 ... x_n)) (p y_1 ... y_n)}
     Special case: (not (= x y)) (not (p x y)) (p y x)
     """
     elems = goal.strip_disj()
     preds, pred_fun, concl = elems[:-2], elems[-2], elems[-1]
     if pred_fun.is_not():
         args_pair = [(i, j) for i, j in zip(pred_fun.arg.strip_comb()[1],
                                             concl.strip_comb()[1])]
     else:
         args_pair = [(i, j) for i, j in zip(pred_fun.strip_comb()[1],
                                             concl.arg.strip_comb()[1])]
     if len(preds) > 1:
         preds_pair = [(i.arg.lhs, i.arg.rhs) for i in preds]
     else:
         preds_pair = [(preds[0].arg.lhs, preds[0].arg.rhs),
                       (preds[0].arg.lhs, preds[0].arg.rhs)]
     if pred_fun.is_not():
         fun = concl.head
     else:
         fun = pred_fun.head
     pt0 = ProofTerm.reflexive(fun)
     pt_args_assms = []
     for arg, pred in zip(args_pair, preds_pair):
         if arg == pred:
             pt_args_assms.append(ProofTerm.assume(Eq(pred[0], pred[1])))
         elif arg[0] == pred[1] and pred[0] == arg[1]:
             pt_args_assms.append(
                 ProofTerm.assume(Eq(pred[0], pred[1])).symmetric())
         else:
             raise NotImplementedError
     pt1 = functools.reduce(lambda x, y: x.combination(y), pt_args_assms,
                            pt0)
     if pred_fun.is_not():
         pt2 = logic.apply_theorem("eq_implies1", pt1).implies_elim(
             ProofTerm.assume(pred_fun.arg))
         return ProofTerm("imp_to_or", elems[:-1] + [goal], prevs=[pt2])
     else:
         pt2 = pt1.on_prop(conv.rewr_conv("neg_iff_both_sides"))
         pt3 = logic.apply_theorem("eq_implies1", pt2).implies_elim(
             ProofTerm.assume(Not(pred_fun)))
         return ProofTerm("imp_to_or", elems[:-1] + [goal], prevs=[pt3])
Пример #25
0
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
Пример #26
0
    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')))
Пример #27
0
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())
Пример #28
0
    def real_combine_pt(self, pt1, pt2, c1, c2):
        """
        pt1, pt2 are all proof terms which prop is a normal inequality,
        v is the variable index which will be elimated.
        c1, c2 are the coefficient pt1, pt2's prop need to multiply
        """
        def get_const_comp_pt(c):
            """
            c is a number, return a pt: c ⋈ 0
            """
            if c > 0:
                return proofterm.ProofTerm(
                    'int_const_ineq',
                    term.greater(term.IntType)(term.Int(c), term.Int(0)))
            else:
                return proofterm.ProofTerm(
                    'int_const_ineq',
                    term.less(term.IntType)(term.Int(c), term.Int(0)))

        def ineq_mul_const(c, pt):
            assert c != 0
            pt_c = get_const_comp_pt(c)
            if c > 0:
                return logic.apply_theorem('int_geq_zero_mul_pos', pt_c, pt)
            else:
                return logic.apply_theorem('int_geq_zero_mul_neg', pt_c, pt)

        pt1_mul_c1, pt2_mul_c2 = ineq_mul_const(c1,
                                                pt1), ineq_mul_const(c2, pt2)
        pt_final = logic.apply_theorem(
            'int_pos_plus', pt1_mul_c1,
            pt2_mul_c2).on_prop(conv.arg_conv(integer.omega_simp_full_conv()))

        if pt_final.prop.arg.is_number():  # ⊢ 0 <= -3
            pt_less_zero = proofterm.ProofTerm(
                'int_const_ineq',
                term.less(term.IntType)(pt_final.prop.arg, term.Int(0)))
            return logic.apply_theorem('int_zero_less_eq_neg', pt_less_zero,
                                       pt_final)
        else:
            return pt_final
Пример #29
0
    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)
Пример #30
0
    def handle_geq_stage1(self, pts):
        if not pts:
            return None, None, None

        # ⊢ min(min(...(min(x_1, x_2), x_3)...), x_n-1), x_n) > 0
        min_pos_pt = functools.reduce(
            lambda pt1, pt2: logic.apply_theorem("min_greater_0", pt1, pt2),
            pts[1:], pts[0])

        # ⊢ 0 < 2
        two_pos_pt = ProofTerm("real_compare", Real(0) < Real(2))

        # ⊢ min(...) / 2 > 0
        min_divides_two_pos = logic.apply_theorem(
            "real_lt_div", min_pos_pt.on_prop(rewr_conv("real_ge_to_le")),
            two_pos_pt).on_prop(rewr_conv("real_ge_to_le", sym=True))

        # ⊢ 2 ≥ 1
        two_larger_one = ProofTerm("real_compare", Real(2) >= Real(1))

        # ⊢ min(...) ≥ min(...) / 2
        larger_half_pt = logic.apply_theorem("real_divides_larger_1",
                                             two_larger_one, min_pos_pt)

        # ⊢ min(...) / 2 = δ_1
        delta_1 = Var("δ_1", RealType)
        pt_delta1_eq = ProofTerm.assume(Eq(larger_half_pt.prop.arg, delta_1))

        # ⊢ min(...) ≥ δ_1
        larger_half_pt_delta = larger_half_pt.on_prop(
            top_conv(replace_conv(pt_delta1_eq)))

        # ⊢ δ_1 > 0
        delta_1_pos = min_divides_two_pos.on_prop(
            arg1_conv(replace_conv(pt_delta1_eq)))

        return larger_half_pt_delta, delta_1_pos, pt_delta1_eq