Buckets:
MisterAI/LocalAI_Demo_backends / cpu-diffusers.upgrade-tmp /venv /lib /python3.10 /site-packages /sympy /sets /sets.py
| from __future__ import annotations | |
| from typing import Any, Callable, TYPE_CHECKING, overload | |
| from functools import reduce | |
| from collections import defaultdict | |
| from collections.abc import Mapping, Iterable | |
| import inspect | |
| from sympy.core.kind import Kind, UndefinedKind, NumberKind | |
| from sympy.core.basic import Basic | |
| from sympy.core.containers import Tuple, TupleKind | |
| from sympy.core.decorators import sympify_method_args, sympify_return | |
| from sympy.core.evalf import EvalfMixin | |
| from sympy.core.expr import Expr | |
| from sympy.core.function import Lambda | |
| from sympy.core.logic import (FuzzyBool, fuzzy_bool, fuzzy_or, fuzzy_and, | |
| fuzzy_not) | |
| from sympy.core.numbers import Float, Integer | |
| from sympy.core.operations import LatticeOp | |
| from sympy.core.parameters import global_parameters | |
| from sympy.core.relational import Eq, Ne, is_lt | |
| from sympy.core.singleton import Singleton, S | |
| from sympy.core.sorting import ordered | |
| from sympy.core.symbol import symbols, Symbol, Dummy, uniquely_named_symbol | |
| from sympy.core.sympify import _sympify, sympify, _sympy_converter | |
| from sympy.functions.elementary.exponential import exp, log | |
| from sympy.functions.elementary.miscellaneous import Max, Min | |
| from sympy.logic.boolalg import And, Or, Not, Xor, true, false | |
| from sympy.utilities.decorator import deprecated | |
| from sympy.utilities.exceptions import sympy_deprecation_warning | |
| from sympy.utilities.iterables import (iproduct, sift, roundrobin, iterable, | |
| subsets) | |
| from sympy.utilities.misc import func_name, filldedent | |
| from mpmath import mpi, mpf | |
| from mpmath.libmp.libmpf import prec_to_dps | |
| tfn = defaultdict(lambda: None, { | |
| True: S.true, | |
| S.true: S.true, | |
| False: S.false, | |
| S.false: S.false}) | |
| class Set(Basic, EvalfMixin): | |
| """ | |
| The base class for any kind of set. | |
| Explanation | |
| =========== | |
| This is not meant to be used directly as a container of items. It does not | |
| behave like the builtin ``set``; see :class:`FiniteSet` for that. | |
| Real intervals are represented by the :class:`Interval` class and unions of | |
| sets by the :class:`Union` class. The empty set is represented by the | |
| :class:`EmptySet` class and available as a singleton as ``S.EmptySet``. | |
| """ | |
| __slots__: tuple[()] = () | |
| is_number = False | |
| is_iterable = False | |
| is_interval = False | |
| is_FiniteSet = False | |
| is_Interval = False | |
| is_ProductSet = False | |
| is_Union = False | |
| is_Intersection: FuzzyBool = None | |
| is_UniversalSet: FuzzyBool = None | |
| is_Complement: FuzzyBool = None | |
| is_ComplexRegion = False | |
| is_empty: FuzzyBool = None | |
| is_finite_set: FuzzyBool = None | |
| # type: ignore | |
| def is_EmptySet(self): | |
| return None | |
| if TYPE_CHECKING: | |
| def __new__(cls, *args: Basic | complex) -> Set: | |
| ... | |
| # type: ignore | |
| def subs(self, arg1: Mapping[Basic | complex, Set | complex], arg2: None=None) -> Set: ... | |
| def subs(self, arg1: Iterable[tuple[Basic | complex, Set | complex]], arg2: None=None, **kwargs: Any) -> Set: ... | |
| def subs(self, arg1: Set | complex, arg2: Set | complex) -> Set: ... | |
| def subs(self, arg1: Mapping[Basic | complex, Basic | complex], arg2: None=None, **kwargs: Any) -> Basic: ... | |
| def subs(self, arg1: Iterable[tuple[Basic | complex, Basic | complex]], arg2: None=None, **kwargs: Any) -> Basic: ... | |
| def subs(self, arg1: Basic | complex, arg2: Basic | complex, **kwargs: Any) -> Basic: ... | |
| def subs(self, arg1: Mapping[Basic | complex, Basic | complex] | Basic | complex, # type: ignore | |
| arg2: Basic | complex | None = None, **kwargs: Any) -> Basic: | |
| ... | |
| def simplify(self, **kwargs) -> Set: | |
| assert False | |
| def evalf(self, n: int = 15, subs: dict[Basic, Basic | float] | None = None, | |
| maxn: int = 100, chop: bool = False, strict: bool = False, | |
| quad: str | None = None, verbose: bool = False) -> Set: | |
| ... | |
| n = evalf | |
| def _infimum_key(expr): | |
| """ | |
| Return infimum (if possible) else S.Infinity. | |
| """ | |
| try: | |
| infimum = expr.inf | |
| assert infimum.is_comparable | |
| infimum = infimum.evalf() # issue #18505 | |
| except (NotImplementedError, | |
| AttributeError, AssertionError, ValueError): | |
| infimum = S.Infinity | |
| return infimum | |
| def union(self, other): | |
| """ | |
| Returns the union of ``self`` and ``other``. | |
| Examples | |
| ======== | |
| As a shortcut it is possible to use the ``+`` operator: | |
| >>> from sympy import Interval, FiniteSet | |
| >>> Interval(0, 1).union(Interval(2, 3)) | |
| Union(Interval(0, 1), Interval(2, 3)) | |
| >>> Interval(0, 1) + Interval(2, 3) | |
| Union(Interval(0, 1), Interval(2, 3)) | |
| >>> Interval(1, 2, True, True) + FiniteSet(2, 3) | |
| Union({3}, Interval.Lopen(1, 2)) | |
| Similarly it is possible to use the ``-`` operator for set differences: | |
| >>> Interval(0, 2) - Interval(0, 1) | |
| Interval.Lopen(1, 2) | |
| >>> Interval(1, 3) - FiniteSet(2) | |
| Union(Interval.Ropen(1, 2), Interval.Lopen(2, 3)) | |
| """ | |
| return Union(self, other) | |
| def intersect(self, other): | |
| """ | |
| Returns the intersection of 'self' and 'other'. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval | |
| >>> Interval(1, 3).intersect(Interval(1, 2)) | |
| Interval(1, 2) | |
| >>> from sympy import imageset, Lambda, symbols, S | |
| >>> n, m = symbols('n m') | |
| >>> a = imageset(Lambda(n, 2*n), S.Integers) | |
| >>> a.intersect(imageset(Lambda(m, 2*m + 1), S.Integers)) | |
| EmptySet | |
| """ | |
| return Intersection(self, other) | |
| def intersection(self, other): | |
| """ | |
| Alias for :meth:`intersect()` | |
| """ | |
| return self.intersect(other) | |
| def is_disjoint(self, other): | |
| """ | |
| Returns True if ``self`` and ``other`` are disjoint. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval | |
| >>> Interval(0, 2).is_disjoint(Interval(1, 2)) | |
| False | |
| >>> Interval(0, 2).is_disjoint(Interval(3, 4)) | |
| True | |
| References | |
| ========== | |
| .. [1] https://en.wikipedia.org/wiki/Disjoint_sets | |
| """ | |
| return self.intersect(other) == S.EmptySet | |
| def isdisjoint(self, other): | |
| """ | |
| Alias for :meth:`is_disjoint()` | |
| """ | |
| return self.is_disjoint(other) | |
| def complement(self, universe): | |
| r""" | |
| The complement of 'self' w.r.t the given universe. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval, S | |
| >>> Interval(0, 1).complement(S.Reals) | |
| Union(Interval.open(-oo, 0), Interval.open(1, oo)) | |
| >>> Interval(0, 1).complement(S.UniversalSet) | |
| Complement(UniversalSet, Interval(0, 1)) | |
| """ | |
| return Complement(universe, self) | |
| def _complement(self, other): | |
| # this behaves as other - self | |
| if isinstance(self, ProductSet) and isinstance(other, ProductSet): | |
| # If self and other are disjoint then other - self == self | |
| if len(self.sets) != len(other.sets): | |
| return other | |
| # There can be other ways to represent this but this gives: | |
| # (A x B) - (C x D) = ((A - C) x B) U (A x (B - D)) | |
| overlaps = [] | |
| pairs = list(zip(self.sets, other.sets)) | |
| for n in range(len(pairs)): | |
| sets = (o if i != n else o-s for i, (s, o) in enumerate(pairs)) | |
| overlaps.append(ProductSet(*sets)) | |
| return Union(*overlaps) | |
| elif isinstance(other, Interval): | |
| if isinstance(self, (Interval, FiniteSet)): | |
| return Intersection(other, self.complement(S.Reals)) | |
| elif isinstance(other, Union): | |
| return Union(*(o - self for o in other.args)) | |
| elif isinstance(other, Complement): | |
| return Complement(other.args[0], Union(other.args[1], self), evaluate=False) | |
| elif other is S.EmptySet: | |
| return S.EmptySet | |
| elif isinstance(other, FiniteSet): | |
| sifted = sift(other, lambda x: fuzzy_bool(self.contains(x))) | |
| # ignore those that are contained in self | |
| return Union(FiniteSet(*(sifted[False])), | |
| Complement(FiniteSet(*(sifted[None])), self, evaluate=False) | |
| if sifted[None] else S.EmptySet) | |
| def symmetric_difference(self, other): | |
| """ | |
| Returns symmetric difference of ``self`` and ``other``. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval, S | |
| >>> Interval(1, 3).symmetric_difference(S.Reals) | |
| Union(Interval.open(-oo, 1), Interval.open(3, oo)) | |
| >>> Interval(1, 10).symmetric_difference(S.Reals) | |
| Union(Interval.open(-oo, 1), Interval.open(10, oo)) | |
| >>> from sympy import S, EmptySet | |
| >>> S.Reals.symmetric_difference(EmptySet) | |
| Reals | |
| References | |
| ========== | |
| .. [1] https://en.wikipedia.org/wiki/Symmetric_difference | |
| """ | |
| return SymmetricDifference(self, other) | |
| def _symmetric_difference(self, other): | |
| return Union(Complement(self, other), Complement(other, self)) | |
| def inf(self): | |
| """ | |
| The infimum of ``self``. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval, Union | |
| >>> Interval(0, 1).inf | |
| 0 | |
| >>> Union(Interval(0, 1), Interval(2, 3)).inf | |
| 0 | |
| """ | |
| return self._inf | |
| def _inf(self): | |
| raise NotImplementedError("(%s)._inf" % self) | |
| def sup(self): | |
| """ | |
| The supremum of ``self``. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval, Union | |
| >>> Interval(0, 1).sup | |
| 1 | |
| >>> Union(Interval(0, 1), Interval(2, 3)).sup | |
| 3 | |
| """ | |
| return self._sup | |
| def _sup(self): | |
| raise NotImplementedError("(%s)._sup" % self) | |
| def contains(self, other): | |
| """ | |
| Returns a SymPy value indicating whether ``other`` is contained | |
| in ``self``: ``true`` if it is, ``false`` if it is not, else | |
| an unevaluated ``Contains`` expression (or, as in the case of | |
| ConditionSet and a union of FiniteSet/Intervals, an expression | |
| indicating the conditions for containment). | |
| Examples | |
| ======== | |
| >>> from sympy import Interval, S | |
| >>> from sympy.abc import x | |
| >>> Interval(0, 1).contains(0.5) | |
| True | |
| As a shortcut it is possible to use the ``in`` operator, but that | |
| will raise an error unless an affirmative true or false is not | |
| obtained. | |
| >>> Interval(0, 1).contains(x) | |
| (0 <= x) & (x <= 1) | |
| >>> x in Interval(0, 1) | |
| Traceback (most recent call last): | |
| ... | |
| TypeError: did not evaluate to a bool: None | |
| The result of 'in' is a bool, not a SymPy value | |
| >>> 1 in Interval(0, 2) | |
| True | |
| >>> _ is S.true | |
| False | |
| """ | |
| from .contains import Contains | |
| other = sympify(other, strict=True) | |
| c = self._contains(other) | |
| if isinstance(c, Contains): | |
| return c | |
| if c is None: | |
| return Contains(other, self, evaluate=False) | |
| b = tfn[c] | |
| if b is None: | |
| return c | |
| return b | |
| def _contains(self, other): | |
| """Test if ``other`` is an element of the set ``self``. | |
| This is an internal method that is expected to be overridden by | |
| subclasses of ``Set`` and will be called by the public | |
| :func:`Set.contains` method or the :class:`Contains` expression. | |
| Parameters | |
| ========== | |
| other: Sympified :class:`Basic` instance | |
| The object whose membership in ``self`` is to be tested. | |
| Returns | |
| ======= | |
| Symbolic :class:`Boolean` or ``None``. | |
| A return value of ``None`` indicates that it is unknown whether | |
| ``other`` is contained in ``self``. Returning ``None`` from here | |
| ensures that ``self.contains(other)`` or ``Contains(self, other)`` will | |
| return an unevaluated :class:`Contains` expression. | |
| If not ``None`` then the returned value is a :class:`Boolean` that is | |
| logically equivalent to the statement that ``other`` is an element of | |
| ``self``. Usually this would be either ``S.true`` or ``S.false`` but | |
| not always. | |
| """ | |
| raise NotImplementedError(f"{type(self).__name__}._contains") | |
| def is_subset(self, other): | |
| """ | |
| Returns True if ``self`` is a subset of ``other``. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval | |
| >>> Interval(0, 0.5).is_subset(Interval(0, 1)) | |
| True | |
| >>> Interval(0, 1).is_subset(Interval(0, 1, left_open=True)) | |
| False | |
| """ | |
| if not isinstance(other, Set): | |
| raise ValueError("Unknown argument '%s'" % other) | |
| # Handle the trivial cases | |
| if self == other: | |
| return True | |
| is_empty = self.is_empty | |
| if is_empty is True: | |
| return True | |
| elif fuzzy_not(is_empty) and other.is_empty: | |
| return False | |
| if self.is_finite_set is False and other.is_finite_set: | |
| return False | |
| # Dispatch on subclass rules | |
| ret = self._eval_is_subset(other) | |
| if ret is not None: | |
| return ret | |
| ret = other._eval_is_superset(self) | |
| if ret is not None: | |
| return ret | |
| # Use pairwise rules from multiple dispatch | |
| from sympy.sets.handlers.issubset import is_subset_sets | |
| ret = is_subset_sets(self, other) | |
| if ret is not None: | |
| return ret | |
| # Fall back on computing the intersection | |
| # XXX: We shouldn't do this. A query like this should be handled | |
| # without evaluating new Set objects. It should be the other way round | |
| # so that the intersect method uses is_subset for evaluation. | |
| if self.intersect(other) == self: | |
| return True | |
| def _eval_is_subset(self, other): | |
| '''Returns a fuzzy bool for whether self is a subset of other.''' | |
| return None | |
| def _eval_is_superset(self, other): | |
| '''Returns a fuzzy bool for whether self is a subset of other.''' | |
| return None | |
| # This should be deprecated: | |
| def issubset(self, other): | |
| """ | |
| Alias for :meth:`is_subset()` | |
| """ | |
| return self.is_subset(other) | |
| def is_proper_subset(self, other): | |
| """ | |
| Returns True if ``self`` is a proper subset of ``other``. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval | |
| >>> Interval(0, 0.5).is_proper_subset(Interval(0, 1)) | |
| True | |
| >>> Interval(0, 1).is_proper_subset(Interval(0, 1)) | |
| False | |
| """ | |
| if isinstance(other, Set): | |
| return self != other and self.is_subset(other) | |
| else: | |
| raise ValueError("Unknown argument '%s'" % other) | |
| def is_superset(self, other): | |
| """ | |
| Returns True if ``self`` is a superset of ``other``. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval | |
| >>> Interval(0, 0.5).is_superset(Interval(0, 1)) | |
| False | |
| >>> Interval(0, 1).is_superset(Interval(0, 1, left_open=True)) | |
| True | |
| """ | |
| if isinstance(other, Set): | |
| return other.is_subset(self) | |
| else: | |
| raise ValueError("Unknown argument '%s'" % other) | |
| # This should be deprecated: | |
| def issuperset(self, other): | |
| """ | |
| Alias for :meth:`is_superset()` | |
| """ | |
| return self.is_superset(other) | |
| def is_proper_superset(self, other): | |
| """ | |
| Returns True if ``self`` is a proper superset of ``other``. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval | |
| >>> Interval(0, 1).is_proper_superset(Interval(0, 0.5)) | |
| True | |
| >>> Interval(0, 1).is_proper_superset(Interval(0, 1)) | |
| False | |
| """ | |
| if isinstance(other, Set): | |
| return self != other and self.is_superset(other) | |
| else: | |
| raise ValueError("Unknown argument '%s'" % other) | |
| def _eval_powerset(self): | |
| from .powerset import PowerSet | |
| return PowerSet(self) | |
| def powerset(self): | |
| """ | |
| Find the Power set of ``self``. | |
| Examples | |
| ======== | |
| >>> from sympy import EmptySet, FiniteSet, Interval | |
| A power set of an empty set: | |
| >>> A = EmptySet | |
| >>> A.powerset() | |
| {EmptySet} | |
| A power set of a finite set: | |
| >>> A = FiniteSet(1, 2) | |
| >>> a, b, c = FiniteSet(1), FiniteSet(2), FiniteSet(1, 2) | |
| >>> A.powerset() == FiniteSet(a, b, c, EmptySet) | |
| True | |
| A power set of an interval: | |
| >>> Interval(1, 2).powerset() | |
| PowerSet(Interval(1, 2)) | |
| References | |
| ========== | |
| .. [1] https://en.wikipedia.org/wiki/Power_set | |
| """ | |
| return self._eval_powerset() | |
| def measure(self): | |
| """ | |
| The (Lebesgue) measure of ``self``. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval, Union | |
| >>> Interval(0, 1).measure | |
| 1 | |
| >>> Union(Interval(0, 1), Interval(2, 3)).measure | |
| 2 | |
| """ | |
| return self._measure | |
| def kind(self): | |
| """ | |
| The kind of a Set | |
| Explanation | |
| =========== | |
| Any :class:`Set` will have kind :class:`SetKind` which is | |
| parametrised by the kind of the elements of the set. For example | |
| most sets are sets of numbers and will have kind | |
| ``SetKind(NumberKind)``. If elements of sets are different in kind than | |
| their kind will ``SetKind(UndefinedKind)``. See | |
| :class:`sympy.core.kind.Kind` for an explanation of the kind system. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval, Matrix, FiniteSet, EmptySet, ProductSet, PowerSet | |
| >>> FiniteSet(Matrix([1, 2])).kind | |
| SetKind(MatrixKind(NumberKind)) | |
| >>> Interval(1, 2).kind | |
| SetKind(NumberKind) | |
| >>> EmptySet.kind | |
| SetKind() | |
| A :class:`sympy.sets.powerset.PowerSet` is a set of sets: | |
| >>> PowerSet({1, 2, 3}).kind | |
| SetKind(SetKind(NumberKind)) | |
| A :class:`ProductSet` represents the set of tuples of elements of | |
| other sets. Its kind is :class:`sympy.core.containers.TupleKind` | |
| parametrised by the kinds of the elements of those sets: | |
| >>> p = ProductSet(FiniteSet(1, 2), FiniteSet(3, 4)) | |
| >>> list(p) | |
| [(1, 3), (2, 3), (1, 4), (2, 4)] | |
| >>> p.kind | |
| SetKind(TupleKind(NumberKind, NumberKind)) | |
| When all elements of the set do not have same kind, the kind | |
| will be returned as ``SetKind(UndefinedKind)``: | |
| >>> FiniteSet(0, Matrix([1, 2])).kind | |
| SetKind(UndefinedKind) | |
| The kind of the elements of a set are given by the ``element_kind`` | |
| attribute of ``SetKind``: | |
| >>> Interval(1, 2).kind.element_kind | |
| NumberKind | |
| See Also | |
| ======== | |
| NumberKind | |
| sympy.core.kind.UndefinedKind | |
| sympy.core.containers.TupleKind | |
| MatrixKind | |
| sympy.matrices.expressions.sets.MatrixSet | |
| sympy.sets.conditionset.ConditionSet | |
| Rationals | |
| Naturals | |
| Integers | |
| sympy.sets.fancysets.ImageSet | |
| sympy.sets.fancysets.Range | |
| sympy.sets.fancysets.ComplexRegion | |
| sympy.sets.powerset.PowerSet | |
| sympy.sets.sets.ProductSet | |
| sympy.sets.sets.Interval | |
| sympy.sets.sets.Union | |
| sympy.sets.sets.Intersection | |
| sympy.sets.sets.Complement | |
| sympy.sets.sets.EmptySet | |
| sympy.sets.sets.UniversalSet | |
| sympy.sets.sets.FiniteSet | |
| sympy.sets.sets.SymmetricDifference | |
| sympy.sets.sets.DisjointUnion | |
| """ | |
| return self._kind() | |
| def boundary(self): | |
| """ | |
| The boundary or frontier of a set. | |
| Explanation | |
| =========== | |
| A point x is on the boundary of a set S if | |
| 1. x is in the closure of S. | |
| I.e. Every neighborhood of x contains a point in S. | |
| 2. x is not in the interior of S. | |
| I.e. There does not exist an open set centered on x contained | |
| entirely within S. | |
| There are the points on the outer rim of S. If S is open then these | |
| points need not actually be contained within S. | |
| For example, the boundary of an interval is its start and end points. | |
| This is true regardless of whether or not the interval is open. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval | |
| >>> Interval(0, 1).boundary | |
| {0, 1} | |
| >>> Interval(0, 1, True, False).boundary | |
| {0, 1} | |
| """ | |
| return self._boundary | |
| def is_open(self): | |
| """ | |
| Property method to check whether a set is open. | |
| Explanation | |
| =========== | |
| A set is open if and only if it has an empty intersection with its | |
| boundary. In particular, a subset A of the reals is open if and only | |
| if each one of its points is contained in an open interval that is a | |
| subset of A. | |
| Examples | |
| ======== | |
| >>> from sympy import S | |
| >>> S.Reals.is_open | |
| True | |
| >>> S.Rationals.is_open | |
| False | |
| """ | |
| return Intersection(self, self.boundary).is_empty | |
| def is_closed(self): | |
| """ | |
| A property method to check whether a set is closed. | |
| Explanation | |
| =========== | |
| A set is closed if its complement is an open set. The closedness of a | |
| subset of the reals is determined with respect to R and its standard | |
| topology. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval | |
| >>> Interval(0, 1).is_closed | |
| True | |
| """ | |
| return self.boundary.is_subset(self) | |
| def closure(self): | |
| """ | |
| Property method which returns the closure of a set. | |
| The closure is defined as the union of the set itself and its | |
| boundary. | |
| Examples | |
| ======== | |
| >>> from sympy import S, Interval | |
| >>> S.Reals.closure | |
| Reals | |
| >>> Interval(0, 1).closure | |
| Interval(0, 1) | |
| """ | |
| return self + self.boundary | |
| def interior(self): | |
| """ | |
| Property method which returns the interior of a set. | |
| The interior of a set S consists all points of S that do not | |
| belong to the boundary of S. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval | |
| >>> Interval(0, 1).interior | |
| Interval.open(0, 1) | |
| >>> Interval(0, 1).boundary.interior | |
| EmptySet | |
| """ | |
| return self - self.boundary | |
| def _boundary(self): | |
| raise NotImplementedError() | |
| def _measure(self): | |
| raise NotImplementedError("(%s)._measure" % self) | |
| def _kind(self): | |
| return SetKind(UndefinedKind) | |
| def _eval_evalf(self, prec): | |
| dps = prec_to_dps(prec) | |
| return self.func(*[arg.evalf(n=dps) for arg in self.args]) | |
| def __add__(self, other): | |
| return self.union(other) | |
| def __or__(self, other): | |
| return self.union(other) | |
| def __and__(self, other): | |
| return self.intersect(other) | |
| def __mul__(self, other): | |
| return ProductSet(self, other) | |
| def __xor__(self, other): | |
| return SymmetricDifference(self, other) | |
| def __pow__(self, exp): | |
| if not (exp.is_Integer and exp >= 0): | |
| raise ValueError("%s: Exponent must be a positive Integer" % exp) | |
| return ProductSet(*[self]*exp) | |
| def __sub__(self, other): | |
| return Complement(self, other) | |
| def __contains__(self, other): | |
| other = _sympify(other) | |
| c = self._contains(other) | |
| b = tfn[c] | |
| if b is None: | |
| # x in y must evaluate to T or F; to entertain a None | |
| # result with Set use y.contains(x) | |
| raise TypeError('did not evaluate to a bool: %r' % c) | |
| return b | |
| class ProductSet(Set): | |
| """ | |
| Represents a Cartesian Product of Sets. | |
| Explanation | |
| =========== | |
| Returns a Cartesian product given several sets as either an iterable | |
| or individual arguments. | |
| Can use ``*`` operator on any sets for convenient shorthand. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval, FiniteSet, ProductSet | |
| >>> I = Interval(0, 5); S = FiniteSet(1, 2, 3) | |
| >>> ProductSet(I, S) | |
| ProductSet(Interval(0, 5), {1, 2, 3}) | |
| >>> (2, 2) in ProductSet(I, S) | |
| True | |
| >>> Interval(0, 1) * Interval(0, 1) # The unit square | |
| ProductSet(Interval(0, 1), Interval(0, 1)) | |
| >>> coin = FiniteSet('H', 'T') | |
| >>> set(coin**2) | |
| {(H, H), (H, T), (T, H), (T, T)} | |
| The Cartesian product is not commutative or associative e.g.: | |
| >>> I*S == S*I | |
| False | |
| >>> (I*I)*I == I*(I*I) | |
| False | |
| Notes | |
| ===== | |
| - Passes most operations down to the argument sets | |
| References | |
| ========== | |
| .. [1] https://en.wikipedia.org/wiki/Cartesian_product | |
| """ | |
| is_ProductSet = True | |
| def __new__(cls, *sets, **assumptions): | |
| if len(sets) == 1 and iterable(sets[0]) and not isinstance(sets[0], (Set, set)): | |
| sympy_deprecation_warning( | |
| """ | |
| ProductSet(iterable) is deprecated. Use ProductSet(*iterable) instead. | |
| """, | |
| deprecated_since_version="1.5", | |
| active_deprecations_target="deprecated-productset-iterable", | |
| ) | |
| sets = tuple(sets[0]) | |
| sets = [sympify(s) for s in sets] | |
| if not all(isinstance(s, Set) for s in sets): | |
| raise TypeError("Arguments to ProductSet should be of type Set") | |
| # Nullary product of sets is *not* the empty set | |
| if len(sets) == 0: | |
| return FiniteSet(()) | |
| if S.EmptySet in sets: | |
| return S.EmptySet | |
| return Basic.__new__(cls, *sets, **assumptions) | |
| def sets(self): | |
| return self.args | |
| def flatten(self): | |
| def _flatten(sets): | |
| for s in sets: | |
| if s.is_ProductSet: | |
| yield from _flatten(s.sets) | |
| else: | |
| yield s | |
| return ProductSet(*_flatten(self.sets)) | |
| def _contains(self, element): | |
| """ | |
| ``in`` operator for ProductSets. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval | |
| >>> (2, 3) in Interval(0, 5) * Interval(0, 5) | |
| True | |
| >>> (10, 10) in Interval(0, 5) * Interval(0, 5) | |
| False | |
| Passes operation on to constituent sets | |
| """ | |
| if element.is_Symbol: | |
| return None | |
| if not isinstance(element, Tuple) or len(element) != len(self.sets): | |
| return S.false | |
| return And(*[s.contains(e) for s, e in zip(self.sets, element)]) | |
| def as_relational(self, *symbols): | |
| symbols = [_sympify(s) for s in symbols] | |
| if len(symbols) != len(self.sets) or not all( | |
| i.is_Symbol for i in symbols): | |
| raise ValueError( | |
| 'number of symbols must match the number of sets') | |
| return And(*[s.as_relational(i) for s, i in zip(self.sets, symbols)]) | |
| def _boundary(self): | |
| return Union(*(ProductSet(*(b + b.boundary if i != j else b.boundary | |
| for j, b in enumerate(self.sets))) | |
| for i, a in enumerate(self.sets))) | |
| def is_iterable(self): | |
| """ | |
| A property method which tests whether a set is iterable or not. | |
| Returns True if set is iterable, otherwise returns False. | |
| Examples | |
| ======== | |
| >>> from sympy import FiniteSet, Interval | |
| >>> I = Interval(0, 1) | |
| >>> A = FiniteSet(1, 2, 3, 4, 5) | |
| >>> I.is_iterable | |
| False | |
| >>> A.is_iterable | |
| True | |
| """ | |
| return all(set.is_iterable for set in self.sets) | |
| def __iter__(self): | |
| """ | |
| A method which implements is_iterable property method. | |
| If self.is_iterable returns True (both constituent sets are iterable), | |
| then return the Cartesian Product. Otherwise, raise TypeError. | |
| """ | |
| return iproduct(*self.sets) | |
| def is_empty(self): | |
| return fuzzy_or(s.is_empty for s in self.sets) | |
| def is_finite_set(self): | |
| all_finite = fuzzy_and(s.is_finite_set for s in self.sets) | |
| return fuzzy_or([self.is_empty, all_finite]) | |
| def _measure(self): | |
| measure = 1 | |
| for s in self.sets: | |
| measure *= s.measure | |
| return measure | |
| def _kind(self): | |
| return SetKind(TupleKind(*(i.kind.element_kind for i in self.args))) | |
| def __len__(self): | |
| return reduce(lambda a, b: a*b, (len(s) for s in self.args)) | |
| def __bool__(self): | |
| return all(self.sets) | |
| class Interval(Set): | |
| """ | |
| Represents a real interval as a Set. | |
| Usage: | |
| Returns an interval with end points ``start`` and ``end``. | |
| For ``left_open=True`` (default ``left_open`` is ``False``) the interval | |
| will be open on the left. Similarly, for ``right_open=True`` the interval | |
| will be open on the right. | |
| Examples | |
| ======== | |
| >>> from sympy import Symbol, Interval | |
| >>> Interval(0, 1) | |
| Interval(0, 1) | |
| >>> Interval.Ropen(0, 1) | |
| Interval.Ropen(0, 1) | |
| >>> Interval.Ropen(0, 1) | |
| Interval.Ropen(0, 1) | |
| >>> Interval.Lopen(0, 1) | |
| Interval.Lopen(0, 1) | |
| >>> Interval.open(0, 1) | |
| Interval.open(0, 1) | |
| >>> a = Symbol('a', real=True) | |
| >>> Interval(0, a) | |
| Interval(0, a) | |
| Notes | |
| ===== | |
| - Only real end points are supported | |
| - ``Interval(a, b)`` with $a > b$ will return the empty set | |
| - Use the ``evalf()`` method to turn an Interval into an mpmath | |
| ``mpi`` interval instance | |
| References | |
| ========== | |
| .. [1] https://en.wikipedia.org/wiki/Interval_%28mathematics%29 | |
| """ | |
| is_Interval = True | |
| def __new__(cls, start, end, left_open=False, right_open=False): | |
| start = _sympify(start) | |
| end = _sympify(end) | |
| left_open = _sympify(left_open) | |
| right_open = _sympify(right_open) | |
| if not all(isinstance(a, (type(true), type(false))) | |
| for a in [left_open, right_open]): | |
| raise NotImplementedError( | |
| "left_open and right_open can have only true/false values, " | |
| "got %s and %s" % (left_open, right_open)) | |
| # Only allow real intervals | |
| if fuzzy_not(fuzzy_and(i.is_extended_real for i in (start, end, end-start))): | |
| raise ValueError("Non-real intervals are not supported") | |
| # evaluate if possible | |
| if is_lt(end, start): | |
| return S.EmptySet | |
| elif (end - start).is_negative: | |
| return S.EmptySet | |
| if end == start and (left_open or right_open): | |
| return S.EmptySet | |
| if end == start and not (left_open or right_open): | |
| if start is S.Infinity or start is S.NegativeInfinity: | |
| return S.EmptySet | |
| return FiniteSet(end) | |
| # Make sure infinite interval end points are open. | |
| if start is S.NegativeInfinity: | |
| left_open = true | |
| if end is S.Infinity: | |
| right_open = true | |
| if start == S.Infinity or end == S.NegativeInfinity: | |
| return S.EmptySet | |
| return Basic.__new__(cls, start, end, left_open, right_open) | |
| def start(self): | |
| """ | |
| The left end point of the interval. | |
| This property takes the same value as the ``inf`` property. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval | |
| >>> Interval(0, 1).start | |
| 0 | |
| """ | |
| return self._args[0] | |
| def end(self): | |
| """ | |
| The right end point of the interval. | |
| This property takes the same value as the ``sup`` property. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval | |
| >>> Interval(0, 1).end | |
| 1 | |
| """ | |
| return self._args[1] | |
| def left_open(self): | |
| """ | |
| True if interval is left-open. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval | |
| >>> Interval(0, 1, left_open=True).left_open | |
| True | |
| >>> Interval(0, 1, left_open=False).left_open | |
| False | |
| """ | |
| return self._args[2] | |
| def right_open(self): | |
| """ | |
| True if interval is right-open. | |
| Examples | |
| ======== | |
| >>> from sympy import Interval | |
| >>> Interval(0, 1, right_open=True).right_open | |
| True | |
| >>> Interval(0, 1, right_open=False).right_open | |
| False | |
| """ | |
| return self._args[3] | |
| def open(cls, a, b): | |
| """Return an interval including neither boundary.""" | |
| return cls(a, b, True, True) | |
| def Lopen(cls, a, b): | |
| """Return an interval not including the left boundary.""" | |
| return cls(a, b, True, False) | |
| def Ropen(cls, a, b): | |
| """Return an interval not including the right boundary.""" | |
| return cls(a, b, False, True) | |
| def _inf(self): | |
| return self.start | |
| def _sup(self): | |
| return self.end | |
| def left(self): | |
| return self.start | |
| def right(self): | |
| return self.end | |
| def is_empty(self): | |
| if self.left_open or self.right_open: | |
| cond = self.start >= self.end # One/both bounds open | |
| else: | |
| cond = self.start > self.end # Both bounds closed | |
| return fuzzy_bool(cond) | |
| def is_finite_set(self): | |
| return self.measure.is_zero | |
| def _complement(self, other): | |
| if other == S.Reals: | |
| a = Interval(S.NegativeInfinity, self.start, | |
| True, not self.left_open) | |
| b = Interval(self.end, S.Infinity, not self.right_open, True) | |
| return Union(a, b) | |
| if isinstance(other, FiniteSet): | |
| nums = [m for m in other.args if m.is_number] | |
| if nums == []: | |
| return None | |
| return Set._complement(self, other) | |
| def _boundary(self): | |
| finite_points = [p for p in (self.start, self.end) | |
| if abs(p) != S.Infinity] | |
| return FiniteSet(*finite_points) | |
| def _contains(self, other): | |
| if (not isinstance(other, Expr) or other is S.NaN | |
| or other.is_real is False or other.has(S.ComplexInfinity)): | |
| # if an expression has zoo it will be zoo or nan | |
| # and neither of those is real | |
| return false | |
| if self.start is S.NegativeInfinity and self.end is S.Infinity: | |
| if other.is_real is not None: | |
| return tfn[other.is_real] | |
| d = Dummy() | |
| return self.as_relational(d).subs(d, other) | |
| def as_relational(self, x): | |
| """Rewrite an interval in terms of inequalities and logic operators.""" | |
| x = sympify(x) | |
| if self.right_open: | |
| right = x < self.end | |
| else: | |
| right = x <= self.end | |
| if self.left_open: | |
| left = self.start < x | |
| else: | |
| left = self.start <= x | |
| return And(left, right) | |
| def _measure(self): | |
| return self.end - self.start | |
| def _kind(self): | |
| return SetKind(NumberKind) | |
| def to_mpi(self, prec=53): | |
| return mpi(mpf(self.start._eval_evalf(prec)), | |
| mpf(self.end._eval_evalf(prec))) | |
| def _eval_evalf(self, prec): | |
| return Interval(self.left._evalf(prec), self.right._evalf(prec), | |
| left_open=self.left_open, right_open=self.right_open) | |
| def _is_comparable(self, other): | |
| is_comparable = self.start.is_comparable | |
| is_comparable &= self.end.is_comparable | |
| is_comparable &= other.start.is_comparable | |
| is_comparable &= other.end.is_comparable | |
| return is_comparable | |
| def is_left_unbounded(self): | |
| """Return ``True`` if the left endpoint is negative infinity. """ | |
| return self.left is S.NegativeInfinity or self.left == Float("-inf") | |
| def is_right_unbounded(self): | |
| """Return ``True`` if the right endpoint is positive infinity. """ | |
| return self.right is S.Infinity or self.right == Float("+inf") | |
| def _eval_Eq(self, other): | |
| if not isinstance(other, Interval): | |
| if isinstance(other, FiniteSet): | |
| return false | |
| elif isinstance(other, Set): | |
| return None | |
| return false | |
| class Union(Set, LatticeOp): | |
| """ | |
| Represents a union of sets as a :class:`Set`. | |
| Examples | |
| ======== | |
| >>> from sympy import Union, Interval | |
| >>> Union(Interval(1, 2), Interval(3, 4)) | |
| Union(Interval(1, 2), Interval(3, 4)) | |
| The Union constructor will always try to merge overlapping intervals, | |
| if possible. For example: | |
| >>> Union(Interval(1, 2), Interval(2, 3)) | |
| Interval(1, 3) | |
| See Also | |
| ======== | |
| Intersection | |
| References | |
| ========== | |
| .. [1] https://en.wikipedia.org/wiki/Union_%28set_theory%29 | |
| """ | |
| is_Union = True | |
| def identity(self): | |
| return S.EmptySet | |
| def zero(self): | |
| return S.UniversalSet | |
| def __new__(cls, *args, **kwargs): | |
| evaluate = kwargs.get('evaluate', global_parameters.evaluate) | |
| # flatten inputs to merge intersections and iterables | |
| args = _sympify(args) | |
| # Reduce sets using known rules | |
| if evaluate: | |
| args = list(cls._new_args_filter(args)) | |
| return simplify_union(args) | |
| args = list(ordered(args, Set._infimum_key)) | |
| obj = Basic.__new__(cls, *args) | |
| obj._argset = frozenset(args) | |
| return obj | |
| def args(self): | |
| return self._args | |
| def _complement(self, universe): | |
| # DeMorgan's Law | |
| return Intersection(s.complement(universe) for s in self.args) | |
| def _inf(self): | |
| # We use Min so that sup is meaningful in combination with symbolic | |
| # interval end points. | |
| return Min(*[set.inf for set in self.args]) | |
| def _sup(self): | |
| # We use Max so that sup is meaningful in combination with symbolic | |
| # end points. | |
| return Max(*[set.sup for set in self.args]) | |
| def is_empty(self): | |
| return fuzzy_and(set.is_empty for set in self.args) | |
| def is_finite_set(self): | |
| return fuzzy_and(set.is_finite_set for set in self.args) | |
| def _measure(self): | |
| # Measure of a union is the sum of the measures of the sets minus | |
| # the sum of their pairwise intersections plus the sum of their | |
| # triple-wise intersections minus ... etc... | |
| # Sets is a collection of intersections and a set of elementary | |
| # sets which made up those intersections (called "sos" for set of sets) | |
| # An example element might of this list might be: | |
| # ( {A,B,C}, A.intersect(B).intersect(C) ) | |
| # Start with just elementary sets ( ({A}, A), ({B}, B), ... ) | |
| # Then get and subtract ( ({A,B}, (A int B), ... ) while non-zero | |
| sets = [(FiniteSet(s), s) for s in self.args] | |
| measure = 0 | |
| parity = 1 | |
| while sets: | |
| # Add up the measure of these sets and add or subtract it to total | |
| measure += parity * sum(inter.measure for sos, inter in sets) | |
| # For each intersection in sets, compute the intersection with every | |
| # other set not already part of the intersection. | |
| sets = ((sos + FiniteSet(newset), newset.intersect(intersection)) | |
| for sos, intersection in sets for newset in self.args | |
| if newset not in sos) | |
| # Clear out sets with no measure | |
| sets = [(sos, inter) for sos, inter in sets if inter.measure != 0] | |
| # Clear out duplicates | |
| sos_list = [] | |
| sets_list = [] | |
| for _set in sets: | |
| if _set[0] in sos_list: | |
| continue | |
| else: | |
| sos_list.append(_set[0]) | |
| sets_list.append(_set) | |
| sets = sets_list | |
| # Flip Parity - next time subtract/add if we added/subtracted here | |
| parity *= -1 | |
| return measure | |
| def _kind(self): | |
| kinds = tuple(arg.kind for arg in self.args if arg is not S.EmptySet) | |
| if not kinds: | |
| return SetKind() | |
| elif all(i == kinds[0] for i in kinds): | |
| return kinds[0] | |
| else: | |
| return SetKind(UndefinedKind) | |
| def _boundary(self): | |
| def boundary_of_set(i): | |
| """ The boundary of set i minus interior of all other sets """ | |
| b = self.args[i].boundary | |
| for j, a in enumerate(self.args): | |
| if j != i: | |
| b = b - a.interior | |
| return b | |
| return Union(*map(boundary_of_set, range(len(self.args)))) | |
| def _contains(self, other): | |
| return Or(*[s.contains(other) for s in self.args]) | |
| def is_subset(self, other): | |
| return fuzzy_and(s.is_subset(other) for s in self.args) | |
| def as_relational(self, symbol): | |
| """Rewrite a Union in terms of equalities and logic operators. """ | |
| if (len(self.args) == 2 and | |
| all(isinstance(i, Interval) for i in self.args)): | |
| # optimization to give 3 args as (x > 1) & (x < 5) & Ne(x, 3) | |
| # instead of as 4, ((1 <= x) & (x < 3)) | ((x <= 5) & (3 < x)) | |
| # XXX: This should be ideally be improved to handle any number of | |
| # intervals and also not to assume that the intervals are in any | |
| # particular sorted order. | |
| a, b = self.args | |
| if a.sup == b.inf and a.right_open and b.left_open: | |
| mincond = symbol > a.inf if a.left_open else symbol >= a.inf | |
| maxcond = symbol < b.sup if b.right_open else symbol <= b.sup | |
| necond = Ne(symbol, a.sup) | |
| return And(necond, mincond, maxcond) | |
| return Or(*[i.as_relational(symbol) for i in self.args]) | |
| def is_iterable(self): | |
| return all(arg.is_iterable for arg in self.args) | |
| def __iter__(self): | |
| return roundrobin(*(iter(arg) for arg in self.args)) | |
| class Intersection(Set, LatticeOp): | |
| """ | |
| Represents an intersection of sets as a :class:`Set`. | |
| Examples | |
| ======== | |
| >>> from sympy import Intersection, Interval | |
| >>> Intersection(Interval(1, 3), Interval(2, 4)) | |
| Interval(2, 3) | |
| We often use the .intersect method | |
| >>> Interval(1,3).intersect(Interval(2,4)) | |
| Interval(2, 3) | |
| See Also | |
| ======== | |
| Union | |
| References | |
| ========== | |
| .. [1] https://en.wikipedia.org/wiki/Intersection_%28set_theory%29 | |
| """ | |
| is_Intersection = True | |
| def identity(self): | |
| return S.UniversalSet | |
| def zero(self): | |
| return S.EmptySet | |
| def __new__(cls, *args , evaluate=None): | |
| if evaluate is None: | |
| evaluate = global_parameters.evaluate | |
| # flatten inputs to merge intersections and iterables | |
| args = list(ordered(set(_sympify(args)))) | |
| # Reduce sets using known rules | |
| if evaluate: | |
| args = list(cls._new_args_filter(args)) | |
| return simplify_intersection(args) | |
| args = list(ordered(args, Set._infimum_key)) | |
| obj = Basic.__new__(cls, *args) | |
| obj._argset = frozenset(args) | |
| return obj | |
| def args(self): | |
| return self._args | |
| def is_iterable(self): | |
| return any(arg.is_iterable for arg in self.args) | |
| def is_finite_set(self): | |
| if fuzzy_or(arg.is_finite_set for arg in self.args): | |
| return True | |
| def _kind(self): | |
| kinds = tuple(arg.kind for arg in self.args if arg is not S.UniversalSet) | |
| if not kinds: | |
| return SetKind(UndefinedKind) | |
| elif all(i == kinds[0] for i in kinds): | |
| return kinds[0] | |
| else: | |
| return SetKind() | |
| def _inf(self): | |
| raise NotImplementedError() | |
| def _sup(self): | |
| raise NotImplementedError() | |
| def _contains(self, other): | |
| return And(*[set.contains(other) for set in self.args]) | |
| def __iter__(self): | |
| sets_sift = sift(self.args, lambda x: x.is_iterable) | |
| completed = False | |
| candidates = sets_sift[True] + sets_sift[None] | |
| finite_candidates, others = [], [] | |
| for candidate in candidates: | |
| length = None | |
| try: | |
| length = len(candidate) | |
| except TypeError: | |
| others.append(candidate) | |
| if length is not None: | |
| finite_candidates.append(candidate) | |
| finite_candidates.sort(key=len) | |
| for s in finite_candidates + others: | |
| other_sets = set(self.args) - {s} | |
| other = Intersection(*other_sets, evaluate=False) | |
| completed = True | |
| for x in s: | |
| try: | |
| if x in other: | |
| yield x | |
| except TypeError: | |
| completed = False | |
| if completed: | |
| return | |
| if not completed: | |
| if not candidates: | |
| raise TypeError("None of the constituent sets are iterable") | |
| raise TypeError( | |
| "The computation had not completed because of the " | |
| "undecidable set membership is found in every candidates.") | |
| def _handle_finite_sets(args): | |
| '''Simplify intersection of one or more FiniteSets and other sets''' | |
| # First separate the FiniteSets from the others | |
| fs_args, others = sift(args, lambda x: x.is_FiniteSet, binary=True) | |
| # Let the caller handle intersection of non-FiniteSets | |
| if not fs_args: | |
| return | |
| # Convert to Python sets and build the set of all elements | |
| fs_sets = [set(fs) for fs in fs_args] | |
| all_elements = reduce(lambda a, b: a | b, fs_sets, set()) | |
| # Extract elements that are definitely in or definitely not in the | |
| # intersection. Here we check contains for all of args. | |
| definite = set() | |
| for e in all_elements: | |
| inall = fuzzy_and(s.contains(e) for s in args) | |
| if inall is True: | |
| definite.add(e) | |
| if inall is not None: | |
| for s in fs_sets: | |
| s.discard(e) | |
| # At this point all elements in all of fs_sets are possibly in the | |
| # intersection. In some cases this is because they are definitely in | |
| # the intersection of the finite sets but it's not clear if they are | |
| # members of others. We might have {m, n}, {m}, and Reals where we | |
| # don't know if m or n is real. We want to remove n here but it is | |
| # possibly in because it might be equal to m. So what we do now is | |
| # extract the elements that are definitely in the remaining finite | |
| # sets iteratively until we end up with {n}, {}. At that point if we | |
| # get any empty set all remaining elements are discarded. | |
| fs_elements = reduce(lambda a, b: a | b, fs_sets, set()) | |
| # Need fuzzy containment testing | |
| fs_symsets = [FiniteSet(*s) for s in fs_sets] | |
| while fs_elements: | |
| for e in fs_elements: | |
| infs = fuzzy_and(s.contains(e) for s in fs_symsets) | |
| if infs is True: | |
| definite.add(e) | |
| if infs is not None: | |
| for n, s in enumerate(fs_sets): | |
| # Update Python set and FiniteSet | |
| if e in s: | |
| s.remove(e) | |
| fs_symsets[n] = FiniteSet(*s) | |
| fs_elements.remove(e) | |
| break | |
| # If we completed the for loop without removing anything we are | |
| # done so quit the outer while loop | |
| else: | |
| break | |
| # If any of the sets of remainder elements is empty then we discard | |
| # all of them for the intersection. | |
| if not all(fs_sets): | |
| fs_sets = [set()] | |
| # Here we fold back the definitely included elements into each fs. | |
| # Since they are definitely included they must have been members of | |
| # each FiniteSet to begin with. We could instead fold these in with a | |
| # Union at the end to get e.g. {3}|({x}&{y}) rather than {3,x}&{3,y}. | |
| if definite: | |
| fs_sets = [fs | definite for fs in fs_sets] | |
| if fs_sets == [set()]: | |
| return S.EmptySet | |
| sets = [FiniteSet(*s) for s in fs_sets] | |
| # Any set in others is redundant if it contains all the elements that | |
| # are in the finite sets so we don't need it in the Intersection | |
| all_elements = reduce(lambda a, b: a | b, fs_sets, set()) | |
| is_redundant = lambda o: all(fuzzy_bool(o.contains(e)) for e in all_elements) | |
| others = [o for o in others if not is_redundant(o)] | |
| if others: | |
| rest = Intersection(*others) | |
| # XXX: Maybe this shortcut should be at the beginning. For large | |
| # FiniteSets it could much more efficient to process the other | |
| # sets first... | |
| if rest is S.EmptySet: | |
| return S.EmptySet | |
| # Flatten the Intersection | |
| if rest.is_Intersection: | |
| sets.extend(rest.args) | |
| else: | |
| sets.append(rest) | |
| if len(sets) == 1: | |
| return sets[0] | |
| else: | |
| return Intersection(*sets, evaluate=False) | |
| def as_relational(self, symbol): | |
| """Rewrite an Intersection in terms of equalities and logic operators""" | |
| return And(*[set.as_relational(symbol) for set in self.args]) | |
| class Complement(Set): | |
| r"""Represents the set difference or relative complement of a set with | |
| another set. | |
| $$A - B = \{x \in A \mid x \notin B\}$$ | |
| Examples | |
| ======== | |
| >>> from sympy import Complement, FiniteSet | |
| >>> Complement(FiniteSet(0, 1, 2), FiniteSet(1)) | |
| {0, 2} | |
| See Also | |
| ========= | |
| Intersection, Union | |
| References | |
| ========== | |
| .. [1] https://mathworld.wolfram.com/ComplementSet.html | |
| """ | |
| is_Complement = True | |
| def __new__(cls, a, b, evaluate=True): | |
| a, b = map(_sympify, (a, b)) | |
| if evaluate: | |
| return Complement.reduce(a, b) | |
| return Basic.__new__(cls, a, b) | |
| def reduce(A, B): | |
| """ | |
| Simplify a :class:`Complement`. | |
| """ | |
| if B == S.UniversalSet or A.is_subset(B): | |
| return S.EmptySet | |
| if isinstance(B, Union): | |
| return Intersection(*(s.complement(A) for s in B.args)) | |
| result = B._complement(A) | |
| if result is not None: | |
| return result | |
| else: | |
| return Complement(A, B, evaluate=False) | |
| def _contains(self, other): | |
| A = self.args[0] | |
| B = self.args[1] | |
| return And(A.contains(other), Not(B.contains(other))) | |
| def as_relational(self, symbol): | |
| """Rewrite a complement in terms of equalities and logic | |
| operators""" | |
| A, B = self.args | |
| A_rel = A.as_relational(symbol) | |
| B_rel = Not(B.as_relational(symbol)) | |
| return And(A_rel, B_rel) | |
| def _kind(self): | |
| return self.args[0].kind | |
| def is_iterable(self): | |
| if self.args[0].is_iterable: | |
| return True | |
| def is_finite_set(self): | |
| A, B = self.args | |
| a_finite = A.is_finite_set | |
| if a_finite is True: | |
| return True | |
| elif a_finite is False and B.is_finite_set: | |
| return False | |
| def __iter__(self): | |
| A, B = self.args | |
| for a in A: | |
| if a not in B: | |
| yield a | |
| else: | |
| continue | |
| class EmptySet(Set, metaclass=Singleton): | |
| """ | |
| Represents the empty set. The empty set is available as a singleton | |
| as ``S.EmptySet``. | |
| Examples | |
| ======== | |
| >>> from sympy import S, Interval | |
| >>> S.EmptySet | |
| EmptySet | |
| >>> Interval(1, 2).intersect(S.EmptySet) | |
| EmptySet | |
| See Also | |
| ======== | |
| UniversalSet | |
| References | |
| ========== | |
| .. [1] https://en.wikipedia.org/wiki/Empty_set | |
| """ | |
| is_empty = True | |
| is_finite_set = True | |
| is_FiniteSet = True | |
| # type: ignore | |
| def is_EmptySet(self): | |
| return True | |
| def _measure(self): | |
| return 0 | |
| def _contains(self, other): | |
| return false | |
| def as_relational(self, symbol): | |
| return false | |
| def __len__(self): | |
| return 0 | |
| def __iter__(self): | |
| return iter([]) | |
| def _eval_powerset(self): | |
| return FiniteSet(self) | |
| def _boundary(self): | |
| return self | |
| def _complement(self, other): | |
| return other | |
| def _kind(self): | |
| return SetKind() | |
| def _symmetric_difference(self, other): | |
| return other | |
| class UniversalSet(Set, metaclass=Singleton): | |
| """ | |
| Represents the set of all things. | |
| The universal set is available as a singleton as ``S.UniversalSet``. | |
| Examples | |
| ======== | |
| >>> from sympy import S, Interval | |
| >>> S.UniversalSet | |
| UniversalSet | |
| >>> Interval(1, 2).intersect(S.UniversalSet) | |
| Interval(1, 2) | |
| See Also | |
| ======== | |
| EmptySet | |
| References | |
| ========== | |
| .. [1] https://en.wikipedia.org/wiki/Universal_set | |
| """ | |
| is_UniversalSet = True | |
| is_empty = False | |
| is_finite_set = False | |
| def _complement(self, other): | |
| return S.EmptySet | |
| def _symmetric_difference(self, other): | |
| return other | |
| def _measure(self): | |
| return S.Infinity | |
| def _kind(self): | |
| return SetKind(UndefinedKind) | |
| def _contains(self, other): | |
| return true | |
| def as_relational(self, symbol): | |
| return true | |
| def _boundary(self): | |
| return S.EmptySet | |
| class FiniteSet(Set): | |
| """ | |
| Represents a finite set of Sympy expressions. | |
| Examples | |
| ======== | |
| >>> from sympy import FiniteSet, Symbol, Interval, Naturals0 | |
| >>> FiniteSet(1, 2, 3, 4) | |
| {1, 2, 3, 4} | |
| >>> 3 in FiniteSet(1, 2, 3, 4) | |
| True | |
| >>> FiniteSet(1, (1, 2), Symbol('x')) | |
| {1, x, (1, 2)} | |
| >>> FiniteSet(Interval(1, 2), Naturals0, {1, 2}) | |
| FiniteSet({1, 2}, Interval(1, 2), Naturals0) | |
| >>> members = [1, 2, 3, 4] | |
| >>> f = FiniteSet(*members) | |
| >>> f | |
| {1, 2, 3, 4} | |
| >>> f - FiniteSet(2) | |
| {1, 3, 4} | |
| >>> f + FiniteSet(2, 5) | |
| {1, 2, 3, 4, 5} | |
| References | |
| ========== | |
| .. [1] https://en.wikipedia.org/wiki/Finite_set | |
| """ | |
| is_FiniteSet = True | |
| is_iterable = True | |
| is_empty = False | |
| is_finite_set = True | |
| def __new__(cls, *args, **kwargs): | |
| evaluate = kwargs.get('evaluate', global_parameters.evaluate) | |
| if evaluate: | |
| args = list(map(sympify, args)) | |
| if len(args) == 0: | |
| return S.EmptySet | |
| else: | |
| args = list(map(sympify, args)) | |
| # keep the form of the first canonical arg | |
| dargs = {} | |
| for i in reversed(list(ordered(args))): | |
| if i.is_Symbol: | |
| dargs[i] = i | |
| else: | |
| try: | |
| dargs[i.as_dummy()] = i | |
| except TypeError: | |
| # e.g. i = class without args like `Interval` | |
| dargs[i] = i | |
| _args_set = set(dargs.values()) | |
| args = list(ordered(_args_set, Set._infimum_key)) | |
| obj = Basic.__new__(cls, *args) | |
| obj._args_set = _args_set | |
| return obj | |
| def __iter__(self): | |
| return iter(self.args) | |
| def _complement(self, other): | |
| if isinstance(other, Interval): | |
| # Splitting in sub-intervals is only done for S.Reals; | |
| # other cases that need splitting will first pass through | |
| # Set._complement(). | |
| nums, syms = [], [] | |
| for m in self.args: | |
| if m.is_number and m.is_real: | |
| nums.append(m) | |
| elif m.is_real == False: | |
| pass # drop non-reals | |
| else: | |
| syms.append(m) # various symbolic expressions | |
| if other == S.Reals and nums != []: | |
| nums.sort() | |
| intervals = [] # Build up a list of intervals between the elements | |
| intervals += [Interval(S.NegativeInfinity, nums[0], True, True)] | |
| for a, b in zip(nums[:-1], nums[1:]): | |
| intervals.append(Interval(a, b, True, True)) # both open | |
| intervals.append(Interval(nums[-1], S.Infinity, True, True)) | |
| if syms != []: | |
| return Complement(Union(*intervals, evaluate=False), | |
| FiniteSet(*syms), evaluate=False) | |
| else: | |
| return Union(*intervals, evaluate=False) | |
| elif nums == []: # no splitting necessary or possible: | |
| if syms: | |
| return Complement(other, FiniteSet(*syms), evaluate=False) | |
| else: | |
| return other | |
| elif isinstance(other, FiniteSet): | |
| unk = [] | |
| for i in self: | |
| c = sympify(other.contains(i)) | |
| if c is not S.true and c is not S.false: | |
| unk.append(i) | |
| unk = FiniteSet(*unk) | |
| if unk == self: | |
| return | |
| not_true = [] | |
| for i in other: | |
| c = sympify(self.contains(i)) | |
| if c is not S.true: | |
| not_true.append(i) | |
| return Complement(FiniteSet(*not_true), unk) | |
| return Set._complement(self, other) | |
| def _contains(self, other): | |
| """ | |
| Tests whether an element, other, is in the set. | |
| Explanation | |
| =========== | |
| The actual test is for mathematical equality (as opposed to | |
| syntactical equality). In the worst case all elements of the | |
| set must be checked. | |
| Examples | |
| ======== | |
| >>> from sympy import FiniteSet | |
| >>> 1 in FiniteSet(1, 2) | |
| True | |
| >>> 5 in FiniteSet(1, 2) | |
| False | |
| """ | |
| if other in self._args_set: | |
| return S.true | |
| else: | |
| # evaluate=True is needed to override evaluate=False context; | |
| # we need Eq to do the evaluation | |
| return Or(*[Eq(e, other, evaluate=True) for e in self.args]) | |
| def _eval_is_subset(self, other): | |
| return fuzzy_and(other._contains(e) for e in self.args) | |
| def _boundary(self): | |
| return self | |
| def _inf(self): | |
| return Min(*self) | |
| def _sup(self): | |
| return Max(*self) | |
| def measure(self): | |
| return 0 | |
| def _kind(self): | |
| if not self.args: | |
| return SetKind() | |
| elif all(i.kind == self.args[0].kind for i in self.args): | |
| return SetKind(self.args[0].kind) | |
| else: | |
| return SetKind(UndefinedKind) | |
| def __len__(self): | |
| return len(self.args) | |
| def as_relational(self, symbol): | |
| """Rewrite a FiniteSet in terms of equalities and logic operators. """ | |
| return Or(*[Eq(symbol, elem) for elem in self]) | |
| def compare(self, other): | |
| return (hash(self) - hash(other)) | |
| def _eval_evalf(self, prec): | |
| dps = prec_to_dps(prec) | |
| return FiniteSet(*[elem.evalf(n=dps) for elem in self]) | |
| def _eval_simplify(self, **kwargs): | |
| from sympy.simplify import simplify | |
| return FiniteSet(*[simplify(elem, **kwargs) for elem in self]) | |
| def _sorted_args(self): | |
| return self.args | |
| def _eval_powerset(self): | |
| return self.func(*[self.func(*s) for s in subsets(self.args)]) | |
| def _eval_rewrite_as_PowerSet(self, *args, **kwargs): | |
| """Rewriting method for a finite set to a power set.""" | |
| from .powerset import PowerSet | |
| is2pow = lambda n: bool(n and not n & (n - 1)) | |
| if not is2pow(len(self)): | |
| return None | |
| fs_test = lambda arg: isinstance(arg, Set) and arg.is_FiniteSet | |
| if not all(fs_test(arg) for arg in args): | |
| return None | |
| biggest = max(args, key=len) | |
| for arg in subsets(biggest.args): | |
| arg_set = FiniteSet(*arg) | |
| if arg_set not in args: | |
| return None | |
| return PowerSet(biggest) | |
| def __ge__(self, other): | |
| if not isinstance(other, Set): | |
| raise TypeError("Invalid comparison of set with %s" % func_name(other)) | |
| return other.is_subset(self) | |
| def __gt__(self, other): | |
| if not isinstance(other, Set): | |
| raise TypeError("Invalid comparison of set with %s" % func_name(other)) | |
| return self.is_proper_superset(other) | |
| def __le__(self, other): | |
| if not isinstance(other, Set): | |
| raise TypeError("Invalid comparison of set with %s" % func_name(other)) | |
| return self.is_subset(other) | |
| def __lt__(self, other): | |
| if not isinstance(other, Set): | |
| raise TypeError("Invalid comparison of set with %s" % func_name(other)) | |
| return self.is_proper_subset(other) | |
| def __eq__(self, other): | |
| if isinstance(other, (set, frozenset)): | |
| return self._args_set == other | |
| return super().__eq__(other) | |
| __hash__ : Callable[[Basic], Any] = Basic.__hash__ | |
| _sympy_converter[set] = lambda x: FiniteSet(*x) | |
| _sympy_converter[frozenset] = lambda x: FiniteSet(*x) | |
| class SymmetricDifference(Set): | |
| """Represents the set of elements which are in either of the | |
| sets and not in their intersection. | |
| Examples | |
| ======== | |
| >>> from sympy import SymmetricDifference, FiniteSet | |
| >>> SymmetricDifference(FiniteSet(1, 2, 3), FiniteSet(3, 4, 5)) | |
| {1, 2, 4, 5} | |
| See Also | |
| ======== | |
| Complement, Union | |
| References | |
| ========== | |
| .. [1] https://en.wikipedia.org/wiki/Symmetric_difference | |
| """ | |
| is_SymmetricDifference = True | |
| def __new__(cls, a, b, evaluate=True): | |
| if evaluate: | |
| return SymmetricDifference.reduce(a, b) | |
| return Basic.__new__(cls, a, b) | |
| def reduce(A, B): | |
| result = B._symmetric_difference(A) | |
| if result is not None: | |
| return result | |
| else: | |
| return SymmetricDifference(A, B, evaluate=False) | |
| def as_relational(self, symbol): | |
| """Rewrite a symmetric_difference in terms of equalities and | |
| logic operators""" | |
| A, B = self.args | |
| A_rel = A.as_relational(symbol) | |
| B_rel = B.as_relational(symbol) | |
| return Xor(A_rel, B_rel) | |
| def is_iterable(self): | |
| if all(arg.is_iterable for arg in self.args): | |
| return True | |
| def __iter__(self): | |
| args = self.args | |
| union = roundrobin(*(iter(arg) for arg in args)) | |
| for item in union: | |
| count = 0 | |
| for s in args: | |
| if item in s: | |
| count += 1 | |
| if count % 2 == 1: | |
| yield item | |
| class DisjointUnion(Set): | |
| """ Represents the disjoint union (also known as the external disjoint union) | |
| of a finite number of sets. | |
| Examples | |
| ======== | |
| >>> from sympy import DisjointUnion, FiniteSet, Interval, Union, Symbol | |
| >>> A = FiniteSet(1, 2, 3) | |
| >>> B = Interval(0, 5) | |
| >>> DisjointUnion(A, B) | |
| DisjointUnion({1, 2, 3}, Interval(0, 5)) | |
| >>> DisjointUnion(A, B).rewrite(Union) | |
| Union(ProductSet({1, 2, 3}, {0}), ProductSet(Interval(0, 5), {1})) | |
| >>> C = FiniteSet(Symbol('x'), Symbol('y'), Symbol('z')) | |
| >>> DisjointUnion(C, C) | |
| DisjointUnion({x, y, z}, {x, y, z}) | |
| >>> DisjointUnion(C, C).rewrite(Union) | |
| ProductSet({x, y, z}, {0, 1}) | |
| References | |
| ========== | |
| https://en.wikipedia.org/wiki/Disjoint_union | |
| """ | |
| def __new__(cls, *sets): | |
| dj_collection = [] | |
| for set_i in sets: | |
| if isinstance(set_i, Set): | |
| dj_collection.append(set_i) | |
| else: | |
| raise TypeError("Invalid input: '%s', input args \ | |
| to DisjointUnion must be Sets" % set_i) | |
| obj = Basic.__new__(cls, *dj_collection) | |
| return obj | |
| def sets(self): | |
| return self.args | |
| def is_empty(self): | |
| return fuzzy_and(s.is_empty for s in self.sets) | |
| def is_finite_set(self): | |
| all_finite = fuzzy_and(s.is_finite_set for s in self.sets) | |
| return fuzzy_or([self.is_empty, all_finite]) | |
| def is_iterable(self): | |
| if self.is_empty: | |
| return False | |
| iter_flag = True | |
| for set_i in self.sets: | |
| if not set_i.is_empty: | |
| iter_flag = iter_flag and set_i.is_iterable | |
| return iter_flag | |
| def _eval_rewrite_as_Union(self, *sets, **kwargs): | |
| """ | |
| Rewrites the disjoint union as the union of (``set`` x {``i``}) | |
| where ``set`` is the element in ``sets`` at index = ``i`` | |
| """ | |
| dj_union = S.EmptySet | |
| index = 0 | |
| for set_i in sets: | |
| if isinstance(set_i, Set): | |
| cross = ProductSet(set_i, FiniteSet(index)) | |
| dj_union = Union(dj_union, cross) | |
| index = index + 1 | |
| return dj_union | |
| def _contains(self, element): | |
| """ | |
| ``in`` operator for DisjointUnion | |
| Examples | |
| ======== | |
| >>> from sympy import Interval, DisjointUnion | |
| >>> D = DisjointUnion(Interval(0, 1), Interval(0, 2)) | |
| >>> (0.5, 0) in D | |
| True | |
| >>> (0.5, 1) in D | |
| True | |
| >>> (1.5, 0) in D | |
| False | |
| >>> (1.5, 1) in D | |
| True | |
| Passes operation on to constituent sets | |
| """ | |
| if not isinstance(element, Tuple) or len(element) != 2: | |
| return S.false | |
| if not element[1].is_Integer: | |
| return S.false | |
| if element[1] >= len(self.sets) or element[1] < 0: | |
| return S.false | |
| return self.sets[element[1]]._contains(element[0]) | |
| def _kind(self): | |
| if not self.args: | |
| return SetKind() | |
| elif all(i.kind == self.args[0].kind for i in self.args): | |
| return self.args[0].kind | |
| else: | |
| return SetKind(UndefinedKind) | |
| def __iter__(self): | |
| if self.is_iterable: | |
| iters = [] | |
| for i, s in enumerate(self.sets): | |
| iters.append(iproduct(s, {Integer(i)})) | |
| return iter(roundrobin(*iters)) | |
| else: | |
| raise ValueError("'%s' is not iterable." % self) | |
| def __len__(self): | |
| """ | |
| Returns the length of the disjoint union, i.e., the number of elements in the set. | |
| Examples | |
| ======== | |
| >>> from sympy import FiniteSet, DisjointUnion, EmptySet | |
| >>> D1 = DisjointUnion(FiniteSet(1, 2, 3, 4), EmptySet, FiniteSet(3, 4, 5)) | |
| >>> len(D1) | |
| 7 | |
| >>> D2 = DisjointUnion(FiniteSet(3, 5, 7), EmptySet, FiniteSet(3, 5, 7)) | |
| >>> len(D2) | |
| 6 | |
| >>> D3 = DisjointUnion(EmptySet, EmptySet) | |
| >>> len(D3) | |
| 0 | |
| Adds up the lengths of the constituent sets. | |
| """ | |
| if self.is_finite_set: | |
| size = 0 | |
| for set in self.sets: | |
| size += len(set) | |
| return size | |
| else: | |
| raise ValueError("'%s' is not a finite set." % self) | |
| def imageset(*args): | |
| r""" | |
| Return an image of the set under transformation ``f``. | |
| Explanation | |
| =========== | |
| If this function cannot compute the image, it returns an | |
| unevaluated ImageSet object. | |
| .. math:: | |
| \{ f(x) \mid x \in \mathrm{self} \} | |
| Examples | |
| ======== | |
| >>> from sympy import S, Interval, imageset, sin, Lambda | |
| >>> from sympy.abc import x | |
| >>> imageset(x, 2*x, Interval(0, 2)) | |
| Interval(0, 4) | |
| >>> imageset(lambda x: 2*x, Interval(0, 2)) | |
| Interval(0, 4) | |
| >>> imageset(Lambda(x, sin(x)), Interval(-2, 1)) | |
| ImageSet(Lambda(x, sin(x)), Interval(-2, 1)) | |
| >>> imageset(sin, Interval(-2, 1)) | |
| ImageSet(Lambda(x, sin(x)), Interval(-2, 1)) | |
| >>> imageset(lambda y: x + y, Interval(-2, 1)) | |
| ImageSet(Lambda(y, x + y), Interval(-2, 1)) | |
| Expressions applied to the set of Integers are simplified | |
| to show as few negatives as possible and linear expressions | |
| are converted to a canonical form. If this is not desirable | |
| then the unevaluated ImageSet should be used. | |
| >>> imageset(x, -2*x + 5, S.Integers) | |
| ImageSet(Lambda(x, 2*x + 1), Integers) | |
| See Also | |
| ======== | |
| sympy.sets.fancysets.ImageSet | |
| """ | |
| from .fancysets import ImageSet | |
| from .setexpr import set_function | |
| if len(args) < 2: | |
| raise ValueError('imageset expects at least 2 args, got: %s' % len(args)) | |
| if isinstance(args[0], (Symbol, tuple)) and len(args) > 2: | |
| f = Lambda(args[0], args[1]) | |
| set_list = args[2:] | |
| else: | |
| f = args[0] | |
| set_list = args[1:] | |
| if isinstance(f, Lambda): | |
| pass | |
| elif callable(f): | |
| nargs = getattr(f, 'nargs', {}) | |
| if nargs: | |
| if len(nargs) != 1: | |
| raise NotImplementedError(filldedent(''' | |
| This function can take more than 1 arg | |
| but the potentially complicated set input | |
| has not been analyzed at this point to | |
| know its dimensions. TODO | |
| ''')) | |
| N = nargs.args[0] | |
| if N == 1: | |
| s = 'x' | |
| else: | |
| s = [Symbol('x%i' % i) for i in range(1, N + 1)] | |
| else: | |
| s = inspect.signature(f).parameters | |
| dexpr = _sympify(f(*[Dummy() for i in s])) | |
| var = tuple(uniquely_named_symbol( | |
| Symbol(i), dexpr) for i in s) | |
| f = Lambda(var, f(*var)) | |
| else: | |
| raise TypeError(filldedent(''' | |
| expecting lambda, Lambda, or FunctionClass, | |
| not \'%s\'.''' % func_name(f))) | |
| if any(not isinstance(s, Set) for s in set_list): | |
| name = [func_name(s) for s in set_list] | |
| raise ValueError( | |
| 'arguments after mapping should be sets, not %s' % name) | |
| if len(set_list) == 1: | |
| set = set_list[0] | |
| try: | |
| # TypeError if arg count != set dimensions | |
| r = set_function(f, set) | |
| if r is None: | |
| raise TypeError | |
| if not r: | |
| return r | |
| except TypeError: | |
| r = ImageSet(f, set) | |
| if isinstance(r, ImageSet): | |
| f, set = r.args | |
| if f.variables[0] == f.expr: | |
| return set | |
| if isinstance(set, ImageSet): | |
| # XXX: Maybe this should just be: | |
| # f2 = set.lambda | |
| # fun = Lambda(f2.signature, f(*f2.expr)) | |
| # return imageset(fun, *set.base_sets) | |
| if len(set.lamda.variables) == 1 and len(f.variables) == 1: | |
| x = set.lamda.variables[0] | |
| y = f.variables[0] | |
| return imageset( | |
| Lambda(x, f.expr.subs(y, set.lamda.expr)), *set.base_sets) | |
| if r is not None: | |
| return r | |
| return ImageSet(f, *set_list) | |
| def is_function_invertible_in_set(func, setv): | |
| """ | |
| Checks whether function ``func`` is invertible when the domain is | |
| restricted to set ``setv``. | |
| """ | |
| # Functions known to always be invertible: | |
| if func in (exp, log): | |
| return True | |
| u = Dummy("u") | |
| fdiff = func(u).diff(u) | |
| # monotonous functions: | |
| # TODO: check subsets (`func` in `setv`) | |
| if (fdiff > 0) == True or (fdiff < 0) == True: | |
| return True | |
| # TODO: support more | |
| return None | |
| def simplify_union(args): | |
| """ | |
| Simplify a :class:`Union` using known rules. | |
| Explanation | |
| =========== | |
| We first start with global rules like 'Merge all FiniteSets' | |
| Then we iterate through all pairs and ask the constituent sets if they | |
| can simplify themselves with any other constituent. This process depends | |
| on ``union_sets(a, b)`` functions. | |
| """ | |
| from sympy.sets.handlers.union import union_sets | |
| # ===== Global Rules ===== | |
| if not args: | |
| return S.EmptySet | |
| for arg in args: | |
| if not isinstance(arg, Set): | |
| raise TypeError("Input args to Union must be Sets") | |
| # Merge all finite sets | |
| finite_sets = [x for x in args if x.is_FiniteSet] | |
| if len(finite_sets) > 1: | |
| a = (x for set in finite_sets for x in set) | |
| finite_set = FiniteSet(*a) | |
| args = [finite_set] + [x for x in args if not x.is_FiniteSet] | |
| # ===== Pair-wise Rules ===== | |
| # Here we depend on rules built into the constituent sets | |
| args = set(args) | |
| new_args = True | |
| while new_args: | |
| for s in args: | |
| new_args = False | |
| for t in args - {s}: | |
| new_set = union_sets(s, t) | |
| # This returns None if s does not know how to intersect | |
| # with t. Returns the newly intersected set otherwise | |
| if new_set is not None: | |
| if not isinstance(new_set, set): | |
| new_set = {new_set} | |
| new_args = (args - {s, t}).union(new_set) | |
| break | |
| if new_args: | |
| args = new_args | |
| break | |
| if len(args) == 1: | |
| return args.pop() | |
| else: | |
| return Union(*args, evaluate=False) | |
| def simplify_intersection(args): | |
| """ | |
| Simplify an intersection using known rules. | |
| Explanation | |
| =========== | |
| We first start with global rules like | |
| 'if any empty sets return empty set' and 'distribute any unions' | |
| Then we iterate through all pairs and ask the constituent sets if they | |
| can simplify themselves with any other constituent | |
| """ | |
| # ===== Global Rules ===== | |
| if not args: | |
| return S.UniversalSet | |
| for arg in args: | |
| if not isinstance(arg, Set): | |
| raise TypeError("Input args to Union must be Sets") | |
| # If any EmptySets return EmptySet | |
| if S.EmptySet in args: | |
| return S.EmptySet | |
| # Handle Finite sets | |
| rv = Intersection._handle_finite_sets(args) | |
| if rv is not None: | |
| return rv | |
| # If any of the sets are unions, return a Union of Intersections | |
| for s in args: | |
| if s.is_Union: | |
| other_sets = set(args) - {s} | |
| if len(other_sets) > 0: | |
| other = Intersection(*other_sets) | |
| return Union(*(Intersection(arg, other) for arg in s.args)) | |
| else: | |
| return Union(*s.args) | |
| for s in args: | |
| if s.is_Complement: | |
| args.remove(s) | |
| other_sets = args + [s.args[0]] | |
| return Complement(Intersection(*other_sets), s.args[1]) | |
| from sympy.sets.handlers.intersection import intersection_sets | |
| # At this stage we are guaranteed not to have any | |
| # EmptySets, FiniteSets, or Unions in the intersection | |
| # ===== Pair-wise Rules ===== | |
| # Here we depend on rules built into the constituent sets | |
| args = set(args) | |
| new_args = True | |
| while new_args: | |
| for s in args: | |
| new_args = False | |
| for t in args - {s}: | |
| new_set = intersection_sets(s, t) | |
| # This returns None if s does not know how to intersect | |
| # with t. Returns the newly intersected set otherwise | |
| if new_set is not None: | |
| new_args = (args - {s, t}).union({new_set}) | |
| break | |
| if new_args: | |
| args = new_args | |
| break | |
| if len(args) == 1: | |
| return args.pop() | |
| else: | |
| return Intersection(*args, evaluate=False) | |
| def _handle_finite_sets(op, x, y, commutative): | |
| # Handle finite sets: | |
| fs_args, other = sift([x, y], lambda x: isinstance(x, FiniteSet), binary=True) | |
| if len(fs_args) == 2: | |
| return FiniteSet(*[op(i, j) for i in fs_args[0] for j in fs_args[1]]) | |
| elif len(fs_args) == 1: | |
| sets = [_apply_operation(op, other[0], i, commutative) for i in fs_args[0]] | |
| return Union(*sets) | |
| else: | |
| return None | |
| def _apply_operation(op, x, y, commutative): | |
| from .fancysets import ImageSet | |
| d = Dummy('d') | |
| out = _handle_finite_sets(op, x, y, commutative) | |
| if out is None: | |
| out = op(x, y) | |
| if out is None and commutative: | |
| out = op(y, x) | |
| if out is None: | |
| _x, _y = symbols("x y") | |
| if isinstance(x, Set) and not isinstance(y, Set): | |
| out = ImageSet(Lambda(d, op(d, y)), x).doit() | |
| elif not isinstance(x, Set) and isinstance(y, Set): | |
| out = ImageSet(Lambda(d, op(x, d)), y).doit() | |
| else: | |
| out = ImageSet(Lambda((_x, _y), op(_x, _y)), x, y) | |
| return out | |
| def set_add(x, y): | |
| from sympy.sets.handlers.add import _set_add | |
| return _apply_operation(_set_add, x, y, commutative=True) | |
| def set_sub(x, y): | |
| from sympy.sets.handlers.add import _set_sub | |
| return _apply_operation(_set_sub, x, y, commutative=False) | |
| def set_mul(x, y): | |
| from sympy.sets.handlers.mul import _set_mul | |
| return _apply_operation(_set_mul, x, y, commutative=True) | |
| def set_div(x, y): | |
| from sympy.sets.handlers.mul import _set_div | |
| return _apply_operation(_set_div, x, y, commutative=False) | |
| def set_pow(x, y): | |
| from sympy.sets.handlers.power import _set_pow | |
| return _apply_operation(_set_pow, x, y, commutative=False) | |
| def set_function(f, x): | |
| from sympy.sets.handlers.functions import _set_function | |
| return _set_function(f, x) | |
| class SetKind(Kind): | |
| """ | |
| SetKind is kind for all Sets | |
| Every instance of Set will have kind ``SetKind`` parametrised by the kind | |
| of the elements of the ``Set``. The kind of the elements might be | |
| ``NumberKind``, or ``TupleKind`` or something else. When not all elements | |
| have the same kind then the kind of the elements will be given as | |
| ``UndefinedKind``. | |
| Parameters | |
| ========== | |
| element_kind: Kind (optional) | |
| The kind of the elements of the set. In a well defined set all elements | |
| will have the same kind. Otherwise the kind should | |
| :class:`sympy.core.kind.UndefinedKind`. The ``element_kind`` argument is optional but | |
| should only be omitted in the case of ``EmptySet`` whose kind is simply | |
| ``SetKind()`` | |
| Examples | |
| ======== | |
| >>> from sympy import Interval | |
| >>> Interval(1, 2).kind | |
| SetKind(NumberKind) | |
| >>> Interval(1,2).kind.element_kind | |
| NumberKind | |
| See Also | |
| ======== | |
| sympy.core.kind.NumberKind | |
| sympy.matrices.kind.MatrixKind | |
| sympy.core.containers.TupleKind | |
| """ | |
| def __new__(cls, element_kind=None): | |
| obj = super().__new__(cls, element_kind) | |
| obj.element_kind = element_kind | |
| return obj | |
| def __repr__(self): | |
| if not self.element_kind: | |
| return "SetKind()" | |
| else: | |
| return "SetKind(%s)" % self.element_kind | |
Xet Storage Details
- Size:
- 81.2 kB
- Xet hash:
- d564297e1abcd2d24f2edce2cc8de8977a99dabb0599e7cb15dc967e586c8b6a
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.