Ticket #12453: trac_12453-refactor_integer_vectors-ts.patch

File trac_12453-refactor_integer_vectors-ts.patch, 82.6 KB (added by tscrim, 6 years ago)
  • sage/combinat/integer_vector.py

    # HG changeset patch
    # User Travis Scrimshaw <tscrim@ucdavis.edu>
    # Date 1361507744 28800
    # Node ID 885787392cf69885be31468836afe85f0188157f
    # Parent 7bf8980143c47c079b69b6640259a09704f13e53
    #12453: Refactored IntegerVectors to use ClonableIntArray.
    
    diff --git a/sage/combinat/integer_vector.py b/sage/combinat/integer_vector.py
    a b  
    33
    44AUTHORS:
    55
    6  *   Mike Hanson (2007) - original module
    7  *   Nathann Cohen, David Joyner (2009-2010) - Gale-Ryser stuff
    8  *   Nathann Cohen, David Joyner (2011) - Gale-Ryser bugfix
    9  *   Travis Scrimshaw (2012-05-12) - Updated doc-strings to tell the user of
    10      that the class's name is a misnomer (that they only contains non-negative
    11      entries).
     6* Mike Hanson (2007) - original module
     7* Nathann Cohen, David Joyner (2009-2010) - Gale-Ryser stuff
     8* Nathann Cohen, David Joyner (2011) - Gale-Ryser bugfix
     9* Travis Scrimshaw (2012-05-12) - Updated doc-strings to tell the user of
     10  that the class's name is a misnomer (that they only contains non-negative
     11  entries).
     12* Travis Scrimshaw (2013-02-04) - Refactored to use ``ClonableIntArray``
    1213"""
    1314#*****************************************************************************
    1415#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,
    AUTHORS: 
    2627#                  http://www.gnu.org/licenses/
    2728#*****************************************************************************
    2829
    29 from combinat import CombinatorialClass
    30 from __builtin__ import list as builtinlist
    31 from sage.rings.integer import Integer
    32 from sage.rings.arith import binomial
    3330import misc
    34 from sage.rings.infinity import PlusInfinity
    3531import integer_list
    3632import cartesian_product
    3733import functools
    3834
     35from sage.structure.parent import Parent
     36from sage.structure.unique_representation import UniqueRepresentation
     37from sage.structure.list_clone import ClonableIntArray
     38from sage.misc.classcall_metaclass import ClasscallMetaclass
     39
     40from sage.categories.enumerated_sets import EnumeratedSets
     41from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
     42from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
     43from sage.rings.infinity import PlusInfinity, MinusInfinity
     44from sage.rings.arith import binomial
     45from sage.rings.all import NN, ZZ
     46from sage.rings.integer import Integer
    3947
    4048def is_gale_ryser(r,s):
    4149    r"""
    def is_gale_ryser(r,s): 
    7179      which does not alter the columns (resp. rows) sums.
    7280
    7381    We can then assume that `r` and `s` are partitions
    74     (see the corresponding class ``Partition``)
     82    (see the corresponding class :class:`Partition`)
    7583
    7684    If `r^*` denote the conjugate of `r`, the Gale-Ryser theorem
    7785    asserts that a binary Matrix satisfying the constraints exists
    78     if and only if `s\preceq r^*`, where `\preceq` denotes
     86    if and only if `s \preceq r^*`, where `\preceq` denotes
    7987    the domination order on partitions.
    8088
    8189    EXAMPLES::
    def is_gale_ryser(r,s): 
    110118    rstar = Partition(r2).conjugate()
    111119
    112120    #                                same number of 1s           domination
    113     return len(rstar) <= len(s2) and  sum(r2) == sum(s2) and rstar.dominates(s)
     121    return len(rstar) <= len(s2) and sum(r2) == sum(s2) and rstar.dominates(s)
    114122
    115123def _slider01(A, t, k, p1, p2, fixedcols=[]):
    116124    r"""
    def _slider01(A, t, k, p1, p2, fixedcols 
    119127    returns a matrix `B` which is the same as `A` except that it
    120128    has slid `t` of the `1` in each of these rows of `A`
    121129    over towards the `k`-th column. Care must be taken when the
    122     last leading 1 is in column >=k. It avoids those in columns
     130    last leading 1 is in column `\geq k`. It avoids those in columns
    123131    listed in fixedcols.
    124132
    125     This is a 'private' function for use in gale_ryser_theorem.
     133    This is a 'private' function for use in :func:`gale_ryser_theorem`.
    126134
    127135    INPUT:
    128136
    129     - ``A`` -- an `m\times n` (0,1) matrix
     137    - ``A`` -- an `m \times n` `(0,1)`-matrix
     138
    130139    - ``t``, ``k`` -- integers satisfying `0 < t < m`, `0 < k < n`
     140
    131141    - ``fixedcols`` -- those columns (if any) whose entries
    132                        aren't permitted to slide
     142      aren't permitted to slide
    133143
    134144    OUTPUT:
    135145
    136     An `m\times n` (0,1) matrix, which is the same as `A` except
     146    An `m \times n` `(0,1)`-matrix, which is the same as `A` except
    137147    that it has exactly one `1` in `A` slid over to the `k`-th
    138148    column.
    139149
    def _slider01(A, t, k, p1, p2, fixedcols 
    193203    return matrix(B)
    194204
    195205def gale_ryser_theorem(p1, p2, algorithm="gale"):
    196         r"""
    197         Returns the binary matrix given by the Gale-Ryser theorem.
     206    r"""
     207    Returns the binary matrix given by the Gale-Ryser theorem.
    198208
    199         The Gale Ryser theorem asserts that if `p_1,p_2` are two
    200         partitions of `n` of respective lengths `k_1,k_2`, then there is
    201         a binary `k_1\times k_2` matrix `M` such that `p_1` is the vector
    202         of row sums and `p_2` is the vector of column sums of `M`, if
    203         and only if the conjugate of `p_2` dominates `p_1`.
     209    The Gale Ryser theorem asserts that if `p_1,p_2` are two
     210    partitions of `n` of respective lengths `k_1,k_2`, then there is
     211    a binary `k_1\times k_2` matrix `M` such that `p_1` is the vector
     212    of row sums and `p_2` is the vector of column sums of `M`, if
     213    and only if the conjugate of `p_2` dominates `p_1`.
    204214
    205         INPUT:
     215    INPUT:
    206216
    207         - ``p1, p2``-- list of integers representing the vectors
    208           of row/column sums
     217    - ``p1, p2``-- list of integers representing the vectors
     218      of row/column sums
    209219
    210         - ``algorithm`` -- two possible string values :
     220    - ``algorithm`` -- two possible string values:
    211221
    212             - ``"ryser"`` implements the construction due
    213               to Ryser [Ryser63]_.
     222      - ``'ryser'`` implements the construction due
     223        to Ryser [Ryser63]_.
     224      - ``'gale'`` (default) implements the construction due to Gale [Gale57]_.
    214225
    215             - ``"gale"`` (default) implements the construction due to Gale [Gale57]_.
     226    OUTPUT:
    216227
    217         OUTPUT:
     228    A binary matrix if it exists, ``None`` otherwise.
    218229
    219         - A binary matrix if it exists, ``None`` otherwise.
     230    Gale's Algorithm:
    220231
    221         Gale's Algorithm:
     232    (Gale [Gale57]_): A matrix satisfying the constraints of its
     233    sums can be defined as the solution of the following
     234    Linear Program, which Sage knows how to solve.
    222235
    223         (Gale [Gale57]_): A matrix satisfying the constraints of its
    224         sums can be defined as the solution of the following
    225         Linear Program, which Sage knows how to solve.
     236    .. MATH::
    226237
    227         .. MATH::
     238        \forall i&\sum_{j=1}^{k_2} b_{i,j}=p_{1,j}\\
     239        \forall i&\sum_{j=1}^{k_1} b_{j,i}=p_{2,j}\\
     240        &b_{i,j}\mbox{ is a binary variable}
    228241
    229             \forall i&\sum_{j=1}^{k_2} b_{i,j}=p_{1,j}\\
    230             \forall i&\sum_{j=1}^{k_1} b_{j,i}=p_{2,j}\\
    231             &b_{i,j}\mbox{ is a binary variable}
     242    Ryser's Algorithm:
    232243
    233         Ryser's Algorithm:
     244    (Ryser [Ryser63]_): The construction of an `m\times n` matrix `A=A_{r,s}`,
     245    due to Ryser, is described as follows. The
     246    construction works if and only if have `s\preceq r^*`.
    234247
    235         (Ryser [Ryser63]_): The construction of an `m\times n` matrix `A=A_{r,s}`,
    236         due to Ryser, is described as follows. The
    237         construction works if and only if have `s\preceq r^*`.
     248    * Construct the `m\times n` matrix `B` from `r` by defining
     249      the `i`-th row of `B` to be the vector whose first `r_i`
     250      entries are `1`, and the remainder are 0's, `1\leq i\leq
     251      m`.  This maximal matrix `B` with row sum `r` and ones left
     252      justified has column sum `r^{*}`.
    238253
    239         * Construct the `m\times n` matrix `B` from `r` by defining
    240           the `i`-th row of `B` to be the vector whose first `r_i`
    241           entries are `1`, and the remainder are 0's, `1\leq i\leq
    242           m`.  This maximal matrix `B` with row sum `r` and ones left
    243           justified has column sum `r^{*}`.
     254    * Shift the last `1` in certain rows of `B` to column `n` in
     255      order to achieve the sum `s_n`.  Call this `B` again.
    244256
    245         * Shift the last `1` in certain rows of `B` to column `n` in
    246           order to achieve the sum `s_n`.  Call this `B` again.
     257      * The `1`'s in column n are to appear in those
     258        rows in which `A` has the largest row sums, giving
     259        preference to the bottom-most positions in case of ties.
     260      * Note: When this step automatically "fixes" other columns,
     261        one must skip ahead to the first column index
     262        with a wrong sum in the step below.
    247263
    248           * The `1`'s in column n are to appear in those
    249             rows in which `A` has the largest row sums, giving
    250             preference to the bottom-most positions in case of ties.
    251           * Note: When this step automatically "fixes" other columns,
    252             one must skip ahead to the first column index
    253             with a wrong sum in the step below.
     264    * Proceed inductively to construct columns `n-1`, ..., `2`, `1`.
    254265
    255         * Proceed inductively to construct columns `n-1`, ..., `2`, `1`.
     266    * Set `A = B`. Return `A`.
    256267
    257         * Set `A = B`. Return `A`.
     268    EXAMPLES:
    258269
    259         EXAMPLES:
     270    Computing the matrix for `p_1=p_2=2+2+1`::
    260271
    261         Computing the matrix for `p_1=p_2=2+2+1` ::
     272        sage: from sage.combinat.integer_vector import gale_ryser_theorem
     273        sage: p1 = [2,2,1]
     274        sage: p2 = [2,2,1]
     275        sage: print gale_ryser_theorem(p1, p2)     # not tested
     276        [1 1 0]
     277        [1 0 1]
     278        [0 1 0]       
     279        sage: A = gale_ryser_theorem(p1, p2)
     280        sage: rs = [sum(x) for x in A.rows()]
     281        sage: cs = [sum(x) for x in A.columns()]
     282        sage: p1 == rs; p2 == cs
     283        True
     284        True
    262285
    263             sage: from sage.combinat.integer_vector import gale_ryser_theorem
    264             sage: p1 = [2,2,1]
    265             sage: p2 = [2,2,1]
    266             sage: print gale_ryser_theorem(p1, p2)     # not tested
    267             [1 1 0]
    268             [1 0 1]
    269             [0 1 0]       
    270             sage: A = gale_ryser_theorem(p1, p2)
    271             sage: rs = [sum(x) for x in A.rows()]
    272             sage: cs = [sum(x) for x in A.columns()]
    273             sage: p1 == rs; p2 == cs
    274             True
    275             True
     286    Or for a non-square matrix with `p_1=3+3+2+1` and `p_2=3+2+2+1+1`,
     287    using Ryser's algorithm::
    276288
    277         Or for a non-square matrix with `p_1=3+3+2+1` and `p_2=3+2+2+1+1`, using Ryser's algorithm ::
     289        sage: from sage.combinat.integer_vector import gale_ryser_theorem
     290        sage: p1 = [3,3,1,1]
     291        sage: p2 = [3,3,1,1]
     292        sage: gale_ryser_theorem(p1, p2, algorithm = "ryser")
     293        [1 1 0 1]
     294        [1 1 1 0]
     295        [0 1 0 0]
     296        [1 0 0 0]
     297        sage: p1 = [4,2,2]
     298        sage: p2 = [3,3,1,1]
     299        sage: gale_ryser_theorem(p1, p2, algorithm = "ryser")
     300        [1 1 1 1]
     301        [1 1 0 0]
     302        [1 1 0 0]
     303        sage: p1 = [4,2,2,0]
     304        sage: p2 = [3,3,1,1,0,0]
     305        sage: gale_ryser_theorem(p1, p2, algorithm = "ryser")
     306        [1 1 1 1 0 0]
     307        [1 1 0 0 0 0]
     308        [1 1 0 0 0 0]
     309        [0 0 0 0 0 0]
     310        sage: p1 = [3,3,2,1]
     311        sage: p2 = [3,2,2,1,1]
     312        sage: print gale_ryser_theorem(p1, p2, algorithm="gale")  # not tested
     313        [1 1 1 0 0]
     314        [1 1 0 0 1]
     315        [1 0 1 0 0]
     316        [0 0 0 1 0]
    278317
    279             sage: from sage.combinat.integer_vector import gale_ryser_theorem
    280             sage: p1 = [3,3,1,1]
    281             sage: p2 = [3,3,1,1]
    282             sage: gale_ryser_theorem(p1, p2, algorithm = "ryser")
    283             [1 1 0 1]
    284             [1 1 1 0]
    285             [0 1 0 0]
    286             [1 0 0 0]
    287             sage: p1 = [4,2,2]
    288             sage: p2 = [3,3,1,1]
    289             sage: gale_ryser_theorem(p1, p2, algorithm = "ryser")
    290             [1 1 1 1]
    291             [1 1 0 0]
    292             [1 1 0 0]       
    293             sage: p1 = [4,2,2,0]
    294             sage: p2 = [3,3,1,1,0,0]
    295             sage: gale_ryser_theorem(p1, p2, algorithm = "ryser")
    296             [1 1 1 1 0 0]
    297             [1 1 0 0 0 0]
    298             [1 1 0 0 0 0]
    299             [0 0 0 0 0 0]
    300             sage: p1 = [3,3,2,1]
    301             sage: p2 = [3,2,2,1,1]
    302             sage: print gale_ryser_theorem(p1, p2, algorithm="gale")  # not tested
    303             [1 1 1 0 0]
    304             [1 1 0 0 1]
    305             [1 0 1 0 0]
    306             [0 0 0 1 0]
     318    With `0` in the sequences, and with unordered inputs::
    307319
    308         With `0` in the sequences, and with unordered inputs ::
     320        sage: from sage.combinat.integer_vector import gale_ryser_theorem
     321        sage: gale_ryser_theorem([3,3,0,1,1,0], [3,1,3,1,0], algorithm = "ryser")   
     322        [1 0 1 1 0]
     323        [1 1 1 0 0]
     324        [0 0 0 0 0]
     325        [0 0 1 0 0]
     326        [1 0 0 0 0]
     327        [0 0 0 0 0]
     328        sage: p1 = [3,1,1,1,1]; p2 = [3,2,2,0]
     329        sage: gale_ryser_theorem(p1, p2, algorithm = "ryser")                           
     330        [1 1 1 0]
     331        [0 0 1 0]
     332        [0 1 0 0]
     333        [1 0 0 0]
     334        [1 0 0 0]
    309335
    310             sage: from sage.combinat.integer_vector import gale_ryser_theorem
    311             sage: gale_ryser_theorem([3,3,0,1,1,0], [3,1,3,1,0], algorithm = "ryser")   
    312             [1 0 1 1 0]
    313             [1 1 1 0 0]
    314             [0 0 0 0 0]
    315             [0 0 1 0 0]
    316             [1 0 0 0 0]
    317             [0 0 0 0 0]
    318             sage: p1 = [3,1,1,1,1]; p2 = [3,2,2,0]
    319             sage: gale_ryser_theorem(p1, p2, algorithm = "ryser")                           
    320             [1 1 1 0]
    321             [0 0 1 0]
    322             [0 1 0 0]
    323             [1 0 0 0]
    324             [1 0 0 0]
     336    TESTS:
    325337
    326         TESTS:
     338    This test created a random bipartite graph on `n+m` vertices. Its
     339    adjacency matrix is binary, and it is used to create some
     340    "random-looking" sequences which correspond to an existing matrix. The
     341    ``gale_ryser_theorem`` is then called on these sequences, and the output
     342    checked for correction.::
    327343
    328         This test created a random bipartite graph on `n+m` vertices. Its
    329         adjacency matrix is binary, and it is used to create some
    330         "random-looking" sequences which correspond to an existing matrix. The
    331         ``gale_ryser_theorem`` is then called on these sequences, and the output
    332         checked for correction.::
     344        sage: def test_algorithm(algorithm, low = 10, high = 50):
     345        ....:    n,m = randint(low,high), randint(low,high)
     346        ....:    g = graphs.RandomBipartite(n, m, .3)
     347        ....:    s1 = sorted(g.degree([(0,i) for i in range(n)]), reverse = True)
     348        ....:    s2 = sorted(g.degree([(1,i) for i in range(m)]), reverse = True)
     349        ....:    m = gale_ryser_theorem(s1, s2, algorithm = algorithm)
     350        ....:    ss1 = sorted(map(lambda x : sum(x) , m.rows()), reverse = True)
     351        ....:    ss2 = sorted(map(lambda x : sum(x) , m.columns()), reverse = True)
     352        ....:    if ((ss1 == s1) and (ss2 == s2)):
     353        ....:        return True
     354        ....:    return False
    333355
    334             sage: def test_algorithm(algorithm, low = 10, high = 50):
    335             ...      n,m = randint(low,high), randint(low,high)
    336             ...      g = graphs.RandomBipartite(n, m, .3)
    337             ...      s1 = sorted(g.degree([(0,i) for i in range(n)]), reverse = True)
    338             ...      s2 = sorted(g.degree([(1,i) for i in range(m)]), reverse = True)
    339             ...      m = gale_ryser_theorem(s1, s2, algorithm = algorithm)
    340             ...      ss1 = sorted(map(lambda x : sum(x) , m.rows()), reverse = True)
    341             ...      ss2 = sorted(map(lambda x : sum(x) , m.columns()), reverse = True)
    342             ...      if ((ss1 == s1) and (ss2 == s2)):
    343             ...          return True
    344             ...      return False
     356        sage: for algorithm in ["gale", "ryser"]:                            # long time
     357        ....:    for i in range(50):                                         # long time
     358        ....:       if not test_algorithm(algorithm, 3, 10):                 # long time
     359        ....:           print "Something wrong with algorithm ", algorithm   # long time
     360        ....:           break                                                # long time
    345361
    346             sage: for algorithm in ["gale", "ryser"]:                            # long time
    347             ...      for i in range(50):                                         # long time
    348             ...         if not test_algorithm(algorithm, 3, 10):                 # long time
    349             ...             print "Something wrong with algorithm ", algorithm   # long time
    350             ...             break                                                # long time
     362    Null matrix::
    351363
    352         Null matrix::
     364        sage: gale_ryser_theorem([0,0,0],[0,0,0,0], algorithm="gale")
     365        [0 0 0 0]
     366        [0 0 0 0]
     367        [0 0 0 0]
     368        sage: gale_ryser_theorem([0,0,0],[0,0,0,0], algorithm="ryser")
     369        [0 0 0 0]
     370        [0 0 0 0]
     371        [0 0 0 0]
    353372
    354             sage: gale_ryser_theorem([0,0,0],[0,0,0,0], algorithm="gale")
    355             [0 0 0 0]
    356             [0 0 0 0]
    357             [0 0 0 0]
    358             sage: gale_ryser_theorem([0,0,0],[0,0,0,0], algorithm="ryser")
    359             [0 0 0 0]
    360             [0 0 0 0]
    361             [0 0 0 0]
     373    REFERENCES:
    362374
    363         REFERENCES:
     375    ..  [Ryser63] H. J. Ryser, Combinatorial Mathematics,
     376        Carus Monographs, MAA, 1963.
     377    ..  [Gale57] D. Gale, A theorem on flows in networks, Pacific J. Math.
     378        7(1957)1073-1082.
     379    """
     380    from sage.combinat.partition import Partition
     381    from sage.matrix.constructor import matrix
    364382
    365         ..  [Ryser63] H. J. Ryser, Combinatorial Mathematics,
    366                 Carus Monographs, MAA, 1963.
    367         ..  [Gale57] D. Gale, A theorem on flows in networks, Pacific J. Math.
    368                 7(1957)1073-1082.
    369         """
    370         from sage.combinat.partition import Partition
    371         from sage.matrix.constructor import matrix
     383    if not(is_gale_ryser(p1,p2)):
     384        return False
    372385
    373         if not(is_gale_ryser(p1,p2)):
    374             return False
     386    if algorithm=="ryser": # ryser's algorithm
     387        from sage.combinat.permutation import Permutation
    375388
    376         if algorithm=="ryser": # ryser's algorithm
    377             from sage.combinat.permutation import Permutation
     389        # Sorts the sequences if they are not, and remembers the permutation
     390        # applied
     391        tmp = sorted(enumerate(p1), reverse=True, key=lambda x:x[1])
     392        r = [x[1] for x in tmp if x[1]>0]
     393        r_permutation = [x-1 for x in Permutation([x[0]+1 for x in tmp]).inverse()]
     394        m = len(r)
    378395
    379             # Sorts the sequences if they are not, and remembers the permutation
    380             # applied
    381             tmp = sorted(enumerate(p1), reverse=True, key=lambda x:x[1])
    382             r = [x[1] for x in tmp if x[1]>0]
    383             r_permutation = [x-1 for x in Permutation([x[0]+1 for x in tmp]).inverse()]
    384             m = len(r)
     396        tmp = sorted(enumerate(p2), reverse=True, key=lambda x:x[1])
     397        s = [x[1] for x in tmp if x[1]>0]
     398        s_permutation = [x-1 for x in Permutation([x[0]+1 for x in tmp]).inverse()]
     399        n = len(s)
    385400
    386             tmp = sorted(enumerate(p2), reverse=True, key=lambda x:x[1])
    387             s = [x[1] for x in tmp if x[1]>0]
    388             s_permutation = [x-1 for x in Permutation([x[0]+1 for x in tmp]).inverse()]
    389             n = len(s)
     401        A0 = matrix([[1]*r[j]+[0]*(n-r[j]) for j in range(m)])
    390402
    391             A0 = matrix([[1]*r[j]+[0]*(n-r[j]) for j in range(m)])
     403        for k in range(1,n+1):
     404            goodcols = [i for i in range(n) if s[i]==sum(A0.column(i))]
     405            if sum(A0.column(n-k))<>s[n-k]:
     406                A0 = _slider01(A0,s[n-k],n-k, p1, p2, goodcols)
    392407
    393             for k in range(1,n+1):
    394                 goodcols = [i for i in range(n) if s[i]==sum(A0.column(i))]
    395                 if sum(A0.column(n-k))<>s[n-k]:
    396                     A0 = _slider01(A0,s[n-k],n-k, p1, p2, goodcols)
     408        # If we need to add empty rows/columns
     409        if len(p1) != m:
     410            A0 = A0.stack(matrix([[0]*n]*(len(p1)-m)))
    397411
    398             # If we need to add empty rows/columns
    399             if len(p1)!=m:
    400                 A0 = A0.stack(matrix([[0]*n]*(len(p1)-m)))
     412        if len(p2) != n:
     413            A0 = A0.transpose().stack(matrix([[0]*len(p1)]*(len(p2)-n))).transpose()
     414           
     415        # Applying the permutations to get a matrix satisfying the
     416        # order given by the input
     417        A0 = A0.matrix_from_rows_and_columns(r_permutation, s_permutation)
     418        return A0   
    401419
    402             if len(p2)!=n:
    403                 A0 = A0.transpose().stack(matrix([[0]*len(p1)]*(len(p2)-n))).transpose()
    404                
    405             # Applying the permutations to get a matrix satisfying the
    406             # order given by the input
    407             A0 = A0.matrix_from_rows_and_columns(r_permutation, s_permutation)
    408             return A0   
     420    if algorithm == "gale":
     421        from sage.numerical.mip import MixedIntegerLinearProgram
     422        k1, k2=len(p1), len(p2)
     423        p = MixedIntegerLinearProgram()
     424        b = p.new_variable(dim=2)
     425        for (i,c) in enumerate(p1):
     426            p.add_constraint(p.sum([b[i][j] for j in xrange(k2)]),min=c,max=c)
     427        for (i,c) in enumerate(p2):
     428            p.add_constraint(p.sum([b[j][i] for j in xrange(k1)]),min=c,max=c)
     429        p.set_objective(None)
     430        p.set_binary(b)
     431        p.solve()
     432        b = p.get_values(b)
     433        M = [[0]*k2 for i in xrange(k1)]
     434        for i in xrange(k1):
     435          for j in xrange(k2):
     436              M[i][j] = int(b[i][j])
     437        return matrix(M)
    409438
    410         elif algorithm == "gale":
    411           from sage.numerical.mip import MixedIntegerLinearProgram
    412           k1, k2=len(p1), len(p2)
    413           p = MixedIntegerLinearProgram()
    414           b = p.new_variable(dim=2)
    415           for (i,c) in enumerate(p1):
    416               p.add_constraint(p.sum([b[i][j] for j in xrange(k2)]),min=c,max=c)
    417           for (i,c) in enumerate(p2):
    418               p.add_constraint(p.sum([b[j][i] for j in xrange(k1)]),min=c,max=c)
    419           p.set_objective(None)
    420           p.set_binary(b)
    421           p.solve()
    422           b = p.get_values(b)
    423           M = [[0]*k2 for i in xrange(k1)]
    424           for i in xrange(k1):
    425               for j in xrange(k2):
    426                   M[i][j] = int(b[i][j])
    427           return matrix(M)
    428 
    429         else:
    430             raise ValueError("The only two algorithms available are \"gale\" and \"ryser\"")
     439    raise ValueError("The only two algorithms available are \"gale\" and \"ryser\"")
    431440
    432441def _default_function(l, default, i):
    433442    """
    434443    EXAMPLES::
    435    
     444
    436445        sage: from sage.combinat.integer_vector import _default_function
    437446        sage: import functools
    438447        sage: f = functools.partial(_default_function, [1,2,3], 99)
    def _default_function(l, default, i): 
    453462        return l[i-1]
    454463    except IndexError:
    455464        return default
    456    
    457 infinity = PlusInfinity()
     465
    458466def list2func(l, default=None):
    459467    """
    460     Given a list l, return a function that takes in a value i and
    461     return l[i-1]. If default is not None, then the function will
    462     return the default value for out of range i's.
    463    
     468    Given a list ``l``, return a function that takes in a value ``i`` and
     469    return ``l[i-1]``. If default is not ``None``, then the function will
     470    return the default value for out of range ``i``'s.
     471
    464472    EXAMPLES::
    465    
     473
    466474        sage: f = sage.combinat.integer_vector.list2func([1,2,3])
    467475        sage: f(1)
    468476        1
    def list2func(l, default=None): 
    487495        return lambda i: l[i-1]
    488496    else:
    489497        return functools.partial(_default_function, l, default)
    490 
    491498       
    492499def constant_func(i):
    493500    """
    494     Returns the constant function i.
    495    
     501    Return the constant function ``i``.
     502
    496503    EXAMPLES::
    497    
     504
    498505        sage: f = sage.combinat.integer_vector.constant_func(3)
     506        doctest:...: DeprecationWarning: constant_func is deprecated. Use lambda x: i instead
     507        See http://trac.sagemath.org/12453 for details.
    499508        sage: f(-1)
    500509        3
    501510        sage: f('asf')
    502511        3
    503512    """
     513    from sage.misc.superseded import deprecation
     514    deprecation(12453, 'constant_func is deprecated. Use lambda x: i instead')
    504515    return lambda x: i
    505516
    506 def IntegerVectors(n=None, k=None, **kwargs):
     517class IntegerVector(ClonableIntArray):
    507518    """
    508     Returns the combinatorial class of (non-negative) integer vectors.
    509    
    510     NOTE - These integer vectors are non-negative.
    511    
    512     EXAMPLES: If n is not specified, it returns the class of all
    513     integer vectors.
    514    
    515     ::
    516    
     519    An integer vector.
     520    """
     521    def check(self):
     522        """
     523        Check to make sure this is a valid integer vector by making sure
     524        all entries are non-negative.
     525
     526        EXAMPLES::
     527
     528            sage: IV = IntegerVectors()
     529            sage: elt = IV([1,2,1])
     530            sage: elt.check()
     531        """
     532        if any(x < 0 for x in self):
     533            raise ValueError("All entries must be non-negative")
     534
     535class IntegerVectors(Parent):
     536    """
     537    Returns the class of (non-negative) integer vectors.
     538
     539    .. NOTE::
     540
     541        The entries are non-negative integers.
     542
     543    EXAMPLES:
     544
     545    If `n` is not specified, it returns the class of all integer vectors::
     546
    517547        sage: IntegerVectors()
    518548        Integer vectors
    519549        sage: [] in IntegerVectors()
    def IntegerVectors(n=None, k=None, **kwa 
    522552        True
    523553        sage: [1, 0, 0] in IntegerVectors()
    524554        True
    525        
    526     Entries are non-negative.
    527    
    528     ::
     555
     556    Entries are non-negative::
    529557
    530558        sage: [-1, 2] in IntegerVectors()
    531559        False
    532    
    533     If n is specified, then it returns the class of all integer vectors
    534     which sum to n.
    535    
    536     ::
    537    
     560
     561    If `n` is specified, then it returns the class of all integer vectors
     562    which sum to `n`::
     563
    538564        sage: IV3 = IntegerVectors(3); IV3
    539565        Integer vectors that sum to 3
    540    
    541     Note that trailing zeros are ignored so that [3, 0] does not show
    542     up in the following list (since [3] does)
    543    
    544     ::
    545    
     566
     567    Note that trailing zeros are ignored so that ``[3, 0]`` does not show
     568    up in the following list (since ``[3]`` does)::
     569
    546570        sage: IntegerVectors(3, max_length=2).list()
    547571        [[3], [2, 1], [1, 2], [0, 3]]
    548572   
    549     If n and k are both specified, then it returns the class of integer
    550     vectors that sum to n and are of length k.
    551    
    552     ::
    553    
     573    If `n` and `k` are both specified, then it returns the class of integer
     574    vectors that sum to `n` and are of length `k`::
     575
    554576        sage: IV53 = IntegerVectors(5,3); IV53
    555577        Integer vectors of length 3 that sum to 5
    556578        sage: IV53.cardinality()
    def IntegerVectors(n=None, k=None, **kwa 
    562584        sage: IV53.random_element()
    563585        [4, 0, 1]
    564586    """
    565     if n is None:
    566         return IntegerVectors_all()
    567     elif k is None:
    568         return IntegerVectors_nconstraints(n,kwargs)
    569     else:
    570         if isinstance(k, builtinlist):
    571             return IntegerVectors_nnondescents(n,k)
    572         else:
    573             if len(kwargs) == 0:
    574                 return IntegerVectors_nk(n,k)
    575             else:
    576                 return IntegerVectors_nkconstraints(n,k,kwargs)
     587    __metaclass__ = ClasscallMetaclass
    577588
     589    @staticmethod
     590    def __classcall_private__(cls, n=None, k=None, **kwargs):
     591        """
     592        Choose the correct parent based upon input.
    578593
    579 class IntegerVectors_all(CombinatorialClass):
    580     def __repr__(self):
     594        EXAMPLES::
     595
     596            sage: IV1 = IntegerVectors(3, 2)
     597            sage: IV2 = IntegerVectors(3, 2)
     598            sage: IV1 is IV2
     599            True
    581600        """
     601        if len(kwargs) != 0:
     602            return IntegerVectorsConstraints(n, k, **kwargs)
     603
     604        if k is None:
     605            if n is None:
     606                return IntegerVectors_all()
     607            return IntegerVectors_n(n)
     608        if n is None:
     609            return IntegerVectors_k(k)
     610
     611        try:
     612            return IntegerVectors_nnondescents(n, tuple(k))
     613        except TypeError:
     614            pass
     615
     616        return IntegerVectors_nk(n, k)
     617
     618    def __init__(self, category=None):
     619        """
     620        Initialize ``self``.
     621
    582622        EXAMPLES::
    583        
    584             sage: IntegerVectors()
     623
     624            sage: IV = IntegerVectors()
     625            sage: TestSuite(IV).run()
     626        """
     627        if category is None:
     628            category = EnumeratedSets()
     629        Parent.__init__(self, category=category)
     630
     631    def _element_constructor_(self, lst):
     632        """
     633        Construct an element of ``self`` from ``lst``.
     634
     635        EXAMPLES::
     636
     637            sage: IV = IntegerVectors()
     638            sage: elt = IV([3, 1, 0, 3, 2]); elt
     639            [3, 1, 0, 3, 2]
     640            sage: elt.parent()
    585641            Integer vectors
    586642        """
    587         return "Integer vectors"
    588    
     643        if isinstance(lst, IntegerVector):
     644            if lst.parent() is self:
     645                return lst
     646            lst = list(lst)
     647        return self.element_class(self, lst)
     648
     649    Element = IntegerVector
     650
    589651    def __contains__(self, x):
    590652        """
    591653        EXAMPLES::
    592        
     654
    593655            sage: [] in IntegerVectors()
    594656            True
    595657            sage: [3,2,2,1] in IntegerVectors()
    596658            True
    597659        """
    598         if not isinstance(x, builtinlist):
     660        if isinstance(x, IntegerVector):
     661            return True
     662
     663        if not isinstance(x, (list, tuple)):
    599664            return False
     665
    600666        for i in x:
    601             if not isinstance(i, (int, Integer)):
     667            if i not in ZZ:
    602668                return False
    603669            if i < 0:
    604670                return False
    605 
    606671        return True
    607672
    608     def list(self):
     673class IntegerVectors_all(IntegerVectors, UniqueRepresentation):
     674    """
     675    Class of all integer vectors.
     676    """
     677    def __init__(self):
     678        """
     679        Initialize ``self``.
     680
     681        EXAMPLES::
     682
     683            sage: IV = IntegerVectors()
     684            sage: TestSuite(IV).run()
     685        """
     686        IntegerVectors.__init__(self, category=InfiniteEnumeratedSets())
     687
     688    def _repr_(self):
    609689        """
    610690        EXAMPLES::
    611        
    612             sage: IntegerVectors().list()
    613             Traceback (most recent call last):
    614             ...
    615             NotImplementedError: infinite list
     691
     692            sage: IntegerVectors()
     693            Integer vectors
    616694        """
    617         raise NotImplementedError, "infinite list"  # can't use InfiniteAbstractCombinatorialClass
     695        return "Integer vectors"
    618696
    619     def cardinality(self):
     697    def __iter__(self):
     698        """
     699        Iterate over ``self``.
     700
     701        EXAMPLES::
     702
     703            sage: IV = IntegerVectors()
     704            sage: it = IV.__iter__()
     705            sage: [it.next() for x in range(10)]
     706            [[], [1], [2], [2, 0], [1, 1], [0, 2], [3], [3, 0], [2, 1], [1, 2]]
     707        """
     708        yield self.element_class(self, [])
     709        n = 1
     710        while True:
     711            for k in range(1,n+1):
     712                for x in IntegerVectors(n, k):
     713                    yield self.element_class(self, list(x))
     714            n += 1
     715
     716class IntegerVectors_n(IntegerVectors, UniqueRepresentation):
     717    """
     718    Integer vectors that sum to `n`.
     719    """
     720    def __init__(self, n):
     721        """
     722        TESTS::
     723
     724            sage: IV = IntegerVectors(3)
     725            sage: TestSuite(IV).run()
     726        """       
     727        self.n = n
     728        IntegerVectors.__init__(self, category=InfiniteEnumeratedSets())
     729
     730    def _repr_(self):
     731        """
     732        TESTS::
     733
     734            sage: IV = IntegerVectors(3)
     735            sage: IV
     736            Integer vectors that sum to 3
     737        """
     738        return "Integer vectors that sum to %s"%self.n
     739
     740    def __iter__(self):
     741        """
     742        Iterate over ``self``.
     743
     744        EXAMPLES::
     745
     746            sage: it = IntegerVectors(3).__iter__()
     747            sage: [it.next() for x in range(10)]
     748            [[3],
     749             [3, 0],
     750             [2, 1],
     751             [1, 2],
     752             [0, 3],
     753             [3, 0, 0],
     754             [2, 1, 0],
     755             [2, 0, 1],
     756             [1, 2, 0],
     757             [1, 1, 1]]
     758        """
     759        k = 1
     760        while True:
     761            for iv in IntegerVectors_nk(self.n, k):
     762                yield self.element_class(self, list(iv))
     763            k += 1
     764
     765    def __contains__(self, x):
    620766        """
    621767        EXAMPLES::
    622        
    623             sage: IntegerVectors().cardinality()
    624             +Infinity
     768
     769            sage: [0] in IntegerVectors(0)
     770            True
     771            sage: [3] in IntegerVectors(3)
     772            True
     773            sage: [3] in IntegerVectors(2)
     774            False
     775            sage: [3,2,2,1] in IntegerVectors(9)
     776            False           
     777            sage: [3,2,2,1] in IntegerVectors(8)
     778            True
    625779        """
    626         return infinity
     780        if not IntegerVectors.__contains__(self, x):
     781            return False
     782        return sum(x) == self.n
    627783
     784class IntegerVectors_k(IntegerVectors, UniqueRepresentation):
     785    """
     786    Integer vectors of length `k`.
     787    """
     788    def __init__(self, k):
     789        """
     790        TESTS::
    628791
    629 class IntegerVectors_nk(CombinatorialClass):
     792            sage: IV = IntegerVectors(k=2)
     793            sage: TestSuite(IV).run()
     794        """       
     795        self.k = k
     796        IntegerVectors.__init__(self, category=InfiniteEnumeratedSets())
     797
     798    def _repr_(self):
     799        """
     800        TESTS::
     801
     802            sage: IV = IntegerVectors(k=2)
     803            sage: IV
     804            Integer vectors of length 2
     805        """
     806        return "Integer vectors of length %s"%self.k
     807
     808    def __iter__(self):
     809        """
     810        Iterate over ``self``.
     811
     812        EXAMPLES::
     813
     814            sage: it = IntegerVectors(k=2).__iter__()
     815            sage: [it.next() for x in range(10)]
     816            [[0, 0],
     817             [1, 0],
     818             [0, 1],
     819             [2, 0],
     820             [1, 1],
     821             [0, 2],
     822             [3, 0],
     823             [2, 1],
     824             [1, 2],
     825             [0, 3]]
     826        """
     827        n = 0
     828        while True:
     829            for iv in IntegerVectors_nk(n, self.k):
     830                yield self.element_class(self, list(iv))
     831            n += 1
     832
     833    def __contains__(self, x):
     834        """
     835        EXAMPLES::
     836
     837            sage: [] in IntegerVectors(k=0)
     838            True
     839            sage: [3] in IntegerVectors(k=1)
     840            True
     841            sage: [3] in IntegerVectors(k=2)
     842            False
     843            sage: [3,2,2,1] in IntegerVectors(k=3)
     844            False           
     845            sage: [3,2,2,1] in IntegerVectors(k=4)
     846            True
     847        """
     848        if not IntegerVectors.__contains__(self, x):
     849            return False
     850        return len(x) == self.k
     851
     852class IntegerVectors_nk(IntegerVectors, UniqueRepresentation):
     853    """
     854    Integer vectors of length `k` that sum to `n`.
     855
     856    AUTHORS:
     857
     858    - Martin Albrecht
     859    - Mike Hansen
     860    """
    630861    def __init__(self, n, k):
    631862        """
    632863        TESTS::
    633        
    634             sage: IV = IntegerVectors(2,3)
    635             sage: IV == loads(dumps(IV))
    636             True
    637        
    638         AUTHORS:
    639864
    640         - Martin Albrecht
    641 
    642         - Mike Hansen
     865            sage: IV = IntegerVectors(2, 3)
     866            sage: TestSuite(IV).run()
    643867        """       
    644868        self.n = n
    645869        self.k = k
    646 
     870        IntegerVectors.__init__(self, category=FiniteEnumeratedSets())
    647871
    648872    def _list_rec(self, n, k):
    649873        """
    650         Return a list of a exponent tuples of length `size` such
     874        Return a list of a exponent tuples of length ``size`` such
    651875        that the degree of the associated monomial is `D`.
    652        
     876
    653877        INPUT:
    654        
    655        
    656         -  ``n`` - degree (must be 0)
    657        
    658         -  ``k`` - length of exponent tuples (must be 0)
    659        
    660        
     878
     879        -  ``n`` -- degree (must be 0)
     880
     881        -  ``k`` -- length of exponent tuples (must be 0)
     882
    661883        EXAMPLES::
    662        
     884
    663885            sage: IV = IntegerVectors(2,3)
    664886            sage: IV._list_rec(2,3)
    665887            [(2, 0, 0), (1, 1, 0), (1, 0, 1), (0, 2, 0), (0, 1, 1), (0, 0, 2)]
    class IntegerVectors_nk(CombinatorialCla 
    675897                res.append((n_diff,)+rest)
    676898        return res
    677899
    678     def list(self):
    679         """
    680         EXAMPLE::
    681        
    682             sage: IV = IntegerVectors(2,3)
    683             sage: IV.list()
    684             [[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]]
    685             sage: IntegerVectors(3, 0).list()
    686             []
    687             sage: IntegerVectors(3, 1).list()
    688             [[3]]
    689             sage: IntegerVectors(0, 1).list()
    690             [[0]]
    691             sage: IntegerVectors(0, 2).list()
    692             [[0, 0]]
    693             sage: IntegerVectors(2, 2).list()
    694             [[2, 0], [1, 1], [0, 2]]
    695         """
    696         if self.n < 0:
    697             return []
    698 
    699         if self.k == 0:
    700             if self.n == 0:
    701                 return [[]]
    702             else:
    703                 return []
    704         elif self.k == 1:
    705             return [[self.n]]
    706        
    707         res = self._list_rec(self.n, self.k)
    708         return map(list, res)
    709    
    710 
    711900    def __iter__(self):
    712901        """
    713         EXAMPLE::
    714        
    715             sage: IV = IntegerVectors(2,3)
     902        Iterate over ``self``.
     903
     904        EXAMPLES::
     905
     906            sage: IV = IntegerVectors(2, 3)
    716907            sage: list(IV)
    717908            [[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]]
    718909            sage: list(IntegerVectors(3, 0))
    class IntegerVectors_nk(CombinatorialCla 
    725916            [[0, 0]]
    726917            sage: list(IntegerVectors(2, 2))
    727918            [[2, 0], [1, 1], [0, 2]]
    728             sage: IntegerVectors(0,0).list()
     919            sage: IntegerVectors(0, 0).list()
    729920            [[]]
    730             sage: IntegerVectors(1,0).list()
     921            sage: IntegerVectors(1, 0).list()
    731922            []
    732             sage: IntegerVectors(0,1).list()
     923            sage: IntegerVectors(0, 1).list()
    733924            [[0]]
    734             sage: IntegerVectors(2,2).list()
     925            sage: IntegerVectors(2, 2).list()
    735926            [[2, 0], [1, 1], [0, 2]]
    736927            sage: IntegerVectors(-1,0).list()
    737928            []
    class IntegerVectors_nk(CombinatorialCla 
    740931        """
    741932        if self.n < 0:
    742933            return
    743        
     934
    744935        if self.k == 0:
    745936            if self.n == 0:
    746                 yield []
     937                yield self.element_class(self, [])
    747938            return
    748939        elif self.k == 1:
    749             yield [self.n]
     940            yield self.element_class(self, [self.n])
    750941            return
    751942
    752943        for nbar in range(self.n+1):
    753             n = self.n-nbar
    754             for rest in IntegerVectors_nk(nbar , self.k-1):
    755                 yield [n] + rest
     944            n = self.n - nbar
     945            for rest in IntegerVectors_nk(nbar, self.k-1):
     946                yield self.element_class(self, [n] + list(rest))
    756947
    757     def __repr__(self):
     948    def _repr_(self):
    758949        """
    759950        TESTS::
    760        
     951
    761952            sage: IV = IntegerVectors(2,3)
    762             sage: repr(IV)
    763             'Integer vectors of length 3 that sum to 2'
     953            sage: IV
     954            Integer vectors of length 3 that sum to 2
    764955        """
    765956        return "Integer vectors of length %s that sum to %s"%(self.k, self.n)
    766957
    767958    def __contains__(self, x):
    768959        """
    769960        TESTS::
    770        
    771             sage: IV = IntegerVectors(2,3)
     961
     962            sage: IV = IntegerVectors(2, 3)
    772963            sage: all([i in IV for i in IV])
    773964            True
    774965            sage: [0,1,2] in IV
    775966            False
    776967            sage: [2.0, 0, 0] in IV
    777             False
     968            True
    778969            sage: [0,1,0,1] in IV
    779970            False
    780971            sage: [0,1,1] in IV
    781972            True
    782973            sage: [-1,2,1] in IV
    783974            False
    784         """
    785         if x not in IntegerVectors():
    786             return False
    787975
    788         if sum(x) != self.n:
    789             return False
    790 
    791         if len(x) != self.k:
    792             return False
    793 
    794         if len(x) > 0 and min(x) < 0:
    795             return False
    796 
    797         return True
    798  
    799 class IntegerVectors_nkconstraints(CombinatorialClass):
    800     def __init__(self, n, k, constraints):
    801         """
    802         EXAMPLES::
    803        
    804             sage: IV = IntegerVectors(2,3,min_slope=0)
    805             sage: IV == loads(dumps(IV))
    806             True
    807         """
    808         self.n = n
    809         self.k = k
    810         self.constraints = constraints
    811 
    812     def __repr__(self):
    813         """
    814         EXAMPLES::
    815        
    816             sage: IntegerVectors(2,3,min_slope=0).__repr__()
    817             'Integer vectors of length 3 that sum to 2 with constraints: min_slope=0'
    818         """
    819         return "Integer vectors of length %s that sum to %s with constraints: %s"%(self.k, self.n, ", ".join( ["%s=%s"%(key, self.constraints[key]) for key in sorted(self.constraints.keys())] ))
    820 
    821  
    822     def __contains__(self, x):
    823         """
    824         TESTS::
    825        
    826             sage: [0] in IntegerVectors(0)
    827             True
    828976            sage: [0] in IntegerVectors(0, 1)
    829977            True
    830978            sage: [] in IntegerVectors(0, 0)
    class IntegerVectors_nkconstraints(Combi 
    833981            False
    834982            sage: [] in IntegerVectors(1, 0)
    835983            False
    836             sage: [3] in IntegerVectors(3)
     984            sage: [3] in IntegerVectors(2, 1)
     985            False
     986            sage: [3] in IntegerVectors(3, 1)
    837987            True
    838             sage: [3] in IntegerVectors(2,1)
     988            sage: [3,2,2,1] in IntegerVectors(9, 5)
    839989            False
    840             sage: [3] in IntegerVectors(2)
     990            sage: [3,2,2,1] in IntegerVectors(8, 5)
    841991            False
    842             sage: [3] in IntegerVectors(3,1)
     992            sage: [3,2,2,1] in IntegerVectors(8, 4)
    843993            True
    844             sage: [3,2,2,1] in IntegerVectors(9)
    845             False
    846             sage: [3,2,2,1] in IntegerVectors(9,5)
    847             False           
    848             sage: [3,2,2,1] in IntegerVectors(8)
    849             True
    850             sage: [3,2,2,1] in IntegerVectors(8,5)
    851             False
    852             sage: [3,2,2,1] in IntegerVectors(8,4)
    853             True
    854             sage: [3,2,2,1] in IntegerVectors(8,4, min_part = 1)
    855             True
    856             sage: [3,2,2,1] in IntegerVectors(8,4, min_part = 2)
    857             False
    858994        """
    859         if x not in IntegerVectors():
     995        if isinstance(x, IntegerVector) and x.parent() is self:
     996            return True
     997
     998        if not IntegerVectors.__contains__(self, x):
     999            return False
     1000
     1001        if len(x) != self.k:
    8601002            return False
    8611003
    8621004        if sum(x) != self.n:
    8631005            return False
    8641006
    865         if len(x) != self.k:
     1007        if len(x) > 0 and min(x) < 0:
    8661008            return False
    8671009
    868         if self.constraints:
    869             if not misc.check_integer_list_constraints(x, singleton=True, **self.constraints):
    870                 return False
    871 
    8721010        return True
    8731011
    874     def cardinality(self):
     1012class IntegerVectors_nnondescents(IntegerVectors, UniqueRepresentation):
     1013    r"""
     1014    Integer vectors `v` graded by two parameters:
     1015
     1016    - ``n`` -- the sum of the parts of `v`
     1017
     1018    - ``comp`` -- the non descents composition of `v`
     1019   
     1020    In other words: the length of `v` equals ``c[1]+...+c[k]``, and `v` is
     1021    decreasing in the consecutive blocs of length ``c[1], ..., c[k]``
     1022   
     1023    Those are the integer vectors of sum ``n`` which are lexicographically
     1024    maximal (for the natural left-to-right reading) in their orbit by the
     1025    young subgroup `S_{c_1} \times \cdots \times S_{c_k}`. In particular, they
     1026    form a set of orbit representative of integer vectors with respect to this
     1027    Young subgroup.
     1028    """
     1029    @staticmethod
     1030    def __classcall_private__(cls, n, comp):
     1031        """
     1032        Normalize input to ensure a unique representation.
     1033
     1034        EXAMPLES::
     1035
     1036            sage: IntegerVectors(4, [2,1]) is IntegerVectors(int(4), (2,1))
     1037            True
     1038        """
     1039        return super(IntegerVectors_nnondescents, cls).__classcall__(cls, n, tuple(comp))
     1040
     1041    def __init__(self, n, comp):
    8751042        """
    8761043        EXAMPLES::
    8771044       
    878             sage: IntegerVectors(3,3, min_part=1).cardinality()
     1045            sage: IV = IntegerVectors(4, [2])
     1046            sage: TestSuite(IV).run()
     1047        """
     1048        self.n = n
     1049        self.comp = comp
     1050        IntegerVectors.__init__(self, category=FiniteEnumeratedSets())
     1051
     1052    def _repr_(self):
     1053        """
     1054        EXAMPLES::
     1055       
     1056            sage: IntegerVectors(4, [2])
     1057            Integer vectors of 4 with non-descents composition [2]
     1058        """
     1059        return "Integer vectors of %s with non-descents composition %s"%(self.n, list(self.comp))
     1060
     1061    def __iter__(self):
     1062        """
     1063        TESTS::
     1064 
     1065            sage: IntegerVectors(0, []).list()
     1066            [[]]
     1067            sage: IntegerVectors(5, []).list()
     1068            []
     1069            sage: IntegerVectors(0, [1]).list()
     1070            [[0]]
     1071            sage: IntegerVectors(4, [1]).list()
     1072            [[4]]
     1073            sage: IntegerVectors(4, [2]).list()
     1074            [[4, 0], [3, 1], [2, 2]]
     1075            sage: IntegerVectors(4, [2,2]).list()
     1076            [[4, 0, 0, 0],
     1077             [3, 1, 0, 0],
     1078             [2, 2, 0, 0],
     1079             [3, 0, 1, 0],
     1080             [2, 1, 1, 0],
     1081             [2, 0, 2, 0],
     1082             [2, 0, 1, 1],
     1083             [1, 1, 2, 0],
     1084             [1, 1, 1, 1],
     1085             [1, 0, 3, 0],
     1086             [1, 0, 2, 1],
     1087             [0, 0, 4, 0],
     1088             [0, 0, 3, 1],
     1089             [0, 0, 2, 2]]
     1090            sage: IntegerVectors(5, [1,1,1]).list()
     1091            [[5, 0, 0],
     1092             [4, 1, 0],
     1093             [4, 0, 1],
     1094             [3, 2, 0],
     1095             [3, 1, 1],
     1096             [3, 0, 2],
     1097             [2, 3, 0],
     1098             [2, 2, 1],
     1099             [2, 1, 2],
     1100             [2, 0, 3],
     1101             [1, 4, 0],
     1102             [1, 3, 1],
     1103             [1, 2, 2],
     1104             [1, 1, 3],
     1105             [1, 0, 4],
     1106             [0, 5, 0],
     1107             [0, 4, 1],
     1108             [0, 3, 2],
     1109             [0, 2, 3],
     1110             [0, 1, 4],
     1111             [0, 0, 5]]
     1112            sage: IntegerVectors(0, [2,3]).list()
     1113            [[0, 0, 0, 0, 0]]
     1114        """
     1115        for iv in IntegerVectors(self.n, len(self.comp)):
     1116            blocks = [ IntegerVectors(iv[i], self.comp[i], max_slope=0).list() for i in range(len(self.comp))]
     1117            for parts in cartesian_product.CartesianProduct(*blocks):
     1118                res = []
     1119                for part in parts:
     1120                    res += part
     1121                yield self.element_class(self, res)
     1122
     1123class IntegerVectorsConstraints(IntegerVectors):
     1124    """
     1125    Class of integer vectors subject to various constraints.
     1126    """
     1127    def __init__(self, n=None, k=None, **constraints):
     1128        """
     1129        Initialize ``self``.
     1130
     1131        EXAMPLES::
     1132
     1133            sage: TestSuite(IntegerVectors(min_slope=0)).run()
     1134            sage: TestSuite(IntegerVectors(3, max_slope=0)).run()
     1135            sage: TestSuite(IntegerVectors(3, max_length=4)).run()
     1136            sage: TestSuite(IntegerVectors(k=2, max_part=4)).run()
     1137            sage: TestSuite(IntegerVectors(k=2, min_part=2, max_part=4)).run()
     1138            sage: TestSuite(IntegerVectors(3, 2, max_slope=0)).run()
     1139        """
     1140        self.n = n
     1141        self.k = k
     1142        self.constraints = constraints
     1143
     1144        if n is not None:
     1145            if k is not None or 'max_length' in constraints:
     1146                category = FiniteEnumeratedSets()
     1147            else:
     1148                category = EnumeratedSets()
     1149        elif k is not None and 'max_part' in constraints: # n is None
     1150            category = FiniteEnumeratedSets()
     1151        else:
     1152            category = EnumeratedSets()
     1153        IntegerVectors.__init__(self, category=category) # placeholder category
     1154
     1155    def _repr_(self):
     1156        """
     1157        Return a string representation of ``self``.
     1158
     1159        EXAMPLES::
     1160       
     1161            sage: IntegerVectors(min_slope=0)
     1162            Integer vectors with constraints: min_slope=0
     1163
     1164            sage: IntegerVectors(3, max_length=2)
     1165            Integer vectors that sum to 3 with constraints: max_length=2
     1166
     1167            sage: IntegerVectors(2, 3, min_slope=0)
     1168            Integer vectors of length 3 that sum to 2 with constraints: min_slope=0
     1169        """
     1170        if self.k is not None:
     1171            if self.n is not None:
     1172                base = "Integer vectors of length %s that sum to %s with constraints: "%(self.k, self.n)
     1173            else:
     1174                base = "Integer vectors of length %s with constraints: "%(self.k)
     1175        elif self.n is not None:
     1176            base ="Integer vectors that sum to %s with constraints: "%(self.n)
     1177        else:
     1178            base = "Integer vectors with constraints: "
     1179        return base + ", ".join( "%s=%s"%(key, self.constraints[key]) \
     1180                                for key in sorted(self.constraints.keys()) )
     1181
     1182    def __eq__(self, rhs):
     1183        """
     1184        EXAMPLES::
     1185
     1186            sage: IntegerVectors(min_slope=0) == IntegerVectors(min_slope=0)
     1187            True
     1188            sage: IntegerVectors(2, min_slope=0) == IntegerVectors(2, min_slope=0)
     1189            True
     1190            sage: IntegerVectors(2, 3, min_slope=0) == IntegerVectors(2, 3, min_slope=0)
     1191            True
     1192        """
     1193        if isinstance(rhs, IntegerVectorsConstraints):
     1194            return self.n == rhs.n and self.k == rhs.k and self.constraints == rhs.constraints
     1195        return False
     1196
     1197    def __ne__(self, rhs):
     1198        """
     1199        EXAMPLES::
     1200
     1201            sage: IntegerVectors(min_slope=0) != IntegerVectors(min_slope=3)
     1202            True
     1203        """
     1204        return not self.__eq__(rhs)
     1205
     1206    def __contains__(self, x):
     1207        """
     1208        TESTS::
     1209
     1210            sage: [3,2,2,1] in IntegerVectors(8,4, min_part = 1)
     1211            True
     1212            sage: [3,2,2,1] in IntegerVectors(8,4, min_part = 2)
     1213            False
     1214
     1215            sage: [0,3,0,1,2] in IntegerVectors(6, max_length=3)
     1216            False
     1217        """
     1218        if isinstance(x, IntegerVector) and x.parent() is self:
     1219            return True
     1220
     1221        if not IntegerVectors.__contains__(self, x):
     1222            return False
     1223
     1224        if self.k is not None and len(x) != self.k:
     1225            return False
     1226
     1227        if self.n is not None and sum(x) != self.n:
     1228            return False
     1229
     1230        return misc.check_integer_list_constraints(x, singleton=True, **self.constraints)
     1231
     1232    def cardinality(self):
     1233        """
     1234        Return the cardinality of ``self``.
     1235
     1236        EXAMPLES::
     1237
     1238            sage: IntegerVectors(3, 3, min_part=1).cardinality()
    8791239            1
    880             sage: IntegerVectors(5,3, min_part=1).cardinality()
     1240            sage: IntegerVectors(5, 3, min_part=1).cardinality()
    8811241            6
     1242            sage: IntegerVectors(13, 4, max_part=4).cardinality()
     1243            20
     1244            sage: IntegerVectors(k=4, max_part=3).cardinality()
     1245            256
     1246            sage: IntegerVectors(k=3, min_part=2, max_part=4).cardinality()
     1247            27
    8821248            sage: IntegerVectors(13, 4, min_part=2, max_part=4).cardinality()
    8831249            16
    8841250        """
    885         if not self.constraints:
    886             if self.n >= 0:
    887                 return binomial(self.n+self.k-1,self.n)
    888             else:
    889                 return 0
    890         else:
    891             if len(self.constraints) == 1 and 'max_part' in self.constraints and self.constraints['max_part'] != infinity:
     1251        if self.k is not None and 'max_part' in self.constraints \
     1252                and self.constraints['max_part'] != PlusInfinity():
     1253            if self.n is None and len(self.constraints) == 2 \
     1254                    and 'min_part' in self.constraints \
     1255                    and self.constraints['min_part'] != MinusInfinity():
     1256                num = self.constraints['max_part'] - self.constraints['min_part'] + 1
     1257                return Integer(num ** self.k)
     1258            if len(self.constraints) == 1:
    8921259                m = self.constraints['max_part']
     1260                if self.n is None:
     1261                    return Integer((m+1) ** self.k)
    8931262                if m >= self.n:
    894                     return binomial(self.n+self.k-1,self.n)
    895                 else: #do by inclusion / exclusion on the number
    896                       #i of parts greater than m
    897                     return sum( [(-1)**i * binomial(self.n+self.k-1-i*(m+1), self.k-1)*binomial(self.k,i) for i in range(0, self.n/(m+1)+1)])
    898             else:
    899                 return len(self.list())
    900 
     1263                    return Integer(binomial(self.n+self.k-1, self.n))
     1264                # do by inclusion / exclusion on the number
     1265                # i of parts greater than m
     1266                return Integer(sum( (-1)**i * binomial(self.n+self.k-1-i*(m+1), self.k-1) \
     1267                    * binomial(self.k,i) for i in range(0, self.n/(m+1)+1) ))
     1268        return Integer(sum(1 for x in self))
    9011269
    9021270    def _parameters(self):
    9031271        """
    904         Returns a tuple (min_length, max_length, floor, ceiling,
    905         min_slope, max_slope) for the parameters of self.
     1272        Return a tuple ``(min_length, max_length, floor, ceiling,
     1273        min_slope, max_slope)`` for the parameters of ``self``.
    9061274       
    9071275        EXAMPLES::
    9081276       
    class IntegerVectors_nkconstraints(Combi 
    9151283            sage: [floor(i) for i in range(1,10)]
    9161284            [0, 0, 0, 0, 0, 0, 0, 0, 0]
    9171285            sage: [ceiling(i) for i in range(1,5)]
    918             [+Infinity, +Infinity, +Infinity, +Infinity]
     1286            [inf, inf, inf, inf]
    9191287            sage: min_slope
    9201288            0
    9211289            sage: max_slope
    922             +Infinity
     1290            inf
    9231291
    9241292            sage: IV = IntegerVectors(3,10,inner=[4,1,3], min_part = 2)
    9251293            sage: min_length, max_length, floor, ceiling, min_slope, max_slope = IV._parameters()
    class IntegerVectors_nkconstraints(Combi 
    9331301        """
    9341302        constraints = self.constraints
    9351303        #n, min_length, max_length, floor, ceiling, min_slope, max_slope
    936         if self.k == -1:
     1304        if self.k is None:
    9371305            min_length = constraints.get('min_length', 0)
    938             max_length = constraints.get('max_length', infinity)
     1306            max_length = constraints.get('max_length', float('+inf'))
    9391307        else:
    9401308            min_length = self.k
    9411309            max_length = self.k
    9421310           
    9431311        min_part = constraints.get('min_part', 0)
    944         max_part = constraints.get('max_part', infinity)
    945         min_slope = constraints.get('min_slope', -infinity)
    946         max_slope = constraints.get('max_slope', infinity)
     1312        max_part = constraints.get('max_part', float('+inf'))
     1313        min_slope = constraints.get('min_slope', float('-inf'))
     1314        max_slope = constraints.get('max_slope', float('+inf'))
    9471315        if 'outer' in self.constraints:
    9481316            ceiling = list2func( map(lambda i: min(max_part, i), self.constraints['outer']), default=max_part )
    9491317        else:
    950             ceiling = constant_func(max_part)
     1318            ceiling = lambda x: max_part
    9511319
    9521320        if 'inner' in self.constraints:
    9531321            floor = list2func( map(lambda i: max(min_part, i), self.constraints['inner']), default=min_part )
    9541322        else:
    955             floor = constant_func(min_part)
     1323            floor = lambda x: min_part
    9561324
    9571325        return (min_length, max_length, floor, ceiling, min_slope, max_slope)
    958    
    9591326
    9601327    def first(self):
    9611328        """
    class IntegerVectors_nkconstraints(Combi 
    9641331            sage: IntegerVectors(2,3,min_slope=0).first()
    9651332            [0, 1, 1]
    9661333        """
    967         return integer_list.first(self.n, *self._parameters())
    968    
     1334        return self.__iter__().next()
     1335
     1336    _an_element_ = first
     1337
    9691338    def next(self, x):
    9701339        """
    9711340        EXAMPLES::
    972        
    973             sage: IntegerVectors(2,3,min_slope=0).last()
     1341
     1342            sage: IV = IntegerVectors(2, 3, min_slope=0)
     1343            sage: x = IV.first()
     1344            sage: IV.next(x)
    9741345            [0, 0, 2]
    9751346        """
    976         return integer_list.next(x, *self._parameters())
     1347        ret = self.element_class(self, integer_list.next(x, *self._parameters()))
     1348        if ret is None and self.n is None:
     1349            return self.element_class(self, integer_list.first(sum(x)+1, *self._parameters()))
     1350        return ret
    9771351
    9781352    def __iter__(self):
    9791353        """
    9801354        EXAMPLES::
    981        
     1355
    9821356            sage: IntegerVectors(-1, 0, min_part = 1).list()
    9831357            []
    9841358            sage: IntegerVectors(-1, 2, min_part = 1).list()
    class IntegerVectors_nkconstraints(Combi 
    9951369            []
    9961370            sage: IntegerVectors(4, 2, min_part=1).list()
    9971371            [[3, 1], [2, 2], [1, 3]]
    998        
     1372
    9991373        ::
    1000        
     1374
    10011375            sage: IntegerVectors(0, 3, outer=[0,0,0]).list()
    10021376            [[0, 0, 0]]
    10031377            sage: IntegerVectors(1, 3, outer=[0,0,0]).list()
    class IntegerVectors_nkconstraints(Combi 
    10191393             [0, 0, 1, 1, 0],
    10201394             [0, 0, 1, 0, 1],
    10211395             [0, 0, 0, 1, 1]]
    1022        
     1396
    10231397        ::
    1024        
    1025             sage: iv = [ IntegerVectors(n,k) for n in range(-2, 7) for k in range(7) ]
     1398
     1399            sage: iv = [ IntegerVectors(n, k) for n in range(-2, 7) for k in range(7) ]
    10261400            sage: all(map(lambda x: x.cardinality() == len(x.list()), iv))
    10271401            True
    10281402            sage: essai = [[1,1,1], [2,5,6], [6,5,2]]
    class IntegerVectors_nkconstraints(Combi 
    10301404            sage: all(map(lambda x: x.cardinality() == len(x.list()), iv))
    10311405            True
    10321406        """
    1033         return integer_list.iterator(self.n, *self._parameters())
     1407        if self.n is None:
     1408            if self.k is not None and 'max_part' in self.constraints:
     1409                n_list = range((self.constraints['max_part'] + 1) * self.k)
     1410            else:
     1411                n_list = NN
     1412        else:
     1413            n_list = [self.n]
     1414        for n in n_list:
     1415            for x in integer_list.iterator(n, *self._parameters()):
     1416                yield self.element_class(self, x)
    10341417
    1035 class IntegerVectors_nconstraints(IntegerVectors_nkconstraints):
    1036     def __init__(self, n, constraints):
    1037         """
    1038         TESTS::
    1039        
    1040             sage: IV = IntegerVectors(3, max_length=2)
    1041             sage: IV == loads(dumps(IV))
    1042             True
    1043         """
    1044         IntegerVectors_nkconstraints.__init__(self, n, -1, constraints)
     1418def IntegerVectors_nconstraints(n, **constraints):
     1419    """
     1420    EXAMPLES::
    10451421
    1046     def __repr__(self):
    1047         """
    1048         EXAMPLES::
    1049        
    1050             sage: repr(IntegerVectors(3))
    1051             'Integer vectors that sum to 3'
    1052             sage: repr(IntegerVectors(3, max_length=2))
    1053             'Integer vectors that sum to 3 with constraints: max_length=2'
    1054         """
    1055         if self.constraints:
    1056             return "Integer vectors that sum to %s with constraints: %s"%(self.n,", ".join( ["%s=%s"%(key, self.constraints[key]) for key in sorted(self.constraints.keys())] ))
    1057         else:
    1058             return "Integer vectors that sum to %s"%(self.n,)
     1422        sage: sage.combinat.integer_vector.IntegerVectors_nconstraints(2)
     1423        doctest:...: DeprecationWarning: this class is deprecated. Use sage.combinat.integer_vector.IntegerVectors_n instead
     1424        See http://trac.sagemath.org/12453 for details.
     1425        Integer vectors that sum to 2
     1426        sage: sage.combinat.integer_vector.IntegerVectors_nconstraints(2, min_slope=0)
     1427        doctest:...: DeprecationWarning: this class is deprecated. Use sage.combinat.integer_vector.IntegerVectorsConstraints instead
     1428        See http://trac.sagemath.org/12453 for details.
     1429        Integer vectors that sum to 2 with constraints: min_slope=0
     1430    """
     1431    from sage.misc.superseded import deprecation
     1432    if len(constraints) == 0:
     1433        deprecation(12453, 'this class is deprecated. Use sage.combinat.integer_vector.IntegerVectors_n instead')
     1434        return IntegerVectors_n(n)
     1435    deprecation(12453, 'this class is deprecated. Use sage.combinat.integer_vector.IntegerVectorsConstraints instead')
     1436    return IntegerVectorsConstraints(n, **constraints)
    10591437
    1060     def __contains__(self, x):
    1061         """
    1062         EXAMPLES::
    1063        
    1064             sage: [0,3,0,1,2] in IntegerVectors(6)
    1065             True
    1066             sage: [0,3,0,1,2] in IntegerVectors(6, max_length=3)
    1067             False
    1068         """
    1069         if self.constraints:
    1070             return x in IntegerVectors_all() and misc.check_integer_list_constraints(x, singleton=True, **self.constraints)
    1071         else:
    1072             return x in IntegerVectors_all() and sum(x) == self.n
     1438def IntegerVectors_nkconstraints(n=None, k=None, **constraints):
     1439    """
     1440    EXAMPLES::
    10731441
    1074     def cardinality(self):
    1075         """
    1076         EXAMPLES::
    1077        
    1078             sage: IntegerVectors(3, max_length=2).cardinality()
    1079             4
    1080             sage: IntegerVectors(3).cardinality()
    1081             +Infinity
    1082         """
    1083         if 'max_length' not in self.constraints:
    1084             return infinity
    1085         else:
    1086             return self._CombinatorialClass__cardinality_from_iterator()
     1442        sage: sage.combinat.integer_vector.IntegerVectors_nkconstraints(3, 2)
     1443        doctest:...: DeprecationWarning: this class is deprecated. Use sage.combinat.integer_vector.IntegerVectors_nk instead
     1444        See http://trac.sagemath.org/12453 for details.
     1445        Integer vectors of length 2 that sum to 3
     1446        sage: sage.combinat.integer_vector.IntegerVectors_nkconstraints(3, 2, min_slope=0)
     1447        doctest:...: DeprecationWarning: this class is deprecated. Use sage.combinat.integer_vector.IntegerVectorsConstraints instead
     1448        See http://trac.sagemath.org/12453 for details.
     1449        Integer vectors of length 2 that sum to 3 with constraints: min_slope=0
     1450    """
     1451    from sage.misc.superseded import deprecation
     1452    if len(constraints) == 0:
     1453        if n is None:
     1454            deprecation(12453, 'this class is deprecated. Use sage.combinat.integer_vector.IntegerVectors_k instead')
     1455            return IntegerVectors_k(k)
     1456        deprecation(12453, 'this class is deprecated. Use sage.combinat.integer_vector.IntegerVectors_nk instead')
     1457        return IntegerVectors_nk(n, k)
     1458    deprecation(12453, 'this class is deprecated. Use sage.combinat.integer_vector.IntegerVectorsConstraints instead')
     1459    return IntegerVectorsConstraints(n, k, **constraints)
    10871460
    1088     def list(self):
    1089         """
    1090         EXAMPLES::
    1091        
    1092             sage: IntegerVectors(3, max_length=2).list()
    1093             [[3], [2, 1], [1, 2], [0, 3]]
    1094             sage: IntegerVectors(3).list()
    1095             Traceback (most recent call last):
    1096             ...
    1097             NotImplementedError: infinite list
    1098         """
    1099         if 'max_length' not in self.constraints:
    1100             raise NotImplementedError, "infinite list" # no list from infinite iter
    1101         else:
    1102             return list(self)
     1461# October 2012: fixing outdated pickles which use classes being deprecated
     1462from sage.structure.sage_object import register_unpickle_override
     1463register_unpickle_override('sage.combinat.integer_vector', 'IntegerVectors_nconstraints', IntegerVectorsConstraints)
     1464register_unpickle_override('sage.combinat.integer_vector', 'IntegerVectors_nkconstraints', IntegerVectorsConstraints)
    11031465
    1104 
    1105 class IntegerVectors_nnondescents(CombinatorialClass):
    1106     r"""
    1107     The combinatorial class of integer vectors v graded by two
    1108     parameters:
    1109 
    1110     - n: the sum of the parts of v
    1111 
    1112     - comp: the non descents composition of v
    1113    
    1114     In other words: the length of v equals c[1]+...+c[k], and v is
    1115     decreasing in the consecutive blocs of length c[1], ..., c[k]
    1116    
    1117     Those are the integer vectors of sum n which are lexicographically
    1118     maximal (for the natural left->right reading) in their orbit by the
    1119     young subgroup S_c_1 x x S_c_k. In particular, they form a set
    1120     of orbit representative of integer vectors w.r.t. this young
    1121     subgroup.
    1122     """
    1123     def __init__(self, n, comp):
    1124         """
    1125         EXAMPLES::
    1126        
    1127             sage: IV = IntegerVectors(4, [2])
    1128             sage: IV == loads(dumps(IV))
    1129             True
    1130         """
    1131         self.n = n
    1132         self.comp = comp
    1133 
    1134     def __repr__(self):
    1135         """
    1136         EXAMPLES::
    1137        
    1138             sage: IntegerVectors(4, [2]).__repr__()
    1139             'Integer vectors of 4 with non-descents composition [2]'
    1140         """
    1141         return "Integer vectors of %s with non-descents composition %s"%(self.n, self.comp)
    1142 
    1143     def __iter__(self):
    1144         """
    1145          TESTS::
    1146          
    1147              sage: IntegerVectors(0, []).list()
    1148              [[]]
    1149              sage: IntegerVectors(5, []).list()
    1150              []
    1151              sage: IntegerVectors(0, [1]).list()
    1152              [[0]]
    1153              sage: IntegerVectors(4, [1]).list()
    1154              [[4]]
    1155              sage: IntegerVectors(4, [2]).list()
    1156              [[4, 0], [3, 1], [2, 2]]
    1157              sage: IntegerVectors(4, [2,2]).list()
    1158              [[4, 0, 0, 0],
    1159               [3, 1, 0, 0],
    1160               [2, 2, 0, 0],
    1161               [3, 0, 1, 0],
    1162               [2, 1, 1, 0],
    1163               [2, 0, 2, 0],
    1164               [2, 0, 1, 1],
    1165               [1, 1, 2, 0],
    1166               [1, 1, 1, 1],
    1167               [1, 0, 3, 0],
    1168               [1, 0, 2, 1],
    1169               [0, 0, 4, 0],
    1170               [0, 0, 3, 1],
    1171               [0, 0, 2, 2]]
    1172              sage: IntegerVectors(5, [1,1,1]).list()
    1173              [[5, 0, 0],
    1174               [4, 1, 0],
    1175               [4, 0, 1],
    1176               [3, 2, 0],
    1177               [3, 1, 1],
    1178               [3, 0, 2],
    1179               [2, 3, 0],
    1180               [2, 2, 1],
    1181               [2, 1, 2],
    1182               [2, 0, 3],
    1183               [1, 4, 0],
    1184               [1, 3, 1],
    1185               [1, 2, 2],
    1186               [1, 1, 3],
    1187               [1, 0, 4],
    1188               [0, 5, 0],
    1189               [0, 4, 1],
    1190               [0, 3, 2],
    1191               [0, 2, 3],
    1192               [0, 1, 4],
    1193               [0, 0, 5]]
    1194              sage: IntegerVectors(0, [2,3]).list()
    1195              [[0, 0, 0, 0, 0]]
    1196          """
    1197         for iv in IntegerVectors(self.n, len(self.comp)):
    1198             blocks = [ IntegerVectors(iv[i], self.comp[i], max_slope=0).list() for i in range(len(self.comp))]
    1199             for parts in cartesian_product.CartesianProduct(*blocks):
    1200                 res = []
    1201                 for part in parts:
    1202                     res += part
    1203                 yield res
    1204 
    1205    
  • sage/combinat/integer_vector_weighted.py

    diff --git a/sage/combinat/integer_vector_weighted.py b/sage/combinat/integer_vector_weighted.py
    a b Weighted Integer Vectors 
    33
    44AUTHORS:
    55
    6  - Mike Hansen (2007): initial version, ported from MuPAD-Combinat
    7  - Nicolas M. Thiery (2010-10-30): WeightedIntegerVectors(weights) + cleanup
    8 
    9 .. WARNING::
    10 
    11     The list(self) function in this file used the :class:`Permutation` class improperly, returning
    12     a list of, generally speaking, invalid permutations (repeated entries, including 0).
     6- Mike Hansen (2007): initial version, ported from MuPAD-Combinat
     7- Nicolas M. Thiery (2010-10-30): WeightedIntegerVectors(weights) + cleanup
    138"""
    149#*****************************************************************************
    1510#  Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>
    AUTHORS: 
    1914#
    2015#                  http://www.gnu.org/licenses/
    2116#*****************************************************************************
     17
     18from sage.structure.unique_representation import UniqueRepresentation
     19from sage.structure.parent import Parent
    2220from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
    2321from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
    2422from sage.categories.sets_with_grading import SetsWithGrading
    25 from __builtin__ import list as builtinlist
     23from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets
    2624from sage.rings.integer import Integer
    27 from sage.structure.unique_representation import UniqueRepresentation
    28 from sage.structure.parent import Parent
    29 from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets
     25from sage.rings.all import ZZ
     26from sage.combinat.integer_vector import IntegerVector
    3027from sage.combinat.words.word import Word
    31 from permutation import Permutation
     28from sage.combinat.permutation import Permutation
    3229
    33 def WeightedIntegerVectors(n = None, weight = None):
    34     """
    35     Returns the combinatorial class of integer vectors of ``n``
    36     weighted by ``weight``, that is, the nonnegative integer vectors
    37     `(v_1,\\dots,v_{length(weight)})` satisfying `\\sum_i v_i
    38     weight[i]==n`.
     30class WeightedIntegerVectors(Parent, UniqueRepresentation):
     31    r"""
     32    The class of integer vectors of `n` weighted by ``weight``, that is, the
     33    nonnegative integer vectors `(v_1, \ldots, v_{\ell})`
     34    satisfying `\sum_{i=1}^{\ell} v_i w_i = n` where `\ell` is
     35    ``length(weight)`` and `w_i` is ``weight[i]``.
    3936
    4037    INPUT:
    4138
    def WeightedIntegerVectors(n = None, wei 
    6865        sage: WeightedIntegerVectors(None,None)
    6966        Traceback (most recent call last):
    7067        ...
    71         ValueError: weights should be specified
     68        ValueError: the weights must be specified
    7269
    7370    .. TODO::
    7471
    7572        should the order of the arguments ``n`` and ``weight`` be
    76         exchanged to simplify the logic ?
     73        exchanged to simplify the logic?
    7774    """
    78     if weight is None and n is not None:
    79         weight = n
    80         n = None
    81     if weight is None:
    82         raise ValueError("weights should be specified")
    83     weight = tuple(weight)
    84     if n is None:
    85         return WeightedIntegerVectors_all(weight)
    86     else:
    87         return WeightedIntegerVectors_nweight(n, weight)
     75    @staticmethod
     76    def __classcall_private__(cls, n=None, weight=None):
     77        """
     78        Normalize inputs to ensure a unique representation.
    8879
    89 class WeightedIntegerVectors_all(DisjointUnionEnumeratedSets):
    90     r"""
    91     Set of weighted integer vectors.
    92 
    93     EXAMPLES::
    94 
    95         sage: W = WeightedIntegerVectors([3,1,1,2,1]); W
    96         Integer vectors weighted by [3, 1, 1, 2, 1]
    97         sage: W.cardinality()
    98         +Infinity
    99 
    100         sage: W12 = W.graded_component(12)
    101         sage: W12.an_element()
    102         [4, 0, 0, 0, 0]
    103         sage: W12.last()
    104         [0, 12, 0, 0, 0]
    105         sage: W12.cardinality()
    106         441
    107         sage: for w in W12: print w
    108         [4, 0, 0, 0, 0]
    109         [3, 0, 0, 1, 1]
    110         [3, 0, 1, 1, 0]
    111         ...
    112         [0, 11, 1, 0, 0]
    113         [0, 12, 0, 0, 0]
    114     """
    115     def __init__(self, weights):
    116         """
    11780        TESTS::
    11881
    119             sage: C = WeightedIntegerVectors([2,1,3])
    120             sage: C.__class__
    121             <class 'sage.combinat.integer_vector_weighted.WeightedIntegerVectors_all_with_category'>
    122             sage: C.category()
    123             Join of Category of infinite enumerated sets and Category of sets with grading
    124             sage: TestSuite(C).run()
     82            sage: W = WeightedIntegerVectors(8, [1,1,2])
     83            sage: W2 = WeightedIntegerVectors(int(8), (1,1,2))
     84            sage: W is W2
     85            True
    12586        """
    126         self._weights = weights
    127         from sage.sets.all import Family, NonNegativeIntegers
    128         # Use "partial" to make the basis function (with the weights
    129         # argument specified) pickleable.  Otherwise, it seems to
    130         # cause problems...
    131         from functools import partial
    132         F = Family(NonNegativeIntegers(), partial(WeightedIntegerVectors, weight = weights))
    133         DisjointUnionEnumeratedSets.__init__(self, F, facade=True, keepkey=False,
    134                                              category = (SetsWithGrading(), InfiniteEnumeratedSets()))
     87        if weight is None:
     88            if n is None:
     89                raise ValueError("the weights must be specified")
     90            if n in ZZ:
     91                weight = (n,)
     92            else:
     93                weight = tuple(n)
     94            n = None
    13595
    136     def _repr_(self):
    137         """
    138         EXAMPLES::
     96        weight = tuple(weight)
     97        if n is None:
     98            return WeightedIntegerVectors_all(weight)
    13999
    140             sage: WeightedIntegerVectors([2,1,3])
    141             Integer vectors weighted by [2, 1, 3]
    142         """
    143         return "Integer vectors weighted by %s"%list(self._weights)
     100        return super(WeightedIntegerVectors, cls).__classcall__(cls, n, weight)
    144101
    145     def __contains__(self, x):
    146         """
    147         EXAMPLES::
    148 
    149             sage: [] in WeightedIntegerVectors([])
    150             True
    151             sage: [3,0,0] in WeightedIntegerVectors([2,1,1])
    152             True
    153             sage: [3,0] in WeightedIntegerVectors([2,1,1])
    154             False
    155             sage: [3,-1,0] in WeightedIntegerVectors([2,1,1])
    156             False
    157         """
    158         return isinstance(x, (builtinlist, Permutation)) and \
    159             len(x) == len(self._weights)   and \
    160             all(isinstance(i, (int, Integer)) and i>=0 for i in x)
    161 
    162     def subset(self, size = None):
    163         """
    164         EXAMPLES::
    165 
    166             sage: C = WeightedIntegerVectors([2,1,3])
    167             sage: C.subset(4)
    168             Integer vectors of 4 weighted by [2, 1, 3]
    169         """
    170         if size is None:
    171             return self
    172         return self._family[size]
    173 
    174     def grading(self, x): # or degree / grading
    175         """
    176         EXAMPLES::
    177 
    178             sage: C = WeightedIntegerVectors([2,1,3])
    179             sage: C.grading((2,1,1))
    180             8
    181         """
    182         return sum([exp*deg for exp,deg in zip(x, self._weights)])
    183 
    184 class WeightedIntegerVectors_nweight(UniqueRepresentation, Parent):
    185102    def __init__(self, n, weight):
    186103        """
    187104        TESTS::
    188105
    189             sage: C = WeightedIntegerVectors(8, [1,1,2])
    190             sage: C.__class__
    191             <class 'sage.combinat.integer_vector_weighted.WeightedIntegerVectors_nweight_with_category'>
    192             sage: TestSuite(C).run()
     106            sage: WIV = WeightedIntegerVectors(8, [1,1,2])
     107            sage: TestSuite(WIV).run()
    193108        """
    194         Parent.__init__(self, category = FiniteEnumeratedSets())
    195109        self._n = n
    196110        self._weights = weight
     111        Parent.__init__(self, category=FiniteEnumeratedSets())
     112
     113    Element = IntegerVector
     114
     115    def _element_constructor_(self, lst):
     116        """
     117        Construct an element of ``self`` from ``lst``.
     118
     119        EXAMPLES::
     120
     121            sage: WIV = WeightedIntegerVectors(3, [2,1,1])
     122            sage: elt = WIV([1, 2, 0]); elt
     123            [1, 2, 0]
     124            sage: elt.parent() is WIV
     125            True
     126        """
     127        if isinstance(lst, IntegerVector):
     128            if lst.parent() is self:
     129                return lst
     130            raise ValueError("Cannot convert %s into %s"(lst, self))
     131        return self.element_class(self, lst)
    197132
    198133    def _repr_(self):
    199134        """
    200135        TESTS::
    201136
    202             sage: repr(WeightedIntegerVectors(8, [1,1,2]))
    203             'Integer vectors of 8 weighted by [1, 1, 2]'
     137            sage: WeightedIntegerVectors(8, [1,1,2])
     138            Integer vectors of 8 weighted by [1, 1, 2]
    204139        """
    205140        return "Integer vectors of %s weighted by %s"%(self._n, list(self._weights))
    206141
    class WeightedIntegerVectors_nweight(Uni 
    231166            sage: [0] in WeightedIntegerVectors(0, [])
    232167            False
    233168        """
    234         if not isinstance(x, (builtinlist, Permutation)):
     169        if not isinstance(x, (list, IntegerVector, Permutation)):
    235170            return False
    236171        if len(self._weights) != len(x):
    237172            return False
    238173        s = 0
    239174        for i in range(len(x)):
    240             if not isinstance(x[i], (int, Integer)):
     175            if (not isinstance(x[i], (int, Integer))) and (x[i] not in ZZ):
    241176                return False
    242177            s += x[i]*self._weights[i]
    243         if s != self._n:
    244             return False
    245 
    246         return True
     178        return s == self._n
    247179
    248180    def _recfun(self, n, l):
    249181        """
    class WeightedIntegerVectors_nweight(Uni 
    279211
    280212            sage: ivw = [ WeightedIntegerVectors(k, [1,1,1]) for k in range(11) ]
    281213            sage: iv  = [ IntegerVectors(k, 3) for k in range(11) ]
    282             sage: all( [ sorted(iv[k].list()) == sorted(ivw[k].list()) for k in range(11) ] )
     214            sage: all( [ sorted(map(list, iv[k].list())) == sorted(map(list, ivw[k].list())) for k in range(11) ] )
    283215            True
    284216
    285217        ::
    class WeightedIntegerVectors_nweight(Uni 
    290222        """
    291223        if len(self._weights) == 0:
    292224            if self._n == 0:
    293                 yield []
     225                yield self.element_class(self, [])
    294226            return
    295227
    296228        perm = Word(self._weights).standard_permutation()
    297         l = [x for x in sorted(self._weights)]
    298         for x in self._recfun(self._n, l):
    299             yield perm.action(x)
    300             #_left_to_right_multiply_on_right(Permutation(x))
     229        for a in self._recfun(self._n, [x for x in sorted(self._weights)]):
     230            yield self.element_class(self, list(perm.action(a)))
     231
     232class WeightedIntegerVectors_all(DisjointUnionEnumeratedSets):
     233    r"""
     234    Set of weighted integer vectors.
     235
     236    EXAMPLES::
     237
     238        sage: W = WeightedIntegerVectors([3,1,1,2,1]); W
     239        Integer vectors weighted by [3, 1, 1, 2, 1]
     240        sage: W.cardinality()
     241        +Infinity
     242
     243        sage: W12 = W.graded_component(12)
     244        sage: W12.an_element()
     245        [4, 0, 0, 0, 0]
     246        sage: W12.last()
     247        [0, 12, 0, 0, 0]
     248        sage: W12.cardinality()
     249        441
     250        sage: for w in W12: print w
     251        [4, 0, 0, 0, 0]
     252        [3, 0, 0, 1, 1]
     253        [3, 0, 1, 1, 0]
     254        ...
     255        [0, 11, 1, 0, 0]
     256        [0, 12, 0, 0, 0]
     257    """
     258    def __init__(self, weight):
     259        """
     260        TESTS::
     261
     262            sage: C = WeightedIntegerVectors([2,1,3])
     263            sage: C.category()
     264            Join of Category of infinite enumerated sets and Category of sets with grading
     265            sage: TestSuite(C).run()
     266        """
     267        self._weights = weight
     268        from sage.sets.all import Family, NonNegativeIntegers
     269        # Use "partial" to make the basis function (with the weights
     270        # argument specified) pickleable.  Otherwise, it seems to
     271        # cause problems...
     272        from functools import partial
     273        F = Family(NonNegativeIntegers(), partial(WeightedIntegerVectors, weight=weight))
     274        DisjointUnionEnumeratedSets.__init__(self, F, facade=True, keepkey=False,
     275                                             category = (SetsWithGrading(), InfiniteEnumeratedSets()))
     276
     277    def _repr_(self):
     278        """
     279        EXAMPLES::
     280
     281            sage: WeightedIntegerVectors([2,1,3])
     282            Integer vectors weighted by [2, 1, 3]
     283        """
     284        return "Integer vectors weighted by %s"%list(self._weights)
     285
     286    def __contains__(self, x):
     287        """
     288        EXAMPLES::
     289
     290            sage: [] in WeightedIntegerVectors([])
     291            True
     292            sage: [3,0,0] in WeightedIntegerVectors([2,1,1])
     293            True
     294            sage: [3,0] in WeightedIntegerVectors([2,1,1])
     295            False
     296            sage: [3,-1,0] in WeightedIntegerVectors([2,1,1])
     297            False
     298        """
     299        return isinstance(x, (list, IntegerVector, Permutation)) and \
     300            len(x) == len(self._weights) and \
     301            all(i in ZZ and i >= 0 for i in x)
     302
     303    def subset(self, size = None):
     304        """
     305        EXAMPLES::
     306
     307            sage: C = WeightedIntegerVectors([2,1,3])
     308            sage: C.subset(4)
     309            Integer vectors of 4 weighted by [2, 1, 3]
     310        """
     311        if size is None:
     312            return self
     313        return self._family[size]
     314
     315    def grading(self, x): # or degree / grading
     316        """
     317        EXAMPLES::
     318
     319            sage: C = WeightedIntegerVectors([2,1,3])
     320            sage: C.grading((2,1,1))
     321            8
     322        """
     323        return sum([exp*deg for exp,deg in zip(x, self._weights)])
     324
     325def WeightedIntegerVectors_nweight(n, weight):
     326    """
     327    Deprecated in :trac:`12453`. Use :class:`WeightedIntegerVectors` instead.
     328
     329    EXAMPLES::
     330
     331        sage: sage.combinat.integer_vector_weighted.WeightedIntegerVectors_nweight(7, [2,2])
     332        doctest:...: DeprecationWarning: this class is deprecated. Use WeightedIntegerVectors instead
     333        See http://trac.sagemath.org/12453 for details.
     334        Integer vectors of 7 weighted by [2, 2]
     335    """
     336    from sage.misc.superseded import deprecation
     337    deprecation(12453, 'this class is deprecated. Use WeightedIntegerVectors instead')
     338    return WeightedIntegerVectors(n, weight)
     339
     340from sage.structure.sage_object import register_unpickle_override
     341register_unpickle_override('sage.combinat.integer_vector_weighted', 'WeightedIntegerVectors_nweight', WeightedIntegerVectors)
     342
  • sage/combinat/integer_vectors_mod_permgroup.py

    diff --git a/sage/combinat/integer_vectors_mod_permgroup.py b/sage/combinat/integer_vectors_mod_permgroup.py
    a b class IntegerVectorsModPermutationGroup_ 
    304304
    305305            sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
    306306            sage: S.ambient()
    307             Integer vectors
     307            Integer vectors with constraints: length=4
    308308        """
    309309        # TODO: Fix me once 'IntegerVectors(length=bla)' will return
    310310        # the integer vectors of length bla
    class IntegerVectorsModPermutationGroup_ 
    801801            Integer vectors that sum to 6
    802802            sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 6, max_part=12); S.ambient()
    803803            Integer vectors that sum to 6 with constraints: max_part=12
    804 
    805         .. todo::
    806 
    807          Integer vectors should accept ``max_part`` as a single argument, and the following should change::
    808 
    809804            sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), max_part=12); S.ambient()
    810             Integer vectors
    811 
     805            Integer vectors with constraints: max_part=12
    812806        """
    813807        if self._sum is not None:
    814808            if self._max_part <= -1:
  • sage/combinat/partition.py

    diff --git a/sage/combinat/partition.py b/sage/combinat/partition.py
    a b class Partition(CombinatorialObject, Ele 
    34063406
    34073407        #list all of the positions for cells
    34083408        #filling each self from the left to the right
    3409         l = IntegerVectors(k, len(shelf), outer=shelf).list()
    3410         for iv in l:
     3409        for iv in IntegerVectors(k, len(shelf), outer=shelf):
     3410            iv = list(iv) # Make a mutable list
    34113411            tmp = conj + [0]*k
    34123412            j = 0
    34133413            for t in range(len(iv)):
  • sage/combinat/tableau.py

    diff --git a/sage/combinat/tableau.py b/sage/combinat/tableau.py
    a b class SemistandardTableaux_size_inf(Semi 
    43994399                if i != 1:
    44004400                    for k in range(1, self.size+1):
    44014401                        for c in IntegerVectors(self.size - k, i-1):
     4402                            c = list(c)
    44024403                            c.append(k)
    44034404                            for sst in SemistandardTableaux_shape_weight(part, Composition(c)):
    44044405                                yield self.element_class(self, sst)
    class SemistandardTableaux_shape_inf(Sem 
    45014502            if i != 1:
    45024503                for k in range(1, n+1):
    45034504                    for c in IntegerVectors(n - k, i-1):
     4505                        c = list(c)
    45044506                        c.append(k)
    45054507                        for sst in SemistandardTableaux_shape_weight(self.shape, Composition(c)):
    45064508                            yield self.element_class(self, sst)