# Ticket #13072: trac_13072-tuples-of-partitions_am.patch

File trac_13072-tuples-of-partitions_am.patch, 241.9 KB (added by andrew.mathas, 7 years ago)

• ## doc/de/tutorial/tour_numtheory.rst

# HG changeset patch
# User Andrew Mathas <andrew.mathas at sydney.edu.au>
# Date 1341585162 -28800
# Node ID e01a2b546f1d3b6f6d105263b65b16082201f0dd
# Parent  8c7785b0f522cedaea430b967b8f673c4b483e21
#13072 Implementing partition tuples + general partition clean up

diff --git a/doc/de/tutorial/tour_numtheory.rst b/doc/de/tutorial/tour_numtheory.rst
 a Schließlich illustrieren wir den chines [1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1] sage: n = 10000; sum([moebius(m) for m in range(1,n)]) -23 sage: list(partitions(4)) [(1, 1, 1, 1), (1, 1, 2), (2, 2), (1, 3), (4,)] sage: Partitions(4).list() [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]] :math:p-adische Zahlen ------------------------
• ## doc/en/reference/combinat/index.rst

diff --git a/doc/en/reference/combinat/index.rst b/doc/en/reference/combinat/index.rst
 a Combinatorics ../sage/combinat/necklace ../sage/combinat/non_decreasing_parking_function ../sage/combinat/partition ../sage/combinat/partition_tuple ../sage/combinat/permutation ../sage/combinat/perfect_matching ../sage/combinat/q_analogues
• ## doc/en/tutorial/tour_numtheory.rst

diff --git a/doc/en/tutorial/tour_numtheory.rst b/doc/en/tutorial/tour_numtheory.rst
 a Finally we illustrate the Chinese remain [1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1] sage: n = 10000; sum([moebius(m) for m in range(1,n)]) -23 sage: list(partitions(4)) [(1, 1, 1, 1), (1, 1, 2), (2, 2), (1, 3), (4,)] sage: Partitions(4).list() [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]] :math:p-adic Numbers ------------------------
• ## doc/fr/tutorial/tour_numtheory.rst

diff --git a/doc/fr/tutorial/tour_numtheory.rst b/doc/fr/tutorial/tour_numtheory.rst
 a Et finalement un exemple d'utilisation d [1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1] sage: n = 10000; sum([moebius(m) for m in range(1,n)]) -23 sage: list(partitions(4)) [(1, 1, 1, 1), (1, 1, 2), (2, 2), (1, 3), (4,)] sage: Partitions(4).list() [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]] Nombres :math:p-adiques -------------------------
• ## doc/ru/tutorial/tour_numtheory.rst

diff --git a/doc/ru/tutorial/tour_numtheory.rst b/doc/ru/tutorial/tour_numtheory.rst
 a Sage содержит стандартн [1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1] sage: n = 10000; sum([moebius(m) for m in range(1,n)]) -23 sage: list(partitions(4)) [(1, 1, 1, 1), (1, 1, 2), (2, 2), (1, 3), (4,)] sage: Partitions(4).list() [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]] :math:p--адические числа
• ## sage/combinat/all.py

diff --git a/sage/combinat/all.py b/sage/combinat/all.py
 a from expnums import expnums from sage.combinat.crystals.all import * from rigged_configurations.all import * from sage.combinat.dlx import DLXMatrix, AllExactCovers, OneExactCover from sage.combinat.dlx import DLXMatrix, AllExactCovers, OneExactCover # block designs, etc from sage.combinat.designs.all import * from composition import Composition, Com from composition_signed import SignedCompositions #Partitions import partition from partition import Partition, Partitions, PartitionsInBox,\ OrderedPartitions, RestrictedPartitions, PartitionTuples,\ PartitionsGreatestLE, PartitionsGreatestEQ, partitions_set,\ number_of_partitions_set, number_of_partitions_list, \ ordered_partitions, number_of_ordered_partitions, number_of_partitions,\ partitions, cyclic_permutations_of_partition,\ cyclic_permutations_of_partition_iterator, ferrers_diagram, \ partitions_greatest, partitions_greatest_eq, partitions_restricted,\ number_of_partitions_restricted, partitions_tuples, \ number_of_partitions_tuples, partition_power, partition_sign, \ partition_associated, partitions_list OrderedPartitions, PartitionsGreatestLE, PartitionsGreatestEQ,\ PartitionsGreatestLE, PartitionsGreatestEQ, number_of_partitions #Functions being deprecated from partition from partition import partitions_set, RestrictedPartitions, number_of_partitions_set,\ ordered_partitions, number_of_ordered_partitions, partitions,\ cyclic_permutations_of_partition, cyclic_permutations_of_partition_iterator,\ ferrers_diagram, partitions_greatest, partitions_greatest_eq,\ partitions_tuples, number_of_partitions_tuples, partition_power from partition_tuple import PartitionTuple, PartitionTuples from skew_partition import SkewPartition, SkewPartitions #Partition algebra from partition_algebra import SetPartitionsAk, SetPartitionsPk, SetPartitionsTk, SetPartitionsIk, SetPartitionsBk, SetPartitionsSk, SetPartitionsRk, SetPartitionsRk, SetPartitionsPRk #Cores
• ## sage/combinat/combinat.py

diff --git a/sage/combinat/combinat.py b/sage/combinat/combinat.py
 a r""" Combinatorial Functions AUTHORS: - David Joyner (2006-07): initial implementation. Partitions: of set S is a set of pairwise disjoint nonempty sets with union S and is represented by a sorted list of such sets. -  Partitions of an integer, partitions_list, number_of_partitions_list. An unordered partition of n is an unordered sum -  Partitions of an integer, Partitions. An unordered partition of n is an unordered sum n = p_1+p_2 +\ldots+ p_k of positive integers and is represented by the list p = [p_1,p_2,\ldots,p_k], in nonincreasing order, i.e., p1\geq p_2 ...\geq p_k. Partitions: represented by the list p = [p_1,p_2,\ldots,p_k], in nonincreasing order, i.e., p1\geq p_2 ...\geq p_k. -  Restricted partitions of an integer, partitions_restricted, number_of_partitions_restricted. An unordered restricted partition of n is an unordered sum n = p_1+p_2 +\ldots+ p_k of positive integers p_i belonging to a given set S, and is represented by the list p = [p_1,p_2,\ldots,p_k], in nonincreasing order, i.e., p1\geq p_2 ...\geq p_k. -  partitions_greatest implements a special type of restricted partition. -  partitions_greatest_eq is another type of restricted partition. -  Tuples of partitions, partition_tuples, number_of_partition_tuples. A k-tuple -  Tuples of partitions, PartitionTuples. A k-tuple of partitions is represented by a list of all k-tuples of partitions which together form a partition of n. Partitions: The power of a partition corresponds to the k-th power of a permutation with cycle structure \pi. -  Sign of a partition, partition_sign( pi ) This means the sign of a permutation with cycle structure given by the partition pi. -  Associated partition, partition_associated( pi ) The "associated" (also called "conjugate" in the literature) partition of the partition pi which is obtained by transposing the corresponding Ferrers diagram. -  Ferrers diagram, ferrers_diagram. Analogous to the Young diagram of an irreducible representation of S_n. Related functions: combinatorial functions: \frac {\Gamma(x+a)} {\Gamma(x)}. -  gaussian_binomial the gaussian binomial .. math:: \binom{n}{k}_q = \frac{(1-q^m)(1-q^{m-1})\cdots (1-q^{m-r+1})}                              {(1-q)(1-q^2)\cdots (1-q^r)}. \binom{n}{k}_q = \frac{(1-q^m)(1-q^{m-1})\cdots (1-q^{m-r+1})}                              {(1-q)(1-q^2)\cdots (1-q^r)}. def bell_number(n): r""" Returns the n-th Bell number (the number of ways to partition a set of n elements into pairwise disjoint nonempty subsets). If n \leq 0, returns 1. Wraps GAP's Bell. EXAMPLES:: sage: bell_number(10) 115975 sage: bell_number(2) def bell_number(n): ## def bernoulli_number(n): ##     r""" ##     Returns the n-th Bernoulli number $B_n$; $B_n/n!$ is the ##     Returns the n-th Bernoulli number $B_n$; $B_n/n!$ is the ##     coefficient of $x^n$ in the power series of $x/(e^x-1)$. ##     Wraps GAP's Bernoulli. ##     EXAMPLES: def bell_number(n): def catalan_number(n): r""" Returns the n-th Catalan number Catalan numbers: The n-th Catalan number is given directly in terms of binomial coefficients by .. math:: C_n = \frac{1}{n+1}{2n\choose n} = \frac{(2n)!}{(n+1)!\,n!}              \qquad\mbox{ for }\quad n\ge 0. C_n = \frac{1}{n+1}{2n\choose n} = \frac{(2n)!}{(n+1)!\,n!}              \qquad\mbox{ for }\quad n\ge 0. Consider the set S = \{ 1, ..., n \}. A noncrossing partition of S is a partition in which no two blocks "cross" each other, i.e., if a and b belong to one block and x and def catalan_number(n): C_n is the number of noncrossing partitions of the set S. There are many other interpretations (see REFERENCES). When n=-1, this function raises a ZeroDivisionError; for other n<0 it returns 0. def catalan_number(n): - n - integer OUTPUT: integer EXAMPLES:: sage: [catalan_number(i) for i in range(7)] [1, 1, 2, 5, 14, 42, 132] sage: taylor((-1/2)*sqrt(1 - 4*x^2), x, 0, 15) def catalan_number(n): sage: catalan_number(-1) Traceback (most recent call last): ... ZeroDivisionError ZeroDivisionError sage: [catalan_number(n).mod(2) for n in range(16)] [1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1] REFERENCES: -  http://en.wikipedia.org/wiki/Catalan_number -  http://www-history.mcs.st-andrews.ac.uk/~history/Miscellaneous/CatalanNumbers/catalan.html """ from sage.rings.arith import binomial def catalan_number(n): def euler_number(n): """ Returns the n-th Euler number IMPLEMENTATION: Wraps Maxima's euler. EXAMPLES:: sage: [euler_number(i) for i in range(10)] [1, 0, -1, 0, 5, 0, -61, 0, 1385, 0] sage: maxima.eval("taylor (2/(exp(x)+exp(-x)), x, 0, 10)") def euler_number(n): sage: euler_number(-1) Traceback (most recent call last): ... ValueError: n (=-1) must be a nonnegative integer ValueError: n (=-1) must be a nonnegative integer REFERENCES: - http://en.wikipedia.org/wiki/Euler_number def fibonacci(n, algorithm="pari"): F_{n+2} = F_{n+1} + F_n. For negative n we define F_n = (-1)^{n+1}F_{-n}, which is consistent with the recurrence relation. INPUT: -  algorithm - string: -  "pari" - (default) - use the PARI C library's fibo function. -  "gap" - use GAP's Fibonacci function .. note:: PARI is tens to hundreds of times faster than GAP here; moreover, PARI works for every large input whereas GAP doesn't. EXAMPLES:: sage: fibonacci(10) 55 sage: fibonacci(10, algorithm='gap') 55 :: sage: fibonacci(-100) -354224848179261915075 sage: fibonacci(100) 354224848179261915075 :: sage: fibonacci(0) 0 sage: fibonacci(1/2) def lucas_number1(n,P,Q): defined by the initial conditions L^{(1)}_1=0, L^{(1)}_2=1 and the recurrence relation L^{(1)}_{n+2} = P*L^{(1)}_{n+1} - Q*L^{(1)}_n. Wraps GAP's Lucas(...)[1]. P=1, Q=-1 gives the Fibonacci sequence. INPUT: -  n - integer -  P, Q - integer or rational numbers OUTPUT: integer or rational number EXAMPLES:: sage: lucas_number1(5,1,-1) 5 sage: lucas_number1(6,1,-1) def lucas_number1(n,P,Q): 13 sage: lucas_number1(7,1,-2) 43 :: sage: lucas_number1(5,2,3/5) 229/25 sage: lucas_number1(5,2,1.5) Traceback (most recent call last): ... TypeError: no canonical coercion from Real Field with 53 bits of precision to Rational Field There was a conjecture that the sequence L_n defined by L_{n+2} = L_{n+1} + L_n, L_1=1, L_2=3, has the property that n prime implies that L_n is prime. :: sage: lucas = lambda n : Integer((5/2)*lucas_number1(n,1,-1)+(1/2)*lucas_number2(n,1,-1)) sage: [[lucas(n),is_prime(lucas(n)),n+1,is_prime(n+1)] for n in range(15)] [[1, False, 1, False], def lucas_number1(n,P,Q): [521, True, 13, True], [843, False, 14, False], [1364, False, 15, False]] Can you use Sage to find a counterexample to the conjecture? """ ans=gap.eval("Lucas(%s,%s,%s)[1]"%(QQ._coerce_(P),QQ._coerce_(Q),ZZ(n))) def lucas_number2(n,P,Q): defined by the initial conditions L^{(2)}_1=2, L^{(2)}_2=P and the recurrence relation L^{(2)}_{n+2} = P*L^{(2)}_{n+1} - Q*L^{(2)}_n. Wraps GAP's Lucas(...)[2]. INPUT: -  n - integer -  P, Q - integer or rational numbers OUTPUT: integer or rational number EXAMPLES:: sage: [lucas_number2(i,1,-1) for i in range(10)] [2, 1, 3, 4, 7, 11, 18, 29, 47, 76] sage: [fibonacci(i-1)+fibonacci(i+1) for i in range(10)] [2, 1, 3, 4, 7, 11, 18, 29, 47, 76] :: sage: n = lucas_number2(5,2,3); n 2 sage: type(n) def lucas_number2(n,P,Q): 418/9 sage: type(n) The case P=1, Q=-1 is the Lucas sequence in Brualdi's Introductory Combinatorics, 4th ed., Prentice-Hall, 2004:: sage: [lucas_number2(n,1,-1) for n in range(10)] [2, 1, 3, 4, 7, 11, 18, 29, 47, 76] """ def stirling_number1(n,k): Returns the n-th Stilling number S_1(n,k) of the first kind (the number of permutations of n points with k cycles). Wraps GAP's Stirling1. EXAMPLES:: sage: stirling_number1(3,2) 3 sage: stirling_number1(5,2) def stirling_number1(n,k): 269325 sage: stirling_number1(10,5) 269325 Indeed, S_1(n,k) = S_1(n-1,k-1) + (n-1)S_1(n-1,k). """ return ZZ(gap.eval("Stirling1(%s,%s)"%(ZZ(n),ZZ(k)))) class CombinatorialObject(SageObject): differences are that __setitem__ is disabled so that CombinatorialObjects are shallowly immutable, and the intention is that they are semantically immutable. Because of this, CombinatorialObjects provide a __hash__ function which computes the hash of the string representation of a list and the hash of its parent's class. Thus, each CombinatorialObject should have a unique string representation. INPUT: -  l - a list or any object that can be convert to a list by -  l - a list or any object that can be convert to a list by list EXAMPLES:: sage: c = CombinatorialObject([1,2,3]) sage: c == loads(dumps(c)) True class CombinatorialObject(SageObject): def __str__(self): """ EXAMPLES:: sage: c = CombinatorialObject([1,2,3]) sage: str(c) '[1, 2, 3]' class CombinatorialObject(SageObject): def _repr_(self): """ EXAMPLES:: sage: c = CombinatorialObject([1,2,3]) sage: c.__repr__() '[1, 2, 3]' """ return self._list.__repr__() def __eq__(self, other): """ EXAMPLES:: sage: c = CombinatorialObject([1,2,3]) sage: d = CombinatorialObject([2,3,4]) sage: c == [1,2,3] class CombinatorialObject(SageObject): sage: c == d False """ if isinstance(other, CombinatorialObject): return self._list.__eq__(other._list) else: class CombinatorialObject(SageObject): def __lt__(self, other): """ EXAMPLES:: sage: c = CombinatorialObject([1,2,3]) sage: d = CombinatorialObject([2,3,4]) sage: c < d class CombinatorialObject(SageObject): sage: c < [2,3,4] True """ if isinstance(other, CombinatorialObject): return self._list.__lt__(other._list) else: class CombinatorialObject(SageObject): def __le__(self, other): """ EXAMPLES:: sage: c = CombinatorialObject([1,2,3]) sage: d = CombinatorialObject([2,3,4]) sage: c <= c class CombinatorialObject(SageObject): def __gt__(self, other): """ EXAMPLES:: sage: c = CombinatorialObject([1,2,3]) sage: d = CombinatorialObject([2,3,4]) sage: c > c class CombinatorialObject(SageObject): def __ge__(self, other): """ EXAMPLES:: sage: c = CombinatorialObject([1,2,3]) sage: d = CombinatorialObject([2,3,4]) sage: c >= c class CombinatorialObject(SageObject): def __ne__(self, other): """ EXAMPLES:: sage: c = CombinatorialObject([1,2,3]) sage: d = CombinatorialObject([2,3,4]) sage: c != c class CombinatorialObject(SageObject): def __add__(self, other): """ EXAMPLES:: sage: c = CombinatorialObject([1,2,3]) sage: c + [4] [1, 2, 3, 4] class CombinatorialObject(SageObject): Computes the hash of self by computing the hash of the string representation of self._list. The hash is cached and stored in self._hash. EXAMPLES:: sage: c = CombinatorialObject([1,2,3]) sage: c._hash is None True class CombinatorialObject(SageObject): def __len__(self): """ EXAMPLES:: sage: c = CombinatorialObject([1,2,3]) sage: len(c) 3 class CombinatorialObject(SageObject): def __getitem__(self, key): """ EXAMPLES:: sage: c = CombinatorialObject([1,2,3]) sage: c[0] 1 class CombinatorialObject(SageObject): def __iter__(self): """ EXAMPLES:: sage: c = CombinatorialObject([1,2,3]) sage: list(iter(c)) [1, 2, 3] class CombinatorialObject(SageObject): def __contains__(self, item): """ EXAMPLES:: sage: c = CombinatorialObject([1,2,3]) sage: 1 in c True class CombinatorialObject(SageObject): def index(self, key): """ EXAMPLES:: sage: c = CombinatorialObject([1,2,3]) sage: c.index(1) 0 class CombinatorialClass(Parent): """ __len__ has been removed ! to get the number of element in a combinatorial class, use .cardinality instead. TEST:: sage: len(Partitions(5)) Traceback (most recent call last): ... class CombinatorialClass(Parent): def count(self): """ Deprecated ! Please use .cardinality instead. TEST:: sage: class C(CombinatorialClass): ...     def __iter__(self): ...          return iter([1,2,3]) class CombinatorialClass(Parent): def is_finite(self): """ Returns whether self is finite or not. EXAMPLES:: sage: Partitions(5).is_finite() True sage: Permutations().is_finite() class CombinatorialClass(Parent): """ from sage.rings.all import infinity return self.cardinality() != infinity def __getitem__(self, i): """ Returns the combinatorial object of rank i. EXAMPLES:: sage: p5 = Partitions(5) sage: p5[0] [5] class CombinatorialClass(Parent): def __str__(self): """ Returns a string representation of self. EXAMPLES:: sage: str(Partitions(5)) 'Partitions of the integer 5' """ return self.__repr__() def _repr_(self): """ EXAMPLES:: sage: repr(Partitions(5))   # indirect doctest 'Partitions of the integer 5' """ class CombinatorialClass(Parent): Tests whether or not the combinatorial class contains the object x. This raises a NotImplementedError as a default since _all_ subclasses of CombinatorialClass should override this. Note that we could replace this with a default implementation that just iterates through the elements of the combinatorial class and checks for equality. However, since we use __contains__ for type checking, this operation should be cheap and should be implemented manually for each combinatorial class. EXAMPLES:: sage: C = CombinatorialClass() sage: x in C Traceback (most recent call last): class CombinatorialClass(Parent): """ Compares two different combinatorial classes. For now, the comparison is done just on their repr's. EXAMPLES:: sage: p5 = Partitions(5) sage: p6 = Partitions(6) sage: repr(p5) == repr(p6) class CombinatorialClass(Parent): False """ return cmp(repr(self), repr(x)) def __cardinality_from_iterator(self): """ Default implementation of cardinality which just goes through the iterator of the combinatorial class to count the number of objects. EXAMPLES:: sage: class C(CombinatorialClass): ...     def __iter__(self): ...          return iter([1,2,3]) class CombinatorialClass(Parent): def __call__(self, x): """ Returns x as an element of the combinatorial class's object class. EXAMPLES:: sage: p5 = Partitions(5) sage: a = [2,2,1] sage: type(a) class CombinatorialClass(Parent): """ The default implementation of list which builds the list from the iterator. EXAMPLES:: sage: class C(CombinatorialClass): ...     def __iter__(self): ...          return iter([1,2,3]) class CombinatorialClass(Parent): def __iterator_from_next(self): """ An iterator to use when .first() and .next() are provided. EXAMPLES:: sage: C = CombinatorialClass() sage: C.first = lambda: 0 sage: C.next  = lambda c: c+1 class CombinatorialClass(Parent): f = self.next(f) except (TypeError, ValueError ): break if f is None or f is False : break else: yield f def __iterator_from_previous(self): """ An iterator to use when .last() and .previous() are provided. Note that this requires the combinatorial class to be finite. It is not recommended to implement combinatorial classes using last and previous. EXAMPLES:: sage: C = CombinatorialClass() sage: C.last = lambda: 4 sage: def prev(c): class CombinatorialClass(Parent): l = self.previous(l) except (TypeError, ValueError): break if l == None: break else: li.append(l) return reversed(li) def __iterator_from_unrank(self): """ An iterator to use when .unrank() is provided. EXAMPLES:: sage: C = CombinatorialClass() sage: l = [1,2,3] sage: C.unrank = lambda c: l[c] class CombinatorialClass(Parent): u = self.unrank(r) except (TypeError, ValueError, IndexError): break if u == None: break else: class CombinatorialClass(Parent): def __iterator_from_list(self): """ An iterator to use when .list() is provided() EXAMPLES:: sage: C = CombinatorialClass() sage: C.list = lambda: [1, 2, 3] sage: list(C) # indirect doctest class CombinatorialClass(Parent): def iterator(self): """ Iterator is deprecated for combinatorial classes. EXAMPLES:: sage: p5 = Partitions(3) sage: it = p5.iterator() doctest:...: DeprecationWarning: The usage of iterator for combinatorial classes is deprecated. Please use the class itself See http://trac.sagemath.org/5308 for details. sage: [i for i in it] [[3], [2, 1], [1, 1, 1]] [[3], [2, 1], [1, 1, 1]] sage: [i for i in p5] [[3], [2, 1], [1, 1, 1]] [[3], [2, 1], [1, 1, 1]] """ from sage.misc.superseded import deprecation deprecation(5308, "The usage of iterator for combinatorial classes is deprecated. Please use the class itself") return self.__iter__() def __iter__(self): """ Allows the combinatorial class to be treated as an iterator. Default implementation. EXAMPLES:: sage: p5 = Partitions(5) sage: [i for i in p5] [[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1], [2, 1, 1, 1], [1, 1, 1, 1, 1]] class CombinatorialClass(Parent): def __unrank_from_iterator(self, r): """ Default implementation of unrank which goes through the iterator. EXAMPLES:: sage: C = CombinatorialClass() sage: C.list = lambda: [1,2,3] sage: C.unrank(1) # indirect doctest class CombinatorialClass(Parent): #Set the default implementation of unrank unrank = __unrank_from_iterator def __random_element_from_unrank(self): """ Default implementation of random which uses unrank. EXAMPLES:: sage: C = CombinatorialClass() sage: C.list = lambda: [1,2,3] sage: C.random_element()       # indirect doctest class CombinatorialClass(Parent): def random(self): """ Deprecated. Use self.random_element() instead. EXAMPLES:: sage: C = CombinatorialClass() sage: C.random() Traceback (most recent call last): ... NotImplementedError: Deprecated: use random_element() instead """ raise NotImplementedError, "Deprecated: use random_element() instead" raise NotImplementedError, "Deprecated: use random_element() instead" def __rank_from_iterator(self, obj): """ Default implementation of rank which uses iterator. EXAMPLES:: sage: C = CombinatorialClass() sage: C.list = lambda: [1,2,3] sage: C.rank(3) # indirect doctest class CombinatorialClass(Parent): return r r += 1 raise ValueError rank =  __rank_from_iterator def __first_from_iterator(self): """ Default implementation for first which uses iterator. EXAMPLES:: sage: C = CombinatorialClass() sage: C.list = lambda: [1,2,3] sage: C.first() # indirect doctest class CombinatorialClass(Parent): def __last_from_iterator(self): """ Default implementation for first which uses iterator. EXAMPLES:: sage: C = CombinatorialClass() sage: C.list = lambda: [1,2,3] sage: C.last() # indirect doctest class CombinatorialClass(Parent): def __next_from_iterator(self, obj): """ Default implementation for next which uses iterator. EXAMPLES:: sage: C = CombinatorialClass() sage: C.list = lambda: [1,2,3] sage: C.next(2) # indirect doctest class CombinatorialClass(Parent): def __previous_from_iterator(self, obj): """ Default implementation for next which uses iterator. EXAMPLES:: sage: C = CombinatorialClass() sage: C.list = lambda: [1,2,3] sage: C.previous(2) # indirect doctest class CombinatorialClass(Parent): """ Returns the combinatorial subclass of f which consists of the elements x of self such that f(x) is True. EXAMPLES:: sage: P = Permutations(3).filter(lambda x: x.avoids([1,2])) sage: P.list() [[3, 2, 1]] class CombinatorialClass(Parent): """ Returns the combinatorial class representing the union of self and right_cc. EXAMPLES:: sage: P = Permutations(2).union(Permutations(1)) sage: P.list() [[1, 2], [2, 1], [1]] class FilteredCombinatorialClass(Combina A filtered combinatorial class F is a subset of another combinatorial class C specified by a function f that takes in an element c of C and returns True if and only if c is in F. TESTS:: sage: Permutations(3).filter(lambda x: x.avoids([1,2])) Filtered sublass of Standard permutations of 3 """ class FilteredCombinatorialClass(Combina def __repr__(self): """ EXAMPLES:: sage: P = Permutations(3).filter(lambda x: x.avoids([1,2])) sage: P.__repr__() 'Filtered sublass of Standard permutations of 3' class FilteredCombinatorialClass(Combina def __contains__(self, x): """ EXAMPLES:: sage: P = Permutations(3).filter(lambda x: x.avoids([1,2])) sage: 'cat' in P False class FilteredCombinatorialClass(Combina def cardinality(self): """ EXAMPLES:: sage: P = Permutations(3).filter(lambda x: x.avoids([1,2])) sage: P.cardinality() 1 class FilteredCombinatorialClass(Combina def __iter__(self): """ EXAMPLES:: sage: P = Permutations(3).filter(lambda x: x.avoids([1,2])) sage: list(P) [[3, 2, 1]] class UnionCombinatorialClass(Combinator """ A UnionCombinatorialClass is a union of two other combinatorial classes. TESTS:: sage: P = Permutations(3).union(Permutations(2)) sage: P == loads(dumps(P)) True class UnionCombinatorialClass(Combinator def __repr__(self): """ TESTS:: sage: print repr(Permutations(3).union(Permutations(2))) Union combinatorial class of Union combinatorial class of Standard permutations of 3 and Standard permutations of 2 class UnionCombinatorialClass(Combinator def __contains__(self, x): """ EXAMPLES:: sage: P = Permutations(3).union(Permutations(2)) sage: [1,2] in P True class UnionCombinatorialClass(Combinator def cardinality(self): """ EXAMPLES:: sage: P = Permutations(3).union(Permutations(2)) sage: P.cardinality() 8 class UnionCombinatorialClass(Combinator def list(self): """ EXAMPLES:: sage: P = Permutations(3).union(Permutations(2)) sage: P.list() [[1, 2, 3], class UnionCombinatorialClass(Combinator def __iter__(self): """ EXAMPLES:: sage: P = Permutations(3).union(Permutations(2)) sage: list(P) [[1, 2, 3], class UnionCombinatorialClass(Combinator def first(self): """ EXAMPLES:: sage: P = Permutations(3).union(Permutations(2)) sage: P.first() [1, 2, 3] class UnionCombinatorialClass(Combinator def last(self): """ EXAMPLES:: sage: P = Permutations(3).union(Permutations(2)) sage: P.last() [2, 1] class UnionCombinatorialClass(Combinator def rank(self, x): """ EXAMPLES:: sage: P = Permutations(3).union(Permutations(2)) sage: P.rank(Permutation([2,1])) 7 class UnionCombinatorialClass(Combinator def unrank(self, x): """ EXAMPLES:: sage: P = Permutations(3).union(Permutations(2)) sage: P.unrank(7) [2, 1] class MapCombinatorialClass(Combinatoria def __init__(self, cc, f, name=None): """ TESTS:: sage: Partitions(3).map(attrcall('conjugate')) Image of Partitions of the integer 3 by *.conjugate() """ class MapCombinatorialClass(Combinatoria ############################################################################## from sage.rings.all import infinity class InfiniteAbstractCombinatorialClass(CombinatorialClass): r""" r""" This is an internal class that should not be used directly.  A class which inherits from InfiniteAbstractCombinatorialClass inherits the standard methods list and count. class InfiniteAbstractCombinatorialClass def list(self): """ Returns an error since self is an infinite combinatorial class. EXAMPLES: sage: R = InfiniteAbstractCombinatorialClass() sage: R.list() class InfiniteAbstractCombinatorialClass Traceback (most recent call last): ... NotImplementedError sage: c = iter(Compositions()) # indirect doctest sage: c.next(), c.next(), c.next(), c.next(), c.next(), c.next() ([], [1], [1, 1], [2], [1, 1, 1], [1, 2]) class InfiniteAbstractCombinatorialClass while True: for c in finite(i): yield c i+=1 i+=1 def hurwitz_zeta(s,x,N): """ Returns the value of the \zeta(s,x) to N decimals, where s and x are real. The Hurwitz zeta function is one of the many zeta functions. It defined as .. math:: \zeta(s,x) = \sum_{k=0}^\infty (k+x)^{-s}. \zeta(s,x) = \sum_{k=0}^\infty (k+x)^{-s}. When x = 1, this coincides with Riemann's zeta function. The Dirichlet L-functions may be expressed as a linear combination of Hurwitz zeta functions. Note that if you use floating point inputs, then the results may be slightly off. EXAMPLES:: sage: hurwitz_zeta(3,1/2,6) 8.41439000000000 sage: hurwitz_zeta(11/10,1/2,6) 12.1041000000000 sage: hurwitz_zeta(11/10,1/2,50) 12.10381349568375510570907741296668061903364861809 REFERENCES: - http://en.wikipedia.org/wiki/Hurwitz_zeta_function def hurwitz_zeta(s,x,N): return sage_eval(s[:i]) else: return sage_eval(s[:i])*10**sage_eval(s[i+1:]) return s  ## returns an odd string def combinations(mset,k): without repetitions and is represented by a sorted sublist of mset. Returns the set of all combinations of the multiset mset with k elements. .. warning:: Wraps GAP's Combinations. Hence mset must be a list of objects def combinations(mset,k): GAP interpreter. If mset consists of at all complicated Sage objects, this function does *not* do what you expect. A proper function should be written! (TODO!) EXAMPLES:: sage: mset = [1,1,2,3,4,4,5] sage: combinations(mset,2) [[1, 1], def combinations(mset,k): sage: mset = ["d","a","v","i","d"] sage: combinations(mset,3) ['add', 'adi', 'adv', 'aiv', 'ddi', 'ddv', 'div'] .. note:: For large lists, this raises a string error. def combinations_iterator(mset,n=None): """ Posted by Raymond Hettinger, 2006/03/23, to the Python Cookbook: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/474124 Much faster than combinations. EXAMPLES:: sage: X = combinations_iterator([1,2,3,4,5],3) sage: [x for x in X] [[1, 2, 3], def combinations_iterator(mset,n=None): """ items = mset if n is None: n = len(items) n = len(items) for i in range(len(items)): v = items[i:i+1] if n == 1: def number_of_combinations(mset,k): """ Returns the size of combinations(mset,k). IMPLEMENTATION: Wraps GAP's NrCombinations. .. note:: mset must be a list of integers or strings (i.e., this is very restricted). EXAMPLES:: sage: mset = [1,1,2,3,4,4,5] sage: number_of_combinations(mset,2) 12 def arrangements(mset,k): An arrangement of mset is an ordered selection without repetitions and is represented by a list that contains only elements from mset, but maybe in a different order. arrangements returns the set of arrangements of the multiset mset that contain k elements. IMPLEMENTATION: Wraps GAP's Arrangements. .. warning:: Wraps GAP - hence mset must be a list of objects that have def arrangements(mset,k): interpreter. If mset consists of at all complicated Sage objects, this function does *not* do what you expect. A proper function should be written! (TODO!) EXAMPLES:: sage: mset = [1,1,2,3,4,4,5] sage: arrangements(mset,2) [[1, 1], def arrangements(mset,k): [4, 4], [4, 5], [5, 1], [5, 2], [5, 2], [5, 3], [5, 4]] sage: arrangements( ["c","a","t"], 2 ) def number_of_arrangements(mset,k): """ Returns the size of arrangements(mset,k). Wraps GAP's NrArrangements. EXAMPLES:: sage: mset = [1,1,2,3,4,4,5] sage: number_of_arrangements(mset,2) 22 def derangements(mset): represented by a list that contains exactly the same elements as mset, but possibly in different order. Derangements returns the set of all derangements of a multiset. Wraps GAP's Derangements. .. warning:: Wraps GAP - hence mset must be a list of objects that have def derangements(mset): interpreter. If mset consists of at all complicated Sage objects, this function does *not* do what you expect. A proper function should be written! (TODO!) EXAMPLES:: sage: mset = [1,2,3,4] sage: derangements(mset) [[2, 1, 4, 3], def number_of_derangements(mset): """ Returns the size of derangements(mset). Wraps GAP's NrDerangements. EXAMPLES:: sage: mset = [1,2,3,4] sage: number_of_derangements(mset) 9 def tuples(S,k): repetition and is represented by a list of length k containing elements of set. tuples returns the set of all ordered tuples of length k of the set. EXAMPLES:: sage: S = [1,2] sage: tuples(S,3) [[1, 1, 1], [2, 1, 1], [1, 2, 1], [2, 2, 1], [1, 1, 2], [2, 1, 2], [1, 2, 2], [2, 2, 2]] def tuples(S,k): ['e', 't'], ['i', 't'], ['n', 't'], ['s', 'e'], ['t', 'e'], ['e', 'e'], ['i', 'e'], ['n', 'e'], ['s', 'i'], ['t', 'i'], ['e', 'i'], ['i', 'i'], ['n', 'i'], ['s', 'n'], ['t', 'n'], ['e', 'n'], ['i', 'n'], ['n', 'n']] The Set(...) comparisons are necessary because finite fields are not enumerated in a standard order. :: sage: K. = GF(4, 'a') sage: mset = [x for x in K if x!=0] sage: tuples(mset,2) [[a, a], [a + 1, a], [1, a], [a, a + 1], [a + 1, a + 1], [1, a + 1], [a, 1], [a + 1, 1], [1, 1]] AUTHORS: - Jon Hanke (2006-08) def tuples(S,k): def number_of_tuples(S,k): """ Returns the size of tuples(S,k). Wraps GAP's NrTuples. EXAMPLES:: sage: S = [1,2,3,4,5] sage: number_of_tuples(S,2) 25 def unordered_tuples(S,k): An unordered tuple of length k of set is a unordered selection with repetitions of set and is represented by a sorted list of length k containing elements from set. unordered_tuples returns the set of all unordered tuples of length k of the set. Wraps GAP's UnorderedTuples. .. warning:: Wraps GAP - hence mset must be a list of objects that have def unordered_tuples(S,k): interpreter. If mset consists of at all complicated Sage objects, this function does *not* do what you expect. A proper function should be written! (TODO!) EXAMPLES:: sage: S = [1,2] sage: unordered_tuples(S,3) [[1, 1, 1], [1, 1, 2], [1, 2, 2], [2, 2, 2]] def number_of_unordered_tuples(S,k): """ Returns the size of unordered_tuples(S,k). Wraps GAP's NrUnorderedTuples. EXAMPLES:: sage: S = [1,2,3,4,5] sage: number_of_unordered_tuples(S,2) 15 def permutations(mset): second element appears k_2 times and so on, the number of permutations is |mset|! / (k_1! k_2! \ldots), which is sometimes called a multinomial coefficient. permutations returns the set of all permutations of a multiset. Calls a function written by Mike Hansen, not GAP. EXAMPLES:: sage: mset = [1,1,2,2,2] sage: permutations(mset) [[1, 1, 2, 2, 2], def permutations_iterator(mset,n=None): Do not use this function. It will be deprecated in future version of Sage and eventually removed. Use Permutations instead; instead of for p in permutations_iterator(range(1, m+1), n) use for p in Permutations(m, n). Note that Permutations, unlike this function, treats repeated elements as identical. If you insist on using this now: Returns an iterator (http://docs.python.org/lib/typeiter.html) which can be used in place of permutations(mset) if all you need it for is a 'for' loop. Posted by Raymond Hettinger, 2006/03/23, to the Python Cookbook: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/474124 Note- This function considers repeated elements as different entries, so for example:: sage: from sage.combinat.combinat import permutations, permutations_iterator sage: mset = [1,2,2] sage: permutations(mset) def permutations_iterator(mset,n=None): [2, 2, 1] [2, 1, 2] [2, 2, 1] EXAMPLES:: sage: X = permutations_iterator(range(3),2) sage: [x for x in X] [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]] def number_of_permutations(mset): Do not use this function. It will be deprecated in future version of Sage and eventually removed. Use Permutations instead; instead of number_of_permutations(mset) use Permutations(mset).cardinality(). If you insist on using this now: Returns the size of permutations(mset). AUTHORS: - Robert L. Miller EXAMPLES:: sage: mset = [1,1,2,2,2] sage: number_of_permutations(mset) 10 def cyclic_permutations(mset): """ Returns a list of all cyclic permutations of mset. Treats mset as a list, not a set, i.e. entries with the same value are distinct. AUTHORS: - Emily Kirkman EXAMPLES:: sage: from sage.combinat.combinat import cyclic_permutations, cyclic_permutations_iterator sage: cyclic_permutations(range(4)) [[0, 1, 2, 3], [0, 1, 3, 2], [0, 2, 1, 3], [0, 2, 3, 1], [0, 3, 1, 2], [0, 3, 2, 1]] def cyclic_permutations(mset): ...       print cycle ['a', 'b', 'c'] ['a', 'c', 'b'] Note that lists with repeats are not handled intuitively:: sage: cyclic_permutations([1,1,1]) [[1, 1, 1], [1, 1, 1]] """ def cyclic_permutations_iterator(mset): Iterates over all cyclic permutations of mset in cycle notation. Treats mset as a list, not a set, i.e. entries with the same value are distinct. AUTHORS: - Emily Kirkman EXAMPLES:: sage: from sage.combinat.combinat import cyclic_permutations, cyclic_permutations_iterator sage: cyclic_permutations(range(4)) [[0, 1, 2, 3], [0, 1, 3, 2], [0, 2, 1, 3], [0, 2, 3, 1], [0, 3, 1, 2], [0, 3, 2, 1]] def cyclic_permutations_iterator(mset): ...       print cycle ['a', 'b', 'c'] ['a', 'c', 'b'] Note that lists with repeats are not handled intuitively:: sage: cyclic_permutations([1,1,1]) [[1, 1, 1], [1, 1, 1]] """ def bell_polynomial(n, k): B_{n,k}(x_1, x_2, \ldots, x_{n-k+1}) = \sum_{\sum{j_i}=k, \sum{i j_i} =n} \frac{n!}{j_1!j_2!\ldots} \frac{x_1}{1!}^j_1 \frac{x_2}{2!}^j_2 \ldots INPUT: - n - integer def bell_polynomial(n, k): OUTPUT: - polynomial expression (SymbolicArithmetic) EXAMPLES:: sage: bell_polynomial(6,2) 10*x_3^2 + 15*x_2*x_4 + 6*x_1*x_5 sage: bell_polynomial(6,3) def bell_polynomial(n, k): REFERENCES: - E.T. Bell, "Partition Polynomials" AUTHORS: - Blair Sutton (2009-01-26) def bell_polynomial(n, k): factorial_product *= factorial(count) power_factorial_product *= factorial(part)**count coefficient = factorial(n) / (factorial_product * power_factorial_product) coefficient = factorial(n) / (factorial_product * power_factorial_product) result += coefficient *  prod([vars[i-1] for i in p]) return result return result def fibonacci_sequence(start, stop=None, algorithm=None): r""" Returns an iterator over the Fibonacci sequence, for all fibonacci numbers f_n from n = start up to (but not including) n = stop INPUT: -  start - starting value -  stop - stopping value -  algorithm - default (None) - passed on to fibonacci function (or not passed on if None, i.e., use the default). EXAMPLES:: sage: fibs = [i for i in fibonacci_sequence(10, 20)] sage: fibs [55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181] :: sage: sum([i for i in fibonacci_sequence(100, 110)]) 69919376923075308730013 .. seealso:: :func:fibonacci_xrange AUTHORS: - Bobby Moretti def fibonacci_xrange(start, stop=None, a Returns an iterator over all of the Fibonacci numbers in the given range, including f_n = start up to, but not including, f_n = stop. EXAMPLES:: sage: fibs_in_some_range =  [i for i in fibonacci_xrange(10^7, 10^8)] sage: len(fibs_in_some_range) 4 sage: fibs_in_some_range [14930352, 24157817, 39088169, 63245986] :: sage: fibs = [i for i in fibonacci_xrange(10, 100)] sage: fibs [13, 21, 34, 55, 89] :: sage: list(fibonacci_xrange(13, 34)) [13, 21] A solution to the second Project Euler problem:: sage: sum([i for i in fibonacci_xrange(10^6) if is_even(i)]) 1089154 .. seealso:: :func:fibonacci_sequence AUTHORS: - Bobby Moretti def fibonacci_xrange(start, stop=None, a def bernoulli_polynomial(x, n): r""" Return the nth Bernoulli polynomial evaluated at x. The generating function for the Bernoulli polynomials is .. math:: \frac{t e^{xt}}{e^t-1}= \sum_{n=0}^\infty B_n(x) \frac{t^n}{n!}, \frac{t e^{xt}}{e^t-1}= \sum_{n=0}^\infty B_n(x) \frac{t^n}{n!}, and they are given directly by .. math:: B_n(x) = \sum_{i=0}^n \binom{n}{i}B_{n-i}x^i. One has B_n(x) = - n\zeta(1 - n,x), where \zeta(s,x) is the Hurwitz zeta function. Thus, in a certain sense, the Hurwitz zeta function generalizes the certain sense, the Hurwitz zeta function generalizes the Bernoulli polynomials to non-integer values of n. EXAMPLES:: sage: y = QQ['y'].0 sage: bernoulli_polynomial(y, 5) y^5 - 5/2*y^4 + 5/3*y^3 - 1/6*y def bernoulli_polynomial(x, n): sage: 5*power_sum == bernoulli_polynomial(10, 5) - bernoulli(5) True REFERENCES: - http://en.wikipedia.org/wiki/Bernoulli_polynomials """ try: def bernoulli_polynomial(x, n): if n == 1: return x - ZZ(1)/2 k = n.mod(2) coeffs = [0]*k + sum(([binomial(n, i)*bernoulli(n-i), 0] coeffs = [0]*k + sum(([binomial(n, i)*bernoulli(n-i), 0] for i in range(k, n+1, 2)), []) coeffs[-3] = -n/2 def bernoulli_polynomial(x, n): return x.parent()(coeffs)(x) except TypeError: pass x2 = x*x xi = x**k s = 0
• ## sage/combinat/partition.py

diff --git a/sage/combinat/partition.py b/sage/combinat/partition.py
 a AUTHORS: - Dan Drake (2009-03-28): deprecate RestrictedPartitions and implement Partitions_parts_in - Travis Scrimshaw (2012-01-12): Implemented latex function to Partition_class - Travis Scrimshaw (2012-05-09): Fixed Partitions(-1).list() infinite recursion loop by saying Partitions_n is the empty set. - Travis Scrimshaw (2012-05-11): Fixed bug in inner where if the length was longer than the length of the inner partition, it would include 0's. - Andrew Mathas (2012-06-01): Removed depreciated functions and added compatibility with the PartitionTuple classes.  See :trac:13072 EXAMPLES: There are 5 partitions of the integer 4:: the partition back up from them:: sage: Partition(core=[],quotient=([2, 1], [4], [1, 1, 1])) [11, 5, 5, 3, 2, 2, 2] We can compute the Frobenius coordinates (or beta numbers), and go back We can compute the Frobenius coordinates and go back and forth:: sage: Partition([7,3,1]).frobenius_coordinates() import sage.combinat.skew_partition from sage.rings.integer import Integer import __builtin__ from combinat import CombinatorialClass, CombinatorialObject, cyclic_permutations_iterator, InfiniteAbstractCombinatorialClass import partitions as partitions_ext from sage.combinat.partitions import number_of_partitions as bober_number_of_partitions from sage.libs.all import pari import tableau import permutation import composition from integer_vector import IntegerVectors from cartesian_product import CartesianProduct from integer_list import IntegerListsLex from sage.misc.superseded import deprecation, deprecated_function_alias from sage.misc.prandom import randrange from sage.rings.infinity import infinity from sage.groups.perm_gps.permgroup import PermutationGroup def Partition(mu=None, **keyword): """ def Partition(mu=None, **keyword): * a list (the default) * using exponential notation * by Frobenius coordinates (also called beta numbers) * by Frobenius coordinates * specifying the core and the quotient * specifying the core and the canonical quotient (TODO) See the examples below. def Partition(mu=None, **keyword): return Partition_class(mu) else: raise ValueError, "%s is not a valid partition"%mu elif 'beta_numbers' in keyword and len(keyword)==1: return from_beta_numbers(keyword['beta_numbers']) elif 'core' in keyword and 'quotient' in keyword and len(keyword)==2: return from_core_and_quotient(keyword['core'], keyword['quotient']) elif 'exp' in keyword and len(keyword)==1: return from_exp(keyword['exp']) elif 'frobenius_coordinates' in keyword and len(keyword)==1: return from_frobenius_coordinates(keyword['frobenius_coordinates']) elif 'exp' in keyword and len(keyword)==1: return from_exp(keyword['exp']) elif 'core' in keyword and 'quotient' in keyword and len(keyword)==2: return from_core_and_quotient(keyword['core'], keyword['quotient']) elif 'core' in keyword and 'canonical_quotient' in keyword and len(keyword)==2: raise NotImplementedError elif 'core_and_quotient' in keyword and len(keyword)==1: deprecation(5790, '"core_and_quotient=(*)" is deprecated. Use "core=[*], quotient=[*]" instead.') return from_core_and_quotient(*keyword['core_and_quotient']) else: raise ValueError, 'incorrect syntax for Partition()' def from_frobenius_coordinates(frobenius EXAMPLES:: sage: Partition(frobenius_coordinates=([],[])) sage: Partition(frobenius_coordinates=([],[])) # indirect doctest [] sage: Partition(frobenius_coordinates=([0],[0])) [1] def from_frobenius_coordinates(frobenius raise ValueError, '%s is not a partition, the coordinates need to be strictly decreasing'%str(frobenius_coordinates) return Partition(tmp) def from_beta_numbers(beta): r""" Return the partition corresponding to a sequence of beta numbers. A sequence of beta numbers is a strictly increasing sequence 0 \leq b_1 < \cdots < b_k of non-negative integers. The corresponding partition \mu = (\mu_k, \ldots, \mu_1) is given by \mu_i = [1,i) \setminus \{ b_1, \ldots, b_i \}. This gives a bijection from the set of partitions with at most k non-zero parts to the set of strictly increasing sequences of non-negative integers of length k. .. NOTE:: This function is for internal use only; use Partition(beta_numbers=*) instead. EXAMPLES:: sage: Partition(beta_numbers=[0,1,2,4,5,8]) # indirect doctest [3, 1, 1] sage: Partition(beta_numbers=[0,2,3,6]) [3, 1, 1] """ beta.sort()  # put them into increasing order just in case offset=0 while offset= lq new_w += [ w[i][j] + length*quotient[i][j] for j in range(lq)] new_w += [ w[i][j] + length*components[i][j] for j in range(lq)] new_w += [ w[i][j] for j in range(lq,lw)] new_w.sort(reverse=True) return Partition([new_w[i]+i for i in range(len(new_w))]) class Partition_class(CombinatorialObject): r""" A partition p of a nonnegative integer n is a non-increasing list of positive integers (the *parts* of the partition) with total sum n. A partition can be depicted by a diagram made of rows of cells, where the number of cells in the i^{th} row starting from the top is the i^{th} part of the partition. The coordinate system related to a partition applies from the top to the bottom and from left to right. So, the corners of the partition [5, 3, 1] are [[0,4], [1,2], [2,0]]. EXAMPLES:: sage: mu=Partition([3,2,1,1,1] ); mu [3, 2, 1, 1, 1] sage: nu=Partition([3,2,1,1,1] ); mu [3, 2, 1, 1, 1] sage: mu == nu True sage: mu is nu False sage: mu in Partitions() True sage: mu.parent() Partitions of the integer 8 sage: mu.size() 8 sage: mu.category() Category of objects sage: mu.parent() Partitions of the integer 8 sage: mu[0] 3 sage: mu[1] 2 sage: mu[2] 1 sage: mu.pp() *** ** * * * sage: mu.removable_cells() [(0, 2), (1, 1), (4, 0)] sage: mu.down_list() [[2, 2, 1, 1, 1], [3, 1, 1, 1, 1], [3, 2, 1, 1]] sage: mu.addable_cells() [(0, 3), (1, 2), (2, 1), (5, 0)] sage: mu.up_list() [[4, 2, 1, 1, 1], [3, 3, 1, 1, 1], [3, 2, 2, 1, 1], [3, 2, 1, 1, 1, 1]] sage: mu.conjugate() [5, 2, 1] sage: mu.dominates(nu) True sage: nu.dominates(mu) True """ def _repr_(self, compact=False): r""" Partitions are represented as the underlying list. There is an optional compact argument which gives a more compact representation. EXAMPLE:: sage: mu=Partition([7,7,7,3,3,2,1,1,1,1,1,1,1]); mu [7, 7, 7, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1] sage: mu._repr_(compact=True) '7^3,3^2,2,1^7' """ if compact: exp=self.to_exp()[::-1]  # reversed list of exponents M=max(self) return '%s' % ','.join('%s%s' % (M-m, '' if e==1 else '^%s'%e) for (m,e) in enumerate(exp) if e>0) else: return '[%s]' % ', '.join('%s'%m for m in self) def level(self): """ Returns the level of self, which is always 1. This method exists only for compatibility with :class:PartitionTuples. EXAMPLE:: sage: Partition([4,3,2]).level() 1 """ return 1 def components(self): """ Return a list containing the shape of self. This method exists only for compatibility with :class:PartitionTuples. EXAMPLE:: sage: Partition([3,2]).components() [[3, 2]] """ return [ self ] def Young_subgroup(self): """ Return the corresponding Young, or parabolic, subgroup of the symmetric group. EXAMPLE:: sage: Partition([4,2]).Young_subgroup() Permutation Group with generators [(), (5,6), (3,4), (2,3), (1,2)] """ gens=[] m=0 for row in self: gens.extend([ (c,c+1) for c in range(m+1,m+row)]) m+=row gens.append( range(1,self.size()+1) )  # to ensure we get a subgroup of Sym_n return PermutationGroup( gens ) def Young_subgroup_generators(self): """ Return an indexing set for the generators of the corresponding Young subgroup. EXAMPLE:: sage: Partition([4,2]).Young_subgroup_generators() [1, 2, 3, 5] """ gens=[] m=0 for row in self: gens.extend([c for c in range(m+1,m+row)]) m+=row return gens def _latex_(self): r""" Returns a LaTeX version of self. Returns a LaTeX version of self. EXAMPLES:: sage: latex(Partition([2, 1])) sage: latex(Partition([2, 1]))       # indirect doctest {\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}} \raisebox{-.6ex}{\$\begin{array}[b]{cc} \cline{1-1}\cline{2-2} class Partition_class(CombinatorialObjec """ if len(self._list) == 0: return "{\\emptyset}" from sage.combinat.output import tex_from_array return tex_from_array([ ["\\phantom{x}"]*row_size for row_size in self._list ]) def ferrers_diagram(self): """ Return the Ferrers diagram of pi. INPUT: -  pi - a partition, given as a list of integers. r""" Return the Ferrers diagram of self. EXAMPLES:: class Partition_class(CombinatorialObjec return sage.combinat.skew_partition.SkewPartition([self[:], p]) def power(self, k): """ r""" Returns the cycle type of the k-th power of any permutation with cycle type self (thus describes the powermap of symmetric groups). Wraps GAP's PowerPartition. EXAMPLES:: sage: p = Partition([5,3]) sage: p.power(1) [5, 3] class Partition_class(CombinatorialObjec [5, 3] sage: Partition([3,2,1]).power(3) [2, 1, 1, 1, 1] Now let us compare this to the power map on S_8:: sage: G = SymmetricGroup(8) sage: g = G([(1,2,3,4,5),(6,7,8)]) sage: g class Partition_class(CombinatorialObjec res.extend( [ZZ(i//g)]*int(g) ) res.sort(reverse=True) return Partition_class( res ) def next(self): """ Returns the partition that lexicographically follows the partition p. If p is the last partition, then it returns False. EXAMPLES:: sage: Partition([4]).next() [3, 1] sage: Partition([1,1,1,1]).next() class Partition_class(CombinatorialObjec for i in p: n += i m += 1 next_p = p[:] + [1]*(n - len(p)) #Check to see if we are at the last (all ones) partition class Partition_class(CombinatorialObjec #Let h be the number of non-one  entries in the #partition h = 0 h = 0 for i in next_p: if i != 1: h += 1 class Partition_class(CombinatorialObjec next_p[h-1] = t return Partition_class(next_p[:m]) def size(self): """ Returns the size of partition p. EXAMPLES:: sage: Partition([2,2]).size() 4 sage: Partition([3,2,1]).size() class Partition_class(CombinatorialObjec def sign(self): r""" Returns the sign of any permutation with cycle type self. This function corresponds to a homomorphism from the symmetric group S_n into the cyclic group of order 2, whose kernel is exactly the alternating group A_n. Partitions of sign 1 are called even partitions while partitions of sign -1 are called odd. EXAMPLES:: sage: Partition([5,3]).sign() 1 sage: Partition([5,2]).sign() -1 Zolotarev's lemma states that the Legendre symbol \left(\frac{a}{p}\right) for an integer a \pmod p (p a prime number), can be computed class Partition_class(CombinatorialObjec p_a the permutation of the residue classes \pmod p induced by modular multiplication by a, provided p does not divide a. We verify this in some examples. :: sage: F = GF(11) sage: a = F.multiplicative_generator();a 2 sage: plist = [int(a*F(x)) for x in range(1,11)]; plist [2, 4, 6, 8, 10, 1, 3, 5, 7, 9] This corresponds to the permutation (1, 2, 4, 8, 5, 10, 9, 7, 3, 6) (acting the set \{1,2,...,10\}) and to the partition [10]. :: sage: p = PermutationGroupElement('(1, 2, 4, 8, 5, 10, 9, 7, 3, 6)') sage: p.sign() -1 class Partition_class(CombinatorialObjec -1 sage: kronecker_symbol(11,2) -1 Now replace 2 by 3:: sage: plist = [int(F(3*x)) for x in range(1,11)]; plist [3, 6, 9, 1, 4, 7, 10, 2, 5, 8] sage: range(1,11) class Partition_class(CombinatorialObjec 1 sage: Partition([5,1,1,1,1,1]).sign() 1 In both cases, Zolotarev holds. REFERENCES: - http://en.wikipedia.org/wiki/Zolotarev's_lemma class Partition_class(CombinatorialObjec r""" Returns a generator for partitions that can be obtained from pi by adding a cell. EXAMPLES:: sage: [p for p in Partition([2,1,1]).up()] [[3, 1, 1], [2, 2, 1], [2, 1, 1, 1]] sage: [p for p in Partition([3,2]).up()] class Partition_class(CombinatorialObjec """ Returns a list of the partitions that can be formed from the partition p by adding a cell. EXAMPLES:: sage: Partition([2,1,1]).up_list() [[3, 1, 1], [2, 2, 1], [2, 1, 1, 1]] sage: Partition([3,2]).up_list() class Partition_class(CombinatorialObjec r""" Returns a generator for partitions that can be obtained from p by removing a cell. EXAMPLES:: sage: [p for p in Partition([2,1,1]).down()] [[1, 1, 1], [2, 1]] sage: [p for p in Partition([3,2]).down()] [[2, 2], [3, 1]] sage: [p for p in Partition([3,2,1]).down()] [[2, 2, 1], [3, 1, 1], [3, 2]] TESTS: We check that #11435 is actually fixed:: sage: Partition([]).down_list() #indirect doctest [] """ class Partition_class(CombinatorialObjec """ Returns a list of the partitions that can be obtained from the partition p by removing a cell. EXAMPLES:: sage: Partition([2,1,1]).down_list() [[1, 1, 1], [2, 1]] sage: Partition([3,2]).down_list() [[2, 2], [3, 1]] sage: Partition([3,2,1]).down_list() [[2, 2, 1], [3, 1, 1], [3, 2]] sage: Partition([]).down_list()  #checks trac #11435 sage: Partition([]).down_list()  #checks :trac:11435 [] """ return [p for p in self.down()] def frobenius_coordinates(self): """ Returns a couple of sequences of beta numbers aka Frobenius coordinates of the partition. These are two striclty decreasing sequences of nonnegative integers, of the same length. """ Returns a pair of sequences of Frobenius coordinates aka beta numbers of the partition. These are two strictly decreasing sequences of nonnegative integers of the same length. EXAMPLES:: sage: Partition([]).frobenius_coordinates() ([], []) sage: Partition([1]).frobenius_coordinates() class Partition_class(CombinatorialObjec a = filter(lambda x: x>=0, [mu[i]-i-1 for i in range(len(b))]) return (a,b) beta_numbers = frobenius_coordinates def frobenius_rank(self): """ Returns the Frobenius rank of the partition, which is the number of cells on the main diagonal. EXAMPLES:: sage: Partition([]).frobenius_rank() 0 sage: Partition([1]).frobenius_rank() class Partition_class(CombinatorialObjec return len(filter(lambda x: x>=0, [val-i-1 for i, val in enumerate(muconj)])) def beta_numbers(self, length=None): """ Return the set of beta numbers corresponding to self. The optional argument length specifies the length of the beta set (which must be at least the length of self). For more on beta numbers, see :meth:frobenius_coordinates. EXAMPLES:: sage: Partition([4,3,2]).beta_numbers() [6, 4, 2] sage: Partition([4,3,2]).beta_numbers(5) [8, 6, 4, 1, 0] """ if length==None: length=self.length() elif lengthself.length(): beta.extend( range(length-self.length()-1,-1,-1) ) return beta def dominates(self, p2): r""" Returns True if partition p1 dominates partitions p2. Otherwise, it returns False. EXAMPLES:: sage: p = Partition([3,2]) sage: p.dominates([3,1]) True class Partition_class(CombinatorialObjec min_length = min(len(p1), len(p2)) if min_length == 0: return len(p1) >= len(p2) for i in range(min_length): sum1 += p1[i] sum2 += p2[i] class Partition_class(CombinatorialObjec """ Return the coordinates of the cells of self. Coordinates are given as (row-index, column-index) and are 0 based. EXAMPLES:: sage: Partition([2,2]).cells() [(0, 0), (0, 1), (1, 0), (1, 1)] sage: Partition([3,2]).cells() class Partition_class(CombinatorialObjec res.append( (i,j) ) return res boxes = deprecated_function_alias(7515, cells) def generalized_pochhammer_symbol(self, a, alpha): r""" Returns the generalized Pochhammer symbol (a)_{self}^{(\alpha)}. This is the product over all cells (i,j) in p of a - (i-1) / \alpha + j - 1. EXAMPLES:: sage: Partition([2,2]).generalized_pochhammer_symbol(2,1) 12 """ class Partition_class(CombinatorialObjec perm = permutation.Permutation(word) return perm.robinson_schensted()[1] associated = deprecated_function_alias(6655, conjugate) def arm_length(self, i, j): """ r""" Returns the length of the arm of cell (i,j) in partition p. INPUT: i and j: two integers OUPUT: an integer or a ValueError OUTPUT: An integer or a ValueError The arm of cell (i,j) is the cells that appear to the right of cell (i,j). Note that i and j are 0-based indices. If your coordinates are class Partition_class(CombinatorialObjec if i < len(p) and j < p[i]: return p[i]-(j+1) else: raise ValueError, "The cells is not in the diagram" arm = deprecated_function_alias(6655, arm_length) raise ValueError, "The cell is not in the diagram" def arm_lengths(self, flat=False): """ class Partition_class(CombinatorialObjec (i,j). Note that i and j are 0-based indices. If your coordinates are in the form (i,j), use Python's \*-operator. Examples:: EXAMPLES:: sage: Partition([4,4,3,1]).arm_cells(1,1) [(1, 2), (1, 3)] class Partition_class(CombinatorialObjec sage: Partition([]).arm_cells(0,0) Traceback (most recent call last): ... ValueError: The cells is not in the diagram ValueError: The cell is not in the diagram """ p = self if i < len(p) and j < p[i]: return [ (i, x) for x in range(j+1, p[i]) ] else: raise ValueError, "The cells is not in the diagram" raise ValueError, "The cell is not in the diagram" def leg_length(self, i, j): """ class Partition_class(CombinatorialObjec INPUT: i and j: two integers OUPUT: an integer or a ValueError OUTPUT: an integer or a ValueError The leg of cell (i,j) is defined to be the cells below it in partition p (in English convention). Note that i and j are 0-based. If your class Partition_class(CombinatorialObjec if j < len(conj) and i < conj[j]: return conj[j]-(i+1) else: raise ValueError, "The cells is not in the diagram" leg = deprecated_function_alias(6655, leg_length) raise ValueError, "The cell is not in the diagram" def leg_lengths(self, flat=False): """ class Partition_class(CombinatorialObjec p (in English convention). Note that i and j are 0-based. If your coordinates are in the form (i,j), use Python's \*-operator. Examples:: EXAMPLES:: sage: Partition([4,4,3,1]).leg_cells(1,1) [(2, 1)] class Partition_class(CombinatorialObjec sage: Partition([]).leg_cells(0,0) Traceback (most recent call last): ... ValueError: The cells is not in the diagram ValueError: The cell is not in the diagram """ l = self.leg_length(i, j) return [(x, j) for x in range(i+1, i+l+1)] class Partition_class(CombinatorialObjec """ Returns a list of the partitions dominated by n. If n is specified, then it only returns the ones with = rows rows. EXAMPLES:: sage: Partition([3,2,1]).dominate() [[3, 2, 1], [3, 1, 1, 1], [2, 2, 2], [2, 2, 1, 1], [2, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1]] sage: Partition([3,2,1]).dominate(rows=3) class Partition_class(CombinatorialObjec """ Returns True if p2 is a partition whose Ferrers diagram is contained in the Ferrers diagram of self EXAMPLES:: sage: p = Partition([3,2,1]) sage: p.contains([2,1]) True class Partition_class(CombinatorialObjec False """ return len(self) >= len(x) and all(self[i] >= x[i] for i in range(len(x))) def hook_product(self, a): """ Returns the Jack hook-product. EXAMPLES:: sage: Partition([3,2,1]).hook_product(x) (x + 2)^2*(2*x + 3) sage: Partition([2,2]).hook_product(x) 2*(x + 1)*(x + 2) """ nu = self.conjugate() res = 1 for i in range(len(self)): class Partition_class(CombinatorialObjec def hook_polynomial(self, q, t): """ Returns the two-variable hook polynomial. EXAMPLES:: sage: R. = PolynomialRing(QQ) sage: a = Partition([2,2]).hook_polynomial(q,t) sage: a == (1 - t)*(1 - q*t)*(1 - t^2)*(1 - q*t^2) class Partition_class(CombinatorialObjec hook of cell (i,j) is defined as the cells to the right or below (in the English convention). Note that i and j are 0-based. If your coordinates are in the form (i,j), use Python's \*-operator. EXAMPLES:: sage: p = Partition([2,2,1]) sage: p.hook_length(0, 0) 4 sage: p.hook_length(0, 1) 2 sage: p.hook_length(2, 0) 1 1 sage: Partition([3,3]).hook_length(0, 0) 4 4 sage: cell = [0,0]; Partition([3,3]).hook_length(*cell) 4 """ return self.leg_length(i,j)+self.arm_length(i,j)+1 hook = deprecated_function_alias(7515, hook_length) def hooks(self): """ Returns a sorted list of the hook lengths in self. class Partition_class(CombinatorialObjec res += row res.sort(reverse=True) return res def hook_lengths(self): r""" Returns a tableau of shape p with the cells filled in with the hook lengths. In each cell, put the sum of one plus the number of cells horizontally to the right and vertically below the cell (the hook length). For example, consider the partition [3,2,1] of 6 with Ferrers Diagram:: class Partition_class(CombinatorialObjec 5 3 1 3 1 1 EXAMPLES:: sage: Partition([2,2,1]).hook_lengths() [[4, 2], [3, 1], [1]] sage: Partition([3,3]).hook_lengths() class Partition_class(CombinatorialObjec [[3, 2], [2, 1]] sage: Partition([5]).hook_lengths() [[5, 4, 3, 2, 1]] REFERENCES: - http://mathworld.wolfram.com/HookLengthFormula.html class Partition_class(CombinatorialObjec Returns the upper hook length of the cell (i,j) in self. When alpha == 1, this is just the normal hook length. As usual, indices are 0 based. The upper hook length of a cell (i,j) in a partition \kappa is defined by .. math:: h_*^\kappa(i,j) = \kappa_j^\prime-i+\alpha(\kappa_i - j+1). EXAMPLES:: sage: p = Partition([2,1]) sage: p.upper_hook(0,0,1) 3 class Partition_class(CombinatorialObjec r""" Returns the upper hook lengths of the partition. When alpha == 1, these are just the normal hook lengths. The upper hook length of a cell (i,j) in a partition \kappa is defined by .. math:: h_*^\kappa(i,j) = \kappa_j^\prime-i+1+\alpha(\kappa_i - j). EXAMPLES:: sage: Partition([3,2,1]).upper_hook_lengths(x) [[3*x + 2, 2*x + 1, x], [2*x + 1, x], [x]] sage: Partition([3,2,1]).upper_hook_lengths(1) class Partition_class(CombinatorialObjec r""" Returns the lower hook length of the cell (i,j) in self. When alpha == 1, this is just the normal hook length. Indices are 0-based. The lower hook length of a cell (i,j) in a partition \kappa is defined by .. math:: h_*^\kappa(i,j) = \kappa_j^\prime-i+1+\alpha(\kappa_i - j). EXAMPLES:: sage: p = Partition([2,1]) sage: p.lower_hook(0,0,1) 3 class Partition_class(CombinatorialObjec r""" Returns the lower hook lengths of the partition. When alpha == 1, these are just the normal hook lengths. The lower hook length of a cell (i,j) in a partition \kappa is defined by .. math:: h_\kappa^*(i,j) = \kappa_j^\prime-i+\alpha(\kappa_i - j + 1). EXAMPLES:: sage: Partition([3,2,1]).lower_hook_lengths(x) [[2*x + 3, x + 2, 1], [x + 2, 1], [1]] sage: Partition([3,2,1]).lower_hook_lengths(1) class Partition_class(CombinatorialObjec Returns sum([i\*p[i] for i in range(len(p))]). It is also the sum of the leg length of every cell in b, or the sum of binomial(s[i],2) for s the conjugate partition of p. EXAMPLES:: sage: Partition([2,2]).weighted_size() 2 sage: Partition([3,3,3]).weighted_size() class Partition_class(CombinatorialObjec def length(self): """ Returns the number of parts in self. EXAMPLES:: sage: Partition([3,2]).length() 2 sage: Partition([2,2,1]).length() class Partition_class(CombinatorialObjec Return a list of the multiplicities of the parts of a partition. Use the optional parameter k to get a return list of length at least k. EXAMPLES:: sage: Partition([3,2,2,1]).to_exp() [1, 2, 1] sage: Partition([3,2,2,1]).to_exp(5) class Partition_class(CombinatorialObjec def evaluation(self): """ Returns the evaluation of the partition. EXAMPLES:: sage: Partition([4,3,1,1]).evaluation() [2, 0, 1, 1] """ class Partition_class(CombinatorialObjec Including the optional parameters t and q gives the q-t analog which is the former product times times .. math:: \prod_{i=1}^{\mathrm{length}(p)} \frac{1 - q^{p_i}}{1 - t^{p_i}}. EXAMPLES:: sage: Partition([2,2,1]).centralizer_size() 8 sage: Partition([2,2,2]).centralizer_size() 48 48 REFERENCES: - Kerber, A. 'Algebraic Combinatorics via Finite Group Action', class Partition_class(CombinatorialObjec Returns a factor for the number of permutations with cycle type self. self.aut() returns 1^{j_1}j_1! \cdots n^{j_n}j_n! where j_k is the number of parts in self equal to k. is the number of parts in self equal to k. The number of permutations having p as a cycle type is given by .. math:: \frac{n!}{1^{j_1}j_1! \cdots n^{j_n}j_n!} . EXAMPLES:: sage: Partition([2,1]).aut() 2 """ m = self.to_exp() return prod([(i+1)**m[i]*factorial(m[i]) for i in range(len(m)) if m[i] > 0]) def content(self, i, j): def content(self, r, c, multicharge=[0]): r""" Returns the content statistic of the given cell, which is simply defined by j - i. This doesn't technically depend on the partition, but is included here because it is often useful in the context of partitions. Returns the content of the cell at row r and column c. The content of a cell is c - r. For consistency with partition tuples there is also an optional multicharge argument which is an offset to the usual content. By setting the multicharge equal to the 0-element the ring \ZZ/e\ZZ the corresponding e-residue will be returned. This is the content modulo e. The content (and residue) do not strictly depend on the partition, however, this method is included because it is often useful in the context of partitions. EXAMPLES:: sage: Partition([2,1]).content(0,1) 1 sage: Partition([2,1]).content(1,0) -1 sage: p = Partition([3,2]) sage: sum([p.content(*c) for c in p.cells()]) 2 """ return j - i and now we return the 3-residue of a cell:: sage: Partition([2,1]).content(1,0, multicharge=[IntegerModRing(3)(0)]) 2 """ return c - r + multicharge[0] def conjugacy_class_size(self): """ Returns the size of the conjugacy class of the symmetric group indexed by the partition p. EXAMPLES:: sage: Partition([2,2,2]).conjugacy_class_size() 15 sage: Partition([2,2,1]).conjugacy_class_size() 15 sage: Partition([2,1,1]).conjugacy_class_size() sage: Partition([2,1,1]).conjugacy_class_size() 6 REFERENCES: - Kerber, A. 'Algebraic Combinatorics via Finite Group Action' 1.3 p24 """ .. [Ker]  Kerber, A. 'Algebraic Combinatorics via Finite Group Action' 1.3 p24 """ return factorial(sum(self))/self.centralizer_size() def corners(self): """ Returns a list of the corners of the partitions. These are the positions where we can remove a cell. Indices are of the form (i,j) where i is the row-index and j is the column-index, and are positions where we can remove a cell. Indices are of the form (i,j) where i is the row-index and j is the column-index, and are 0-based. EXAMPLES:: class Partition_class(CombinatorialObjec return map(tuple, lcors) removable_cells = corners            # for compatibility with partition tuples def outside_corners(self): """ Returns a list of the positions where we can add a cell so that the shape is still a partition. Indices are of the form (i,j) where i is the row-index and j is the column-index, and are 0-based. shape is still a partition. Indices are of the form (i,j) where i is the row-index and j is the column-index, and are 0-based. EXAMPLES:: class Partition_class(CombinatorialObjec return res addable_cells=outside_corners        # for compatibility with partition tuples def rim(self): r""" Returns the rim of self. class Partition_class(CombinatorialObjec #Select the r-core return Partition_class(filter(lambda x: x != 0, part)) r_core = deprecated_function_alias(11165, core) def quotient(self, length): """ Returns the quotient of the partition  -- in the literature the class Partition_class(CombinatorialObjec a.reverse() result[e] = a return tuple(map(Partition_class, result)) r_quotient = deprecated_function_alias(7515, quotient) from partition_tuple import PartitionTuple return PartitionTuple(result)  #tuple(map(Partition_class, result)) def is_core(self, k): r""" class Partition_class(CombinatorialObjec raise ValueError, "[%s, %s] is not an addable cell"%(i,j) add_box = deprecated_function_alias(7515, add_cell) def remove_cell(self, i, j = None): """ class Partition_class(CombinatorialObjec else: return Partition(self[:i] + [ self[i:i+1][0] - 1 ] + self[i+1:]) remove_box = deprecated_function_alias(7515, remove_cell) def k_skew(self, k): r""" Returns the k-skew partition. The k-skew diagram of a k-bounded partition is the skew diagram denoted \lambda/^k satisfying the conditions: 1. row i of \lambda/^k has length \lambda_i 2. no cell in \lambda/^k has hook-length exceeding k denoted \lambda/^k satisfying the conditions: 1. row i of \lambda/^k has length \lambda_i 2. no cell in \lambda/^k has hook-length exceeding k 3. every square above the diagram of \lambda/^k has hook length exceeding k. REFERENCES: - Lapointe, L. and Morse, J. 'Order Ideals in Weak Subposets of Young's Lattice and Associated Unimodality Conjectures' EXAMPLES:: sage: p = Partition([4,3,2,2,1,1]) sage: p.k_skew(4) [[9, 5, 3, 2, 1, 1], [5, 2, 1]] class Partition_class(CombinatorialObjec #Find the k-skew diagram of the partition formed #by removing the first row s = Partition(self[1:]).k_skew(k) s_inner = s.inner() s_outer = s.outer() s_conj_rl = s.conjugate().row_lengths() #Find the leftmost column with less than # or equal to kdiff cells kdiff = k - self[0] if s_outer == []: spot = 0 else: class Partition_class(CombinatorialObjec def to_core(self, k): r""" Maps the k-bounded partition self to its corresponding k+1-core. See also :meth:k_skew. EXAMPLES:: sage: p = Partition([4,3,2,2,1,1]) sage: c = p.to_core(4); c [9, 5, 3, 2, 1, 1] class Partition_class(CombinatorialObjec def to_list(self): r""" Return self as a list. EXAMPLES:: sage: p = Partition([2,1]).to_list(); p [2, 1] sage: type(p) TESTS:: sage: p = Partition([2,1]) sage: pl = p.to_list() sage: pl[0] = 0; p class Partition_class(CombinatorialObjec """ Returns a list of all the partitions that can be obtained by adding a vertical border strip of length k to self. EXAMPLES:: sage: Partition([]).add_vertical_border_strip(0) [[]] sage: Partition([]).add_vertical_border_strip(2) class Partition_class(CombinatorialObjec """ Returns a list of all the partitions that can be obtained by adding a horizontal border strip of length k to self. EXAMPLES:: sage: Partition([]).add_horizontal_border_strip(0) [[]] sage: Partition([]).add_horizontal_border_strip(2) class Partition_class(CombinatorialObjec sage: Partition([3,2,2]).add_horizontal_border_strip(2) [[3, 2, 2, 2], [3, 3, 2, 1], [4, 2, 2, 1], [4, 3, 2], [5, 2, 2]] TODO: reimplement like remove_horizontal_border_strip using IntegerListsLex .. TODO:: reimplement like remove_horizontal_border_strip using IntegerListsLex """ conj = self.conjugate().to_list() shelf = [] class Partition_class(CombinatorialObjec horizontal border strip of length k EXAMPLES:: sage: Partition([5,3,1]).remove_horizontal_border_strip(0).list() [[5, 3, 1]] [[5, 3, 1]] sage: Partition([5,3,1]).remove_horizontal_border_strip(1).list() [[5, 3], [5, 2, 1], [4, 3, 1]] sage: Partition([5,3,1]).remove_horizontal_border_strip(2).list() class Partition_class(CombinatorialObjec [] The result is returned as a combinatorial class:: sage: Partition([5,3,1]).remove_horizontal_border_strip(5) The subpartitions of [5, 3, 1] obtained by removing an horizontal border strip of length 5 TESTS:: sage: Partition([3,2,2]).remove_horizontal_border_strip(2).list() [[3, 2], [2, 2, 1]] sage: Partition([3,2,2]).remove_horizontal_border_strip(2).first().parent() class Partition_class(CombinatorialObjec def k_conjugate(self, k): """ Returns the k-conjugate of the partition. The k-conjugate is the partition that is given by the columns of the k-skew diagram of the partition. EXAMPLES:: sage: p = Partition([4,3,2,2,1,1]) sage: p.k_conjugate(4) [3, 2, 2, 1, 1, 1, 1, 1, 1] """ return Partition(self.k_skew(k).conjugate().row_lengths()) def parent(self): """ Returns the combinatorial class of partitions of sum(self). EXAMPLES:: sage: Partition([3,2,1]).parent() Partitions of the integer 6 """ class Partition_class(CombinatorialObjec """ This is a statistic on a cell c=(i,j) in the diagram of partition p given by .. math:: [ (1 - q^{arm_length(c)} * t^{leg_length(c) + 1}) ] /            [ (1 - q^{arm_length(c) + 1} * t^{leg_length(c)}) ] [ (1 - q^{arm_length(c)} * t^{leg_length(c) + 1}) ] /            [ (1 - q^{arm_length(c) + 1} * t^{leg_length(c)}) ] EXAMPLES:: sage: Partition([3,2,1]).arms_legs_coeff(1,1) (-t + 1)/(-q + 1) sage: Partition([3,2,1]).arms_legs_coeff(0,0) class Partition_class(CombinatorialObjec """ Returns a list of the standard tableaux of size self.size() whose atom is equal to self. EXAMPLES:: sage: Partition([2,1]).atom() [[[1, 2], [3]]] sage: Partition([3,2,1]).atom() class Partition_class(CombinatorialObjec def k_atom(self, k): """ EXAMPLES:: sage: p = Partition([3,2,1]) sage: p.k_atom(1) [] class Partition_class(CombinatorialObjec [[1, 1, 1, 2, 3], [2]]] sage: Partition([3,2,1]).k_atom(4) [[[1, 1, 1], [2, 2], [3]], [[1, 1, 1, 3], [2, 2]]] TESTS:: sage: Partition([1]).k_atom(1) [[[1]]] sage: Partition([1]).k_atom(2) class Partition_class(CombinatorialObjec def k_split(self, k): """ Returns the k-split of self. EXAMPLES:: sage: Partition([4,3,2,1]).k_split(3) [] sage: Partition([4,3,2,1]).k_split(4) class Partition_class(CombinatorialObjec if part != []: res.append(part) return res def jacobi_trudi(self): """ EXAMPLES:: sage: part = Partition([3,2,1]) sage: jt = part.jacobi_trudi(); jt [h[3] h[1]    0] class Partition_class(CombinatorialObjec def character_polynomial(self): r""" Returns the character polynomial associated to the partition self. Returns the character polynomial associated to the partition self. The character polynomial q_\mu is defined by .. math:: q_\mu(x_1, x_2, \ldots, x_k) = \downarrow \sum_{\alpha \vdash k}\frac{ \chi^\mu_\alpha }{1^{a_1}2^{a_2}\cdots k^{a_k}a_1!a_2!\cdots a_k!} \prod_{i=1}^{k} (ix_i-1)^{a_i} q_\mu(x_1, x_2, \ldots, x_k) = \downarrow \sum_{\alpha \vdash k}\frac{ \chi^\mu_\alpha }{1^{a_1}2^{a_2}\cdots k^{a_k}a_1!a_2!\cdots a_k!} \prod_{i=1}^{k} (ix_i-1)^{a_i} where a_i is the multiplicity of i in \alpha. It is computed in the following manner. 1. Expand the Schur function s_\mu in the power-sum basis. 2. Replace each p_i with ix_i-1 basis. 2. Replace each p_i with ix_i-1 3. Apply the umbral operator \downarrow to the resulting polynomial. EXAMPLES:: sage: Partition([1]).character_polynomial() x - 1 sage: Partition([1,1]).character_polynomial() class Partition_class(CombinatorialObjec sage: Partition([2,1]).character_polynomial() 1/3*x0^3 - 2*x0^2 + 8/3*x0 - x2 """ #Create the polynomial ring we will use k = self.size() P = PolynomialRing(QQ, k, 'x') class Partition_class(CombinatorialObjec ################################################## def number_of_partitions_list(n,k=None): r""" This function will be deprecated in a future version of Sage and eventually removed. Use Partitions(n).cardinality() or Partitions(n, length=k).cardinality() instead. Original docstring follows. Returns the size of partitions_list(n,k). Wraps GAP's NrPartitions. It is possible to associate with every partition of the integer n a conjugacy class of permutations in the symmetric group on n points and vice versa. Therefore p(n) = NrPartitions(n) is the number of conjugacy classes of the symmetric group on n points. number_of_partitions(n) is also available in PARI, however the speed seems the same until n is in the thousands (in which case PARI is faster). EXAMPLES:: sage: partition.number_of_partitions_list(10,2) 5 sage: partition.number_of_partitions_list(10) 42 A generating function for p(n) is given by the reciprocal of Euler's function: .. math:: \sum_{n=0}^\infty p(n)x^n = \prod_{k=1}^\infty \left(\frac {1}{1-x^k} \right). Sage verifies that the first several coefficients do instead agree:: sage: q = PowerSeriesRing(QQ, 'q', default_prec=9).gen() sage: prod([(1-q^k)^(-1) for k in range(1,9)])  ## partial product of 1 + q + 2*q^2 + 3*q^3 + 5*q^4 + 7*q^5 + 11*q^6 + 15*q^7 + 22*q^8 + O(q^9) sage: [partition.number_of_partitions_list(k) for k in range(2,10)] [2, 3, 5, 7, 11, 15, 22, 30] REFERENCES: - http://en.wikipedia.org/wiki/Partition\_(number\_theory) """ if k is None: ans=gap.eval("NrPartitions(%s)"%(ZZ(n))) else: ans=gap.eval("NrPartitions(%s,%s)"%(ZZ(n),ZZ(k))) return ZZ(ans) ###################### # Ordered Partitions # ###################### def OrderedPartitions(n, k=None): Returns the combinatorial class of ordered partitions of n. If k is specified, then only the ordered partitions of length k are returned. .. note:: It is recommended that you use Compositions instead as OrderedPartitions wraps GAP. See also ordered_partitions. EXAMPLES:: sage: OrderedPartitions(3) Ordered partitions of 3 sage: OrderedPartitions(3).list() class OrderedPartitions_nk(Combinatorial def __init__(self, n, k=None): """ EXAMPLES:: sage: o = OrderedPartitions(4,2) sage: o == loads(dumps(o)) True class OrderedPartitions_nk(Combinatorial def __contains__(self, x): """ EXAMPLES:: sage: o = OrderedPartitions(4,2) sage: [2,1] in o False class OrderedPartitions_nk(Combinatorial def __repr__(self): """ EXAMPLES:: sage: OrderedPartitions(3).__repr__() 'Ordered partitions of 3' sage: OrderedPartitions(3,2).__repr__() class OrderedPartitions_nk(Combinatorial if self.k is not None: string += " of length %s"%self.k return string def list(self): """ EXAMPLES:: sage: OrderedPartitions(3).list() [[3], [2, 1], [1, 2], [1, 1, 1]] sage: OrderedPartitions(3,2).list() class OrderedPartitions_nk(Combinatorial def cardinality(self): """ Return the cardinality of self. EXAMPLES:: sage: OrderedPartitions(3).cardinality() 4 sage: OrderedPartitions(3,2).cardinality() class PartitionsGreatestLE(IntegerListsL Returns the combinatorial class of all (unordered) "restricted" partitions of the integer n having parts less than or equal to the integer k. EXAMPLES:: sage: PartitionsGreatestLE(10,2) Partitions of 10 having parts less than or equal to 2 sage: PartitionsGreatestLE(10,2).list() class PartitionsGreatestLE(IntegerListsL """ IntegerListsLex.__init__(self, n, max_slope = 0, min_part=1, max_part = k) self.k = k def _repr_(self): """ TESTS:: sage: PartitionsGreatestLE(10, 2).__repr__() 'Partitions of 10 having parts less than or equal to 2' """ class PartitionsGreatestLE_nk(Partitions def __setstate__(self, data): r""" TESTS:: sage: p = loads('x\x9c\x85\x8e\xbd\xaa\xc2@\x10\x85\x89\xff.>\xc4\x94\xda\x04\x15|\x04\xb1\xb1\x90\x0b[\x87I\x18\x935\xc9\xae\xb33\xda\t\xd7\xc2\xf76"biw\x0e\x9c\x9f\xef\xbfW\x08\x96\x94\x16\xa1\xcd\x9dGM\xcf\x18\xd5\xa9\x0b\xde\x1c>Jv\x91PIt\xbf\xcd|m8Y\xdc\xb9w\xe3\xfe\xdc&\xf5\xbb\x1d\x9d/%u^\xa9\xa4hZ\xac)\xfb\x18\x1e\xd8d\xfd\xf8\xe3\xa1\x1df\x1e[\xe2\x91\xdd|\x97!\x1ca\xb5\x84\n\xaf\xdd\x02\xbc\xbe\x05\x1a\x12\x01\xad\xd0C\x88@|\xc1\x064\xc0\x9a\xc7v\x16\xf2\x13\x15\x9a\x15\r\x8a\xf0\xe47\xf9;ixj\x13_u \xd8\x81\x98K\x9e>\x01\x13iVH') sage: p == PartitionsGreatestLE(10,2) True class PartitionsGreatestEQ(IntegerListsL Returns combinatorial class of all (unordered) "restricted" partitions of the integer n having its greatest part equal to the integer k. EXAMPLES:: sage: PartitionsGreatestEQ(10,2) Partitions of 10 having greatest part equal to 2 sage: PartitionsGreatestEQ(10,2).list() class PartitionsGreatestEQ(IntegerListsL sage: PartitionsGreatestEQ(10,2).first().parent() Partitions... """ """ def __init__(self, n, k): """ class PartitionsGreatestEQ(IntegerListsL IntegerListsLex.__init__(self, n, max_slope = 0, max_part=k, floor = [k]) self.k = k def _repr_(self): def __repr__(self): """ TESTS:: sage: PartitionsGreatestEQ(10,2).__repr__() 'Partitions of 10 having greatest part equal to 2' """ class PartitionsGreatestEQ_nk(Partitions self.__class__ = PartitionsGreatestEQ self.__init__(data['n'], data['k']) ######################### # Restricted Partitions # ######################### def RestrictedPartitions(n, S, k=None): r""" This function has been deprecated and will be removed in a future version of Sage; use Partitions() with the parts_in keyword. future version of Sage; use :meth:Partitions with the parts_in keyword. Note, however, that the current implementation of :meth:Partitions does not allow the parts_in keyword to be combined with keywords such as max_length; see :trac:13072 and :trac:12278 for more details. This class should not be removed until this problem has been fixed. Original docstring follows. def RestrictedPartitions(n, S, k=None): nonincreasing order. The difference is that here the p_i must be elements from the set S, while for ordinary partitions they may be elements from [1..n]. Returns the list of all restricted partitions of the positive integer n into sums with k summands with the summands of the partition coming from the set S. If k is not given all restricted partitions for all k are returned. integer n into sums with k summands with the summands of the partition coming from the set S. If k is not given all restricted partitions for all k are returned. Wraps GAP's RestrictedPartitions. EXAMPLES:: sage: RestrictedPartitions(5,[3,2,1]) doctest:...: DeprecationWarning: RestrictedPartitions is deprecated; use Partitions with the parts_in keyword instead. See http://trac.sagemath.org/5478 for details. doctest:1: DeprecationWarning: RestrictedPartitions is deprecated; use Partitions with the parts_in keyword instead. See http://trac.sagemath.org/13072 for details. doctest:...: DeprecationWarning: RestrictedPartitions_nsk is deprecated; use Partitions with the parts_in keyword instead. See http://trac.sagemath.org/13072 for details. Partitions of 5 restricted to the values [1, 2, 3] sage: RestrictedPartitions(5,[3,2,1]).list() [[3, 2], [3, 1, 1], [2, 2, 1], [2, 1, 1, 1], [1, 1, 1, 1, 1]] def RestrictedPartitions(n, S, k=None): [[2, 1, 1, 1]] """ from sage.misc.superseded import deprecation deprecation(5478, 'RestrictedPartitions is deprecated; use Partitions with the parts_in keyword instead.') deprecation(13072, 'RestrictedPartitions is deprecated; use Partitions with the parts_in keyword instead.') return RestrictedPartitions_nsk(n, S, k) class RestrictedPartitions_nsk(CombinatorialClass): r""" We are deprecating RestrictedPartitions, so this class should be deprecated too. be deprecated too. See :trac:13072. """ def __init__(self, n, S, k=None): """ TESTS:: sage: r = RestrictedPartitions(5,[3,2,1]) doctest:...: DeprecationWarning: RestrictedPartitions is deprecated; use Partitions with the parts_in keyword instead. See http://trac.sagemath.org/5478 for details. doctest:1: DeprecationWarning: RestrictedPartitions is deprecated; use Partitions with the parts_in keyword instead. See http://trac.sagemath.org/13072 for details. sage: r == loads(dumps(r)) True """ from sage.misc.superseded import deprecation deprecation(5478, 'RestrictedPartitions_nsk is deprecated; use Partitions with the parts_in keyword instead.') deprecation(13072, 'RestrictedPartitions_nsk is deprecated; use Partitions with the parts_in keyword instead.') self.n = n self.S = S self.S.sort() self.k = k Element = Partition_class def __contains__(self, x): """ EXAMPLES:: sage: [4,1] in RestrictedPartitions(5,[3,2,1]) doctest:...: DeprecationWarning: RestrictedPartitions is deprecated; use Partitions with the parts_in keyword instead. See http://trac.sagemath.org/5478 for details. See http://trac.sagemath.org/13072 for details. False sage: [3,2] in RestrictedPartitions(5,[3,2,1]) True class RestrictedPartitions_nsk(Combinato EXAMPLES:: sage: RestrictedPartitions(5,[3,2,1]).__repr__() doctest:...: DeprecationWarning: RestrictedPartitions is deprecated; use Partitions with the parts_in keyword instead. See http://trac.sagemath.org/5478 for details. doctest:...: DeprecationWarning: RestrictedPartitions_nsk is deprecated; use Partitions with the parts_in keyword instead. See http://trac.sagemath.org/5478 for details. doctest:1: DeprecationWarning: RestrictedPartitions is deprecated; use Partitions with the parts_in keyword instead. See http://trac.sagemath.org/13072 for details. 'Partitions of 5 restricted to the values [1, 2, 3]' sage: RestrictedPartitions(5,[3,2,1],4).__repr__() 'Partitions of 5 restricted to the values [1, 2, 3] of length 4' """ string = "Partitions of %s restricted to the values %s"%(self.n, self.S) if self.k is not None: class RestrictedPartitions_nsk(Combinato sage: RestrictedPartitions(8,[1,3,5,7]).list() doctest:...: DeprecationWarning: RestrictedPartitions is deprecated; use Partitions with the parts_in keyword instead. See http://trac.sagemath.org/5478 for details. See http://trac.sagemath.org/13072 for details. [[7, 1], [5, 3], [5, 1, 1, 1], [3, 3, 1, 1], [3, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1]] sage: RestrictedPartitions(8,[1,3,5,7],2).list() [[7, 1], [5, 3]] class RestrictedPartitions_nsk(Combinato """ Returns the size of RestrictedPartitions(n,S,k). Wraps GAP's NrRestrictedPartitions. EXAMPLES:: sage: RestrictedPartitions(8,[1,3,5,7]).cardinality() doctest:...: DeprecationWarning: RestrictedPartitions is deprecated; use Partitions with the parts_in keyword instead. See http://trac.sagemath.org/5478 for details. See http://trac.sagemath.org/13072 for details. 6 sage: RestrictedPartitions(8,[1,3,5,7],2).cardinality() 2 class RestrictedPartitions_nsk(Combinato else: ans=gap.eval("NrRestrictedPartitions(%s,%s,%s)"%(ZZ(n),S,ZZ(k))) return ZZ(ans) #################### # Partition Tuples # #################### def PartitionTuples(n,k): """ Returns the combinatorial class of k-tuples of partitions of n. These are are ordered list of k partitions whose sizes add up to TODO: reimplement in term of species.ProductSpecies and Partitions These describe the classes and the characters of wreath products of groups with k conjugacy classes with the symmetric group S_n. EXAMPLES:: sage: PartitionTuples(4,2) 2-tuples of partitions of 4 sage: PartitionTuples(3,2).list() [[[3], []], [[2, 1], []], [[1, 1, 1], []], [[2], [1]], [[1, 1], [1]], [[1], [2]], [[1], [1, 1]], [[], [3]], [[], [2, 1]], [[], [1, 1, 1]]] """ return PartitionTuples_nk(n,k) class PartitionTuples_nk(CombinatorialClass): def __init__(self, n, k): """ TESTS:: sage: p = PartitionTuples(4,2) sage: p == loads(dumps(p)) True """ self.n = n self.k = k Element = Partition_class def __contains__(self, x): """ EXAMPLES:: sage: [[], [1, 1, 1]] in PartitionTuples(3,2) True sage: [[1], [1, 1, 1]] in PartitionTuples(3,2) False """ p = Partitions_all() return len(x) == self.k and all(i in p for i in x)\ and sum(sum(i) for i in x) == self.n def __repr__(self): """ EXAMPLES:: sage: PartitionTuples(4,2).__repr__() '2-tuples of partitions of 4' """ return "%s-tuples of partitions of %s"%(self.k, self.n) def __iter__(self): r""" Returns an iterator for all k-tuples of partitions which together form a partition of n. EXAMPLES:: sage: PartitionTuples(2,0).list() #indirect doctest [] sage: PartitionTuples(2,1).list() #indirect doctest [[[2]], [[1, 1]]] sage: PartitionTuples(2,2).list() #indirect doctest [[[2], []], [[1, 1], []], [[1], [1]], [[], [2]], [[], [1, 1]]] sage: PartitionTuples(3,2).list() #indirect doctest [[[3], []], [[2, 1], []], [[1, 1, 1], []], [[2], [1]], [[1, 1], [1]], [[1], [2]], [[1], [1, 1]], [[], [3]], [[], [2, 1]], [[], [1, 1, 1]]] """ p = [Partitions(i) for i in range(self.n+1)] for iv in IntegerVectors(self.n,self.k): for cp in CartesianProduct(*[p[i] for i in iv]): yield cp def cardinality(self): r""" Returns the number of k-tuples of partitions which together form a partition of n. Wraps GAP's NrPartitionTuples. EXAMPLES:: sage: PartitionTuples(3,2).cardinality() 10 sage: PartitionTuples(8,2).cardinality() 185 Now we compare that with the result of the following GAP computation:: gap> S8:=Group((1,2,3,4,5,6,7,8),(1,2)); Group([ (1,2,3,4,5,6,7,8), (1,2) ]) gap> C2:=Group((1,2)); Group([ (1,2) ]) gap> W:=WreathProduct(C2,S8); gap> Size(W); 10321920     ## = 2^8*Factorial(8), which is good:-) gap> Size(ConjugacyClasses(W)); 185 """ return ZZ(gp.eval('polcoeff(1/eta(x)^%s, %s, x)'%(self.k, self.n))) ############## # Partitions # def Partitions(n=None, **kwargs): Partitions(n, \*\*kwargs) returns the combinatorial class of integer partitions of n, subject to the constraints given by the keywords. Valid keywords are: starting, ending, min_part, max_part, max_length, min_length, length, max_slope, min_slope, inner, outer, and parts_in. They have the following meanings: - starting=p specifies that the partitions should all be greater than or equal to p in reverse lex order. def Partitions(n=None, **kwargs): - parts_in=S specifies that the partitions have parts in the set S, which can be any sequence of positive integers. The max_* versions, along with inner and ending, work analogously. def Partitions(n=None, **kwargs): keyword arguments. If you specify, say, parts_in, all other keyword arguments will be ignored; starting and ending work the same way. EXAMPLES: If no arguments are passed, then the combinatorial class EXAMPLES: If no arguments are passed, then the combinatorial class of all integer partitions is returned. :: sage: Partitions() Partitions sage: [2,1] in Partitions() True If an integer n is passed, then the combinatorial class of integer partitions of n is returned. :: sage: Partitions(3) Partitions of the integer 3 sage: Partitions(3).list() [[3], [2, 1], [1, 1, 1]] If starting=p is passed, then the combinatorial class of partitions greater than or equal to p in lexicographic order is returned. :: sage: Partitions(3, starting=[2,1]) Partitions of the integer 3 starting with [2, 1] sage: Partitions(3, starting=[2,1]).list() [[2, 1], [1, 1, 1]] If ending=p is passed, then the combinatorial class of partitions at most p in lexicographic order is returned. :: sage: Partitions(3, ending=[2,1]) Partitions of the integer 3 ending with [2, 1] sage: Partitions(3, ending=[2,1]).list() [[3], [2, 1]] Using max_slope=-1 yields partitions into distinct parts -- each part differs from the next by at least 1. Use a different max_slope to get parts that differ by, say, 2. def Partitions(n=None, **kwargs): and length. :: sage: Partitions(5,min_part=2) Partitions of the integer 5 satisfying constraints min_part=2 sage: Partitions(5,min_part=2).list() [[5], [3, 2]] :: sage: Partitions(3,max_length=2).list() [[3], [2, 1]] :: sage: Partitions(10, min_part=2, length=3).list() [[6, 2, 2], [5, 3, 2], [4, 4, 2], [4, 3, 3]] Here are some further examples using various constraints:: sage: [x for x in Partitions(4)] [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]] sage: [x for x in Partitions(4, length=2)] def Partitions(n=None, **kwargs): Partition class makes. :: sage: [x for x in Partitions(4, length=3, min_part=0)] doctest:... RuntimeWarning: Currently, setting min_part=0 produces Partition objects which violate internal assumptions.  Calling methods on these objects may produce errors or WRONG results! [[4, 0, 0], [3, 1, 0], [2, 2, 0], [2, 1, 1]] def Partitions(n=None, **kwargs): [[1000]] In particular, getting the first element is also constant time:: sage: Partitions(30, max_part=29).first() [29, 1] TESTS:: sage: P = Partitions(5, min_part=2) sage: P == loads(dumps(P)) True sage: repr( Partitions(5, min_part=2) ) 'Partitions of the integer 5 satisfying constraints min_part=2' sage: P = Partitions(5, min_part=2) sage: P.first().parent() Partitions... def Partitions(n=None, **kwargs): [[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1], [2, 1, 1, 1]] sage: Partitions(6, length=2, max_slope=-1).list() [[5, 1], [4, 2]] sage: Partitions(length=2, max_slope=-1).list() Traceback (most recent call last): ... ValueError: the size must be specified with any keyword argument """ assert n != infinity, "n cannot be infinite" if n == infinity: raise ValueError, "n cannot be infinite" if n is None: assert(len(kwargs) == 0) if len(kwargs) > 0: raise ValueError, 'the size must be specified with any keyword argument' return Partitions_all() else: if len(kwargs) == 0: def Partitions(n=None, **kwargs): #                return Partitions_constraints(n, **kwargs) # Allows to pickle old constrained Partitions_constraints objects. # Allows to pickle old constrained Partitions_constraints objects. class Partitions_constraints(IntegerListsLex): def __setstate__(self, data): r""" class Partitions_all(InfiniteAbstractCom def __contains__(self, x): """ TESTS:: sage: P = Partitions() sage: Partition([2,1]) in P True class Partitions_all(InfiniteAbstractCom def __repr__(self): """ TESTS:: sage: repr(Partitions()) 'Partitions' """ class Partitions_all(InfiniteAbstractCom def _infinite_cclass_slice(self, n): """ Needed by InfiniteAbstractCombinatorialClass to build __iter__. TESTS: TESTS:: sage: Partitions()._infinite_cclass_slice(4) == Partitions(4) True sage: it = iter(Partitions())    # indirect doctest class Partitions_all(InfiniteAbstractCom return Partitions_n(n) class Partitions_n(CombinatorialClass): Element = Partition_class def __init__(self, n): """ TESTS:: class Partitions_n(CombinatorialClass): """ self.n = n def __contains__(self, x): """ TESTS:: class Partitions_n(CombinatorialClass): EXAMPLES:: sage: Partitions(4)._an_element_() sage: Partitions(4).an_element()  # indirect doctest [3, 1] sage: Partitions(0)._an_element_() sage: Partitions(0).an_element() [] sage: Partitions(1)._an_element_() sage: Partitions(1).an_element() [1] """ if self.n == 0: class Partitions_n(CombinatorialClass): lst = [self.n-1, 1] return self._element_constructor_(lst) def cardinality(self, algorithm='default'): def cardinality(self, algorithm='bober'): r""" Returns the number of partitions of the specified size. INPUT: - algorithm - (default: default) - 'bober' - use Jonathan Bober's implementation (*very* fast, but relatively new) - 'gap' - use GAP (VERY *slow*) - 'pari' - use PARI. Speed seems the same as GAP until n is in the thousands, in which case PARI is faster. - 'default' - 'bober' when k is not specified; otherwise use 'gap'. Use the function partitions(n) to return a generator over all partitions of n. It is possible to associate with every partition of the integer n a conjugacy class of permutations in the symmetric group on n points and vice versa. Therefore p(n) = NrPartitions(n) is the number of conjugacy classes of the symmetric group on n points. - algorithm  - (default: 'bober') - 'bober' - use Jonathan Bober's implementation (*very* fast). The default - 'gap' - use GAP (VERY *slow*) - 'pari' - use PARI. Speed seems the same as GAP until n is in the thousands, in which case PARI is faster. - 'default' - 'bober' when k is not specified; otherwise use 'gap'. Use the function :meth:partitions to return a generator over all partitions of n. It is possible to associate with every partition of the integer n a conjugacy class of permutations in the symmetric group on n points and vice versa. Therefore p(n) = NrPartitions(n) is the number of conjugacy classes of the symmetric group on n points. EXAMPLES:: sage: v = Partitions(5).list(); v [[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1], [2, 1, 1, 1], [1, 1, 1, 1, 1]] sage: len(v) class Partitions_n(CombinatorialClass): 7 sage: Partitions(5).cardinality(algorithm='bober') 7 The input must be a nonnegative integer or a ValueError is raised. :: sage: Partitions(10).cardinality() 42 sage: Partitions(3).cardinality() class Partitions_n(CombinatorialClass): 37338 sage: Partitions(100).cardinality() 190569292 A generating function for p(n) is given by the reciprocal of Euler's function: .. math:: \sum_{n=0}^\infty p(n)x^n = \prod_{k=1}^\infty \left(\frac {1}{1-x^k} \right). We use Sage to verify that the first several coefficients do instead agree:: sage: q = PowerSeriesRing(QQ, 'q', default_prec=9).gen() sage: prod([(1-q^k)^(-1) for k in range(1,9)])  ## partial product of sage: prod([(1-q^k)^(-1) for k in range(1,9)])  ## partial product of 1 + q + 2*q^2 + 3*q^3 + 5*q^4 + 7*q^5 + 11*q^6 + 15*q^7 + 22*q^8 + O(q^9) sage: [Partitions(k) .cardinality()for k in range(2,10)] [2, 3, 5, 7, 11, 15, 22, 30] REFERENCES: - http://en.wikipedia.org/wiki/Partition\_(number\_theory) """ return number_of_partitions(self.n, algorithm=algorithm) if algorithm == 'bober': return cached_number_of_partitions(self.n) elif algorithm == 'gap': return ZZ( gap.eval("NrPartitions(%s)"%(ZZ(self.n))) ) elif algorithm == 'pari': return ZZ(pari(ZZ(self.n)).numbpart()) raise ValueError, "unknown algorithm '%s'"%algorithm def random_element(self, measure = 'uniform'): """ class Partitions_n(CombinatorialClass): INPUT: - measure - - uniform - (default) pick a element for the uniform mesure. see :meth:random_element_uniform - Plancherel - use plancherel measure. see :meth:random_element_plancherel - measure - uniform -- (default) pick a element for the uniform mesure. see :meth:random_element_uniform - Plancherel -- use plancherel measure. see :meth:random_element_plancherel EXAMPLES:: class Partitions_n(CombinatorialClass): ALGORITHM: - It is a python Implementation of RANDPAR, see [nw] below.  The complexity is unkown, there may be better algorithms.  TODO: Check in Knuth AOCP4. complexity is unknown, there may be better algorithms. .. TODO: : Check in Knuth AOCP4. - There is also certainly a lot of room for optimizations, see comments in the code. class Partitions_n(CombinatorialClass): # equiprobable. # The following could be made faster by a clever use of floats rand = randrange(0, n*_numpart(n))  # cached number_of_partition rand = randrange(0, n*cached_number_of_partitions(n))  # cached number_of_partition # It is better to start by the j = 1 pairs because they are the # most probable. Maybe there is an even more clever order. class Partitions_n(CombinatorialClass): d = 1 r = n-j        # n - d*j while  r >= 0: rand -= d * _numpart(r) rand -= d * cached_number_of_partitions(r) if rand < 0: break d +=1 r -= j class Partitions_n(CombinatorialClass): ALGORITHM: - insert by robinson-schensted a uniform random permutations of n and - insert by Robinson-Schensted a uniform random permutations of n and returns the shape of the resulting tableau. The complexity is O(n\ln(n)) which is likely optimal. However, the implementation could be optimized. class Partitions_n(CombinatorialClass): """ Returns the lexicographically first partition of a positive integer n. This is the partition [n]. EXAMPLES:: sage: Partitions(4).first() [4] """ class Partitions_n(CombinatorialClass): """ Returns the lexicographically last partition of the positive integer n. This is the all-ones partition. EXAMPLES:: sage: Partitions(4).last() [1, 1, 1, 1] """ class Partitions_n(CombinatorialClass): def __iter__(self): """ An iterator for the partitions of n. EXAMPLES:: sage: [x for x in Partitions(4)] [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]] """ for p in self._fast_iterator(): yield Partition_class(p) def _fast_iterator(self): """ A fast iterator for the partitions of n which returns lists and not partition types. EXAMPLES:: sage: p = Partitions(4) sage: it = p._fast_iterator() sage: it.next() class Partitions_n(CombinatorialClass): if self.n == 0: yield [] return # modify the partitions of n-1 to form the partitions of n for p in Partitions_n(self.n-1)._fast_iterator(): if p and (len(p) < 2 or p[-2] > p[-1]): yield p[:-1] + [p[-1] + 1] yield p + [1] yield p + [1] class Partitions_parts_in(CombinatorialClass): class Partitions_parts_in(CombinatorialC def __init__(self, n, parts): """ TESTS:: sage: p = Partitions(5, parts_in=[1,2,3]) sage: p == loads(dumps(p)) True class Partitions_parts_in(CombinatorialC def __contains__(self, x): """ TESTS:: sage: p = Partitions(5, parts_in=[1,2]) sage: [2,1,1,1] in p True sage: [4,1] in p False """ return (x in Partitions_all() and sum(x) == self.n and return (x in Partitions_all() and sum(x) == self.n and all(p in self.parts for p in x)) def __repr__(self): """ TESTS:: sage: repr(Partitions(5, parts_in=[1,2,3])) 'Partitions of the integer 5 with parts in [1, 2, 3]' """ class Partitions_parts_in(CombinatorialC Return the lexicographically first partition of a positive integer n with the specified parts, or None if no such partition exists. EXAMPLES:: sage: Partitions(9, parts_in=[3,4]).first() [3, 3, 3] sage: Partitions(6, parts_in=[1..6]).first() class Partitions_parts_in(CombinatorialC sage: p._findfirst(0, p.parts[:]) [] sage: p._findfirst(p.n, [10]) """ if n == 0: return [] class Partitions_parts_in(CombinatorialC Returns the lexicographically last partition of the positive integer n with the specified parts, or None if no such partition exists. EXAMPLES:: sage: Partitions(15, parts_in=[2,3]).last() [3, 2, 2, 2, 2, 2, 2] sage: Partitions(30, parts_in=[4,7,8,10,11]).last() sage: Partitions(30, parts_in=[4,7,8,10,11]).last() [7, 7, 4, 4, 4, 4] sage: Partitions(10, parts_in=[3,6]).last() is None True sage: Partitions(50, parts_in=[11,12,13]).last() [13, 13, 12, 12] sage: Partitions(30, parts_in=[4,7,8,10,11]).last() sage: Partitions(30, parts_in=[4,7,8,10,11]).last() [7, 7, 4, 4, 4, 4] TESTS:: class Partitions_parts_in(CombinatorialC - n: nonnegative integer - parts: a sorted list of positive integers. OUTPUT:: OUTPUT: A list of integers in weakly decreasing order, or None. The output is just a list, not a Partition object. class Partitions_parts_in(CombinatorialC def __iter__(self): """ An iterator a list of the partitions of n. EXAMPLES:: sage: [x for x in Partitions(4)] [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]] """ for p in self._fast_iterator(self.n, self.parts[:]): yield Partition_class(p) def _fast_iterator(self, n, parts): """ A fast iterator for the partitions of n which returns lists and not partition types. This function is not intended to be called directly. INPUT: - n: nonnegative integer. class Partitions_parts_in(CombinatorialC If the parts in parts are sorted in increasing order, this function returns weakly decreasing lists. If parts is not sorted, your lists won't be, either. EXAMPLES:: sage: p = Partitions(4) sage: it = p._fast_iterator() sage: it.next() class Partitions_starting(CombinatorialC def __init__(self, n, starting_partition): """ EXAMPLES:: sage: Partitions(3, starting=[2,1]) Partitions of the integer 3 starting with [2, 1] sage: Partitions(3, starting=[2,1]).list() [[2, 1], [1, 1, 1]] TESTS:: sage: p = Partitions(3, starting=[2,1]) sage: p == loads(dumps(p)) True class Partitions_starting(CombinatorialC def __repr__(self): """ EXAMPLES:: sage: Partitions(3, starting=[2,1]).__repr__() 'Partitions of the integer 3 starting with [2, 1]' """ class Partitions_starting(CombinatorialC def __contains__(self, x): """ EXAMPLES:: sage: p = Partitions(3, starting=[2,1]) sage: [1,1] in p False class Partitions_starting(CombinatorialC def first(self): """ EXAMPLES:: sage: Partitions(3, starting=[2,1]).first() [2, 1] """ class Partitions_starting(CombinatorialC def next(self, part): """ EXAMPLES:: sage: Partitions(3, starting=[2,1]).next(Partition([2,1])) [1, 1, 1] """ class Partitions_ending(CombinatorialCla def __init__(self, n, ending_partition): """ EXAMPLES:: sage: Partitions(4, ending=[1,1,1,1]).list() [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]] sage: Partitions(4, ending=[2,2]).list() [[4], [3, 1], [2, 2]] sage: Partitions(4, ending=[4]).list() [[4]] TESTS:: sage: p = Partitions(4, ending=[1,1,1,1]) sage: p == loads(dumps(p)) True """ """ self.n = n self._ending = Partition(ending_partition) def __repr__(self): """ EXAMPLES:: sage: Partitions(4, ending=[1,1,1,1]).__repr__() 'Partitions of the integer 4 ending with [1, 1, 1, 1]' """ class Partitions_ending(CombinatorialCla def __contains__(self, x): """ EXAMPLES:: sage: p = Partitions(4, ending=[2,2]) sage: [4] in p True class Partitions_ending(CombinatorialCla def first(self): """ EXAMPLES:: sage: Partitions(4, ending=[1,1,1,1]).first() [4] """ class Partitions_ending(CombinatorialCla def next(self, part): """ EXAMPLES:: sage: Partitions(4, ending=[1,1,1,1]).next(Partition([4])) [3, 1] sage: Partitions(4, ending=[1,1,1,1]).next(Partition([1,1,1,1])) is None class Partitions_ending(CombinatorialCla return None else: return part.next() def PartitionsInBox(h, w): """ Returns the combinatorial class of partitions that fit in a h by w box. EXAMPLES:: sage: PartitionsInBox(2,2) Integer partitions which fit in a 2 x 2 box sage: PartitionsInBox(2,2).list() class PartitionsInBox_hw(CombinatorialCl def __init__(self, h, w): """ TESTS:: sage: p = PartitionsInBox(2,2) sage: p == loads(dumps(p)) True class PartitionsInBox_hw(CombinatorialCl def __contains__(self, x): """ EXAMPLES:: sage: [] in PartitionsInBox(2,2) True sage: [2,1] in PartitionsInBox(2,2) class PartitionsInBox_hw(CombinatorialCl """ return x in Partitions_all() and len(x) <= self.h \ and (len(x) == 0 or x[0] <= self.w) def list(self): """ Returns a list of all the partitions inside a box of height h and width w. EXAMPLES:: sage: PartitionsInBox(2,2).list() [[], [1], [1, 1], [2], [2, 1], [2, 2]] TESTS:: sage: type(PartitionsInBox(0,0)[0]) # check for 10890 """ class PartitionsInBox_hw(CombinatorialCl l = new_list return [Partition(filter(lambda x: x!=0, p)) for p in l] ######################################################################### #### partitions def partitions_set(S,k=None, use_file=Tr An unordered partition of a set S is a set of pairwise disjoint nonempty subsets with union S and is represented by a sorted list of such subsets. partitions_set returns the list of all unordered partitions of the list S of increasing positive integers into k pairwise disjoint nonempty sets. If k is omitted then all partitions are returned. The Bell number B_n, named in honor of Eric Temple Bell, is the number of different partitions of a set with n elements. .. warning:: .. WARNING:: Wraps GAP - hence S must be a list of objects that have string representations that can be interpreted by the GAP interpreter. If mset consists of at all complicated Sage objects, this function does *not* do what you expect. See SetPartitions in combinat/set_partition. .. warning:: .. WARNING:: This function is inefficient. The runtime is dominated by parsing the output from GAP. Wraps GAP's PartitionsSet. EXAMPLES:: sage: S = [1,2,3,4] sage: from sage.combinat.partition import partitions_set sage: partitions_set(S,2) [[[1], [2, 3, 4]], [[1, 2], [3, 4]], [[1, 2, 3], [4]], [[1, 2, 4], [3]], [[1, 3], [2, 4]], [[1, 3, 4], [2]], [[1, 4], [2, 3]]] REFERENCES: doctest:1: DeprecationWarning: partitions_set is deprecated. Use SetPartitions instead. See http://trac.sagemath.org/13072 for details. Set partitions of [1, 2, 3, 4] with 2 parts - http://en.wikipedia.org/wiki/Partition_of_a_set """ if k is None: ans=gap("PartitionsSet(%s)"%S).str(use_file=use_file) else: ans=gap("PartitionsSet(%s,%s)"%(S,k)).str(use_file=use_file) return eval(ans) from sage.misc.superseded import deprecation deprecation(13072,'partitions_set is deprecated. Use SetPartitions instead.') return sage.combinat.set_partition.SetPartitions(S,k) def number_of_partitions_set(S,k): r""" Returns the size of partitions_set(S,k). Wraps GAP's NrPartitionsSet. The Stirling number of the second kind is the number of partitions of a set of size n into k blocks. EXAMPLES:: sage: mset = [1,2,3,4] sage: from sage.combinat.partition import number_of_partitions_set sage: number_of_partitions_set(mset,2) doctest:1: DeprecationWarning: number_of_partitions_set is deprecated. Use SetPartitions().cardinality() instead. See http://trac.sagemath.org/13072 for details. 7 sage: stirling_number2(4,2) 7 REFERENCES - http://en.wikipedia.org/wiki/Partition_of_a_set """ if k is None: ans=gap.eval("NrPartitionsSet(%s)"%S) else: ans=gap.eval("NrPartitionsSet(%s,%s)"%(S,ZZ(k))) return ZZ(ans) def partitions_list(n,k=None): r""" This function will be deprecated in a future version of Sage and eventually removed. Use Partitions(n).list() or Partitions(n, length=k).list() instead. Original docstring follows. An unordered partition of n is an unordered sum n = p_1+p_2 +\ldots+ p_k of positive integers and is represented by the list p = [p_1,p_2,\ldots,p_k], in nonincreasing order, i.e., p1\geq p_2 ...\geq p_k. INPUT: -  n, k - positive integer partitions_list(n,k) returns the list of all (unordered) partitions of the positive integer n into sums with k summands. If k is omitted then all partitions are returned. Do not call partitions_list with an n much larger than 40, in which case there are 37338 partitions, since the list will simply become too large. Wraps GAP's Partitions. EXAMPLES:: sage: partitions_list(10,2) [[5, 5], [6, 4], [7, 3], [8, 2], [9, 1]] sage: partitions_list(5) [[1, 1, 1, 1, 1], [2, 1, 1, 1], [2, 2, 1], [3, 1, 1], [3, 2], [4, 1], [5]] """ n = ZZ(n) if n <= 0: raise ValueError, "n (=%s) must be a positive integer"%n if k is None: ans=gap.eval("Partitions(%s)"%(n)) else: ans=gap.eval("Partitions(%s,%s)"%(n,k)) return eval(ans.replace('\n','')) from sage.misc.superseded import deprecation deprecation(13072,'number_of_partitions_set is deprecated. Use SetPartitions().cardinality() instead.') return sage.combinat.set_partition.SetPartitions(S,k).cardinality() def number_of_partitions(n,k=None, algorithm='default'): r""" Returns the size of partitions_list(n,k). Returns the number of partitions of n with, optionally, at most k parts. The options of sage.combinat.partition.number_of_partitions are being deprecated :trac:13072 in favour of :meth:Partitions().cardinality() so that number_of_partitions() can become a stripped down version of the fastest algorithm available (currently this is due to Bober, but an faster implementation using FLINT will soon be merged into sage). INPUT: -  n - an integer -  k - (default: None); if specified, instead -  k - (default: None); if specified, instead returns the cardinality of the set of all (unordered) partitions of the positive integer n into sums with k summands. the positive integer n into sums with k summands. [Will be deprecated: please use PartitionTuples(level, size).cardinality() ] -  algorithm - (default: 'default') -  'default' - If k is not None, then use Gap (very slow). If k is None, use Jonathan Bober's highly optimized implementation (this is the fastest code in the world for this problem). -  'bober' - use Jonathan Bober's implementation -  'gap' - use GAP (VERY *slow*) -  'pari' - use PARI. Speed seems the same as GAP until n is in the thousands, in which case PARI is faster. *But* PARI has a bug, e.g., on 64-bit Linux PARI-2.3.2 outputs numbpart(147007)%1000 as 536 when it should be 533!. So do not use this option. IMPLEMENTATION: Wraps GAP's NrPartitions or PARI's numbpart function. Use the function partitions(n) to return a generator over all partitions of n. It is possible to associate with every partition of the integer n a conjugacy class of permutations in the symmetric group on n points and vice versa. Therefore p(n) = NrPartitions(n) is the number of conjugacy classes of the symmetric group on n points. [Will be deprecated except in Partition().cardinality() ] -  'default' - If k is not None, then use Gap (very slow). If k is None, use Jonathan Bober's highly optimized implementation. -  'bober' - use Jonathan Bober's implementation -  'gap' - use GAP (VERY *slow*) -  'pari' - use PARI. Speed seems the same as GAP until n is in the thousands, in which case PARI is faster. *But* PARI has a bug, e.g., on 64-bit Linux PARI-2.3.2 outputs numbpart(147007)%1000 as 536 when it should be 533!. So do not use this option. EXAMPLES:: sage: v = list(partitions(5)); v [(1, 1, 1, 1, 1), (1, 1, 1, 2), (1, 2, 2), (1, 1, 3), (2, 3), (1, 4), (5,)] sage: v = Partitions(5).list(); v [[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1], [2, 1, 1, 1], [1, 1, 1, 1, 1]] sage: len(v) 7 sage: number_of_partitions(5, algorithm='gap') doctest:1: DeprecationWarning: sage.combinat.number_of_partitions is deprecated. Use  Partitions().cardinality(algorithm='gap') See http://trac.sagemath.org/13072 for details. 7 sage: number_of_partitions(5, algorithm='pari') doctest:1: DeprecationWarning: sage.combinat.number_of_partitions is deprecated. Use  Partitions().cardinality(algorithm='pari') See http://trac.sagemath.org/13072 for details. 7 sage: number_of_partitions(5, algorithm='bober') 7 The input must be a nonnegative integer or a ValueError is raised. :: sage: number_of_partitions(-5) Traceback (most recent call last): ... ValueError: n (=-5) must be a nonnegative integer :: sage: number_of_partitions(10,2) doctest:1: DeprecationWarning: sage.combinat.number_of_partitions(size, level) is deprecated. Use PartitionTuples(level, size).cardinality() instead. See http://trac.sagemath.org/13072 for details. 5 sage: number_of_partitions(10) 42 sage: number_of_partitions(3) def number_of_partitions(n,k=None, algor 190569292 sage: number_of_partitions(100000) 27493510569775696512677516320986352688173429315980054758203125984302147328114964173055050741660736621590157844774296248940493063070200461792764493033510116079342457190155718943509725312466108452006369558934464248716828789832182345009262853831404597021307130674510624419227311238999702284408609370935531629697851569569892196108480158600569421098519 A generating function for p(n) is given by the reciprocal of A generating function for the partition function is given by the reciprocal of Euler's function: .. math:: \sum_{n=0}^\infty p(n)x^n = \prod_{k=1}^\infty \left(\frac {1}{1-x^k} \right). \sum_{n=0}^\infty p(n)x^n = \prod_{k=1}^\infty \left(\frac {1}{1-x^k} \right). We use Sage to verify that the first several coefficients do instead agree:: sage: q = PowerSeriesRing(QQ, 'q', default_prec=9).gen() sage: prod([(1-q^k)^(-1) for k in range(1,9)])  ## partial product of sage: prod([(1-q^k)^(-1) for k in range(1,9)])  ## partial product of 1 + q + 2*q^2 + 3*q^3 + 5*q^4 + 7*q^5 + 11*q^6 + 15*q^7 + 22*q^8 + O(q^9) sage: [number_of_partitions(k) for k in range(2,10)] [2, 3, 5, 7, 11, 15, 22, 30] REFERENCES: - http://en.wikipedia.org/wiki/Partition\_(number\_theory) TESTS:: sage: n = 500 + randint(0,500) sage: number_of_partitions( n - (n % 385) + 369) % 385 == 0 True def number_of_partitions(n,k=None, algor sage: n = 1000000 + randint(0,1000000) sage: number_of_partitions( n - (n % 385) + 369) % 385 == 0 True sage: n = 100000000 + randint(0,100000000) sage: n = 100000000 + randint(0,100000000) sage: number_of_partitions( n - (n % 385) + 369) % 385 == 0  # long time (4s on sage.math, 2011) True Another consistency test for n up to 500:: sage: len([n for n in [1..500] if number_of_partitions(n) != number_of_partitions(n,algorithm='pari')]) 0 """ from sage.misc.superseded import deprecation n = ZZ(n) if n < 0: raise ValueError, "n (=%s) must be a nonnegative integer"%n def number_of_partitions(n,k=None, algor algorithm = 'bober' else: algorithm = 'gap' if algorithm == 'gap': if k is None: deprecation(13072,"sage.combinat.number_of_partitions is deprecated. Use  Partitions().cardinality(algorithm='gap')") ans=gap.eval("NrPartitions(%s)"%(ZZ(n))) else: deprecation(13072,'sage.combinat.number_of_partitions(size, level) is deprecated. Use PartitionTuples(level, size).cardinality() instead.') ans=gap.eval("NrPartitions(%s,%s)"%(ZZ(n),ZZ(k))) return ZZ(ans) if k is not None: raise ValueError, "only the GAP algorithm works if k is specified." if algorithm == 'bober': return partitions_ext.number_of_partitions(n) return cached_number_of_partitions(n) elif algorithm == 'pari': deprecation(13072,"sage.combinat.number_of_partitions is deprecated. Use  Partitions().cardinality(algorithm='pari')") return ZZ(pari(ZZ(n)).numbpart()) raise ValueError, "unknown algorithm '%s'"%algorithm # Some function e.g.: Partitions(n).random() heavily use number_of_partitions # so I'm caching the result # This function was previously used to cache number_of_partitions with the # justification that "Some function e.g.: Partitions(n).random() heavily use # number_of_partitions", however, the random() method of Partitions() seems to be # the only place where this was used. from sage.misc.superseded import deprecated_function_alias _numpart = deprecated_function_alias(13072, sage.combinat.partitions.number_of_partitions) # Rather than caching an under used function I have cached the default # number_of_partitions functions which is currently that implemented by Bober, # although this will soon need to be replaced by the FLINT implementation. # AM :trac:13072 from sage.misc.all import cached_function _numpart = cached_function(number_of_partitions) def partitions(n): r""" Generator of all the partitions of the integer n. INPUT: -  n - int To compute the number of partitions of n use number_of_partitions(n). EXAMPLES:: sage: partitions(3) sage: list(partitions(3)) [(1, 1, 1), (1, 2), (3,)] AUTHORS: - Adapted from David Eppstein, Jan Van lent, George Yoshida; Python Cookbook 2, Recipe 19.16. """ n = ZZ(n) # base case of the recursion: zero is the sum of the empty tuple if n == 0: yield ( ) return # modify the partitions of n-1 to form the partitions of n for p in partitions(n-1): yield (1,) + p if p and (len(p) < 2 or p[1] > p[0]): yield (p[0] + 1,) + p[1:] cached_number_of_partitions = cached_function( bober_number_of_partitions ) def cyclic_permutations_of_partition(partition): """ Returns all combinations of cyclic permutations of each cell of the partition. AUTHORS: - Robert L. Miller EXAMPLES:: sage: from sage.combinat.partition import cyclic_permutations_of_partition sage: from sage.combinat.partition import cyclic_permutations_of_partition sage: cyclic_permutations_of_partition([[1,2,3,4],[5,6,7]]) doctest:1: DeprecationWarning: cyclic_permutations_of_partition is being removed from the global namespace. Use sage.combinat.set_partition.cyclic_permutations_of_set_partition instead. See http://trac.sagemath.org/13072 for details. doctest:...: DeprecationWarning: cyclic_permutations_of_partition_iterator is being removed from the global namespace. Please use sage.combinat.set_partition.cyclic_permutations_of_set_partition_iterator instead. See http://trac.sagemath.org/13072 for details. doctest:...: DeprecationWarning: cyclic_permutations_of_partition_iterator is being removed from the global namespace. Please use sage.combinat.set_partition.cyclic_permutations_of_set_partition_iterator instead. See http://trac.sagemath.org/13072 for details. [[[1, 2, 3, 4], [5, 6, 7]], [[1, 2, 4, 3], [5, 6, 7]], [[1, 3, 2, 4], [5, 6, 7]], def cyclic_permutations_of_partition(par [[1, 3, 4, 2], [5, 7, 6]], [[1, 4, 2, 3], [5, 7, 6]], [[1, 4, 3, 2], [5, 7, 6]]] Note that repeated elements are not considered equal:: sage: cyclic_permutations_of_partition([[1,2,3],[4,4,4]]) [[[1, 2, 3], [4, 4, 4]], [[1, 3, 2], [4, 4, 4]], [[1, 2, 3], [4, 4, 4]], [[1, 3, 2], [4, 4, 4]]] """ from sage.misc.superseded import deprecation deprecation(13072,'cyclic_permutations_of_partition is being removed from the global namespace. Use sage.combinat.set_partition.cyclic_permutations_of_set_partition instead.') return list(cyclic_permutations_of_partition_iterator(partition)) def cyclic_permutations_of_partition_iterator(partition): """ Iterates over all combinations of cyclic permutations of each cell of the partition. AUTHORS: - Robert L. Miller EXAMPLES:: sage: from sage.combinat.partition import cyclic_permutations_of_partition sage: from sage.combinat.partition import cyclic_permutations_of_partition_iterator sage: list(cyclic_permutations_of_partition_iterator([[1,2,3,4],[5,6,7]])) doctest:1: DeprecationWarning: cyclic_permutations_of_partition_iterator is being removed from the global namespace. Please use sage.combinat.set_partition.cyclic_permutations_of_set_partition_iterator instead. See http://trac.sagemath.org/13072 for details. [[[1, 2, 3, 4], [5, 6, 7]], [[1, 2, 4, 3], [5, 6, 7]], [[1, 3, 2, 4], [5, 6, 7]], def cyclic_permutations_of_partition_ite [[1, 3, 4, 2], [5, 7, 6]], [[1, 4, 2, 3], [5, 7, 6]], [[1, 4, 3, 2], [5, 7, 6]]] Note that repeated elements are not considered equal:: sage: list(cyclic_permutations_of_partition_iterator([[1,2,3],[4,4,4]])) [[[1, 2, 3], [4, 4, 4]], [[1, 3, 2], [4, 4, 4]], [[1, 2, 3], [4, 4, 4]], [[1, 3, 2], [4, 4, 4]]] """ from sage.misc.superseded import deprecation deprecation(13072,'cyclic_permutations_of_partition_iterator is being removed from the global namespace. Please use sage.combinat.set_partition.cyclic_permutations_of_set_partition_iterator instead.') if len(partition) == 1: for i in cyclic_permutations_iterator(partition[0]): yield [i] def cyclic_permutations_of_partition_ite for perm in cyclic_permutations_iterator(partition[0]): yield [perm] + right def partitions(n): r""" Generator of all the partitions of the integer n. To compute the number of partitions of n use :meth:number_of_partitions. INPUT: -  n -- An integer EXAMPLES:: sage: partitions(3) sage: list(partitions(3)) doctest:1: DeprecationWarning: partitions is deprecated. Use Partitions() instead. See http://trac.sagemath.org/13072 for details. doctest:...: DeprecationWarning: partitions is deprecated. Use Partitions() instead. See http://trac.sagemath.org/13072 for details. [(1, 1, 1), (1, 2), (3,)] AUTHORS: - Adapted from David Eppstein, Jan Van lent, George Yoshida; Python Cookbook 2, Recipe 19.16. """ from sage.misc.superseded import deprecation deprecation(13072,'partitions is deprecated. Use Partitions() instead.') n = ZZ(n) # base case of the recursion: zero is the sum of the empty tuple if n == 0: yield ( ) return # modify the partitions of n-1 to form the partitions of n for p in partitions(n-1): yield (1,) + p if p and (len(p) < 2 or p[1] > p[0]): yield (p[0] + 1,) + p[1:] def ferrers_diagram(pi): """ Return the Ferrers diagram of pi. def ferrers_diagram(pi): def ordered_partitions(n,k=None): r""" An ordered partition of n is an ordered sum .. math:: n = p_1+p_2 + \cdots + p_k n = p_1+p_2 + \cdots + p_k of positive integers and is represented by the list p = [p_1,p_2,\cdots ,p_k]. If k is omitted then all ordered partitions are returned. ordered_partitions(n,k) returns the list of all (ordered) partitions of the positive integer n into sums with k summands. Do not call ordered_partitions with an n much larger than 15, since the list will simply become too large. Wraps GAP's OrderedPartitions. The number of ordered partitions T_n of \{ 1, 2, ..., n \} has the generating function is .. math:: \sum_n {T_n \over n!} x^n = {1 \over 2-e^x}. EXAMPLES:: sage: from sage.combinat.partition import ordered_partitions sage: ordered_partitions(10,2) doctest:1: DeprecationWarning: ordered_partitions is deprecated. Use OrderedPartitions instead. See http://trac.sagemath.org/13072 for details. [[1, 9], [2, 8], [3, 7], [4, 6], [5, 5], [6, 4], [7, 3], [8, 2], [9, 1]] :: def ordered_partitions(n,k=None): - http://en.wikipedia.org/wiki/Ordered_partition_of_a_set """ from sage.misc.superseded import deprecation deprecation(13072,'ordered_partitions is deprecated. Use OrderedPartitions instead.') if k is None: ans=gap.eval("OrderedPartitions(%s)"%(ZZ(n))) else: def number_of_ordered_partitions(n,k=Non """ Returns the size of ordered_partitions(n,k). Wraps GAP's NrOrderedPartitions. It is possible to associate with every partition of the integer n a conjugacy class of permutations in the symmetric group on n points and vice versa. Therefore p(n) = NrPartitions(n) is the number of def number_of_ordered_partitions(n,k=Non EXAMPLES:: sage: from sage.combinat.partition import number_of_ordered_partitions sage: number_of_ordered_partitions(10,2)