def _from_Monomial_on_basis(self, J): r""" Given a quasi-symmetric monomial function, this method returns the expansion into the dual immaculate basis. INPUT: - ``J`` -- a composition OUTPUT: - A quasi-symmetric function in the dual immaculate basis. EXAMPLES: sage: dI = QuasiSymmetricFunctions(QQ).dI() sage: dI._from_Monomial_on_basis(Composition([])) dI[] sage: dI._from_Monomial_on_basis(Composition([2,1])) -dI[1, 1, 1] - dI[1, 2] + dI[2, 1] sage: dI._from_Monomial_on_basis(Composition([3,1,2])) -dI[1, 1, 1, 1, 1, 1] + dI[1, 1, 1, 1, 2] + dI[1, 1, 1, 3] - dI[1, 1, 4] - dI[1, 2, 1, 1, 1] + dI[1, 2, 3] + dI[2, 1, 1, 1, 1] - dI[2, 1, 1, 2] + dI[2, 2, 1, 1] - dI[2, 2, 2] - dI[3, 1, 1, 1] + dI[3, 1, 2] """ n = J.size() C = Compositions() C_n = Compositions(n) mat = self._matrix_monomial_to_dual_immaculate(n) column = C_n.list().index(J) return self.sum_of_terms( (C(I), mat[C_n.list().index(I)][column]) for I in C_n)
def to_B_basis(self, S): r""" Return `D_S` as a linear combination of `B_p`-basis elements. EXAMPLES:: sage: DA = DescentAlgebra(QQ, 4) sage: D = DA.D() sage: B = DA.B() sage: for b in D.basis(): B(b) # indirect doctest B[4] B[1, 3] - B[4] B[2, 2] - B[4] B[1, 1, 2] - B[1, 3] - B[2, 2] + B[4] B[3, 1] - B[4] B[1, 2, 1] - B[1, 3] - B[3, 1] + B[4] B[2, 1, 1] - B[2, 2] - B[3, 1] + B[4] B[1, 1, 1, 1] - B[1, 1, 2] - B[1, 2, 1] + B[1, 3] - B[2, 1, 1] + B[2, 2] + B[3, 1] - B[4] """ B = self.realization_of().B() if len(S) == 0: return B.one() n = self.realization_of()._n C = Compositions(n) return B.sum_of_terms([(C.from_subset(T, n), (-1)**(len(S)-len(T))) for T in subsets(S)])
def __init__(self, parent, t): r""" Initialize a composition tableau. TESTS:: sage: t = CompositionTableaux()([[1],[2,2]]) sage: s = CompositionTableaux(3)([[1],[2,2]]) sage: s==t True sage: t.parent() Composition Tableaux sage: s.parent() Composition Tableaux of size 3 and maximum entry 3 sage: r = CompositionTableaux()(s) sage: r.parent() Composition Tableaux """ if isinstance(t, CompositionTableau): CombinatorialElement.__init__(self, parent, t._list) return # CombinatorialObject verifies that t is a list # We must verify t is a list of lists if not all(isinstance(row, list) for row in t): raise ValueError("A composition tableau must be a list of lists.") if not [len(_) for _ in t] in Compositions(): raise ValueError( "A composition tableau must be a list of non-empty lists.") # Verify rows weakly decrease from left to right for row in t: if any(row[i] < row[i + 1] for i in range(len(row) - 1)): raise ValueError( "Rows must weakly decrease from left to right.") # Verify leftmost column strictly increases from top to bottom first_col = [row[0] for row in t if t != [[]]] if any(first_col[i] >= first_col[i + 1] for i in range(len(t) - 1)): raise ValueError( "Leftmost column must strictly increase from top to bottom.") # Verify triple condition l = len(t) m = max([len(_) for _ in t] + [0]) TT = [row + [0] * (m - len(row)) for row in t] for i in range(l): for j in range(i + 1, l): for k in range(1, m): if TT[j][k] != 0 and TT[j][k] >= TT[i][k] and TT[j][ k] <= TT[i][k - 1]: raise ValueError("Triple condition must be satisfied.") CombinatorialElement.__init__(self, parent, t)
def __init__(self, QSym): """ EXAMPLES:: sage: M = QuasiSymmetricFunctions(QQ).Monomial(); M Quasisymmetric functions over the Rational Field in the Monomial basis sage: TestSuite(M).run() """ CombinatorialFreeModule.__init__(self, QSym.base_ring(), Compositions(), prefix='M', bracket=False, category=QSym.Bases())
def product_on_basis(self, p, q): r""" Return `B_p B_q`, where `p` and `q` are compositions of `n`. EXAMPLES:: sage: DA = DescentAlgebra(QQ, 4) sage: B = DA.B() sage: p = Composition([1,2,1]) sage: q = Composition([3,1]) sage: B.product_on_basis(p, q) B[1, 1, 1, 1] + 2*B[1, 2, 1] """ IM = IntegerMatrices(list(p), list(q)) P = Compositions(self.realization_of()._n) to_composition = lambda m: P([x for x in m.list() if x != 0]) return self.sum_of_monomials([to_composition(_) for _ in IM])
def one_basis(self): r""" Return the empty composition. OUTPUT - The empty composition. EXAMPLES:: sage: L=NonCommutativeSymmetricFunctions(QQ).L() sage: parent(L) <class 'sage.combinat.ncsf_qsym.ncsf.NonCommutativeSymmetricFunctions.Elementary_with_category'> sage: parent(L).one_basis() [] """ return Compositions()([])
def __init__(self, w1, w2, r): """ EXAMPLES:: sage: from sage.combinat.words.shuffle_product import ShuffleProduct_overlapping_r sage: w, u = map(Words("abcdef"), ["ab", "cd"]) sage: S = ShuffleProduct_overlapping_r(w,u,1) sage: S == loads(dumps(S)) True """ self._w1 = w1 self._w2 = w2 self.r = r self.W = self._w1.parent() # Special situation: the parent of w1 is too # restrictive to be cast on the shuffles. if isinstance(self.W, Compositions_n): self.W = Compositions()
def __init__(self, alg, prefix="B"): r""" Initialize ``self``. EXAMPLES:: sage: TestSuite(DescentAlgebra(QQ, 4).B()).run() """ self._prefix = prefix self._basis_name = "subset" CombinatorialFreeModule.__init__(self, alg.base_ring(), Compositions(alg._n), category=DescentAlgebraBases(alg), bracket="", prefix=prefix) S = NonCommutativeSymmetricFunctions(alg.base_ring()).Complete() self.module_morphism(self.to_nsym, codomain=S, category=Algebras(alg.base_ring()) ).register_as_coercion()
def IntegerCompositions(n): """ Returns the poset of integer compositions of the integer ``n``. A composition of a positive integer `n` is a list of positive integers that sum to `n`. The order is reverse refinement: `[p_1,p_2,...,p_l] < [q_1,q_2,...,q_m]` if `q` consists of an integer composition of `p_1`, followed by an integer composition of `p_2`, and so on. EXAMPLES:: sage: P = Posets.IntegerCompositions(7); P Finite poset containing 64 elements sage: len(P.cover_relations()) 192 """ from sage.combinat.composition import Compositions C = Compositions(n) return Poset((C, [[c,d] for c in C for d in C if d.is_finer(c)]), cover_relations=False)
def one_basis(self): r""" Return the identity element which is the composition `[n]`, as per ``AlgebrasWithBasis.ParentMethods.one_basis``. EXAMPLES:: sage: DescentAlgebra(QQ, 4).B().one_basis() [4] sage: DescentAlgebra(QQ, 0).B().one_basis() [] sage: all( U * DescentAlgebra(QQ, 3).B().one() == U ....: for U in DescentAlgebra(QQ, 3).B().basis() ) True """ n = self.realization_of()._n P = Compositions(n) if not n: # n == 0 return P([]) return P([n])
def __iter__(self): """ EXAMPLES:: sage: [ p for p in OrderedSetPartitions([1,2,3]) ] [[{1}, {2}, {3}], [{1}, {3}, {2}], [{2}, {1}, {3}], [{3}, {1}, {2}], [{2}, {3}, {1}], [{3}, {2}, {1}], [{1}, {2, 3}], [{2}, {1, 3}], [{3}, {1, 2}], [{1, 2}, {3}], [{1, 3}, {2}], [{2, 3}, {1}], [{1, 2, 3}]] """ for x in Compositions(len(self._set)): for z in OrderedSetPartitions(self._set, x): yield self.element_class(self, z)
def number_of_fCT(content_comp, shape_comp): r""" Return the number of Immaculate tableaux of shape ``shape_comp`` and content ``content_comp``. See [BBSSZ2012]_, Definition 3.9, for the notion of an immaculate tableau. INPUT: - ``content_comp``, ``shape_comp`` -- compositions OUTPUT: - An integer EXAMPLES:: sage: from sage.combinat.ncsf_qsym.combinatorics import number_of_fCT sage: number_of_fCT(Composition([3,1]), Composition([1,3])) 0 sage: number_of_fCT(Composition([1,2,1]), Composition([1,3])) 1 sage: number_of_fCT(Composition([1,1,3,1]), Composition([2,1,3])) 2 """ if content_comp.to_partition().length() == 1: if shape_comp.to_partition().length() == 1: return 1 else: return 0 C = Compositions(content_comp.size() - content_comp[-1], outer=list(shape_comp)) s = 0 for x in C: if len(x) >= len(shape_comp) - 1: s += number_of_fCT(Composition(content_comp[:-1]), x) return s
def m_to_s_stat(R, I, K): r""" Return the coefficient of the complete non-commutative symmetric function `S^K` in the expansion of the monomial non-commutative symmetric function `M^I` with respect to the complete basis over the ring `R`. This is the coefficient in formula (36) of Tevlin's paper [Tev2007]_. INPUT: - ``R`` -- A ring, supposed to be a `\QQ`-algebra - ``I``, ``K`` -- compositions OUTPUT: - The coefficient of `S^K` in the expansion of `M^I` in the complete basis of the non-commutative symmetric functions over ``R``. EXAMPLES:: sage: from sage.combinat.ncsf_qsym.combinatorics import m_to_s_stat sage: m_to_s_stat(QQ, Composition([2,1]), Composition([1,1,1])) -1 sage: m_to_s_stat(QQ, Composition([3]), Composition([1,2])) -2 sage: m_to_s_stat(QQ, Composition([2,1,2]), Composition([2,1,2])) 8/3 """ stat = 0 for J in Compositions(I.size()): if (I.is_finer(J) and K.is_finer(J)): pvec = [ 0 ] + Composition(I).refinement_splitting_lengths(J).partial_sums() pp = prod(R(len(I) - pvec[i]) for i in range(len(pvec) - 1)) stat += R((-1)**(len(I) - len(K)) / pp * coeff_lp(K, J)) return stat
def fatter(self): """ Return the set of ordered set partitions which are fatter than ``self``. See :meth:`finer` for the definition of "fatter". EXAMPLES:: sage: C = OrderedSetPartition([[2, 5], [1], [3, 4]]).fatter() sage: C.cardinality() 4 sage: sorted(C) [[{1, 2, 3, 4, 5}], [{1, 2, 5}, {3, 4}], [{2, 5}, {1, 3, 4}], [{2, 5}, {1}, {3, 4}]] sage: OrderedSetPartition([[4, 9], [-1, 2]]).fatter().list() [[{4, 9}, {-1, 2}], [{-1, 2, 4, 9}]] Some extreme cases:: sage: list(OrderedSetPartition([[5]]).fatter()) [[{5}]] sage: list(Composition([]).fatter()) [[]] sage: sorted(OrderedSetPartition([[1], [2], [3], [4]]).fatter()) [[{1, 2, 3, 4}], [{1, 2, 3}, {4}], [{1, 2}, {3, 4}], [{1, 2}, {3}, {4}], [{1}, {2, 3, 4}], [{1}, {2, 3}, {4}], [{1}, {2}, {3, 4}], [{1}, {2}, {3}, {4}]] """ return Compositions(len(self)).map(self.fatten)
def __init__(self, w1, w2, r): """ The overlapping shuffle product of the two words ``w1`` and ``w2`` with precisely ``r`` overlaps. See :class:`ShuffleProduct_overlapping` for a definition. EXAMPLES:: sage: from sage.combinat.words.shuffle_product import ShuffleProduct_overlapping_r sage: w, u = map(Words(range(20)), [[2, 9], [9, 1]]) sage: S = ShuffleProduct_overlapping_r(w,u,1) sage: S == loads(dumps(S)) True """ self._w1 = w1 self._w2 = w2 self.r = r self.W = self._w1.parent() # Special situation: the parent of w1 is too # restrictive to be cast on the shuffles. if isinstance(self.W, Compositions_n): self.W = Compositions()
def idempotent(self, la): """ Return the idemponent corresponding to the partition ``la``. EXAMPLES:: sage: I = DescentAlgebra(QQ, 4).I() sage: E = I.idempotent([3,1]); E 1/2*I[1, 3] + 1/2*I[3, 1] sage: E*E == E True sage: E2 = I.idempotent([2,1,1]); E2 1/6*I[1, 1, 2] + 1/6*I[1, 2, 1] + 1/6*I[2, 1, 1] sage: E2*E2 == E2 True sage: E*E2 == I.zero() True """ from sage.combinat.permutation import Permutations k = len(la) C = Compositions(self.realization_of()._n) return self.sum_of_terms([(C(x), ~QQ(factorial(k))) for x in Permutations(la)])
def __iter__(self): """ EXAMPLES:: sage: [ p for p in OrderedSetPartitions([1,2,3,4], 2) ] [[{1, 2, 3}, {4}], [{1, 2, 4}, {3}], [{1, 3, 4}, {2}], [{2, 3, 4}, {1}], [{1, 2}, {3, 4}], [{1, 3}, {2, 4}], [{1, 4}, {2, 3}], [{2, 3}, {1, 4}], [{2, 4}, {1, 3}], [{3, 4}, {1, 2}], [{1}, {2, 3, 4}], [{2}, {1, 3, 4}], [{3}, {1, 2, 4}], [{4}, {1, 2, 3}]] """ for x in Compositions(len(self._set), length=self.n): for z in OrderedSetPartitions_scomp(self._set, x): yield self.element_class(self, z)
def __init__(self, alg, prefix="I"): r""" Initialize ``self``. EXAMPLES:: sage: TestSuite(DescentAlgebra(QQ, 4).B()).run() """ self._prefix = prefix self._basis_name = "idempotent" CombinatorialFreeModule.__init__(self, alg.base_ring(), Compositions(alg._n), category=DescentAlgebraBases(alg), bracket="", prefix=prefix) # Change of basis: B = alg.B() self.module_morphism(self.to_B_basis, codomain=B, category=self.category() ).register_as_coercion() B.module_morphism(B.to_I_basis, codomain=self, category=self.category() ).register_as_coercion()
def strongly_finer(self): """ Return the set of ordered set partitions which are strongly finer than ``self``. See :meth:`is_strongly_finer` for the definition of "strongly finer". EXAMPLES:: sage: C = OrderedSetPartition([[1, 3], [2]]).strongly_finer() sage: C.cardinality() 2 sage: C.list() [[{1}, {3}, {2}], [{1, 3}, {2}]] sage: OrderedSetPartition([]).strongly_finer() {[]} sage: W = OrderedSetPartition([[4, 9], [-1, 2]]) sage: W.strongly_finer().list() [[{4}, {9}, {-1}, {2}], [{4}, {9}, {-1, 2}], [{4, 9}, {-1}, {2}], [{4, 9}, {-1, 2}]] """ par = parent(self) if not self: return FiniteEnumeratedSet([self]) else: buo = OrderedSetPartition.bottom_up_osp return FiniteEnumeratedSet([ par(sum((list(P) for P in C), [])) for C in cartesian_product( [[buo(X, comp) for comp in Compositions(len(X))] for X in self]) ])
def compositions_order(n): r""" Return the compositions of `n` ordered as defined in [QSCHUR]_. Let `S(\gamma)` return the composition `\gamma` after sorting. For compositions `\alpha` and `\beta`, we order `\alpha \rhd \beta` if 1) `S(\alpha) > S(\beta)` lexicographically, or 2) `S(\alpha) = S(\beta)` and `\alpha > \beta` lexicographically. INPUT: - ``n`` -- a positive integer OUTPUT: - A list of the compositions of ``n`` sorted into decreasing order by `\rhd` EXAMPLES:: sage: from sage.combinat.ncsf_qsym.combinatorics import compositions_order sage: compositions_order(3) [[3], [2, 1], [1, 2], [1, 1, 1]] sage: compositions_order(4) [[4], [3, 1], [1, 3], [2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] """ def _myorder(I, J): pI = sorted(I, reverse=True) pJ = sorted(J, reverse=True) if pI == pJ: return cmp(list(J), list(I)) else: return cmp(pJ, pI) return sorted(Compositions(n), cmp=_myorder)
def duality_pairing_matrix(self, basis, degree): r""" The matrix of scalar products between elements of NSym and elements of QSym. INPUT: - ``basis`` -- A basis of the dual Hopf algebra - ``degree`` -- a non-negative integer OUTPUT: - The matrix of scalar products between the basis ``self`` and the basis ``basis`` in the dual Hopf algebra of degree ``degree``. EXAMPLES: The ribbon basis of NCSF is dual to the fundamental basis of QSym:: sage: R = NonCommutativeSymmetricFunctions(QQ).ribbon() sage: F = QuasiSymmetricFunctions(QQ).Fundamental() sage: R.duality_pairing_matrix(F, 3) [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] sage: F.duality_pairing_matrix(R, 3) [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] The complete basis of NCSF is dual to the monomial basis of QSym:: sage: S = NonCommutativeSymmetricFunctions(QQ).complete() sage: M = QuasiSymmetricFunctions(QQ).Monomial() sage: S.duality_pairing_matrix(M, 3) [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] sage: M.duality_pairing_matrix(S, 3) [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] The matrix between the ribbon basis of NCSF and the monomial basis of QSym:: sage: R = NonCommutativeSymmetricFunctions(QQ).ribbon() sage: M = QuasiSymmetricFunctions(QQ).Monomial() sage: R.duality_pairing_matrix(M, 3) [ 1 -1 -1 1] [ 0 1 0 -1] [ 0 0 1 -1] [ 0 0 0 1] sage: M.duality_pairing_matrix(R, 3) [ 1 0 0 0] [-1 1 0 0] [-1 0 1 0] [ 1 -1 -1 1] The matrix between the complete basis of NCSF and the fundamental basis of QSym:: sage: S = NonCommutativeSymmetricFunctions(QQ).complete() sage: F = QuasiSymmetricFunctions(QQ).Fundamental() sage: S.duality_pairing_matrix(F, 3) [1 1 1 1] [0 1 0 1] [0 0 1 1] [0 0 0 1] A base case test:: sage: R.duality_pairing_matrix(M,0) [1] """ from sage.matrix.constructor import matrix # TODO: generalize to keys indexing the basis of the graded component from sage.combinat.composition import Compositions return matrix(self.base_ring(), [[self.duality_pairing(self[I], basis[J]) \ for J in Compositions(degree)] \ for I in Compositions(degree)])
def number_of_SSRCT(content_comp, shape_comp): r""" The number of semi-standard reverse composition tableaux. The dual quasisymmetric-Schur functions satisfy a left Pieri rule where `S_n dQS_\gamma` is a sum over dual quasisymmetric-Schur functions indexed by compositions which contain the composition `\gamma`. The definition of an SSRCT comes from this rule. The number of SSRCT of content `\beta` and shape `\alpha` is equal to the number of SSRCT of content `(\beta_2, \ldots, \beta_\ell)` and shape `\gamma` where `dQS_\alpha` appears in the expansion of `S_{\beta_1} dQS_\gamma`. In sage the recording tableau for these objects are called :class:`~sage.combinat.composition_tableau.CompositionTableaux`. INPUT: - ``content_comp``, ``shape_comp`` -- compositions OUTPUT: - An integer EXAMPLES:: sage: from sage.combinat.ncsf_qsym.combinatorics import number_of_SSRCT sage: number_of_SSRCT(Composition([3,1]), Composition([1,3])) 0 sage: number_of_SSRCT(Composition([1,2,1]), Composition([1,3])) 1 sage: number_of_SSRCT(Composition([1,1,2,2]), Composition([3,3])) 2 sage: all(CompositionTableaux(be).cardinality() ....: == sum(number_of_SSRCT(al,be)*binomial(4,len(al)) ....: for al in Compositions(4)) ....: for be in Compositions(4)) True """ if len(content_comp) == 1: if len(shape_comp) == 1: return ZZ.one() else: return ZZ.zero() s = ZZ.zero() cond = lambda al, be: all(al[j] <= be_val and not any(al[ i] <= k and k <= be[i] for k in range(al[j], be_val) for i in range(j)) for j, be_val in enumerate(be)) C = Compositions(content_comp.size() - content_comp[0], inner=[1] * len(shape_comp), outer=list(shape_comp)) for x in C: if cond(x, shape_comp): s += number_of_SSRCT(Composition(content_comp[1:]), x) if shape_comp[0] <= content_comp[0]: C = Compositions( content_comp.size() - content_comp[0], inner=[min(val, shape_comp[0] + 1) for val in shape_comp[1:]], outer=shape_comp[1:]) Comps = Compositions() for x in C: if cond([shape_comp[0]] + list(x), shape_comp): s += number_of_SSRCT(Comps(content_comp[1:]), x) return s
def LyndonWords(e=None, k=None): """ Returns the combinatorial class of Lyndon words. A Lyndon word `w` is a word that is lexicographically less than all of its rotations. Equivalently, whenever `w` is split into two non-empty substrings, `w` is lexicographically less than the right substring. INPUT: - no input at all or - ``e`` - integer, size of alphabet - ``k`` - integer, length of the words or - ``e`` - a composition OUTPUT: A combinatorial class of Lyndon words. EXAMPLES:: sage: LyndonWords() Lyndon words If e is an integer, then e specifies the length of the alphabet; k must also be specified in this case:: sage: LW = LyndonWords(3,3); LW Lyndon words from an alphabet of size 3 of length 3 sage: LW.first() word: 112 sage: LW.last() word: 233 sage: LW.random_element() word: 112 sage: LW.cardinality() 8 If e is a (weak) composition, then it returns the class of Lyndon words that have evaluation e:: sage: LyndonWords([2, 0, 1]).list() [word: 113] sage: LyndonWords([2, 0, 1, 0, 1]).list() [word: 1135, word: 1153, word: 1315] sage: LyndonWords([2, 1, 1]).list() [word: 1123, word: 1132, word: 1213] """ if e is None and k is None: return LyndonWords_class() elif isinstance(e, (int, Integer)): if e > 0: if not isinstance(k, (int, Integer)): raise TypeError("k must be a non-negative integer") if k < 0: raise TypeError("k must be a non-negative integer") return LyndonWords_nk(e, k) elif e in Compositions(): return LyndonWords_evaluation(e) raise TypeError("e must be a positive integer or a composition")
def __classcall_private__(cls, *args, **kwargs): r""" This is a factory class which returns the appropriate parent based on arguments. See the documentation for :class:`CompositionTableaux` for more information. TESTS:: sage: CT = CompositionTableaux(3); CT Composition Tableaux of size 3 and maximum entry 3 sage: CT = CompositionTableaux(size=3); CT Composition Tableaux of size 3 and maximum entry 3 sage: CT = CompositionTableaux([1,2]); CT Composition tableaux of shape [1, 2] and maximun entry 3 sage: CT = CompositionTableaux(shape=[1,2]); CT Composition tableaux of shape [1, 2] and maximun entry 3 sage: CT = CompositionTableaux(shape=[]); CT Composition tableaux of shape [] and maximun entry 0 sage: CT = CompositionTableaux(0); CT Composition Tableaux of size 0 and maximum entry 0 sage: CT = CompositionTableaux(max_entry=3); CT Composition tableaux with maximum entry 3 sage: CT = CompositionTableaux([1,2],max_entry=3); CT Composition tableaux of shape [1, 2] and maximun entry 3 sage: CT = CompositionTableaux(size=2,shape=[1,2]); CT Traceback (most recent call last): ... ValueError: size and shape are different sizes """ # Process keyword arguments first n = kwargs.get('n', None) size = kwargs.get('size', n) comp = kwargs.get('comp', None) shape = kwargs.get('shape', comp) max_entry = kwargs.get('max_entry', None) # Process positional arguments if args: # The first arg could be either a size or a shape if isinstance(args[0], (int, Integer)): if size is not None: raise ValueError("size was specified more than once") else: size = args[0] else: if shape is not None: raise ValueError("the shape was specified more than once") shape = args[0] # Consistency checks if size is not None: if not isinstance(size, (int, Integer)): raise ValueError("size must be an integer") elif size < 0: raise ValueError("size must be non-negative") if shape is not None: # use in (and not isinstance) below so that lists can be used as # shorthand if not shape in Compositions(): raise ValueError("shape must be a composition") if any(i == 0 for i in shape): raise ValueError("shape must have non-zero parts") shape = Composition(shape) if (size is not None) and (shape is not None): if sum(shape) != size: raise ValueError("size and shape are different sizes") if max_entry is not None: if not isinstance(max_entry, (int, Integer)): raise ValueError("max_entry must be an integer") elif max_entry <= 0: raise ValueError("max_entry must be positive") # Dispatch to appropriate class if (shape is not None): return CompositionTableaux_shape(shape, max_entry) if (size is not None): return CompositionTableaux_size(size, max_entry) return CompositionTableaux_all(max_entry)