Skip to content

Commit d9c4091

Browse files
author
Release Manager
committed
Trac #34579: Faster iterator for planar set partitions
Right now, we iterate through all planar set partitions in `algebras.PlanarPartition` by filtering out the non-planar diagrams. However, this is very inefficient for large values of `n`. We implement a recursive algorithm that works by simply taking the part `{a, b, c, ...}` that contains the largest element and uses the fact that we can form the planar partition by combining the planar set partitions on the remaining sets `{1, ..., a-1}`, `{a+1, ..., b-1}`, `...`, which are all independent. URL: https://trac.sagemath.org/34579 Reported by: tscrim Ticket author(s): Travis Scrimshaw Reviewer(s): Frédéric Chapoton
2 parents 321f970 + 22d8a70 commit d9c4091

File tree

1 file changed

+106
-40
lines changed

1 file changed

+106
-40
lines changed

src/sage/combinat/diagram_algebras.py

+106-40
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,13 @@ def planar_diagrams(k):
166166
EXAMPLES::
167167
168168
sage: import sage.combinat.diagram_algebras as da
169-
sage: all_diagrams = da.partition_diagrams(2)
170-
sage: [SetPartition(p) for p in all_diagrams if p not in da.planar_diagrams(2)]
169+
sage: all_diagrams = [SetPartition(p) for p in da.partition_diagrams(2)]
170+
sage: da2 = [SetPartition(p) for p in da.planar_diagrams(2)]
171+
sage: [p for p in all_diagrams if p not in da2]
171172
[{{-2, 1}, {-1, 2}}]
172-
sage: all_diagrams = da.partition_diagrams(5/2)
173-
sage: [SetPartition(p) for p in all_diagrams if p not in da.planar_diagrams(5/2)]
173+
sage: all_diagrams = [SetPartition(p) for p in da.partition_diagrams(5/2)]
174+
sage: da5o2 = [SetPartition(p) for p in da.planar_diagrams(5/2)]
175+
sage: [p for p in all_diagrams if p not in da5o2]
174176
[{{-3, -1, 3}, {-2, 1, 2}},
175177
{{-3, -2, 1, 3}, {-1, 2}},
176178
{{-3, -1, 1, 3}, {-2, 2}},
@@ -182,9 +184,73 @@ def planar_diagrams(k):
182184
{{-3, -1, 3}, {-2, 1}, {2}},
183185
{{-3, -1, 3}, {-2, 2}, {1}}]
184186
"""
185-
for i in partition_diagrams(k):
186-
if is_planar(i):
187-
yield i
187+
if k in ZZ:
188+
X = list(range(1,k+1)) + list(range(-k,0))
189+
yield from planar_partitions_rec(X)
190+
elif k + ZZ(1)/ZZ(2) in ZZ: # Else k in 1/2 ZZ
191+
k = ZZ(k + ZZ(1) / ZZ(2))
192+
X = list(range(1,k+1)) + list(range(-k+1,0))
193+
for Y in planar_partitions_rec(X):
194+
Y = list(Y)
195+
for part in Y:
196+
if k in part:
197+
part.append(-k)
198+
break
199+
yield Y
200+
else:
201+
raise ValueError("argument %s must be a half-integer" % k)
202+
203+
def planar_partitions_rec(X):
204+
r"""
205+
Iterate over all planar set partitions of ``X`` by using a
206+
recursive algorithm.
207+
208+
ALGORITHM:
209+
210+
To construct the set partition `\rho = \{\rho_1, \ldots, \rho_k\}` of
211+
`[n]`, we remove the part of the set partition containing the last
212+
element of ``X``, which, we consider to be `\rho_k = \{i_1, \ldots, i_m\}`
213+
without loss of generality. The remaining parts come from the planar set
214+
partitions of `\{1, \ldots, i_1-1\}, \{i_1+1, \ldots, i_2-1\}, \ldots,
215+
\{i_m+1, \ldots, n\}`.
216+
217+
EXAMPLES::
218+
219+
sage: import sage.combinat.diagram_algebras as da
220+
sage: list(da.planar_partitions_rec([1,2,3]))
221+
[([1, 2], [3]), ([1], [2], [3]), ([2], [1, 3]), ([1], [2, 3]), ([1, 2, 3],)]
222+
"""
223+
if not X:
224+
return
225+
if len(X) <= 2:
226+
# Direct implementation of small cases
227+
yield (X,)
228+
if len(X) > 1:
229+
yield ([X[0]], [X[1]])
230+
return
231+
from sage.misc.misc import powerset
232+
from itertools import product
233+
for S in powerset(range(len(X)-1)):
234+
if not S:
235+
for Y in planar_partitions_rec(X[:-1]):
236+
yield Y + ([X[-1]],)
237+
continue
238+
last = [X[i] for i in S]
239+
last.append(X[-1])
240+
pt = []
241+
if S[0] != 0:
242+
pt += [X[:S[0]]]
243+
pt = [X[S[i]+1:S[i+1]] for i in range(len(S)-1) if S[i]+1 != S[i+1]]
244+
if S[-1] + 1 != len(X) - 1:
245+
pt += [X[S[-1]+1:-1]]
246+
parts = [planar_partitions_rec(X[S[i]+1:S[i+1]]) for i in range(len(S)-1)
247+
if S[i] + 1 != S[i+1]]
248+
if S[0] != 0:
249+
parts.append(planar_partitions_rec(X[:S[0]]))
250+
if S[-1] + 1 != len(X) - 1:
251+
parts.append(planar_partitions_rec(X[S[-1]+1:-1]))
252+
for Y in product(*parts):
253+
yield sum(Y, ()) + (last,)
188254

189255
def ideal_diagrams(k):
190256
r"""
@@ -606,20 +672,20 @@ class PlanarDiagram(AbstractPartitionDiagram):
606672
sage: PlanarDiagrams(2)
607673
Planar diagrams of order 2
608674
sage: PlanarDiagrams(2).list()
609-
[{{-2, -1, 1, 2}},
610-
{{-2, 1, 2}, {-1}},
611-
{{-2}, {-1, 1, 2}},
612-
{{-2, -1}, {1, 2}},
613-
{{-2}, {-1}, {1, 2}},
614-
{{-2, -1, 1}, {2}},
675+
[{{-2}, {-1}, {1, 2}},
676+
{{-2}, {-1}, {1}, {2}},
615677
{{-2, 1}, {-1}, {2}},
616-
{{-2, 2}, {-1, 1}},
617-
{{-2, -1, 2}, {1}},
618678
{{-2, 2}, {-1}, {1}},
679+
{{-2, 1, 2}, {-1}},
680+
{{-2, 2}, {-1, 1}},
619681
{{-2}, {-1, 1}, {2}},
620682
{{-2}, {-1, 2}, {1}},
683+
{{-2}, {-1, 1, 2}},
684+
{{-2, -1}, {1, 2}},
621685
{{-2, -1}, {1}, {2}},
622-
{{-2}, {-1}, {1}, {2}}]
686+
{{-2, -1, 1}, {2}},
687+
{{-2, -1, 2}, {1}},
688+
{{-2, -1, 1, 2}}]
623689
"""
624690
@staticmethod
625691
def __classcall_private__(cls, diag):
@@ -1183,27 +1249,27 @@ def __iter__(self):
11831249
[{{-2, -1}, {1, 2}}, {{-2, 2}, {-1, 1}}]
11841250
11851251
sage: list(da.PlanarDiagrams(3/2))
1186-
[{{-2, -1, 1, 2}},
1187-
{{-2, 1, 2}, {-1}},
1252+
[{{-2, 1, 2}, {-1}},
1253+
{{-2, 2}, {-1}, {1}},
11881254
{{-2, 2}, {-1, 1}},
11891255
{{-2, -1, 2}, {1}},
1190-
{{-2, 2}, {-1}, {1}}]
1256+
{{-2, -1, 1, 2}}]
11911257
11921258
sage: list(da.PlanarDiagrams(2))
1193-
[{{-2, -1, 1, 2}},
1194-
{{-2, 1, 2}, {-1}},
1195-
{{-2}, {-1, 1, 2}},
1196-
{{-2, -1}, {1, 2}},
1197-
{{-2}, {-1}, {1, 2}},
1198-
{{-2, -1, 1}, {2}},
1259+
[{{-2}, {-1}, {1, 2}},
1260+
{{-2}, {-1}, {1}, {2}},
11991261
{{-2, 1}, {-1}, {2}},
1200-
{{-2, 2}, {-1, 1}},
1201-
{{-2, -1, 2}, {1}},
12021262
{{-2, 2}, {-1}, {1}},
1263+
{{-2, 1, 2}, {-1}},
1264+
{{-2, 2}, {-1, 1}},
12031265
{{-2}, {-1, 1}, {2}},
12041266
{{-2}, {-1, 2}, {1}},
1267+
{{-2}, {-1, 1, 2}},
1268+
{{-2, -1}, {1, 2}},
12051269
{{-2, -1}, {1}, {2}},
1206-
{{-2}, {-1}, {1}, {2}}]
1270+
{{-2, -1, 1}, {2}},
1271+
{{-2, -1, 2}, {1}},
1272+
{{-2, -1, 1, 2}}]
12071273
12081274
sage: list(da.IdealDiagrams(3/2))
12091275
[{{-2, -1, 1, 2}},
@@ -1654,11 +1720,11 @@ class PlanarDiagrams(AbstractPartitionDiagrams):
16541720
sage: pld = da.PlanarDiagrams(3/2); pld
16551721
Planar diagrams of order 3/2
16561722
sage: pld.list()
1657-
[{{-2, -1, 1, 2}},
1658-
{{-2, 1, 2}, {-1}},
1723+
[{{-2, 1, 2}, {-1}},
1724+
{{-2, 2}, {-1}, {1}},
16591725
{{-2, 2}, {-1, 1}},
16601726
{{-2, -1, 2}, {1}},
1661-
{{-2, 2}, {-1}, {1}}]
1727+
{{-2, -1, 1, 2}}]
16621728
16631729
TESTS::
16641730
@@ -3967,20 +4033,20 @@ class PlanarAlgebra(SubPartitionAlgebra, UnitDiagramMixin):
39674033
sage: Pl.basis().keys()([[-1, 1], [2, -2]])
39684034
{{-2, 2}, {-1, 1}}
39694035
sage: Pl.basis().list()
3970-
[Pl{{-2, -1, 1, 2}},
3971-
Pl{{-2, 1, 2}, {-1}},
3972-
Pl{{-2}, {-1, 1, 2}},
3973-
Pl{{-2, -1}, {1, 2}},
3974-
Pl{{-2}, {-1}, {1, 2}},
3975-
Pl{{-2, -1, 1}, {2}},
4036+
[Pl{{-2}, {-1}, {1, 2}},
4037+
Pl{{-2}, {-1}, {1}, {2}},
39764038
Pl{{-2, 1}, {-1}, {2}},
3977-
Pl{{-2, 2}, {-1, 1}},
3978-
Pl{{-2, -1, 2}, {1}},
39794039
Pl{{-2, 2}, {-1}, {1}},
4040+
Pl{{-2, 1, 2}, {-1}},
4041+
Pl{{-2, 2}, {-1, 1}},
39804042
Pl{{-2}, {-1, 1}, {2}},
39814043
Pl{{-2}, {-1, 2}, {1}},
4044+
Pl{{-2}, {-1, 1, 2}},
4045+
Pl{{-2, -1}, {1, 2}},
39824046
Pl{{-2, -1}, {1}, {2}},
3983-
Pl{{-2}, {-1}, {1}, {2}}]
4047+
Pl{{-2, -1, 1}, {2}},
4048+
Pl{{-2, -1, 2}, {1}},
4049+
Pl{{-2, -1, 1, 2}}]
39844050
sage: E = Pl([[1,2],[-1,-2]])
39854051
sage: E^2 == x*E
39864052
True

0 commit comments

Comments
 (0)