Ticket #8910: trac_8910-subsets_an_element-fh.patch

File trac_8910-subsets_an_element-fh.patch, 16.3 KB (added by hivert, 10 years ago)
  • sage/combinat/subset.py

    # HG changeset patch
    # User Florent Hivert <Florent.Hivert@univ-rouen.fr>
    # Date 1275319974 -7200
    # Node ID c4217440241d89fd7e6591deff81a455e7b8e93d
    # Parent  396ecfecef3602f2d2b350bd257fc176a3cc2d71
    #8910: Have CombinatorialClass inherits from Parent (first step to get rid of it)
    
    diff --git a/sage/combinat/subset.py b/sage/combinat/subset.py
    a b Subsets 
    33
    44The combinatorial class of the subsets of a finite set. The set can
    55be given as a list or a Set or else as an integer `n` which encodes the set
    6 `\{1,2,...,n\}`. See the ``Subsets`` for more information and examples.
     6`\{1,2,...,n\}`. See :class:`Subsets` for more information and examples.
    77
    88AUTHORS:
    99
    AUTHORS: 
    1313
    1414"""
    1515#*****************************************************************************
    16 #       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
     16#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,
    1717#
    1818#  Distributed under the terms of the GNU General Public License (GPL)
    1919#
    import __builtin__ 
    3737import itertools
    3838from combinat import CombinatorialClass, CombinatorialObject
    3939from sage.sets.set import Set_object_enumerated
     40from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
    4041
    4142
    4243def Subsets(s, k=None, submultiset=False):
    def Subsets(s, k=None, submultiset=False 
    4647    to a set. It can alternatively be given a non-negative integer `n`
    4748    which encode the set `\{1,2,\dots,n\}` (i.e. the Sage
    4849    ``range(1,s+1)``).
    49    
     50
    5051    A second optional parameter k can be given. In this case, Subsets returns
    5152    the combinatorial class of subsets of s of size k.
    52        
     53
    5354    Finally the option ``submultiset`` allows one to deal with sets with
    54     repeated elements usually called multisets. 
     55    repeated elements usually called multisets.
    5556
    5657    EXAMPLES::
    57    
     58
    5859        sage: S = Subsets([1, 2, 3]); S
    5960        Subsets of {1, 2, 3}
    6061        sage: S.cardinality()
    def Subsets(s, k=None, submultiset=False 
    6768        {2}
    6869        sage: S.list()
    6970        [{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}]
    70    
     71
    7172    Here is the same example where the set is given as an integer::
    72    
     73
    7374        sage: S = Subsets(3)
    7475        sage: S.list()
    7576        [{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}]
    76    
     77
    7778    We demonstrate various the effect of the various options::
    78    
     79
    7980        sage: S = Subsets(3, 2); S
    8081        Subsets of {1, 2, 3} of size 2
    8182        sage: S.list()
    def Subsets(s, k=None, submultiset=False 
    8788        [[], [1], [2], [1, 2], [2, 2], [1, 2, 2]]
    8889
    8990        sage: S = Subsets([1, 2, 2, 3], 3, submultiset=True); S
    90         SubMultiset of [1, 2, 2, 3] of size 3       
     91        SubMultiset of [1, 2, 2, 3] of size 3
    9192        sage: S.list()
    9293        [[1, 2, 2], [1, 2, 3], [2, 2, 3]]
    9394    """
    9495    if k is not None:
    9596        k=Integer(k)
    96    
     97
    9798    if isinstance(s, (int, Integer)):
    9899        if s < 0:
    99100            raise ValueError, "s must be non-negative"
    def Subsets(s, k=None, submultiset=False 
    101102
    102103#    if len(Set(s)) != len(s):
    103104#        multi = True
    104    
     105
    105106    if k is None:
    106107        if submultiset:
    107108            return SubMultiset_s(s)
    def Subsets(s, k=None, submultiset=False 
    112113            return SubMultiset_sk(s, k)
    113114        else:
    114115            return Subsets_sk(s, k)
    115            
     116
    116117
    117118
    118119
    class Subsets_s(CombinatorialClass): 
    121122    def __init__(self, s):
    122123        """
    123124        TESTS::
    124        
     125
     126            sage: s = Subsets(Set([1]))
     127            sage: e = s.first()
     128            sage: isinstance(e, s.element_class)
     129            True
     130
     131        In the following "_test_elements" is temporarily disabled
     132        until :class:`sage.sets.set.Set_object_enumerated` objects
     133        pass the category tests::
     134
    125135            sage: S = Subsets([1,2,3])
    126             sage: TestSuite(S).run()
    127             sage: s = Subsets(Set([1]))
    128             sage: e = s.first()
    129             sage: isinstance(e, s.element_class)
    130             True
     136            sage: TestSuite(S).run(skip=["_test_elements"])
     137
     138            sage: S = sage.sets.set.Set_object_enumerated([1,2])
     139            sage: TestSuite(S).run()         # todo: not implemented
    131140        """
     141        CombinatorialClass.__init__(self, category=FiniteEnumeratedSets())
    132142        self.s = Set(s)
    133143
    134144    def __repr__(self):
    135145        """
    136146        TESTS::
    137        
     147
    138148            sage: repr(Subsets([1,2,3]))
    139149            'Subsets of {1, 2, 3}'
    140150        """
    class Subsets_s(CombinatorialClass): 
    143153    def __contains__(self, value):
    144154        """
    145155        TESTS::
    146        
     156
    147157            sage: S = Subsets([1,2,3])
    148158            sage: Set([1,2]) in S
    149159            True
    class Subsets_s(CombinatorialClass): 
    156166        for v in value:
    157167            if not v in self.s:
    158168                return False
    159         return True   
    160        
     169        return True
     170
    161171    def cardinality(self):
    162172        r"""
    163173        Returns the number of subsets of the set s.
    164        
     174
    165175        This is given by `2^{|s|}`.
    166        
     176
    167177        EXAMPLES::
    168        
     178
    169179            sage: Subsets(Set([1,2,3])).cardinality()
    170180            8
    171181            sage: Subsets([1,2,3,3]).cardinality()
    class Subsets_s(CombinatorialClass): 
    179189        """
    180190        Returns the first subset of s. Since we aren't restricted to
    181191        subsets of a certain size, this is always the empty set.
    182        
     192
    183193        EXAMPLES::
    184        
     194
    185195            sage: Subsets([1,2,3]).first()
    186196            {}
    187197            sage: Subsets(3).first()
    class Subsets_s(CombinatorialClass): 
    193203        """
    194204        Returns the last subset of s. Since we aren't restricted to subsets
    195205        of a certain size, this is always the set s itself.
    196        
     206
    197207        EXAMPLES::
    198        
     208
    199209            sage: Subsets([1,2,3]).last()
    200210            {1, 2, 3}
    201211            sage: Subsets(3).last()
    class Subsets_s(CombinatorialClass): 
    203213        """
    204214        return self.s
    205215
    206    
     216
    207217    def __iter__(self):
    208218        """
    209219        Iterates through the subsets of s.
    210        
     220
    211221        EXAMPLES::
    212        
     222
    213223            sage: [sub for sub in Subsets(Set([1,2,3]))]
    214224            [{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}]
    215225            sage: [sub for sub in Subsets(3)]
    class Subsets_s(CombinatorialClass): 
    229239        """
    230240        Returns a random element of the class of subsets of s (in other
    231241        words, a random subset of s).
    232        
     242
    233243        EXAMPLES::
    234        
     244
    235245            sage: Subsets(3).random_element()
    236246            {2}
    237247            sage: Subsets([4,5,6]).random_element()
    class Subsets_s(CombinatorialClass): 
    244254    def rank(self, sub):
    245255        """
    246256        Returns the rank of sub as a subset of s.
    247        
     257
    248258        EXAMPLES::
    249        
     259
    250260            sage: Subsets(3).rank([])
    251261            0
    252262            sage: Subsets(3).rank([1,2])
    class Subsets_s(CombinatorialClass): 
    283293            {}
    284294            sage: Subsets([2,4,5]).unrank(1)
    285295            {2}
    286             sage: s = Subsets([2,4,5])
    287296        """
    288297
    289298        lset = __builtin__.list(self.s)
    class Subsets_s(CombinatorialClass): 
    299308                else:
    300309                    return Set([lset[i] for i in choose_nk.from_rank(r, n, k)])
    301310
     311    def _an_element_(self):
     312        """
     313        Returns an example of subset.
     314
     315        EXAMPLES::
     316
     317            sage: Subsets(0)._an_element_()
     318            {}
     319            sage: Subsets(3)._an_element_()
     320            {1, 2}
     321            sage: Subsets([2,4,5])._an_element_()
     322            {2, 4}
     323        """
     324        return self.unrank(self.cardinality() // 2)
     325
    302326    def _element_constructor_(self, x):
    303327        """
    304328        TESTS::
    class Subsets_sk(CombinatorialClass): 
    319343    def __init__(self, s, k):
    320344        """
    321345        TESTS::
    322        
     346
     347            sage: s = Subsets(Set([1]))
     348            sage: e = s.first()
     349            sage: isinstance(e, s.element_class)
     350            True
     351
     352        In the following "_test_elements" is temporarily disabled
     353        until :class:`sage.sets.set.Set_object_enumerated` objects
     354        pass the category tests::
     355
    323356            sage: S = Subsets(3,2)
    324             sage: TestSuite(S).run()
    325             sage: s = Subsets(Set([1]))
    326             sage: e = s.first()
    327             sage: isinstance(e, s.element_class)
    328             True
     357            sage: TestSuite(S).run(skip=["_test_elements"])
    329358        """
     359        CombinatorialClass.__init__(self, category=FiniteEnumeratedSets())
    330360        self.s = Set(s)
    331361        self.k = k
    332362
    333363    def __repr__(self):
    334364        """
    335365        TESTS::
    336        
     366
    337367            sage: repr(Subsets(3,2))
    338368            'Subsets of {1, 2, 3} of size 2'
    339369        """
    class Subsets_sk(CombinatorialClass): 
    356386        for v in value:
    357387            if not v in self.s:
    358388                return False
    359         return True   
     389        return True
    360390
    361391    def cardinality(self):
    362392        """
    363393        EXAMPLES::
    364        
     394
    365395            sage: Subsets(Set([1,2,3]), 2).cardinality()
    366396            3
    367397            sage: Subsets([1,2,3,3], 2).cardinality()
    class Subsets_sk(CombinatorialClass): 
    384414        else:
    385415            return binomial(len(self.s),self.k)
    386416
    387        
     417
    388418    def first(self):
    389419        """
    390420        Returns the first subset of s of size k.
    391        
     421
    392422        EXAMPLES::
    393        
     423
    394424            sage: Subsets(Set([1,2,3]), 2).first()
    395425            {1, 2}
    396426            sage: Subsets([1,2,3,3], 2).first()
    class Subsets_sk(CombinatorialClass): 
    409439    def last(self):
    410440        """
    411441        Returns the last subset of s of size k.
    412        
     442
    413443        EXAMPLES::
    414        
     444
    415445            sage: Subsets(Set([1,2,3]), 2).last()
    416446            {2, 3}
    417447            sage: Subsets([1,2,3,3], 2).last()
    class Subsets_sk(CombinatorialClass): 
    431461    def __iter__(self):
    432462        """
    433463        Iterates through the subsets of s of size k.
    434        
     464
    435465        EXAMPLES::
    436        
     466
    437467            sage: [sub for sub in Subsets(Set([1,2,3]), 2)]
    438468            [{1, 2}, {1, 3}, {2, 3}]
    439469            sage: [sub for sub in Subsets([1,2,3,3], 2)]
    class Subsets_sk(CombinatorialClass): 
    443473        """
    444474        if self.k not in range(len(self.s)+1):
    445475            return
    446        
     476
    447477        lset = __builtin__.list(self.s)
    448478        #We use the iterator for the subwords of range(len(self.s))
    449479        ind_set = lambda index_list: Set([lset[i] for i in index_list])
    450480        for sub in choose_nk.ChooseNK(len(lset),self.k):
    451481            yield ind_set(sub)
    452    
     482
    453483
    454484
    455485    def random_element(self):
    456486        """
    457487        Returns a random element of the class of subsets of s of size k (in
    458488        other words, a random subset of s of size k).
    459        
     489
    460490        EXAMPLES::
    461        
     491
    462492            sage: Subsets(3, 2).random_element()
    463493            {1, 2}
    464494            sage: Subsets(3,4).random_element() is None
    class Subsets_sk(CombinatorialClass): 
    475505    def rank(self, sub):
    476506        """
    477507        Returns the rank of sub as a subset of s of size k.
    478        
     508
    479509        EXAMPLES::
    480        
     510
    481511            sage: Subsets(3,2).rank([1,2])
    482512            0
    483513            sage: Subsets([2,3,4],2).rank([3,4])
    class Subsets_sk(CombinatorialClass): 
    528558        else:
    529559            return Set([lset[i] for i in choose_nk.from_rank(r, n, self.k)])
    530560
     561    def _an_element_(self):
     562        """
     563        Returns an example of subset.
     564
     565        EXAMPLES::
     566
     567            sage: Subsets(0,0)._an_element_()
     568            {}
     569            sage: Subsets(3,2)._an_element_()
     570            {1, 3}
     571            sage: Subsets([2,4,5],2)._an_element_()
     572            {2, 5}
     573        """
     574        return self.unrank(self.cardinality() // 2)
     575
    531576    def _element_constructor_(self, x):
    532577        """
    533578        TESTS::
    class Subsets_sk(CombinatorialClass): 
    547592class SubMultiset_s(CombinatorialClass):
    548593    """
    549594    The combinatorial class of the sub multisets of s.
    550    
     595
    551596    EXAMPLES::
    552        
     597
    553598        sage: S = Subsets([1,2,2,3], submultiset=True)
    554599        sage: S._s
    555600        [1, 2, 2, 3]
    556601
    557602    The positions of the unique elements in s are stored in::
    558            
     603
    559604        sage: S._indices
    560605        [0, 1, 3]
    561606
    562607    and their multiplicities in::
    563        
     608
    564609        sage: S._multiplicities
    565610        [1, 2, 1]
    566611        sage: Subsets([1,2,3,3], submultiset=True).cardinality()
    class SubMultiset_s(CombinatorialClass): 
    572617        Constructs the combinatorial class of the sub multisets of s.
    573618
    574619        EXAMPLES::
    575        
     620
    576621            sage: S = Subsets([1,2,2,3], submultiset=True)
    577622            sage: Subsets([1,2,3,3], submultiset=True).cardinality()
    578623            12
    579624        """
     625        CombinatorialClass.__init__(self, category=FiniteEnumeratedSets())
    580626        s = list(s)
    581627        indices = list(sorted(Set([s.index(a) for a in s])))
    582628        multiplicities = [len([a for a in s if a == s[i]])
    class SubMultiset_s(CombinatorialClass): 
    584630        self._s = sorted(s)
    585631        self._indices = indices
    586632        self._multiplicities = multiplicities
    587        
     633
    588634    def __repr__(self):
    589635        """
    590636        TESTS::
    class SubMultiset_s(CombinatorialClass): 
    593639            SubMultiset of [1, 2, 2, 3]
    594640        """
    595641        return "SubMultiset of %s"%self._s
    596        
     642
    597643    def __contains__(self, s):
    598644        """
    599645        TESTS::
    600        
     646
    601647            sage: S = Subsets([1,2,2,3], submultiset=True)
    602648            sage: [] in S
    603649            True
    class SubMultiset_s(CombinatorialClass): 
    613659            False
    614660        """
    615661        return sorted(s) in subword.Subwords(self._s)
    616        
     662
    617663    def __iter__(self):
    618664        """
    619665        Iterates through the subsets of the multiset ``self._s``.  Note
    class SubMultiset_s(CombinatorialClass): 
    622668        in sage).
    623669
    624670        EXAMPLES::
    625        
     671
    626672            sage: S = Subsets([1,2,2,3], submultiset=True)
    627673            sage: S.list()
    628674            [[],
    class SubMultiset_s(CombinatorialClass): 
    642688        for k in range(len(self._s)+1):
    643689            for s in SubMultiset_sk(self._s, k):
    644690                yield s
    645    
     691
    646692
    647693class SubMultiset_sk(SubMultiset_s):
    648694    """
    class SubMultiset_sk(SubMultiset_s): 
    650696    that each subset is represented by a list of the elements rather than a
    651697    set since we can have multiplicities (no multiset data structure yet in
    652698    sage).
    653            
     699
    654700    EXAMPLES::
    655        
     701
    656702        sage: S = Subsets([1,2,3,3],2, submultiset=True)
    657703        sage: S._k
    658704        2
    class SubMultiset_sk(SubMultiset_s): 
    669715    def __init__(self, s, k):
    670716        """
    671717        TEST::
    672        
     718
    673719            sage: S = Subsets([1,2,3,3],2, submultiset=True)
    674720            sage: [sub for sub in S]
    675721            [[1, 2], [1, 3], [2, 3], [3, 3]]
    class SubMultiset_sk(SubMultiset_s): 
    682728        TESTS::
    683729
    684730            sage: S = Subsets([1, 2, 2, 3], 3, submultiset=True); S
    685             SubMultiset of [1, 2, 2, 3] of size 3       
     731            SubMultiset of [1, 2, 2, 3] of size 3
    686732        """
    687733        return "SubMultiset of %s of size %s"%(self._s, self._k)
    688734
    689735    def __contains__(self, s):
    690736        """
    691737        TESTS::
    692        
     738
    693739            sage: S = Subsets([1,2,2,3], 2, submultiset=True)
    694740            sage: [] in S
    695741            False
    class SubMultiset_sk(SubMultiset_s): 
    707753            False
    708754        """
    709755        return sorted(s) in subword.Subwords(self._s, self._k)
    710        
     756
    711757    def __iter__(self):
    712758        """
    713759        Iterates through the subsets of size ``self._k`` of the multiset
    714760        ``self._s``. Note that each subset is represented by a list of the
    715761        elements rather than a set since we can have multiplicities (no
    716762        multiset data structure yet in sage).
    717        
     763
    718764        EXAMPLES::
    719        
     765
    720766            sage: S = Subsets([1,2,2,3],2, submultiset=True)
    721767            sage: S.list()
    722768            [[1, 2], [1, 3], [2, 2], [2, 3]]
    class SubMultiset_sk(SubMultiset_s): 
    724770        from sage.combinat.integer_vector import IntegerVectors
    725771        for iv in IntegerVectors(self._k, len(self._indices), outer=self._multiplicities):
    726772            yield sum([ [self._s[self._indices[i]]]*iv[i] for i in range(len(iv))], [])
    727            
     773