Example #1
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
Example #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)))
Example #3
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')
Example #4
0
File: real.py Project: bzhan/holpy
    def get_proof_term(self, t):
        a, p = t.args

        # Exponent is an integer: apply rpow_pow
        if p.is_number() and p.is_comb('of_nat', 1) and p.arg.is_binary():
            return refl(t).on_rhs(
                arg_conv(rewr_conv('real_of_nat_id', sym=True)),
                rewr_conv('rpow_pow'))

        if not (a.is_number() and p.is_number()):
            raise ConvException

        a, p = a.dest_number(), p.dest_number()
        if a <= 0:
            raise ConvException

        # Case 1: base is a composite number
        factors = factorint(a)
        keys = list(factors.keys())
        if len(keys) > 1 or (len(keys) == 1 and keys[0] != a):
            b1 = list(factors.keys())[0]
            b2 = a // b1
            eq_th = refl(Real(b1) * b2).on_rhs(real_eval_conv())
            pt = refl(t).on_rhs(arg1_conv(rewr_conv(eq_th, sym=True)))
            pt = pt.on_rhs(rewr_conv('rpow_mul'))
            return pt

        # Case 2: exponent is not between 0 and 1
        if isinstance(p, Fraction) and p.numerator // p.denominator != 0:
            div, mod = divmod(p.numerator, p.denominator)
            eq_th = refl(Real(div) + Real(mod) / p.denominator).on_rhs(
                real_eval_conv())
            pt = refl(t).on_rhs(arg_conv(rewr_conv(eq_th, sym=True)))
            a_gt_0 = auto.auto_solve(Real(a) > 0)
            pt = pt.on_rhs(rewr_conv('rpow_add', conds=[a_gt_0]))
            return pt

        return refl(t)
Example #5
0
def get_bounds_proof(t, var_range):
    """Given a term t and a mapping from variables to intervals,
    return a theorem for t belonging to an interval.

    t - Term, a HOL expression.
    var_range - dict(str, Thm): mapping from variables x to theorems of
        the form x Mem [a, b] or x Mem (a, b).

    Returns a theorem of the form t Mem [a, b] or t Mem (a, b).

    """
    if t.ty == Term.VAR:
        assert t.name in var_range, "get_bounds_proof: variable %s not found" % t.name
        return var_range[t.name]

    elif t.is_number() or t == real.pi:
        return apply_theorem('const_interval', inst=Inst(x=t))

    elif t.is_plus():
        pt1 = get_bounds_proof(t.arg1, var_range)
        pt2 = get_bounds_proof(t.arg, var_range)
        if is_mem_closed(pt1) and is_mem_closed(pt2):
            pt = apply_theorem('add_interval_closed', pt1, pt2)
        elif is_mem_open(pt1) and is_mem_open(pt2):
            pt = apply_theorem('add_interval_open', pt1, pt2)
        elif is_mem_open(pt1) and is_mem_closed(pt2):
            pt = apply_theorem('add_interval_open_closed', pt1, pt2)
        elif is_mem_closed(pt1) and is_mem_open(pt2):
            pt = apply_theorem('add_interval_closed_open', pt1, pt2)
        elif is_mem_closed(pt1) and is_mem_lopen(pt2):
            pt = apply_theorem('add_interval_closed_lopen', pt1, pt2)
        elif is_mem_closed(pt1) and is_mem_ropen(pt2):
            pt = apply_theorem('add_interval_closed_ropen', pt1, pt2)
        elif is_mem_ropen(pt1) and is_mem_closed(pt2):
            pt = apply_theorem('add_interval_closed_ropen', pt2, pt1)
            pt = pt.on_prop(arg1_conv(rewr_conv('real_add_comm')))
        else:
            raise NotImplementedError('get_bounds: %s, %s' % (pt1, pt2))
        return norm_mem_interval(pt)

    elif t.is_uminus():
        pt = get_bounds_proof(t.arg, var_range)
        if is_mem_closed(pt):
            pt = apply_theorem('neg_interval_closed', pt)
        elif is_mem_open(pt):
            pt = apply_theorem('neg_interval_open', pt)
        else:
            raise NotImplementedError
        return norm_mem_interval(pt)

    elif t.is_minus():
        rewr_t = t.arg1 + (-t.arg)
        pt = get_bounds_proof(rewr_t, var_range)
        return pt.on_prop(arg1_conv(rewr_conv('real_minus_def', sym=True)))

    elif t.is_real_inverse():
        pt = get_bounds_proof(t.arg, var_range)
        a, b = get_mem_bounds(pt)
        if eval_hol_expr(a) > 0 and is_mem_closed(pt):
            pt = apply_theorem('inverse_interval_pos_closed',
                               auto.auto_solve(real_pos(a)), pt)
        else:
            raise NotImplementedError
        return norm_mem_interval(pt)

    elif t.is_times():
        if t.arg1.has_var():
            pt1 = get_bounds_proof(t.arg1, var_range)
            pt2 = get_bounds_proof(t.arg, var_range)
            a, b = get_mem_bounds(pt1)
            c, d = get_mem_bounds(pt2)
            if eval_hol_expr(a) >= 0 and eval_hol_expr(c) >= 0 and is_mem_open(
                    pt1) and is_mem_open(pt2):
                pt = apply_theorem('mult_interval_pos_pos_open',
                                   auto.auto_solve(real_nonneg(a)),
                                   auto.auto_solve(real_nonneg(c)), pt1, pt2)
            elif eval_hol_expr(a) >= 0 and eval_hol_expr(
                    c) >= 0 and is_mem_closed(pt1) and is_mem_closed(pt2):
                pt = apply_theorem('mult_interval_pos_pos_closed',
                                   auto.auto_solve(real_nonneg(a)),
                                   auto.auto_solve(real_nonneg(c)), pt1, pt2)
            elif eval_hol_expr(a) >= 0 and eval_hol_expr(
                    c) >= 0 and is_mem_lopen(pt1) and is_mem_ropen(pt2):
                pt = apply_theorem('mult_interval_pos_pos_lopen_ropen',
                                   auto.auto_solve(real_nonneg(a)),
                                   auto.auto_solve(real_nonneg(c)), pt1, pt2)
            elif eval_hol_expr(b) <= 0 and eval_hol_expr(
                    c) >= 0 and is_mem_open(pt1) and is_mem_open(pt2):
                pt = apply_theorem('mult_interval_neg_pos_open',
                                   auto.auto_solve(real_nonpos(b)),
                                   auto.auto_solve(real_nonneg(c)), pt1, pt2)
            else:
                raise NotImplementedError('get_bounds: %s, %s' % (pt1, pt2))
        else:
            pt = get_bounds_proof(t.arg, var_range)
            a, b = get_mem_bounds(pt)
            c = t.arg1
            nc = eval_hol_expr(c)
            if nc >= 0 and is_mem_closed(pt):
                pt = apply_theorem('mult_interval_pos_closed',
                                   auto.auto_solve(real_nonneg(c)), pt)
            elif nc >= 0 and is_mem_open(pt):
                pt = apply_theorem('mult_interval_pos_open',
                                   auto.auto_solve(real_nonneg(c)), pt)
            elif nc >= 0 and is_mem_lopen(pt):
                pt = apply_theorem('mult_interval_pos_lopen',
                                   auto.auto_solve(real_nonneg(c)), pt)
            elif nc >= 0 and is_mem_ropen(pt):
                pt = apply_theorem('mult_interval_pos_ropen',
                                   auto.auto_solve(real_nonneg(c)), pt)
            elif nc < 0 and is_mem_closed(pt):
                pt = apply_theorem('mult_interval_neg_closed',
                                   auto.auto_solve(real_neg(c)), pt)
            elif nc < 0 and is_mem_open(pt):
                pt = apply_theorem('mult_interval_neg_open',
                                   auto.auto_solve(real_neg(c)), pt)
            elif nc < 0 and is_mem_lopen(pt):
                pt = apply_theorem('mult_interval_neg_lopen',
                                   auto.auto_solve(real_neg(c)), pt)
            elif nc < 0 and is_mem_ropen(pt):
                pt = apply_theorem('mult_interval_neg_ropen',
                                   auto.auto_solve(real_neg(c)), pt)
            else:
                raise NotImplementedError
        return norm_mem_interval(pt)

    elif t.is_divides():
        rewr_t = t.arg1 * (real.inverse(t.arg))
        pt = get_bounds_proof(rewr_t, var_range)
        return pt.on_prop(arg1_conv(rewr_conv('real_divide_def', sym=True)))

    elif t.is_nat_power():
        pt = get_bounds_proof(t.arg1, var_range)
        if not t.arg.is_number():
            raise NotImplementedError
        return get_nat_power_bounds(pt, t.arg)

    elif t.is_real_power():
        pt = get_bounds_proof(t.arg1, var_range)
        a, b = get_mem_bounds(pt)
        if not t.arg.is_number():
            raise NotImplementedError
        p = t.arg.dest_number()
        if p >= 0 and eval_hol_expr(a) >= 0:
            nonneg_p = auto.auto_solve(real_nonneg(t.arg))
            nonneg_a = auto.auto_solve(real_nonneg(a))
            if is_mem_closed(pt):
                pt = apply_theorem('real_power_interval_pos_closed', nonneg_p,
                                   nonneg_a, pt)
            elif is_mem_open(pt):
                pt = apply_theorem('real_power_interval_pos_open', nonneg_p,
                                   nonneg_a, pt)
            else:
                raise NotImplementedError
        elif p < 0:
            neg_p = auto.auto_solve(real_neg(t.arg))
            if is_mem_closed(pt) and eval_hol_expr(a) > 0:
                pos_a = auto.auto_solve(real_pos(a))
                pt = apply_theorem('real_power_interval_neg_closed', neg_p,
                                   pos_a, pt)
            elif is_mem_open(pt):
                nonneg_a = auto.auto_solve(real_nonneg(a))
                pt = apply_theorem('real_power_interval_neg_open', neg_p,
                                   nonneg_a, pt)
            elif is_mem_lopen(pt):
                nonneg_a = auto.auto_solve(real_nonneg(a))
                pt = apply_theorem('real_power_interval_neg_lopen', neg_p,
                                   nonneg_a, pt)
            else:
                print(pt)
                raise NotImplementedError
        else:
            raise NotImplementedError
        return norm_mem_interval(pt)

    elif t.head == real.log:
        pt = get_bounds_proof(t.arg, var_range)
        a, b = get_mem_bounds(pt)
        if eval_hol_expr(a) > 0 and is_mem_closed(pt):
            pt = apply_theorem('log_interval_closed',
                               auto.auto_solve(real_pos(a)), pt)
        elif eval_hol_expr(a) >= 0 and is_mem_open(pt):
            pt = apply_theorem('log_interval_open',
                               auto.auto_solve(real_nonneg(a)), pt)
        else:
            raise NotImplementedError
        return norm_mem_interval(pt)

    elif t.head == real.exp:
        pt = get_bounds_proof(t.arg, var_range)
        if is_mem_closed(pt):
            pt = apply_theorem('exp_interval_closed', pt)
        elif is_mem_open(pt):
            pt = apply_theorem('exp_interval_open', pt)
        else:
            raise NotImplementedError
        return norm_mem_interval(pt)

    elif t.head == real.sin:
        pt = get_bounds_proof(t.arg, var_range)
        a, b = get_mem_bounds(pt)
        if eval_hol_expr(a) >= -math.pi / 2 and eval_hol_expr(
                b) <= math.pi / 2:
            if is_mem_closed(pt):
                pt = apply_theorem(
                    'sin_interval_main_closed',
                    auto.auto_solve(real.greater_eq(a, -real.pi / 2)),
                    auto.auto_solve(real.less_eq(b, real.pi / 2)), pt)
            elif is_mem_open(pt):
                pt = apply_theorem(
                    'sin_interval_main_open',
                    auto.auto_solve(real.greater_eq(a, -real.pi / 2)),
                    auto.auto_solve(real.less_eq(b, real.pi / 2)), pt)
            else:
                raise NotImplementedError
        elif eval_hol_expr(a) >= 0 and eval_hol_expr(b) <= math.pi:
            if is_mem_closed(pt):
                pt = apply_theorem('sin_interval_pos_closed',
                                   auto.auto_solve(real_nonneg(a)),
                                   auto.solve(real.less_eq(b, real.pi)), pt)
            elif is_mem_open(pt):
                pt = apply_theorem('sin_interval_pos_open',
                                   auto.auto_solve(real_nonneg(a)),
                                   auto.solve(real.less_eq(b, real.pi)), pt)
            else:
                raise NotImplementedError
        else:
            raise NotImplementedError
        return norm_mem_interval(pt)

    elif t.head == real.cos:
        pt = get_bounds_proof(t.arg, var_range)
        a, b = get_mem_bounds(pt)
        if eval_hol_expr(a) >= 0 and eval_hol_expr(b) <= math.pi:
            if is_mem_closed(pt):
                pt = apply_theorem('cos_interval_main_closed',
                                   auto.auto_solve(real_nonneg(a)),
                                   auto.auto_solve(real.less_eq(b, real.pi)),
                                   pt)
            elif is_mem_open(pt):
                pt = apply_theorem('cos_interval_main_open',
                                   auto.auto_solve(real_nonneg(a)),
                                   auto.auto_solve(real.less_eq(b, real.pi)),
                                   pt)
            else:
                raise NotImplementedError
        elif eval_hol_expr(a) >= -math.pi / 2 and eval_hol_expr(
                b) <= math.pi / 2:
            if is_mem_closed(pt):
                pt = apply_theorem(
                    'cos_interval_pos_closed',
                    auto.auto_solve(real.greater_eq(a, -real.pi / 2)),
                    auto.auto_solve(real.less_eq(b, real.pi / 2)), pt)
            elif is_mem_open(pt):
                pt = apply_theorem(
                    'cos_interval_pos_open',
                    auto.auto_solve(real.greater_eq(a, -real.pi / 2)),
                    auto.auto_solve(real.less_eq(b, real.pi / 2)), pt)
            else:
                raise NotImplementedError
        else:
            raise NotImplementedError
        return norm_mem_interval(pt)

    elif t.head == real.atn:
        pt = get_bounds_proof(t.arg, var_range)
        if is_mem_closed(pt):
            pt = apply_theorem('atn_interval_closed', pt)
        elif is_mem_open(pt):
            pt = apply_theorem('atn_interval_open', pt)
        else:
            raise NotImplementedError
        return norm_mem_interval(pt)

    else:
        print("Cannot deal with", t)
        raise NotImplementedError
Example #6
0
def get_nat_power_bounds(pt, n):
    """Given theorem of the form t Mem I, obtain a theorem of
    the form t ^ n Mem J.

    """
    a, b = get_mem_bounds(pt)
    if not n.is_number():
        raise NotImplementedError
    if eval_hol_expr(a) >= 0 and is_mem_closed(pt):
        pt = apply_theorem('nat_power_interval_pos_closed',
                           auto.auto_solve(real_nonneg(a)),
                           pt,
                           inst=Inst(n=n))
    elif eval_hol_expr(a) >= 0 and is_mem_open(pt):
        pt = apply_theorem('nat_power_interval_pos_open',
                           auto.auto_solve(real_nonneg(a)),
                           pt,
                           inst=Inst(n=n))
    elif eval_hol_expr(a) >= 0 and is_mem_lopen(pt):
        pt = apply_theorem('nat_power_interval_pos_lopen',
                           auto.auto_solve(real_nonneg(a)),
                           pt,
                           inst=Inst(n=n))
    elif eval_hol_expr(a) >= 0 and is_mem_ropen(pt):
        pt = apply_theorem('nat_power_interval_pos_ropen',
                           auto.auto_solve(real_nonneg(a)),
                           pt,
                           inst=Inst(n=n))
    elif eval_hol_expr(b) <= 0 and is_mem_closed(pt):
        int_n = n.dest_number()
        if int_n % 2 == 0:
            even_pt = nat_as_even(int_n)
            pt = apply_theorem('nat_power_interval_neg_even_closed',
                               auto.auto_solve(real_nonpos(b)), even_pt, pt)
        else:
            odd_pt = nat_as_odd(int_n)
            pt = apply_theorem('nat_power_interval_neg_odd_closed',
                               auto.auto_solve(real_nonpos(b)), odd_pt, pt)
    elif eval_hol_expr(b) <= 0 and is_mem_open(pt):
        int_n = n.dest_number()
        if int_n % 2 == 0:
            even_pt = nat_as_even(int_n)
            pt = apply_theorem('nat_power_interval_neg_even_open',
                               auto.auto_solve(real_nonpos(b)), even_pt, pt)
        else:
            odd_pt = nat_as_odd(int_n)
            pt = apply_theorem('nat_power_interval_neg_odd_open',
                               auto.auto_solve(real_nonpos(b)), odd_pt, pt)
    elif is_mem_closed(pt):
        # Closed interval containing 0
        t = pt.prop.arg1
        assm1 = hol_set.mk_mem(t, real.closed_interval(a, Real(0)))
        assm2 = hol_set.mk_mem(t, real.closed_interval(Real(0), b))
        pt1 = get_nat_power_bounds(ProofTerm.assume(assm1),
                                   n).implies_intr(assm1)
        pt2 = get_nat_power_bounds(ProofTerm.assume(assm2),
                                   n).implies_intr(assm2)
        x = Var('x', RealType)
        pt = apply_theorem('split_interval_closed',
                           auto.auto_solve(real.less_eq(a, Real(0))),
                           auto.auto_solve(real.less_eq(Real(0), b)),
                           pt1,
                           pt2,
                           pt,
                           inst=Inst(x=t, f=Lambda(x, x**n)))
        subset_pt = interval_union_subset(pt.prop.arg)
        pt = apply_theorem('subsetE', subset_pt, pt)
    elif is_mem_open(pt):
        # Open interval containing 0
        t = pt.prop.arg1
        assm1 = hol_set.mk_mem(t, real.open_interval(a, Real(0)))
        assm2 = hol_set.mk_mem(t, real.ropen_interval(Real(0), b))
        pt1 = get_nat_power_bounds(ProofTerm.assume(assm1),
                                   n).implies_intr(assm1)
        pt2 = get_nat_power_bounds(ProofTerm.assume(assm2),
                                   n).implies_intr(assm2)
        x = Var('x', RealType)
        pt = apply_theorem('split_interval_open',
                           auto.auto_solve(real.less_eq(a, Real(0))),
                           auto.auto_solve(real.less_eq(Real(0), b)),
                           pt1,
                           pt2,
                           pt,
                           inst=Inst(x=t, f=Lambda(x, x**n)))
        subset_pt = interval_union_subset(pt.prop.arg)
        pt = apply_theorem('subsetE', subset_pt, pt)
    else:
        raise NotImplementedError
    return norm_mem_interval(pt)
Example #7
0
def nat_as_odd(n):
    """Obtain theorem of form odd n."""
    assert n % 2 == 1, "nat_as_odd: n is not odd"
    eq_pt = auto.auto_solve(Eq(nat.Suc(Nat(2) * Nat(n // 2)), Nat(n)))
    pt = apply_theorem('odd_double', inst=Inst(n=Nat(n // 2)))
    return pt.on_prop(arg_conv(rewr_conv(eq_pt)))
Example #8
0
def nat_as_even(n):
    """Obtain theorem of form even n."""
    assert n % 2 == 0, "nat_as_even: n is not even"
    eq_pt = auto.auto_solve(Eq(Nat(2) * Nat(n // 2), Nat(n)))
    pt = apply_theorem('even_double', inst=Inst(n=Nat(n // 2)))
    return pt.on_prop(arg_conv(rewr_conv(eq_pt)))