Spaces:
Sleeping
Sleeping
File size: 3,186 Bytes
6a86ad5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
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')
@_set_pow.register(Basic, Basic)
def _(x, y):
return None
@_set_pow.register(Set, Set)
def _(x, y):
return ImageSet(Lambda((_x, _y), (_x ** _y)), x, y)
@_set_pow.register(Expr, Expr)
def _(x, y):
return x**y
@_set_pow.register(Interval, Zero)
def _(x, z):
return FiniteSet(S.One)
@_set_pow.register(Interval, Integer)
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)
@_set_pow.register(Interval, Infinity)
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)
@_set_pow.register(Interval, NegativeInfinity)
def _(b, e):
return _set_pow(set_div(S.One, b), oo)
|