union.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. from sympy.core.singleton import S
  2. from sympy.core.sympify import sympify
  3. from sympy.sets.sets import (EmptySet, FiniteSet, Intersection,
  4. Interval, ProductSet, Set, Union, UniversalSet)
  5. from sympy.sets.fancysets import (ComplexRegion, Naturals, Naturals0,
  6. Integers, Rationals, Reals)
  7. from sympy.multipledispatch import Dispatcher
  8. union_sets = Dispatcher('union_sets')
  9. @union_sets.register(Naturals0, Naturals)
  10. def _(a, b):
  11. return a
  12. @union_sets.register(Rationals, Naturals)
  13. def _(a, b):
  14. return a
  15. @union_sets.register(Rationals, Naturals0)
  16. def _(a, b):
  17. return a
  18. @union_sets.register(Reals, Naturals)
  19. def _(a, b):
  20. return a
  21. @union_sets.register(Reals, Naturals0)
  22. def _(a, b):
  23. return a
  24. @union_sets.register(Reals, Rationals)
  25. def _(a, b):
  26. return a
  27. @union_sets.register(Integers, Set)
  28. def _(a, b):
  29. intersect = Intersection(a, b)
  30. if intersect == a:
  31. return b
  32. elif intersect == b:
  33. return a
  34. @union_sets.register(ComplexRegion, Set)
  35. def _(a, b):
  36. if b.is_subset(S.Reals):
  37. # treat a subset of reals as a complex region
  38. b = ComplexRegion.from_real(b)
  39. if b.is_ComplexRegion:
  40. # a in rectangular form
  41. if (not a.polar) and (not b.polar):
  42. return ComplexRegion(Union(a.sets, b.sets))
  43. # a in polar form
  44. elif a.polar and b.polar:
  45. return ComplexRegion(Union(a.sets, b.sets), polar=True)
  46. return None
  47. @union_sets.register(EmptySet, Set)
  48. def _(a, b):
  49. return b
  50. @union_sets.register(UniversalSet, Set)
  51. def _(a, b):
  52. return a
  53. @union_sets.register(ProductSet, ProductSet)
  54. def _(a, b):
  55. if b.is_subset(a):
  56. return a
  57. if len(b.sets) != len(a.sets):
  58. return None
  59. if len(a.sets) == 2:
  60. a1, a2 = a.sets
  61. b1, b2 = b.sets
  62. if a1 == b1:
  63. return a1 * Union(a2, b2)
  64. if a2 == b2:
  65. return Union(a1, b1) * a2
  66. return None
  67. @union_sets.register(ProductSet, Set)
  68. def _(a, b):
  69. if b.is_subset(a):
  70. return a
  71. return None
  72. @union_sets.register(Interval, Interval)
  73. def _(a, b):
  74. if a._is_comparable(b):
  75. from sympy.functions.elementary.miscellaneous import Min, Max
  76. # Non-overlapping intervals
  77. end = Min(a.end, b.end)
  78. start = Max(a.start, b.start)
  79. if (end < start or
  80. (end == start and (end not in a and end not in b))):
  81. return None
  82. else:
  83. start = Min(a.start, b.start)
  84. end = Max(a.end, b.end)
  85. left_open = ((a.start != start or a.left_open) and
  86. (b.start != start or b.left_open))
  87. right_open = ((a.end != end or a.right_open) and
  88. (b.end != end or b.right_open))
  89. return Interval(start, end, left_open, right_open)
  90. @union_sets.register(Interval, UniversalSet)
  91. def _(a, b):
  92. return S.UniversalSet
  93. @union_sets.register(Interval, Set)
  94. def _(a, b):
  95. # If I have open end points and these endpoints are contained in b
  96. # But only in case, when endpoints are finite. Because
  97. # interval does not contain oo or -oo.
  98. open_left_in_b_and_finite = (a.left_open and
  99. sympify(b.contains(a.start)) is S.true and
  100. a.start.is_finite)
  101. open_right_in_b_and_finite = (a.right_open and
  102. sympify(b.contains(a.end)) is S.true and
  103. a.end.is_finite)
  104. if open_left_in_b_and_finite or open_right_in_b_and_finite:
  105. # Fill in my end points and return
  106. open_left = a.left_open and a.start not in b
  107. open_right = a.right_open and a.end not in b
  108. new_a = Interval(a.start, a.end, open_left, open_right)
  109. return {new_a, b}
  110. return None
  111. @union_sets.register(FiniteSet, FiniteSet)
  112. def _(a, b):
  113. return FiniteSet(*(a._elements | b._elements))
  114. @union_sets.register(FiniteSet, Set)
  115. def _(a, b):
  116. # If `b` set contains one of my elements, remove it from `a`
  117. if any(b.contains(x) == True for x in a):
  118. return {
  119. FiniteSet(*[x for x in a if b.contains(x) != True]), b}
  120. return None
  121. @union_sets.register(Set, Set)
  122. def _(a, b):
  123. return None