Coverage for /usr/lib/python3/dist-packages/sympy/sets/handlers/union.py: 42%
103 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1from sympy.core.singleton import S
2from sympy.core.sympify import sympify
3from sympy.functions.elementary.miscellaneous import Min, Max
4from sympy.sets.sets import (EmptySet, FiniteSet, Intersection,
5 Interval, ProductSet, Set, Union, UniversalSet)
6from sympy.sets.fancysets import (ComplexRegion, Naturals, Naturals0,
7 Integers, Rationals, Reals)
8from sympy.multipledispatch import Dispatcher
11union_sets = Dispatcher('union_sets')
14@union_sets.register(Naturals0, Naturals)
15def _(a, b):
16 return a
18@union_sets.register(Rationals, Naturals)
19def _(a, b):
20 return a
22@union_sets.register(Rationals, Naturals0)
23def _(a, b):
24 return a
26@union_sets.register(Reals, Naturals)
27def _(a, b):
28 return a
30@union_sets.register(Reals, Naturals0)
31def _(a, b):
32 return a
34@union_sets.register(Reals, Rationals)
35def _(a, b):
36 return a
38@union_sets.register(Integers, Set)
39def _(a, b):
40 intersect = Intersection(a, b)
41 if intersect == a:
42 return b
43 elif intersect == b:
44 return a
46@union_sets.register(ComplexRegion, Set)
47def _(a, b):
48 if b.is_subset(S.Reals):
49 # treat a subset of reals as a complex region
50 b = ComplexRegion.from_real(b)
52 if b.is_ComplexRegion:
53 # a in rectangular form
54 if (not a.polar) and (not b.polar):
55 return ComplexRegion(Union(a.sets, b.sets))
56 # a in polar form
57 elif a.polar and b.polar:
58 return ComplexRegion(Union(a.sets, b.sets), polar=True)
59 return None
61@union_sets.register(EmptySet, Set)
62def _(a, b):
63 return b
66@union_sets.register(UniversalSet, Set)
67def _(a, b):
68 return a
70@union_sets.register(ProductSet, ProductSet)
71def _(a, b):
72 if b.is_subset(a):
73 return a
74 if len(b.sets) != len(a.sets):
75 return None
76 if len(a.sets) == 2:
77 a1, a2 = a.sets
78 b1, b2 = b.sets
79 if a1 == b1:
80 return a1 * Union(a2, b2)
81 if a2 == b2:
82 return Union(a1, b1) * a2
83 return None
85@union_sets.register(ProductSet, Set)
86def _(a, b):
87 if b.is_subset(a):
88 return a
89 return None
91@union_sets.register(Interval, Interval)
92def _(a, b):
93 if a._is_comparable(b):
94 # Non-overlapping intervals
95 end = Min(a.end, b.end)
96 start = Max(a.start, b.start)
97 if (end < start or
98 (end == start and (end not in a and end not in b))):
99 return None
100 else:
101 start = Min(a.start, b.start)
102 end = Max(a.end, b.end)
104 left_open = ((a.start != start or a.left_open) and
105 (b.start != start or b.left_open))
106 right_open = ((a.end != end or a.right_open) and
107 (b.end != end or b.right_open))
108 return Interval(start, end, left_open, right_open)
110@union_sets.register(Interval, UniversalSet)
111def _(a, b):
112 return S.UniversalSet
114@union_sets.register(Interval, Set)
115def _(a, b):
116 # If I have open end points and these endpoints are contained in b
117 # But only in case, when endpoints are finite. Because
118 # interval does not contain oo or -oo.
119 open_left_in_b_and_finite = (a.left_open and
120 sympify(b.contains(a.start)) is S.true and
121 a.start.is_finite)
122 open_right_in_b_and_finite = (a.right_open and
123 sympify(b.contains(a.end)) is S.true and
124 a.end.is_finite)
125 if open_left_in_b_and_finite or open_right_in_b_and_finite:
126 # Fill in my end points and return
127 open_left = a.left_open and a.start not in b
128 open_right = a.right_open and a.end not in b
129 new_a = Interval(a.start, a.end, open_left, open_right)
130 return {new_a, b}
131 return None
133@union_sets.register(FiniteSet, FiniteSet)
134def _(a, b):
135 return FiniteSet(*(a._elements | b._elements))
137@union_sets.register(FiniteSet, Set)
138def _(a, b):
139 # If `b` set contains one of my elements, remove it from `a`
140 if any(b.contains(x) == True for x in a):
141 return {
142 FiniteSet(*[x for x in a if b.contains(x) != True]), b}
143 return None
145@union_sets.register(Set, Set)
146def _(a, b):
147 return None