Skip to content

Commit d83fb88

Browse files
author
Release Manager
committed
Trac #34376: Set_object_enumerated should be in FiniteEnumeratedSets()
{{{ sage: Set([0, 1, 2, 3]) {0, 1, 2, 3} sage: _.category() Category of finite sets sage: Set([0, 1, 2, 3], category=FiniteEnumeratedSets()) TypeError: Set() got an unexpected keyword argument 'category' }}} Likewise for the `Set_object_binary` classes (which implement lazy union, intersection, ...), the category should be computed from the categories of the inputs. Also we add a `category` argument to the `Set` factory and the `__init__` methods of the various implementation classes. Follow ups: - #34398 the relation between `Set_object_enumerated` and `FiniteEnumeratedSet` (and `TrivialFamily`, `EnumeratedFamily`) should be clarified - #34387 `Set()` should construct facade parents URL: https://trac.sagemath.org/34376 Reported by: mkoeppe Ticket author(s): Matthias Koeppe Reviewer(s): Travis Scrimshaw
2 parents f84d7a4 + e58d2ab commit d83fb88

File tree

7 files changed

+95
-29
lines changed

7 files changed

+95
-29
lines changed

src/sage/categories/cartesian_product.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ def __call__(self, args, **kwds):
153153
sage: cartesian_product([set([0,1,2]), [0,1]])
154154
The Cartesian product of ({0, 1, 2}, {0, 1})
155155
sage: _.category()
156-
Category of Cartesian products of sets
156+
Category of Cartesian products of finite enumerated sets
157157
158158
Check that the empty product is handled correctly:
159159

src/sage/categories/enumerated_sets.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ def _call_(self, X):
137137
sage: S = EnumeratedSets()(Set([1, 2, 3])); S
138138
{1, 2, 3}
139139
sage: S.category()
140-
Category of facade finite enumerated sets
140+
Category of finite enumerated sets
141141
142142
Also Python3 range are now accepted::
143143

src/sage/categories/homset.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,7 @@ def _element_constructor_(self, x, check=None, **options):
828828
sage: H = Hom(Set([1,2,3]), Set([1,2,3]))
829829
sage: f = H( lambda x: 4-x )
830830
sage: f.parent()
831-
Set of Morphisms from {1, 2, 3} to {1, 2, 3} in Category of finite sets
831+
Set of Morphisms from {1, 2, 3} to {1, 2, 3} in Category of finite enumerated sets
832832
sage: f(1), f(2), f(3) # todo: not implemented
833833
834834
sage: H = Hom(ZZ, QQ, Sets())

src/sage/categories/sets_cat.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ def _call_(self, X, enumerated_set=False):
247247
{1, 2, 3}
248248
249249
sage: S = Sets()([1, 2, 3]); S.category()
250-
Category of finite sets
250+
Category of finite enumerated sets
251251
sage: S = Sets()([1, 2, 3], enumerated_set=True); S.category()
252252
Category of facade finite enumerated sets
253253
@@ -1361,7 +1361,7 @@ def some_elements(self):
13611361
sage: S.some_elements()
13621362
[47]
13631363
sage: S = Set([])
1364-
sage: S.some_elements()
1364+
sage: list(S.some_elements())
13651365
[]
13661366
13671367
This method should return an iterable, *not* an iterator.

src/sage/combinat/sidon_sets.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@ def sidon_sets(N, g = 1):
4646
sage: S.cardinality()
4747
8
4848
sage: S.category()
49-
Category of finite sets
49+
Category of finite enumerated sets
5050
sage: sid = S.an_element()
5151
sage: sid
5252
{2}
5353
sage: sid.category()
54-
Category of finite sets
54+
Category of finite enumerated sets
5555
5656
TESTS::
5757

src/sage/sets/set.py

+87-21
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848

4949
from sage.categories.sets_cat import Sets
5050
from sage.categories.enumerated_sets import EnumeratedSets
51+
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
5152

5253
import sage.rings.infinity
5354

@@ -85,7 +86,7 @@ def has_finite_length(obj):
8586
return True
8687

8788

88-
def Set(X=None):
89+
def Set(X=None, category=None):
8990
r"""
9091
Create the underlying set of ``X``.
9192
@@ -187,22 +188,22 @@ def Set(X=None):
187188
if X is None:
188189
X = []
189190
elif isinstance(X, CategoryObject):
190-
if isinstance(X, Set_generic):
191+
if isinstance(X, Set_generic) and category is None:
191192
return X
192193
elif X in Sets().Finite():
193-
return Set_object_enumerated(X)
194+
return Set_object_enumerated(X, category=category)
194195
else:
195-
return Set_object(X)
196+
return Set_object(X, category=category)
196197

197198
if isinstance(X, Element) and not isinstance(X, Set_base):
198199
raise TypeError("Element has no defined underlying set")
199200

200201
try:
201202
X = frozenset(X)
202203
except TypeError:
203-
return Set_object(X)
204+
return Set_object(X, category=category)
204205
else:
205-
return Set_object_enumerated(X)
206+
return Set_object_enumerated(X, category=category)
206207

207208

208209
class Set_base():
@@ -474,7 +475,7 @@ def __init__(self, X, category=None):
474475
sage: type(Set(QQ))
475476
<class 'sage.sets.set.Set_object_with_category'>
476477
sage: Set(QQ).category()
477-
Category of sets
478+
Category of infinite sets
478479
479480
TESTS::
480481
@@ -492,6 +493,15 @@ def __init__(self, X, category=None):
492493

493494
if category is None:
494495
category = Sets()
496+
497+
if isinstance(X, CategoryObject):
498+
if X in Sets().Finite():
499+
category = category.Finite()
500+
elif X in Sets().Infinite():
501+
category = category.Infinite()
502+
if X in Sets().Enumerated():
503+
category = category.Enumerated()
504+
495505
Parent.__init__(self, category=category)
496506
self.__object = X
497507

@@ -666,6 +676,9 @@ def cardinality(self):
666676
sage: Set(GF(5^2,'a')).cardinality()
667677
25
668678
"""
679+
if self in Sets().Infinite():
680+
return sage.rings.infinity.infinity
681+
669682
if not self.is_finite():
670683
return sage.rings.infinity.infinity
671684

@@ -680,7 +693,7 @@ def cardinality(self):
680693
except TypeError:
681694
pass
682695

683-
raise NotImplementedError("computation of cardinality of %s not yet implemented" % self.__object)
696+
return super().cardinality()
684697

685698
def is_empty(self):
686699
"""
@@ -733,6 +746,10 @@ def is_finite(self):
733746
sage: Set([1,'a',ZZ]).is_finite()
734747
True
735748
"""
749+
if self in Sets().Finite():
750+
return True
751+
if self in Sets().Infinite():
752+
return False
736753
obj = self.__object
737754
try:
738755
is_finite = obj.is_finite
@@ -830,7 +847,7 @@ class Set_object_enumerated(Set_object):
830847
"""
831848
A finite enumerated set.
832849
"""
833-
def __init__(self, X):
850+
def __init__(self, X, category=None):
834851
r"""
835852
Initialize ``self``.
836853
@@ -839,12 +856,12 @@ def __init__(self, X):
839856
sage: S = Set(GF(19)); S
840857
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}
841858
sage: S.category()
842-
Category of finite sets
859+
Category of finite enumerated sets
843860
sage: print(latex(S))
844861
\left\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18\right\}
845862
sage: TestSuite(S).run()
846863
"""
847-
Set_object.__init__(self, X, category=Sets().Finite())
864+
Set_object.__init__(self, X, category=FiniteEnumeratedSets().or_subcategory(category))
848865

849866
def random_element(self):
850867
r"""
@@ -1267,7 +1284,7 @@ def __classcall__(cls, X, Y, *args, **kwds):
12671284
Y = Set(Y)
12681285
return type.__call__(cls, X, Y, *args, **kwds)
12691286

1270-
def __init__(self, X, Y, op, latex_op):
1287+
def __init__(self, X, Y, op, latex_op, category=None):
12711288
r"""
12721289
Initialization.
12731290
@@ -1284,7 +1301,7 @@ def __init__(self, X, Y, op, latex_op):
12841301
self._Y = Y
12851302
self._op = op
12861303
self._latex_op = latex_op
1287-
Set_object.__init__(self, self)
1304+
Set_object.__init__(self, self, category=category)
12881305

12891306
def _repr_(self):
12901307
r"""
@@ -1338,7 +1355,7 @@ class Set_object_union(Set_object_binary):
13381355
"""
13391356
A formal union of two sets.
13401357
"""
1341-
def __init__(self, X, Y):
1358+
def __init__(self, X, Y, category=None):
13421359
r"""
13431360
Initialize ``self``.
13441361
@@ -1348,13 +1365,23 @@ def __init__(self, X, Y):
13481365
sage: T = Set(ZZ)
13491366
sage: X = S.union(T); X
13501367
Set-theoretic union of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring
1368+
sage: X.category()
1369+
Category of infinite sets
13511370
13521371
sage: latex(X)
13531372
\Bold{Q}^{2} \cup \Bold{Z}
13541373
13551374
sage: TestSuite(X).run()
13561375
"""
1357-
Set_object_binary.__init__(self, X, Y, "union", "\\cup")
1376+
if category is None:
1377+
category = Sets()
1378+
if all(S in Sets().Enumerated() for S in (X, Y)):
1379+
category = category.Enumerated()
1380+
if any(S in Sets().Infinite() for S in (X, Y)):
1381+
category = category.Infinite()
1382+
elif all(S in Sets().Finite() for S in (X, Y)):
1383+
category = category.Finite()
1384+
Set_object_binary.__init__(self, X, Y, "union", "\\cup", category=category)
13581385

13591386
def is_finite(self):
13601387
r"""
@@ -1481,7 +1508,7 @@ class Set_object_intersection(Set_object_binary):
14811508
"""
14821509
Formal intersection of two sets.
14831510
"""
1484-
def __init__(self, X, Y):
1511+
def __init__(self, X, Y, category=None):
14851512
r"""
14861513
Initialize ``self``.
14871514
@@ -1491,15 +1518,32 @@ def __init__(self, X, Y):
14911518
sage: T = Set(ZZ)
14921519
sage: X = S.intersection(T); X
14931520
Set-theoretic intersection of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring
1521+
sage: X.category()
1522+
Category of enumerated sets
14941523
sage: latex(X)
14951524
\Bold{Q}^{2} \cap \Bold{Z}
14961525
14971526
sage: X = Set(IntegerRange(100)).intersection(Primes())
14981527
sage: X.is_finite()
14991528
True
1529+
sage: X.cardinality()
1530+
25
1531+
sage: X.category()
1532+
Category of finite enumerated sets
1533+
sage: TestSuite(X).run()
1534+
1535+
sage: X = Set(Primes(), category=Sets()).intersection(Set(IntegerRange(200)))
1536+
sage: X.cardinality()
1537+
46
15001538
sage: TestSuite(X).run()
15011539
"""
1502-
Set_object_binary.__init__(self, X, Y, "intersection", "\\cap")
1540+
if category is None:
1541+
category = Sets()
1542+
if any(S in Sets().Finite() for S in (X, Y)):
1543+
category = category.Finite()
1544+
if any(S in Sets().Enumerated() for S in (X, Y)):
1545+
category = category.Enumerated()
1546+
Set_object_binary.__init__(self, X, Y, "intersection", "\\cap", category=category)
15031547

15041548
def is_finite(self):
15051549
r"""
@@ -1643,7 +1687,7 @@ class Set_object_difference(Set_object_binary):
16431687
"""
16441688
Formal difference of two sets.
16451689
"""
1646-
def __init__(self, X, Y):
1690+
def __init__(self, X, Y, category=None):
16471691
r"""
16481692
Initialize ``self``.
16491693
@@ -1653,12 +1697,22 @@ def __init__(self, X, Y):
16531697
sage: T = Set(ZZ)
16541698
sage: X = S.difference(T); X
16551699
Set-theoretic difference of Set of elements of Rational Field and Set of elements of Integer Ring
1700+
sage: X.category()
1701+
Category of sets
16561702
sage: latex(X)
16571703
\Bold{Q} - \Bold{Z}
16581704
16591705
sage: TestSuite(X).run()
16601706
"""
1661-
Set_object_binary.__init__(self, X, Y, "difference", "-")
1707+
if category is None:
1708+
category = Sets()
1709+
if X in Sets().Enumerated():
1710+
category = category.Enumerated()
1711+
if X in Sets().Finite():
1712+
category = category.Finite()
1713+
elif X in Sets().Infinite() and Y in Sets().Finite():
1714+
category = category.Infinite()
1715+
Set_object_binary.__init__(self, X, Y, "difference", "-", category=category)
16621716

16631717
def is_finite(self):
16641718
r"""
@@ -1787,13 +1841,17 @@ def _sympy_(self):
17871841
Set-theoretic difference of
17881842
Set of elements of Rational Field and
17891843
Set of elements of Integer Ring
1844+
sage: X.category()
1845+
Category of sets
17901846
sage: X._sympy_()
17911847
Complement(Rationals, Integers)
17921848
17931849
sage: X = Set(ZZ).difference(Set(QQ)); X
17941850
Set-theoretic difference of
17951851
Set of elements of Integer Ring and
17961852
Set of elements of Rational Field
1853+
sage: X.category()
1854+
Category of enumerated sets
17971855
sage: X._sympy_()
17981856
EmptySet
17991857
"""
@@ -1807,7 +1865,7 @@ class Set_object_symmetric_difference(Set_object_binary):
18071865
"""
18081866
Formal symmetric difference of two sets.
18091867
"""
1810-
def __init__(self, X, Y):
1868+
def __init__(self, X, Y, category=None):
18111869
r"""
18121870
Initialize ``self``.
18131871
@@ -1817,12 +1875,20 @@ def __init__(self, X, Y):
18171875
sage: T = Set(ZZ)
18181876
sage: X = S.symmetric_difference(T); X
18191877
Set-theoretic symmetric difference of Set of elements of Rational Field and Set of elements of Integer Ring
1878+
sage: X.category()
1879+
Category of sets
18201880
sage: latex(X)
18211881
\Bold{Q} \bigtriangleup \Bold{Z}
18221882
18231883
sage: TestSuite(X).run()
18241884
"""
1825-
Set_object_binary.__init__(self, X, Y, "symmetric difference", "\\bigtriangleup")
1885+
if category is None:
1886+
category = Sets()
1887+
if all(S in Sets().Finite() for S in (X, Y)):
1888+
category = category.Finite()
1889+
if all(S in Sets().Enumerated() for S in (X, Y)):
1890+
category = category.Enumerated()
1891+
Set_object_binary.__init__(self, X, Y, "symmetric difference", "\\bigtriangleup", category=category)
18261892

18271893
def is_finite(self):
18281894
r"""

src/sage/structure/parent.pyx

+1-1
Original file line numberDiff line numberDiff line change
@@ -2863,7 +2863,7 @@ cdef class Set_generic(Parent):
28632863
TESTS::
28642864
28652865
sage: Set(QQ).category()
2866-
Category of sets
2866+
Category of infinite sets
28672867
28682868
"""
28692869
def object(self):

0 commit comments

Comments
 (0)