diff --git a/src/sage/categories/cartesian_product.py b/src/sage/categories/cartesian_product.py index 33f5c5b9b02..e6fbf670750 100644 --- a/src/sage/categories/cartesian_product.py +++ b/src/sage/categories/cartesian_product.py @@ -153,7 +153,7 @@ def __call__(self, args, **kwds): sage: cartesian_product([set([0,1,2]), [0,1]]) The Cartesian product of ({0, 1, 2}, {0, 1}) sage: _.category() - Category of Cartesian products of sets + Category of Cartesian products of finite enumerated sets Check that the empty product is handled correctly: diff --git a/src/sage/categories/enumerated_sets.py b/src/sage/categories/enumerated_sets.py index 563a8025e6d..e1dcbd86839 100644 --- a/src/sage/categories/enumerated_sets.py +++ b/src/sage/categories/enumerated_sets.py @@ -137,7 +137,7 @@ def _call_(self, X): sage: S = EnumeratedSets()(Set([1, 2, 3])); S {1, 2, 3} sage: S.category() - Category of facade finite enumerated sets + Category of finite enumerated sets Also Python3 range are now accepted:: diff --git a/src/sage/categories/homset.py b/src/sage/categories/homset.py index bfd78e8d8a5..219286af8b9 100644 --- a/src/sage/categories/homset.py +++ b/src/sage/categories/homset.py @@ -828,7 +828,7 @@ def _element_constructor_(self, x, check=None, **options): sage: H = Hom(Set([1,2,3]), Set([1,2,3])) sage: f = H( lambda x: 4-x ) sage: f.parent() - Set of Morphisms from {1, 2, 3} to {1, 2, 3} in Category of finite sets + Set of Morphisms from {1, 2, 3} to {1, 2, 3} in Category of finite enumerated sets sage: f(1), f(2), f(3) # todo: not implemented sage: H = Hom(ZZ, QQ, Sets()) diff --git a/src/sage/categories/sets_cat.py b/src/sage/categories/sets_cat.py index 6dd406343e7..0d8a77c6f5f 100644 --- a/src/sage/categories/sets_cat.py +++ b/src/sage/categories/sets_cat.py @@ -247,7 +247,7 @@ def _call_(self, X, enumerated_set=False): {1, 2, 3} sage: S = Sets()([1, 2, 3]); S.category() - Category of finite sets + Category of finite enumerated sets sage: S = Sets()([1, 2, 3], enumerated_set=True); S.category() Category of facade finite enumerated sets @@ -1361,7 +1361,7 @@ def some_elements(self): sage: S.some_elements() [47] sage: S = Set([]) - sage: S.some_elements() + sage: list(S.some_elements()) [] This method should return an iterable, *not* an iterator. diff --git a/src/sage/combinat/sidon_sets.py b/src/sage/combinat/sidon_sets.py index 3f5cfcb3173..ec5038eb2c4 100644 --- a/src/sage/combinat/sidon_sets.py +++ b/src/sage/combinat/sidon_sets.py @@ -46,12 +46,12 @@ def sidon_sets(N, g = 1): sage: S.cardinality() 8 sage: S.category() - Category of finite sets + Category of finite enumerated sets sage: sid = S.an_element() sage: sid {2} sage: sid.category() - Category of finite sets + Category of finite enumerated sets TESTS:: diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index 96e3b2ad7a4..b76e6b064ef 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -48,6 +48,7 @@ from sage.categories.sets_cat import Sets from sage.categories.enumerated_sets import EnumeratedSets +from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets import sage.rings.infinity @@ -85,7 +86,7 @@ def has_finite_length(obj): return True -def Set(X=None): +def Set(X=None, category=None): r""" Create the underlying set of ``X``. @@ -187,12 +188,12 @@ def Set(X=None): if X is None: X = [] elif isinstance(X, CategoryObject): - if isinstance(X, Set_generic): + if isinstance(X, Set_generic) and category is None: return X elif X in Sets().Finite(): - return Set_object_enumerated(X) + return Set_object_enumerated(X, category=category) else: - return Set_object(X) + return Set_object(X, category=category) if isinstance(X, Element) and not isinstance(X, Set_base): raise TypeError("Element has no defined underlying set") @@ -200,9 +201,9 @@ def Set(X=None): try: X = frozenset(X) except TypeError: - return Set_object(X) + return Set_object(X, category=category) else: - return Set_object_enumerated(X) + return Set_object_enumerated(X, category=category) class Set_base(): @@ -474,7 +475,7 @@ def __init__(self, X, category=None): sage: type(Set(QQ)) sage: Set(QQ).category() - Category of sets + Category of infinite sets TESTS:: @@ -492,6 +493,15 @@ def __init__(self, X, category=None): if category is None: category = Sets() + + if isinstance(X, CategoryObject): + if X in Sets().Finite(): + category = category.Finite() + elif X in Sets().Infinite(): + category = category.Infinite() + if X in Sets().Enumerated(): + category = category.Enumerated() + Parent.__init__(self, category=category) self.__object = X @@ -666,6 +676,9 @@ def cardinality(self): sage: Set(GF(5^2,'a')).cardinality() 25 """ + if self in Sets().Infinite(): + return sage.rings.infinity.infinity + if not self.is_finite(): return sage.rings.infinity.infinity @@ -680,7 +693,7 @@ def cardinality(self): except TypeError: pass - raise NotImplementedError("computation of cardinality of %s not yet implemented" % self.__object) + return super().cardinality() def is_empty(self): """ @@ -733,6 +746,10 @@ def is_finite(self): sage: Set([1,'a',ZZ]).is_finite() True """ + if self in Sets().Finite(): + return True + if self in Sets().Infinite(): + return False obj = self.__object try: is_finite = obj.is_finite @@ -830,7 +847,7 @@ class Set_object_enumerated(Set_object): """ A finite enumerated set. """ - def __init__(self, X): + def __init__(self, X, category=None): r""" Initialize ``self``. @@ -839,12 +856,12 @@ def __init__(self, X): sage: S = Set(GF(19)); S {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18} sage: S.category() - Category of finite sets + Category of finite enumerated sets sage: print(latex(S)) \left\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18\right\} sage: TestSuite(S).run() """ - Set_object.__init__(self, X, category=Sets().Finite()) + Set_object.__init__(self, X, category=FiniteEnumeratedSets().or_subcategory(category)) def random_element(self): r""" @@ -1267,7 +1284,7 @@ def __classcall__(cls, X, Y, *args, **kwds): Y = Set(Y) return type.__call__(cls, X, Y, *args, **kwds) - def __init__(self, X, Y, op, latex_op): + def __init__(self, X, Y, op, latex_op, category=None): r""" Initialization. @@ -1284,7 +1301,7 @@ def __init__(self, X, Y, op, latex_op): self._Y = Y self._op = op self._latex_op = latex_op - Set_object.__init__(self, self) + Set_object.__init__(self, self, category=category) def _repr_(self): r""" @@ -1338,7 +1355,7 @@ class Set_object_union(Set_object_binary): """ A formal union of two sets. """ - def __init__(self, X, Y): + def __init__(self, X, Y, category=None): r""" Initialize ``self``. @@ -1348,13 +1365,23 @@ def __init__(self, X, Y): sage: T = Set(ZZ) sage: X = S.union(T); X Set-theoretic union of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring + sage: X.category() + Category of infinite sets sage: latex(X) \Bold{Q}^{2} \cup \Bold{Z} sage: TestSuite(X).run() """ - Set_object_binary.__init__(self, X, Y, "union", "\\cup") + if category is None: + category = Sets() + if all(S in Sets().Enumerated() for S in (X, Y)): + category = category.Enumerated() + if any(S in Sets().Infinite() for S in (X, Y)): + category = category.Infinite() + elif all(S in Sets().Finite() for S in (X, Y)): + category = category.Finite() + Set_object_binary.__init__(self, X, Y, "union", "\\cup", category=category) def is_finite(self): r""" @@ -1481,7 +1508,7 @@ class Set_object_intersection(Set_object_binary): """ Formal intersection of two sets. """ - def __init__(self, X, Y): + def __init__(self, X, Y, category=None): r""" Initialize ``self``. @@ -1491,15 +1518,32 @@ def __init__(self, X, Y): sage: T = Set(ZZ) sage: X = S.intersection(T); X Set-theoretic intersection of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring + sage: X.category() + Category of enumerated sets sage: latex(X) \Bold{Q}^{2} \cap \Bold{Z} sage: X = Set(IntegerRange(100)).intersection(Primes()) sage: X.is_finite() True + sage: X.cardinality() + 25 + sage: X.category() + Category of finite enumerated sets + sage: TestSuite(X).run() + + sage: X = Set(Primes(), category=Sets()).intersection(Set(IntegerRange(200))) + sage: X.cardinality() + 46 sage: TestSuite(X).run() """ - Set_object_binary.__init__(self, X, Y, "intersection", "\\cap") + if category is None: + category = Sets() + if any(S in Sets().Finite() for S in (X, Y)): + category = category.Finite() + if any(S in Sets().Enumerated() for S in (X, Y)): + category = category.Enumerated() + Set_object_binary.__init__(self, X, Y, "intersection", "\\cap", category=category) def is_finite(self): r""" @@ -1643,7 +1687,7 @@ class Set_object_difference(Set_object_binary): """ Formal difference of two sets. """ - def __init__(self, X, Y): + def __init__(self, X, Y, category=None): r""" Initialize ``self``. @@ -1653,12 +1697,22 @@ def __init__(self, X, Y): sage: T = Set(ZZ) sage: X = S.difference(T); X Set-theoretic difference of Set of elements of Rational Field and Set of elements of Integer Ring + sage: X.category() + Category of sets sage: latex(X) \Bold{Q} - \Bold{Z} sage: TestSuite(X).run() """ - Set_object_binary.__init__(self, X, Y, "difference", "-") + if category is None: + category = Sets() + if X in Sets().Enumerated(): + category = category.Enumerated() + if X in Sets().Finite(): + category = category.Finite() + elif X in Sets().Infinite() and Y in Sets().Finite(): + category = category.Infinite() + Set_object_binary.__init__(self, X, Y, "difference", "-", category=category) def is_finite(self): r""" @@ -1787,6 +1841,8 @@ def _sympy_(self): Set-theoretic difference of Set of elements of Rational Field and Set of elements of Integer Ring + sage: X.category() + Category of sets sage: X._sympy_() Complement(Rationals, Integers) @@ -1794,6 +1850,8 @@ def _sympy_(self): Set-theoretic difference of Set of elements of Integer Ring and Set of elements of Rational Field + sage: X.category() + Category of enumerated sets sage: X._sympy_() EmptySet """ @@ -1807,7 +1865,7 @@ class Set_object_symmetric_difference(Set_object_binary): """ Formal symmetric difference of two sets. """ - def __init__(self, X, Y): + def __init__(self, X, Y, category=None): r""" Initialize ``self``. @@ -1817,12 +1875,20 @@ def __init__(self, X, Y): sage: T = Set(ZZ) sage: X = S.symmetric_difference(T); X Set-theoretic symmetric difference of Set of elements of Rational Field and Set of elements of Integer Ring + sage: X.category() + Category of sets sage: latex(X) \Bold{Q} \bigtriangleup \Bold{Z} sage: TestSuite(X).run() """ - Set_object_binary.__init__(self, X, Y, "symmetric difference", "\\bigtriangleup") + if category is None: + category = Sets() + if all(S in Sets().Finite() for S in (X, Y)): + category = category.Finite() + if all(S in Sets().Enumerated() for S in (X, Y)): + category = category.Enumerated() + Set_object_binary.__init__(self, X, Y, "symmetric difference", "\\bigtriangleup", category=category) def is_finite(self): r""" diff --git a/src/sage/structure/parent.pyx b/src/sage/structure/parent.pyx index 36b1e45d223..585ec9e559e 100644 --- a/src/sage/structure/parent.pyx +++ b/src/sage/structure/parent.pyx @@ -2863,7 +2863,7 @@ cdef class Set_generic(Parent): TESTS:: sage: Set(QQ).category() - Category of sets + Category of infinite sets """ def object(self):