Ticket #5600: compositions-cleanup-5600-nt.patch

File compositions-cleanup-5600-nt.patch, 40.4 KB (added by nthiery, 13 years ago)
  • sage/combinat/composition.py

    # HG changeset patch
    # User Nicolas M. Thiery <nthiery@users.sf.net>
    # Date 1242256615 25200
    # Node ID 5de5b31de7e612b4fd77ea6bb0f35eb6ba9fc3d9
    # Parent  268d1efbf60f6c24ad9c49cb9c91ff0437e42340
    #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 not any better specific code
       Note: this changes the iteration order to inverse lexicographic,
       and iteration changes the iteration order for set partitions, skew
       partitions, and skew 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"""
     1"""
    22Compositions
    33
    4 A composition c of a nonnegative integer n is a list of positive
    5 integers with total sum n.
    6 
    7 EXAMPLES: There are 8 compositions of 4.
    8 
    9 ::
    10 
    11     sage: Compositions(4).cardinality()
    12     8
    13 
    14 Here is the list of them::
    15 
    16     sage: Compositions(4).list()
    17     [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]]
    18 
    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.
    151 
    152 AUTHORS:
    153 
    154 - Mike Hansen
    155 
    156 - MuPAD-Combinat developers (for algorithms and design inspiration)
     4A compositions `c` of a nonnegative integer `n` is a list of positive integers
     5(the *parts* of the compositions) with total sum `n`.
    1576"""
    1587#*****************************************************************************
    1598#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,
    AUTHORS: 
    17221
    17322import sage.combinat.skew_partition
    17423from combinat import CombinatorialClass, CombinatorialObject, InfiniteAbstractCombinatorialClass
     24from cartesian_product import CartesianProduct
     25from integer_list import IntegerListsLex
    17526import __builtin__
    17627from sage.rings.integer import Integer
    17728from sage.rings.arith import binomial
    import misc 
    17930
    18031def Composition(co=None, descents=None, code=None):
    18132    """
    182     Returns a composition object.
     33    Constructor for integer compositions. See Composition_class?
     34    """
     35    if descents is not None:
     36        if isinstance(descents, tuple):
     37            return from_descents(descents[0], nps=descents[1])
     38        else:
     39            return from_descents(descents)
     40    elif code is not None:
     41        return from_code(code)
     42    elif isinstance(co, Composition_class):
     43        return co
     44    else:
     45        co = list(co)
     46        assert(co in Compositions())
     47        #raise ValueError, "invalid composition"
     48        return Composition_class(co)
     49
     50
     51class Composition_class(CombinatorialObject):
     52    """
     53    A class for integer compositions.
    18354   
    184     EXAMPLES: The standard way to create a composition is by specifying
    185     it as a list.
    186    
    187     ::
     55    A composition of a nonnegative integer `n` is a list
     56    `(i_1,\dots,i_k)` of positive integers with total sum `n`.
     57
     58    TODO: mathematical definition of descents, code, ...
     59
     60    EXAMPLES:
     61
     62    The simplest way to create a composition is by specifying its
     63    entries as a list, tuple (or other iterable)::
    18864   
    18965        sage: Composition([3,1,2])
    19066        [3, 1, 2]
     67        sage: Composition((3,1,2))
     68        [3, 1, 2]
     69        sage: Composition(i for i in range(2,5))
     70        [2, 3, 4]
    19171   
    192     You can create a composition from a list of its descents.
    193    
    194     ::
     72    You can alternatively create a composition from the list of its
     73    descents::
    19574   
    19675        sage: Composition([1, 1, 3, 4, 3]).descents()
    19776        [0, 1, 4, 8, 11]
    19877        sage: Composition(descents=[1,0,4,8,11])
    19978        [1, 1, 3, 4, 3]
    20079   
    201     You can also create a composition from its code.
    202    
    203     ::
     80    You can also create a composition from its code::
    20481   
    20582        sage: Composition([4,1,2,3,5]).to_code()
    20683        [1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0]
    def Composition(co=None, descents=None,  
    21289        [3, 1, 2, 3, 5]
    21390    """
    21491
    215     if descents is not None:
    216         if isinstance(descents, tuple):
    217             return from_descents(descents[0], nps=descents[1])
    218         else:
    219             return from_descents(descents)
    220     elif code is not None:
    221         return from_code(code)
    222     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            
    230 
    231 class Composition_class(CombinatorialObject):
    23292    def conjugate(self):
    23393        r"""
    23494        Returns the conjugate of the composition comp.
    class Composition_class(CombinatorialObj 
    268128        """
    269129        return Composition([element for element in reversed(self.conjugate())])
    270130
     131
     132    def __add__(self, other):
     133        """
     134        Returns the concatenation of two compositions.
     135
     136        EXAMPLES::
     137       
     138            sage: Composition([1, 1, 3]) + Composition([4, 1, 2])
     139            [1, 1, 3, 4, 1, 2]
     140
     141        TESTS::
     142       
     143            sage: Composition([]) + Composition([]) == Composition([])
     144            True
     145        """
     146        return Composition(list(self)+list(other))
     147
     148    def size(self):
     149        """
     150        Returns the size of the composition, that is the sum of its parts.
     151
     152        EXAMPLES::
     153       
     154            sage: Composition([7,1,3]).size()
     155            11
     156        """
     157        return sum(self)
     158
     159    @staticmethod
     160    def sum(compositions):
     161        """
     162        INPUT:
     163
     164         - ``compositions``: a list (or iterable) of compositions
     165
     166        Returns the concatenation of the given compositions
     167
     168        EXAMPLES::
     169
     170            sage: sage.combinat.composition.Composition_class.sum([Composition([1, 1, 3]), Composition([4, 1, 2]), Composition([3,1])])
     171            [1, 1, 3, 4, 1, 2, 3, 1]
     172
     173        Any iterable can be provided as input::
     174
     175            sage: sage.combinat.composition.Composition_class.sum([Composition([i,i]) for i in [4,1,3]])
     176            [4, 4, 1, 1, 3, 3]
     177
     178        Empty inputs are handled gracefuly::
     179       
     180            sage: sage.combinat.composition.Composition_class.sum([]) == Composition([])
     181            True
     182        """
     183        return sum(compositions, Composition([]))
     184
     185    def finer(self):
     186        """
     187        Returns the set of compositions which are finer than self
     188
     189        EXAMPLES::
     190       
     191            sage: C = Composition([3,2]).finer()
     192            sage: C.cardinality()
     193            8
     194            sage: list(C)
     195            [[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]]
     196        """
     197        return CartesianProduct(*[Compositions(i) for i in self]).map(Composition_class.sum)
     198
    271199    def is_finer(self, co2):
    272200        """
    273201        Returns True if the composition self is finer than the composition
    class Composition_class(CombinatorialObj 
    303231
    304232        return True
    305233
     234    def fatten(self, grouping):
     235        """
     236        INPUT:
     237       
     238         - ``grouping`` - a composition whose sum is the length of self
     239       
     240        Returns the composition fatter than self, obtained by grouping
     241        together consecutive parts according to grouping.
     242
     243        EXAMPLES:
     244       
     245        Let us start with the composition::
     246       
     247            sage: c = Composition([4,5,2,7,1])
     248
     249        With `grouping = (1,\dots,1)`, `c` is left unchanged::
     250       
     251            sage: c.fatten(Composition([1,1,1,1,1]))
     252            [4, 5, 2, 7, 1]
     253
     254        With `grouping = (5)`, this yields the coarser composition above `c`::
     255       
     256            sage: c.fatten(Composition([5]))
     257            [19]
     258
     259        Other values for `grouping` yield (all the) other compositions coarser
     260        to `c`::
     261       
     262            sage: c.fatten(Composition([2,1,2]))
     263            [9, 2, 8]
     264            sage: c.fatten(Composition([3,1,1]))
     265            [11, 7, 1]
     266       
     267        TESTS::
     268       
     269            sage: Composition([]).fatten(Composition([]))
     270            []
     271            sage: c.fatten(Composition([3,1,1])).__class__ == c.__class__
     272            True
     273        """
     274        result = [None] * len(grouping)
     275        j = 0
     276        for i in range(len(grouping)):
     277            result[i] = sum(self[j:j+grouping[i]])
     278            j += grouping[i]
     279        return Composition_class(result)
     280
     281    def fatter(self):
     282        """
     283        Returns the set of compositions which are fatter than self
     284
     285        Complexity for generation: O(size(c)) memory, O(size(result)) time
     286
     287        EXAMPLES::
     288       
     289            sage: C = Composition([4,5,2]).fatter()
     290            sage: C.cardinality()
     291            4
     292            sage: list(C)
     293            [[4, 5, 2], [4, 7], [9, 2], [11]]
     294
     295        Some extreme cases::
     296       
     297            sage: list(Composition([5]).fatter())
     298            [[5]]
     299            sage: list(Composition([]).fatter())
     300            [[]]
     301            sage: list(Composition([1,1,1,1]).fatter()) == list(Compositions(4))
     302            True
     303        """
     304       
     305        return Compositions(len(self)).map(self.fatten)
     306
    306307    def refinement(self, co2):
    307308        """
    308309        Returns the refinement composition of self and co2.
    class Composition_class(CombinatorialObj 
    442443              filter(lambda x: x != 0, [l for l in reversed(inner)])])
    443444   
    444445
    445 
    446446##############################################################
    447447
    448448
    449449def 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     ::
     450    r"""
     451    Sets of integer Compositions
     452
     453    A composition `c` of a nonnegative integer `n` is a list of
     454    positive integers with total sum `n`.
     455
     456    See also: `Composition`, `Partitions`, `IntegerVectors`
     457
     458    EXAMPLES:
     459
     460    There are 8 compositions of 4::
     461
     462        sage: Compositions(4).cardinality()
     463        8
     464
     465    Here is the list of them::
     466
     467        sage: list(Compositions(4))
     468        [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]]
     469
     470    You can use the .first() method to get the 'first' composition of
     471    a number::
     472
     473        sage: Compositions(4).first()
     474        [1, 1, 1, 1]
     475
     476    You can also calculate the 'next' composition given the current
     477    one::
     478
     479        sage: Compositions(4).next([1,1,2])
     480        [1, 2, 1]
     481
     482
     483
     484    If `n` is not specified, this returns the combinatorial class of
     485    all (non-negative) integer compositions::
    457486   
    458487        sage: Compositions()
    459488        Compositions of non-negative integers
    def Compositions(n=None, **kwargs): 
    464493        sage: [-2,3,1] in Compositions()
    465494        False
    466495   
    467     If n is specified, it returns the class of compositions of n.
    468    
    469     ::
     496    If n is specified, it returns the class of compositions of n::
    470497   
    471498        sage: Compositions(3)
    472499        Compositions of 3
    473         sage: Compositions(3).list()
     500        sage: list(Compositions(3))
    474501        [[1, 1, 1], [1, 2], [2, 1], [3]]
    475502        sage: Compositions(3).cardinality()
    476503        4
     504
     505    The following examples shows how to test whether or not an object
     506    is a composition::
     507
     508        sage: [3,4] in Compositions()
     509        True
     510        sage: [3,4] in Compositions(7)
     511        True
     512        sage: [3,4] in Compositions(5)
     513        False
     514
     515    Similarly, one can check whether or not an object is a composition
     516    which satisfies further constraints::
     517
     518        sage: [4,2] in Compositions(6, inner=[2,2])
     519        True
     520        sage: [4,2] in Compositions(6, inner=[2,3])
     521        False
     522        sage: [4,1] in Compositions(5, inner=[2,1], max_slope = 0)
     523        True
     524
     525    Note that the given constraints should be compatible::
     526
     527        sage: [4,2] in Compositions(6, inner=[2,2], min_part=3) #
     528        True
     529
     530    The options length, min_length, and max_length can be used to set
     531    length constraints on the compositions. For example, the
     532    compositions of 4 of length equal to, at least, and at most 2 are
     533    given by::
     534
     535        sage: Compositions(4, length=2).list()
     536        [[3, 1], [2, 2], [1, 3]]
     537        sage: Compositions(4, min_length=2).list()
     538        [[3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
     539        sage: Compositions(4, max_length=2).list()
     540        [[4], [3, 1], [2, 2], [1, 3]]
     541
     542    Setting both min_length and max_length to the same value is
     543    equivalent to setting length to this value::
     544
     545        sage: Compositions(4, min_length=2, max_length=2).list()
     546        [[3, 1], [2, 2], [1, 3]]
     547
     548    The options inner and outer can be used to set part-by-part
     549    containment constraints. The list of compositions of 4 bounded
     550    above by [3,1,2] is given by::
     551
     552        sage: list(Compositions(4, outer=[3,1,2]))
     553        [[3, 1], [2, 1, 1], [1, 1, 2]]
     554
     555    Outer sets max_length to the length of its argument. Moreover, the
     556    parts of outer may be infinite to clear the constraint on specific
     557    parts. This is the list of compositions of 4 of length at most 3
     558    such that the first and third parts are at most 1::
     559
     560        sage: list(Compositions(4, outer=[1,oo,1]))
     561        [[1, 3], [1, 2, 1]]
     562
     563    This is the list of compositions of 4 bounded below by [1,1,1]::
     564
     565        sage: list(Compositions(4, inner=[1,1,1]))
     566        [[2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
     567
     568    The options min_slope and max_slope can be used to set constraints
     569    on the slope, that is the difference `p[i+1]-p[i]` of two
     570    consecutive parts. The following is the list of weakly increasing
     571    compositions of 4::
     572
     573        sage: Compositions(4, min_slope=0).list()
     574        [[4], [2, 2], [1, 3], [1, 1, 2], [1, 1, 1, 1]]
    477575   
    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,
     576    Here are the weakly decreasing ones::
     577
     578        sage: Compositions(4, max_slope=0).list()
     579        [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]]
     580
     581
     582    The following is the list of compositions of 4 such that two
     583    consecutive parts differ by at most one::
     584
     585        sage: Compositions(4, min_slope=-1, max_slope=1).list()
     586        [[4], [2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
     587
     588    The constraints can be combined together in all reasonable ways.
     589    This is the list of compositions of 5 of length between 2 and 4
     590    such that the difference between consecutive parts is between -2
     591    and 1::
     592
     593        sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4).list()
     594        [[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]]
     595
     596    We can do the same thing with an outer constraint::
     597
     598        sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4, outer=[2,5,2]).list()
     599        [[2, 3], [2, 2, 1], [2, 1, 2], [1, 2, 2]]
     600
     601    However, providing incoherent constraints may yield strange
     602    results. It is up to the user to ensure that the inner and outer
     603    compositions themselves satisfy the parts and slope constraints.
     604
     605    Note that if you specify min_part=0, then the objects produced may
     606    have parts equal to zero. This violates the internal assumptions
     607    that the Composition class makes. Use at your own risk, or
     608    preferably consider using `IntegerVectors` instead::
     609
     610        sage: list(Compositions(2, length=3, min_part=0))
     611        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!
     612        [[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]]
     613
     614        sage: list(IntegerVectors(2, 3))
     615        [[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]]
     616
     617    The generation algorithm is constant amortized time, and handled
     618    by the generic tool `IntegerListsLex`.
     619
     620    AUTHORS:
     621
     622    - Mike Hansen, Nicolas M. Thiery
     623
     624    - MuPAD-Combinat developers (for algorithms and design inspiration)
     625
     626    TESTS::
    482627   
    483     ::
     628        sage: C = Compositions(4, length=2)
     629        sage: C == loads(dumps(C))
     630        True
     631
     632        sage: Compositions(6, min_part=2, length=3)
     633        Compositions of the integer 6 satisfying constraints length=3, min_part=2
    484634   
    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]]
     635       
     636        sage: [2, 1] in Compositions(3, length=2)
     637        True
     638        sage: [2,1,2] in Compositions(5, min_part=1)
     639        True
     640        sage: [2,1,2] in Compositions(5, min_part=2)
     641        False
     642   
     643        sage: Compositions(4, length=2).cardinality()
     644        3
     645        sage: Compositions(4, min_length=2).cardinality()
     646        7
     647        sage: Compositions(4, max_length=2).cardinality()
     648        4
     649        sage: Compositions(4, max_part=2).cardinality()
     650        5
     651        sage: Compositions(4, min_part=2).cardinality()
     652        2
     653        sage: Compositions(4, outer=[3,1,2]).cardinality()
     654        3
     655       
     656        sage: Compositions(4, length=2).list()
     657        [[3, 1], [2, 2], [1, 3]]
     658        sage: Compositions(4, min_length=2).list()
     659        [[3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
     660        sage: Compositions(4, max_length=2).list()
     661        [[4], [3, 1], [2, 2], [1, 3]]
     662        sage: Compositions(4, max_part=2).list()
     663        [[2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
     664        sage: Compositions(4, min_part=2).list()
     665        [[4], [2, 2]]
     666        sage: Compositions(4, outer=[3,1,2]).list()
     667        [[3, 1], [2, 1, 1], [1, 1, 2]]
     668        sage: Compositions(4, outer=[1,oo,1]).list()
     669        [[1, 3], [1, 2, 1]]
     670        sage: Compositions(4, inner=[1,1,1]).list()
     671        [[2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
     672        sage: Compositions(4, min_slope=0).list()
     673        [[4], [2, 2], [1, 3], [1, 1, 2], [1, 1, 1, 1]]
     674        sage: Compositions(4, min_slope=-1, max_slope=1).list()
     675        [[4], [2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
     676        sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4).list()
     677        [[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]]
     678        sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4, outer=[2,5,2]).list()
     679        [[2, 3], [2, 2, 1], [2, 1, 2], [1, 2, 2]]
    489680    """
    490681    if n is None:
     682        assert(len(kwargs) == 0)
    491683        return Compositions_all()
    492684    else:
    493         if kwargs:
    494             return Compositions_constraints(n, **kwargs)
     685        if len(kwargs) == 0:
     686            if isinstance(n, (int,Integer)):
     687                return Compositions_n(n)
     688            else:
     689                raise ValueError, "n must be an integer"
    495690        else:
    496             return Compositions_n(n)
     691            # FIXME: should inherit from IntegerListLex, and implement repr, or _name as a lazy attribute
     692            kwargs['name'] = "Compositions of the integer %s satisfying constraints %s"%(n, ", ".join( ["%s=%s"%(key, kwargs[key]) for key in sorted(kwargs.keys())] ))
     693            kwargs['element_constructor'] = Composition_class
     694            if 'min_part' not in kwargs:
     695                kwargs['min_part'] = 1
     696            elif kwargs['min_part'] == 0:
     697                from warnings import warn
     698                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)
     699
     700            if 'outer' in kwargs:
     701                kwargs['ceiling'] = kwargs['outer']
     702                if 'max_length' in kwargs:
     703                    kwargs['max_length'] = min( len(kwargs['outer']), kwargs['max_length'])
     704                else:
     705                    kwargs['max_length'] = len(kwargs['outer'])
     706                del kwargs['outer']
     707
     708            if 'inner' in kwargs:
     709                inner = kwargs['inner']
     710                kwargs['floor'] = inner
     711                del kwargs['inner']
     712                # Should this be handled by integer lists lex?
     713                if 'min_length' in kwargs:
     714                    kwargs['min_length'] = max( len(inner), kwargs['min_length'])
     715                else:
     716                    kwargs['min_length'] = len(inner)
     717            return IntegerListsLex(n, **kwargs)
     718           
     719
     720# Allows to unpickle old constrained Compositions_constraints objects.             
     721class Compositions_constraints(IntegerListsLex):
     722    def __setstate__(self, data):
     723        """
     724        TESTS::
     725
     726            # dumps(Compositions(4, max_part=2))
     727            sage: pickle = 'x\x9ck`J.NLO\xd5K\xce\xcfM\xca\xccK,\x011\n\xf2\x8b3K2\xf3\xf3\xb8\x9c\x11\xec\xe2\xf8d QR\x94\x98\x99WR\xccU\xc8\xa8\xd9X\xc8T[\xc8\xac\x11\xca\x8d$^\xc8R[\xc8\x1a\xca\x91\x9bX\x11_\x90XTR\xc8\x061\xbb(3/\xbdX\x0f\xa8 5=\xb5\x88+71;5\x1e\xc6)d\x0fe4j\r*\xe4(\x0ee\xcc\xcb\x00rL\x80\x1c\xce\xd2$=\x00\xbd\xea5\xb2'
     728            sage: sp = loads(pickle); sp
     729            Integer lists of sum 4 satisfying certain constraints
     730            sage: sp.list()
     731            [[2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
     732        """
     733        n = data['n']
     734        self.__class__ = IntegerListsLex
     735        constraints = {
     736                       'min_part' : 1,
     737                       'element_constructor' : Composition_class}
     738        constraints.update(data['constraints'])
     739        self.__init__(n, **constraints)
    497740
    498741class Compositions_all(InfiniteAbstractCombinatorialClass):
    499742    def __init__(self):
    class Compositions_n(CombinatorialClass) 
    626869        return [Composition_class(r) for r in result]
    627870
    628871
    629 class Compositions_constraints(CombinatorialClass):
    630     object_class = Composition_class
    631872
    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
    642873
    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 
     874# Those belong to the Compositino class
    755875
    756876def from_descents(descents, nps=None):
    757877    """
  • sage/combinat/partition.py

    diff --git a/sage/combinat/partition.py b/sage/combinat/partition.py
    a b class Partitions_parts_in(CombinatorialC 
    32573257        given parts, or None if no such partition exists. This function
    32583258        is not intended to be called directly.
    32593259
    3260         INPUT::
     3260        INPUT:
    32613261
    32623262        - ``n``: nonnegative integer
    32633263        - ``parts``: a sorted list of positive integers.
  • 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 
    618617        sage: SkewPartitions(4, overlap=2)
    619618        Skew partitions of 4 with overlap of 2
    620619        sage: SkewPartitions(4, overlap=2).list()
    621         [[[2, 2], []], [[4], []]]
     620        [[[4], []], [[2, 2], []]]
    622621    """
    623622    number_of_arguments = 0
    624623    for arg in ['n', 'row_lengths']:
    class SkewPartitions_all(CombinatorialCl 
    731730        raise NotImplementedError
    732731
    733732class SkewPartitions_n(CombinatorialClass):
     733    """
     734    The combinatorial class of skew partitions with given size (and
     735    horizontal minimal overlap).
     736    """
    734737    def __init__(self, n, overlap=0):
    735738        """
     739        INPUT:
     740         - n: an non negative integer
     741         - overlap: an integer
     742       
     743        Returns the set of the skew partitions of ``n`` with overlap
     744        at least ``overlap``, and no empty row.
     745
     746        The iteration order is not specified yet.
     747
     748        Caveat: this set is stable under conjugation only for overlap=
     749        0 or 1. What exactly happens for negative overlaps is not yet
     750        well specified, and subject to change (we may want to
     751        introduce vertical overlap constraints as well). overlap would
     752        also better be named min_overlap.
     753
     754        Todo: as is, this set is essentially the composition of
     755        Compositions(n) (which give the row lengths) and
     756        SkewPartition(n, row_lengths=...), and one would want to
     757        "inherit" list and cardinality from this composition.
     758
    736759        TESTS::
    737760       
    738761            sage: S = SkewPartitions(3)
    class SkewPartitions_n(CombinatorialClas 
    802825        Returns the number of skew partitions related to the composition co
    803826        by 'sliding'. The composition co is the list of row lengths of the
    804827        skew partition.
     828
     829        Todo: this should be a method of SkewPartition
    805830       
    806831        EXAMPLES::
    807832       
    class SkewPartitions_n(CombinatorialClas 
    852877            return 1
    853878
    854879        if overlap > 0:
    855             gg = sage.combinat.composition.Compositions(n, min_part = overlap)
     880            gg = sage.combinat.composition.Compositions(n, min_part = max(1, overlap))
    856881        else:
    857882            gg = sage.combinat.composition.Compositions(n)
    858883
    class SkewPartitions_n(CombinatorialClas 
    862887
    863888        return sum_a
    864889
    865     def list(self):
     890    def __iter__(self):
    866891        """
    867892        Returns a list of the skew partitions of n.
    868        
     893
    869894        EXAMPLES::
    870895       
    871896            sage: SkewPartitions(3).list()
    872             [[[1, 1, 1], []],
    873              [[2, 2, 1], [1, 1]],
    874              [[2, 1, 1], [1]],
    875              [[3, 2, 1], [2, 1]],
    876              [[2, 2], [1]],
    877              [[3, 2], [2]],
    878              [[2, 1], []],
    879              [[3, 1], [1]],
    880              [[3], []]]
     897            [[[3], []],
     898            [[2, 1], []],
     899            [[3, 1], [1]],
     900            [[2, 2], [1]],
     901            [[3, 2], [2]],
     902            [[1, 1, 1], []],
     903            [[2, 2, 1], [1, 1]],
     904            [[2, 1, 1], [1]],
     905            [[3, 2, 1], [2, 1]]]
     906
     907
    881908            sage: SkewPartitions(3, overlap=0).list()
    882             [[[1, 1, 1], []],
    883              [[2, 2, 1], [1, 1]],
    884              [[2, 1, 1], [1]],
    885              [[3, 2, 1], [2, 1]],
    886              [[2, 2], [1]],
    887              [[3, 2], [2]],
    888              [[2, 1], []],
    889              [[3, 1], [1]],
    890              [[3], []]]
     909            [[[3], []],
     910            [[2, 1], []],
     911            [[3, 1], [1]],
     912            [[2, 2], [1]],
     913            [[3, 2], [2]],
     914            [[1, 1, 1], []],
     915            [[2, 2, 1], [1, 1]],
     916            [[2, 1, 1], [1]],
     917            [[3, 2, 1], [2, 1]]]
    891918            sage: SkewPartitions(3, overlap=1).list()
    892             [[[1, 1, 1], []], [[2, 2], [1]], [[2, 1], []], [[3], []]]
     919            [[[3], []], [[2, 1], []], [[2, 2], [1]], [[1, 1, 1], []]]
    893920            sage: SkewPartitions(3, overlap=2).list()
    894921            [[[3], []]]
    895922            sage: SkewPartitions(3, overlap=3).list()
    class SkewPartitions_n(CombinatorialClas 
    900927        n = self.n
    901928        overlap = self.overlap
    902929
    903         result = []
    904         for co in sage.combinat.composition.Compositions(n, min_part=overlap).list():
    905             result += SkewPartitions(row_lengths=co, overlap=overlap).list()
    906 
    907         return result
     930        for co in sage.combinat.composition.Compositions(n, min_part = max(1, overlap)):
     931            for sp in SkewPartitions(row_lengths=co, overlap=overlap):
     932                yield sp
    908933   
    909934######################################
    910935# 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 
    719719            True
    720720            sage: it = iter(StandardSkewTableaux())    # indirect doctest
    721721            sage: [it.next() for i in range(10)]
    722             [[], [[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]]]
     722            [[], [[1]], [[1, 2]], [[1], [2]], [[None, 1], [2]], [[None, 2], [1]], [[1, 2, 3]], [[1, 2], [3]], [[1, 3], [2]], [[None, 1, 2], [3]]]
    723723        """
    724724        return StandardSkewTableaux_n(n)
    725725
    class StandardSkewTableaux_n(Combinatori 
    767767        EXAMPLES::
    768768       
    769769            sage: StandardSkewTableaux(2).list() #indirect doctest
    770             [[[1], [2]], [[None, 1], [2]], [[None, 2], [1]], [[1, 2]]]
     770            [[[1, 2]], [[1], [2]], [[None, 1], [2]], [[None, 2], [1]]]
     771
     772            sage: StandardSkewTableaux(3).list() #indirect doctest
     773            [[[1, 2, 3]],
     774             [[1, 2], [3]], [[1, 3], [2]],
     775             [[None, 1, 2], [3]], [[None, 1, 3], [2]],
     776             [[None, 2, 3], [1]],
     777             [[None, 1], [2, 3]], [[None, 2], [1, 3]],
     778             [[None, None, 1], [2, 3]], [[None, None, 2], [1, 3]], [[None, None, 3], [1, 2]],
     779             [[1], [2], [3]],
     780             [[None, 1], [None, 2], [3]], [[None, 1], [None, 3], [2]], [[None, 2], [None, 3], [1]],
     781             [[None, 1], [2], [3]], [[None, 2], [1], [3]], [[None, 3], [1], [2]],
     782             [[None, None, 1], [None, 2], [3]], [[None, None, 1], [None, 3], [2]],
     783             [[None, None, 2], [None, 1], [3]], [[None, None, 3], [None, 1], [2]],
     784             [[None, None, 2], [None, 3], [1]], [[None, None, 3], [None, 2], [1]]]
    771785        """
    772786        for skp in skew_partition.SkewPartitions(self.n):
    773787            for sst in StandardSkewTableaux_skewpartition(skp):
    class SemistandardSkewTableaux_n(Combina 
    944958        EXAMPLES::
    945959       
    946960            sage: SemistandardSkewTableaux(2).list() # indirect doctest
    947             [[[1], [2]],
     961            [[[1, 1]],
     962             [[1, 2]],
     963             [[2, 2]],
     964             [[1], [2]],
    948965             [[None, 1], [1]],
    949966             [[None, 2], [1]],
    950967             [[None, 1], [2]],
    951              [[None, 2], [2]],
    952              [[1, 1]],
    953              [[1, 2]],
    954              [[2, 2]]]
     968             [[None, 2], [2]]]
    955969        """
    956970        for p in skew_partition.SkewPartitions(self.n):
    957971            for ssst in SemistandardSkewTableaux_p(p):
    class SemistandardSkewTableaux_nmu(Combi 
    9951009        EXAMPLES::
    9961010       
    9971011            sage: SemistandardSkewTableaux(2,[1,1]).list() # indirect doctest
    998             [[[1], [2]], [[None, 2], [1]], [[None, 1], [2]], [[1, 2]]]
     1012            [[[1, 2]], [[1], [2]], [[None, 2], [1]], [[None, 1], [2]]]
    9991013        """       
    10001014        for p in skew_partition.SkewPartitions(self.n):
    10011015            for ssst in SemistandardSkewTableaux_pmu(p, self.mu):