Пример #1
0
    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
Пример #2
0
    def __call__(self, *args):
        if not (len(args) == 1 and isinstance(args[0], FactItem)):
            return []

        t = args[0].prop
        pt = args[0].pt
        res = []

        if self.prop.is_equals():
            try:
                inst = matcher.first_order_match(self.prop.lhs, t)
                res.append(FactItem(self.pt.substitution(inst).equal_elim(pt)))
            except matcher.MatchException:
                pass
        elif self.prop.is_implies():
            try:
                inst = matcher.first_order_match(self.prop.arg1, t)
                res.append(
                    FactItem(self.pt.substitution(inst).implies_elim(pt)))
            except matcher.MatchException:
                pass
        else:
            pass

        return res
Пример #3
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)
Пример #4
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')))
Пример #5
0
    def testFirstOrderMatchFun(self):
        """First-order matching of variables in function position."""
        P = Var("P", TFun(Ta, boolT))
        Q = Var("Q", TFun(Ta, boolT))
        C = Const("C", TFun(boolT, boolT, boolT))

        test_data = [
            (abs(x, P(x)), abs(x, C(P(x), Q(x))), {
                "P": abs(x, C(P(x), Q(x)))
            }),
            (abs(x, C(P(x), Q(x))), abs(x, C(Q(x), P(x))), {
                "P": Q,
                "Q": P
            }),
            (abs(x, C(P(x), P(x))), abs(x, C(C(P(x), Q(x)), C(P(x), Q(x)))), {
                "P": abs(x, C(P(x), Q(x)))
            }),
            (exists(x, P(x)), exists(x, conj(P(x), Q(x))), {
                "P": abs(x, conj(P(x), Q(x)))
            }),
        ]

        for pat, t, inst in test_data:
            if inst is not None:
                self.assertEqual(matcher.first_order_match(pat, t)[1], inst)
            else:
                self.assertRaises(matcher.MatchException,
                                  matcher.first_order_match, pat, t)
Пример #6
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())
Пример #7
0
    def get_proof_term(self, t):
        if not t.is_compares():
            raise ConvException('%s is not a comparison.' % str(t))

        pt = refl(t)
        pt_norm_form = pt.on_rhs(norm_eq(), arg1_conv(omega_simp_full_conv()))
        summands = strip_plus(pt_norm_form.rhs.arg1)
        coeffs = [
            int_eval(s.arg1) if not s.is_number() else int_eval(s)
            for s in summands
        ]
        g = functools.reduce(gcd, coeffs)
        if g <= 1:
            return pt

        vars = [s.arg for s in summands if not s.is_number()]
        elim_gcd_coeffs = [int(i / g) for i in coeffs]
        if len(vars) < len(coeffs):
            simp_t = sum([
                coeff * v for coeff, v in zip(elim_gcd_coeffs[1:-1], vars[1:])
            ], elim_gcd_coeffs[0] * vars[0]) + Int(elim_gcd_coeffs[-1])
        else:
            simp_t = sum(
                [coeff * v for coeff, v in zip(elim_gcd_coeffs[1:], vars[1:])],
                elim_gcd_coeffs[0] * vars[0])

        simp_t_times_gcd = Int(g) * simp_t
        pt_simp_t_times_gcd = refl(simp_t_times_gcd).on_rhs(
            omega_simp_full_conv()).symmetric()
        pt_c = ProofTerm('int_const_ineq', greater(IntType)(Int(g), Int(0)))
        if t.is_less():
            gcd_pt = ProofTerm.theorem('int_simp_less')
        elif t.is_less_eq():
            gcd_pt = ProofTerm.theorem('int_simp_leq')
        elif t.is_greater():
            gcd_pt = ProofTerm.theorem('int_simp_gt')
        elif t.is_greater_eq():
            gcd_pt = ProofTerm.theorem('int_simp_geq')

        inst1 = matcher.first_order_match(gcd_pt.prop.arg1, pt_c.prop)
        inst2 = matcher.first_order_match(gcd_pt.prop.arg.rhs.arg1,
                                          simp_t,
                                          inst=inst1)

        pt_simp = gcd_pt.substitution(inst2).implies_elim(pt_c).on_lhs(
            arg1_conv(omega_simp_full_conv()))
        return pt_norm_form.transitive(pt_simp).on_rhs(omega_form_conv())
Пример #8
0
 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))
Пример #9
0
    def get_proof_term(self, args, pts):
        th_name, goal = args
        pt = ProofTerm.theorem(th_name)
        assert pt.prop.is_not(), "resolve_theorem_macro"

        # Match for variables in pt.
        inst = matcher.first_order_match(pt.prop.arg, pts[0].prop)
        pt = pt.subst_type(inst.tyinst).substitution(inst)
        pt = apply_theorem('negE', pt, pts[0])  # false
        return apply_theorem('falseE', pt, concl=goal)
Пример #10
0
def apply_theorem(th_name, *pts, concl=None, inst=None):
    """Wrapper for apply_theorem and apply_theorem_for macros.

    The function takes optional arguments concl, inst. Matching
    always starts with inst. If conclusion is specified, it is
    matched next. Finally, the assumptions are matched.

    """
    typecheck.checkinstance('apply_theorem', pts, [ProofTerm])
    if concl is None and inst is None:
        # Normal case, can use apply_theorem
        return ProofTerm("apply_theorem", th_name, pts)
    else:
        pt = ProofTerm.theorem(th_name)
        if inst is None:
            inst = Inst()
        if concl is not None:
            inst = matcher.first_order_match(pt.concl, concl, inst)
        for i, prev in enumerate(pts):
            inst = matcher.first_order_match(pt.assums[i], prev.prop, inst)
        return ProofTerm("apply_theorem_for", (th_name, inst), pts)
Пример #11
0
    def get_proof_term(self, goal, *, args=None, prevs=None):
        assert isinstance(prevs, list) and len(prevs) >= 1, "apply_prev"
        pt, prev_pts = prevs[0], prevs[1:]

        # First, obtain the patterns
        new_names = logic.get_forall_names(pt.prop)
        new_vars, As, C = logic.strip_all_implies(pt.prop, new_names)
        assert len(prev_pts) <= len(As), "apply_prev: too many prev_pts"

        if args is None:
            inst = Inst()
        else:
            inst = args
        inst = matcher.first_order_match(C, goal.prop, inst)
        for idx, prev_pt in enumerate(prev_pts):
            inst = matcher.first_order_match(As[idx], prev_pt.prop, inst)

        unmatched_vars = [v for v in new_names if v not in inst]
        if unmatched_vars:
            raise theory.ParameterQueryException(
                list("param_" + name for name in unmatched_vars))

        pt = pt.subst_type(inst.tyinst)
        for new_name in new_names:
            pt = pt.forall_elim(inst[new_name])
        if pt.prop.beta_norm() != pt.prop:
            pt = pt.on_prop(beta_norm_conv())
        inst_As, inst_C = pt.prop.strip_implies()

        inst_arg = [inst[new_name] for new_name in new_names]
        new_goals = [
            ProofTerm.sorry(Thm(goal.hyps, A)) for A in inst_As[len(prev_pts):]
        ]
        if set(new_names).issubset({v.name for v in term.get_vars(As)}) and \
           matcher.is_pattern_list(As, []):
            return ProofTerm('apply_fact', args=None, prevs=prevs + new_goals)
        else:
            return ProofTerm('apply_fact_for',
                             args=inst_arg,
                             prevs=prevs + new_goals)
Пример #12
0
    def run_test(self, thy_name, pat, t, *, vars=None, svars=None, tyinst=None, inst=None, failed=None):
        context.set_context(thy_name, vars=vars, svars=svars)

        pat, t = Term(pat), Term(t)
        inst = Inst((nm, Term(s)) for nm, s in inst.items()) if inst is not None else Inst()
        if tyinst is not None:
            inst.tyinst = TyInst((nm, Type(s)) for nm, s in tyinst.items())

        if failed is not None:
            self.assertRaises(failed, first_order_match, pat, t)
            return

        self.assertEqual(first_order_match(pat, t), inst)
Пример #13
0
    def get_proof_term(self, t):
        # If self.eq_pt is not present, produce it from thy, self.pt
        # and self.sym. Decompose into self.As and self.C.
        if self.eq_pt is None:
            if isinstance(self.pt, str):
                self.eq_pt = ProofTerm.theorem(self.pt)
            else:
                self.eq_pt = self.pt

            self.As, self.C = self.eq_pt.prop.strip_implies()

        # The conclusion of eq_pt should be an equality, and the number of
        # assumptions in eq_pt should match number of conditions.
        assert self.C.is_equals(), "rewr_conv: theorem is not an equality."
        if len(self.As) != len(self.conds):
            raise ConvException("rewr_conv: number of conds does not agree")

        inst = Inst()
        ts = [cond.prop for cond in self.conds]
        if not self.sym:
            lhs = self.C.lhs
        else:
            lhs = self.C.rhs
        try:
            inst = matcher.first_order_match_list(self.As, ts, inst)
            inst = matcher.first_order_match(lhs, t, inst)
        except matcher.MatchException:
            raise ConvException("rewr_conv: cannot match left side")

        # Check that every variable in the theorem has an instantiation
        if set(term.get_svars(self.As + [lhs])) != set(
                term.get_svars(self.As + [self.C])):
            raise ConvException("rewr_conv: unmatched vars")

        pt = self.eq_pt
        pt = pt.substitution(inst)
        pt = pt.implies_elim(*self.conds)
        if self.sym:
            pt = pt.symmetric()

        assert pt.th.is_equals(), "rewr_conv: wrong result."

        if pt.th.prop.lhs != t:
            pt = pt.on_prop(beta_norm_conv())

        if pt.th.prop.lhs != t:
            pt = pt.on_prop(eta_conv())

        assert pt.th.prop.lhs == t, "rewr_conv: wrong result. Expected %s, got %s" % (
            str(t), str(pt.th.prop.lhs))
        return pt
Пример #14
0
    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
Пример #15
0
    def testFirstOrderMatchType(self):
        test_data = [
            (x, m, ({
                "a": natT
            }, {
                "x": m
            })),
            (p, m, ({}, {
                "p": m
            })),
        ]

        for pat, t, instsp in test_data:
            if instsp is not None:
                self.assertEqual(matcher.first_order_match(pat, t), instsp)
            else:
                self.assertRaises(matcher.MatchException,
                                  matcher.first_order_match, pat, t)
Пример #16
0
    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
Пример #17
0
    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
Пример #18
0
    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)
Пример #19
0
    def testFirstOrderMatch(self):
        test_data = [
            (x, y, {
                "x": y
            }),
            (x, a, {
                "x": a
            }),
            (a, a, {}),
            (a, b, None),
            (f(x, y), f(a, b), {
                "x": a,
                "y": b
            }),
            (f(x, x), f(a, a), {
                "x": a
            }),
            (f(x, x), f(a, b), None),
            (abs(x, y), abs(x, a), {
                "y": a
            }),
            (abs(x, a), abs(x, a), {}),
            (abs(x, a), abs(x, b), None),
            (abs(x, y), abs(x, x), None),
            (abs(x, z), abs(x, abs(y, y)), {
                "z": abs(y, y)
            }),
            (abs(x, y), abs(x, abs(y, x)), None),
            (abs(x, x), abs(x, x), {}),
            (abs(x, abs(y, y)), abs(x, abs(y, x)), None),
        ]

        for pat, t, inst in test_data:
            if inst is not None:
                self.assertEqual(matcher.first_order_match(pat, t)[1], inst)
            else:
                self.assertRaises(matcher.MatchException,
                                  matcher.first_order_match, pat, t)
Пример #20
0
    def get_proof_term(self, args, pts):
        if not self.with_inst:
            assert len(pts) >= 2, "apply fact: too few prevs"

        pt, pt_prevs = pts[0], pts[1:]

        # First, obtain the patterns
        new_names = get_forall_names(pt.prop)

        new_vars, As, C = strip_all_implies(pt.prop, new_names)
        assert len(pt_prevs) <= len(As), "apply_fact: too many prevs"

        if self.with_inst:
            assert len(args) == len(new_names), "apply_fact_macro: wrong number of args."
            inst = Inst({nm: v for nm, v in zip(new_names, args)})
        else:
            inst = Inst()
            for idx, pt_prev in enumerate(pt_prevs):
                inst = matcher.first_order_match(As[idx], pt_prev.prop, inst)

        pt = pt.subst_type(inst.tyinst)
        for new_var in new_vars:
            if new_var.name in inst:
                pt = pt.forall_elim(inst[new_var.name])
            else:
                pt = pt.forall_elim(new_var)
        if pt.prop.beta_norm() != pt.prop:
            pt = pt.on_prop(beta_norm_conv())
        for prev_pt in pt_prevs:
            if prev_pt.prop != pt.assums[0]:
                prev_pt = prev_pt.on_prop(beta_norm_conv())
            pt = pt.implies_elim(prev_pt)
        for new_var in new_vars:
            if new_var.name not in inst:
                pt = pt.forall_intr(new_var)

        return pt
Пример #21
0
    def get_proof_term(self, args, prevs=None):
        """
        Let x_i denotes greater comparison, x__i denotes less comparison,
        for the greater comparison, find the smallest number x_min = min(x_1, ..., x_n), since x_min is positive, 
        x_min/2 > 0 ==> x_min >= x_min / 2 ==> x_1, ..., x_n >= x_min / 2 ==> ∃δ. δ > 0 ∧ x_1 >= δ ∧ ... ∧ x_n >= δ.
        for the less comparison, find the largest number x_max = max(x__1, ..., x__n), since x_max is negative, x_max < 
        x_max/2 ==> x__1, ..., x__n <= x_max/2;
        let δ = min(x_min/2, -x_max/2), then all x_i >= δ as well as all x__i <= -δ.
        """
        def need_convert(tm):
            return False if real_eval(tm.arg) != 0 else True

        original_ineq_pts = [ProofTerm.assume(ineq) for ineq in args]

        # record the ineq which rhs is not 0
        need_convert_pt = {arg for arg in args if need_convert(arg)}

        # record the args order
        order_args = {args[i].arg1: i for i in range(len(args))}

        # convert all ineqs to x_i > 0 or x_i < 0
        normal_ineq_pts = [
            pt.on_prop(norm_real_ineq_conv()) if pt.prop.arg != Real(0) else pt
            for pt in original_ineq_pts
        ]

        # dividing less comparison and greater comparison
        greater_ineq_pts = [
            pt for pt in normal_ineq_pts if pt.prop.is_greater()
        ]
        less_ineq_pts = [pt for pt in normal_ineq_pts if pt.prop.is_less()]

        # stage 1: get the max(min) pos bound
        # ⊢ min(...) ≥ δ_1, δ_1 > 0
        # ⊢ max(...) ≤ δ_2, δ_2 < 0
        pt_lower_bound, lower_bound_pos_pt, pt_assert_delta1 = self.handle_geq_stage1(
            greater_ineq_pts)
        pt_upper_bound, upper_bound_neg_pt, pt_assert_delta2 = self.handle_leq_stage1(
            less_ineq_pts)

        delta_1 = Var("δ_1", RealType)
        delta_2 = Var("δ_2", RealType)

        # generate the relaxed inequations
        if pt_lower_bound is None:  # all comparisons are ≤
            pts = self.handle_leq_stage2(pt_upper_bound, less_ineq_pts,
                                         delta_2)
            bound_pt = upper_bound_neg_pt
            delta = delta_2
            pt_asserts = [pt_assert_delta2]
        elif pt_upper_bound is None:  # all comparisons are ≥
            pts = self.handle_geq_stage2(pt_lower_bound, greater_ineq_pts,
                                         delta_1)
            bound_pt = lower_bound_pos_pt
            delta = delta_1
            pt_asserts = [pt_assert_delta1]
        else:  # have both ≥ and ≤
            # ⊢ δ_1 ≥ min(δ_1, δ_2)
            pt_min_lower_bound = logic.apply_theorem("real_greater_min",
                                                     inst=matcher.Inst(
                                                         x=delta_1, y=delta_2))
            # ⊢ -δ_2 ≤ max(-δ_2, -δ_1)
            pt_max_upper_bound = logic.apply_theorem("real_less_max",
                                                     inst=matcher.Inst(
                                                         x=-delta_2,
                                                         y=-delta_1))
            # ⊢ max(-δ_2, -δ_1) = -min(δ_1, δ_2)
            pt_max_min = logic.apply_theorem("max_min",
                                             inst=matcher.Inst(x=delta_1,
                                                               y=delta_2))
            # ⊢ min(...) ≥ min(δ_1, δ_2)
            pt_new_lower_bound = logic.apply_theorem("real_geq_trans",
                                                     pt_lower_bound,
                                                     pt_min_lower_bound)
            # ⊢ -δ_2 ≤ -min(δ_1, δ_2)
            pt_max_upper_bound_1 = pt_max_upper_bound.on_prop(
                arg_conv(replace_conv(pt_max_min)))
            # ⊢ max(...) ≤ -min(δ_1, δ_2)
            pt_new_upper_bound = logic.apply_theorem("real_le_trans",
                                                     pt_upper_bound,
                                                     pt_max_upper_bound_1)
            # ⊢ min(δ_1, δ_2) > 0
            pt_new_lower_bound_pos = logic.apply_theorem(
                "min_pos", lower_bound_pos_pt, upper_bound_neg_pt)
            # ⊢ min(δ_1, δ_2) = δ
            delta = Var("δ", RealType)
            pt_delta_eq = ProofTerm.assume(
                Eq(pt_min_lower_bound.prop.arg, delta))
            pt_asserts = [pt_delta_eq, pt_assert_delta1, pt_assert_delta2]
            # ⊢ min(...) ≥ δ
            pt_new_lower_bound_delta = pt_new_lower_bound.on_prop(
                arg_conv(replace_conv(pt_delta_eq)))
            # ⊢ max(...) ≤ -δ
            pt_new_upper_bound_delta = pt_new_upper_bound.on_prop(
                top_conv(replace_conv(pt_delta_eq)))
            # use new bound
            pts_leq = self.handle_leq_stage2(pt_new_upper_bound_delta,
                                             less_ineq_pts, delta)
            pts_geq = self.handle_geq_stage2(pt_new_lower_bound_delta,
                                             greater_ineq_pts, delta)
            pts = pts_leq + pts_geq
            bound_pt = pt_new_lower_bound_pos.on_prop(
                arg1_conv(replace_conv(pt_delta_eq)))

        # sort_pts = sorted(pts, key=lambda pt: order_args[pt.prop.arg1])

        pt_conj = functools.reduce(
            lambda x, y: logic.apply_theorem("conjI", y, x),
            reversed([bound_pt] + pts))

        # get ⊢∃δ. δ > 0 ∧ x_1 >= δ ∧ ... ∧ x_n >= δ
        th = ProofTerm.theorem("exI")
        inst = matcher.first_order_match(th.prop.arg,
                                         Exists(delta, pt_conj.prop))
        pt_conj_exists = logic.apply_theorem("exI", pt_conj, inst=inst)
        pt_final = pt_conj_exists
        for pt_subst in pt_asserts:
            lhs, rhs = pt_subst.prop.args
            if not rhs.is_uminus():
                pt_final = pt_final.implies_intr(pt_subst.prop).forall_intr(rhs).\
                            forall_elim(lhs).implies_elim(ProofTerm.reflexive(lhs))
            else:
                pt_final = pt_final.implies_intr(pt_subst.prop).forall_intr(rhs.arg).\
                    forall_elim(-lhs).on_prop(top_conv(rewr_conv("real_neg_neg"))).implies_elim(ProofTerm.reflexive(lhs))
        return pt_final
Пример #22
0
    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()))