Ticket #14772: trac_14772-review-dg.patch

File trac_14772-review-dg.patch, 13.5 KB (added by darij, 7 years ago)

review patch. finished!

• sage/combinat/permutation.py

# HG changeset patch
# User darij grinberg <darijgrinberg@gmail.com>
# Date 1374276088 25200
# Node ID c5d98d7e87201304898f22a0dd1f21f93bd42ae0
# Parent  e6a0c6c4e3f21f38156166aab745b881267249bb
trac #14772: review patch (dg)

diff --git a/sage/combinat/permutation.py b/sage/combinat/permutation.py
 a class Permutations(Parent, UniqueReprese specify n or k along with a keyword. Permutations(descents=(list,n)) returns the class of permutations of n with descents in the positions specified by list. If n is not specified (i. e., with syntax Permutations(descents=list)), it defaults to the (arguably not very useful) value max(list) + 1. n with descents in the positions specified by list. This uses the slightly nonstandard convention that the images of 1,2,...,n under the permutation are regarded as positions 0,1,...,n-1, so for example the presence of 1 in list signifies that the permutations \pi should satisfy \pi(2) > \pi(3). Note that list is supposed to be a list of positions of the descents, not the descents composition. The alternative syntax Permutations(descents=list) is deprecated. It used to boil down Permutations(descents=(list, max(list) + 2)) (unless the list list is empty). It does *not* return the class of permutations with descents composition list. Permutations(bruhat_smaller=p) and Permutations(bruhat_greater=p) return the class of permutations smaller or greater, respectively, than class Permutations(Parent, UniqueReprese return StandardPermutations_descents(tuple(args[0]), args[1]) else: #Size not specified return StandardPermutations_descents(tuple(kwargs['descents']), max(kwargs['descents'])+1) return StandardPermutations_descents(kwargs['descents']) elif 'bruhat_smaller' in kwargs: return StandardPermutations_bruhat_smaller(Permutation(kwargs['bruhat_smaller'])) elif 'bruhat_greater' in kwargs: class Permutations_mset(Permutations): self.mset = mset Permutations.__init__(self, category=FiniteEnumeratedSets()) def __contains__(self, x): """ EXAMPLES:: sage: p = Permutations([1,2,2]) sage: [1,2,2] in p True sage: [] in p False sage: [2,2] in p False sage: [1,1] in p False sage: [2,1] in p False sage: [2,1,2] in p True """ s = list(self.mset) if len(x) != len(s): return False for i in x: if i in s: s.remove(i) else: return False return True class Element(ClonableArray): """ A permutation of an arbitrary multiset. class Permutations_mset(Permutations): sage: elt = S(['c','c','a']) sage: elt.check() """ mset = self.parent().mset for val in self: if val not in mset: raise ValueError("Invalid permutation") if self not in self.parent(): raise ValueError("Invalid permutation") def _repr_(self): """ class Permutations_mset(Permutations): c = factorial(len(lmset)) for i in d: if d[i] != 1: c /= factorial(d[i]) c //= factorial(d[i]) return ZZ(c) class Permutations_set(Permutations): """ Permutations of an arbitrary given set. Permutations of an arbitrary given finite set. Here, a "permutation of a finite set S" means a list of the elements of S in which every element of S occurs exactly once. This is not to be confused with bijections from S to S, which are also often called permutations in literature. """ @staticmethod def __classcall_private__(cls, s): class Permutations_set(Permutations): Permutations.__init__(self, category=FiniteEnumeratedSets()) self._set = s def __contains__(self, x): """ EXAMPLES:: sage: p = Permutations([4,-1,'cthulhu']) sage: [4,-1,'cthulhu'] in p True sage: [] in p False sage: [4,'cthulhu','fhtagn'] in p False sage: [4,'cthulhu',4,-1] in p False sage: [-1,'cthulhu',4] in p True """ s = list(self._set) if len(x) != len(s): return False for i in x: if i in s: s.remove(i)   # not strictly necessary since no element appears in s twice else: return False return True def _repr_(self): """ TESTS:: class Permutations_set(Permutations): sage: elt = S(['t','c','a']) sage: elt.check() """ set = self.parent()._set for val in self: if val not in set: raise ValueError("Invalid permutation") if self not in self.parent(): raise ValueError("Invalid permutation") def __iter__(self): r""" class Permutations_msetk(Permutations_ms class Permutations_setk(Permutations_set): """ Permutations of length k of an arbitrary set. Permutations of length k of an arbitrary given finite set. Here, a "permutation of length k of a finite set S" means a list of length k whose entries are pairwise distinct and all belong to S. """ @staticmethod def __classcall_private__(cls, s, k): class StandardPermutations_n(Permutation from sage.combinat.partition import Partition nu = Partition(nu) if nu.size() > self.n: raise ValueError("The size of the partition (=%s) should be lower" " than the size of the permutations(=%s)"%(nu.size,self.n)) l=[] i=0 raise ValueError("The size of the partition (=%s) should be lower or equal" " to the size of the permutations (=%s)"%(nu.size,self.n)) l = [] i = 0 for nui in nu: for j in range(nui-1): l.append(i+j+2) l.append(i+1) i+=nui for i in range(nu.size(),self.n): i += nui for i in range(nu.size(), self.n): l.append(i+1) return self.element_class(self, l) def from_inversion_vector(iv): def from_cycles(n, cycles): r""" Return the permutation corresponding to cycles. Return the permutation in the n-th symmetric group whose decomposition into disjoint cycles is cycles. This function checks that its input is correct (i.e. that the cycles are disjoint and their elements integers among 1...n). It raises an exception def from_cycles(n, cycles): sage: import sage.combinat.permutation as permutation sage: permutation.from_cycles(4, [[1,2]]) [2, 1, 3, 4] sage: permutation.from_cycles(4, [[1,2,4]]) [2, 4, 3, 1] sage: permutation.from_cycles(10, [[3,1],[4,5],[6,8,9]]) [3, 2, 1, 5, 4, 8, 7, 9, 6, 10] sage: permutation.from_cycles(10, ((2, 5), (6, 1, 3))) [3, 5, 6, 4, 2, 1, 7, 8, 9, 10] sage: permutation.from_cycles(4, []) [1, 2, 3, 4] sage: permutation.from_cycles(4, [[]]) robinson_schensted_inverse = deprecated_ def bistochastic_as_sum_of_permutations(M, check = True): r""" Return the positive sum of permutations corresponding to the bistochastic matrix. the bistochastic matrix M. A stochastic matrix is a matrix with nonnegative real entries such that the sum of the elements of any row is equal to 1. A bistochastic matrix is a def bistochastic_as_sum_of_permutations( class StandardPermutations_descents(StandardPermutations_n): """ Permutations of \{1, \ldots, n\} with a fixed set of decents. Permutations of \{1, \ldots, n\} with a fixed set of descents. """ @staticmethod def __classcall_private__(cls, d, n=None): class StandardPermutations_descents(Stan sage: P2 = Permutations(descents=((1,0,4,8),12)) sage: P1 is P2 True sage: from sage.combinat.permutation import * sage: Permutations(descents=[1,0,4,8]) doctest:...: DeprecationWarning: Permutations(descents=list) has been deprecated in favor of Permutations(descents=(list, n)) for a suitably chosen n (this function sets n = max(list) + 2, but this might not be what you want See http://trac.sagemath.org/14772 for details. Standard permutations of 10 with descents [1, 0, 4, 8] """ if n is None: n = max(d) + 1 # This if-loop allows calling Permutations(descents=list) # rather than Permutations(descents=(list, n)). In this # case, the n is set to the first integer for which # Permutations(descents=(list, n)) would be # well-defined. (Note that this only allows constructing # classes of permutations where the last possible # position for a descent is a descent!) # The syntax is deprecated since (and was broken before) # trac #14772. from sage.misc.superseded import deprecation deprecation(14772, 'Permutations(descents=list) has been ' + 'deprecated in favor of ' + 'Permutations(descents=(list, n)) for ' + 'a suitably chosen n (this function ' + 'sets n = max(list) + 2, but this might ' + 'not be what you want') if len(d) == 0: n = 0 n = max(d) + 2 return super(StandardPermutations_descents, cls).__classcall__(cls, tuple(d), n) def __init__(self, d, n): """ The class of all permutations of \{1, 2, ..., n\} with set of descents d. with set of descent positions d (where the descent positions are being counted from 0, so that i lies in this set if and only if the permutation takes a larger value at i + 1 than at i + 2). TESTS:: def descents_composition_list(dc): def descents_composition_first(dc): r""" Compute the smallest element of a descent class having a descent decomposition dc. composition dc. EXAMPLES:: def descents_composition_first(dc): def descents_composition_last(dc): r""" Return the largest element of a descent class having a descent decomposition dc. composition dc. EXAMPLES:: def from_major_code(mc, final_descent=Fa class StandardPermutations_bruhat_smaller(Permutations): r""" Permutations of \{1, \ldots, n\} that are less than or equal to a permutation p in Bruhat order. permutation p in the Bruhat order. """ @staticmethod def __classcall_private__(cls, p): class StandardPermutations_bruhat_smalle class StandardPermutations_bruhat_greater(Permutations): r""" Permutations of \{1, \ldots, n\} that are greater than or equal to a permutation p. permutation p in the Bruhat order. """ @staticmethod def __classcall_private__(cls, p): def bruhat_lequal(p1, p2): def permutohedron_lequal(p1, p2, side="right"): r""" Return True if p1 is less than p2 in the permutohedron order. Return True if p1 is less than or equal to p2 in the permutohedron order. By default, the computations are done in the right permutohedron. If you pass the option side='left', then they will be done in the class StandardPermutations_avoiding_321( """ TESTS:: sage: P = Permutations(3, avoiding=[2, 1, 3]) sage: P = Permutations(3, avoiding=[3, 2, 1]) sage: TestSuite(P).run() """ StandardPermutations_avoiding_generic.__init__(self, n, Permutation([2, 1, 3])) StandardPermutations_avoiding_generic.__init__(self, n, Permutation([3, 2, 1])) def cardinality(self): """ class StandardPermutations_avoiding_231( """ TESTS:: sage: P = Permutations(3, avoiding=[2, 1, 3]) sage: P = Permutations(3, avoiding=[2, 3, 1]) sage: TestSuite(P).run() """ StandardPermutations_avoiding_generic.__init__(self, n, Permutation([2, 1, 3])) StandardPermutations_avoiding_generic.__init__(self, n, Permutation([2, 3, 1])) def cardinality(self): """