|
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): |
|
|
|
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): |
|
|
|
|
|
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: |
|
|
|
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: |
|
|
|
|
|
a_set = set(a_range) |
|
b_remaining = len(b_finiteset) |
|
|
|
|
|
|
|
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) |
|
|