Spaces:
Sleeping
Sleeping
from sympy.core import Basic, Expr | |
from sympy.core.function import Lambda | |
from sympy.core.numbers import oo, Infinity, NegativeInfinity, Zero, Integer | |
from sympy.core.singleton import S | |
from sympy.core.symbol import symbols | |
from sympy.functions.elementary.miscellaneous import (Max, Min) | |
from sympy.sets.fancysets import ImageSet | |
from sympy.sets.setexpr import set_div | |
from sympy.sets.sets import Set, Interval, FiniteSet, Union | |
from sympy.multipledispatch import Dispatcher | |
_x, _y = symbols("x y") | |
_set_pow = Dispatcher('_set_pow') | |
def _(x, y): | |
return None | |
def _(x, y): | |
return ImageSet(Lambda((_x, _y), (_x ** _y)), x, y) | |
def _(x, y): | |
return x**y | |
def _(x, z): | |
return FiniteSet(S.One) | |
def _(x, exponent): | |
""" | |
Powers in interval arithmetic | |
https://en.wikipedia.org/wiki/Interval_arithmetic | |
""" | |
s1 = x.start**exponent | |
s2 = x.end**exponent | |
if ((s2 > s1) if exponent > 0 else (x.end > -x.start)) == True: | |
left_open = x.left_open | |
right_open = x.right_open | |
# TODO: handle unevaluated condition. | |
sleft = s2 | |
else: | |
# TODO: `s2 > s1` could be unevaluated. | |
left_open = x.right_open | |
right_open = x.left_open | |
sleft = s1 | |
if x.start.is_positive: | |
return Interval( | |
Min(s1, s2), | |
Max(s1, s2), left_open, right_open) | |
elif x.end.is_negative: | |
return Interval( | |
Min(s1, s2), | |
Max(s1, s2), left_open, right_open) | |
# Case where x.start < 0 and x.end > 0: | |
if exponent.is_odd: | |
if exponent.is_negative: | |
if x.start.is_zero: | |
return Interval(s2, oo, x.right_open) | |
if x.end.is_zero: | |
return Interval(-oo, s1, True, x.left_open) | |
return Union(Interval(-oo, s1, True, x.left_open), Interval(s2, oo, x.right_open)) | |
else: | |
return Interval(s1, s2, x.left_open, x.right_open) | |
elif exponent.is_even: | |
if exponent.is_negative: | |
if x.start.is_zero: | |
return Interval(s2, oo, x.right_open) | |
if x.end.is_zero: | |
return Interval(s1, oo, x.left_open) | |
return Interval(0, oo) | |
else: | |
return Interval(S.Zero, sleft, S.Zero not in x, left_open) | |
def _(b, e): | |
# TODO: add logic for open intervals? | |
if b.start.is_nonnegative: | |
if b.end < 1: | |
return FiniteSet(S.Zero) | |
if b.start > 1: | |
return FiniteSet(S.Infinity) | |
return Interval(0, oo) | |
elif b.end.is_negative: | |
if b.start > -1: | |
return FiniteSet(S.Zero) | |
if b.end < -1: | |
return FiniteSet(-oo, oo) | |
return Interval(-oo, oo) | |
else: | |
if b.start > -1: | |
if b.end < 1: | |
return FiniteSet(S.Zero) | |
return Interval(0, oo) | |
return Interval(-oo, oo) | |
def _(b, e): | |
return _set_pow(set_div(S.One, b), oo) | |