Path: blob/master/src/sage/sets/finite_enumerated_set.py
8817 views
"""1Finite Enumerated Sets2"""3#*****************************************************************************4# Copyright (C) 2009 Florent Hivert <[email protected]>5#6# Distributed under the terms of the GNU General Public License (GPL)7#8# This code is distributed in the hope that it will be useful,9# but WITHOUT ANY WARRANTY; without even the implied warranty of10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU11# General Public License for more details.12#13# The full text of the GPL is available at:14#15# http://www.gnu.org/licenses/16#******************************************************************************1718from sage.structure.parent import Parent19from sage.structure.unique_representation import UniqueRepresentation20from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets21from sage.categories.sets_cat import EmptySetError22from sage.rings.integer import Integer2324#################################################################25class FiniteEnumeratedSet(UniqueRepresentation, Parent):26"""27A class for finite enumerated set.2829Returns the finite enumerated set with elements in ``elements``30where ``element`` is any (finite) iterable object.3132The main purpose is to provide a variant of ``list`` or ``tuple``,33which is a parent with an interface consistent with34``EnumeratedSets`` and has unique representation.35The list of the elements is expanded in memory.363738EXAMPLES::3940sage: S = FiniteEnumeratedSet([1, 2, 3])41sage: S42{1, 2, 3}43sage: S.list()44[1, 2, 3]45sage: S.cardinality()46347sage: S.random_element()48149sage: S.first()50151sage: S.category()52Category of facade finite enumerated sets53sage: TestSuite(S).run()5455Note that being and enumerated set, the result depends on the order::5657sage: S1 = FiniteEnumeratedSet((1, 2, 3))58sage: S159{1, 2, 3}60sage: S1.list()61[1, 2, 3]62sage: S1 == S63True64sage: S2 = FiniteEnumeratedSet((2, 1, 3))65sage: S2 == S66False6768As an abuse, repeated entries in ``elements`` are allowed to model69multisets::7071sage: S1 = FiniteEnumeratedSet((1, 2, 1, 2, 2, 3))72sage: S173{1, 2, 1, 2, 2, 3}7475Finaly the elements are not aware of their parent::7677sage: S.first().parent()78Integer Ring79"""8081@staticmethod82def __classcall__(cls, iterable):83"""84Standard trick to expand the iterable upon input, and85guarantees unique representation, independently of the type of86the iterable. See ``UniqueRepresentation``.8788TESTS::8990sage: S1 = FiniteEnumeratedSet([1, 2, 3])91sage: S2 = FiniteEnumeratedSet((1, 2, 3))92sage: S3 = FiniteEnumeratedSet((x for x in range(1,4)))93sage: S1 is S294True95sage: S2 is S396True97"""98return super(FiniteEnumeratedSet, cls).__classcall__(99cls,100tuple(iterable))101102def __init__(self, elements):103"""104TESTS::105106sage: TestSuite(FiniteEnumeratedSet([1,2,3])).run()107sage: TestSuite(FiniteEnumeratedSet([])).run()108"""109self._elements = elements110Parent.__init__(self, facade = True, category = FiniteEnumeratedSets())111112def __nonzero__(self):113r"""114Conversion to boolean.115116EXAMPLES::117118sage: bool(FiniteEnumeratedSet('abc'))119True120sage: bool(FiniteEnumeratedSet([]))121False122"""123return bool(self._elements)124125def _repr_(self):126"""127TESTS::128129sage: S = FiniteEnumeratedSet([1,2,3])130sage: repr(S)131'{1, 2, 3}'132sage: S = FiniteEnumeratedSet(['1','2','3'])133sage: repr(S)134"{'1', '2', '3'}"135sage: S = FiniteEnumeratedSet([1])136sage: repr(S)137'{1}'138"""139return '{' + ', '.join(repr(e) for e in self._elements) + '}'140141def __contains__(self, x):142"""143TESTS::144145sage: S = FiniteEnumeratedSet([1,2,3])146sage: 1 in S147True148sage: 2 in S149True150sage: 4 in S151False152sage: ZZ in S153False154155sage: S.is_parent_of(2)156True157sage: S.is_parent_of(4)158False159"""160return x in self._elements161162is_parent_of = __contains__163164def __iter__(self):165r"""166Iterator over the element of self.167168EXAMPLES::169170sage: for i in FiniteEnumeratedSet([1,2,3]): print i171117221733174"""175return iter(self._elements)176177def list(self):178"""179TESTS::180181sage: S = FiniteEnumeratedSet([1,2,3])182sage: S.list()183[1, 2, 3]184"""185return list(self._elements)186187def an_element(self):188"""189TESTS::190191sage: S = FiniteEnumeratedSet([1,2,3])192sage: S.an_element()1931194"""195if not self._elements:196raise EmptySetError197return self._elements[0]198199def first(self):200r"""201Return the first element of the enumeration or raise an EmptySetError if202the set is empty.203204EXAMPLES::205206sage: S = FiniteEnumeratedSet('abc')207sage: S.first()208'a'209"""210if not self._elements:211raise EmptySetError212return self._elements[0]213214def last(self):215r"""216Returns the last element of the iteration or raise an EmptySetError if217the set is empty.218219EXAMPLES::220221sage: S = FiniteEnumeratedSet([0,'a',1.23, 'd'])222sage: S.last()223'd'224"""225if not self._elements:226raise EmptySetError227return self._elements[-1]228229def random_element(self):230r"""231Return a random element.232233EXAMPLES::234235sage: S = FiniteEnumeratedSet('abc')236sage: S.random_element() # random237'b'238"""239if not self._elements:240raise EmptySetError241from sage.misc.prandom import choice242return choice(self._elements)243244def cardinality(self):245"""246TESTS::247248sage: S = FiniteEnumeratedSet([1,2,3])249sage: S.cardinality()2503251"""252return Integer(len(self._elements))253254def rank(self, x):255"""256Returns the index of ``x`` in this finite enumerated set.257258EXAMPLES::259260sage: S = FiniteEnumeratedSet(['a','b','c'])261sage: S.index('b')2621263"""264return self._elements.index(x)265266index = rank267268def unrank(self,i):269r"""270Return the element at position i.271272EXAMPLES::273274sage: S = FiniteEnumeratedSet([1,'a',-51])275sage: S[0], S[1], S[2]276(1, 'a', -51)277sage: S[3]278Traceback (most recent call last):279...280IndexError: list index out of range281sage: S[-1], S[-2], S[-3]282(-51, 'a', 1)283sage: S[-4]284Traceback (most recent call last):285...286IndexError: list index out of range287"""288return self._elements[i]289290def _element_constructor_(self, el):291"""292TESTS::293294sage: S = FiniteEnumeratedSet([1,2,3])295sage: one,two,three = sorted(S)296sage: S(1) is one297True298sage: x = 3299sage: x is three300False301sage: S(x) is three302True303sage: S(0)304Traceback (most recent call last):305...306ValueError: 0 not in {1, 2, 3}307"""308try:309return self._elements[self.rank(el)]310except (ValueError,KeyError):311raise ValueError("%s not in %s"%(el, self))312313314