Ticket #5600: trac_5600-compositions_cleanup-nt.patch

File trac_5600-compositions_cleanup-nt.patch, 41.5 KB (added by nthiery, 13 years ago)

Apply only this one, yes, this one!

  • sage/combinat/composition.py

    # HG changeset patch
    # User Nicolas M. Thiery <nthiery@users.sf.net>
    # Date 1248870604 -7200
    # Node ID 6c08fdb91d39a1124b92b24067f90b10d8bea563
    # Parent  ed6bb458aa9bfcc4a199d4f2a036be6c6dab0103
    #5600: Cleanup of integer compositions
    
     - Documentation improvements
     - Fixes some of http://wiki.sagemath.org/combinat/Weirdness
     - Composition(l) accepts any iterable l, and in particular a tuple
     - New functionalities:
        - concatenation (as __add__ and sum)
        - size
        - fatter, finer, fatten (refinement of compositions)
     - Uses IntegerListsLex (fast iteration, ...) instead of specific yet equivalent code
       Note: this changes the iteration order to inverse lexicographic,
       and iteration changes the iteration order for set partitions, skew
       partitions, skew tableaux, and ribbon tableaux.
     - Handles unpickling of former internal class Compositions_constraints
    
    diff --git a/sage/combinat/composition.py b/sage/combinat/composition.py
    a b  
    1 r"""
    2 Compositions
     1"""
     2Integer compositions
    33
    4 A composition c of a nonnegative integer n is a list of positive
    5 integers with total sum n.
     4A composition `c` of a nonnegative integer `n` is a list of positive integers
     5(the *parts* of the compositions) with total sum `n`.
    66
    7 EXAMPLES: There are 8 compositions of 4.
     7This module provide tools for manipulating compositions and enumerated
     8sets of compositions.
    89
    9 ::
     10EXAMPLES::
    1011
    11     sage: Compositions(4).cardinality()
    12     8
    13 
    14 Here is the list of them::
    15 
    16     sage: Compositions(4).list()
     12    sage: Composition([5, 3, 1, 3])
     13    [5, 3, 1, 3]
     14    sage: list(Compositions(4))
    1715    [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]]
    1816
    19 You can use the .first() method to get the 'first' composition of a
    20 number.
    21 
    22 ::
    23 
    24     sage: Compositions(4).first()
    25     [1, 1, 1, 1]
    26 
    27 You can also calculate the 'next' composition given the current
    28 one.
    29 
    30 ::
    31 
    32     sage: Compositions(4).next([1,1,2])
    33     [1, 2, 1]
    34 
    35 The following examples shows how to test whether or not an object
    36 is a composition.
    37 
    38 ::
    39 
    40     sage: [3,4] in Compositions()
    41     True
    42     sage: [3,4] in Compositions(7)
    43     True
    44     sage: [3,4] in Compositions(5)
    45     False
    46 
    47 Similarly, one can check whether or not an object is a composition
    48 which satisfies further constraints.
    49 
    50 ::
    51 
    52     sage: [4,2] in Compositions(6, inner=[2,2], min_part=2)
    53     True
    54     sage: [4,2] in Compositions(6, inner=[2,2], min_part=2)
    55     True
    56     sage: [4,2] in Compositions(6, inner=[2,2], min_part=3)
    57     False
    58 
    59 Note that the given constraints should compatible.
    60 
    61 ::
    62 
    63     sage: [4,1] in Compositions(5, inner=[2,1], min_part=1)
    64     True
    65 
    66 The options length, min_length, and max_length can be used to set
    67 length constraints on the compositions. For example, the
    68 compositions of 4 of length equal to, at least, and at most 2 are
    69 given by::
    70 
    71     sage: Compositions(4, length=2).list()
    72     [[1, 3], [2, 2], [3, 1]]
    73     sage: Compositions(4, min_length=2).list()
    74     [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1]]
    75     sage: Compositions(4, max_length=2).list()
    76     [[1, 3], [2, 2], [3, 1], [4]]
    77 
    78 Setting both min_length and max_length to the same value is
    79 equivalent to setting length to this value.
    80 
    81 ::
    82 
    83     sage: Compositions(4, min_length=2, max_length=2).list()
    84     [[1, 3], [2, 2], [3, 1]]
    85 
    86 The options inner and outer can be used to set part-by-part
    87 containment constraints. The list of compositions of 4 bounded above
    88 by [3,1,2] is given by::
    89 
    90     sage: Compositions(4, outer=[3,1,2]).list()
    91     [[1, 1, 2], [2, 1, 1], [3, 1]]
    92 
    93 Outer sets max_length to the length of its argument. Moreover, the
    94 parts of outer may be infinite to clear the constraint on specific
    95 parts. This is the list of compositions of 4 of length at most 3
    96 such that the first and third parts are at most 1::
    97 
    98     sage: Compositions(4, outer=[1,oo,1]).list()
    99     [[1, 2, 1], [1, 3]]
    100 
    101 This is the list of compositions of 4 bounded below by [1,1,1].
    102 
    103 ::
    104 
    105     sage: Compositions(4, inner=[1,1,1]).list()
    106     [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [2, 1, 1]]
    107 
    108 The options min_slope and max_slope can be used to set
    109 constraints on the slope, that is the difference p[i+1]-p[i] of two
    110 consecutive parts. The following is the list of weakly increasing
    111 compositions of 4.
    112 
    113 ::
    114 
    115     sage: Compositions(4, min_slope=0).list()
    116     [[1, 1, 1, 1], [1, 1, 2], [1, 3], [2, 2], [4]]
    117 
    118 The following is the list of compositions of 4 such that two
    119 consecutive parts differ by at most one unit::
    120 
    121     sage: Compositions(4, min_slope=-1, max_slope=1).list()
    122     [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [2, 1, 1], [2, 2], [4]]
    123 
    124 The constraints can be combinat together in all reasonable ways.
    125 This is the list of compositions of 5 of length between 2 and 4
    126 such that the difference between consecutive parts is between -2 and
    127 1.
    128 
    129 ::
    130 
    131     sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4).list()
    132     [[1, 1, 1, 2],
    133      [1, 1, 2, 1],
    134      [1, 2, 1, 1],
    135      [1, 2, 2],
    136      [2, 1, 1, 1],
    137      [2, 1, 2],
    138      [2, 2, 1],
    139      [2, 3],
    140      [3, 1, 1],
    141      [3, 2]]
    142 
    143 We can do the same thing with an outer constraint::
    144 
    145     sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4, outer=[2,5,2]).list()
    146     [[1, 2, 2], [2, 1, 2], [2, 2, 1], [2, 3]]
    147 
    148 However, providing incoherent constraints may yield strange
    149 results. It is up to the user to ensure that the inner and outer
    150 compositions themselves satisfy the parts and slope constraints.
    15117
    15218AUTHORS:
    15319
    154 - Mike Hansen
     20 - Mike Hansen, Nicolas M. Thiery
     21 - MuPAD-Combinat developers (algorithms and design inspiration)
    15522
    156 - MuPAD-Combinat developers (for algorithms and design inspiration)
    15723"""
    15824#*****************************************************************************
    159 #       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,
     25#       Copyright (C) 2007 Mike Hansen       <mhansen@gmail.com>
     26#                     2009 Nicolas M. Thiery <nthiery at users.sf.net>
    16027#
    16128#  Distributed under the terms of the GNU General Public License (GPL)
    162 #
    163 #    This code is distributed in the hope that it will be useful,
    164 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
    165 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    166 #    General Public License for more details.
    167 #
    168 #  The full text of the GPL is available at:
    169 #
    170 #                  http://www.gnu.org/licenses/
     29#              http://www.gnu.org/licenses/
    17130#*****************************************************************************
    17231
    17332import sage.combinat.skew_partition
    17433from combinat import CombinatorialClass, CombinatorialObject, InfiniteAbstractCombinatorialClass
     34from cartesian_product import CartesianProduct
     35from integer_list import IntegerListsLex
    17536import __builtin__
    17637from sage.rings.integer import Integer
    17738from sage.rings.arith import binomial
    import misc 
    17940
    18041def Composition(co=None, descents=None, code=None):
    18142    """
    182     Returns a composition object.
    183    
    184     EXAMPLES: The standard way to create a composition is by specifying
    185     it as a list.
    186    
    187     ::
    188    
     43    Integer compositions
     44
     45    A composition of a nonnegative integer `n` is a list
     46    `(i_1,\dots,i_k)` of positive integers with total sum `n`.
     47
     48    TODO: mathematical definition of descents, code, ...
     49
     50    EXAMPLES:
     51
     52    The simplest way to create a composition is by specifying its
     53    entries as a list, tuple (or other iterable)::
     54
    18955        sage: Composition([3,1,2])
    19056        [3, 1, 2]
    191    
    192     You can create a composition from a list of its descents.
    193    
    194     ::
    195    
     57        sage: Composition((3,1,2))
     58        [3, 1, 2]
     59        sage: Composition(i for i in range(2,5))
     60        [2, 3, 4]
     61
     62    You can alternatively create a composition from the list of its
     63    descents::
     64
    19665        sage: Composition([1, 1, 3, 4, 3]).descents()
    19766        [0, 1, 4, 8, 11]
    19867        sage: Composition(descents=[1,0,4,8,11])
    19968        [1, 1, 3, 4, 3]
    200    
    201     You can also create a composition from its code.
    202    
    203     ::
    204    
     69
     70    You can also create a composition from its code::
     71
    20572        sage: Composition([4,1,2,3,5]).to_code()
    20673        [1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0]
    207         sage: Composition(code=_)         
     74        sage: Composition(code=_)
    20875        [4, 1, 2, 3, 5]
    20976        sage: Composition([3,1,2,3,5]).to_code()
    21077        [1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0]
    def Composition(co=None, descents=None,  
    21986            return from_descents(descents)
    22087    elif code is not None:
    22188        return from_code(code)
     89    elif isinstance(co, Composition_class):
     90        return co
    22291    else:
    223         if isinstance(co, Composition_class):
    224             return co
    225         elif co in Compositions():
    226             return Composition_class(co)
    227         else:
    228             raise ValueError, "invalid composition"
    229            
     92        co = list(co)
     93        assert(co in Compositions())
     94        #raise ValueError, "invalid composition"
     95        return Composition_class(co)
     96
    23097
    23198class Composition_class(CombinatorialObject):
     99    __doc__ = Composition.__doc__
     100
    232101    def conjugate(self):
    233102        r"""
    234103        Returns the conjugate of the composition comp.
    class Composition_class(CombinatorialObj 
    268137        """
    269138        return Composition([element for element in reversed(self.conjugate())])
    270139
     140
     141    def __add__(self, other):
     142        """
     143        Returns the concatenation of two compositions.
     144
     145        EXAMPLES::
     146       
     147            sage: Composition([1, 1, 3]) + Composition([4, 1, 2])
     148            [1, 1, 3, 4, 1, 2]
     149
     150        TESTS::
     151       
     152            sage: Composition([]) + Composition([]) == Composition([])
     153            True
     154        """
     155        return Composition(list(self)+list(other))
     156
     157    def size(self):
     158        """
     159        Returns the size of the composition, that is the sum of its parts.
     160
     161        EXAMPLES::
     162       
     163            sage: Composition([7,1,3]).size()
     164            11
     165        """
     166        return sum(self)
     167
     168    @staticmethod
     169    def sum(compositions):
     170        """
     171        INPUT:
     172
     173         - ``compositions``: a list (or iterable) of compositions
     174
     175        Returns the concatenation of the given compositions
     176
     177        EXAMPLES::
     178
     179            sage: sage.combinat.composition.Composition_class.sum([Composition([1, 1, 3]), Composition([4, 1, 2]), Composition([3,1])])
     180            [1, 1, 3, 4, 1, 2, 3, 1]
     181
     182        Any iterable can be provided as input::
     183
     184            sage: sage.combinat.composition.Composition_class.sum([Composition([i,i]) for i in [4,1,3]])
     185            [4, 4, 1, 1, 3, 3]
     186
     187        Empty inputs are handled gracefuly::
     188       
     189            sage: sage.combinat.composition.Composition_class.sum([]) == Composition([])
     190            True
     191        """
     192        return sum(compositions, Composition([]))
     193
     194    def finer(self):
     195        """
     196        Returns the set of compositions which are finer than self
     197
     198        EXAMPLES::
     199       
     200            sage: C = Composition([3,2]).finer()
     201            sage: C.cardinality()
     202            8
     203            sage: list(C)
     204            [[1, 1, 1, 1, 1], [1, 1, 1, 2], [1, 2, 1, 1], [1, 2, 2], [2, 1, 1, 1], [2, 1, 2], [3, 1, 1], [3, 2]]
     205        """
     206        return CartesianProduct(*[Compositions(i) for i in self]).map(Composition_class.sum)
     207
    271208    def is_finer(self, co2):
    272209        """
    273210        Returns True if the composition self is finer than the composition
    class Composition_class(CombinatorialObj 
    303240
    304241        return True
    305242
     243    def fatten(self, grouping):
     244        """
     245        INPUT:
     246       
     247         - ``grouping`` - a composition whose sum is the length of self
     248       
     249        Returns the composition fatter than self, obtained by grouping
     250        together consecutive parts according to grouping.
     251
     252        EXAMPLES:
     253       
     254        Let us start with the composition::
     255       
     256            sage: c = Composition([4,5,2,7,1])
     257
     258        With `grouping = (1,\dots,1)`, `c` is left unchanged::
     259       
     260            sage: c.fatten(Composition([1,1,1,1,1]))
     261            [4, 5, 2, 7, 1]
     262
     263        With `grouping = (5)`, this yields the coarser composition above `c`::
     264       
     265            sage: c.fatten(Composition([5]))
     266            [19]
     267
     268        Other values for `grouping` yield (all the) other compositions coarser
     269        to `c`::
     270       
     271            sage: c.fatten(Composition([2,1,2]))
     272            [9, 2, 8]
     273            sage: c.fatten(Composition([3,1,1]))
     274            [11, 7, 1]
     275       
     276        TESTS::
     277       
     278            sage: Composition([]).fatten(Composition([]))
     279            []
     280            sage: c.fatten(Composition([3,1,1])).__class__ == c.__class__
     281            True
     282        """
     283        result = [None] * len(grouping)
     284        j = 0
     285        for i in range(len(grouping)):
     286            result[i] = sum(self[j:j+grouping[i]])
     287            j += grouping[i]
     288        return Composition_class(result)
     289
     290    def fatter(self):
     291        """
     292        Returns the set of compositions which are fatter than self
     293
     294        Complexity for generation: O(size(c)) memory, O(size(result)) time
     295
     296        EXAMPLES::
     297       
     298            sage: C = Composition([4,5,2]).fatter()
     299            sage: C.cardinality()
     300            4
     301            sage: list(C)
     302            [[4, 5, 2], [4, 7], [9, 2], [11]]
     303
     304        Some extreme cases::
     305       
     306            sage: list(Composition([5]).fatter())
     307            [[5]]
     308            sage: list(Composition([]).fatter())
     309            [[]]
     310            sage: list(Composition([1,1,1,1]).fatter()) == list(Compositions(4))
     311            True
     312        """
     313       
     314        return Compositions(len(self)).map(self.fatten)
     315
    306316    def refinement(self, co2):
    307317        """
    308318        Returns the refinement composition of self and co2.
    class Composition_class(CombinatorialObj 
    442452              filter(lambda x: x != 0, [l for l in reversed(inner)])])
    443453   
    444454
    445 
    446455##############################################################
    447456
    448457
    449458def Compositions(n=None, **kwargs):
    450     """
    451     Returns the combinatorial class of compositions.
    452    
    453     EXAMPLES: If n is not specified, it returns the combinatorial
    454     class of all (non-negative) integer compositions.
    455    
    456     ::
     459    r"""
     460    Sets of integer Compositions
     461
     462    A composition `c` of a nonnegative integer `n` is a list of
     463    positive integers with total sum `n`.
     464
     465    See also: `Composition`, `Partitions`, `IntegerVectors`
     466
     467    EXAMPLES:
     468
     469    There are 8 compositions of 4::
     470
     471        sage: Compositions(4).cardinality()
     472        8
     473
     474    Here is the list of them::
     475
     476        sage: list(Compositions(4))
     477        [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]]
     478
     479    You can use the .first() method to get the 'first' composition of
     480    a number::
     481
     482        sage: Compositions(4).first()
     483        [1, 1, 1, 1]
     484
     485    You can also calculate the 'next' composition given the current
     486    one::
     487
     488        sage: Compositions(4).next([1,1,2])
     489        [1, 2, 1]
     490
     491
     492
     493    If `n` is not specified, this returns the combinatorial class of
     494    all (non-negative) integer compositions::
    457495   
    458496        sage: Compositions()
    459497        Compositions of non-negative integers
    def Compositions(n=None, **kwargs): 
    464502        sage: [-2,3,1] in Compositions()
    465503        False
    466504   
    467     If n is specified, it returns the class of compositions of n.
    468    
    469     ::
     505    If n is specified, it returns the class of compositions of n::
    470506   
    471507        sage: Compositions(3)
    472508        Compositions of 3
    473         sage: Compositions(3).list()
     509        sage: list(Compositions(3))
    474510        [[1, 1, 1], [1, 2], [2, 1], [3]]
    475511        sage: Compositions(3).cardinality()
    476512        4
     513
     514    The following examples shows how to test whether or not an object
     515    is a composition::
     516
     517        sage: [3,4] in Compositions()
     518        True
     519        sage: [3,4] in Compositions(7)
     520        True
     521        sage: [3,4] in Compositions(5)
     522        False
     523
     524    Similarly, one can check whether or not an object is a composition
     525    which satisfies further constraints::
     526
     527        sage: [4,2] in Compositions(6, inner=[2,2])
     528        True
     529        sage: [4,2] in Compositions(6, inner=[2,3])
     530        False
     531        sage: [4,1] in Compositions(5, inner=[2,1], max_slope = 0)
     532        True
     533
     534    Note that the given constraints should be compatible::
     535
     536        sage: [4,2] in Compositions(6, inner=[2,2], min_part=3) #
     537        True
     538
     539    The options length, min_length, and max_length can be used to set
     540    length constraints on the compositions. For example, the
     541    compositions of 4 of length equal to, at least, and at most 2 are
     542    given by::
     543
     544        sage: Compositions(4, length=2).list()
     545        [[3, 1], [2, 2], [1, 3]]
     546        sage: Compositions(4, min_length=2).list()
     547        [[3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
     548        sage: Compositions(4, max_length=2).list()
     549        [[4], [3, 1], [2, 2], [1, 3]]
     550
     551    Setting both min_length and max_length to the same value is
     552    equivalent to setting length to this value::
     553
     554        sage: Compositions(4, min_length=2, max_length=2).list()
     555        [[3, 1], [2, 2], [1, 3]]
     556
     557    The options inner and outer can be used to set part-by-part
     558    containment constraints. The list of compositions of 4 bounded
     559    above by [3,1,2] is given by::
     560
     561        sage: list(Compositions(4, outer=[3,1,2]))
     562        [[3, 1], [2, 1, 1], [1, 1, 2]]
     563
     564    Outer sets max_length to the length of its argument. Moreover, the
     565    parts of outer may be infinite to clear the constraint on specific
     566    parts. This is the list of compositions of 4 of length at most 3
     567    such that the first and third parts are at most 1::
     568
     569        sage: list(Compositions(4, outer=[1,oo,1]))
     570        [[1, 3], [1, 2, 1]]
     571
     572    This is the list of compositions of 4 bounded below by [1,1,1]::
     573
     574        sage: list(Compositions(4, inner=[1,1,1]))
     575        [[2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
     576
     577    The options min_slope and max_slope can be used to set constraints
     578    on the slope, that is the difference `p[i+1]-p[i]` of two
     579    consecutive parts. The following is the list of weakly increasing
     580    compositions of 4::
     581
     582        sage: Compositions(4, min_slope=0).list()
     583        [[4], [2, 2], [1, 3], [1, 1, 2], [1, 1, 1, 1]]
    477584   
    478     In addition, the following constraints can be put on the
    479     compositions: length, min_part, max_part, min_length,
    480     max_length, min_slope, max_slope, inner, and outer. For
    481     example,
     585    Here are the weakly decreasing ones::
     586
     587        sage: Compositions(4, max_slope=0).list()
     588        [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]]
     589
     590
     591    The following is the list of compositions of 4 such that two
     592    consecutive parts differ by at most one::
     593
     594        sage: Compositions(4, min_slope=-1, max_slope=1).list()
     595        [[4], [2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
     596
     597    The constraints can be combined together in all reasonable ways.
     598    This is the list of compositions of 5 of length between 2 and 4
     599    such that the difference between consecutive parts is between -2
     600    and 1::
     601
     602        sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4).list()
     603        [[3, 2], [3, 1, 1], [2, 3], [2, 2, 1], [2, 1, 2], [2, 1, 1, 1], [1, 2, 2], [1, 2, 1, 1], [1, 1, 2, 1], [1, 1, 1, 2]]
     604
     605    We can do the same thing with an outer constraint::
     606
     607        sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4, outer=[2,5,2]).list()
     608        [[2, 3], [2, 2, 1], [2, 1, 2], [1, 2, 2]]
     609
     610    However, providing incoherent constraints may yield strange
     611    results. It is up to the user to ensure that the inner and outer
     612    compositions themselves satisfy the parts and slope constraints.
     613
     614    Note that if you specify min_part=0, then the objects produced may
     615    have parts equal to zero. This violates the internal assumptions
     616    that the Composition class makes. Use at your own risk, or
     617    preferably consider using `IntegerVectors` instead::
     618
     619        sage: list(Compositions(2, length=3, min_part=0))
     620        doctest:... RuntimeWarning: Currently, setting min_part=0 produces Composition objects which violate internal assumptions.  Calling methods on these objects may produce errors or WRONG results!
     621        [[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]]
     622
     623        sage: list(IntegerVectors(2, 3))
     624        [[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]]
     625
     626    The generation algorithm is constant amortized time, and handled
     627    by the generic tool `IntegerListsLex`.
     628
     629    TESTS::
    482630   
    483     ::
     631        sage: C = Compositions(4, length=2)
     632        sage: C == loads(dumps(C))
     633        True
     634
     635        sage: Compositions(6, min_part=2, length=3)
     636        Compositions of the integer 6 satisfying constraints length=3, min_part=2
    484637   
    485         sage: Compositions(3, length=2).list()
    486         [[1, 2], [2, 1]]
    487         sage: Compositions(4, max_slope=0).list()
    488         [[1, 1, 1, 1], [2, 1, 1], [2, 2], [3, 1], [4]]
     638       
     639        sage: [2, 1] in Compositions(3, length=2)
     640        True
     641        sage: [2,1,2] in Compositions(5, min_part=1)
     642        True
     643        sage: [2,1,2] in Compositions(5, min_part=2)
     644        False
     645   
     646        sage: Compositions(4, length=2).cardinality()
     647        3
     648        sage: Compositions(4, min_length=2).cardinality()
     649        7
     650        sage: Compositions(4, max_length=2).cardinality()
     651        4
     652        sage: Compositions(4, max_part=2).cardinality()
     653        5
     654        sage: Compositions(4, min_part=2).cardinality()
     655        2
     656        sage: Compositions(4, outer=[3,1,2]).cardinality()
     657        3
     658       
     659        sage: Compositions(4, length=2).list()
     660        [[3, 1], [2, 2], [1, 3]]
     661        sage: Compositions(4, min_length=2).list()
     662        [[3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
     663        sage: Compositions(4, max_length=2).list()
     664        [[4], [3, 1], [2, 2], [1, 3]]
     665        sage: Compositions(4, max_part=2).list()
     666        [[2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
     667        sage: Compositions(4, min_part=2).list()
     668        [[4], [2, 2]]
     669        sage: Compositions(4, outer=[3,1,2]).list()
     670        [[3, 1], [2, 1, 1], [1, 1, 2]]
     671        sage: Compositions(4, outer=[1,oo,1]).list()
     672        [[1, 3], [1, 2, 1]]
     673        sage: Compositions(4, inner=[1,1,1]).list()
     674        [[2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
     675        sage: Compositions(4, min_slope=0).list()
     676        [[4], [2, 2], [1, 3], [1, 1, 2], [1, 1, 1, 1]]
     677        sage: Compositions(4, min_slope=-1, max_slope=1).list()
     678        [[4], [2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
     679        sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4).list()
     680        [[3, 2], [3, 1, 1], [2, 3], [2, 2, 1], [2, 1, 2], [2, 1, 1, 1], [1, 2, 2], [1, 2, 1, 1], [1, 1, 2, 1], [1, 1, 1, 2]]
     681        sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4, outer=[2,5,2]).list()
     682        [[2, 3], [2, 2, 1], [2, 1, 2], [1, 2, 2]]
    489683    """
    490684    if n is None:
     685        assert(len(kwargs) == 0)
    491686        return Compositions_all()
    492687    else:
    493         if kwargs:
    494             return Compositions_constraints(n, **kwargs)
     688        if len(kwargs) == 0:
     689            if isinstance(n, (int,Integer)):
     690                return Compositions_n(n)
     691            else:
     692                raise ValueError, "n must be an integer"
    495693        else:
    496             return Compositions_n(n)
     694            # FIXME: should inherit from IntegerListLex, and implement repr, or _name as a lazy attribute
     695            kwargs['name'] = "Compositions of the integer %s satisfying constraints %s"%(n, ", ".join( ["%s=%s"%(key, kwargs[key]) for key in sorted(kwargs.keys())] ))
     696            kwargs['element_constructor'] = Composition_class
     697            if 'min_part' not in kwargs:
     698                kwargs['min_part'] = 1
     699            elif kwargs['min_part'] == 0:
     700                from warnings import warn
     701                warn("Currently, setting min_part=0 produces Composition objects which violate internal assumptions.  Calling methods on these objects may produce errors or WRONG results!", RuntimeWarning)
     702
     703            if 'outer' in kwargs:
     704                kwargs['ceiling'] = kwargs['outer']
     705                if 'max_length' in kwargs:
     706                    kwargs['max_length'] = min( len(kwargs['outer']), kwargs['max_length'])
     707                else:
     708                    kwargs['max_length'] = len(kwargs['outer'])
     709                del kwargs['outer']
     710
     711            if 'inner' in kwargs:
     712                inner = kwargs['inner']
     713                kwargs['floor'] = inner
     714                del kwargs['inner']
     715                # Should this be handled by integer lists lex?
     716                if 'min_length' in kwargs:
     717                    kwargs['min_length'] = max( len(inner), kwargs['min_length'])
     718                else:
     719                    kwargs['min_length'] = len(inner)
     720            return IntegerListsLex(n, **kwargs)
     721
     722
     723# Allows to unpickle old constrained Compositions_constraints objects.
     724class Compositions_constraints(IntegerListsLex):
     725    def __setstate__(self, data):
     726        """
     727        TESTS::
     728
     729            # This is the unpickling sequence for Compositions(4, max_part=2) in sage <= 4.1.1
     730            sage: pg_Compositions_constraints = unpickle_global('sage.combinat.composition', 'Compositions_constraints')
     731            sage: si = unpickle_newobj(pg_Compositions_constraints, ())
     732            sage: pg_make_integer = unpickle_global('sage.rings.integer', 'make_integer')
     733            sage: unpickle_build(si, {'constraints':{'max_part':pg_make_integer('2')}, 'n':pg_make_integer('4')})
     734            sage: si
     735            Integer lists of sum 4 satisfying certain constraints
     736            sage: si.list()
     737            [[2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
     738        """
     739        n = data['n']
     740        self.__class__ = IntegerListsLex
     741        constraints = {
     742                       'min_part' : 1,
     743                       'element_constructor' : Composition_class}
     744        constraints.update(data['constraints'])
     745        self.__init__(n, **constraints)
    497746
    498747class Compositions_all(InfiniteAbstractCombinatorialClass):
    499748    def __init__(self):
    class Compositions_n(CombinatorialClass) 
    626875        return [Composition_class(r) for r in result]
    627876
    628877
    629 class Compositions_constraints(CombinatorialClass):
    630     object_class = Composition_class
    631878
    632     def __init__(self, n, **kwargs):
    633         """
    634         ::
    635        
    636             sage: C = Compositions(4, length=2)
    637             sage: C == loads(dumps(C))
    638             True
    639         """
    640         self.n = n
    641         self.constraints = kwargs
    642879
    643     def __repr__(self):
    644         """
    645         TESTS::
    646        
    647             sage: repr(Compositions(6, min_part=2, length=3))
    648             'Compositions of 6 with constraints length=3, min_part=2'
    649         """
    650         return "Compositions of %s with constraints %s"%(self.n, ", ".join( ["%s=%s"%(key, self.constraints[key]) for key in sorted(self.constraints.keys())] ))
    651    
    652     def __contains__(self, x):
    653         """
    654         TESTS::
    655        
    656             sage: [2, 1] in Compositions(3, length=2)
    657             True
    658             sage: [2,1,2] in Compositions(5, min_part=1)
    659             True
    660             sage: [2,1,2] in Compositions(5, min_part=2)
    661             False
    662         """
    663         return x in Compositions() and sum(x) == self.n and misc.check_integer_list_constraints(x, singleton=True, **self.constraints)
    664    
    665 
    666     def cardinality(self):
    667         """
    668         EXAMPLES::
    669        
    670             sage: Compositions(4, length=2).cardinality()
    671             3
    672             sage: Compositions(4, min_length=2).cardinality()
    673             7
    674             sage: Compositions(4, max_length=2).cardinality()
    675             4
    676             sage: Compositions(4, max_part=2).cardinality()
    677             5
    678             sage: Compositions(4, min_part=2).cardinality()
    679             2
    680             sage: Compositions(4, outer=[3,1,2]).cardinality()
    681             3
    682         """
    683         if len(self.constraints) == 1 and 'length' in self.constraints:
    684             if self.n >= 1:
    685                 return binomial(self.n-1, self.constraints['length'] - 1)
    686             elif self.n == 0:
    687                 if self.constraints['length'] == 0:
    688                     return 1
    689                 else:
    690                     return 0
    691             else:
    692                 return 0
    693         return len(self.list())
    694 
    695 
    696 
    697     def list(self):
    698         """
    699         Returns a list of all the compositions of n.
    700        
    701         EXAMPLES::
    702        
    703             sage: Compositions(4, length=2).list()
    704             [[1, 3], [2, 2], [3, 1]]
    705             sage: Compositions(4, min_length=2).list()
    706             [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1]]
    707             sage: Compositions(4, max_length=2).list()
    708             [[1, 3], [2, 2], [3, 1], [4]]
    709             sage: Compositions(4, max_part=2).list()
    710             [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [2, 1, 1], [2, 2]]
    711             sage: Compositions(4, min_part=2).list()
    712             [[2, 2], [4]]
    713             sage: Compositions(4, outer=[3,1,2]).list()
    714             [[1, 1, 2], [2, 1, 1], [3, 1]]
    715             sage: Compositions(4, outer=[1,'inf',1]).list()
    716             [[1, 2, 1], [1, 3]]
    717             sage: Compositions(4, inner=[1,1,1]).list()
    718             [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [2, 1, 1]]
    719             sage: Compositions(4, min_slope=0).list()
    720             [[1, 1, 1, 1], [1, 1, 2], [1, 3], [2, 2], [4]]
    721             sage: Compositions(4, min_slope=-1, max_slope=1).list()
    722             [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [2, 1, 1], [2, 2], [4]]
    723             sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4).list()
    724             [[1, 1, 1, 2],
    725              [1, 1, 2, 1],
    726              [1, 2, 1, 1],
    727              [1, 2, 2],
    728              [2, 1, 1, 1],
    729              [2, 1, 2],
    730              [2, 2, 1],
    731              [2, 3],
    732              [3, 1, 1],
    733              [3, 2]]
    734             sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4, outer=[2,5,2]).list()
    735             [[1, 2, 2], [2, 1, 2], [2, 2, 1], [2, 3]]
    736         """
    737         n = self.n
    738 
    739         if n == 0:
    740             return [Composition_class([])]
    741 
    742         result = []
    743         for i in range(1,n+1):
    744             result += map(lambda x: [i]+x[:], Compositions_constraints(n-i).list())
    745 
    746         if self.constraints:
    747             result = misc.check_integer_list_constraints(result, **self.constraints)
    748 
    749         result = [Composition_class(r) for r in result]
    750 
    751         return result
    752 
    753 
    754 
     880# Those belong to the Compositino class
    755881
    756882def from_descents(descents, nps=None):
    757883    """
  • sage/combinat/partition.py

    diff --git a/sage/combinat/partition.py b/sage/combinat/partition.py
    a b class Partitions_parts_in(CombinatorialC 
    32783278        given parts, or None if no such partition exists. This function
    32793279        is not intended to be called directly.
    32803280
    3281         INPUT::
     3281        INPUT:
    32823282
    32833283        - ``n``: nonnegative integer
    32843284        - ``parts``: a sorted list of positive integers.
  • sage/combinat/ribbon_tableau.py

    diff --git a/sage/combinat/ribbon_tableau.py b/sage/combinat/ribbon_tableau.py
    a b class SemistandardMultiSkewTtableaux_sha 
    873873        EXAMPLES::
    874874       
    875875            sage: sp = SkewPartitions(3).list()
    876             sage: SemistandardMultiSkewTableaux([sp[0], sp[-1]],[2,2,2]).list()
     876            sage: SemistandardMultiSkewTableaux([SkewPartition([[1, 1, 1], []]), SkewPartition([[3], []])],[2,2,2]).list()
    877877            [[[[1], [2], [3]], [[1, 2, 3]]]]
    878878       
    879879        ::
  • sage/combinat/set_partition_ordered.py

    diff --git a/sage/combinat/set_partition_ordered.py b/sage/combinat/set_partition_ordered.py
    a b class OrderedSetPartitions_sn(Combinator 
    316316        EXAMPLES::
    317317       
    318318            sage: [ p for p in OrderedSetPartitions([1,2,3,4], 2) ]
    319             [[{1}, {2, 3, 4}],
    320              [{2}, {1, 3, 4}],
    321              [{3}, {1, 2, 4}],
    322              [{4}, {1, 2, 3}],
     319            [[{1, 2, 3}, {4}],
     320             [{1, 2, 4}, {3}],
     321             [{1, 3, 4}, {2}],
     322             [{2, 3, 4}, {1}],
    323323             [{1, 2}, {3, 4}],
    324324             [{1, 3}, {2, 4}],
    325325             [{1, 4}, {2, 3}],
    326326             [{2, 3}, {1, 4}],
    327327             [{2, 4}, {1, 3}],
    328328             [{3, 4}, {1, 2}],
    329              [{1, 2, 3}, {4}],
    330              [{1, 2, 4}, {3}],
    331              [{1, 3, 4}, {2}],
    332              [{2, 3, 4}, {1}]]
     329             [{1}, {2, 3, 4}],
     330             [{2}, {1, 3, 4}],
     331             [{3}, {1, 2, 4}],
     332             [{4}, {1, 2, 3}]]
    333333        """
    334334        for x in composition.Compositions(len(self.s),length=self.n):
    335335            for z in OrderedSetPartitions_scomp(self.s,x):
  • sage/combinat/skew_partition.py

    diff --git a/sage/combinat/skew_partition.py b/sage/combinat/skew_partition.py
    a b below are the coordinates of the inner a 
    6363    sage: SkewPartition([[5,4,3,1],[3,3,1]]).inner_corners()
    6464    [[0, 3], [2, 1], [3, 0]]
    6565
    66 EXAMPLES: There are 9 skew partitions of size 3.
     66EXAMPLES:
    6767
    68 ::
     68There are 9 skew partitions of size 3, with no empty row nor empty
     69column::
    6970
    7071    sage: SkewPartitions(3).cardinality()
    7172    9
    7273    sage: SkewPartitions(3).list()
    73     [[[1, 1, 1], []],
     74    [[[3], []],
     75     [[2, 1], []],
     76     [[3, 1], [1]],
     77     [[2, 2], [1]],
     78     [[3, 2], [2]],
     79     [[1, 1, 1], []],
    7480     [[2, 2, 1], [1, 1]],
    7581     [[2, 1, 1], [1]],
    76      [[3, 2, 1], [2, 1]],
    77      [[2, 2], [1]],
    78      [[3, 2], [2]],
    79      [[2, 1], []],
    80      [[3, 1], [1]],
    81      [[3], []]]
     82     [[3, 2, 1], [2, 1]]]
    8283
    83 There are 4 connected skew partitions of size 3.
    84 
    85 ::
     84There are 4 connected skew partitions of size 3::
    8685
    8786    sage: SkewPartitions(3, overlap=1).cardinality()
    8887    4
    8988    sage: SkewPartitions(3, overlap=1).list()
    90     [[[1, 1, 1], []], [[2, 2], [1]], [[2, 1], []], [[3], []]]
     89    [[[3], []], [[2, 1], []], [[2, 2], [1]], [[1, 1, 1], []]]
    9190
    9291This is the conjugate of the skew partition [[4,3,1],[2]]
    9392
    def SkewPartitions(n=None, row_lengths=N 
    624623        sage: SkewPartitions(4, overlap=2)
    625624        Skew partitions of 4 with overlap of 2
    626625        sage: SkewPartitions(4, overlap=2).list()
    627         [[[2, 2], []], [[4], []]]
     626        [[[4], []], [[2, 2], []]]
    628627    """
    629628    number_of_arguments = 0
    630629    for arg in ['n', 'row_lengths']:
    class SkewPartitions_all(CombinatorialCl 
    737736        raise NotImplementedError
    738737
    739738class SkewPartitions_n(CombinatorialClass):
     739    """
     740    The combinatorial class of skew partitions with given size (and
     741    horizontal minimal overlap).
     742    """
    740743    def __init__(self, n, overlap=0):
    741744        """
     745        INPUT:
     746         - n: an non negative integer
     747         - overlap: an integer
     748       
     749        Returns the set of the skew partitions of ``n`` with overlap
     750        at least ``overlap``, and no empty row.
     751
     752        The iteration order is not specified yet.
     753
     754        Caveat: this set is stable under conjugation only for overlap=
     755        0 or 1. What exactly happens for negative overlaps is not yet
     756        well specified, and subject to change (we may want to
     757        introduce vertical overlap constraints as well). overlap would
     758        also better be named min_overlap.
     759
     760        Todo: as is, this set is essentially the composition of
     761        Compositions(n) (which give the row lengths) and
     762        SkewPartition(n, row_lengths=...), and one would want to
     763        "inherit" list and cardinality from this composition.
     764
    742765        TESTS::
    743766       
    744767            sage: S = SkewPartitions(3)
    class SkewPartitions_n(CombinatorialClas 
    808831        Returns the number of skew partitions related to the composition co
    809832        by 'sliding'. The composition co is the list of row lengths of the
    810833        skew partition.
     834
     835        Todo: this should be a method of SkewPartition
    811836       
    812837        EXAMPLES::
    813838       
    class SkewPartitions_n(CombinatorialClas 
    858883            return 1
    859884
    860885        if overlap > 0:
    861             gg = sage.combinat.composition.Compositions(n, min_part = overlap)
     886            gg = sage.combinat.composition.Compositions(n, min_part = max(1, overlap))
    862887        else:
    863888            gg = sage.combinat.composition.Compositions(n)
    864889
    class SkewPartitions_n(CombinatorialClas 
    868893
    869894        return sum_a
    870895
    871     def list(self):
     896    def __iter__(self):
    872897        """
    873898        Returns a list of the skew partitions of n.
    874        
     899
    875900        EXAMPLES::
    876901       
    877902            sage: SkewPartitions(3).list()
    878             [[[1, 1, 1], []],
    879              [[2, 2, 1], [1, 1]],
    880              [[2, 1, 1], [1]],
    881              [[3, 2, 1], [2, 1]],
    882              [[2, 2], [1]],
    883              [[3, 2], [2]],
    884              [[2, 1], []],
    885              [[3, 1], [1]],
    886              [[3], []]]
     903            [[[3], []],
     904            [[2, 1], []],
     905            [[3, 1], [1]],
     906            [[2, 2], [1]],
     907            [[3, 2], [2]],
     908            [[1, 1, 1], []],
     909            [[2, 2, 1], [1, 1]],
     910            [[2, 1, 1], [1]],
     911            [[3, 2, 1], [2, 1]]]
     912
     913
    887914            sage: SkewPartitions(3, overlap=0).list()
    888             [[[1, 1, 1], []],
    889              [[2, 2, 1], [1, 1]],
    890              [[2, 1, 1], [1]],
    891              [[3, 2, 1], [2, 1]],
    892              [[2, 2], [1]],
    893              [[3, 2], [2]],
    894              [[2, 1], []],
    895              [[3, 1], [1]],
    896              [[3], []]]
     915            [[[3], []],
     916            [[2, 1], []],
     917            [[3, 1], [1]],
     918            [[2, 2], [1]],
     919            [[3, 2], [2]],
     920            [[1, 1, 1], []],
     921            [[2, 2, 1], [1, 1]],
     922            [[2, 1, 1], [1]],
     923            [[3, 2, 1], [2, 1]]]
    897924            sage: SkewPartitions(3, overlap=1).list()
    898             [[[1, 1, 1], []], [[2, 2], [1]], [[2, 1], []], [[3], []]]
     925            [[[3], []], [[2, 1], []], [[2, 2], [1]], [[1, 1, 1], []]]
    899926            sage: SkewPartitions(3, overlap=2).list()
    900927            [[[3], []]]
    901928            sage: SkewPartitions(3, overlap=3).list()
    class SkewPartitions_n(CombinatorialClas 
    906933        n = self.n
    907934        overlap = self.overlap
    908935
    909         result = []
    910         for co in sage.combinat.composition.Compositions(n, min_part=overlap).list():
    911             result += SkewPartitions(row_lengths=co, overlap=overlap).list()
    912 
    913         return result
     936        for co in sage.combinat.composition.Compositions(n, min_part = max(1, overlap)):
     937            for sp in SkewPartitions(row_lengths=co, overlap=overlap):
     938                yield sp
    914939   
    915940######################################
    916941# Skew Partitions (from row lengths) #
  • sage/combinat/skew_tableau.py

    diff --git a/sage/combinat/skew_tableau.py b/sage/combinat/skew_tableau.py
    a b class StandardSkewTableaux_all(InfiniteA 
    722722            True
    723723            sage: it = iter(StandardSkewTableaux())    # indirect doctest
    724724            sage: [it.next() for i in range(10)]
    725             [[], [[1]], [[1], [2]], [[None, 1], [2]], [[None, 2], [1]], [[1, 2]], [[1], [2], [3]], [[None, 1], [None, 2], [3]], [[None, 1], [None, 3], [2]], [[None, 2], [None, 3], [1]]]
     725            [[], [[1]], [[1, 2]], [[1], [2]], [[None, 1], [2]], [[None, 2], [1]], [[1, 2, 3]], [[1, 2], [3]], [[1, 3], [2]], [[None, 1, 2], [3]]]
    726726        """
    727727        return StandardSkewTableaux_n(n)
    728728
    class StandardSkewTableaux_n(Combinatori 
    770770        EXAMPLES::
    771771       
    772772            sage: StandardSkewTableaux(2).list() #indirect doctest
    773             [[[1], [2]], [[None, 1], [2]], [[None, 2], [1]], [[1, 2]]]
     773            [[[1, 2]], [[1], [2]], [[None, 1], [2]], [[None, 2], [1]]]
     774
     775            sage: StandardSkewTableaux(3).list() #indirect doctest
     776            [[[1, 2, 3]],
     777             [[1, 2], [3]], [[1, 3], [2]],
     778             [[None, 1, 2], [3]], [[None, 1, 3], [2]],
     779             [[None, 2, 3], [1]],
     780             [[None, 1], [2, 3]], [[None, 2], [1, 3]],
     781             [[None, None, 1], [2, 3]], [[None, None, 2], [1, 3]], [[None, None, 3], [1, 2]],
     782             [[1], [2], [3]],
     783             [[None, 1], [None, 2], [3]], [[None, 1], [None, 3], [2]], [[None, 2], [None, 3], [1]],
     784             [[None, 1], [2], [3]], [[None, 2], [1], [3]], [[None, 3], [1], [2]],
     785             [[None, None, 1], [None, 2], [3]], [[None, None, 1], [None, 3], [2]],
     786             [[None, None, 2], [None, 1], [3]], [[None, None, 3], [None, 1], [2]],
     787             [[None, None, 2], [None, 3], [1]], [[None, None, 3], [None, 2], [1]]]
    774788        """
    775789        for skp in skew_partition.SkewPartitions(self.n):
    776790            for sst in StandardSkewTableaux_skewpartition(skp):
    class SemistandardSkewTableaux_n(Combina 
    947961        EXAMPLES::
    948962       
    949963            sage: SemistandardSkewTableaux(2).list() # indirect doctest
    950             [[[1], [2]],
     964            [[[1, 1]],
     965             [[1, 2]],
     966             [[2, 2]],
     967             [[1], [2]],
    951968             [[None, 1], [1]],
    952969             [[None, 2], [1]],
    953970             [[None, 1], [2]],
    954              [[None, 2], [2]],
    955              [[1, 1]],
    956              [[1, 2]],
    957              [[2, 2]]]
     971             [[None, 2], [2]]]
    958972        """
    959973        for p in skew_partition.SkewPartitions(self.n):
    960974            for ssst in SemistandardSkewTableaux_p(p):
    class SemistandardSkewTableaux_nmu(Combi 
    9981012        EXAMPLES::
    9991013       
    10001014            sage: SemistandardSkewTableaux(2,[1,1]).list() # indirect doctest
    1001             [[[1], [2]], [[None, 2], [1]], [[None, 1], [2]], [[1, 2]]]
     1015            [[[1, 2]], [[1], [2]], [[None, 2], [1]], [[None, 1], [2]]]
    10021016        """       
    10031017        for p in skew_partition.SkewPartitions(self.n):
    10041018            for ssst in SemistandardSkewTableaux_pmu(p, self.mu):