Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/sets/finite_enumerated_set.py
8817 views
1
"""
2
Finite Enumerated Sets
3
"""
4
#*****************************************************************************
5
# Copyright (C) 2009 Florent Hivert <[email protected]>
6
#
7
# Distributed under the terms of the GNU General Public License (GPL)
8
#
9
# This code is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
# General Public License for more details.
13
#
14
# The full text of the GPL is available at:
15
#
16
# http://www.gnu.org/licenses/
17
#******************************************************************************
18
19
from sage.structure.parent import Parent
20
from sage.structure.unique_representation import UniqueRepresentation
21
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
22
from sage.categories.sets_cat import EmptySetError
23
from sage.rings.integer import Integer
24
25
#################################################################
26
class FiniteEnumeratedSet(UniqueRepresentation, Parent):
27
"""
28
A class for finite enumerated set.
29
30
Returns the finite enumerated set with elements in ``elements``
31
where ``element`` is any (finite) iterable object.
32
33
The main purpose is to provide a variant of ``list`` or ``tuple``,
34
which is a parent with an interface consistent with
35
``EnumeratedSets`` and has unique representation.
36
The list of the elements is expanded in memory.
37
38
39
EXAMPLES::
40
41
sage: S = FiniteEnumeratedSet([1, 2, 3])
42
sage: S
43
{1, 2, 3}
44
sage: S.list()
45
[1, 2, 3]
46
sage: S.cardinality()
47
3
48
sage: S.random_element()
49
1
50
sage: S.first()
51
1
52
sage: S.category()
53
Category of facade finite enumerated sets
54
sage: TestSuite(S).run()
55
56
Note that being and enumerated set, the result depends on the order::
57
58
sage: S1 = FiniteEnumeratedSet((1, 2, 3))
59
sage: S1
60
{1, 2, 3}
61
sage: S1.list()
62
[1, 2, 3]
63
sage: S1 == S
64
True
65
sage: S2 = FiniteEnumeratedSet((2, 1, 3))
66
sage: S2 == S
67
False
68
69
As an abuse, repeated entries in ``elements`` are allowed to model
70
multisets::
71
72
sage: S1 = FiniteEnumeratedSet((1, 2, 1, 2, 2, 3))
73
sage: S1
74
{1, 2, 1, 2, 2, 3}
75
76
Finaly the elements are not aware of their parent::
77
78
sage: S.first().parent()
79
Integer Ring
80
"""
81
82
@staticmethod
83
def __classcall__(cls, iterable):
84
"""
85
Standard trick to expand the iterable upon input, and
86
guarantees unique representation, independently of the type of
87
the iterable. See ``UniqueRepresentation``.
88
89
TESTS::
90
91
sage: S1 = FiniteEnumeratedSet([1, 2, 3])
92
sage: S2 = FiniteEnumeratedSet((1, 2, 3))
93
sage: S3 = FiniteEnumeratedSet((x for x in range(1,4)))
94
sage: S1 is S2
95
True
96
sage: S2 is S3
97
True
98
"""
99
return super(FiniteEnumeratedSet, cls).__classcall__(
100
cls,
101
tuple(iterable))
102
103
def __init__(self, elements):
104
"""
105
TESTS::
106
107
sage: TestSuite(FiniteEnumeratedSet([1,2,3])).run()
108
sage: TestSuite(FiniteEnumeratedSet([])).run()
109
"""
110
self._elements = elements
111
Parent.__init__(self, facade = True, category = FiniteEnumeratedSets())
112
113
def __nonzero__(self):
114
r"""
115
Conversion to boolean.
116
117
EXAMPLES::
118
119
sage: bool(FiniteEnumeratedSet('abc'))
120
True
121
sage: bool(FiniteEnumeratedSet([]))
122
False
123
"""
124
return bool(self._elements)
125
126
def _repr_(self):
127
"""
128
TESTS::
129
130
sage: S = FiniteEnumeratedSet([1,2,3])
131
sage: repr(S)
132
'{1, 2, 3}'
133
sage: S = FiniteEnumeratedSet(['1','2','3'])
134
sage: repr(S)
135
"{'1', '2', '3'}"
136
sage: S = FiniteEnumeratedSet([1])
137
sage: repr(S)
138
'{1}'
139
"""
140
return '{' + ', '.join(repr(e) for e in self._elements) + '}'
141
142
def __contains__(self, x):
143
"""
144
TESTS::
145
146
sage: S = FiniteEnumeratedSet([1,2,3])
147
sage: 1 in S
148
True
149
sage: 2 in S
150
True
151
sage: 4 in S
152
False
153
sage: ZZ in S
154
False
155
156
sage: S.is_parent_of(2)
157
True
158
sage: S.is_parent_of(4)
159
False
160
"""
161
return x in self._elements
162
163
is_parent_of = __contains__
164
165
def __iter__(self):
166
r"""
167
Iterator over the element of self.
168
169
EXAMPLES::
170
171
sage: for i in FiniteEnumeratedSet([1,2,3]): print i
172
1
173
2
174
3
175
"""
176
return iter(self._elements)
177
178
def list(self):
179
"""
180
TESTS::
181
182
sage: S = FiniteEnumeratedSet([1,2,3])
183
sage: S.list()
184
[1, 2, 3]
185
"""
186
return list(self._elements)
187
188
def an_element(self):
189
"""
190
TESTS::
191
192
sage: S = FiniteEnumeratedSet([1,2,3])
193
sage: S.an_element()
194
1
195
"""
196
if not self._elements:
197
raise EmptySetError
198
return self._elements[0]
199
200
def first(self):
201
r"""
202
Return the first element of the enumeration or raise an EmptySetError if
203
the set is empty.
204
205
EXAMPLES::
206
207
sage: S = FiniteEnumeratedSet('abc')
208
sage: S.first()
209
'a'
210
"""
211
if not self._elements:
212
raise EmptySetError
213
return self._elements[0]
214
215
def last(self):
216
r"""
217
Returns the last element of the iteration or raise an EmptySetError if
218
the set is empty.
219
220
EXAMPLES::
221
222
sage: S = FiniteEnumeratedSet([0,'a',1.23, 'd'])
223
sage: S.last()
224
'd'
225
"""
226
if not self._elements:
227
raise EmptySetError
228
return self._elements[-1]
229
230
def random_element(self):
231
r"""
232
Return a random element.
233
234
EXAMPLES::
235
236
sage: S = FiniteEnumeratedSet('abc')
237
sage: S.random_element() # random
238
'b'
239
"""
240
if not self._elements:
241
raise EmptySetError
242
from sage.misc.prandom import choice
243
return choice(self._elements)
244
245
def cardinality(self):
246
"""
247
TESTS::
248
249
sage: S = FiniteEnumeratedSet([1,2,3])
250
sage: S.cardinality()
251
3
252
"""
253
return Integer(len(self._elements))
254
255
def rank(self, x):
256
"""
257
Returns the index of ``x`` in this finite enumerated set.
258
259
EXAMPLES::
260
261
sage: S = FiniteEnumeratedSet(['a','b','c'])
262
sage: S.index('b')
263
1
264
"""
265
return self._elements.index(x)
266
267
index = rank
268
269
def unrank(self,i):
270
r"""
271
Return the element at position i.
272
273
EXAMPLES::
274
275
sage: S = FiniteEnumeratedSet([1,'a',-51])
276
sage: S[0], S[1], S[2]
277
(1, 'a', -51)
278
sage: S[3]
279
Traceback (most recent call last):
280
...
281
IndexError: list index out of range
282
sage: S[-1], S[-2], S[-3]
283
(-51, 'a', 1)
284
sage: S[-4]
285
Traceback (most recent call last):
286
...
287
IndexError: list index out of range
288
"""
289
return self._elements[i]
290
291
def _element_constructor_(self, el):
292
"""
293
TESTS::
294
295
sage: S = FiniteEnumeratedSet([1,2,3])
296
sage: one,two,three = sorted(S)
297
sage: S(1) is one
298
True
299
sage: x = 3
300
sage: x is three
301
False
302
sage: S(x) is three
303
True
304
sage: S(0)
305
Traceback (most recent call last):
306
...
307
ValueError: 0 not in {1, 2, 3}
308
"""
309
try:
310
return self._elements[self.rank(el)]
311
except (ValueError,KeyError):
312
raise ValueError("%s not in %s"%(el, self))
313
314