mul.py 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. from sympy.core import Basic, Expr
  2. from sympy.core.numbers import oo
  3. from sympy.core.symbol import symbols
  4. from sympy.multipledispatch import Dispatcher
  5. from sympy.sets.setexpr import set_mul
  6. from sympy.sets.sets import Interval, Set
  7. _x, _y = symbols("x y")
  8. _set_mul = Dispatcher('_set_mul')
  9. _set_div = Dispatcher('_set_div')
  10. @_set_mul.register(Basic, Basic)
  11. def _(x, y):
  12. return None
  13. @_set_mul.register(Set, Set)
  14. def _(x, y):
  15. return None
  16. @_set_mul.register(Expr, Expr)
  17. def _(x, y):
  18. return x*y
  19. @_set_mul.register(Interval, Interval)
  20. def _(x, y):
  21. """
  22. Multiplications in interval arithmetic
  23. https://en.wikipedia.org/wiki/Interval_arithmetic
  24. """
  25. # TODO: some intervals containing 0 and oo will fail as 0*oo returns nan.
  26. comvals = (
  27. (x.start * y.start, bool(x.left_open or y.left_open)),
  28. (x.start * y.end, bool(x.left_open or y.right_open)),
  29. (x.end * y.start, bool(x.right_open or y.left_open)),
  30. (x.end * y.end, bool(x.right_open or y.right_open)),
  31. )
  32. # TODO: handle symbolic intervals
  33. minval, minopen = min(comvals)
  34. maxval, maxopen = max(comvals)
  35. return Interval(
  36. minval,
  37. maxval,
  38. minopen,
  39. maxopen
  40. )
  41. @_set_div.register(Basic, Basic)
  42. def _(x, y):
  43. return None
  44. @_set_div.register(Expr, Expr)
  45. def _(x, y):
  46. return x/y
  47. @_set_div.register(Set, Set)
  48. def _(x, y):
  49. return None
  50. @_set_div.register(Interval, Interval)
  51. def _(x, y):
  52. """
  53. Divisions in interval arithmetic
  54. https://en.wikipedia.org/wiki/Interval_arithmetic
  55. """
  56. if (y.start*y.end).is_negative:
  57. return Interval(-oo, oo)
  58. if y.start == 0:
  59. s2 = oo
  60. else:
  61. s2 = 1/y.start
  62. if y.end == 0:
  63. s1 = -oo
  64. else:
  65. s1 = 1/y.end
  66. return set_mul(x, Interval(s1, s2, y.right_open, y.left_open))