From 47fe99c4b756b2e42d893e378e73a14fd491934e Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Wed, 30 May 2018 12:00:46 +0200 Subject: [PATCH 01/13] switch the internal representation of the blocks from Set to frozenset --- src/sage/coding/code_constructions.py | 10 +-- src/sage/combinat/dyck_word.py | 2 +- src/sage/combinat/ncsym/ncsym.py | 4 +- src/sage/combinat/partition_algebra.py | 4 +- src/sage/combinat/posets/lattices.py | 7 +- src/sage/combinat/set_partition.py | 77 ++++++++++++++----- .../groups/perm_gps/symgp_conjugacy_class.py | 5 +- 7 files changed, 75 insertions(+), 34 deletions(-) diff --git a/src/sage/coding/code_constructions.py b/src/sage/coding/code_constructions.py index 3ed942a4c04..f2789a6f935 100644 --- a/src/sage/coding/code_constructions.py +++ b/src/sage/coding/code_constructions.py @@ -110,11 +110,11 @@ def _is_a_splitting(S1, S2, n, return_automorphism=False): sage: for P in SetPartitions(6,[3,3]): ....: res,aut= _is_a_splitting(P[0],P[1],7,return_automorphism=True) ....: if res: - ....: print((aut, P[0], P[1])) - (6, {1, 2, 3}, {4, 5, 6}) - (3, {1, 2, 4}, {3, 5, 6}) - (6, {1, 3, 5}, {2, 4, 6}) - (6, {1, 4, 5}, {2, 3, 6}) + ....: print((aut, P)) + (6, {{1, 2, 3}, {4, 5, 6}}) + (3, {{1, 2, 4}, {3, 5, 6}}) + (6, {{1, 3, 5}, {2, 4, 6}}) + (6, {{1, 4, 5}, {2, 3, 6}}) We illustrate now how to find idempotents in quotient rings:: diff --git a/src/sage/combinat/dyck_word.py b/src/sage/combinat/dyck_word.py index a8400d9929c..558fcdee74f 100644 --- a/src/sage/combinat/dyck_word.py +++ b/src/sage/combinat/dyck_word.py @@ -3787,7 +3787,7 @@ def from_noncrossing_partition(self, ncp): """ l = [0] * sum(len(v) for v in ncp) for v in ncp: - l[v[-1] - 1] = len(v) + l[max(v) - 1] = len(v) res = [] for i in l: diff --git a/src/sage/combinat/ncsym/ncsym.py b/src/sage/combinat/ncsym/ncsym.py index 460bd827a0b..5c678b539c0 100644 --- a/src/sage/combinat/ncsym/ncsym.py +++ b/src/sage/combinat/ncsym/ncsym.py @@ -387,7 +387,7 @@ def lt(s, t): if s == t: return False for p in s: - if len([ z for z in list(t) if z.intersection(p) != Set([]) ]) != 1: + if len([ z for z in list(t) if len(z.intersection(p)) != 0 ]) != 1: return False return True @@ -1782,7 +1782,7 @@ def lt(s, t): if s == t: return False for p in s: - if len([ z for z in list(t) if z.intersection(p) != Set([]) ]) != 1: + if len([ z for z in list(t) if len(z.intersection(p)) != 0 ]) != 1: return False return True diff --git a/src/sage/combinat/partition_algebra.py b/src/sage/combinat/partition_algebra.py index 6d66dd70911..16d2ca06e66 100644 --- a/src/sage/combinat/partition_algebra.py +++ b/src/sage/combinat/partition_algebra.py @@ -221,12 +221,12 @@ def __iter__(self): sage: all(ak.cardinality() == len(ak.list()) for ak in aks) True """ - kp = Set([-self.k-1]) + kp = frozenset([-self.k-1]) for sp in SetPartitions_set.__iter__(self): res = [] for part in sp: if self.k+1 in part: - res.append( part + kp ) + res.append( part.union(kp) ) else: res.append(part) yield self.element_class(self, res) diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index 1fbb6b8f568..30b0bd5c1d4 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -3889,8 +3889,9 @@ def is_subdirectly_reducible(self, certificate=False): if len(A) == 1: for a in A[0]: if len(a) > 1: - return (False, (self._vertex_to_element(a[0]), - self._vertex_to_element(a[1]))) + x, y = a + return (False, (self._vertex_to_element(x), + self._vertex_to_element(y))) H_closure = H.transitive_closure() a0 = [min(v) for v in A[0]] @@ -4531,7 +4532,7 @@ def congruence(self, S): ....: 6: [8], 3: [9], 7: [10], 8: [10], 9:[10]}) sage: cong = L.congruence([[1, 2]]) sage: cong[0] - {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + frozenset({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) .. SEEALSO:: :meth:`quotient` diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 122f08cf46f..5ee31376f37 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -296,7 +296,7 @@ def __mul__(self, other): sage: def mul2(s, t): ....: temp = [ss.intersection(ts) for ss in s for ts in t] - ....: temp = filter(lambda x: x != Set([]), temp) + ....: temp = filter(lambda x: x, temp) ....: return s.__class__(s.parent(), temp) Let us check that this gives the same as ``__mul__`` on set @@ -308,8 +308,8 @@ def __mul__(self, other): """ new_composition = [] for B in self: - for C in other: - BintC = B.intersection(C) + for C in other: + BintC = [b for b in B if b in C] if BintC: new_composition.append(BintC) return SetPartition(new_composition) @@ -339,10 +339,16 @@ def sup(self, t): sage: sp1.sup(sp2) == s True """ - res = Set(list(self)) + res = list(self) for p in t: - inters = Set([x for x in list(res) if x.intersection(p) != Set([])]) - res = res.difference(inters).union(_set_union(inters)) + # find blocks in res which intersect p + inters = [(i, b) for i, b in enumerate(res) + if any(a in res[i] for a in p)] + # remove these blocks from res + for i, _ in reversed(inters): + del res[i] + # add the union + res.append([e for _, b in inters for e in b]) return self.parent()(res) def standard_form(self): @@ -429,9 +435,9 @@ def union(s): # the elements of this part of s into a single part. ret = [] for part in s: - cur = Set([]) + cur = [] for i in part: - cur = cur.union(self[i-1]) # -1 for indexing + cur.extend(self[i-1]) # -1 for indexing ret.append(cur) return ret return [self.parent()(union(s)) for s in SP] @@ -490,11 +496,7 @@ class SetPartition(AbstractSetPartition): Here is the list of them:: sage: SetPartitions(3).list() - [{{1, 2, 3}}, - {{1}, {2, 3}}, - {{1, 3}, {2}}, - {{1, 2}, {3}}, - {{1}, {2}, {3}}] + [{{1, 2, 3}}, {{1}, {2, 3}}, {{1, 3}, {2}}, {{1, 2}, {3}}, {{1}, {2}, {3}}] There are 6 set partitions of `\{1,2,3,4\}` whose underlying partition is `[2, 1, 1]`:: @@ -544,7 +546,9 @@ def __init__(self, parent, s, check=True): {} """ self._latex_options = {} - ClonableArray.__init__(self, parent, sorted(map(Set, s), key=min), check=check) + sets = map(frozenset, s) + blocks = sorted(sets, key=min) + ClonableArray.__init__(self, parent, blocks, check=check) def check(self): """ @@ -567,7 +571,7 @@ def check(self): sage: s = S([1, 2, 3]) Traceback (most recent call last): ... - TypeError: Element has no defined underlying set + TypeError: 'sage.rings.integer.Integer' object is not iterable """ if self not in self.parent(): raise ValueError("%s is not an element of %s"%(self, self.parent())) @@ -1722,7 +1726,7 @@ def is_less_than(self, s, t): return False for p in s: - x = p[0] + x = next(iter(p)) for t_ in t: if x in t_: break @@ -1817,8 +1821,16 @@ def __iter__(self): sage: it = SetPartitions().__iter__() sage: [next(it) for x in range(10)] - [{}, {{1}}, {{1, 2}}, {{1}, {2}}, {{1, 2, 3}}, {{1}, {2, 3}}, - {{1, 3}, {2}}, {{1, 2}, {3}}, {{1}, {2}, {3}}, {{1, 2, 3, 4}}] + [{}, + {{1}}, + {{1, 2}}, + {{1}, {2}}, + {{1, 2, 3}}, + {{1}, {2, 3}}, + {{1, 3}, {2}}, + {{1, 2}, {3}}, + {{1}, {2}, {3}}, + {{1, 2, 3, 4}}] """ n = 0 while True: @@ -1958,9 +1970,37 @@ def __iter__(self): sage: SetPartitions(3).list() [{{1, 2, 3}}, {{1}, {2, 3}}, {{1, 3}, {2}}, {{1, 2}, {3}}, {{1}, {2}, {3}}] """ + for p in Partitions(len(self._set)): for sp in self._iterator_part(p): yield self.element_class(self, sp) +# base_set = list(self.base_set()) +# def from_word(w): +# sp = [] +# for i, b in zip(base_set, w): +# if len(sp) <= b: +# sp.append([i]) +# else: +# sp[b].append(i) +# return self.element_class(self, sp, check=False) +# +# # Ruskey, Combinatorial Generation, Algorithm 4.22 +# +# N = len(base_set) +# a = [0]*N +# def gen(l, m): +# if l >= N: +# yield from_word(a) +# else: +# for i in range(m+1): +# a[l] = i +# for P in gen(l+1, m): +# yield P +# if m < N-1: +# a[l] = m+1 +# for P in gen(l+1, m+1): +# yield P +# return gen(1, 0) def base_set(self): """ @@ -2335,4 +2375,3 @@ def cyclic_permutations_of_set_partition_iterator(set_part): for right in cyclic_permutations_of_set_partition_iterator(set_part[1:]): for perm in CyclicPermutations(set_part[0]): yield [perm] + right - diff --git a/src/sage/groups/perm_gps/symgp_conjugacy_class.py b/src/sage/groups/perm_gps/symgp_conjugacy_class.py index 3b55bcf178b..5e28f8d77d8 100644 --- a/src/sage/groups/perm_gps/symgp_conjugacy_class.py +++ b/src/sage/groups/perm_gps/symgp_conjugacy_class.py @@ -360,8 +360,9 @@ def conjugacy_class_iterator(part, S=None): m = len(part) for s in SetPartitions(S, part): - firsts = [t[0] for t in s] - rests = [t[1:] for t in s] + blocks = map(Set, s) + firsts = [t[0] for t in blocks] + rests = [t[1:] for t in blocks] iterator = tuple(itertools.permutations(r) for r in rests) for r in itertools.product(*iterator): yield [(firsts[i],) + r[i] for i in range(m)] From 5591b40f3375a1ea6d645adfb5dcfe6cf0c87fa9 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Wed, 30 May 2018 12:09:58 +0200 Subject: [PATCH 02/13] add faster iterator --- src/sage/combinat/set_partition.py | 55 ++++++++++++++---------------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 5ee31376f37..77f94eb734d 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -1970,37 +1970,32 @@ def __iter__(self): sage: SetPartitions(3).list() [{{1, 2, 3}}, {{1}, {2, 3}}, {{1, 3}, {2}}, {{1, 2}, {3}}, {{1}, {2}, {3}}] """ + base_set = list(self.base_set()) + def from_word(w): + sp = [] + for i, b in zip(base_set, w): + if len(sp) <= b: + sp.append([i]) + else: + sp[b].append(i) + return self.element_class(self, sp, check=False) - for p in Partitions(len(self._set)): - for sp in self._iterator_part(p): - yield self.element_class(self, sp) -# base_set = list(self.base_set()) -# def from_word(w): -# sp = [] -# for i, b in zip(base_set, w): -# if len(sp) <= b: -# sp.append([i]) -# else: -# sp[b].append(i) -# return self.element_class(self, sp, check=False) -# -# # Ruskey, Combinatorial Generation, Algorithm 4.22 -# -# N = len(base_set) -# a = [0]*N -# def gen(l, m): -# if l >= N: -# yield from_word(a) -# else: -# for i in range(m+1): -# a[l] = i -# for P in gen(l+1, m): -# yield P -# if m < N-1: -# a[l] = m+1 -# for P in gen(l+1, m+1): -# yield P -# return gen(1, 0) + # Ruskey, Combinatorial Generation, Algorithm 4.22 + N = len(base_set) + a = [0]*N + def gen(l, m): + if l >= N: + yield from_word(a) + else: + for i in range(m+1): + a[l] = i + for P in gen(l+1, m): + yield P + if m < N-1: + a[l] = m+1 + for P in gen(l+1, m+1): + yield P + return gen(1, 0) def base_set(self): """ From 43be53b1dd431d86f7adb2bd73915a81393c4177 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Fri, 1 Jun 2018 09:56:16 +0200 Subject: [PATCH 03/13] alternative, non-recursive iterator --- src/sage/combinat/set_partition.py | 51 ++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 77f94eb734d..aa4c622b0f6 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -1997,6 +1997,57 @@ def gen(l, m): yield P return gen(1, 0) + def _iter_Knuth(self): + """ + Iterate over ``self``. + + EXAMPLES:: + + sage: SetPartitions(3).list() + [{{1, 2, 3}}, {{1}, {2, 3}}, {{1, 3}, {2}}, {{1, 2}, {3}}, {{1}, {2}, {3}}] + """ + base_set = list(self.base_set()) + def from_word(w): + sp = [] + for i, b in zip(base_set, w): + if len(sp) <= b: + sp.append([i]) + else: + sp[b].append(i) + return self.element_class(self, sp, check=False) + + # Knuth, TAOCP 4A 7.2.1.5, Algorithm H + N = len(base_set) + # H1: initialize + a = [0]*N + if N <= 1: + yield self.from_word(base_set, a) + return + b = [1]*N + while True: + # H2: visit + yield self.from_word(base_set, a) + if a[-1] == b[-1]: + # H4: find j + j = N-2 + while a[j] == b[j]: + j -= 1 + # H5: increase a_j + if j == 0: + break + a[j] += 1 + # H6: zero out a_{j+1},...,a_n + b[-1] = b[j] + (1 if a[j] == b[j] else 0) + j += 1 + while j < N-1: + a[j] = 0 + b[j] = b[-1] + j += 1 + a[-1] = 0 + else: + # increase a_n + a[-1] += 1 + def base_set(self): """ Return the base set of ``self``. From 7a2ba0a42dd2230f8beaa51cde386c059a5d02bc Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Fri, 1 Jun 2018 12:50:50 +0200 Subject: [PATCH 04/13] add faster iterator for set partitions with given number of blocks --- src/sage/combinat/set_partition.py | 91 +++++++++++++----------------- 1 file changed, 40 insertions(+), 51 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index aa4c622b0f6..e8e7ea63b91 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -1965,42 +1965,6 @@ def __iter__(self): """ Iterate over ``self``. - EXAMPLES:: - - sage: SetPartitions(3).list() - [{{1, 2, 3}}, {{1}, {2, 3}}, {{1, 3}, {2}}, {{1, 2}, {3}}, {{1}, {2}, {3}}] - """ - base_set = list(self.base_set()) - def from_word(w): - sp = [] - for i, b in zip(base_set, w): - if len(sp) <= b: - sp.append([i]) - else: - sp[b].append(i) - return self.element_class(self, sp, check=False) - - # Ruskey, Combinatorial Generation, Algorithm 4.22 - N = len(base_set) - a = [0]*N - def gen(l, m): - if l >= N: - yield from_word(a) - else: - for i in range(m+1): - a[l] = i - for P in gen(l+1, m): - yield P - if m < N-1: - a[l] = m+1 - for P in gen(l+1, m+1): - yield P - return gen(1, 0) - - def _iter_Knuth(self): - """ - Iterate over ``self``. - EXAMPLES:: sage: SetPartitions(3).list() @@ -2021,12 +1985,12 @@ def from_word(w): # H1: initialize a = [0]*N if N <= 1: - yield self.from_word(base_set, a) + yield from_word(a) return b = [1]*N while True: # H2: visit - yield self.from_word(base_set, a) + yield from_word(a) if a[-1] == b[-1]: # H4: find j j = N-2 @@ -2036,7 +2000,7 @@ def from_word(w): if j == 0: break a[j] += 1 - # H6: zero out a_{j+1},...,a_n + # H6: zero out a_{j+1},...,a_{n-1} b[-1] = b[j] + (1 if a[j] == b[j] else 0) j += 1 while j < N-1: @@ -2045,7 +2009,7 @@ def from_word(w): j += 1 a[-1] = 0 else: - # increase a_n + # H3: increase a_{n-1} a[-1] += 1 def base_set(self): @@ -2189,7 +2153,7 @@ def __contains__(self, x): class SetPartitions_setn(SetPartitions_set): @staticmethod - def __classcall_private__(cls, s, n): + def __classcall_private__(cls, s, k): """ Normalize ``s`` to ensure a unique representation. @@ -2201,16 +2165,16 @@ def __classcall_private__(cls, s, n): sage: S1 is S2, S1 is S3 (True, True) """ - return super(SetPartitions_setn, cls).__classcall__(cls, frozenset(s), n) + return super(SetPartitions_setn, cls).__classcall__(cls, frozenset(s), k) - def __init__(self, s, n): + def __init__(self, s, k): """ TESTS:: sage: S = SetPartitions(5, 3) sage: TestSuite(S).run() """ - self.n = n + self._k = k SetPartitions_set.__init__(self, s) def _repr_(self): @@ -2220,7 +2184,7 @@ def _repr_(self): sage: SetPartitions(5, 3) Set partitions of {1, 2, 3, 4, 5} with 3 parts """ - return "Set partitions of %s with %s parts"%(Set(self._set), self.n) + return "Set partitions of %s with %s parts"%(Set(self._set), self._k) def cardinality(self): """ @@ -2234,7 +2198,7 @@ def cardinality(self): sage: stirling_number2(5,3) 25 """ - return stirling_number2(len(self._set), self.n) + return stirling_number2(len(self._set), self._k) def __iter__(self): """ @@ -2245,9 +2209,34 @@ def __iter__(self): sage: SetPartitions(3).list() [{{1, 2, 3}}, {{1}, {2, 3}}, {{1, 3}, {2}}, {{1, 2}, {3}}, {{1}, {2}, {3}}] """ - for p in Partitions(len(self._set), length=self.n): - for sp in self._iterator_part(p): - yield self.element_class(self, sp) + base_set = list(self.base_set()) + def from_word(w): + sp = [] + for i, b in zip(base_set, w): + if len(sp) <= b: + sp.append([i]) + else: + sp[b].append(i) + return self.element_class(self, sp, check=False) + + # Ruskey, Combinatorial Generation, Algorithm 4.23 + n = len(base_set) + a = list(range(n)) + def gen(n, k): + if n == k: + yield from_word(a) + else: + for i in range(k): + a[n-1] = i + for P in gen(n-1, k): + yield P + a[n-1] = n-1 + if k > 1: + a[n-1] = k-1 + for P in gen(n-1, k-1): + yield P + a[n-1] = n-1 + return gen(n, self._k) def __contains__(self, x): """ @@ -2265,7 +2254,7 @@ def __contains__(self, x): """ if not SetPartitions_set.__contains__(self, x): return False - return len(x) == self.n + return len(x) == self._k def random_element(self): r""" @@ -2293,7 +2282,7 @@ def re(N, k): base_set = list(self.base_set()) N = len(base_set) - k = self.n + k = self._k p = re(N, k) return SetPartition([[base_set[e] for e in b] for b in p]) From d01f25dd69aa1788536c75bd6e8fa917548e075c Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Fri, 1 Jun 2018 16:28:46 +0200 Subject: [PATCH 05/13] adapt doctests --- src/sage/combinat/ncsym/ncsym.py | 6 ++--- src/sage/combinat/partition_algebra.py | 6 ++--- src/sage/combinat/set_partition.py | 31 +++++++++++++++++--------- src/sage/combinat/tutorial.py | 11 +++++---- src/sage/sandpiles/sandpile.py | 20 ++++++++--------- 5 files changed, 43 insertions(+), 31 deletions(-) diff --git a/src/sage/combinat/ncsym/ncsym.py b/src/sage/combinat/ncsym/ncsym.py index 5c678b539c0..17c1a941d6c 100644 --- a/src/sage/combinat/ncsym/ncsym.py +++ b/src/sage/combinat/ncsym/ncsym.py @@ -122,7 +122,7 @@ def nesting(la, nu): [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] - [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] @@ -387,7 +387,7 @@ def lt(s, t): if s == t: return False for p in s: - if len([ z for z in list(t) if len(z.intersection(p)) != 0 ]) != 1: + if len([z for z in t if z.intersection(p)]) != 1: return False return True @@ -1782,7 +1782,7 @@ def lt(s, t): if s == t: return False for p in s: - if len([ z for z in list(t) if len(z.intersection(p)) != 0 ]) != 1: + if len([z for z in t if z.intersection(p)]) != 1: return False return True diff --git a/src/sage/combinat/partition_algebra.py b/src/sage/combinat/partition_algebra.py index 16d2ca06e66..5bcb4d9dcdc 100644 --- a/src/sage/combinat/partition_algebra.py +++ b/src/sage/combinat/partition_algebra.py @@ -81,11 +81,11 @@ def check(self): EXAMPLES:: sage: A2p5 = SetPartitionsAk(2.5) - sage: x = A2p5.first(); x # random - {{1, 2, 3, -1, -3, -2}} + sage: x = A2p5.first(); x + {{-3, -2, -1, 1, 2, 3}} sage: x.check() sage: y = A2p5.next(x); y - {{-3, -2, -1, 2, 3}, {1}} + {{-3, -1, 1, 2, 3}, {-2}} sage: y.check() """ #Check to make sure each element of x is a set diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index e8e7ea63b91..627a7ea2bc1 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -309,7 +309,7 @@ def __mul__(self, other): new_composition = [] for B in self: for C in other: - BintC = [b for b in B if b in C] + BintC = B.intersection(C) if BintC: new_composition.append(BintC) return SetPartition(new_composition) @@ -421,9 +421,9 @@ def coarsenings(self): [{{1, 2, 3, 4}}, {{1, 3}, {2, 4}}] sage: SetPartition([[1],[2,4],[3]]).coarsenings() [{{1, 2, 3, 4}}, - {{1}, {2, 3, 4}}, - {{1, 3}, {2, 4}}, {{1, 2, 4}, {3}}, + {{1, 3}, {2, 4}}, + {{1}, {2, 3, 4}}, {{1}, {2, 4}, {3}}] sage: SetPartition([]).coarsenings() [{}] @@ -496,7 +496,7 @@ class SetPartition(AbstractSetPartition): Here is the list of them:: sage: SetPartitions(3).list() - [{{1, 2, 3}}, {{1}, {2, 3}}, {{1, 3}, {2}}, {{1, 2}, {3}}, {{1}, {2}, {3}}] + [{{1, 2, 3}}, {{1, 2}, {3}}, {{1, 3}, {2}}, {{1}, {2, 3}}, {{1}, {2}, {3}}] There are 6 set partitions of `\{1,2,3,4\}` whose underlying partition is `[2, 1, 1]`:: @@ -1826,9 +1826,9 @@ def __iter__(self): {{1, 2}}, {{1}, {2}}, {{1, 2, 3}}, - {{1}, {2, 3}}, - {{1, 3}, {2}}, {{1, 2}, {3}}, + {{1, 3}, {2}}, + {{1}, {2, 3}}, {{1}, {2}, {3}}, {{1, 2, 3, 4}}] """ @@ -1968,7 +1968,7 @@ def __iter__(self): EXAMPLES:: sage: SetPartitions(3).list() - [{{1, 2, 3}}, {{1}, {2, 3}}, {{1, 3}, {2}}, {{1, 2}, {3}}, {{1}, {2}, {3}}] + [{{1, 2, 3}}, {{1, 2}, {3}}, {{1, 3}, {2}}, {{1}, {2, 3}}, {{1}, {2}, {3}}] """ base_set = list(self.base_set()) def from_word(w): @@ -2036,8 +2036,8 @@ def base_set_cardinality(self): class SetPartitions_setparts(SetPartitions_set): r""" - Class of all set partitions with fixed partition sizes corresponding to - an integer partition `\lambda`. + Set partitions with fixed partition sizes corresponding to an + integer partition `\lambda`. """ @staticmethod def __classcall_private__(cls, s, parts): @@ -2152,6 +2152,9 @@ def __contains__(self, x): return sorted(map(len, x)) == list(reversed(self.parts)) class SetPartitions_setn(SetPartitions_set): + """ + Set partitions with a given number of blocks. + """ @staticmethod def __classcall_private__(cls, s, k): """ @@ -2206,8 +2209,14 @@ def __iter__(self): EXAMPLES:: - sage: SetPartitions(3).list() - [{{1, 2, 3}}, {{1}, {2, 3}}, {{1, 3}, {2}}, {{1, 2}, {3}}, {{1}, {2}, {3}}] + sage: SetPartitions(4, 2).list() + [{{1, 3, 4}, {2}}, + {{1, 4}, {2, 3}}, + {{1, 2, 4}, {3}}, + {{1, 3}, {2, 4}}, + {{1}, {2, 3, 4}}, + {{1, 2}, {3, 4}}, + {{1, 2, 3}, {4}}] """ base_set = list(self.base_set()) def from_word(w): diff --git a/src/sage/combinat/tutorial.py b/src/sage/combinat/tutorial.py index cf479065cfd..25d79509121 100644 --- a/src/sage/combinat/tutorial.py +++ b/src/sage/combinat/tutorial.py @@ -831,14 +831,17 @@ Set partitions:: - sage: C = SetPartitions([1,2,3]) + sage: C = SetPartitions(["a", "b", "c"]) sage: C - Set partitions of {1, 2, 3} + Set partitions of {'a', 'c', 'b'} sage: C.cardinality() 5 sage: C.list() - [{{1, 2, 3}}, {{1}, {2, 3}}, {{1, 3}, {2}}, {{1, 2}, {3}}, - {{1}, {2}, {3}}] + [{{'a', 'b', 'c'}}, + {{'a', 'c'}, {'b'}}, + {{'a', 'b'}, {'c'}}, + {{'a'}, {'b', 'c'}}, + {{'a'}, {'b'}, {'c'}}] Partial orders on a set of `8` elements, up to isomorphism:: diff --git a/src/sage/sandpiles/sandpile.py b/src/sage/sandpiles/sandpile.py index 12bf78bd440..95744ee0e23 100644 --- a/src/sage/sandpiles/sandpile.py +++ b/src/sage/sandpiles/sandpile.py @@ -6564,19 +6564,19 @@ def admissible_partitions(S, k): sage: from sage.sandpiles.sandpile import admissible_partitions sage: from sage.sandpiles.sandpile import partition_sandpile sage: S = sandpiles.Cycle(4) - sage: P = [admissible_partitions(S, i) for i in [2,3,4]] + sage: P = [set(admissible_partitions(S, i)) for i in [2,3,4]] sage: P - [[{{0}, {1, 2, 3}}, - {{0, 2, 3}, {1}}, - {{0, 1, 3}, {2}}, - {{0, 1, 2}, {3}}, + [{{{0}, {1, 2, 3}}, {{0, 1}, {2, 3}}, - {{0, 3}, {1, 2}}], - [{{0}, {1}, {2, 3}}, + {{0, 1, 2}, {3}}, + {{0, 1, 3}, {2}}, + {{0, 2, 3}, {1}}, + {{0, 3}, {1, 2}}}, + {{{0}, {1}, {2, 3}}, {{0}, {1, 2}, {3}}, - {{0, 3}, {1}, {2}}, - {{0, 1}, {2}, {3}}], - [{{0}, {1}, {2}, {3}}]] + {{0, 1}, {2}, {3}}, + {{0, 3}, {1}, {2}}}, + {{{0}, {1}, {2}, {3}}}] sage: for p in P: ....: sum([partition_sandpile(S, i).betti(verbose=False)[-1] for i in p]) 6 From eca8497a21a52fea2b29e1a7eac947ea9e6f0654 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Fri, 1 Jun 2018 21:51:31 +0200 Subject: [PATCH 06/13] fix more doctests --- src/sage/combinat/posets/lattices.py | 2 +- src/sage/combinat/tableau.py | 10 ++++++---- src/sage/tests/finite_poset.py | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index 30b0bd5c1d4..077ed3b6bbc 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -3889,7 +3889,7 @@ def is_subdirectly_reducible(self, certificate=False): if len(A) == 1: for a in A[0]: if len(a) > 1: - x, y = a + x, y = min(a), max(a) return (False, (self._vertex_to_element(x), self._vertex_to_element(y))) diff --git a/src/sage/combinat/tableau.py b/src/sage/combinat/tableau.py index c66ef0234a9..c78124a1c4f 100644 --- a/src/sage/combinat/tableau.py +++ b/src/sage/combinat/tableau.py @@ -7429,8 +7429,8 @@ def random_element(self): EXAMPLES:: - sage: StandardTableaux(5).random_element() # random - [[1, 4, 5], [2], [3]] + sage: StandardTableaux(10).random_element() # random + [[1, 3, 6], [2, 5, 7], [4, 8], [9], [10]] sage: StandardTableaux(0).random_element() [] sage: StandardTableaux(1).random_element() @@ -7470,8 +7470,10 @@ def random_element(self): # singletons (corresponding to the fixed points of the # involution) and pairs (forming a perfect matching on the # remaining values). - permutation_cycle_rep = [(fixed_point,) for fixed_point in fixed_point_positions] + \ - list(PerfectMatchings(set(range(1, self.size + 1)) - set(fixed_point_positions)).random_element()) + matching = PerfectMatchings(set(range(1, self.size + 1)) + - set(fixed_point_positions)).random_element() + permutation_cycle_rep = ([(fixed_point,) for fixed_point in fixed_point_positions] + + [(a,b) for a,b in matching]) return from_cycles(self.size, permutation_cycle_rep).robinson_schensted()[0] diff --git a/src/sage/tests/finite_poset.py b/src/sage/tests/finite_poset.py index 6036901b1f1..48b59315614 100644 --- a/src/sage/tests/finite_poset.py +++ b/src/sage/tests/finite_poset.py @@ -309,7 +309,7 @@ def test_finite_lattice(L): c = L.is_regular(certificate=True)[1] if len(c[0]) == 1: raise ValueError("certificate error 1 in is_regular") - if Set(c[1]) not in c[0]: + if set(c[1]) not in c[0]: raise ValueError("certificate error 2 in is_regular") if L.congruence([c[1]]) == c[0]: raise ValueError("certificate error 3 in is_regular") From c27c580f7d1f9028e89f692b6cb7e97d42138724 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Sat, 2 Jun 2018 17:29:58 +0200 Subject: [PATCH 07/13] remove an expensive call to Set, adapt some doctests --- src/sage/combinat/set_partition.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 627a7ea2bc1..eb8197a02e6 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -296,7 +296,7 @@ def __mul__(self, other): sage: def mul2(s, t): ....: temp = [ss.intersection(ts) for ss in s for ts in t] - ....: temp = filter(lambda x: x, temp) + ....: temp = filter(bool, temp) ....: return s.__class__(s.parent(), temp) Let us check that this gives the same as ``__mul__`` on set @@ -342,13 +342,13 @@ def sup(self, t): res = list(self) for p in t: # find blocks in res which intersect p - inters = [(i, b) for i, b in enumerate(res) - if any(a in res[i] for a in p)] + inters = [(i, q) for i, q in enumerate(res) + if any(a in q for a in p)] # remove these blocks from res for i, _ in reversed(inters): del res[i] # add the union - res.append([e for _, b in inters for e in b]) + res.append([e for _, q in inters for e in q]) return self.parent()(res) def standard_form(self): @@ -452,10 +452,10 @@ def max_block_size(self): sage: pd = PartitionDiagram([[1,-3,-5],[2,4],[3,-1,-2],[5],[-4]]) sage: pd.max_block_size() 3 - sage: [d.max_block_size() for d in PartitionDiagrams(2)] - [4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1] - sage: [sp.max_block_size() for sp in SetPartitions(3)] - [3, 2, 2, 2, 1] + sage: sorted(d.max_block_size() for d in PartitionDiagrams(2)) + [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4] + sage: sorted(sp.max_block_size() for sp in SetPartitions(3)) + [1, 2, 2, 2, 3] """ return max(len(block) for block in self) @@ -1614,7 +1614,7 @@ def __contains__(self, x): return False # Check that all parts are disjoint - base_set = Set([e for p in x for e in p]) + base_set = set([e for p in x for e in p]) if len(base_set) != sum(map(len, x)): return False From 4ca5dfde0c7b3f6095d59a38af050a76beb7dfc3 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Sat, 2 Jun 2018 17:31:09 +0200 Subject: [PATCH 08/13] revert a call to Set which works after #25496 --- src/sage/tests/finite_poset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/tests/finite_poset.py b/src/sage/tests/finite_poset.py index 48b59315614..6036901b1f1 100644 --- a/src/sage/tests/finite_poset.py +++ b/src/sage/tests/finite_poset.py @@ -309,7 +309,7 @@ def test_finite_lattice(L): c = L.is_regular(certificate=True)[1] if len(c[0]) == 1: raise ValueError("certificate error 1 in is_regular") - if set(c[1]) not in c[0]: + if Set(c[1]) not in c[0]: raise ValueError("certificate error 2 in is_regular") if L.congruence([c[1]]) == c[0]: raise ValueError("certificate error 3 in is_regular") From 75a30435cc07e7414e096e88c14c5af2934a4690 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Sat, 2 Jun 2018 17:32:00 +0200 Subject: [PATCH 09/13] use the fast iterators and correct check --- src/sage/combinat/diagram_algebras.py | 29 +++++++++++++-------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/sage/combinat/diagram_algebras.py b/src/sage/combinat/diagram_algebras.py index 783019e569d..260ab2424ae 100644 --- a/src/sage/combinat/diagram_algebras.py +++ b/src/sage/combinat/diagram_algebras.py @@ -77,20 +77,12 @@ def partition_diagrams(k): """ if k in ZZ: S = SetPartitions(list(range(1, k+1)) + list(range(-k,0))) - for p in Partitions(2*k): - for i in S._iterator_part(p): - yield i elif k + ZZ(1)/ZZ(2) in ZZ: # Else k in 1/2 ZZ k = ZZ(k + ZZ(1) / ZZ(2)) S = SetPartitions(list(range(1, k+1)) + list(range(-k+1,0))) - for p in Partitions(2*k-1): - for sp in S._iterator_part(p): - sp = list(sp) - for i in range(len(sp)): - if k in sp[i]: - sp[i] += Set([-k]) - break - yield sp + else: + raise ValueError("argument %s must be a half-integer"%k) + return S def brauer_diagrams(k): r""" @@ -262,17 +254,25 @@ def check(self): Traceback (most recent call last): ... ValueError: {{-1}, {1}} does not represent two rows of vertices of order 2 + + sage: pd2 = da.AbstractPartitionDiagram(pd, [[[1,2],[-1,-2]]]) # indirect doctest + Traceback (most recent call last): + ... + ValueError: {{[-1, -2], [1, 2]}} does not represent two rows of vertices of order 2 """ if self._base_diagram: - tst = frozenset(flatten(self._base_diagram)) - if tst != self.parent()._set: + try: + tst = frozenset(e for B in self._base_diagram for e in B) + if tst != self.parent()._set: + raise TypeError + except TypeError: raise ValueError("{} does not represent two rows of vertices of order {}".format( self, self.parent().order)) def __hash__(self): """ Return the hash of ``self``. - + TESTS:: sage: import sage.combinat.diagram_algebras as da @@ -3888,4 +3888,3 @@ def set_partition_composition(sp1, sp2): ########################################################################## # END BORROWED CODE ########################################################################## - From a7be1effe7a106c409958801c5d7875f353bf1e7 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Sat, 23 Jun 2018 00:12:10 +0200 Subject: [PATCH 10/13] fix (and partially improve) tests in diagram algebras --- src/sage/combinat/diagram_algebras.py | 308 +++++++++++++++----------- 1 file changed, 183 insertions(+), 125 deletions(-) diff --git a/src/sage/combinat/diagram_algebras.py b/src/sage/combinat/diagram_algebras.py index 260ab2424ae..4a6fd5e3076 100644 --- a/src/sage/combinat/diagram_algebras.py +++ b/src/sage/combinat/diagram_algebras.py @@ -65,21 +65,35 @@ def partition_diagrams(k): EXAMPLES:: sage: import sage.combinat.diagram_algebras as da - sage: [SetPartition(p) for p in da.partition_diagrams(2)] - [{{-2, -1, 1, 2}}, {{-2, -1, 2}, {1}}, {{-2, -1, 1}, {2}}, - {{-2, 1, 2}, {-1}}, {{-2}, {-1, 1, 2}}, {{-2, 1}, {-1, 2}}, - {{-2, 2}, {-1, 1}}, {{-2, -1}, {1, 2}}, {{-2, -1}, {1}, {2}}, - {{-2, 2}, {-1}, {1}}, {{-2}, {-1, 2}, {1}}, {{-2, 1}, {-1}, {2}}, - {{-2}, {-1, 1}, {2}}, {{-2}, {-1}, {1, 2}}, {{-2}, {-1}, {1}, {2}}] + sage: [p for p in da.partition_diagrams(2)] + [{{-2, -1, 1, 2}}, + {{-2, 1, 2}, {-1}}, + {{-2}, {-1, 1, 2}}, + {{-2, -1}, {1, 2}}, + {{-2}, {-1}, {1, 2}}, + {{-2, -1, 1}, {2}}, + {{-2, 1}, {-1, 2}}, + {{-2, 1}, {-1}, {2}}, + {{-2, 2}, {-1, 1}}, + {{-2, -1, 2}, {1}}, + {{-2, 2}, {-1}, {1}}, + {{-2}, {-1, 1}, {2}}, + {{-2}, {-1, 2}, {1}}, + {{-2, -1}, {1}, {2}}, + {{-2}, {-1}, {1}, {2}}] sage: [SetPartition(p) for p in da.partition_diagrams(3/2)] - [{{-2, -1, 1, 2}}, {{-2, -1, 2}, {1}}, {{-2, 2}, {-1, 1}}, - {{-2, 1, 2}, {-1}}, {{-2, 2}, {-1}, {1}}] + [{{-2, -1, 1, 2}}, + {{-2, 1, 2}, {-1}}, + {{-2, 2}, {-1, 1}}, + {{-2, -1, 2}, {1}}, + {{-2, 2}, {-1}, {1}}] """ if k in ZZ: S = SetPartitions(list(range(1, k+1)) + list(range(-k,0))) elif k + ZZ(1)/ZZ(2) in ZZ: # Else k in 1/2 ZZ k = ZZ(k + ZZ(1) / ZZ(2)) S = SetPartitions(list(range(1, k+1)) + list(range(-k+1,0))) + S = map(lambda p: [b.union([-k]) if k in b else b for b in p], S) else: raise ValueError("argument %s must be a half-integer"%k) return S @@ -146,17 +160,22 @@ def planar_diagrams(k): EXAMPLES:: sage: import sage.combinat.diagram_algebras as da - sage: [SetPartition(p) for p in da.planar_diagrams(2)] - [{{-2, -1, 1, 2}}, {{-2, -1, 2}, {1}}, - {{-2, -1, 1}, {2}}, {{-2, 1, 2}, {-1}}, - {{-2}, {-1, 1, 2}}, {{-2, 2}, {-1, 1}}, - {{-2, -1}, {1, 2}}, {{-2, -1}, {1}, {2}}, - {{-2, 2}, {-1}, {1}}, {{-2}, {-1, 2}, {1}}, - {{-2, 1}, {-1}, {2}}, {{-2}, {-1, 1}, {2}}, - {{-2}, {-1}, {1, 2}}, {{-2}, {-1}, {1}, {2}}] - sage: [SetPartition(p) for p in da.planar_diagrams(3/2)] - [{{-2, -1, 1, 2}}, {{-2, -1, 2}, {1}}, {{-2, 2}, {-1, 1}}, - {{-2, 1, 2}, {-1}}, {{-2, 2}, {-1}, {1}}] + sage: all_diagrams = da.partition_diagrams(2) + sage: [p for p in all_diagrams if p not in da.planar_diagrams(2)] + [{{-2, 1}, {-1, 2}}] + sage: all_diagrams = da.partition_diagrams(5/2) + sage: [SetPartition(p) for p in all_diagrams if p not in da.planar_diagrams(5/2)] + [{{-3, -1, 3}, {-2, 1, 2}}, + {{-3, -2, 1, 3}, {-1, 2}}, + {{-3, -1, 1, 3}, {-2, 2}}, + {{-3, 1, 3}, {-2, -1, 2}}, + {{-3, 1, 3}, {-2, 2}, {-1}}, + {{-3, 1, 3}, {-2}, {-1, 2}}, + {{-3, -1, 2, 3}, {-2, 1}}, + {{-3, 3}, {-2, 1}, {-1, 2}}, + {{-3, -1, 3}, {-2, 1}, {2}}, + {{-3, -1, 3}, {-2, 2}, {1}}] + """ for i in partition_diagrams(k): if is_planar(i): @@ -172,15 +191,13 @@ def ideal_diagrams(k): EXAMPLES:: sage: import sage.combinat.diagram_algebras as da - sage: [SetPartition(p) for p in da.ideal_diagrams(2)] - [{{-2, -1, 1, 2}}, {{-2, -1, 2}, {1}}, {{-2, -1, 1}, {2}}, - {{-2, 1, 2}, {-1}}, {{-2}, {-1, 1, 2}}, {{-2, -1}, {1, 2}}, - {{-2, -1}, {1}, {2}}, {{-2, 2}, {-1}, {1}}, {{-2}, {-1, 2}, {1}}, - {{-2, 1}, {-1}, {2}}, {{-2}, {-1, 1}, {2}}, {{-2}, {-1}, {1, 2}}, - {{-2}, {-1}, {1}, {2}}] - sage: [SetPartition(p) for p in da.ideal_diagrams(3/2)] - [{{-2, -1, 1, 2}}, {{-2, -1, 2}, {1}}, - {{-2, 1, 2}, {-1}}, {{-2, 2}, {-1}, {1}}] + sage: all_diagrams = da.partition_diagrams(2) + sage: [SetPartition(p) for p in all_diagrams if p not in da.ideal_diagrams(2)] + [{{-2, 1}, {-1, 2}}, {{-2, 2}, {-1, 1}}] + + sage: all_diagrams = da.partition_diagrams(3/2) + sage: [SetPartition(p) for p in all_diagrams if p not in da.ideal_diagrams(3/2)] + [{{-2, 2}, {-1, 1}}] """ for i in partition_diagrams(k): if propagating_number(i) < k: @@ -501,15 +518,22 @@ class IdealDiagram(AbstractPartitionDiagram): sage: IDs(2) Ideal diagrams of order 2 sage: IDs(2).list() - [{{-2, -1, 1, 2}}, {{-2, -1, 2}, {1}}, - {{-2, -1, 1}, {2}}, {{-2, 1, 2}, {-1}}, - {{-2}, {-1, 1, 2}}, {{-2, -1}, {1, 2}}, - {{-2, -1}, {1}, {2}}, {{-2, 2}, {-1}, {1}}, - {{-2}, {-1, 2}, {1}}, {{-2, 1}, {-1}, {2}}, - {{-2}, {-1, 1}, {2}}, {{-2}, {-1}, {1, 2}}, + [{{-2, -1, 1, 2}}, + {{-2, 1, 2}, {-1}}, + {{-2}, {-1, 1, 2}}, + {{-2, -1}, {1, 2}}, + {{-2}, {-1}, {1, 2}}, + {{-2, -1, 1}, {2}}, + {{-2, 1}, {-1}, {2}}, + {{-2, -1, 2}, {1}}, + {{-2, 2}, {-1}, {1}}, + {{-2}, {-1, 1}, {2}}, + {{-2}, {-1, 2}, {1}}, + {{-2, -1}, {1}, {2}}, {{-2}, {-1}, {1}, {2}}] + sage: from sage.combinat.diagram_algebras import PartitionDiagrams as PDs - sage: PDs(4).cardinality() == factorial(4) + IDs(4).cardinality() # long time + sage: PDs(4).cardinality() == factorial(4) + IDs(4).cardinality() True """ @staticmethod @@ -566,13 +590,20 @@ class PlanarDiagram(AbstractPartitionDiagram): sage: PlanarDiagrams(2) Planar diagrams of order 2 sage: PlanarDiagrams(2).list() - [{{-2, -1, 1, 2}}, {{-2, -1, 2}, {1}}, - {{-2, -1, 1}, {2}}, {{-2, 1, 2}, {-1}}, - {{-2}, {-1, 1, 2}}, {{-2, 2}, {-1, 1}}, - {{-2, -1}, {1, 2}}, {{-2, -1}, {1}, {2}}, - {{-2, 2}, {-1}, {1}}, {{-2}, {-1, 2}, {1}}, - {{-2, 1}, {-1}, {2}}, {{-2}, {-1, 1}, {2}}, - {{-2}, {-1}, {1, 2}}, {{-2}, {-1}, {1}, {2}}] + [{{-2, -1, 1, 2}}, + {{-2, 1, 2}, {-1}}, + {{-2}, {-1, 1, 2}}, + {{-2, -1}, {1, 2}}, + {{-2}, {-1}, {1, 2}}, + {{-2, -1, 1}, {2}}, + {{-2, 1}, {-1}, {2}}, + {{-2, 2}, {-1, 1}}, + {{-2, -1, 2}, {1}}, + {{-2, 2}, {-1}, {1}}, + {{-2}, {-1, 1}, {2}}, + {{-2}, {-1, 2}, {1}}, + {{-2, -1}, {1}, {2}}, + {{-2}, {-1}, {1}, {2}}] """ @staticmethod def __classcall_private__(cls, diag): @@ -1056,19 +1087,19 @@ def __init__(self, order, category=None): Category of finite sets sage: pd = da.PartitionDiagrams(2) - sage: TestSuite(pd).run() # long time + sage: TestSuite(pd).run() sage: bd = da.BrauerDiagrams(2) - sage: TestSuite(bd).run() # long time + sage: TestSuite(bd).run() sage: td = da.TemperleyLiebDiagrams(2) - sage: TestSuite(td).run() # long time + sage: TestSuite(td).run() sage: pld = da.PlanarDiagrams(2) - sage: TestSuite(pld).run() # long time + sage: TestSuite(pld).run() sage: id = da.IdealDiagrams(2) - sage: TestSuite(id).run() # long time + sage: TestSuite(id).run() """ if category is None: category = FiniteEnumeratedSets() @@ -1097,22 +1128,28 @@ def __iter__(self): TESTS:: sage: import sage.combinat.diagram_algebras as da - sage: pd = da.PartitionDiagrams(2) sage: list(da.PartitionDiagrams(2)) - [{{-2, -1, 1, 2}}, {{-2, -1, 2}, {1}}, - {{-2, -1, 1}, {2}}, {{-2, 1, 2}, {-1}}, - {{-2}, {-1, 1, 2}}, {{-2, 1}, {-1, 2}}, - {{-2, 2}, {-1, 1}}, {{-2, -1}, {1, 2}}, - {{-2, -1}, {1}, {2}}, {{-2, 2}, {-1}, {1}}, - {{-2}, {-1, 2}, {1}}, {{-2, 1}, {-1}, {2}}, - {{-2}, {-1, 1}, {2}}, {{-2}, {-1}, {1, 2}}, + [{{-2, -1, 1, 2}}, + {{-2, 1, 2}, {-1}}, + {{-2}, {-1, 1, 2}}, + {{-2, -1}, {1, 2}}, + {{-2}, {-1}, {1, 2}}, + {{-2, -1, 1}, {2}}, + {{-2, 1}, {-1, 2}}, + {{-2, 1}, {-1}, {2}}, + {{-2, 2}, {-1, 1}}, + {{-2, -1, 2}, {1}}, + {{-2, 2}, {-1}, {1}}, + {{-2}, {-1, 1}, {2}}, + {{-2}, {-1, 2}, {1}}, + {{-2, -1}, {1}, {2}}, {{-2}, {-1}, {1}, {2}}] sage: list(da.PartitionDiagrams(3/2)) [{{-2, -1, 1, 2}}, - {{-2, -1, 2}, {1}}, - {{-2, 2}, {-1, 1}}, {{-2, 1, 2}, {-1}}, + {{-2, 2}, {-1, 1}}, + {{-2, -1, 2}, {1}}, {{-2, 2}, {-1}, {1}}] sage: list(da.BrauerDiagrams(5/2)) @@ -1129,31 +1166,45 @@ def __iter__(self): sage: list(da.PlanarDiagrams(3/2)) [{{-2, -1, 1, 2}}, - {{-2, -1, 2}, {1}}, - {{-2, 2}, {-1, 1}}, {{-2, 1, 2}, {-1}}, + {{-2, 2}, {-1, 1}}, + {{-2, -1, 2}, {1}}, {{-2, 2}, {-1}, {1}}] + sage: list(da.PlanarDiagrams(2)) - [{{-2, -1, 1, 2}}, {{-2, -1, 2}, {1}}, - {{-2, -1, 1}, {2}}, {{-2, 1, 2}, {-1}}, - {{-2}, {-1, 1, 2}}, {{-2, 2}, {-1, 1}}, - {{-2, -1}, {1, 2}}, {{-2, -1}, {1}, {2}}, - {{-2, 2}, {-1}, {1}}, {{-2}, {-1, 2}, {1}}, - {{-2, 1}, {-1}, {2}}, {{-2}, {-1, 1}, {2}}, - {{-2}, {-1}, {1, 2}}, {{-2}, {-1}, {1}, {2}}] + [{{-2, -1, 1, 2}}, + {{-2, 1, 2}, {-1}}, + {{-2}, {-1, 1, 2}}, + {{-2, -1}, {1, 2}}, + {{-2}, {-1}, {1, 2}}, + {{-2, -1, 1}, {2}}, + {{-2, 1}, {-1}, {2}}, + {{-2, 2}, {-1, 1}}, + {{-2, -1, 2}, {1}}, + {{-2, 2}, {-1}, {1}}, + {{-2}, {-1, 1}, {2}}, + {{-2}, {-1, 2}, {1}}, + {{-2, -1}, {1}, {2}}, + {{-2}, {-1}, {1}, {2}}] sage: list(da.IdealDiagrams(3/2)) [{{-2, -1, 1, 2}}, - {{-2, -1, 2}, {1}}, - {{-2, 1, 2}, {-1}}, - {{-2, 2}, {-1}, {1}}] + {{-2, 1, 2}, {-1}}, + {{-2, -1, 2}, {1}}, + {{-2, 2}, {-1}, {1}}] sage: list(da.IdealDiagrams(2)) - [{{-2, -1, 1, 2}}, {{-2, -1, 2}, {1}}, - {{-2, -1, 1}, {2}}, {{-2, 1, 2}, {-1}}, - {{-2}, {-1, 1, 2}}, {{-2, -1}, {1, 2}}, - {{-2, -1}, {1}, {2}}, {{-2, 2}, {-1}, {1}}, - {{-2}, {-1, 2}, {1}}, {{-2, 1}, {-1}, {2}}, - {{-2}, {-1, 1}, {2}}, {{-2}, {-1}, {1, 2}}, + [{{-2, -1, 1, 2}}, + {{-2, 1, 2}, {-1}}, + {{-2}, {-1, 1, 2}}, + {{-2, -1}, {1, 2}}, + {{-2}, {-1}, {1, 2}}, + {{-2, -1, 1}, {2}}, + {{-2, 1}, {-1}, {2}}, + {{-2, -1, 2}, {1}}, + {{-2, 2}, {-1}, {1}}, + {{-2}, {-1, 1}, {2}}, + {{-2}, {-1, 2}, {1}}, + {{-2, -1}, {1}, {2}}, {{-2}, {-1}, {1}, {2}}] """ # The _diagram_func gets set as a method, but we want to @@ -1544,8 +1595,8 @@ class IdealDiagrams(AbstractPartitionDiagrams): True sage: da.IdealDiagrams(3/2).list() [{{-2, -1, 1, 2}}, - {{-2, -1, 2}, {1}}, {{-2, 1, 2}, {-1}}, + {{-2, -1, 2}, {1}}, {{-2, 2}, {-1}, {1}}] """ Element = IdealDiagram @@ -1585,13 +1636,20 @@ class DiagramAlgebra(CombinatorialFreeModule): sage: R. = QQ[] sage: D = da.DiagramAlgebra(2, x, R, 'P', da.PartitionDiagrams(2)) sage: list(D.basis()) - [P{{-2, -1, 1, 2}}, P{{-2, -1, 2}, {1}}, - P{{-2, -1, 1}, {2}}, P{{-2, 1, 2}, {-1}}, - P{{-2}, {-1, 1, 2}}, P{{-2, 1}, {-1, 2}}, - P{{-2, 2}, {-1, 1}}, P{{-2, -1}, {1, 2}}, - P{{-2, -1}, {1}, {2}}, P{{-2, 2}, {-1}, {1}}, - P{{-2}, {-1, 2}, {1}}, P{{-2, 1}, {-1}, {2}}, - P{{-2}, {-1, 1}, {2}}, P{{-2}, {-1}, {1, 2}}, + [P{{-2, -1, 1, 2}}, + P{{-2, 1, 2}, {-1}}, + P{{-2}, {-1, 1, 2}}, + P{{-2, -1}, {1, 2}}, + P{{-2}, {-1}, {1, 2}}, + P{{-2, -1, 1}, {2}}, + P{{-2, 1}, {-1, 2}}, + P{{-2, 1}, {-1}, {2}}, + P{{-2, 2}, {-1, 1}}, + P{{-2, -1, 2}, {1}}, + P{{-2, 2}, {-1}, {1}}, + P{{-2}, {-1, 1}, {2}}, + P{{-2}, {-1, 2}, {1}}, + P{{-2, -1}, {1}, {2}}, P{{-2}, {-1}, {1}, {2}}] """ def __init__(self, k, q, base_ring, prefix, diagrams, category=None): @@ -2073,13 +2131,20 @@ class PartitionAlgebra(DiagramBasis, UnitDiagramMixin): sage: P.basis().keys()([[-2, 1, 2], [-1]]) {{-2, 1, 2}, {-1}} sage: P.basis().list() - [P{{-2, -1, 1, 2}}, P{{-2, -1, 2}, {1}}, - P{{-2, -1, 1}, {2}}, P{{-2, 1, 2}, {-1}}, - P{{-2}, {-1, 1, 2}}, P{{-2, 1}, {-1, 2}}, - P{{-2, 2}, {-1, 1}}, P{{-2, -1}, {1, 2}}, - P{{-2, -1}, {1}, {2}}, P{{-2, 2}, {-1}, {1}}, - P{{-2}, {-1, 2}, {1}}, P{{-2, 1}, {-1}, {2}}, - P{{-2}, {-1, 1}, {2}}, P{{-2}, {-1}, {1, 2}}, + [P{{-2, -1, 1, 2}}, + P{{-2, 1, 2}, {-1}}, + P{{-2}, {-1, 1, 2}}, + P{{-2, -1}, {1, 2}}, + P{{-2}, {-1}, {1, 2}}, + P{{-2, -1, 1}, {2}}, + P{{-2, 1}, {-1, 2}}, + P{{-2, 1}, {-1}, {2}}, + P{{-2, 2}, {-1, 1}}, + P{{-2, -1, 2}, {1}}, + P{{-2, 2}, {-1}, {1}}, + P{{-2}, {-1, 1}, {2}}, + P{{-2}, {-1, 2}, {1}}, + P{{-2, -1}, {1}, {2}}, P{{-2}, {-1}, {1}, {2}}] sage: E = P([[1,2],[-2,-1]]); E P{{-2, -1}, {1, 2}} @@ -2246,15 +2311,13 @@ def _element_constructor_(self, x): sage: B = BrauerAlgebra(3, x, R) sage: O = A.orbit_basis() sage: O2.an_element() - 3*O{{-2, -1, 1}, {2}} + 2*O{{-2, -1, 1, 2}} + 2*O{{-2, -1, 2}, {1}} + 3*O{{-2}, {-1, 1, 2}} + 2*O{{-2, -1, 1, 2}} + 2*O{{-2, 1, 2}, {-1}} sage: A(O2.an_element()) - 3*P{{-3, 3}, {-2, -1, 1}, {2}} - 3*P{{-3, 3}, {-2, -1, 1, 2}} - + 2*P{{-3, 3}, {-2, -1, 2}, {1}} + 3*P{{-3, 3}, {-2}, {-1, 1, 2}} - 3*P{{-3, 3}, {-2, -1, 1, 2}} + 2*P{{-3, 3}, {-2, 1, 2}, {-1}} sage: A2.an_element() - 3*P{{-2, -1, 1}, {2}} + 2*P{{-2, -1, 1, 2}} + 2*P{{-2, -1, 2}, {1}} + 3*P{{-2}, {-1, 1, 2}} + 2*P{{-2, -1, 1, 2}} + 2*P{{-2, 1, 2}, {-1}} sage: A(A2.an_element()) - 3*P{{-3, 3}, {-2, -1, 1}, {2}} + 2*P{{-3, 3}, {-2, -1, 1, 2}} - + 2*P{{-3, 3}, {-2, -1, 2}, {1}} + 3*P{{-3, 3}, {-2}, {-1, 1, 2}} + 2*P{{-3, 3}, {-2, -1, 1, 2}} + 2*P{{-3, 3}, {-2, 1, 2}, {-1}} sage: S.an_element() [1, 2, 3] + 2*[1, 3, 2] + 3*[2, 1, 3] + [3, 1, 2] sage: A(S.an_element()) @@ -2267,11 +2330,9 @@ def _element_constructor_(self, x): 3*P{{-3, 1}, {-2, -1}, {2, 3}} + 2*P{{-3, 1}, {-2, 2}, {-1, 3}} + 2*P{{-3, 1}, {-2, 3}, {-1, 2}} sage: O.an_element() - 2*O{{-3, -2, -1, 1, 2, 3}} + 3*O{{-3, -2, -1, 1, 3}, {2}} - + 2*O{{-3, -2, -1, 2, 3}, {1}} + 3*O{{-3}, {-2, -1, 1, 2, 3}} + 2*O{{-3, -2, -1, 1, 2, 3}} + 2*O{{-3, -1, 1, 2, 3}, {-2}} sage: A(O.an_element()) - -3*P{{-3, -2, -1, 1, 2, 3}} + 3*P{{-3, -2, -1, 1, 3}, {2}} - + 2*P{{-3, -2, -1, 2, 3}, {1}} + 3*P{{-3}, {-2, -1, 1, 2, 3}} - 3*P{{-3, -2, -1, 1, 2, 3}} + 2*P{{-3, -1, 1, 2, 3}, {-2}} sage: A([]) P{{-3, 3}, {-2, 2}, {-1, 1}} sage: A(4) @@ -2398,12 +2459,9 @@ def _coerce_map_from_(self, R): TESTS:: sage: elt = O3.an_element(); elt - 2*O{{-3, -2, -1, 1, 2, 3}} + 3*O{{-3, -2, -1, 1, 3}, {2}} - + 2*O{{-3, -2, -1, 2, 3}, {1}} + 3*O{{-3}, {-2, -1, 1, 2, 3}} + 2*O{{-3, -2, -1, 1, 2, 3}} + 2*O{{-3, -1, 1, 2, 3}, {-2}} sage: A._coerce_map_from_(O3)(elt) - -3*P{{-4, 4}, {-3, -2, -1, 1, 2, 3}} - + 3*P{{-4, 4}, {-3, -2, -1, 1, 3}, {2}} - + 2*P{{-4, 4}, {-3, -2, -1, 2, 3}, {1}} + 3*P{{-4, 4}, {-3}, {-2, -1, 1, 2, 3}} - 3*P{{-4, 4}, {-3, -2, -1, 1, 2, 3}} + 2*P{{-4, 4}, {-3, -1, 1, 2, 3}, {-2}} """ # coerce from Orbit basis. if isinstance(R, OrbitBasis): @@ -2480,9 +2538,9 @@ def to_orbit_basis(self): sage: R. = QQ[] sage: P = PartitionAlgebra(2, x, R) sage: pp = P.an_element(); pp - 3*P{{-2, -1, 1}, {2}} + 2*P{{-2, -1, 1, 2}} + 2*P{{-2, -1, 2}, {1}} + 3*P{{-2}, {-1, 1, 2}} + 2*P{{-2, -1, 1, 2}} + 2*P{{-2, 1, 2}, {-1}} sage: pp.to_orbit_basis() - 3*O{{-2, -1, 1}, {2}} + 7*O{{-2, -1, 1, 2}} + 2*O{{-2, -1, 2}, {1}} + 3*O{{-2}, {-1, 1, 2}} + 7*O{{-2, -1, 1, 2}} + 2*O{{-2, 1, 2}, {-1}} """ OP = self.parent().orbit_basis() return OP(self) @@ -2713,7 +2771,7 @@ def diagram_basis(self): Partition Algebra of rank 2 with parameter x over Univariate Polynomial Ring in x over Rational Field sage: P2(O2.an_element()) - 3*P{{-2, -1, 1}, {2}} - 3*P{{-2, -1, 1, 2}} + 2*P{{-2, -1, 2}, {1}} + 3*P{{-2}, {-1, 1, 2}} - 3*P{{-2, -1, 1, 2}} + 2*P{{-2, 1, 2}, {-1}} TESTS:: @@ -2789,7 +2847,7 @@ def product_on_basis(self, d1, d2): sage: o3 * o1 == o1 * o3 and o3 * o1 == o3 True sage: o3 * o3 - 6*O{{-2, -1, 1}, {2}} + 4*O{{-2, -1, 1, 2}} + 4*O{{-2, -1, 2}, {1}} + 6*O{{-2}, {-1, 1, 2}} + 4*O{{-2, -1, 1, 2}} + 4*O{{-2, 1, 2}, {-1}} We compute Examples 4.5 in [BH2017]_:: @@ -2888,12 +2946,12 @@ def to_diagram_basis(self): sage: P = PartitionAlgebra(2, x, R) sage: O = P.orbit_basis() sage: elt = O.an_element(); elt - 3*O{{-2, -1, 1}, {2}} + 2*O{{-2, -1, 1, 2}} + 2*O{{-2, -1, 2}, {1}} + 3*O{{-2}, {-1, 1, 2}} + 2*O{{-2, -1, 1, 2}} + 2*O{{-2, 1, 2}, {-1}} sage: elt.to_diagram_basis() - 3*P{{-2, -1, 1}, {2}} - 3*P{{-2, -1, 1, 2}} + 2*P{{-2, -1, 2}, {1}} + 3*P{{-2}, {-1, 1, 2}} - 3*P{{-2, -1, 1, 2}} + 2*P{{-2, 1, 2}, {-1}} sage: pp = P.an_element() sage: op = pp.to_orbit_basis(); op - 3*O{{-2, -1, 1}, {2}} + 7*O{{-2, -1, 1, 2}} + 2*O{{-2, -1, 2}, {1}} + 3*O{{-2}, {-1, 1, 2}} + 7*O{{-2, -1, 1, 2}} + 2*O{{-2, 1, 2}, {-1}} sage: pp == op.to_diagram_basis() True """ @@ -3355,18 +3413,18 @@ class PlanarAlgebra(SubPartitionAlgebra, UnitDiagramMixin): {{-2, 2}, {-1, 1}} sage: Pl.basis().list() [Pl{{-2, -1, 1, 2}}, - Pl{{-2, -1, 2}, {1}}, - Pl{{-2, -1, 1}, {2}}, Pl{{-2, 1, 2}, {-1}}, Pl{{-2}, {-1, 1, 2}}, - Pl{{-2, 2}, {-1, 1}}, Pl{{-2, -1}, {1, 2}}, - Pl{{-2, -1}, {1}, {2}}, - Pl{{-2, 2}, {-1}, {1}}, - Pl{{-2}, {-1, 2}, {1}}, + Pl{{-2}, {-1}, {1, 2}}, + Pl{{-2, -1, 1}, {2}}, Pl{{-2, 1}, {-1}, {2}}, + Pl{{-2, 2}, {-1, 1}}, + Pl{{-2, -1, 2}, {1}}, + Pl{{-2, 2}, {-1}, {1}}, Pl{{-2}, {-1, 1}, {2}}, - Pl{{-2}, {-1}, {1, 2}}, + Pl{{-2}, {-1, 2}, {1}}, + Pl{{-2, -1}, {1}, {2}}, Pl{{-2}, {-1}, {1}, {2}}] sage: E = Pl([[1,2],[-1,-2]]) sage: E^2 == x*E @@ -3444,17 +3502,17 @@ class PropagatingIdeal(SubPartitionAlgebra): Ideal diagrams of order 2 sage: I.basis().list() [I{{-2, -1, 1, 2}}, - I{{-2, -1, 2}, {1}}, - I{{-2, -1, 1}, {2}}, I{{-2, 1, 2}, {-1}}, I{{-2}, {-1, 1, 2}}, I{{-2, -1}, {1, 2}}, - I{{-2, -1}, {1}, {2}}, - I{{-2, 2}, {-1}, {1}}, - I{{-2}, {-1, 2}, {1}}, + I{{-2}, {-1}, {1, 2}}, + I{{-2, -1, 1}, {2}}, I{{-2, 1}, {-1}, {2}}, + I{{-2, -1, 2}, {1}}, + I{{-2, 2}, {-1}, {1}}, I{{-2}, {-1, 1}, {2}}, - I{{-2}, {-1}, {1, 2}}, + I{{-2}, {-1, 2}, {1}}, + I{{-2, -1}, {1}, {2}}, I{{-2}, {-1}, {1}, {2}}] sage: E = I([[1,2],[-1,-2]]) sage: E^2 == x*E From ce6e63c5506a1e686310fc4fe2661bde4edac41e Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Sat, 23 Jun 2018 09:35:40 +0200 Subject: [PATCH 11/13] remove unused imports --- src/sage/combinat/diagram_algebras.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sage/combinat/diagram_algebras.py b/src/sage/combinat/diagram_algebras.py index 4a6fd5e3076..46dfe568943 100644 --- a/src/sage/combinat/diagram_algebras.py +++ b/src/sage/combinat/diagram_algebras.py @@ -34,10 +34,8 @@ from sage.combinat.combinat import bell_number, catalan_number from sage.structure.global_options import GlobalOptions from sage.combinat.set_partition import SetPartitions, AbstractSetPartition -from sage.combinat.partition import Partitions from sage.combinat.symmetric_group_algebra import SymmetricGroupAlgebra_n from sage.combinat.permutation import Permutations -from sage.sets.set import Set from sage.graphs.graph import Graph from sage.misc.cachefunc import cached_method from sage.misc.lazy_attribute import lazy_attribute From 589f13596c3ab0f51fdc8792e5c5b3555a19803b Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Sun, 24 Jun 2018 23:46:11 +0200 Subject: [PATCH 12/13] adress reviewer's comments: new method number_of_blocks and deprecation of n, partition_diagrams now returns iterator --- src/sage/combinat/diagram_algebras.py | 2 +- src/sage/combinat/set_partition.py | 29 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/sage/combinat/diagram_algebras.py b/src/sage/combinat/diagram_algebras.py index 46dfe568943..a1711ed8cd0 100644 --- a/src/sage/combinat/diagram_algebras.py +++ b/src/sage/combinat/diagram_algebras.py @@ -91,7 +91,7 @@ def partition_diagrams(k): elif k + ZZ(1)/ZZ(2) in ZZ: # Else k in 1/2 ZZ k = ZZ(k + ZZ(1) / ZZ(2)) S = SetPartitions(list(range(1, k+1)) + list(range(-k+1,0))) - S = map(lambda p: [b.union([-k]) if k in b else b for b in p], S) + S = itertools.imap(lambda p: [b.union([-k]) if k in b else b for b in p], S) else: raise ValueError("argument %s must be a half-integer"%k) return S diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index eb8197a02e6..e944d9c667c 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -2189,6 +2189,35 @@ def _repr_(self): """ return "Set partitions of %s with %s parts"%(Set(self._set), self._k) + @property + def n(self): + """ + ``self.n`` is deprecated; use :meth:`number_of_blocks` instead. + + TESTS:: + + sage: SetPartitions(5, 3).n + doctest:...: DeprecationWarning: The attribute n for the number of blocks is deprecated, use the method number_of_blocks instead. + See https://trac.sagemath.org/25462 for details. + 3 + + """ + from sage.misc.superseded import deprecation + deprecation(25462, 'The attribute n for the number of blocks is deprecated, use the method number_of_blocks instead.') + return self.number_of_blocks() + + def number_of_blocks(self): + """ + Return the number of blocks of the set partitions in this class. + + EXAMPLES:: + + sage: SetPartitions(5, 3).number_of_blocks() + 3 + + """ + return self._k + def cardinality(self): """ The Stirling number of the second kind is the number of partitions From ca293e395e482e3da3fe5e875b296eec4518cc8c Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Mon, 25 Jun 2018 10:08:58 +0200 Subject: [PATCH 13/13] avoid itertools and modify docstring --- src/sage/combinat/diagram_algebras.py | 6 ++++-- src/sage/combinat/set_partition.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/sage/combinat/diagram_algebras.py b/src/sage/combinat/diagram_algebras.py index a1711ed8cd0..e44decfed8d 100644 --- a/src/sage/combinat/diagram_algebras.py +++ b/src/sage/combinat/diagram_algebras.py @@ -88,13 +88,15 @@ def partition_diagrams(k): """ if k in ZZ: S = SetPartitions(list(range(1, k+1)) + list(range(-k,0))) + for p in S: + yield p elif k + ZZ(1)/ZZ(2) in ZZ: # Else k in 1/2 ZZ k = ZZ(k + ZZ(1) / ZZ(2)) S = SetPartitions(list(range(1, k+1)) + list(range(-k+1,0))) - S = itertools.imap(lambda p: [b.union([-k]) if k in b else b for b in p], S) + for p in S: + yield [b.union([-k]) if k in b else b for b in p] else: raise ValueError("argument %s must be a half-integer"%k) - return S def brauer_diagrams(k): r""" diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index e944d9c667c..957df78ef0a 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -2208,7 +2208,7 @@ def n(self): def number_of_blocks(self): """ - Return the number of blocks of the set partitions in this class. + Return the number of blocks of the set partitions in ``self``. EXAMPLES::