Exemplo n.º 1
0
    def derive_element_in_restricted_number_set(self, **defaults_config):
        '''
        From (member in Interval(x, y)), where x ≥ 0 or y ≤ 0,
        deduce that the element is in Natural, NaturalPos, IntegerNeg,
        or IntegerNonPos as appropriate.
        '''
        _a = self.domain.lower_bound
        _b = self.domain.upper_bound
        _n = self.element

        # We wish to deduce a fact based upon the following
        # membership fact:
        self.expr.prove()

        if (not InSet(_a, Natural).proven()
                and not InSet(_b, IntegerNonPos).proven()):
            # If we don't know that a ≥ 0 or b ≤ 0, we can't prove
            # the element is in either restricted number set
            # (NaturalPos or IntegerNeg).  So, try to sort a, b, 0
            # to work this out.
            LessEq.sort([_a, _b, zero])

        if InSet(_a, Natural).proven():
            try:
                _a.deduce_in_number_set(NaturalPos, automation=False)
            except Exception:
                pass
            if InSet(_a, NaturalPos).proven():
                # member in N^{>0}
                lower_bounding = self.derive_element_lower_bound()
                a_bounding = greater(_a, zero)
                lower_bounding.apply_transitivity(a_bounding)
                return InSet(_n, NaturalPos).prove()
            else:
                # member in N
                lower_bounding = self.derive_element_lower_bound()
                a_bounding = greater_eq(_a, zero)
                lower_bounding.apply_transitivity(a_bounding)
                return InSet(_n, Natural).prove()
        if InSet(_b, IntegerNonPos).proven():
            try:
                _b.deduce_in_number_set(IntegerNeg, automation=False)
            except Exception:
                pass
            if InSet(_b, IntegerNeg).proven():
                # member in Z^{<0}
                upper_bounding = self.derive_element_upper_bound()
                b_bounding = Less(_b, zero)
                upper_bounding.apply_transitivity(b_bounding)
                return InSet(_n, IntegerNeg).prove()
            else:
                # member in Z^{≤0}
                upper_bounding = self.derive_element_upper_bound()
                b_bounding = LessEq(_b, zero)
                upper_bounding.apply_transitivity(b_bounding)
                return InSet(_n, IntegerNonPos).prove()
Exemplo n.º 2
0
 def abs_elimination(self, operand_type=None, **defaults_config):
     '''
     For some |x| expression, deduce either |x| = x (the default) OR
     |x| = -x (for operand_type = 'negative'). Assumptions may be
     needed to deduce x >= 0 or x < 0, respectively.
     '''
     from proveit.numbers import LessEq, zero
     from . import abs_non_neg_elim, abs_neg_elim
     if operand_type is None:
         # LessEq.sort uses a bidirectional search which should
         # be fairly efficient, as long as there aren't too
         # many known relationship directly or indirectly involving
         # self.operand or zero.
         relation_with_zero = LessEq.sort([zero, self.operand])
         if relation_with_zero.normal_lhs == zero:
             operand_type = 'non-negative'
         else:
             operand_type = 'negative'
     # deduce_non_neg(self.operand, assumptions) # NOT YET IMPLEMENTED
     if operand_type is None or operand_type == 'non-negative':
         return abs_non_neg_elim.instantiate({x: self.operand})
     elif operand_type == 'negative':
         return abs_neg_elim.instantiate({x: self.operand})
     else:
         raise ValueError(
             "Unsupported operand type for Abs.abs_elimination() "
             "method; operand type should be omitted or specified "
             "as 'negative' or 'non-negative', but instead was "
             "given as operand_type = {}.".format(operand_type))
Exemplo n.º 3
0
 def exponentiate_both_sides(self, exponent, **defaults_config):
     '''
     Exponentiate both sides of the relation by the 'exponent'.
     '''
     from proveit.numbers import Less, LessEq, zero, deduce_number_set
     from proveit.numbers.exponentiation import (exp_pos_less,
                                                 exp_nonneg_less,
                                                 exp_neg_less,
                                                 exp_nonpos_less)
     # We need to know how the exponent relates to zero.
     deduce_number_set(exponent)
     LessEq.sort([zero, exponent])
     if Less(zero, exponent).proven():
         new_rel = exp_pos_less.instantiate({
             a: exponent,
             x: self.lower,
             y: self.upper
         })
     elif Less(exponent, zero).proven():
         new_rel = exp_neg_less.instantiate({
             a: exponent,
             x: self.lower,
             y: self.upper
         })
     elif LessEq(zero, exponent).proven():
         new_rel = exp_nonneg_less.instantiate({
             a: exponent,
             x: self.lower,
             y: self.upper
         })
     elif LessEq(exponent, zero).proven():
         new_rel = exp_nonpos_less.instantiate({
             a: exponent,
             x: self.lower,
             y: self.upper
         })
     else:
         raise Exception("Cannot exponentiate both sides of %s by %s "
                         "without knowing the exponent's relation with "
                         "zero" % (self, exponent))
     return new_rel.with_mimicked_style(self)
Exemplo n.º 4
0
    def bound_via_denominator_bound(self, relation, **defaults_config):
        '''
        Given a relation applicable to the numerator,  bound this
        division accordingly.  For example,
        if self is "a / b" and the relation is b > y
        return (a / b) < (a / y), provided a, b, and y are positive.

        Also see NumberOperation.deduce_bound.
        '''
        from proveit.numbers import zero, Less, LessEq, greater, greater_eq
        from . import (strong_div_from_denom_bound__all_pos,
                       weak_div_from_denom_bound__all_pos,
                       strong_div_from_denom_bound__all_neg,
                       weak_div_from_denom_bound__all_neg,
                       strong_div_from_denom_bound__neg_over_pos,
                       weak_div_from_denom_bound__neg_over_pos,
                       strong_div_from_denom_bound__pos_over_neg,
                       weak_div_from_denom_bound__pos_over_neg)
        if isinstance(relation, Judgment):
            relation = relation.expr
        if not (isinstance(relation, Less) or isinstance(relation, LessEq)):
            raise TypeError("relation is expected to be Less "
                            "or LessEq number relations, not %s" % relation)
        if self.denominator not in relation.operands:
            raise ValueError("relation is expected to involve the "
                             "denominator of %s.  %s does not." %
                             (self, relation))
        _a = self.numerator
        _x = relation.normal_lhs
        _y = relation.normal_rhs
        try:
            # Ensure that we relate both _x and _y to zero by knowing
            # one of these.
            ordering = LessEq.sort((_x, _y, zero))
            ordering.operands[0].apply_transitivity(ordering.operands[1])
        except:
            pass  # We'll generate an appropriate error below.
        try:
            deduce_number_set(self.numerator)
            deduce_number_set(self.denominator)
        except UnsatisfiedPrerequisites:
            pass
        pos_numer = greater_eq(self.numerator, zero).proven()
        neg_numer = LessEq(self.numerator, zero).proven()
        pos_denom = greater(self.denominator, zero).proven()
        neg_denom = Less(self.denominator, zero).proven()
        if not (pos_numer or neg_numer) or not (pos_denom or neg_denom):
            raise UnsatisfiedPrerequisites(
                "We must know the sign of the numerator and "
                "denominator of %s before we can use "
                "'bound_via_denominator_bound'." % self)
        if pos_numer and pos_denom:
            if isinstance(relation, Less):
                bound = strong_div_from_denom_bound__all_pos.instantiate({
                    a: _a,
                    x: _x,
                    y: _y
                })
            elif isinstance(relation, LessEq):
                bound = weak_div_from_denom_bound__all_pos.instantiate({
                    a: _a,
                    x: _x,
                    y: _y
                })
        elif neg_numer and neg_denom:
            if isinstance(relation, Less):
                bound = strong_div_from_denom_bound__all_neg.instantiate({
                    a: _a,
                    x: _x,
                    y: _y
                })
            elif isinstance(relation, LessEq):
                bound = weak_div_from_denom_bound__all_neg.instantiate({
                    a: _a,
                    x: _x,
                    y: _y
                })
        elif pos_numer and neg_denom:
            if isinstance(relation, Less):
                bound = strong_div_from_denom_bound__pos_over_neg.instantiate({
                    a:
                    _a,
                    x:
                    _x,
                    y:
                    _y
                })
            elif isinstance(relation, LessEq):
                bound = weak_div_from_denom_bound__pos_over_neg.instantiate({
                    a:
                    _a,
                    x:
                    _x,
                    y:
                    _y
                })
        elif neg_numer and pos_denom:
            if isinstance(relation, Less):
                bound = strong_div_from_denom_bound__neg_over_pos.instantiate({
                    a:
                    _a,
                    x:
                    _x,
                    y:
                    _y
                })
            elif isinstance(relation, LessEq):
                bound = weak_div_from_denom_bound__neg_over_pos.instantiate({
                    a:
                    _a,
                    x:
                    _x,
                    y:
                    _y
                })
        else:
            raise UnsatisfiedPrerequisites(
                "We must know whether or not the denominator of %s "
                "is positive or negative before we can use "
                "'bound_via_denominator_bound'." % self)
        if bound.rhs == self:
            return bound.with_direction_reversed()
        return bound
Exemplo n.º 5
0
    def derive_element_in_restricted_number_set(self, **defaults_config):
        '''
        From (element in IntervalXX(x, y)), where x ≥ 0 or y ≤ 0,
        derive that the element is in RealPos, RealNeg, RealNonPos, or
        RealNonNeg as appropriate.
        '''
        from proveit.numbers import (zero, RealPos, RealNonNeg, 
                                     RealNeg, RealNonPos)
        from proveit.numbers import Less, LessEq, greater, greater_eq        
        _a = self.domain.lower_bound
        _b = self.domain.upper_bound
        _n = self.element
        
        # We wish to deduce a fact based upon the following
        # membership fact:
        self.expr.prove()

        if (not InSet(_a, RealNonNeg).proven() and 
                not InSet(_b, RealNonPos).proven()):
            try:
                _a.deduce_in_number_set(RealNonNeg, automation=False)
            except Exception:
                pass
            try:
                _b.deduce_in_number_set(RealNonPos, automation=False)
            except Exception:
                pass
            if (not InSet(_a, RealNonNeg).proven() and 
                    not InSet(_b, RealNonPos).proven()):
                # If we don't know that a ≥ 0 or b ≤ 0, we can't prove
                # the element is in either restricted number set
                # (NaturalPos or IntegerNeg).  So, try to sort a, b, 0
                # to work this out.
                LessEq.sort([_a, _b, zero])

        if InSet(_a, RealNonNeg).proven():
            try:
                _a.deduce_in_number_set(RealPos, automation=False)
            except Exception:
                pass
            lower_bound = self.derive_element_lower_bound()
            a_bound = greater_eq(_a, zero)
            if InSet(_a, RealPos).proven():
                a_bound = greater(_a, zero)
            lower_bound.apply_transitivity(a_bound)
            if (isinstance(self, IntervalOO) 
                    or isinstance(self, IntervalOC)
                    or InSet(_a, RealPos).proven()):
                # member in R^{>0}
                return InSet(_n, RealPos).prove()
            else:
                # member in R^{≥0}
                return InSet(_n, RealNonNeg).prove()
        if InSet(_b, RealNonPos).proven():
            try:
                _b.deduce_in_number_set(RealNeg, automation=False)
            except Exception:
                pass
            upper_bound = self.derive_element_upper_bound()
            b_bound = LessEq(_b, zero)
            if InSet(_b, RealNeg).proven():
                b_bound = Less(_b, zero)                
            upper_bound.apply_transitivity(b_bound)
            if (isinstance(self, IntervalOO)
                    or isinstance(self, IntervalCO)
                    or InSet(_b, RealNeg).proven()):
                # member in R^{<0}
                return InSet(_n, RealNeg).prove()
            else:
                # member in R^{≤0}
                return InSet(_n, RealNonPos).prove()