Spaces:
Sleeping
Sleeping
File size: 4,739 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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
from sympy.core.singleton import S
from sympy.core.symbol import Symbol
from sympy.core.logic import fuzzy_and, fuzzy_bool, fuzzy_not, fuzzy_or
from sympy.core.relational import Eq
from sympy.sets.sets import FiniteSet, Interval, Set, Union, ProductSet
from sympy.sets.fancysets import Complexes, Reals, Range, Rationals
from sympy.multipledispatch import Dispatcher
_inf_sets = [S.Naturals, S.Naturals0, S.Integers, S.Rationals, S.Reals, S.Complexes]
is_subset_sets = Dispatcher('is_subset_sets')
@is_subset_sets.register(Set, Set)
def _(a, b):
return None
@is_subset_sets.register(Interval, Interval)
def _(a, b):
# This is correct but can be made more comprehensive...
if fuzzy_bool(a.start < b.start):
return False
if fuzzy_bool(a.end > b.end):
return False
if (b.left_open and not a.left_open and fuzzy_bool(Eq(a.start, b.start))):
return False
if (b.right_open and not a.right_open and fuzzy_bool(Eq(a.end, b.end))):
return False
@is_subset_sets.register(Interval, FiniteSet)
def _(a_interval, b_fs):
# An Interval can only be a subset of a finite set if it is finite
# which can only happen if it has zero measure.
if fuzzy_not(a_interval.measure.is_zero):
return False
@is_subset_sets.register(Interval, Union)
def _(a_interval, b_u):
if all(isinstance(s, (Interval, FiniteSet)) for s in b_u.args):
intervals = [s for s in b_u.args if isinstance(s, Interval)]
if all(fuzzy_bool(a_interval.start < s.start) for s in intervals):
return False
if all(fuzzy_bool(a_interval.end > s.end) for s in intervals):
return False
if a_interval.measure.is_nonzero:
no_overlap = lambda s1, s2: fuzzy_or([
fuzzy_bool(s1.end <= s2.start),
fuzzy_bool(s1.start >= s2.end),
])
if all(no_overlap(s, a_interval) for s in intervals):
return False
@is_subset_sets.register(Range, Range)
def _(a, b):
if a.step == b.step == 1:
return fuzzy_and([fuzzy_bool(a.start >= b.start),
fuzzy_bool(a.stop <= b.stop)])
@is_subset_sets.register(Range, Interval)
def _(a_range, b_interval):
if a_range.step.is_positive:
if b_interval.left_open and a_range.inf.is_finite:
cond_left = a_range.inf > b_interval.left
else:
cond_left = a_range.inf >= b_interval.left
if b_interval.right_open and a_range.sup.is_finite:
cond_right = a_range.sup < b_interval.right
else:
cond_right = a_range.sup <= b_interval.right
return fuzzy_and([cond_left, cond_right])
@is_subset_sets.register(Range, FiniteSet)
def _(a_range, b_finiteset):
try:
a_size = a_range.size
except ValueError:
# symbolic Range of unknown size
return None
if a_size > len(b_finiteset):
return False
elif any(arg.has(Symbol) for arg in a_range.args):
return fuzzy_and(b_finiteset.contains(x) for x in a_range)
else:
# Checking A \ B == EmptySet is more efficient than repeated naive
# membership checks on an arbitrary FiniteSet.
a_set = set(a_range)
b_remaining = len(b_finiteset)
# Symbolic expressions and numbers of unknown type (integer or not) are
# all counted as "candidates", i.e. *potentially* matching some a in
# a_range.
cnt_candidate = 0
for b in b_finiteset:
if b.is_Integer:
a_set.discard(b)
elif fuzzy_not(b.is_integer):
pass
else:
cnt_candidate += 1
b_remaining -= 1
if len(a_set) > b_remaining + cnt_candidate:
return False
if len(a_set) == 0:
return True
return None
@is_subset_sets.register(Interval, Range)
def _(a_interval, b_range):
if a_interval.measure.is_extended_nonzero:
return False
@is_subset_sets.register(Interval, Rationals)
def _(a_interval, b_rationals):
if a_interval.measure.is_extended_nonzero:
return False
@is_subset_sets.register(Range, Complexes)
def _(a, b):
return True
@is_subset_sets.register(Complexes, Interval)
def _(a, b):
return False
@is_subset_sets.register(Complexes, Range)
def _(a, b):
return False
@is_subset_sets.register(Complexes, Rationals)
def _(a, b):
return False
@is_subset_sets.register(Rationals, Reals)
def _(a, b):
return True
@is_subset_sets.register(Rationals, Range)
def _(a, b):
return False
@is_subset_sets.register(ProductSet, FiniteSet)
def _(a_ps, b_fs):
return fuzzy_and(b_fs.contains(x) for x in a_ps)
|