union.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. from sympy.core.singleton import S
  2. from sympy.core.sympify import sympify
  3. from sympy.functions.elementary.miscellaneous import Min, Max
  4. from sympy.sets.sets import (EmptySet, FiniteSet, Intersection,
  5. Interval, ProductSet, Set, Union, UniversalSet)
  6. from sympy.sets.fancysets import (ComplexRegion, Naturals, Naturals0,
  7. Integers, Rationals, Reals)
  8. from sympy.multipledispatch import Dispatcher
  9. union_sets = Dispatcher('union_sets')
  10. @union_sets.register(Naturals0, Naturals)
  11. def _(a, b):
  12. return a
  13. @union_sets.register(Rationals, Naturals)
  14. def _(a, b):
  15. return a
  16. @union_sets.register(Rationals, Naturals0)
  17. def _(a, b):
  18. return a
  19. @union_sets.register(Reals, Naturals)
  20. def _(a, b):
  21. return a
  22. @union_sets.register(Reals, Naturals0)
  23. def _(a, b):
  24. return a
  25. @union_sets.register(Reals, Rationals)
  26. def _(a, b):
  27. return a
  28. @union_sets.register(Integers, Set)
  29. def _(a, b):
  30. intersect = Intersection(a, b)
  31. if intersect == a:
  32. return b
  33. elif intersect == b:
  34. return a
  35. @union_sets.register(ComplexRegion, Set)
  36. def _(a, b):
  37. if b.is_subset(S.Reals):
  38. # treat a subset of reals as a complex region
  39. b = ComplexRegion.from_real(b)
  40. if b.is_ComplexRegion:
  41. # a in rectangular form
  42. if (not a.polar) and (not b.polar):
  43. return ComplexRegion(Union(a.sets, b.sets))
  44. # a in polar form
  45. elif a.polar and b.polar:
  46. return ComplexRegion(Union(a.sets, b.sets), polar=True)
  47. return None
  48. @union_sets.register(EmptySet, Set)
  49. def _(a, b):
  50. return b
  51. @union_sets.register(UniversalSet, Set)
  52. def _(a, b):
  53. return a
  54. @union_sets.register(ProductSet, ProductSet)
  55. def _(a, b):
  56. if b.is_subset(a):
  57. return a
  58. if len(b.sets) != len(a.sets):
  59. return None
  60. if len(a.sets) == 2:
  61. a1, a2 = a.sets
  62. b1, b2 = b.sets
  63. if a1 == b1:
  64. return a1 * Union(a2, b2)
  65. if a2 == b2:
  66. return Union(a1, b1) * a2
  67. return None
  68. @union_sets.register(ProductSet, Set)
  69. def _(a, b):
  70. if b.is_subset(a):
  71. return a
  72. return None
  73. @union_sets.register(Interval, Interval)
  74. def _(a, b):
  75. if a._is_comparable(b):
  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