# Ticket #14063: trac_14063-remove_cc_compositions-ts.patch

File trac_14063-remove_cc_compositions-ts.patch, 55.3 KB (added by tscrim, 9 years ago)

Fixed docstrings

• ## sage/combinat/composition.py

# HG changeset patch
# User Travis Scrimshaw <tscrim@ucdavis.edu>
# Date 1361280404 28800
# Node ID a963fa24217ffd1f11ce84a68f8fd33ba72792fc
# Parent b9dca1a217f9a12d1a87974164725bf158937c1f
Trac #14063 - Removed CombinatorialClass from Compositions.

diff --git a/sage/combinat/composition.py b/sage/combinat/composition.py
 a """ r""" Integer compositions A composition c of a nonnegative integer n is a list of positive integers AUTHORS: - Mike Hansen, Nicolas M. Thiery - MuPAD-Combinat developers (algorithms and design inspiration) - Travis Scrimshaw (2013-02-03): Removed CombinatorialClass """ #***************************************************************************** #       Copyright (C) 2007 Mike Hansen        AUTHORS: #***************************************************************************** from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent from sage.structure.element import Element from sage.misc.classcall_metaclass import ClasscallMetaclass from sage.misc.superseded import deprecated_function_alias from sage.rings.all import ZZ import sage.combinat.skew_partition from combinat import CombinatorialClass, CombinatorialObject, InfiniteAbstractCombinatorialClass from combinat import CombinatorialObject from cartesian_product import CartesianProduct from integer_list import IntegerListsLex import __builtin__ from sage.rings.integer import Integer def Composition(co=None, descents=None, code=None, from_subset=None): """ class Composition(CombinatorialObject, Element): r""" Integer compositions A composition of a nonnegative integer n is a list (i_1,\dots,i_k) of positive integers with total sum n. (i_1, \ldots, i_k) of positive integers with total sum n. EXAMPLES: def Composition(co=None, descents=None, [2, 3, 4] You can also create a composition from its code. The *code* of a composition [i_1, i_2, \dots, i_k] of n is a list of length n a composition (i_1, i_2, \ldots, i_k) of n is a list of length n that consists of a 1 followed by i_1-1 zeros, then a 1 followed by i_2-1 zeros, and so on. def Composition(co=None, descents=None, [3, 1, 2, 3, 5] You can also create the composition of n corresponding to a subset of \{1, 2, \dots, n-1\} under the bijection that maps the composition [i_1, i_2, \dots, i_k] of n to the subset \{i_1, i_1 + i_2, i_1 + i_2 + i_3, \dots, i_1 + \cdots + i_{k-1}\} \{1, 2, \ldots, n-1\} under the bijection that maps the composition (i_1, i_2, \ldots, i_k) of n to the subset \{i_1, i_1 + i_2, i_1 + i_2 + i_3, \ldots, i_1 + \cdots + i_{k-1}\} (see :meth:to_subset):: sage: Composition(from_subset=({1, 2, 4}, 5)) def Composition(co=None, descents=None, sage: Composition([1, 1, 2, 1]).to_subset() {1, 2, 4} The following notation equivalently specifies the composition from the set \{i_1 - 1, i_1 + i_2 - 1, i_1 + i_2 + i_3 - 1, \dots, i_1 + \cdots The following notation equivalently specifies the composition from the set \{i_1 - 1, i_1 + i_2 - 1, i_1 + i_2 + i_3 - 1, \dots, i_1 + \cdots + i_{k-1} - 1, n-1\} or \{i_1 - 1, i_1 + i_2 - 1, i_1 + i_2 + i_3 - 1, \dots, i_1 + \cdots + i_{k-1} - 1\} and n. This provides compatibility with Python's 0-indexing. def Composition(co=None, descents=None, [1, 1, 2, 1] sage: Composition(descents=({0,1,3},5)) [1, 1, 2, 1] """ __metaclass__ = ClasscallMetaclass """ if descents is not None: if isinstance(descents, tuple): return from_descents(descents[0], nps=descents[1]) else: return from_descents(descents) elif code is not None: return from_code(code) elif from_subset is not None: return composition_from_subset(*from_subset) elif isinstance(co, Composition_class): return co else: co = list(co) assert(co in Compositions()) #raise ValueError, "invalid composition" return Composition_class(co) class Composition_class(CombinatorialObject): __doc__ = Composition.__doc__ def parent(self): @staticmethod def __classcall_private__(cls, co=None, descents=None, code=None, from_subset=None): """ Returns the combinatorial class of compositions. This constructs a list from optional arguments and delegates the construction of a :class:Composition to the element_class() call of the appropriate parent. EXAMPLES:: sage: Composition([3,2,1]).parent() Compositions of non-negative integers sage: Composition([3,2,1]) [3, 2, 1] sage: Composition(from_subset=({1, 2, 4}, 5)) [1, 1, 2, 1] sage: Composition(descents=[1,0,4,8,11]) [1, 1, 3, 4, 3] sage: Composition([4,1,2,3,5]).to_code() [1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0] sage: Composition(code=_) [4, 1, 2, 3, 5] """ return Compositions() if descents is not None: if isinstance(descents, tuple): return Compositions().from_descents(descents[0], nps=descents[1]) else: return Compositions().from_descents(descents) elif code is not None: return Compositions().from_code(code) elif from_subset is not None: return Compositions().from_subset(*from_subset) elif isinstance(co, Composition): return co else: return Compositions()(list(co)) def __init__(self, parent, lst): """ Initialize self. EXAMPLES:: sage: C = Composition([3,1,2]) sage: TestSuite(C).run() """ CombinatorialObject.__init__(self, lst) Element.__init__(self, parent) def __setstate__(self, state): r""" In order to maintain backwards compatibility and be able to unpickle a old pickle from Partition_class we have to override the default __setstate__. EXAMPLES:: sage: loads("x\x9ckJ.NLO\xd5K\xce\xcfM\xca\xccK,\x011\n\xf2\x8b3K2\xf3\xf3\xb8\x9c\x11\xec\xf8\xe4\x9c\xc4\xe2b\xaeBF\xcd\xc6B\xa6\xdaBf\x8dP\xd6\xf8\x8c\xc4\xe2\x8cB\x16? +'\xb3\xb8\xa4\x905\xb6\x90M\x03bZQf^z\xb1^f^Ijzj\x11Wnbvj<\x8cS\xc8\x1e\xcah\xd8\x1aT\xc8\x91\x01d\x18\x01\x19\x9c\x19P\x11\xae\xd4\xd2\$=\x00eW0g") [1, 2, 1] sage: loads(dumps( Composition([1,2,1]) ))  # indirect doctest [1, 2, 1] """ if isinstance(state, dict):   # for old pickles from Composition_class self._set_parent(Compositions()) self.__dict__ = state else: self._set_parent(state[0]) self.__dict__ = state[1] def conjugate(self): r""" class Composition_class(CombinatorialObj cocjg += [i+1 for _ in range(0, (coofcp[n-i-1]-coofcp[n-i-2]))] cocjg += [n for j in range(coofcp[0])] return Composition([cocjg[0]] + [cocjg[i]-cocjg[i-1]+1 for i in range(1,len(cocjg)) ]) return self.parent()([cocjg[0]] + [cocjg[i]-cocjg[i-1]+1 for i in range(1,len(cocjg))]) def reversed(self): """ Returns the reverse of the composition. Return the reverse composition of self. EXAMPLES:: sage: Composition([1, 1, 3, 1, 2, 1, 3]).reversed() [3, 1, 2, 1, 3, 1, 1] """ return Composition(reversed(self)) return self.parent()(reversed(self)) def complement(self): """ Returns the complement of the composition co. The complement is the reverse of co's conjugate composition. Return the complement composition of self. The complement is the reverse of the conjugate composition of self. EXAMPLES:: class Composition_class(CombinatorialObj """ return self.conjugate().reversed() def __add__(self, other): """ Returns the concatenation of two compositions. Return the concatenation of two compositions. EXAMPLES:: class Composition_class(CombinatorialObj def size(self): """ Returns the size of the composition, that is the sum of its parts. Return the size of self, that is the sum of its parts. EXAMPLES:: class Composition_class(CombinatorialObj @staticmethod def sum(compositions): """ Returns the concatenation of the given compositions. Return the concatenation of the given compositions. INPUT: class Composition_class(CombinatorialObj EXAMPLES:: sage: sage.combinat.composition.Composition_class.sum([Composition([1, 1, 3]), Composition([4, 1, 2]), Composition([3,1])]) sage: Composition.sum([Composition([1, 1, 3]), Composition([4, 1, 2]), Composition([3,1])]) [1, 1, 3, 4, 1, 2, 3, 1] Any iterable can be provided as input:: sage: sage.combinat.composition.Composition_class.sum([Composition([i,i]) for i in [4,1,3]]) sage: Composition.sum([Composition([i,i]) for i in [4,1,3]]) [4, 4, 1, 1, 3, 3] Empty inputs are handled gracefully:: sage: sage.combinat.composition.Composition_class.sum([]) == Composition([]) sage: Composition.sum([]) == Composition([]) True """ return sum(compositions, Composition([])) def finer(self): """ Returns the set of compositions which are finer than self. Return the set of compositions which are finer than self. EXAMPLES:: class Composition_class(CombinatorialObj sage: list(C) [[1, 1, 1, 1, 1], [1, 1, 1, 2], [1, 2, 1, 1], [1, 2, 2], [2, 1, 1, 1], [2, 1, 2], [3, 1, 1], [3, 2]] """ return CartesianProduct(*[Compositions(i) for i in self]).map(Composition_class.sum) return CartesianProduct(*[Compositions(i) for i in self]).map(Composition.sum) def is_finer(self, co2): """ Returns True if the composition self is finer than the composition co2; otherwise, it returns False. Return True if the composition self is finer than the composition co2; otherwise, it returns False. EXAMPLES:: class Composition_class(CombinatorialObj """ co1 = self if sum(co1) != sum(co2): #Error: compositions are not of the same size raise ValueError, "compositions self (= %s) and co2 (= %s) must be of the same size"%(self, co2) raise ValueError("compositions self (= %s) and co2 (= %s) must be of the same size"%(self, co2)) sum1 = 0 sum2 = 0 class Composition_class(CombinatorialObj return True def fatten(self, grouping): """ Returns the composition fatter than self, obtained by grouping r""" Return the composition fatter than self, obtained by grouping together consecutive parts according to grouping. INPUT: - grouping -- a composition whose sum is the length of self - grouping -- a composition whose sum is the length of self EXAMPLES: class Composition_class(CombinatorialObj sage: c = Composition([4,5,2,7,1]) With grouping = (1,\dots,1), c is left unchanged:: With grouping equal to (1, \ldots, 1), c is left unchanged:: sage: c.fatten(Composition([1,1,1,1,1])) [4, 5, 2, 7, 1] With grouping = (5), this yields the coarser composition above c:: With grouping equal to (\ell) where \ell is the length of self, this yields the coarser composition above c:: sage: c.fatten(Composition([5])) [19] class Composition_class(CombinatorialObj for i in range(len(grouping)): result[i] = sum(self[j:j+grouping[i]]) j += grouping[i] return Composition_class(result) return Composition(result) def fatter(self): """ Returns the set of compositions which are fatter than self. Return the set of compositions which are fatter than self. Complexity for generation: O(size(c)) memory, O(size(result)) time Complexity for generation: O(|c|) memory, O(|r|) time where |c| is the size of self and r is the result. EXAMPLES:: class Composition_class(CombinatorialObj def refinement_splitting(self, J): r""" Returns the refinement splitting of I=self according to J. Return the refinement splitting of self according to J. INPUT: - J:=(J_1,\dots,J_m) -- a composition such that I is finer than J - J -- A composition such that I is finer than J OUTPUT: class Composition_class(CombinatorialObj obtained by splitting I, such that |I^{(p)}| = J_p for all p = 1, \ldots, m. .. SEEALSO:: :meth:refinement_splitting_lengths .. SEEALSO:: :meth:refinement_splitting_lengths EXAMPLES:: class Composition_class(CombinatorialObj I = self if sum(I) != sum(J): #Error: compositions are not of the same size raise ValueError, "compositions self (= %s) and J (= %s) must be of the same size"%(I, J) raise ValueError("compositions self (= %s) and J (= %s) must be of the same size"%(I, J)) sum1 = 0 sum2 = 0 i1 = -1 class Composition_class(CombinatorialObj new_comp.append(I[i1]) sum1 += new_comp[-1] if sum1 > sum2: raise ValueError, \ "composition J (= %s) does not refine self (= %s)"%(I, J) raise ValueError("composition J (= %s) does not refine self (= %s)"%(I, J)) decomp.append(Composition(new_comp)) return decomp def refinement_splitting_lengths(self, J): """ Returns the lengths of the compositions in the refinement splitting of I=self according to J. Return the lengths of the compositions in the refinement splitting of I=self according to J. .. SEEALSO:: :meth:refinement_splitting for the definition of refinement splitting .. SEEALSO:: :meth:refinement_splitting for the definition of refinement splitting EXAMPLES:: class Composition_class(CombinatorialObj def major_index(self): """ Returns the major index of the composition co. The major index is Return the major index of self. The major index is defined as the sum of the descents. EXAMPLES:: class Composition_class(CombinatorialObj else: return sum([(lv-(i+1))*co[i] for i in range(lv)]) def to_code(self): """ Returns the code of the composition self. The code of a composition is a list of length self.size() of 1s and 0s such that there is a 1 Return the code of the composition self. The code of a composition is a list of length self.size() of 1s and 0s such that there is a 1 wherever a new part starts. EXAMPLES:: class Composition_class(CombinatorialObj sage: Composition([4,1,2,3,5]).to_code() [1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0] """ if self == []: return [0] class Composition_class(CombinatorialObj The partial sums of the sequence defined by the entries of the composition. If I = [i_1, \dots, i_m] is a composition, then the partial sums of If I = (i_1, \ldots, i_m) is a composition, then the partial sums of the entries of the composition are [i_1, i_1 + i_2, \dots, i_1 + i_2 + \cdots + i_{m}]. [i_1, i_1 + i_2, \ldots, i_1 + i_2 + \cdots + i_{m}]. INPUT: - final -- (default: True) whether or not to include the final partial sum, which is always the size of the composition. .. SEEALSO:: :meth:to_subset .. SEEALSO:: :meth:to_subset EXAMPLES:: sage: Composition([1,1,3,1,2,1,3]).partial_sums() [1, 2, 5, 6, 8, 9, 12] With final=False, the last partial sum is not included:: With final = False, the last partial sum is not included:: sage: Composition([1,1,3,1,2,1,3]).partial_sums(final=False) [1, 2, 5, 6, 8, 9] class Composition_class(CombinatorialObj def to_subset(self, final=False): r""" The subset corresponding to self under the bijection (see below) between compositions of n and subsets of \{1, 2, \dots, n-1\}. between compositions of n and subsets of \{1, 2, \ldots, n-1\}. The bijection maps a composition [i_1, \dots, i_k] of n to \{i_1, i_1 + i_2, i_1 + i_2 + i_3, \dots, i_1 + \cdots + i_{k-1}\}. The bijection maps a composition (i_1, \ldots, i_k) of n to \{i_1, i_1 + i_2, i_1 + i_2 + i_3, \ldots, i_1 + \cdots + i_{k-1}\}. INPUT: - final -- (default: False) whether or not to include the final partial sum, which is always the size of the composition. .. SEEALSO:: :meth:partial_sums .. SEEALSO:: :meth:partial_sums EXAMPLES:: class Composition_class(CombinatorialObj through the original implementation was broken (it gave the wrong answer). The same information can be found in :meth:partial_sums. .. SEEALSO:: :meth:partial_sums .. SEEALSO:: :meth:partial_sums INPUT: - self -- a composition - final_descent -- (Default: False) a boolean integer - final_descent -- (Default: False) a boolean integer OUTPUT: - Returns the list of partial sums of self with each part subtracted by 1. This includes the sum of all entries when final_descent is true. final_descent is True. EXAMPLES:: class Composition_class(CombinatorialObj def peaks(self): """ Returns a list of the peaks of the composition self. The Return a list of the peaks of the composition self. The peaks of a composition are the descents which do not immediately follow another descent. class Composition_class(CombinatorialObj def to_skew_partition(self, overlap=1): """ Returns the skew partition obtained from the composition co. The Return the skew partition obtained from self. The parameter overlap indicates the number of cells that are covered by cells of the previous line. class Composition_class(CombinatorialObj r""" The (overlapping) shuffles of self and other. Suppose I = [i_1, \dots, i_k] and J = [j_1, \dots, j_l] are two Suppose I = (i_1, \ldots, i_k) and J = (j_1, \ldots, j_l) are two compositions. A *shuffle* of I and J is a composition of length k + l that contains both I and J as subsequences. class Composition_class(CombinatorialObj INPUT: -  other -- composition -  overlap -- boolean (default: False); if True, the overlapping shuffle product is returned. OUTPUT: - enumerated set (allowing for mutliplicities) An enumerated set (allowing for mutliplicities) EXAMPLES: class Composition_class(CombinatorialObj ############################################################## def Compositions(n=None, **kwargs): class Compositions(Parent, UniqueRepresentation): r""" Sets of integer Compositions. Set of integer compositions. A composition c of a nonnegative integer n is a list of positive integers with total sum n. See also: Composition, Partitions, IntegerVectors .. SEEALSO:: - :class:Composition - :class:Partitions - :class:IntegerVectors EXAMPLES: def Compositions(n=None, **kwargs): Here is the list of them:: sage: list(Compositions(4)) sage: Compositions(4).list() [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]] You can use the .first() method to get the 'first' composition of def Compositions(n=None, **kwargs): sage: Compositions(4).next([1,1,2]) [1, 2, 1] If n is not specified, this returns the combinatorial class of all (non-negative) integer compositions:: def Compositions(n=None, **kwargs): sage: [-2,3,1] in Compositions() False If n is specified, it returns the class of compositions of n:: If n is specified, it returns the class of compositions of n:: sage: Compositions(3) Compositions of 3 def Compositions(n=None, **kwargs): Note that the given constraints should be compatible:: sage: [4,2] in Compositions(6, inner=[2,2], min_part=3) # sage: [4,2] in Compositions(6, inner=[2,2], min_part=3) True The options length, min_length, and max_length can be used to set length constraints on the compositions. For example, the The options length, min_length, and max_length can be used to set length constraints on the compositions. For example, the compositions of 4 of length equal to, at least, and at most 2 are given by:: def Compositions(n=None, **kwargs): sage: Compositions(4, max_length=2).list() [[4], [3, 1], [2, 2], [1, 3]] Setting both min_length and max_length to the same value is equivalent to setting length to this value:: Setting both min_length and max_length to the same value is equivalent to setting length to this value:: sage: Compositions(4, min_length=2, max_length=2).list() [[3, 1], [2, 2], [1, 3]] The options inner and outer can be used to set part-by-part The options inner and outer can be used to set part-by-part containment constraints. The list of compositions of 4 bounded above by [3,1,2] is given by:: above by [3,1,2] is given by:: sage: list(Compositions(4, outer=[3,1,2])) [[3, 1], [2, 1, 1], [1, 1, 2]] Outer sets max_length to the length of its argument. Moreover, the parts of outer may be infinite to clear the constraint on specific outer sets max_length to the length of its argument. Moreover, the parts of outer may be infinite to clear the constraint on specific parts. This is the list of compositions of 4 of length at most 3 such that the first and third parts are at most 1:: sage: list(Compositions(4, outer=[1,oo,1])) sage: Compositions(4, outer=[1,oo,1]).list() [[1, 3], [1, 2, 1]] This is the list of compositions of 4 bounded below by [1,1,1]:: This is the list of compositions of 4 bounded below by [1,1,1]:: sage: list(Compositions(4, inner=[1,1,1])) sage: Compositions(4, inner=[1,1,1]).list() [[2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] The options min_slope and max_slope can be used to set constraints on the slope, that is the difference p[i+1]-p[i] of two The options min_slope and max_slope can be used to set constraints on the slope, that is the difference p[i+1]-p[i] of two consecutive parts. The following is the list of weakly increasing compositions of 4:: def Compositions(n=None, **kwargs): results. It is up to the user to ensure that the inner and outer compositions themselves satisfy the parts and slope constraints. Note that if you specify min_part=0, then the objects produced may Note that if you specify min_part=0, then the objects produced may have parts equal to zero. This violates the internal assumptions that the Composition class makes. Use at your own risk, or that the composition class makes. Use at your own risk, or preferably consider using IntegerVectors instead:: sage: list(Compositions(2, length=3, min_part=0)) sage: Compositions(2, length=3, min_part=0).list() doctest:... RuntimeWarning: Currently, setting min_part=0 produces Composition objects which violate internal assumptions.  Calling methods on these objects may produce errors or WRONG results! [[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]] def Compositions(n=None, **kwargs): [[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]] The generation algorithm is constant amortized time, and handled by the generic tool IntegerListsLex. by the generic tool :class:IntegerListsLex. TESTS:: def Compositions(n=None, **kwargs): sage: Compositions(6, min_part=2, length=3) Compositions of the integer 6 satisfying constraints length=3, min_part=2 sage: [2, 1] in Compositions(3, length=2) True sage: [2,1,2] in Compositions(5, min_part=1) def Compositions(n=None, **kwargs): sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4, outer=[2,5,2]).list() [[2, 3], [2, 2, 1], [2, 1, 2], [1, 2, 2]] """ if n is None: assert(len(kwargs) == 0) return Compositions_all() else: if len(kwargs) == 0: if isinstance(n, (int,Integer)): return Compositions_n(n) @staticmethod def __classcall_private__(self, n=None, **kwargs): """ Return the correct parent based upon the input. EXAMPLES:: sage: C = Compositions(3) sage: C2 = Compositions(int(3)) sage: C is C2 True """ if n is None: if len(kwargs) != 0: raise ValueError("Incorrect number of arguments") return Compositions_all() else: if len(kwargs) == 0: if isinstance(n, (int,Integer)): return Compositions_n(n) else: raise ValueError("n must be an integer") else: raise ValueError, "n must be an integer" # FIXME: should inherit from IntegerListLex, and implement repr, or _name as a lazy attribute kwargs['name'] = "Compositions of the integer %s satisfying constraints %s"%(n, ", ".join( ["%s=%s"%(key, kwargs[key]) for key in sorted(kwargs.keys())] )) kwargs['element_constructor'] = Composition if 'min_part' not in kwargs: kwargs['min_part'] = 1 elif kwargs['min_part'] == 0: from warnings import warn warn("Currently, setting min_part=0 produces Composition objects which violate internal assumptions.  Calling methods on these objects may produce errors or WRONG results!", RuntimeWarning) if 'outer' in kwargs: kwargs['ceiling'] = list(kwargs['outer']) if 'max_length' in kwargs: kwargs['max_length'] = min(len(kwargs['outer']), kwargs['max_length']) else: kwargs['max_length'] = len(kwargs['outer']) del kwargs['outer'] if 'inner' in kwargs: inner = list(kwargs['inner']) kwargs['floor'] = inner del kwargs['inner'] # Should this be handled by integer lists lex? if 'min_length' in kwargs: kwargs['min_length'] = max(len(inner), kwargs['min_length']) else: kwargs['min_length'] = len(inner) return IntegerListsLex(n, **kwargs) def __init__(self, is_infinite=False): """ Initialize self. EXAMPLES:: sage: C = Compositions() sage: TestSuite(C).run() """ if is_infinite: Parent.__init__(self, category=InfiniteEnumeratedSets()) else: # FIXME: should inherit from IntegerListLex, and implement repr, or _name as a lazy attribute kwargs['name'] = "Compositions of the integer %s satisfying constraints %s"%(n, ", ".join( ["%s=%s"%(key, kwargs[key]) for key in sorted(kwargs.keys())] )) kwargs['element_constructor'] = Composition_class if 'min_part' not in kwargs: kwargs['min_part'] = 1 elif kwargs['min_part'] == 0: from warnings import warn warn("Currently, setting min_part=0 produces Composition objects which violate internal assumptions.  Calling methods on these objects may produce errors or WRONG results!", RuntimeWarning) Parent.__init__(self, category=FiniteEnumeratedSets()) if 'outer' in kwargs: kwargs['ceiling'] = list(kwargs['outer']) if 'max_length' in kwargs: kwargs['max_length'] = min( len(kwargs['outer']), kwargs['max_length']) else: kwargs['max_length'] = len(kwargs['outer']) del kwargs['outer'] Element = Composition if 'inner' in kwargs: inner = list(kwargs['inner']) kwargs['floor'] = inner del kwargs['inner'] # Should this be handled by integer lists lex? if 'min_length' in kwargs: kwargs['min_length'] = max( len(inner), kwargs['min_length']) else: kwargs['min_length'] = len(inner) return IntegerListsLex(n, **kwargs) def _element_constructor_(self, lst): """ Construct an element with self as parent. EXAMPLES:: sage: P = Compositions() sage: P([3,3,1]) # indirect doctest [3, 3, 1] """ if isinstance(lst, Composition): lst = list(lst) elt = self.element_class(self, lst) if elt not in self: raise ValueError("%s not in %s"%(elt, self)) return elt def __contains__(self, x): """ TESTS:: sage: [2,1,3] in Compositions() True sage: [] in Compositions() True sage: [-2,-1] in Compositions() False sage: [0,0] in Compositions() True """ if isinstance(x, Composition): return True elif isinstance(x, __builtin__.list): for i in range(len(x)): if (not isinstance(x[i], (int, Integer))) and x[i] not in ZZ: return False if x[i] < 0: return False return True else: return False def from_descents(self, descents, nps=None): """ Returns a composition from the list of descents. INPUT: - descents -- an iterable - nps -- (default: None) an integer or None; if None, then nps is taken to be 1 plus the maximum element of descents. EXAMPLES:: sage: [x-1 for x in Composition([1, 1, 3, 4, 3]).to_subset()] [0, 1, 4, 8] sage: Compositions().from_descents([1,0,4,8],12) [1, 1, 3, 4, 3] sage: Compositions().from_descents([1,0,4,8,11]) [1, 1, 3, 4, 3] """ d = [x+1 for x in sorted(descents)] if nps is None: nps = d.pop() return self.from_subset(d, nps) def from_subset(self, S, n): r""" The composition of n corresponding to the subset S of \{1, 2, \ldots, n-1\} under the bijection that maps the composition (i_1, i_2, \ldots, i_k) of n to the subset \{i_1, i_1 + i_2, i_1 + i_2 + i_3, \ldots, i_1 + \cdots + i_{k-1}\} (see :meth:Composition.to_subset). INPUT: - S -- an iterable, a subset of n-1 - n -- an integer EXAMPLES:: sage: Compositions().from_subset([2,1,5,9], 12) [1, 1, 3, 4, 3] sage: Compositions().from_subset({2,1,5,9}, 12) [1, 1, 3, 4, 3] TESTS:: sage: Compositions().from_subset([2,1,5,9],9) Traceback (most recent call last): ... ValueError: S (=[1, 2, 5, 9]) is not a subset of {1, ..., 8} """ d = sorted(S) if d == []: if n == 0: return self.element_class(self, []) else: return self.element_class(self, [n]) if n <= max(d): raise ValueError, "S (=%s) is not a subset of {1, ..., %s}" % (d,n-1) elif n > max(d): d.append(n) co = [d[0]] for i in range(len(d)-1): co += [ d[i+1]-d[i] ] return self.element_class(self, co) def from_code(self, code): """ Return the composition from its code. The code of a composition is a list of length self.size() of 1s and 0s such that there is a 1 wherever a new part starts. EXAMPLES:: sage: Composition([4,1,2,3,5]).to_code() [1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0] sage: Compositions().from_code(_) [4, 1, 2, 3, 5] sage: Composition([3,1,2,3,5]).to_code() [1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0] sage: Compositions().from_code(_) [3, 1, 2, 3, 5] """ if code == [0]: return [] L = filter(lambda x: code[x]==1, range(len(code))) #the positions of the letter 1 return self.element_class(self, [L[i]-L[i-1] for i in range(1, len(L))] + [len(code)-L[-1]]) # Allows to unpickle old constrained Compositions_constraints objects. class Compositions_constraints(IntegerListsLex): class Compositions_constraints(IntegerLi """ n = data['n'] self.__class__ = IntegerListsLex constraints = { 'min_part' : 1, 'element_constructor' : Composition_class} constraints = {'min_part' : 1, 'element_constructor' : Composition} constraints.update(data['constraints']) self.__init__(n, **constraints) class Compositions_all(InfiniteAbstractCombinatorialClass): class Compositions_all(Compositions): """ Class of all compositions. """ def __init__(self): """ Initialize self. TESTS:: sage: C = Compositions() sage: TestSuite(C).run() """ Compositions.__init__(self, True) def _repr_(self): """ Parent.__init__(self, category = InfiniteEnumeratedSets()) Return a string representation of self. def __repr__(self): """ TESTS:: sage: repr(Compositions()) class Compositions_all(InfiniteAbstractC """ return "Compositions of non-negative integers" Element = Composition_class def subset(self, size=None): """ Returns the set of compositions of the given size. Return the set of compositions of the given size. EXAMPLES:: class Compositions_all(InfiniteAbstractC return self return Compositions(size) def __contains__(self, x): def __iter__(self): """ TESTS:: sage: [2,1,3] in Compositions() True sage: [] in Compositions() True sage: [-2,-1] in Compositions() False sage: [0,0] in Compositions() True """ if isinstance(x, Composition_class): return True elif isinstance(x, __builtin__.list): for i in range(len(x)): if not isinstance(x[i], (int, Integer)): return False if x[i] < 0: return False return True else: return False def _infinite_cclass_slice(self, n): """ Needed by InfiniteAbstractCombinatorialClass to build __iter__. Iterate over all compositions. TESTS:: sage: Compositions()._infinite_cclass_slice(4) == Compositions(4) True sage: it = iter(Compositions())    # indirect doctest sage: C = Compositions() sage: it = C.__iter__() sage: [it.next() for i in range(10)] [[], [1], [1, 1], [2], [1, 1, 1], [1, 2], [2, 1], [3], [1, 1, 1, 1], [1, 1, 2]] """ return Compositions_n(n) n = 0 while True: for c in Compositions(n): yield self.element_class(self, list(c)) n += 1 class Compositions_n(Compositions): """ Class of compositions of a fixed n. """ @staticmethod def __classcall_private__(cls, n): """ Standardize input to ensure a unique representation. class Compositions_n(CombinatorialClass): EXAMPLES:: sage: C = Compositions(5) sage: C2 = Compositions(int(5)) sage: C3 = Compositions(ZZ(5)) sage: C is C2 True sage: C is C3 True """ return super(Compositions_n, cls).__classcall__(cls, Integer(n)) def __init__(self, n): """ TESTS:: class Compositions_n(CombinatorialClass) sage: C = Compositions(3) sage: C == loads(dumps(C)) True sage: TestSuite(C).run() """ self.n = n Compositions.__init__(self, False) def __repr__(self): def _repr_(self): """ Return a string representation of self. TESTS:: sage: repr(Compositions(3)) class Compositions_n(CombinatorialClass) def cardinality(self): """ Return the number of compositions of n. TESTS:: sage: Compositions(3).cardinality() class Compositions_n(CombinatorialClass) else: return 0 def list(self): def __iter__(self): """ Iterate over the compositions of n. TESTS:: sage: Compositions(4).list() class Compositions_n(CombinatorialClass) [[]] """ if self.n == 0: return [Composition_class([])] yield self.element_class(self, []) return result = [] for i in range(1,self.n+1): result += map(lambda x: [i]+x[:], Compositions_n(self.n-i).list()) return [Composition_class(r) for r in result] # Those belong to the Composition class for c in Compositions_n(self.n-i): yield self.element_class(self, [i]+list(c)) def from_descents(descents, nps=None): """ Returns a composition from the list of descents. INPUT: - descents -- an iterable - nps -- (default: None) an integer or None; if None, then nps is taken to be 1 plus the maximum element of descents. r""" This has been deprecated in :trac:14063. Use :meth:Compositions.from_descents() instead. EXAMPLES:: sage: [x-1 for x in Composition([1, 1, 3, 4, 3]).to_subset()] [0, 1, 4, 8] sage: sage.combinat.composition.from_descents([1,0,4,8],12) [1, 1, 3, 4, 3] sage: sage.combinat.composition.from_descents([1,0,4,8,11]) doctest:1: DeprecationWarning: from_descents is deprecated. Use Compositions().from_descents instead. See http://trac.sagemath.org/14063 for details. [1, 1, 3, 4, 3] """ d = [x+1 for x in sorted(descents)] if nps is None: nps = d.pop() return composition_from_subset(d, nps) from sage.misc.superseded import deprecation deprecation(14063, 'from_descents is deprecated. Use Compositions().from_descents instead.') return Compositions().from_descents(descents, nps) def composition_from_subset(S, n): """ The composition of n corresponding to the subset S of \{1, 2, \dots, n-1\} under the bijection that maps the composition [i_1, i_2, \dots, i_k] of n to the subset \{i_1, i_1 + i_2, i_1 + i_2 + i_3, \dots, i_1 + \cdots + i_{k-1}\} (see :meth:to_subset). INPUT: - S -- an iterable, a subset of n-1 - n -- an integer r""" This has been deprecated in :trac:14063. Use :meth:Compositions.from_subset() instead. EXAMPLES:: sage: from sage.combinat.composition import composition_from_subset sage: composition_from_subset([2,1,5,9], 12) doctest:1: DeprecationWarning: composition_from_subset is deprecated. Use Compositions().from_subset instead. See http://trac.sagemath.org/14063 for details. [1, 1, 3, 4, 3] sage: composition_from_subset({2,1,5,9}, 12) [1, 1, 3, 4, 3] TESTS:: sage: from sage.combinat.composition import composition_from_subset sage: composition_from_subset([2,1,5,9],9) Traceback (most recent call last): ... ValueError: S (=[1, 2, 5, 9]) is not a subset of {1, ..., 8} """ d = sorted(S) if d == []: if n == 0: return Composition([]) else: return Composition([n]) if n <= max(d): raise ValueError, "S (=%s) is not a subset of {1, ..., %s}" % (d,n-1) elif n > max(d): d.append(n) co = [d[0]] for i in range(len(d)-1): co += [ d[i+1]-d[i] ] return Composition(co) from sage.misc.superseded import deprecation deprecation(14063, 'composition_from_subset is deprecated. Use Compositions().from_subset instead.') return Compositions().from_subset(S, n) def from_code(code): """ Return the composition from its code. The code of a composition is a list of length self.size() of 1s and 0s such that there is a 1 wherever a new part starts. r""" This has been deprecated in :trac:14063. Use :meth:Compositions.from_code() instead. EXAMPLES:: def from_code(code): sage: Composition([4,1,2,3,5]).to_code() [1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0] sage: composition.from_code(_) doctest:1: DeprecationWarning: from_code is deprecated. Use Compositions().from_code instead. See http://trac.sagemath.org/14063 for details. [4, 1, 2, 3, 5] sage: Composition([3,1,2,3,5]).to_code() [1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0] sage: composition.from_code(_) [3, 1, 2, 3, 5] """ if code == [0]: return [] from sage.misc.superseded import deprecation deprecation(14063, 'from_code is deprecated. Use Compositions().from_code instead.') return Compositions().from_code(code) L = filter(lambda x: code[x]==1, range(len(code))) #the positions of the letter 1 return Composition([L[i]-L[i-1] for i in range(1, len(L))] + [len(code)-L[-1]]) from sage.structure.sage_object import register_unpickle_override register_unpickle_override('sage.combinat.composition', 'Composition_class', Composition)
• ## sage/combinat/composition_signed.py

diff --git a/sage/combinat/composition_signed.py b/sage/combinat/composition_signed.py
 a Signed Compositions #                  http://www.gnu.org/licenses/ #***************************************************************************** from combinat import CombinatorialClass import composition from composition import Compositions_n, Composition import cartesian_product from sage.rings.all import binomial, Integer import __builtin__ def SignedCompositions(n): class SignedCompositions(Compositions_n): """ Returns the combinatorial class of signed compositions of n. The class of signed compositions of n. EXAMPLES:: sage: SC3 = SignedCompositions(3); SC3 Signed compositions of 3 sage: SC3.cardinality() def SignedCompositions(n): [-2, -1], [3], [-3]] TESTS:: sage: SC = SignedCompositions(3) sage: TestSuite(SC).run() """ return SignedCompositions_n(n) class SignedCompositions_n(CombinatorialClass): def __init__(self, n): """ TESTS:: sage: SC3 = SignedCompositions(3) sage: SC3 == loads(dumps(SC3)) True """ self.n = n def __repr__(self): """ TESTS:: sage: repr(SignedCompositions(3)) 'Signed compositions of 3' sage: SignedCompositions(3) Signed compositions of 3 """ return "Signed compositions of %s"%self.n def __contains__(self, x): """ TESTS:: sage: [] in SignedCompositions(0) True sage: [0] in SignedCompositions(0) class SignedCompositions_n(Combinatorial sage: [-2, 1, -3] in SignedCompositions(6) True """ if x == []: return True if isinstance(x, __builtin__.list): for i in range(len(x)): if not isinstance(x[i], (int, Integer)): if (not isinstance(x[i], (int, Integer))) and x[i] not in ZZ: return False if x[i] == 0: return False return True else: elif not isinstance(x, Composition): return False return sum([abs(i) for i in x]) == self.n def cardinality(self): """ r""" Return the number of elements in self. The number of signed compositions of n is equal to .. MATH:: \sum_{i=1}^{n+1} \binom{n-1}{i-1} 2^i TESTS:: sage: SC4 = SignedCompositions(4) sage: SC4.cardinality() == len(SC4.list()) True sage: SignedCompositions(3).cardinality() 18 """ return sum([ binomial(self.n-1, i-1)*2**(i) for i in range(1, self.n+1)]) return sum([binomial(self.n-1, i-1)*2**(i) for i in range(1, self.n+1)]) def __iter__(self): """ TESTS:: sage: SignedCompositions(0).list()   #indirect doctest [[]] sage: SignedCompositions(1).list()   #indirect doctest class SignedCompositions_n(Combinatorial sage: SignedCompositions(2).list()   #indirect doctest [[1, 1], [1, -1], [-1, 1], [-1, -1], [2], [-2]] """ for comp in composition.Compositions(self.n): for comp in Compositions_n.__iter__(self): l = len(comp) a = [[1,-1] for i in range(l)] for sign in cartesian_product.CartesianProduct(*a): yield [ sign[i]*comp[i] for i in range(l)] from sage.structure.sage_object import register_unpickle_override register_unpickle_override('sage.combinat.composition_signed', 'SignedCompositions_n', SignedCompositions)
• ## sage/combinat/ncsf_qsym/generic_basis_code.py

diff --git a/sage/combinat/ncsf_qsym/generic_basis_code.py b/sage/combinat/ncsf_qsym/generic_basis_code.py
 a AUTHORS: from sage.misc.cachefunc import cached_method from sage.categories.realizations import Category_realization_of_parent from sage.categories.modules_with_basis import ModulesWithBasis, ModuleMorphismByLinearity from sage.combinat.composition import Composition, Composition_class from sage.combinat.composition import Composition from sage.combinat.partition import Partition from sage.combinat.permutation import Permutations from sage.rings.integer import Integer class BasesOfQSymOrNCSF(Category_realiza This could possibly be shared with Sym, FQSym, and other algebras with bases indexed by list-like objects """ if isinstance(c, Composition_class): if isinstance(c, Composition): assert len(rest) == 0 else: if len(rest) > 0 or isinstance(c, (int, Integer)):
• ## sage/combinat/ncsf_qsym/qsym.py

diff --git a/sage/combinat/ncsf_qsym/qsym.py b/sage/combinat/ncsf_qsym/qsym.py
 a class QuasiSymmetricFunctions(UniqueRepr M = self.realization_of().Monomial() if J == []: return M([]) return M.sum_of_terms((I, number_of_fCT( I, J) ) for I in Compositions(J.size())) C = Compositions() C_size = Compositions(J.size()) return M.sum_of_terms((C(I), number_of_fCT(C(I), J)) for I in C_size) @cached_method def _matrix_monomial_to_dual_immaculate(self, n): class QuasiSymmetricFunctions(UniqueRepr I = N.I() S = N.S() mat = [] C = Compositions() for alp in Compositions(n): row = [] expansion = S(I(alp)) expansion = S(I(C(alp))) for bet in Compositions(n): row.append(expansion.coefficient(Composition(bet))) row.append(expansion.coefficient(C(bet))) mat.append(row) return mat class QuasiSymmetricFunctions(UniqueRepr -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(n) C = Compositions() C_n = Compositions(n) mat = self._matrix_monomial_to_dual_immaculate(n) column = C.list().index(J) return self.sum_of_terms( (I, mat[C.list().index(I)][column]) for I in Compositions(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) dI = dualImmaculate
• ## sage/combinat/necklace.py

diff --git a/sage/combinat/necklace.py b/sage/combinat/necklace.py
 a The algorithm used in this file comes fr # #                  http://www.gnu.org/licenses/ #***************************************************************************** from sage.combinat.composition import Composition, Composition_class from sage.combinat.composition import Composition from combinat import CombinatorialClass from sage.rings.arith import euler_phi,factorial, divisors, gcd from sage.rings.integer import Integer class Necklaces_evaluation(Combinatorial sage: N == loads(dumps(N)) True """ if isinstance(e, Composition_class): if isinstance(e, Composition): self.e = e else: self.e = Composition(e)
• ## sage/combinat/permutation.py

diff --git a/sage/combinat/permutation.py b/sage/combinat/permutation.py
 a from sage.rings.all import ZZ, Integer, from sage.matrix.all import matrix from sage.combinat.tools import transitive_ideal import sage.combinat.subword as subword from sage.combinat.composition import Composition, Composition_class from sage.combinat.composition import Composition, Composition import tableau import sage.combinat.partition from permutation_nk import PermutationsNK def descents_composition_first(dc): [3, 2, 1, 4, 6, 5, 7, 8, 10, 9, 11, 12] """ if not isinstance(dc, Composition_class): if not isinstance(dc, Composition): try: dc = Composition(dc) except TypeError: def descents_composition_last(dc): sage: permutation.descents_composition_last([1,1,3,4,3]) [12, 11, 8, 9, 10, 4, 5, 6, 7, 1, 2, 3] """ if not isinstance(dc, Composition_class): if not isinstance(dc, Composition): try: dc = Composition(dc) except TypeError:
• ## sage/sets/disjoint_union_enumerated_sets.py

diff --git a/sage/sets/disjoint_union_enumerated_sets.py b/sage/sets/disjoint_union_enumerated_sets.py
 a class DisjointUnionEnumeratedSets(Unique sage: U4 = DisjointUnionEnumeratedSets( ...            Family(NonNegativeIntegers(), Compositions)) sage: U4._is_a(Composition([3,2,1,1])) doctest:...: UserWarning: Disjoint union of Lazy family (Compositions(i))_{i in Non negative integers} is an infinite union doctest:...: UserWarning: Disjoint union of Lazy family ((i))_{i in Non negative integers} is an infinite union The default implementation of __contains__ can loop forever. Please overload it. True """