Path: blob/master/src/sage/sets/totally_ordered_finite_set.py
8817 views
"""1Totally Ordered Finite Sets23AUTHORS:45- Stepan Starosta (2012): Initial version6"""7#*****************************************************************************8# Copyright (C) 2012 Stepan Starosta <[email protected]>9#10# Distributed under the terms of the GNU General Public License (GPL)11#12# This code is distributed in the hope that it will be useful,13# but WITHOUT ANY WARRANTY; without even the implied warranty of14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU15# General Public License for more details.16#17# The full text of the GPL is available at:18#19# http://www.gnu.org/licenses/20#******************************************************************************2122from sage.structure.element import Element23from sage.structure.parent import Parent24from sage.sets.finite_enumerated_set import FiniteEnumeratedSet25from sage.categories.posets import Posets26from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets2728class TotallyOrderedFiniteSetElement(Element):29"""30Element of a finite totally ordered set.3132EXAMPLES::3334sage: S = TotallyOrderedFiniteSet([2,7], facade=False)35sage: x = S(2)36sage: print x37238sage: x.parent()39{2, 7}40"""41def __init__(self, parent, data):42r"""43TESTS::4445sage: T = TotallyOrderedFiniteSet([3,2,1],facade=False)46sage: TestSuite(T.an_element()).run()47"""48Element.__init__(self, parent)49self.value = data5051def __eq__(self, other):52r"""53Equality.5455EXAMPLES::5657sage: A = TotallyOrderedFiniteSet(['gaga',1], facade=False)58sage: A('gaga') == 'gaga' #indirect doctest59False60sage: 'gaga' == A('gaga')61False62sage: A('gaga') == A('gaga')63True64"""65try:66same_parent = self.parent() is other.parent()67except AttributeError:68return False6970if not same_parent:71return False72return other.value == self.value7374def __ne__(self, other):75r"""76Non-equality.7778EXAMPLES::7980sage: A = TotallyOrderedFiniteSet(['gaga',1], facade=False)81sage: A('gaga') != 'gaga' #indirect doctest82True83"""84return not (self == other)8586def __cmp__(self, other):87r"""88Comparison.8990For ``self`` and ``other`` that have the same parent the method compares91their rank. Otherwise, it compares their types as it is for the generic92comparison in :class:`sage.structure.element.Element`.9394TESTS::9596sage: A = TotallyOrderedFiniteSet([3,2,7], facade=False)97sage: A(3) < A(2) and A(3) <= A(2) and A(2) <= A(2)98True99sage: A(2) > A(3) and A(2) >= A(3) and A(7) >= A(7)100True101sage: A(3) >= A(7) or A(2) > A(2)102False103sage: A(7) < A(2) or A(2) <= A(3) or A(2) < A(2)104False105"""106try:107test = self.parent() == other.parent()108except AttributeError:109test = False110if not test:111return cmp(type(self),type(other))112113if self.value == other.value:114return 0115return cmp(self.rank(),other.rank())116117def _repr_(self):118r"""119String representation.120121TESTS::122123sage: A = TotallyOrderedFiniteSet(['gaga',1], facade=False)124sage: repr(A('gaga')) #indirect doctest125"'gaga'"126127"""128return repr(self.value)129130def __str__(self):131r"""132String that represents self.133134EXAMPLES::135136sage: A = TotallyOrderedFiniteSet(['gaga',1], facade=False)137sage: str(A('gaga')) #indirect doctest138'gaga'139"""140return str(self.value)141142class TotallyOrderedFiniteSet(FiniteEnumeratedSet):143"""144Totally ordered finite set.145146This is a finite enumerated set assuming that the elements are147ordered based upon their rank (i.e. their position in the set).148149INPUT:150151- ``elements`` -- A list of elements in the set152153- ``facade`` -- (default: ``True``) if ``True``, a facade is used; it154should be set to ``False`` if the elements do not inherit from155:class:`~sage.structure.element.Element` or if you want a funny order. See156examples for more details.157158.. SEEALSO::159160:class:`FiniteEnumeratedSet`161162EXAMPLES::163164sage: S = TotallyOrderedFiniteSet([1,2,3])165sage: S166{1, 2, 3}167sage: S.cardinality()1683169170By default, totally ordered finite set behaves as a facade::171172sage: S(1).parent()173Integer Ring174175It makes comparison fails when it is not the standard order::176177sage: T1 = TotallyOrderedFiniteSet([3,2,5,1])178sage: T1(3) < T1(1)179False180sage: T2 = TotallyOrderedFiniteSet([3,var('x')])181sage: T2(3) < T2(var('x'))1823 < x183184To make the above example work, you should set the argument facade to185``False`` in the constructor. In that case, the elements of the set have a186dedicated class::187188sage: A = TotallyOrderedFiniteSet([3,2,0,'a',7,(0,0),1], facade=False)189sage: A190{3, 2, 0, 'a', 7, (0, 0), 1}191sage: x = A.an_element()192sage: x1933194sage: x.parent()195{3, 2, 0, 'a', 7, (0, 0), 1}196sage: A(3) < A(2)197True198sage: A('a') < A(7)199True200sage: A(3) > A(2)201False202sage: A(1) < A(3)203False204sage: A(3) == A(3)205True206207But then, the equality comparison is always False with elements outside of208the set::209210sage: A(1) == 1211False212sage: 1 == A(1)213False214sage: 'a' == A('a')215False216sage: A('a') == 'a'217False218219and comparisons are comparisons of types::220221sage: for e in [1,'a',(0, 0)]:222... f = A(e)223... print e == f,224... print cmp(e,f) == cmp(type(e),type(f)),225... print cmp(f,e) == cmp(type(f),type(e))226False True True227False True True228False True True229230This behavior of comparison is the same as the one of231:class:`~sage.structure.element.Element`.232233When you build a totally ordered set whose elements do not inherit from234:class:`sage.structure.element.Element`, the following happens::235236sage: S = TotallyOrderedFiniteSet(['a','b'])237sage: S('a')238Traceback (most recent call last):239...240TypeError: Cannot convert str to sage.structure.element.Element241sage: S = TotallyOrderedFiniteSet(['a','b'], facade = False)242sage: S('a')243'a'244245Multiple elements are automatically deleted::246247sage: TotallyOrderedFiniteSet([1,1,2,1,2,2,5,4])248{1, 2, 5, 4}249"""250Element = TotallyOrderedFiniteSetElement251252@staticmethod253def __classcall__(cls, iterable, facade=True):254"""255Standard trick to expand the iterable upon input, and256guarantees unique representation, independently of the type of257the iterable. See ``UniqueRepresentation``.258259TESTS::260261sage: S1 = TotallyOrderedFiniteSet([1, 2, 3])262sage: S2 = TotallyOrderedFiniteSet((1, 2, 3))263sage: S3 = TotallyOrderedFiniteSet((x for x in range(1,4)))264sage: S1 is S2265True266sage: S2 is S3267True268"""269elements = []270seen = set()271for x in iterable:272if x not in seen:273elements.append(x)274seen.add(x)275return super(FiniteEnumeratedSet, cls).__classcall__(276cls,277tuple(elements),278facade)279280def __init__(self, elements, facade=True):281"""282Initialize ``self``.283284TESTS::285286sage: TestSuite(TotallyOrderedFiniteSet([1,2,3])).run()287sage: TestSuite(TotallyOrderedFiniteSet([1,2,3],facade=False)).run()288sage: TestSuite(TotallyOrderedFiniteSet([1,3,2],facade=False)).run()289sage: TestSuite(TotallyOrderedFiniteSet([])).run()290"""291Parent.__init__(self, facade = facade, category = (Posets(),FiniteEnumeratedSets()))292self._elements = elements293if facade:294self._facade_elements = None295else:296self._facade_elements = self._elements297self._elements = [self.element_class(self,x) for x in elements]298299def _element_constructor_(self, data):300r"""301Build an element of that set from ``data``.302303EXAMPLES::304305sage: S1 = TotallyOrderedFiniteSet([1,2,3])306sage: x = S1(1); x # indirect doctest3071308sage: x.parent()309Integer Ring310311312sage: S2 = TotallyOrderedFiniteSet([3,2,1], facade=False)313sage: y = S2(1); y # indirect doctest3141315sage: y.parent()316{3, 2, 1}317sage: y in S2318True319sage: S2(y) is y320True321"""322if self._facade_elements is None:323return FiniteEnumeratedSet._element_constructor_(self, data)324325try:326i = self._facade_elements.index(data)327except ValueError:328raise ValueError("%s not in %s"%(data, self))329330return self._elements[i]331332def le(self, x, y):333r"""334Return ``True`` if `x \le y` for the order of ``self``.335336EXAMPLES::337338sage: T = TotallyOrderedFiniteSet([1,3,2], facade=False)339sage: T1, T3, T2 = T.list()340sage: T.le(T1,T3)341True342sage: T.le(T3,T2)343True344"""345try:346return self._elements.index(x) <= self._elements.index(y)347except Exception:348raise ValueError("arguments must be elements of the set")349350351352