I am done

This commit is contained in:
2024-10-30 22:14:35 +01:00
parent 720dc28c09
commit 40e2a747cf
36901 changed files with 5011519 additions and 0 deletions

View File

@ -0,0 +1,36 @@
from .sets import (Set, Interval, Union, FiniteSet, ProductSet,
Intersection, imageset, Complement, SymmetricDifference,
DisjointUnion)
from .fancysets import ImageSet, Range, ComplexRegion
from .contains import Contains
from .conditionset import ConditionSet
from .ordinals import Ordinal, OmegaPower, ord0
from .powerset import PowerSet
from ..core.singleton import S
from .handlers.comparison import _eval_is_eq # noqa:F401
Complexes = S.Complexes
EmptySet = S.EmptySet
Integers = S.Integers
Naturals = S.Naturals
Naturals0 = S.Naturals0
Rationals = S.Rationals
Reals = S.Reals
UniversalSet = S.UniversalSet
__all__ = [
'Set', 'Interval', 'Union', 'EmptySet', 'FiniteSet', 'ProductSet',
'Intersection', 'imageset', 'Complement', 'SymmetricDifference', 'DisjointUnion',
'ImageSet', 'Range', 'ComplexRegion', 'Reals',
'Contains',
'ConditionSet',
'Ordinal', 'OmegaPower', 'ord0',
'PowerSet',
'Reals', 'Naturals', 'Naturals0', 'UniversalSet', 'Integers', 'Rationals',
]

View File

@ -0,0 +1,246 @@
from sympy.core.singleton import S
from sympy.core.basic import Basic
from sympy.core.containers import Tuple
from sympy.core.function import Lambda, BadSignatureError
from sympy.core.logic import fuzzy_bool
from sympy.core.relational import Eq
from sympy.core.symbol import Dummy
from sympy.core.sympify import _sympify
from sympy.logic.boolalg import And, as_Boolean
from sympy.utilities.iterables import sift, flatten, has_dups
from sympy.utilities.exceptions import sympy_deprecation_warning
from .contains import Contains
from .sets import Set, Union, FiniteSet, SetKind
adummy = Dummy('conditionset')
class ConditionSet(Set):
r"""
Set of elements which satisfies a given condition.
.. math:: \{x \mid \textrm{condition}(x) = \texttt{True}, x \in S\}
Examples
========
>>> from sympy import Symbol, S, ConditionSet, pi, Eq, sin, Interval
>>> from sympy.abc import x, y, z
>>> sin_sols = ConditionSet(x, Eq(sin(x), 0), Interval(0, 2*pi))
>>> 2*pi in sin_sols
True
>>> pi/2 in sin_sols
False
>>> 3*pi in sin_sols
False
>>> 5 in ConditionSet(x, x**2 > 4, S.Reals)
True
If the value is not in the base set, the result is false:
>>> 5 in ConditionSet(x, x**2 > 4, Interval(2, 4))
False
Notes
=====
Symbols with assumptions should be avoided or else the
condition may evaluate without consideration of the set:
>>> n = Symbol('n', negative=True)
>>> cond = (n > 0); cond
False
>>> ConditionSet(n, cond, S.Integers)
EmptySet
Only free symbols can be changed by using `subs`:
>>> c = ConditionSet(x, x < 1, {x, z})
>>> c.subs(x, y)
ConditionSet(x, x < 1, {y, z})
To check if ``pi`` is in ``c`` use:
>>> pi in c
False
If no base set is specified, the universal set is implied:
>>> ConditionSet(x, x < 1).base_set
UniversalSet
Only symbols or symbol-like expressions can be used:
>>> ConditionSet(x + 1, x + 1 < 1, S.Integers)
Traceback (most recent call last):
...
ValueError: non-symbol dummy not recognized in condition
When the base set is a ConditionSet, the symbols will be
unified if possible with preference for the outermost symbols:
>>> ConditionSet(x, x < y, ConditionSet(z, z + y < 2, S.Integers))
ConditionSet(x, (x < y) & (x + y < 2), Integers)
"""
def __new__(cls, sym, condition, base_set=S.UniversalSet):
sym = _sympify(sym)
flat = flatten([sym])
if has_dups(flat):
raise BadSignatureError("Duplicate symbols detected")
base_set = _sympify(base_set)
if not isinstance(base_set, Set):
raise TypeError(
'base set should be a Set object, not %s' % base_set)
condition = _sympify(condition)
if isinstance(condition, FiniteSet):
condition_orig = condition
temp = (Eq(lhs, 0) for lhs in condition)
condition = And(*temp)
sympy_deprecation_warning(
f"""
Using a set for the condition in ConditionSet is deprecated. Use a boolean
instead.
In this case, replace
{condition_orig}
with
{condition}
""",
deprecated_since_version='1.5',
active_deprecations_target="deprecated-conditionset-set",
)
condition = as_Boolean(condition)
if condition is S.true:
return base_set
if condition is S.false:
return S.EmptySet
if base_set is S.EmptySet:
return S.EmptySet
# no simple answers, so now check syms
for i in flat:
if not getattr(i, '_diff_wrt', False):
raise ValueError('`%s` is not symbol-like' % i)
if base_set.contains(sym) is S.false:
raise TypeError('sym `%s` is not in base_set `%s`' % (sym, base_set))
know = None
if isinstance(base_set, FiniteSet):
sifted = sift(
base_set, lambda _: fuzzy_bool(condition.subs(sym, _)))
if sifted[None]:
know = FiniteSet(*sifted[True])
base_set = FiniteSet(*sifted[None])
else:
return FiniteSet(*sifted[True])
if isinstance(base_set, cls):
s, c, b = base_set.args
def sig(s):
return cls(s, Eq(adummy, 0)).as_dummy().sym
sa, sb = map(sig, (sym, s))
if sa != sb:
raise BadSignatureError('sym does not match sym of base set')
reps = dict(zip(flatten([sym]), flatten([s])))
if s == sym:
condition = And(condition, c)
base_set = b
elif not c.free_symbols & sym.free_symbols:
reps = {v: k for k, v in reps.items()}
condition = And(condition, c.xreplace(reps))
base_set = b
elif not condition.free_symbols & s.free_symbols:
sym = sym.xreplace(reps)
condition = And(condition.xreplace(reps), c)
base_set = b
# flatten ConditionSet(Contains(ConditionSet())) expressions
if isinstance(condition, Contains) and (sym == condition.args[0]):
if isinstance(condition.args[1], Set):
return condition.args[1].intersect(base_set)
rv = Basic.__new__(cls, sym, condition, base_set)
return rv if know is None else Union(know, rv)
sym = property(lambda self: self.args[0])
condition = property(lambda self: self.args[1])
base_set = property(lambda self: self.args[2])
@property
def free_symbols(self):
cond_syms = self.condition.free_symbols - self.sym.free_symbols
return cond_syms | self.base_set.free_symbols
@property
def bound_symbols(self):
return flatten([self.sym])
def _contains(self, other):
def ok_sig(a, b):
tuples = [isinstance(i, Tuple) for i in (a, b)]
c = tuples.count(True)
if c == 1:
return False
if c == 0:
return True
return len(a) == len(b) and all(
ok_sig(i, j) for i, j in zip(a, b))
if not ok_sig(self.sym, other):
return S.false
# try doing base_cond first and return
# False immediately if it is False
base_cond = Contains(other, self.base_set)
if base_cond is S.false:
return S.false
# Substitute other into condition. This could raise e.g. for
# ConditionSet(x, 1/x >= 0, Reals).contains(0)
lamda = Lambda((self.sym,), self.condition)
try:
lambda_cond = lamda(other)
except TypeError:
return None
else:
return And(base_cond, lambda_cond)
def as_relational(self, other):
f = Lambda(self.sym, self.condition)
if isinstance(self.sym, Tuple):
f = f(*other)
else:
f = f(other)
return And(f, self.base_set.contains(other))
def _eval_subs(self, old, new):
sym, cond, base = self.args
dsym = sym.subs(old, adummy)
insym = dsym.has(adummy)
# prioritize changing a symbol in the base
newbase = base.subs(old, new)
if newbase != base:
if not insym:
cond = cond.subs(old, new)
return self.func(sym, cond, newbase)
if insym:
pass # no change of bound symbols via subs
elif getattr(new, '_diff_wrt', False):
cond = cond.subs(old, new)
else:
pass # let error about the symbol raise from __new__
return self.func(sym, cond, base)
def _kind(self):
return SetKind(self.sym.kind)

View File

@ -0,0 +1,63 @@
from sympy.core import S
from sympy.core.sympify import sympify
from sympy.core.relational import Eq, Ne
from sympy.core.parameters import global_parameters
from sympy.logic.boolalg import Boolean
from sympy.utilities.misc import func_name
from .sets import Set
class Contains(Boolean):
"""
Asserts that x is an element of the set S.
Examples
========
>>> from sympy import Symbol, Integer, S, Contains
>>> Contains(Integer(2), S.Integers)
True
>>> Contains(Integer(-2), S.Naturals)
False
>>> i = Symbol('i', integer=True)
>>> Contains(i, S.Naturals)
Contains(i, Naturals)
References
==========
.. [1] https://en.wikipedia.org/wiki/Element_%28mathematics%29
"""
def __new__(cls, x, s, evaluate=None):
x = sympify(x)
s = sympify(s)
if evaluate is None:
evaluate = global_parameters.evaluate
if not isinstance(s, Set):
raise TypeError('expecting Set, not %s' % func_name(s))
if evaluate:
# _contains can return symbolic booleans that would be returned by
# s.contains(x) but here for Contains(x, s) we only evaluate to
# true, false or return the unevaluated Contains.
result = s._contains(x)
if isinstance(result, Boolean):
if result in (S.true, S.false):
return result
elif result is not None:
raise TypeError("_contains() should return Boolean or None")
return super().__new__(cls, x, s)
@property
def binary_symbols(self):
return set().union(*[i.binary_symbols
for i in self.args[1].args
if i.is_Boolean or i.is_Symbol or
isinstance(i, (Eq, Ne))])
def as_set(self):
return self.args[1]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,79 @@
from sympy.core.numbers import oo, Infinity, NegativeInfinity
from sympy.core.singleton import S
from sympy.core import Basic, Expr
from sympy.multipledispatch import Dispatcher
from sympy.sets import Interval, FiniteSet
# XXX: The functions in this module are clearly not tested and are broken in a
# number of ways.
_set_add = Dispatcher('_set_add')
_set_sub = Dispatcher('_set_sub')
@_set_add.register(Basic, Basic)
def _(x, y):
return None
@_set_add.register(Expr, Expr)
def _(x, y):
return x+y
@_set_add.register(Interval, Interval)
def _(x, y):
"""
Additions in interval arithmetic
https://en.wikipedia.org/wiki/Interval_arithmetic
"""
return Interval(x.start + y.start, x.end + y.end,
x.left_open or y.left_open, x.right_open or y.right_open)
@_set_add.register(Interval, Infinity)
def _(x, y):
if x.start is S.NegativeInfinity:
return Interval(-oo, oo)
return FiniteSet({S.Infinity})
@_set_add.register(Interval, NegativeInfinity)
def _(x, y):
if x.end is S.Infinity:
return Interval(-oo, oo)
return FiniteSet({S.NegativeInfinity})
@_set_sub.register(Basic, Basic)
def _(x, y):
return None
@_set_sub.register(Expr, Expr)
def _(x, y):
return x-y
@_set_sub.register(Interval, Interval)
def _(x, y):
"""
Subtractions in interval arithmetic
https://en.wikipedia.org/wiki/Interval_arithmetic
"""
return Interval(x.start - y.end, x.end - y.start,
x.left_open or y.right_open, x.right_open or y.left_open)
@_set_sub.register(Interval, Infinity)
def _(x, y):
if x.start is S.NegativeInfinity:
return Interval(-oo, oo)
return FiniteSet(-oo)
@_set_sub.register(Interval, NegativeInfinity)
def _(x, y):
if x.start is S.NegativeInfinity:
return Interval(-oo, oo)
return FiniteSet(-oo)

View File

@ -0,0 +1,53 @@
from sympy.core.relational import Eq, is_eq
from sympy.core.basic import Basic
from sympy.core.logic import fuzzy_and, fuzzy_bool
from sympy.logic.boolalg import And
from sympy.multipledispatch import dispatch
from sympy.sets.sets import tfn, ProductSet, Interval, FiniteSet, Set
@dispatch(Interval, FiniteSet) # type:ignore
def _eval_is_eq(lhs, rhs): # noqa: F811
return False
@dispatch(FiniteSet, Interval) # type:ignore
def _eval_is_eq(lhs, rhs): # noqa: F811
return False
@dispatch(Interval, Interval) # type:ignore
def _eval_is_eq(lhs, rhs): # noqa: F811
return And(Eq(lhs.left, rhs.left),
Eq(lhs.right, rhs.right),
lhs.left_open == rhs.left_open,
lhs.right_open == rhs.right_open)
@dispatch(FiniteSet, FiniteSet) # type:ignore
def _eval_is_eq(lhs, rhs): # noqa: F811
def all_in_both():
s_set = set(lhs.args)
o_set = set(rhs.args)
yield fuzzy_and(lhs._contains(e) for e in o_set - s_set)
yield fuzzy_and(rhs._contains(e) for e in s_set - o_set)
return tfn[fuzzy_and(all_in_both())]
@dispatch(ProductSet, ProductSet) # type:ignore
def _eval_is_eq(lhs, rhs): # noqa: F811
if len(lhs.sets) != len(rhs.sets):
return False
eqs = (is_eq(x, y) for x, y in zip(lhs.sets, rhs.sets))
return tfn[fuzzy_and(map(fuzzy_bool, eqs))]
@dispatch(Set, Basic) # type:ignore
def _eval_is_eq(lhs, rhs): # noqa: F811
return False
@dispatch(Set, Set) # type:ignore
def _eval_is_eq(lhs, rhs): # noqa: F811
return tfn[fuzzy_and(a.is_subset(b) for a, b in [(lhs, rhs), (rhs, lhs)])]

View File

@ -0,0 +1,262 @@
from sympy.core.singleton import S
from sympy.sets.sets import Set
from sympy.calculus.singularities import singularities
from sympy.core import Expr, Add
from sympy.core.function import Lambda, FunctionClass, diff, expand_mul
from sympy.core.numbers import Float, oo
from sympy.core.symbol import Dummy, symbols, Wild
from sympy.functions.elementary.exponential import exp, log
from sympy.functions.elementary.miscellaneous import Min, Max
from sympy.logic.boolalg import true
from sympy.multipledispatch import Dispatcher
from sympy.sets import (imageset, Interval, FiniteSet, Union, ImageSet,
Intersection, Range, Complement)
from sympy.sets.sets import EmptySet, is_function_invertible_in_set
from sympy.sets.fancysets import Integers, Naturals, Reals
from sympy.functions.elementary.exponential import match_real_imag
_x, _y = symbols("x y")
FunctionUnion = (FunctionClass, Lambda)
_set_function = Dispatcher('_set_function')
@_set_function.register(FunctionClass, Set)
def _(f, x):
return None
@_set_function.register(FunctionUnion, FiniteSet)
def _(f, x):
return FiniteSet(*map(f, x))
@_set_function.register(Lambda, Interval)
def _(f, x):
from sympy.solvers.solveset import solveset
from sympy.series import limit
# TODO: handle functions with infinitely many solutions (eg, sin, tan)
# TODO: handle multivariate functions
expr = f.expr
if len(expr.free_symbols) > 1 or len(f.variables) != 1:
return
var = f.variables[0]
if not var.is_real:
if expr.subs(var, Dummy(real=True)).is_real is False:
return
if expr.is_Piecewise:
result = S.EmptySet
domain_set = x
for (p_expr, p_cond) in expr.args:
if p_cond is true:
intrvl = domain_set
else:
intrvl = p_cond.as_set()
intrvl = Intersection(domain_set, intrvl)
if p_expr.is_Number:
image = FiniteSet(p_expr)
else:
image = imageset(Lambda(var, p_expr), intrvl)
result = Union(result, image)
# remove the part which has been `imaged`
domain_set = Complement(domain_set, intrvl)
if domain_set is S.EmptySet:
break
return result
if not x.start.is_comparable or not x.end.is_comparable:
return
try:
from sympy.polys.polyutils import _nsort
sing = list(singularities(expr, var, x))
if len(sing) > 1:
sing = _nsort(sing)
except NotImplementedError:
return
if x.left_open:
_start = limit(expr, var, x.start, dir="+")
elif x.start not in sing:
_start = f(x.start)
if x.right_open:
_end = limit(expr, var, x.end, dir="-")
elif x.end not in sing:
_end = f(x.end)
if len(sing) == 0:
soln_expr = solveset(diff(expr, var), var)
if not (isinstance(soln_expr, FiniteSet)
or soln_expr is S.EmptySet):
return
solns = list(soln_expr)
extr = [_start, _end] + [f(i) for i in solns
if i.is_real and i in x]
start, end = Min(*extr), Max(*extr)
left_open, right_open = False, False
if _start <= _end:
# the minimum or maximum value can occur simultaneously
# on both the edge of the interval and in some interior
# point
if start == _start and start not in solns:
left_open = x.left_open
if end == _end and end not in solns:
right_open = x.right_open
else:
if start == _end and start not in solns:
left_open = x.right_open
if end == _start and end not in solns:
right_open = x.left_open
return Interval(start, end, left_open, right_open)
else:
return imageset(f, Interval(x.start, sing[0],
x.left_open, True)) + \
Union(*[imageset(f, Interval(sing[i], sing[i + 1], True, True))
for i in range(0, len(sing) - 1)]) + \
imageset(f, Interval(sing[-1], x.end, True, x.right_open))
@_set_function.register(FunctionClass, Interval)
def _(f, x):
if f == exp:
return Interval(exp(x.start), exp(x.end), x.left_open, x.right_open)
elif f == log:
return Interval(log(x.start), log(x.end), x.left_open, x.right_open)
return ImageSet(Lambda(_x, f(_x)), x)
@_set_function.register(FunctionUnion, Union)
def _(f, x):
return Union(*(imageset(f, arg) for arg in x.args))
@_set_function.register(FunctionUnion, Intersection)
def _(f, x):
# If the function is invertible, intersect the maps of the sets.
if is_function_invertible_in_set(f, x):
return Intersection(*(imageset(f, arg) for arg in x.args))
else:
return ImageSet(Lambda(_x, f(_x)), x)
@_set_function.register(FunctionUnion, EmptySet)
def _(f, x):
return x
@_set_function.register(FunctionUnion, Set)
def _(f, x):
return ImageSet(Lambda(_x, f(_x)), x)
@_set_function.register(FunctionUnion, Range)
def _(f, self):
if not self:
return S.EmptySet
if not isinstance(f.expr, Expr):
return
if self.size == 1:
return FiniteSet(f(self[0]))
if f is S.IdentityFunction:
return self
x = f.variables[0]
expr = f.expr
# handle f that is linear in f's variable
if x not in expr.free_symbols or x in expr.diff(x).free_symbols:
return
if self.start.is_finite:
F = f(self.step*x + self.start) # for i in range(len(self))
else:
F = f(-self.step*x + self[-1])
F = expand_mul(F)
if F != expr:
return imageset(x, F, Range(self.size))
@_set_function.register(FunctionUnion, Integers)
def _(f, self):
expr = f.expr
if not isinstance(expr, Expr):
return
n = f.variables[0]
if expr == abs(n):
return S.Naturals0
# f(x) + c and f(-x) + c cover the same integers
# so choose the form that has the fewest negatives
c = f(0)
fx = f(n) - c
f_x = f(-n) - c
neg_count = lambda e: sum(_.could_extract_minus_sign()
for _ in Add.make_args(e))
if neg_count(f_x) < neg_count(fx):
expr = f_x + c
a = Wild('a', exclude=[n])
b = Wild('b', exclude=[n])
match = expr.match(a*n + b)
if match and match[a] and (
not match[a].atoms(Float) and
not match[b].atoms(Float)):
# canonical shift
a, b = match[a], match[b]
if a in [1, -1]:
# drop integer addends in b
nonint = []
for bi in Add.make_args(b):
if not bi.is_integer:
nonint.append(bi)
b = Add(*nonint)
if b.is_number and a.is_real:
# avoid Mod for complex numbers, #11391
br, bi = match_real_imag(b)
if br and br.is_comparable and a.is_comparable:
br %= a
b = br + S.ImaginaryUnit*bi
elif b.is_number and a.is_imaginary:
br, bi = match_real_imag(b)
ai = a/S.ImaginaryUnit
if bi and bi.is_comparable and ai.is_comparable:
bi %= ai
b = br + S.ImaginaryUnit*bi
expr = a*n + b
if expr != f.expr:
return ImageSet(Lambda(n, expr), S.Integers)
@_set_function.register(FunctionUnion, Naturals)
def _(f, self):
expr = f.expr
if not isinstance(expr, Expr):
return
x = f.variables[0]
if not expr.free_symbols - {x}:
if expr == abs(x):
if self is S.Naturals:
return self
return S.Naturals0
step = expr.coeff(x)
c = expr.subs(x, 0)
if c.is_Integer and step.is_Integer and expr == step*x + c:
if self is S.Naturals:
c += step
if step > 0:
if step == 1:
if c == 0:
return S.Naturals0
elif c == 1:
return S.Naturals
return Range(c, oo, step)
return Range(c, -oo, step)
@_set_function.register(FunctionUnion, Reals)
def _(f, self):
expr = f.expr
if not isinstance(expr, Expr):
return
return _set_function(f, Interval(-oo, oo))

View File

@ -0,0 +1,533 @@
from sympy.core.basic import _aresame
from sympy.core.function import Lambda, expand_complex
from sympy.core.mul import Mul
from sympy.core.numbers import ilcm, Float
from sympy.core.relational import Eq
from sympy.core.singleton import S
from sympy.core.symbol import (Dummy, symbols)
from sympy.core.sorting import ordered
from sympy.functions.elementary.complexes import sign
from sympy.functions.elementary.integers import floor, ceiling
from sympy.sets.fancysets import ComplexRegion
from sympy.sets.sets import (FiniteSet, Intersection, Interval, Set, Union)
from sympy.multipledispatch import Dispatcher
from sympy.sets.conditionset import ConditionSet
from sympy.sets.fancysets import (Integers, Naturals, Reals, Range,
ImageSet, Rationals)
from sympy.sets.sets import EmptySet, UniversalSet, imageset, ProductSet
from sympy.simplify.radsimp import numer
intersection_sets = Dispatcher('intersection_sets')
@intersection_sets.register(ConditionSet, ConditionSet)
def _(a, b):
return None
@intersection_sets.register(ConditionSet, Set)
def _(a, b):
return ConditionSet(a.sym, a.condition, Intersection(a.base_set, b))
@intersection_sets.register(Naturals, Integers)
def _(a, b):
return a
@intersection_sets.register(Naturals, Naturals)
def _(a, b):
return a if a is S.Naturals else b
@intersection_sets.register(Interval, Naturals)
def _(a, b):
return intersection_sets(b, a)
@intersection_sets.register(ComplexRegion, Set)
def _(self, other):
if other.is_ComplexRegion:
# self in rectangular form
if (not self.polar) and (not other.polar):
return ComplexRegion(Intersection(self.sets, other.sets))
# self in polar form
elif self.polar and other.polar:
r1, theta1 = self.a_interval, self.b_interval
r2, theta2 = other.a_interval, other.b_interval
new_r_interval = Intersection(r1, r2)
new_theta_interval = Intersection(theta1, theta2)
# 0 and 2*Pi means the same
if ((2*S.Pi in theta1 and S.Zero in theta2) or
(2*S.Pi in theta2 and S.Zero in theta1)):
new_theta_interval = Union(new_theta_interval,
FiniteSet(0))
return ComplexRegion(new_r_interval*new_theta_interval,
polar=True)
if other.is_subset(S.Reals):
new_interval = []
x = symbols("x", cls=Dummy, real=True)
# self in rectangular form
if not self.polar:
for element in self.psets:
if S.Zero in element.args[1]:
new_interval.append(element.args[0])
new_interval = Union(*new_interval)
return Intersection(new_interval, other)
# self in polar form
elif self.polar:
for element in self.psets:
if S.Zero in element.args[1]:
new_interval.append(element.args[0])
if S.Pi in element.args[1]:
new_interval.append(ImageSet(Lambda(x, -x), element.args[0]))
if S.Zero in element.args[0]:
new_interval.append(FiniteSet(0))
new_interval = Union(*new_interval)
return Intersection(new_interval, other)
@intersection_sets.register(Integers, Reals)
def _(a, b):
return a
@intersection_sets.register(Range, Interval)
def _(a, b):
# Check that there are no symbolic arguments
if not all(i.is_number for i in a.args + b.args[:2]):
return
# In case of null Range, return an EmptySet.
if a.size == 0:
return S.EmptySet
# trim down to self's size, and represent
# as a Range with step 1.
start = ceiling(max(b.inf, a.inf))
if start not in b:
start += 1
end = floor(min(b.sup, a.sup))
if end not in b:
end -= 1
return intersection_sets(a, Range(start, end + 1))
@intersection_sets.register(Range, Naturals)
def _(a, b):
return intersection_sets(a, Interval(b.inf, S.Infinity))
@intersection_sets.register(Range, Range)
def _(a, b):
# Check that there are no symbolic range arguments
if not all(all(v.is_number for v in r.args) for r in [a, b]):
return None
# non-overlap quick exits
if not b:
return S.EmptySet
if not a:
return S.EmptySet
if b.sup < a.inf:
return S.EmptySet
if b.inf > a.sup:
return S.EmptySet
# work with finite end at the start
r1 = a
if r1.start.is_infinite:
r1 = r1.reversed
r2 = b
if r2.start.is_infinite:
r2 = r2.reversed
# If both ends are infinite then it means that one Range is just the set
# of all integers (the step must be 1).
if r1.start.is_infinite:
return b
if r2.start.is_infinite:
return a
from sympy.solvers.diophantine.diophantine import diop_linear
# this equation represents the values of the Range;
# it's a linear equation
eq = lambda r, i: r.start + i*r.step
# we want to know when the two equations might
# have integer solutions so we use the diophantine
# solver
va, vb = diop_linear(eq(r1, Dummy('a')) - eq(r2, Dummy('b')))
# check for no solution
no_solution = va is None and vb is None
if no_solution:
return S.EmptySet
# there is a solution
# -------------------
# find the coincident point, c
a0 = va.as_coeff_Add()[0]
c = eq(r1, a0)
# find the first point, if possible, in each range
# since c may not be that point
def _first_finite_point(r1, c):
if c == r1.start:
return c
# st is the signed step we need to take to
# get from c to r1.start
st = sign(r1.start - c)*step
# use Range to calculate the first point:
# we want to get as close as possible to
# r1.start; the Range will not be null since
# it will at least contain c
s1 = Range(c, r1.start + st, st)[-1]
if s1 == r1.start:
pass
else:
# if we didn't hit r1.start then, if the
# sign of st didn't match the sign of r1.step
# we are off by one and s1 is not in r1
if sign(r1.step) != sign(st):
s1 -= st
if s1 not in r1:
return
return s1
# calculate the step size of the new Range
step = abs(ilcm(r1.step, r2.step))
s1 = _first_finite_point(r1, c)
if s1 is None:
return S.EmptySet
s2 = _first_finite_point(r2, c)
if s2 is None:
return S.EmptySet
# replace the corresponding start or stop in
# the original Ranges with these points; the
# result must have at least one point since
# we know that s1 and s2 are in the Ranges
def _updated_range(r, first):
st = sign(r.step)*step
if r.start.is_finite:
rv = Range(first, r.stop, st)
else:
rv = Range(r.start, first + st, st)
return rv
r1 = _updated_range(a, s1)
r2 = _updated_range(b, s2)
# work with them both in the increasing direction
if sign(r1.step) < 0:
r1 = r1.reversed
if sign(r2.step) < 0:
r2 = r2.reversed
# return clipped Range with positive step; it
# can't be empty at this point
start = max(r1.start, r2.start)
stop = min(r1.stop, r2.stop)
return Range(start, stop, step)
@intersection_sets.register(Range, Integers)
def _(a, b):
return a
@intersection_sets.register(Range, Rationals)
def _(a, b):
return a
@intersection_sets.register(ImageSet, Set)
def _(self, other):
from sympy.solvers.diophantine import diophantine
# Only handle the straight-forward univariate case
if (len(self.lamda.variables) > 1
or self.lamda.signature != self.lamda.variables):
return None
base_set = self.base_sets[0]
# Intersection between ImageSets with Integers as base set
# For {f(n) : n in Integers} & {g(m) : m in Integers} we solve the
# diophantine equations f(n)=g(m).
# If the solutions for n are {h(t) : t in Integers} then we return
# {f(h(t)) : t in integers}.
# If the solutions for n are {n_1, n_2, ..., n_k} then we return
# {f(n_i) : 1 <= i <= k}.
if base_set is S.Integers:
gm = None
if isinstance(other, ImageSet) and other.base_sets == (S.Integers,):
gm = other.lamda.expr
var = other.lamda.variables[0]
# Symbol of second ImageSet lambda must be distinct from first
m = Dummy('m')
gm = gm.subs(var, m)
elif other is S.Integers:
m = gm = Dummy('m')
if gm is not None:
fn = self.lamda.expr
n = self.lamda.variables[0]
try:
solns = list(diophantine(fn - gm, syms=(n, m), permute=True))
except (TypeError, NotImplementedError):
# TypeError if equation not polynomial with rational coeff.
# NotImplementedError if correct format but no solver.
return
# 3 cases are possible for solns:
# - empty set,
# - one or more parametric (infinite) solutions,
# - a finite number of (non-parametric) solution couples.
# Among those, there is one type of solution set that is
# not helpful here: multiple parametric solutions.
if len(solns) == 0:
return S.EmptySet
elif any(s.free_symbols for tupl in solns for s in tupl):
if len(solns) == 1:
soln, solm = solns[0]
(t,) = soln.free_symbols
expr = fn.subs(n, soln.subs(t, n)).expand()
return imageset(Lambda(n, expr), S.Integers)
else:
return
else:
return FiniteSet(*(fn.subs(n, s[0]) for s in solns))
if other == S.Reals:
from sympy.solvers.solvers import denoms, solve_linear
def _solution_union(exprs, sym):
# return a union of linear solutions to i in expr;
# if i cannot be solved, use a ConditionSet for solution
sols = []
for i in exprs:
x, xis = solve_linear(i, 0, [sym])
if x == sym:
sols.append(FiniteSet(xis))
else:
sols.append(ConditionSet(sym, Eq(i, 0)))
return Union(*sols)
f = self.lamda.expr
n = self.lamda.variables[0]
n_ = Dummy(n.name, real=True)
f_ = f.subs(n, n_)
re, im = f_.as_real_imag()
im = expand_complex(im)
re = re.subs(n_, n)
im = im.subs(n_, n)
ifree = im.free_symbols
lam = Lambda(n, re)
if im.is_zero:
# allow re-evaluation
# of self in this case to make
# the result canonical
pass
elif im.is_zero is False:
return S.EmptySet
elif ifree != {n}:
return None
else:
# univarite imaginary part in same variable;
# use numer instead of as_numer_denom to keep
# this as fast as possible while still handling
# simple cases
base_set &= _solution_union(
Mul.make_args(numer(im)), n)
# exclude values that make denominators 0
base_set -= _solution_union(denoms(f), n)
return imageset(lam, base_set)
elif isinstance(other, Interval):
from sympy.solvers.solveset import (invert_real, invert_complex,
solveset)
f = self.lamda.expr
n = self.lamda.variables[0]
new_inf, new_sup = None, None
new_lopen, new_ropen = other.left_open, other.right_open
if f.is_real:
inverter = invert_real
else:
inverter = invert_complex
g1, h1 = inverter(f, other.inf, n)
g2, h2 = inverter(f, other.sup, n)
if all(isinstance(i, FiniteSet) for i in (h1, h2)):
if g1 == n:
if len(h1) == 1:
new_inf = h1.args[0]
if g2 == n:
if len(h2) == 1:
new_sup = h2.args[0]
# TODO: Design a technique to handle multiple-inverse
# functions
# Any of the new boundary values cannot be determined
if any(i is None for i in (new_sup, new_inf)):
return
range_set = S.EmptySet
if all(i.is_real for i in (new_sup, new_inf)):
# this assumes continuity of underlying function
# however fixes the case when it is decreasing
if new_inf > new_sup:
new_inf, new_sup = new_sup, new_inf
new_interval = Interval(new_inf, new_sup, new_lopen, new_ropen)
range_set = base_set.intersect(new_interval)
else:
if other.is_subset(S.Reals):
solutions = solveset(f, n, S.Reals)
if not isinstance(range_set, (ImageSet, ConditionSet)):
range_set = solutions.intersect(other)
else:
return
if range_set is S.EmptySet:
return S.EmptySet
elif isinstance(range_set, Range) and range_set.size is not S.Infinity:
range_set = FiniteSet(*list(range_set))
if range_set is not None:
return imageset(Lambda(n, f), range_set)
return
else:
return
@intersection_sets.register(ProductSet, ProductSet)
def _(a, b):
if len(b.args) != len(a.args):
return S.EmptySet
return ProductSet(*(i.intersect(j) for i, j in zip(a.sets, b.sets)))
@intersection_sets.register(Interval, Interval)
def _(a, b):
# handle (-oo, oo)
infty = S.NegativeInfinity, S.Infinity
if a == Interval(*infty):
l, r = a.left, a.right
if l.is_real or l in infty or r.is_real or r in infty:
return b
# We can't intersect [0,3] with [x,6] -- we don't know if x>0 or x<0
if not a._is_comparable(b):
return None
empty = False
if a.start <= b.end and b.start <= a.end:
# Get topology right.
if a.start < b.start:
start = b.start
left_open = b.left_open
elif a.start > b.start:
start = a.start
left_open = a.left_open
else:
start = a.start
if not _aresame(a.start, b.start):
# For example Integer(2) != Float(2)
# Prefer the Float boundary because Floats should be
# contagious in calculations.
if b.start.has(Float) and not a.start.has(Float):
start = b.start
elif a.start.has(Float) and not b.start.has(Float):
start = a.start
else:
#this is to ensure that if Eq(a.start, b.start) but
#type(a.start) != type(b.start) the order of a and b
#does not matter for the result
start = list(ordered([a,b]))[0].start
left_open = a.left_open or b.left_open
if a.end < b.end:
end = a.end
right_open = a.right_open
elif a.end > b.end:
end = b.end
right_open = b.right_open
else:
# see above for logic with start
end = a.end
if not _aresame(a.end, b.end):
if b.end.has(Float) and not a.end.has(Float):
end = b.end
elif a.end.has(Float) and not b.end.has(Float):
end = a.end
else:
end = list(ordered([a,b]))[0].end
right_open = a.right_open or b.right_open
if end - start == 0 and (left_open or right_open):
empty = True
else:
empty = True
if empty:
return S.EmptySet
return Interval(start, end, left_open, right_open)
@intersection_sets.register(EmptySet, Set)
def _(a, b):
return S.EmptySet
@intersection_sets.register(UniversalSet, Set)
def _(a, b):
return b
@intersection_sets.register(FiniteSet, FiniteSet)
def _(a, b):
return FiniteSet(*(a._elements & b._elements))
@intersection_sets.register(FiniteSet, Set)
def _(a, b):
try:
return FiniteSet(*[el for el in a if el in b])
except TypeError:
return None # could not evaluate `el in b` due to symbolic ranges.
@intersection_sets.register(Set, Set)
def _(a, b):
return None
@intersection_sets.register(Integers, Rationals)
def _(a, b):
return a
@intersection_sets.register(Naturals, Rationals)
def _(a, b):
return a
@intersection_sets.register(Rationals, Reals)
def _(a, b):
return a
def _intlike_interval(a, b):
try:
if b._inf is S.NegativeInfinity and b._sup is S.Infinity:
return a
s = Range(max(a.inf, ceiling(b.left)), floor(b.right) + 1)
return intersection_sets(s, b) # take out endpoints if open interval
except ValueError:
return None
@intersection_sets.register(Integers, Interval)
def _(a, b):
return _intlike_interval(a, b)
@intersection_sets.register(Naturals, Interval)
def _(a, b):
return _intlike_interval(a, b)

View File

@ -0,0 +1,144 @@
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)

View File

@ -0,0 +1,79 @@
from sympy.core import Basic, Expr
from sympy.core.numbers import oo
from sympy.core.symbol import symbols
from sympy.multipledispatch import Dispatcher
from sympy.sets.setexpr import set_mul
from sympy.sets.sets import Interval, Set
_x, _y = symbols("x y")
_set_mul = Dispatcher('_set_mul')
_set_div = Dispatcher('_set_div')
@_set_mul.register(Basic, Basic)
def _(x, y):
return None
@_set_mul.register(Set, Set)
def _(x, y):
return None
@_set_mul.register(Expr, Expr)
def _(x, y):
return x*y
@_set_mul.register(Interval, Interval)
def _(x, y):
"""
Multiplications in interval arithmetic
https://en.wikipedia.org/wiki/Interval_arithmetic
"""
# TODO: some intervals containing 0 and oo will fail as 0*oo returns nan.
comvals = (
(x.start * y.start, bool(x.left_open or y.left_open)),
(x.start * y.end, bool(x.left_open or y.right_open)),
(x.end * y.start, bool(x.right_open or y.left_open)),
(x.end * y.end, bool(x.right_open or y.right_open)),
)
# TODO: handle symbolic intervals
minval, minopen = min(comvals)
maxval, maxopen = max(comvals)
return Interval(
minval,
maxval,
minopen,
maxopen
)
@_set_div.register(Basic, Basic)
def _(x, y):
return None
@_set_div.register(Expr, Expr)
def _(x, y):
return x/y
@_set_div.register(Set, Set)
def _(x, y):
return None
@_set_div.register(Interval, Interval)
def _(x, y):
"""
Divisions in interval arithmetic
https://en.wikipedia.org/wiki/Interval_arithmetic
"""
if (y.start*y.end).is_negative:
return Interval(-oo, oo)
if y.start == 0:
s2 = oo
else:
s2 = 1/y.start
if y.end == 0:
s1 = -oo
else:
s1 = 1/y.end
return set_mul(x, Interval(s1, s2, y.right_open, y.left_open))

View File

@ -0,0 +1,107 @@
from sympy.core import Basic, Expr
from sympy.core.function import Lambda
from sympy.core.numbers import oo, Infinity, NegativeInfinity, Zero, Integer
from sympy.core.singleton import S
from sympy.core.symbol import symbols
from sympy.functions.elementary.miscellaneous import (Max, Min)
from sympy.sets.fancysets import ImageSet
from sympy.sets.setexpr import set_div
from sympy.sets.sets import Set, Interval, FiniteSet, Union
from sympy.multipledispatch import Dispatcher
_x, _y = symbols("x y")
_set_pow = Dispatcher('_set_pow')
@_set_pow.register(Basic, Basic)
def _(x, y):
return None
@_set_pow.register(Set, Set)
def _(x, y):
return ImageSet(Lambda((_x, _y), (_x ** _y)), x, y)
@_set_pow.register(Expr, Expr)
def _(x, y):
return x**y
@_set_pow.register(Interval, Zero)
def _(x, z):
return FiniteSet(S.One)
@_set_pow.register(Interval, Integer)
def _(x, exponent):
"""
Powers in interval arithmetic
https://en.wikipedia.org/wiki/Interval_arithmetic
"""
s1 = x.start**exponent
s2 = x.end**exponent
if ((s2 > s1) if exponent > 0 else (x.end > -x.start)) == True:
left_open = x.left_open
right_open = x.right_open
# TODO: handle unevaluated condition.
sleft = s2
else:
# TODO: `s2 > s1` could be unevaluated.
left_open = x.right_open
right_open = x.left_open
sleft = s1
if x.start.is_positive:
return Interval(
Min(s1, s2),
Max(s1, s2), left_open, right_open)
elif x.end.is_negative:
return Interval(
Min(s1, s2),
Max(s1, s2), left_open, right_open)
# Case where x.start < 0 and x.end > 0:
if exponent.is_odd:
if exponent.is_negative:
if x.start.is_zero:
return Interval(s2, oo, x.right_open)
if x.end.is_zero:
return Interval(-oo, s1, True, x.left_open)
return Union(Interval(-oo, s1, True, x.left_open), Interval(s2, oo, x.right_open))
else:
return Interval(s1, s2, x.left_open, x.right_open)
elif exponent.is_even:
if exponent.is_negative:
if x.start.is_zero:
return Interval(s2, oo, x.right_open)
if x.end.is_zero:
return Interval(s1, oo, x.left_open)
return Interval(0, oo)
else:
return Interval(S.Zero, sleft, S.Zero not in x, left_open)
@_set_pow.register(Interval, Infinity)
def _(b, e):
# TODO: add logic for open intervals?
if b.start.is_nonnegative:
if b.end < 1:
return FiniteSet(S.Zero)
if b.start > 1:
return FiniteSet(S.Infinity)
return Interval(0, oo)
elif b.end.is_negative:
if b.start > -1:
return FiniteSet(S.Zero)
if b.end < -1:
return FiniteSet(-oo, oo)
return Interval(-oo, oo)
else:
if b.start > -1:
if b.end < 1:
return FiniteSet(S.Zero)
return Interval(0, oo)
return Interval(-oo, oo)
@_set_pow.register(Interval, NegativeInfinity)
def _(b, e):
return _set_pow(set_div(S.One, b), oo)

View File

@ -0,0 +1,147 @@
from sympy.core.singleton import S
from sympy.core.sympify import sympify
from sympy.functions.elementary.miscellaneous import Min, Max
from sympy.sets.sets import (EmptySet, FiniteSet, Intersection,
Interval, ProductSet, Set, Union, UniversalSet)
from sympy.sets.fancysets import (ComplexRegion, Naturals, Naturals0,
Integers, Rationals, Reals)
from sympy.multipledispatch import Dispatcher
union_sets = Dispatcher('union_sets')
@union_sets.register(Naturals0, Naturals)
def _(a, b):
return a
@union_sets.register(Rationals, Naturals)
def _(a, b):
return a
@union_sets.register(Rationals, Naturals0)
def _(a, b):
return a
@union_sets.register(Reals, Naturals)
def _(a, b):
return a
@union_sets.register(Reals, Naturals0)
def _(a, b):
return a
@union_sets.register(Reals, Rationals)
def _(a, b):
return a
@union_sets.register(Integers, Set)
def _(a, b):
intersect = Intersection(a, b)
if intersect == a:
return b
elif intersect == b:
return a
@union_sets.register(ComplexRegion, Set)
def _(a, b):
if b.is_subset(S.Reals):
# treat a subset of reals as a complex region
b = ComplexRegion.from_real(b)
if b.is_ComplexRegion:
# a in rectangular form
if (not a.polar) and (not b.polar):
return ComplexRegion(Union(a.sets, b.sets))
# a in polar form
elif a.polar and b.polar:
return ComplexRegion(Union(a.sets, b.sets), polar=True)
return None
@union_sets.register(EmptySet, Set)
def _(a, b):
return b
@union_sets.register(UniversalSet, Set)
def _(a, b):
return a
@union_sets.register(ProductSet, ProductSet)
def _(a, b):
if b.is_subset(a):
return a
if len(b.sets) != len(a.sets):
return None
if len(a.sets) == 2:
a1, a2 = a.sets
b1, b2 = b.sets
if a1 == b1:
return a1 * Union(a2, b2)
if a2 == b2:
return Union(a1, b1) * a2
return None
@union_sets.register(ProductSet, Set)
def _(a, b):
if b.is_subset(a):
return a
return None
@union_sets.register(Interval, Interval)
def _(a, b):
if a._is_comparable(b):
# Non-overlapping intervals
end = Min(a.end, b.end)
start = Max(a.start, b.start)
if (end < start or
(end == start and (end not in a and end not in b))):
return None
else:
start = Min(a.start, b.start)
end = Max(a.end, b.end)
left_open = ((a.start != start or a.left_open) and
(b.start != start or b.left_open))
right_open = ((a.end != end or a.right_open) and
(b.end != end or b.right_open))
return Interval(start, end, left_open, right_open)
@union_sets.register(Interval, UniversalSet)
def _(a, b):
return S.UniversalSet
@union_sets.register(Interval, Set)
def _(a, b):
# If I have open end points and these endpoints are contained in b
# But only in case, when endpoints are finite. Because
# interval does not contain oo or -oo.
open_left_in_b_and_finite = (a.left_open and
sympify(b.contains(a.start)) is S.true and
a.start.is_finite)
open_right_in_b_and_finite = (a.right_open and
sympify(b.contains(a.end)) is S.true and
a.end.is_finite)
if open_left_in_b_and_finite or open_right_in_b_and_finite:
# Fill in my end points and return
open_left = a.left_open and a.start not in b
open_right = a.right_open and a.end not in b
new_a = Interval(a.start, a.end, open_left, open_right)
return {new_a, b}
return None
@union_sets.register(FiniteSet, FiniteSet)
def _(a, b):
return FiniteSet(*(a._elements | b._elements))
@union_sets.register(FiniteSet, Set)
def _(a, b):
# If `b` set contains one of my elements, remove it from `a`
if any(b.contains(x) == True for x in a):
return {
FiniteSet(*[x for x in a if b.contains(x) != True]), b}
return None
@union_sets.register(Set, Set)
def _(a, b):
return None

View File

@ -0,0 +1,282 @@
from sympy.core import Basic, Integer
import operator
class OmegaPower(Basic):
"""
Represents ordinal exponential and multiplication terms one of the
building blocks of the :class:`Ordinal` class.
In ``OmegaPower(a, b)``, ``a`` represents exponent and ``b`` represents multiplicity.
"""
def __new__(cls, a, b):
if isinstance(b, int):
b = Integer(b)
if not isinstance(b, Integer) or b <= 0:
raise TypeError("multiplicity must be a positive integer")
if not isinstance(a, Ordinal):
a = Ordinal.convert(a)
return Basic.__new__(cls, a, b)
@property
def exp(self):
return self.args[0]
@property
def mult(self):
return self.args[1]
def _compare_term(self, other, op):
if self.exp == other.exp:
return op(self.mult, other.mult)
else:
return op(self.exp, other.exp)
def __eq__(self, other):
if not isinstance(other, OmegaPower):
try:
other = OmegaPower(0, other)
except TypeError:
return NotImplemented
return self.args == other.args
def __hash__(self):
return Basic.__hash__(self)
def __lt__(self, other):
if not isinstance(other, OmegaPower):
try:
other = OmegaPower(0, other)
except TypeError:
return NotImplemented
return self._compare_term(other, operator.lt)
class Ordinal(Basic):
"""
Represents ordinals in Cantor normal form.
Internally, this class is just a list of instances of OmegaPower.
Examples
========
>>> from sympy import Ordinal, OmegaPower
>>> from sympy.sets.ordinals import omega
>>> w = omega
>>> w.is_limit_ordinal
True
>>> Ordinal(OmegaPower(w + 1, 1), OmegaPower(3, 2))
w**(w + 1) + w**3*2
>>> 3 + w
w
>>> (w + 1) * w
w**2
References
==========
.. [1] https://en.wikipedia.org/wiki/Ordinal_arithmetic
"""
def __new__(cls, *terms):
obj = super().__new__(cls, *terms)
powers = [i.exp for i in obj.args]
if not all(powers[i] >= powers[i+1] for i in range(len(powers) - 1)):
raise ValueError("powers must be in decreasing order")
return obj
@property
def terms(self):
return self.args
@property
def leading_term(self):
if self == ord0:
raise ValueError("ordinal zero has no leading term")
return self.terms[0]
@property
def trailing_term(self):
if self == ord0:
raise ValueError("ordinal zero has no trailing term")
return self.terms[-1]
@property
def is_successor_ordinal(self):
try:
return self.trailing_term.exp == ord0
except ValueError:
return False
@property
def is_limit_ordinal(self):
try:
return not self.trailing_term.exp == ord0
except ValueError:
return False
@property
def degree(self):
return self.leading_term.exp
@classmethod
def convert(cls, integer_value):
if integer_value == 0:
return ord0
return Ordinal(OmegaPower(0, integer_value))
def __eq__(self, other):
if not isinstance(other, Ordinal):
try:
other = Ordinal.convert(other)
except TypeError:
return NotImplemented
return self.terms == other.terms
def __hash__(self):
return hash(self.args)
def __lt__(self, other):
if not isinstance(other, Ordinal):
try:
other = Ordinal.convert(other)
except TypeError:
return NotImplemented
for term_self, term_other in zip(self.terms, other.terms):
if term_self != term_other:
return term_self < term_other
return len(self.terms) < len(other.terms)
def __le__(self, other):
return (self == other or self < other)
def __gt__(self, other):
return not self <= other
def __ge__(self, other):
return not self < other
def __str__(self):
net_str = ""
plus_count = 0
if self == ord0:
return 'ord0'
for i in self.terms:
if plus_count:
net_str += " + "
if i.exp == ord0:
net_str += str(i.mult)
elif i.exp == 1:
net_str += 'w'
elif len(i.exp.terms) > 1 or i.exp.is_limit_ordinal:
net_str += 'w**(%s)'%i.exp
else:
net_str += 'w**%s'%i.exp
if not i.mult == 1 and not i.exp == ord0:
net_str += '*%s'%i.mult
plus_count += 1
return(net_str)
__repr__ = __str__
def __add__(self, other):
if not isinstance(other, Ordinal):
try:
other = Ordinal.convert(other)
except TypeError:
return NotImplemented
if other == ord0:
return self
a_terms = list(self.terms)
b_terms = list(other.terms)
r = len(a_terms) - 1
b_exp = other.degree
while r >= 0 and a_terms[r].exp < b_exp:
r -= 1
if r < 0:
terms = b_terms
elif a_terms[r].exp == b_exp:
sum_term = OmegaPower(b_exp, a_terms[r].mult + other.leading_term.mult)
terms = a_terms[:r] + [sum_term] + b_terms[1:]
else:
terms = a_terms[:r+1] + b_terms
return Ordinal(*terms)
def __radd__(self, other):
if not isinstance(other, Ordinal):
try:
other = Ordinal.convert(other)
except TypeError:
return NotImplemented
return other + self
def __mul__(self, other):
if not isinstance(other, Ordinal):
try:
other = Ordinal.convert(other)
except TypeError:
return NotImplemented
if ord0 in (self, other):
return ord0
a_exp = self.degree
a_mult = self.leading_term.mult
summation = []
if other.is_limit_ordinal:
for arg in other.terms:
summation.append(OmegaPower(a_exp + arg.exp, arg.mult))
else:
for arg in other.terms[:-1]:
summation.append(OmegaPower(a_exp + arg.exp, arg.mult))
b_mult = other.trailing_term.mult
summation.append(OmegaPower(a_exp, a_mult*b_mult))
summation += list(self.terms[1:])
return Ordinal(*summation)
def __rmul__(self, other):
if not isinstance(other, Ordinal):
try:
other = Ordinal.convert(other)
except TypeError:
return NotImplemented
return other * self
def __pow__(self, other):
if not self == omega:
return NotImplemented
return Ordinal(OmegaPower(other, 1))
class OrdinalZero(Ordinal):
"""The ordinal zero.
OrdinalZero can be imported as ``ord0``.
"""
pass
class OrdinalOmega(Ordinal):
"""The ordinal omega which forms the base of all ordinals in cantor normal form.
OrdinalOmega can be imported as ``omega``.
Examples
========
>>> from sympy.sets.ordinals import omega
>>> omega + omega
w*2
"""
def __new__(cls):
return Ordinal.__new__(cls)
@property
def terms(self):
return (OmegaPower(1, 1),)
ord0 = OrdinalZero()
omega = OrdinalOmega()

View File

@ -0,0 +1,119 @@
from sympy.core.decorators import _sympifyit
from sympy.core.parameters import global_parameters
from sympy.core.logic import fuzzy_bool
from sympy.core.singleton import S
from sympy.core.sympify import _sympify
from .sets import Set, FiniteSet, SetKind
class PowerSet(Set):
r"""A symbolic object representing a power set.
Parameters
==========
arg : Set
The set to take power of.
evaluate : bool
The flag to control evaluation.
If the evaluation is disabled for finite sets, it can take
advantage of using subset test as a membership test.
Notes
=====
Power set `\mathcal{P}(S)` is defined as a set containing all the
subsets of `S`.
If the set `S` is a finite set, its power set would have
`2^{\left| S \right|}` elements, where `\left| S \right|` denotes
the cardinality of `S`.
Examples
========
>>> from sympy import PowerSet, S, FiniteSet
A power set of a finite set:
>>> PowerSet(FiniteSet(1, 2, 3))
PowerSet({1, 2, 3})
A power set of an empty set:
>>> PowerSet(S.EmptySet)
PowerSet(EmptySet)
>>> PowerSet(PowerSet(S.EmptySet))
PowerSet(PowerSet(EmptySet))
A power set of an infinite set:
>>> PowerSet(S.Reals)
PowerSet(Reals)
Evaluating the power set of a finite set to its explicit form:
>>> PowerSet(FiniteSet(1, 2, 3)).rewrite(FiniteSet)
FiniteSet(EmptySet, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3})
References
==========
.. [1] https://en.wikipedia.org/wiki/Power_set
.. [2] https://en.wikipedia.org/wiki/Axiom_of_power_set
"""
def __new__(cls, arg, evaluate=None):
if evaluate is None:
evaluate=global_parameters.evaluate
arg = _sympify(arg)
if not isinstance(arg, Set):
raise ValueError('{} must be a set.'.format(arg))
return super().__new__(cls, arg)
@property
def arg(self):
return self.args[0]
def _eval_rewrite_as_FiniteSet(self, *args, **kwargs):
arg = self.arg
if arg.is_FiniteSet:
return arg.powerset()
return None
@_sympifyit('other', NotImplemented)
def _contains(self, other):
if not isinstance(other, Set):
return None
return fuzzy_bool(self.arg.is_superset(other))
def _eval_is_subset(self, other):
if isinstance(other, PowerSet):
return self.arg.is_subset(other.arg)
def __len__(self):
return 2 ** len(self.arg)
def __iter__(self):
found = [S.EmptySet]
yield S.EmptySet
for x in self.arg:
temp = []
x = FiniteSet(x)
for y in found:
new = x + y
yield new
temp.append(new)
found.extend(temp)
@property
def kind(self):
return SetKind(self.arg.kind)

View File

@ -0,0 +1,97 @@
from sympy.core import Expr
from sympy.core.decorators import call_highest_priority, _sympifyit
from .fancysets import ImageSet
from .sets import set_add, set_sub, set_mul, set_div, set_pow, set_function
class SetExpr(Expr):
"""An expression that can take on values of a set.
Examples
========
>>> from sympy import Interval, FiniteSet
>>> from sympy.sets.setexpr import SetExpr
>>> a = SetExpr(Interval(0, 5))
>>> b = SetExpr(FiniteSet(1, 10))
>>> (a + b).set
Union(Interval(1, 6), Interval(10, 15))
>>> (2*a + b).set
Interval(1, 20)
"""
_op_priority = 11.0
def __new__(cls, setarg):
return Expr.__new__(cls, setarg)
set = property(lambda self: self.args[0])
def _latex(self, printer):
return r"SetExpr\left({}\right)".format(printer._print(self.set))
@_sympifyit('other', NotImplemented)
@call_highest_priority('__radd__')
def __add__(self, other):
return _setexpr_apply_operation(set_add, self, other)
@_sympifyit('other', NotImplemented)
@call_highest_priority('__add__')
def __radd__(self, other):
return _setexpr_apply_operation(set_add, other, self)
@_sympifyit('other', NotImplemented)
@call_highest_priority('__rmul__')
def __mul__(self, other):
return _setexpr_apply_operation(set_mul, self, other)
@_sympifyit('other', NotImplemented)
@call_highest_priority('__mul__')
def __rmul__(self, other):
return _setexpr_apply_operation(set_mul, other, self)
@_sympifyit('other', NotImplemented)
@call_highest_priority('__rsub__')
def __sub__(self, other):
return _setexpr_apply_operation(set_sub, self, other)
@_sympifyit('other', NotImplemented)
@call_highest_priority('__sub__')
def __rsub__(self, other):
return _setexpr_apply_operation(set_sub, other, self)
@_sympifyit('other', NotImplemented)
@call_highest_priority('__rpow__')
def __pow__(self, other):
return _setexpr_apply_operation(set_pow, self, other)
@_sympifyit('other', NotImplemented)
@call_highest_priority('__pow__')
def __rpow__(self, other):
return _setexpr_apply_operation(set_pow, other, self)
@_sympifyit('other', NotImplemented)
@call_highest_priority('__rtruediv__')
def __truediv__(self, other):
return _setexpr_apply_operation(set_div, self, other)
@_sympifyit('other', NotImplemented)
@call_highest_priority('__truediv__')
def __rtruediv__(self, other):
return _setexpr_apply_operation(set_div, other, self)
def _eval_func(self, func):
# TODO: this could be implemented straight into `imageset`:
res = set_function(func, self.set)
if res is None:
return SetExpr(ImageSet(func, self.set))
return SetExpr(res)
def _setexpr_apply_operation(op, x, y):
if isinstance(x, SetExpr):
x = x.set
if isinstance(y, SetExpr):
y = y.set
out = op(x, y)
return SetExpr(out)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,294 @@
from sympy.core.expr import unchanged
from sympy.sets import (ConditionSet, Intersection, FiniteSet,
EmptySet, Union, Contains, ImageSet)
from sympy.sets.sets import SetKind
from sympy.core.function import (Function, Lambda)
from sympy.core.mod import Mod
from sympy.core.kind import NumberKind
from sympy.core.numbers import (oo, pi)
from sympy.core.relational import (Eq, Ne)
from sympy.core.singleton import S
from sympy.core.symbol import (Symbol, symbols)
from sympy.functions.elementary.complexes import Abs
from sympy.functions.elementary.trigonometric import (asin, sin)
from sympy.logic.boolalg import And
from sympy.matrices.dense import Matrix
from sympy.matrices.expressions.matexpr import MatrixSymbol
from sympy.sets.sets import Interval
from sympy.testing.pytest import raises, warns_deprecated_sympy
w = Symbol('w')
x = Symbol('x')
y = Symbol('y')
z = Symbol('z')
f = Function('f')
def test_CondSet():
sin_sols_principal = ConditionSet(x, Eq(sin(x), 0),
Interval(0, 2*pi, False, True))
assert pi in sin_sols_principal
assert pi/2 not in sin_sols_principal
assert 3*pi not in sin_sols_principal
assert oo not in sin_sols_principal
assert 5 in ConditionSet(x, x**2 > 4, S.Reals)
assert 1 not in ConditionSet(x, x**2 > 4, S.Reals)
# in this case, 0 is not part of the base set so
# it can't be in any subset selected by the condition
assert 0 not in ConditionSet(x, y > 5, Interval(1, 7))
# since 'in' requires a true/false, the following raises
# an error because the given value provides no information
# for the condition to evaluate (since the condition does
# not depend on the dummy symbol): the result is `y > 5`.
# In this case, ConditionSet is just acting like
# Piecewise((Interval(1, 7), y > 5), (S.EmptySet, True)).
raises(TypeError, lambda: 6 in ConditionSet(x, y > 5,
Interval(1, 7)))
X = MatrixSymbol('X', 2, 2)
matrix_set = ConditionSet(X, Eq(X*Matrix([[1, 1], [1, 1]]), X))
Y = Matrix([[0, 0], [0, 0]])
assert matrix_set.contains(Y).doit() is S.true
Z = Matrix([[1, 2], [3, 4]])
assert matrix_set.contains(Z).doit() is S.false
assert isinstance(ConditionSet(x, x < 1, {x, y}).base_set,
FiniteSet)
raises(TypeError, lambda: ConditionSet(x, x + 1, {x, y}))
raises(TypeError, lambda: ConditionSet(x, x, 1))
I = S.Integers
U = S.UniversalSet
C = ConditionSet
assert C(x, False, I) is S.EmptySet
assert C(x, True, I) is I
assert C(x, x < 1, C(x, x < 2, I)
) == C(x, (x < 1) & (x < 2), I)
assert C(y, y < 1, C(x, y < 2, I)
) == C(x, (x < 1) & (y < 2), I), C(y, y < 1, C(x, y < 2, I))
assert C(y, y < 1, C(x, x < 2, I)
) == C(y, (y < 1) & (y < 2), I)
assert C(y, y < 1, C(x, y < x, I)
) == C(x, (x < 1) & (y < x), I)
assert unchanged(C, y, x < 1, C(x, y < x, I))
assert ConditionSet(x, x < 1).base_set is U
# arg checking is not done at instantiation but this
# will raise an error when containment is tested
assert ConditionSet((x,), x < 1).base_set is U
c = ConditionSet((x, y), x < y, I**2)
assert (1, 2) in c
assert (1, pi) not in c
raises(TypeError, lambda: C(x, x > 1, C((x, y), x > 1, I**2)))
# signature mismatch since only 3 args are accepted
raises(TypeError, lambda: C((x, y), x + y < 2, U, U))
def test_CondSet_intersect():
input_conditionset = ConditionSet(x, x**2 > 4, Interval(1, 4, False,
False))
other_domain = Interval(0, 3, False, False)
output_conditionset = ConditionSet(x, x**2 > 4, Interval(
1, 3, False, False))
assert Intersection(input_conditionset, other_domain
) == output_conditionset
def test_issue_9849():
assert ConditionSet(x, Eq(x, x), S.Naturals
) is S.Naturals
assert ConditionSet(x, Eq(Abs(sin(x)), -1), S.Naturals
) == S.EmptySet
def test_simplified_FiniteSet_in_CondSet():
assert ConditionSet(x, And(x < 1, x > -3), FiniteSet(0, 1, 2)
) == FiniteSet(0)
assert ConditionSet(x, x < 0, FiniteSet(0, 1, 2)) == EmptySet
assert ConditionSet(x, And(x < -3), EmptySet) == EmptySet
y = Symbol('y')
assert (ConditionSet(x, And(x > 0), FiniteSet(-1, 0, 1, y)) ==
Union(FiniteSet(1), ConditionSet(x, And(x > 0), FiniteSet(y))))
assert (ConditionSet(x, Eq(Mod(x, 3), 1), FiniteSet(1, 4, 2, y)) ==
Union(FiniteSet(1, 4), ConditionSet(x, Eq(Mod(x, 3), 1),
FiniteSet(y))))
def test_free_symbols():
assert ConditionSet(x, Eq(y, 0), FiniteSet(z)
).free_symbols == {y, z}
assert ConditionSet(x, Eq(x, 0), FiniteSet(z)
).free_symbols == {z}
assert ConditionSet(x, Eq(x, 0), FiniteSet(x, z)
).free_symbols == {x, z}
assert ConditionSet(x, Eq(x, 0), ImageSet(Lambda(y, y**2),
S.Integers)).free_symbols == set()
def test_bound_symbols():
assert ConditionSet(x, Eq(y, 0), FiniteSet(z)
).bound_symbols == [x]
assert ConditionSet(x, Eq(x, 0), FiniteSet(x, y)
).bound_symbols == [x]
assert ConditionSet(x, x < 10, ImageSet(Lambda(y, y**2), S.Integers)
).bound_symbols == [x]
assert ConditionSet(x, x < 10, ConditionSet(y, y > 1, S.Integers)
).bound_symbols == [x]
def test_as_dummy():
_0, _1 = symbols('_0 _1')
assert ConditionSet(x, x < 1, Interval(y, oo)
).as_dummy() == ConditionSet(_0, _0 < 1, Interval(y, oo))
assert ConditionSet(x, x < 1, Interval(x, oo)
).as_dummy() == ConditionSet(_0, _0 < 1, Interval(x, oo))
assert ConditionSet(x, x < 1, ImageSet(Lambda(y, y**2), S.Integers)
).as_dummy() == ConditionSet(
_0, _0 < 1, ImageSet(Lambda(_0, _0**2), S.Integers))
e = ConditionSet((x, y), x <= y, S.Reals**2)
assert e.bound_symbols == [x, y]
assert e.as_dummy() == ConditionSet((_0, _1), _0 <= _1, S.Reals**2)
assert e.as_dummy() == ConditionSet((y, x), y <= x, S.Reals**2
).as_dummy()
def test_subs_CondSet():
s = FiniteSet(z, y)
c = ConditionSet(x, x < 2, s)
assert c.subs(x, y) == c
assert c.subs(z, y) == ConditionSet(x, x < 2, FiniteSet(y))
assert c.xreplace({x: y}) == ConditionSet(y, y < 2, s)
assert ConditionSet(x, x < y, s
).subs(y, w) == ConditionSet(x, x < w, s.subs(y, w))
# if the user uses assumptions that cause the condition
# to evaluate, that can't be helped from SymPy's end
n = Symbol('n', negative=True)
assert ConditionSet(n, 0 < n, S.Integers) is S.EmptySet
p = Symbol('p', positive=True)
assert ConditionSet(n, n < y, S.Integers
).subs(n, x) == ConditionSet(n, n < y, S.Integers)
raises(ValueError, lambda: ConditionSet(
x + 1, x < 1, S.Integers))
assert ConditionSet(
p, n < x, Interval(-5, 5)).subs(x, p) == Interval(-5, 5), ConditionSet(
p, n < x, Interval(-5, 5)).subs(x, p)
assert ConditionSet(
n, n < x, Interval(-oo, 0)).subs(x, p
) == Interval(-oo, 0)
assert ConditionSet(f(x), f(x) < 1, {w, z}
).subs(f(x), y) == ConditionSet(f(x), f(x) < 1, {w, z})
# issue 17341
k = Symbol('k')
img1 = ImageSet(Lambda(k, 2*k*pi + asin(y)), S.Integers)
img2 = ImageSet(Lambda(k, 2*k*pi + asin(S.One/3)), S.Integers)
assert ConditionSet(x, Contains(
y, Interval(-1,1)), img1).subs(y, S.One/3).dummy_eq(img2)
assert (0, 1) in ConditionSet((x, y), x + y < 3, S.Integers**2)
raises(TypeError, lambda: ConditionSet(n, n < -10, Interval(0, 10)))
def test_subs_CondSet_tebr():
with warns_deprecated_sympy():
assert ConditionSet((x, y), {x + 1, x + y}, S.Reals**2) == \
ConditionSet((x, y), Eq(x + 1, 0) & Eq(x + y, 0), S.Reals**2)
def test_dummy_eq():
C = ConditionSet
I = S.Integers
c = C(x, x < 1, I)
assert c.dummy_eq(C(y, y < 1, I))
assert c.dummy_eq(1) == False
assert c.dummy_eq(C(x, x < 1, S.Reals)) == False
c1 = ConditionSet((x, y), Eq(x + 1, 0) & Eq(x + y, 0), S.Reals**2)
c2 = ConditionSet((x, y), Eq(x + 1, 0) & Eq(x + y, 0), S.Reals**2)
c3 = ConditionSet((x, y), Eq(x + 1, 0) & Eq(x + y, 0), S.Complexes**2)
assert c1.dummy_eq(c2)
assert c1.dummy_eq(c3) is False
assert c.dummy_eq(c1) is False
assert c1.dummy_eq(c) is False
# issue 19496
m = Symbol('m')
n = Symbol('n')
a = Symbol('a')
d1 = ImageSet(Lambda(m, m*pi), S.Integers)
d2 = ImageSet(Lambda(n, n*pi), S.Integers)
c1 = ConditionSet(x, Ne(a, 0), d1)
c2 = ConditionSet(x, Ne(a, 0), d2)
assert c1.dummy_eq(c2)
def test_contains():
assert 6 in ConditionSet(x, x > 5, Interval(1, 7))
assert (8 in ConditionSet(x, y > 5, Interval(1, 7))) is False
# `in` should give True or False; in this case there is not
# enough information for that result
raises(TypeError,
lambda: 6 in ConditionSet(x, y > 5, Interval(1, 7)))
# here, there is enough information but the comparison is
# not defined
raises(TypeError, lambda: 0 in ConditionSet(x, 1/x >= 0, S.Reals))
assert ConditionSet(x, y > 5, Interval(1, 7)
).contains(6) == (y > 5)
assert ConditionSet(x, y > 5, Interval(1, 7)
).contains(8) is S.false
assert ConditionSet(x, y > 5, Interval(1, 7)
).contains(w) == And(Contains(w, Interval(1, 7)), y > 5)
# This returns an unevaluated Contains object
# because 1/0 should not be defined for 1 and 0 in the context of
# reals.
assert ConditionSet(x, 1/x >= 0, S.Reals).contains(0) == \
Contains(0, ConditionSet(x, 1/x >= 0, S.Reals), evaluate=False)
c = ConditionSet((x, y), x + y > 1, S.Integers**2)
assert not c.contains(1)
assert c.contains((2, 1))
assert not c.contains((0, 1))
c = ConditionSet((w, (x, y)), w + x + y > 1, S.Integers*S.Integers**2)
assert not c.contains(1)
assert not c.contains((1, 2))
assert not c.contains(((1, 2), 3))
assert not c.contains(((1, 2), (3, 4)))
assert c.contains((1, (3, 4)))
def test_as_relational():
assert ConditionSet((x, y), x > 1, S.Integers**2).as_relational((x, y)
) == (x > 1) & Contains(x, S.Integers) & Contains(y, S.Integers)
assert ConditionSet(x, x > 1, S.Integers).as_relational(x
) == Contains(x, S.Integers) & (x > 1)
def test_flatten():
"""Tests whether there is basic denesting functionality"""
inner = ConditionSet(x, sin(x) + x > 0)
outer = ConditionSet(x, Contains(x, inner), S.Reals)
assert outer == ConditionSet(x, sin(x) + x > 0, S.Reals)
inner = ConditionSet(y, sin(y) + y > 0)
outer = ConditionSet(x, Contains(y, inner), S.Reals)
assert outer != ConditionSet(x, sin(x) + x > 0, S.Reals)
inner = ConditionSet(x, sin(x) + x > 0).intersect(Interval(-1, 1))
outer = ConditionSet(x, Contains(x, inner), S.Reals)
assert outer == ConditionSet(x, sin(x) + x > 0, Interval(-1, 1))
def test_duplicate():
from sympy.core.function import BadSignatureError
# test coverage for line 95 in conditionset.py, check for duplicates in symbols
dup = symbols('a,a')
raises(BadSignatureError, lambda: ConditionSet(dup, x < 0))
def test_SetKind_ConditionSet():
assert ConditionSet(x, Eq(sin(x), 0), Interval(0, 2*pi)).kind is SetKind(NumberKind)
assert ConditionSet(x, x < 0).kind is SetKind(NumberKind)

View File

@ -0,0 +1,52 @@
from sympy.core.expr import unchanged
from sympy.core.numbers import oo
from sympy.core.relational import Eq
from sympy.core.singleton import S
from sympy.core.symbol import Symbol
from sympy.sets.contains import Contains
from sympy.sets.sets import (FiniteSet, Interval)
from sympy.testing.pytest import raises
def test_contains_basic():
raises(TypeError, lambda: Contains(S.Integers, 1))
assert Contains(2, S.Integers) is S.true
assert Contains(-2, S.Naturals) is S.false
i = Symbol('i', integer=True)
assert Contains(i, S.Naturals) == Contains(i, S.Naturals, evaluate=False)
def test_issue_6194():
x = Symbol('x')
assert unchanged(Contains, x, Interval(0, 1))
assert Interval(0, 1).contains(x) == (S.Zero <= x) & (x <= 1)
assert Contains(x, FiniteSet(0)) != S.false
assert Contains(x, Interval(1, 1)) != S.false
assert Contains(x, S.Integers) != S.false
def test_issue_10326():
assert Contains(oo, Interval(-oo, oo)) == False
assert Contains(-oo, Interval(-oo, oo)) == False
def test_binary_symbols():
x = Symbol('x')
y = Symbol('y')
z = Symbol('z')
assert Contains(x, FiniteSet(y, Eq(z, True))
).binary_symbols == {y, z}
def test_as_set():
x = Symbol('x')
y = Symbol('y')
assert Contains(x, FiniteSet(y)).as_set() == FiniteSet(y)
assert Contains(x, S.Integers).as_set() == S.Integers
assert Contains(x, S.Reals).as_set() == S.Reals
def test_type_error():
# Pass in a parameter not of type "set"
raises(TypeError, lambda: Contains(2, None))

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,67 @@
from sympy.sets.ordinals import Ordinal, OmegaPower, ord0, omega
from sympy.testing.pytest import raises
def test_string_ordinals():
assert str(omega) == 'w'
assert str(Ordinal(OmegaPower(5, 3), OmegaPower(3, 2))) == 'w**5*3 + w**3*2'
assert str(Ordinal(OmegaPower(5, 3), OmegaPower(0, 5))) == 'w**5*3 + 5'
assert str(Ordinal(OmegaPower(1, 3), OmegaPower(0, 5))) == 'w*3 + 5'
assert str(Ordinal(OmegaPower(omega + 1, 1), OmegaPower(3, 2))) == 'w**(w + 1) + w**3*2'
def test_addition_with_integers():
assert 3 + Ordinal(OmegaPower(5, 3)) == Ordinal(OmegaPower(5, 3))
assert Ordinal(OmegaPower(5, 3))+3 == Ordinal(OmegaPower(5, 3), OmegaPower(0, 3))
assert Ordinal(OmegaPower(5, 3), OmegaPower(0, 2))+3 == \
Ordinal(OmegaPower(5, 3), OmegaPower(0, 5))
def test_addition_with_ordinals():
assert Ordinal(OmegaPower(5, 3), OmegaPower(3, 2)) + Ordinal(OmegaPower(3, 3)) == \
Ordinal(OmegaPower(5, 3), OmegaPower(3, 5))
assert Ordinal(OmegaPower(5, 3), OmegaPower(3, 2)) + Ordinal(OmegaPower(4, 2)) == \
Ordinal(OmegaPower(5, 3), OmegaPower(4, 2))
assert Ordinal(OmegaPower(omega, 2), OmegaPower(3, 2)) + Ordinal(OmegaPower(4, 2)) == \
Ordinal(OmegaPower(omega, 2), OmegaPower(4, 2))
def test_comparison():
assert Ordinal(OmegaPower(5, 3)) > Ordinal(OmegaPower(4, 3), OmegaPower(2, 1))
assert Ordinal(OmegaPower(5, 3), OmegaPower(3, 2)) < Ordinal(OmegaPower(5, 4))
assert Ordinal(OmegaPower(5, 4)) < Ordinal(OmegaPower(5, 5), OmegaPower(4, 1))
assert Ordinal(OmegaPower(5, 3), OmegaPower(3, 2)) == \
Ordinal(OmegaPower(5, 3), OmegaPower(3, 2))
assert not Ordinal(OmegaPower(5, 3), OmegaPower(3, 2)) == Ordinal(OmegaPower(5, 3))
assert Ordinal(OmegaPower(omega, 3)) > Ordinal(OmegaPower(5, 3))
def test_multiplication_with_integers():
w = omega
assert 3*w == w
assert w*9 == Ordinal(OmegaPower(1, 9))
def test_multiplication():
w = omega
assert w*(w + 1) == w*w + w
assert (w + 1)*(w + 1) == w*w + w + 1
assert w*1 == w
assert 1*w == w
assert w*ord0 == ord0
assert ord0*w == ord0
assert w**w == w * w**w
assert (w**w)*w*w == w**(w + 2)
def test_exponentiation():
w = omega
assert w**2 == w*w
assert w**3 == w*w*w
assert w**(w + 1) == Ordinal(OmegaPower(omega + 1, 1))
assert (w**w)*(w**w) == w**(w*2)
def test_comapre_not_instance():
w = OmegaPower(omega + 1, 1)
assert(not (w == None))
assert(not (w < 5))
raises(TypeError, lambda: w < 6.66)
def test_is_successort():
w = Ordinal(OmegaPower(5, 1))
assert not w.is_successor_ordinal

View File

@ -0,0 +1,141 @@
from sympy.core.expr import unchanged
from sympy.core.singleton import S
from sympy.core.symbol import Symbol
from sympy.sets.contains import Contains
from sympy.sets.fancysets import Interval
from sympy.sets.powerset import PowerSet
from sympy.sets.sets import FiniteSet
from sympy.testing.pytest import raises, XFAIL
def test_powerset_creation():
assert unchanged(PowerSet, FiniteSet(1, 2))
assert unchanged(PowerSet, S.EmptySet)
raises(ValueError, lambda: PowerSet(123))
assert unchanged(PowerSet, S.Reals)
assert unchanged(PowerSet, S.Integers)
def test_powerset_rewrite_FiniteSet():
assert PowerSet(FiniteSet(1, 2)).rewrite(FiniteSet) == \
FiniteSet(S.EmptySet, FiniteSet(1), FiniteSet(2), FiniteSet(1, 2))
assert PowerSet(S.EmptySet).rewrite(FiniteSet) == FiniteSet(S.EmptySet)
assert PowerSet(S.Naturals).rewrite(FiniteSet) == PowerSet(S.Naturals)
def test_finiteset_rewrite_powerset():
assert FiniteSet(S.EmptySet).rewrite(PowerSet) == PowerSet(S.EmptySet)
assert FiniteSet(
S.EmptySet, FiniteSet(1),
FiniteSet(2), FiniteSet(1, 2)).rewrite(PowerSet) == \
PowerSet(FiniteSet(1, 2))
assert FiniteSet(1, 2, 3).rewrite(PowerSet) == FiniteSet(1, 2, 3)
def test_powerset__contains__():
subset_series = [
S.EmptySet,
FiniteSet(1, 2),
S.Naturals,
S.Naturals0,
S.Integers,
S.Rationals,
S.Reals,
S.Complexes]
l = len(subset_series)
for i in range(l):
for j in range(l):
if i <= j:
assert subset_series[i] in \
PowerSet(subset_series[j], evaluate=False)
else:
assert subset_series[i] not in \
PowerSet(subset_series[j], evaluate=False)
@XFAIL
def test_failing_powerset__contains__():
# XXX These are failing when evaluate=True,
# but using unevaluated PowerSet works fine.
assert FiniteSet(1, 2) not in PowerSet(S.EmptySet).rewrite(FiniteSet)
assert S.Naturals not in PowerSet(S.EmptySet).rewrite(FiniteSet)
assert S.Naturals not in PowerSet(FiniteSet(1, 2)).rewrite(FiniteSet)
assert S.Naturals0 not in PowerSet(S.EmptySet).rewrite(FiniteSet)
assert S.Naturals0 not in PowerSet(FiniteSet(1, 2)).rewrite(FiniteSet)
assert S.Integers not in PowerSet(S.EmptySet).rewrite(FiniteSet)
assert S.Integers not in PowerSet(FiniteSet(1, 2)).rewrite(FiniteSet)
assert S.Rationals not in PowerSet(S.EmptySet).rewrite(FiniteSet)
assert S.Rationals not in PowerSet(FiniteSet(1, 2)).rewrite(FiniteSet)
assert S.Reals not in PowerSet(S.EmptySet).rewrite(FiniteSet)
assert S.Reals not in PowerSet(FiniteSet(1, 2)).rewrite(FiniteSet)
assert S.Complexes not in PowerSet(S.EmptySet).rewrite(FiniteSet)
assert S.Complexes not in PowerSet(FiniteSet(1, 2)).rewrite(FiniteSet)
def test_powerset__len__():
A = PowerSet(S.EmptySet, evaluate=False)
assert len(A) == 1
A = PowerSet(A, evaluate=False)
assert len(A) == 2
A = PowerSet(A, evaluate=False)
assert len(A) == 4
A = PowerSet(A, evaluate=False)
assert len(A) == 16
def test_powerset__iter__():
a = PowerSet(FiniteSet(1, 2)).__iter__()
assert next(a) == S.EmptySet
assert next(a) == FiniteSet(1)
assert next(a) == FiniteSet(2)
assert next(a) == FiniteSet(1, 2)
a = PowerSet(S.Naturals).__iter__()
assert next(a) == S.EmptySet
assert next(a) == FiniteSet(1)
assert next(a) == FiniteSet(2)
assert next(a) == FiniteSet(1, 2)
assert next(a) == FiniteSet(3)
assert next(a) == FiniteSet(1, 3)
assert next(a) == FiniteSet(2, 3)
assert next(a) == FiniteSet(1, 2, 3)
def test_powerset_contains():
A = PowerSet(FiniteSet(1), evaluate=False)
assert A.contains(2) == Contains(2, A)
x = Symbol('x')
A = PowerSet(FiniteSet(x), evaluate=False)
assert A.contains(FiniteSet(1)) == Contains(FiniteSet(1), A)
def test_powerset_method():
# EmptySet
A = FiniteSet()
pset = A.powerset()
assert len(pset) == 1
assert pset == FiniteSet(S.EmptySet)
# FiniteSets
A = FiniteSet(1, 2)
pset = A.powerset()
assert len(pset) == 2**len(A)
assert pset == FiniteSet(FiniteSet(), FiniteSet(1),
FiniteSet(2), A)
# Not finite sets
A = Interval(0, 1)
assert A.powerset() == PowerSet(A)
def test_is_subset():
# covers line 101-102
# initialize powerset(1), which is a subset of powerset(1,2)
subset = PowerSet(FiniteSet(1))
pset = PowerSet(FiniteSet(1, 2))
bad_set = PowerSet(FiniteSet(2, 3))
# assert "subset" is subset of pset == True
assert subset.is_subset(pset)
# assert "bad_set" is subset of pset == False
assert not pset.is_subset(bad_set)

View File

@ -0,0 +1,317 @@
from sympy.sets.setexpr import SetExpr
from sympy.sets import Interval, FiniteSet, Intersection, ImageSet, Union
from sympy.core.expr import Expr
from sympy.core.function import Lambda
from sympy.core.numbers import (I, Rational, oo)
from sympy.core.singleton import S
from sympy.core.symbol import (Dummy, Symbol, symbols)
from sympy.functions.elementary.exponential import (exp, log)
from sympy.functions.elementary.miscellaneous import (Max, Min, sqrt)
from sympy.functions.elementary.trigonometric import cos
from sympy.sets.sets import Set
a, x = symbols("a, x")
_d = Dummy("d")
def test_setexpr():
se = SetExpr(Interval(0, 1))
assert isinstance(se.set, Set)
assert isinstance(se, Expr)
def test_scalar_funcs():
assert SetExpr(Interval(0, 1)).set == Interval(0, 1)
a, b = Symbol('a', real=True), Symbol('b', real=True)
a, b = 1, 2
# TODO: add support for more functions in the future:
for f in [exp, log]:
input_se = f(SetExpr(Interval(a, b)))
output = input_se.set
expected = Interval(Min(f(a), f(b)), Max(f(a), f(b)))
assert output == expected
def test_Add_Mul():
assert (SetExpr(Interval(0, 1)) + 1).set == Interval(1, 2)
assert (SetExpr(Interval(0, 1))*2).set == Interval(0, 2)
def test_Pow():
assert (SetExpr(Interval(0, 2))**2).set == Interval(0, 4)
def test_compound():
assert (exp(SetExpr(Interval(0, 1))*2 + 1)).set == \
Interval(exp(1), exp(3))
def test_Interval_Interval():
assert (SetExpr(Interval(1, 2)) + SetExpr(Interval(10, 20))).set == \
Interval(11, 22)
assert (SetExpr(Interval(1, 2))*SetExpr(Interval(10, 20))).set == \
Interval(10, 40)
def test_FiniteSet_FiniteSet():
assert (SetExpr(FiniteSet(1, 2, 3)) + SetExpr(FiniteSet(1, 2))).set == \
FiniteSet(2, 3, 4, 5)
assert (SetExpr(FiniteSet(1, 2, 3))*SetExpr(FiniteSet(1, 2))).set == \
FiniteSet(1, 2, 3, 4, 6)
def test_Interval_FiniteSet():
assert (SetExpr(FiniteSet(1, 2)) + SetExpr(Interval(0, 10))).set == \
Interval(1, 12)
def test_Many_Sets():
assert (SetExpr(Interval(0, 1)) +
SetExpr(Interval(2, 3)) +
SetExpr(FiniteSet(10, 11, 12))).set == Interval(12, 16)
def test_same_setexprs_are_not_identical():
a = SetExpr(FiniteSet(0, 1))
b = SetExpr(FiniteSet(0, 1))
assert (a + b).set == FiniteSet(0, 1, 2)
# Cannot detect the set being the same:
# assert (a + a).set == FiniteSet(0, 2)
def test_Interval_arithmetic():
i12cc = SetExpr(Interval(1, 2))
i12lo = SetExpr(Interval.Lopen(1, 2))
i12ro = SetExpr(Interval.Ropen(1, 2))
i12o = SetExpr(Interval.open(1, 2))
n23cc = SetExpr(Interval(-2, 3))
n23lo = SetExpr(Interval.Lopen(-2, 3))
n23ro = SetExpr(Interval.Ropen(-2, 3))
n23o = SetExpr(Interval.open(-2, 3))
n3n2cc = SetExpr(Interval(-3, -2))
assert i12cc + i12cc == SetExpr(Interval(2, 4))
assert i12cc - i12cc == SetExpr(Interval(-1, 1))
assert i12cc*i12cc == SetExpr(Interval(1, 4))
assert i12cc/i12cc == SetExpr(Interval(S.Half, 2))
assert i12cc**2 == SetExpr(Interval(1, 4))
assert i12cc**3 == SetExpr(Interval(1, 8))
assert i12lo + i12ro == SetExpr(Interval.open(2, 4))
assert i12lo - i12ro == SetExpr(Interval.Lopen(-1, 1))
assert i12lo*i12ro == SetExpr(Interval.open(1, 4))
assert i12lo/i12ro == SetExpr(Interval.Lopen(S.Half, 2))
assert i12lo + i12lo == SetExpr(Interval.Lopen(2, 4))
assert i12lo - i12lo == SetExpr(Interval.open(-1, 1))
assert i12lo*i12lo == SetExpr(Interval.Lopen(1, 4))
assert i12lo/i12lo == SetExpr(Interval.open(S.Half, 2))
assert i12lo + i12cc == SetExpr(Interval.Lopen(2, 4))
assert i12lo - i12cc == SetExpr(Interval.Lopen(-1, 1))
assert i12lo*i12cc == SetExpr(Interval.Lopen(1, 4))
assert i12lo/i12cc == SetExpr(Interval.Lopen(S.Half, 2))
assert i12lo + i12o == SetExpr(Interval.open(2, 4))
assert i12lo - i12o == SetExpr(Interval.open(-1, 1))
assert i12lo*i12o == SetExpr(Interval.open(1, 4))
assert i12lo/i12o == SetExpr(Interval.open(S.Half, 2))
assert i12lo**2 == SetExpr(Interval.Lopen(1, 4))
assert i12lo**3 == SetExpr(Interval.Lopen(1, 8))
assert i12ro + i12ro == SetExpr(Interval.Ropen(2, 4))
assert i12ro - i12ro == SetExpr(Interval.open(-1, 1))
assert i12ro*i12ro == SetExpr(Interval.Ropen(1, 4))
assert i12ro/i12ro == SetExpr(Interval.open(S.Half, 2))
assert i12ro + i12cc == SetExpr(Interval.Ropen(2, 4))
assert i12ro - i12cc == SetExpr(Interval.Ropen(-1, 1))
assert i12ro*i12cc == SetExpr(Interval.Ropen(1, 4))
assert i12ro/i12cc == SetExpr(Interval.Ropen(S.Half, 2))
assert i12ro + i12o == SetExpr(Interval.open(2, 4))
assert i12ro - i12o == SetExpr(Interval.open(-1, 1))
assert i12ro*i12o == SetExpr(Interval.open(1, 4))
assert i12ro/i12o == SetExpr(Interval.open(S.Half, 2))
assert i12ro**2 == SetExpr(Interval.Ropen(1, 4))
assert i12ro**3 == SetExpr(Interval.Ropen(1, 8))
assert i12o + i12lo == SetExpr(Interval.open(2, 4))
assert i12o - i12lo == SetExpr(Interval.open(-1, 1))
assert i12o*i12lo == SetExpr(Interval.open(1, 4))
assert i12o/i12lo == SetExpr(Interval.open(S.Half, 2))
assert i12o + i12ro == SetExpr(Interval.open(2, 4))
assert i12o - i12ro == SetExpr(Interval.open(-1, 1))
assert i12o*i12ro == SetExpr(Interval.open(1, 4))
assert i12o/i12ro == SetExpr(Interval.open(S.Half, 2))
assert i12o + i12cc == SetExpr(Interval.open(2, 4))
assert i12o - i12cc == SetExpr(Interval.open(-1, 1))
assert i12o*i12cc == SetExpr(Interval.open(1, 4))
assert i12o/i12cc == SetExpr(Interval.open(S.Half, 2))
assert i12o**2 == SetExpr(Interval.open(1, 4))
assert i12o**3 == SetExpr(Interval.open(1, 8))
assert n23cc + n23cc == SetExpr(Interval(-4, 6))
assert n23cc - n23cc == SetExpr(Interval(-5, 5))
assert n23cc*n23cc == SetExpr(Interval(-6, 9))
assert n23cc/n23cc == SetExpr(Interval.open(-oo, oo))
assert n23cc + n23ro == SetExpr(Interval.Ropen(-4, 6))
assert n23cc - n23ro == SetExpr(Interval.Lopen(-5, 5))
assert n23cc*n23ro == SetExpr(Interval.Ropen(-6, 9))
assert n23cc/n23ro == SetExpr(Interval.Lopen(-oo, oo))
assert n23cc + n23lo == SetExpr(Interval.Lopen(-4, 6))
assert n23cc - n23lo == SetExpr(Interval.Ropen(-5, 5))
assert n23cc*n23lo == SetExpr(Interval(-6, 9))
assert n23cc/n23lo == SetExpr(Interval.open(-oo, oo))
assert n23cc + n23o == SetExpr(Interval.open(-4, 6))
assert n23cc - n23o == SetExpr(Interval.open(-5, 5))
assert n23cc*n23o == SetExpr(Interval.open(-6, 9))
assert n23cc/n23o == SetExpr(Interval.open(-oo, oo))
assert n23cc**2 == SetExpr(Interval(0, 9))
assert n23cc**3 == SetExpr(Interval(-8, 27))
n32cc = SetExpr(Interval(-3, 2))
n32lo = SetExpr(Interval.Lopen(-3, 2))
n32ro = SetExpr(Interval.Ropen(-3, 2))
assert n32cc*n32lo == SetExpr(Interval.Ropen(-6, 9))
assert n32cc*n32cc == SetExpr(Interval(-6, 9))
assert n32lo*n32cc == SetExpr(Interval.Ropen(-6, 9))
assert n32cc*n32ro == SetExpr(Interval(-6, 9))
assert n32lo*n32ro == SetExpr(Interval.Ropen(-6, 9))
assert n32cc/n32lo == SetExpr(Interval.Ropen(-oo, oo))
assert i12cc/n32lo == SetExpr(Interval.Ropen(-oo, oo))
assert n3n2cc**2 == SetExpr(Interval(4, 9))
assert n3n2cc**3 == SetExpr(Interval(-27, -8))
assert n23cc + i12cc == SetExpr(Interval(-1, 5))
assert n23cc - i12cc == SetExpr(Interval(-4, 2))
assert n23cc*i12cc == SetExpr(Interval(-4, 6))
assert n23cc/i12cc == SetExpr(Interval(-2, 3))
def test_SetExpr_Intersection():
x, y, z, w = symbols("x y z w")
set1 = Interval(x, y)
set2 = Interval(w, z)
inter = Intersection(set1, set2)
se = SetExpr(inter)
assert exp(se).set == Intersection(
ImageSet(Lambda(x, exp(x)), set1),
ImageSet(Lambda(x, exp(x)), set2))
assert cos(se).set == ImageSet(Lambda(x, cos(x)), inter)
def test_SetExpr_Interval_div():
# TODO: some expressions cannot be calculated due to bugs (currently
# commented):
assert SetExpr(Interval(-3, -2))/SetExpr(Interval(-2, 1)) == SetExpr(Interval(-oo, oo))
assert SetExpr(Interval(2, 3))/SetExpr(Interval(-2, 2)) == SetExpr(Interval(-oo, oo))
assert SetExpr(Interval(-3, -2))/SetExpr(Interval(0, 4)) == SetExpr(Interval(-oo, Rational(-1, 2)))
assert SetExpr(Interval(2, 4))/SetExpr(Interval(-3, 0)) == SetExpr(Interval(-oo, Rational(-2, 3)))
assert SetExpr(Interval(2, 4))/SetExpr(Interval(0, 3)) == SetExpr(Interval(Rational(2, 3), oo))
# assert SetExpr(Interval(0, 1))/SetExpr(Interval(0, 1)) == SetExpr(Interval(0, oo))
# assert SetExpr(Interval(-1, 0))/SetExpr(Interval(0, 1)) == SetExpr(Interval(-oo, 0))
assert SetExpr(Interval(-1, 2))/SetExpr(Interval(-2, 2)) == SetExpr(Interval(-oo, oo))
assert 1/SetExpr(Interval(-1, 2)) == SetExpr(Union(Interval(-oo, -1), Interval(S.Half, oo)))
assert 1/SetExpr(Interval(0, 2)) == SetExpr(Interval(S.Half, oo))
assert (-1)/SetExpr(Interval(0, 2)) == SetExpr(Interval(-oo, Rational(-1, 2)))
assert 1/SetExpr(Interval(-oo, 0)) == SetExpr(Interval.open(-oo, 0))
assert 1/SetExpr(Interval(-1, 0)) == SetExpr(Interval(-oo, -1))
# assert (-2)/SetExpr(Interval(-oo, 0)) == SetExpr(Interval(0, oo))
# assert 1/SetExpr(Interval(-oo, -1)) == SetExpr(Interval(-1, 0))
# assert SetExpr(Interval(1, 2))/a == Mul(SetExpr(Interval(1, 2)), 1/a, evaluate=False)
# assert SetExpr(Interval(1, 2))/0 == SetExpr(Interval(1, 2))*zoo
# assert SetExpr(Interval(1, oo))/oo == SetExpr(Interval(0, oo))
# assert SetExpr(Interval(1, oo))/(-oo) == SetExpr(Interval(-oo, 0))
# assert SetExpr(Interval(-oo, -1))/oo == SetExpr(Interval(-oo, 0))
# assert SetExpr(Interval(-oo, -1))/(-oo) == SetExpr(Interval(0, oo))
# assert SetExpr(Interval(-oo, oo))/oo == SetExpr(Interval(-oo, oo))
# assert SetExpr(Interval(-oo, oo))/(-oo) == SetExpr(Interval(-oo, oo))
# assert SetExpr(Interval(-1, oo))/oo == SetExpr(Interval(0, oo))
# assert SetExpr(Interval(-1, oo))/(-oo) == SetExpr(Interval(-oo, 0))
# assert SetExpr(Interval(-oo, 1))/oo == SetExpr(Interval(-oo, 0))
# assert SetExpr(Interval(-oo, 1))/(-oo) == SetExpr(Interval(0, oo))
def test_SetExpr_Interval_pow():
assert SetExpr(Interval(0, 2))**2 == SetExpr(Interval(0, 4))
assert SetExpr(Interval(-1, 1))**2 == SetExpr(Interval(0, 1))
assert SetExpr(Interval(1, 2))**2 == SetExpr(Interval(1, 4))
assert SetExpr(Interval(-1, 2))**3 == SetExpr(Interval(-1, 8))
assert SetExpr(Interval(-1, 1))**0 == SetExpr(FiniteSet(1))
assert SetExpr(Interval(1, 2))**Rational(5, 2) == SetExpr(Interval(1, 4*sqrt(2)))
#assert SetExpr(Interval(-1, 2))**Rational(1, 3) == SetExpr(Interval(-1, 2**Rational(1, 3)))
#assert SetExpr(Interval(0, 2))**S.Half == SetExpr(Interval(0, sqrt(2)))
#assert SetExpr(Interval(-4, 2))**Rational(2, 3) == SetExpr(Interval(0, 2*2**Rational(1, 3)))
#assert SetExpr(Interval(-1, 5))**S.Half == SetExpr(Interval(0, sqrt(5)))
#assert SetExpr(Interval(-oo, 2))**S.Half == SetExpr(Interval(0, sqrt(2)))
#assert SetExpr(Interval(-2, 3))**(Rational(-1, 4)) == SetExpr(Interval(0, oo))
assert SetExpr(Interval(1, 5))**(-2) == SetExpr(Interval(Rational(1, 25), 1))
assert SetExpr(Interval(-1, 3))**(-2) == SetExpr(Interval(0, oo))
assert SetExpr(Interval(0, 2))**(-2) == SetExpr(Interval(Rational(1, 4), oo))
assert SetExpr(Interval(-1, 2))**(-3) == SetExpr(Union(Interval(-oo, -1), Interval(Rational(1, 8), oo)))
assert SetExpr(Interval(-3, -2))**(-3) == SetExpr(Interval(Rational(-1, 8), Rational(-1, 27)))
assert SetExpr(Interval(-3, -2))**(-2) == SetExpr(Interval(Rational(1, 9), Rational(1, 4)))
#assert SetExpr(Interval(0, oo))**S.Half == SetExpr(Interval(0, oo))
#assert SetExpr(Interval(-oo, -1))**Rational(1, 3) == SetExpr(Interval(-oo, -1))
#assert SetExpr(Interval(-2, 3))**(Rational(-1, 3)) == SetExpr(Interval(-oo, oo))
assert SetExpr(Interval(-oo, 0))**(-2) == SetExpr(Interval.open(0, oo))
assert SetExpr(Interval(-2, 0))**(-2) == SetExpr(Interval(Rational(1, 4), oo))
assert SetExpr(Interval(Rational(1, 3), S.Half))**oo == SetExpr(FiniteSet(0))
assert SetExpr(Interval(0, S.Half))**oo == SetExpr(FiniteSet(0))
assert SetExpr(Interval(S.Half, 1))**oo == SetExpr(Interval(0, oo))
assert SetExpr(Interval(0, 1))**oo == SetExpr(Interval(0, oo))
assert SetExpr(Interval(2, 3))**oo == SetExpr(FiniteSet(oo))
assert SetExpr(Interval(1, 2))**oo == SetExpr(Interval(0, oo))
assert SetExpr(Interval(S.Half, 3))**oo == SetExpr(Interval(0, oo))
assert SetExpr(Interval(Rational(-1, 3), Rational(-1, 4)))**oo == SetExpr(FiniteSet(0))
assert SetExpr(Interval(-1, Rational(-1, 2)))**oo == SetExpr(Interval(-oo, oo))
assert SetExpr(Interval(-3, -2))**oo == SetExpr(FiniteSet(-oo, oo))
assert SetExpr(Interval(-2, -1))**oo == SetExpr(Interval(-oo, oo))
assert SetExpr(Interval(-2, Rational(-1, 2)))**oo == SetExpr(Interval(-oo, oo))
assert SetExpr(Interval(Rational(-1, 2), S.Half))**oo == SetExpr(FiniteSet(0))
assert SetExpr(Interval(Rational(-1, 2), 1))**oo == SetExpr(Interval(0, oo))
assert SetExpr(Interval(Rational(-2, 3), 2))**oo == SetExpr(Interval(0, oo))
assert SetExpr(Interval(-1, 1))**oo == SetExpr(Interval(-oo, oo))
assert SetExpr(Interval(-1, S.Half))**oo == SetExpr(Interval(-oo, oo))
assert SetExpr(Interval(-1, 2))**oo == SetExpr(Interval(-oo, oo))
assert SetExpr(Interval(-2, S.Half))**oo == SetExpr(Interval(-oo, oo))
assert (SetExpr(Interval(1, 2))**x).dummy_eq(SetExpr(ImageSet(Lambda(_d, _d**x), Interval(1, 2))))
assert SetExpr(Interval(2, 3))**(-oo) == SetExpr(FiniteSet(0))
assert SetExpr(Interval(0, 2))**(-oo) == SetExpr(Interval(0, oo))
assert (SetExpr(Interval(-1, 2))**(-oo)).dummy_eq(SetExpr(ImageSet(Lambda(_d, _d**(-oo)), Interval(-1, 2))))
def test_SetExpr_Integers():
assert SetExpr(S.Integers) + 1 == SetExpr(S.Integers)
assert (SetExpr(S.Integers) + I).dummy_eq(
SetExpr(ImageSet(Lambda(_d, _d + I), S.Integers)))
assert SetExpr(S.Integers)*(-1) == SetExpr(S.Integers)
assert (SetExpr(S.Integers)*2).dummy_eq(
SetExpr(ImageSet(Lambda(_d, 2*_d), S.Integers)))
assert (SetExpr(S.Integers)*I).dummy_eq(
SetExpr(ImageSet(Lambda(_d, I*_d), S.Integers)))
# issue #18050:
assert SetExpr(S.Integers)._eval_func(Lambda(x, I*x + 1)).dummy_eq(
SetExpr(ImageSet(Lambda(_d, I*_d + 1), S.Integers)))
# needs improvement:
assert (SetExpr(S.Integers)*I + 1).dummy_eq(
SetExpr(ImageSet(Lambda(x, x + 1),
ImageSet(Lambda(_d, _d*I), S.Integers))))

File diff suppressed because it is too large Load Diff