Skip to content

Commit 6769749

Browse files
committed
fix is_XXX for empty partitions, fix __iter__ for SCPP, improve performance of __iter__ for SSCPP, CSTCPP and CSSCPP
1 parent 947506e commit 6769749

File tree

1 file changed

+126
-44
lines changed

1 file changed

+126
-44
lines changed

src/sage/combinat/plane_partition.py

Lines changed: 126 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -879,7 +879,14 @@ def is_SPP(self) -> bool:
879879
sage: PP = PlanePartition([[3,2],[2,0],[0,0]])
880880
sage: PP.is_SPP()
881881
True
882+
883+
TESTS::
884+
885+
sage: PlanePartition([]).is_SPP()
886+
True
882887
"""
888+
if not self:
889+
return True
883890
Z = self.z_tableau()
884891
c1 = len(Z)
885892
c2 = len(Z[0])
@@ -907,6 +914,11 @@ def is_CSPP(self) -> bool:
907914
sage: PP = PlanePartition([[3,2,2],[3,1,0],[1,1,0]])
908915
sage: PP.is_CSPP()
909916
True
917+
918+
TESTS::
919+
920+
sage: PlanePartition([]).is_CSPP()
921+
True
910922
"""
911923
if self.z_tableau() == self.y_tableau():
912924
return True
@@ -927,6 +939,11 @@ def is_TSPP(self) -> bool:
927939
sage: PP = PlanePartition([[3,3,3],[3,3,2],[3,2,1]])
928940
sage: PP.is_TSPP()
929941
True
942+
943+
TESTS::
944+
945+
sage: PlanePartition([]).is_TSPP()
946+
True
930947
"""
931948
return self.is_CSPP() and self.is_SPP()
932949

@@ -950,6 +967,11 @@ def is_SCPP(self) -> bool:
950967
sage: PP = PlanePartitions([4,4,4])([[4,4,4,4],[4,4,2,0],[4,2,0,0],[0,0,0,0]])
951968
sage: PP.is_SCPP()
952969
True
970+
971+
TESTS::
972+
973+
sage: PlanePartition([]).is_SCPP()
974+
True
953975
"""
954976
return self.z_tableau(tableau=False) == self.complement(tableau_only=True)
955977

@@ -965,6 +987,11 @@ def is_TCPP(self) -> bool:
965987
sage: PP = PlanePartition([[4,4,3,2],[4,4,2,1],[4,2,0,0],[2,0,0,0]])
966988
sage: PP.is_TCPP()
967989
True
990+
991+
TESTS::
992+
993+
sage: PlanePartition([]).is_TCPP()
994+
True
968995
"""
969996
return self.transpose(True) == self.complement(True)
970997

@@ -990,6 +1017,11 @@ def is_SSCPP(self) -> bool:
9901017
sage: PP = PlanePartition([[4,2,2,2],[2,2,2,2],[2,2,2,2],[2,2,2,0]])
9911018
sage: PP.is_SSCPP()
9921019
True
1020+
1021+
TESTS::
1022+
1023+
sage: PlanePartition([]).is_SSCPP()
1024+
True
9931025
"""
9941026
return self.is_SPP() and self.is_SCPP()
9951027

@@ -1006,6 +1038,11 @@ def is_CSTCPP(self) -> bool:
10061038
sage: PP = PlanePartition([[4,4,3,2],[4,3,2,1],[3,2,1,0],[2,1,0,0]])
10071039
sage: PP.is_CSTCPP()
10081040
True
1041+
1042+
TESTS::
1043+
1044+
sage: PlanePartition([]).is_CSTCPP()
1045+
True
10091046
"""
10101047
return self.is_CSPP() and self.is_TCPP()
10111048

@@ -1022,6 +1059,11 @@ def is_CSSCPP(self) -> bool:
10221059
sage: PP = PlanePartition([[4,4,4,1],[3,3,2,1],[3,2,1,1],[3,0,0,0]])
10231060
sage: PP.is_CSSCPP()
10241061
True
1062+
1063+
TESTS::
1064+
1065+
sage: PlanePartition([]).is_CSSCPP()
1066+
True
10251067
"""
10261068
return self.is_CSPP() and self.is_SCPP()
10271069

@@ -1038,6 +1080,11 @@ def is_TSSCPP(self) -> bool:
10381080
sage: PP = PlanePartition([[4,4,3,2],[4,3,2,1],[3,2,1,0],[2,1,0,0]])
10391081
sage: PP.is_TSSCPP()
10401082
True
1083+
1084+
TESTS::
1085+
1086+
sage: PlanePartition([]).is_TSSCPP()
1087+
True
10411088
"""
10421089
return self.is_TSPP() and self.is_SCPP()
10431090

@@ -1609,10 +1656,20 @@ def __iter__(self) -> Iterator:
16091656
16101657
sage: list(PlanePartitions([1,2,1]))
16111658
[Plane partition [], Plane partition [[1]], Plane partition [[1, 1]]]
1659+
1660+
TESTS::
1661+
1662+
sage: all(len(set(PP)) == PP.cardinality()
1663+
....: for b in cartesian_product([range(4)]*3)
1664+
....: if (PP := PlanePartitions(b)))
1665+
True
16121666
"""
16131667
A = self._box[0]
16141668
B = self._box[1]
16151669
C = self._box[2]
1670+
if not A:
1671+
yield self.element_class(self, [], check=False)
1672+
return
16161673
from sage.combinat.tableau import SemistandardTableaux as SST
16171674
for T in SST([B for i in range(A)], max_entry=C + A): # type:ignore
16181675
PP = [[0 for _ in range(B)] for _ in range(A)]
@@ -1725,7 +1782,7 @@ def __iter__(self) -> Iterator:
17251782
17261783
TESTS::
17271784
1728-
sage: all(len(set(PP)) == PP.cardinality() for n in range(1, 10) if (PP := PlanePartitions(n)))
1785+
sage: all(len(set(PP)) == PP.cardinality() for n in range(9) if (PP := PlanePartitions(n)))
17291786
True
17301787
"""
17311788
from sage.combinat.partition import Partitions
@@ -1944,7 +2001,9 @@ def __iter__(self) -> Iterator:
19442001
19452002
TESTS::
19462003
1947-
sage: all(len(set(PP)) == PP.cardinality() for n in range(1, 5) if (PP := PlanePartitions([n]*3, symmetry='SPP')))
2004+
sage: all(len(set(PP)) == PP.cardinality()
2005+
....: for a, b in cartesian_product([range(4)]*2)
2006+
....: if (PP := PlanePartitions([a, a, b], symmetry='SPP')))
19482007
True
19492008
"""
19502009
for acl in self.to_poset().antichains_iterator():
@@ -2174,7 +2233,7 @@ def __iter__(self) -> Iterator:
21742233
21752234
TESTS::
21762235
2177-
sage: all(len(set(PP)) == PP.cardinality() for n in range(1, 5) if (PP := PlanePartitions([n]*3, symmetry='CSPP')))
2236+
sage: all(len(set(PP)) == PP.cardinality() for n in range(5) if (PP := PlanePartitions([n]*3, symmetry='CSPP')))
21782237
True
21792238
"""
21802239
for acl in self.to_poset().antichains_iterator():
@@ -2357,11 +2416,11 @@ def __iter__(self) -> Iterator:
23572416
23582417
TESTS::
23592418
2360-
sage: all(len(set(PP)) == PP.cardinality() for n in range(1, 5) if (PP := PlanePartitions([n]*3, symmetry='TSPP')))
2419+
sage: all(len(set(PP)) == PP.cardinality() for n in range(5) if (PP := PlanePartitions([n]*3, symmetry='TSPP')))
23612420
True
23622421
"""
2363-
for A in self.to_poset().antichains_iterator():
2364-
yield self.from_antichain(A)
2422+
for acl in self.to_poset().antichains_iterator():
2423+
yield self.from_antichain(acl)
23652424

23662425
def cardinality(self) -> Integer:
23672426
r"""
@@ -2457,37 +2516,39 @@ def __iter__(self) -> Iterator:
24572516
sage: PP = PlanePartitions([3,4,5], symmetry='SCPP')
24582517
sage: len(set(PP)) == PP.cardinality()
24592518
True
2519+
2520+
sage: all(len(set(PP)) == PP.cardinality()
2521+
....: for b in cartesian_product([range(4)]*3)
2522+
....: if is_even(prod(b)) and (PP := PlanePartitions(b, symmetry='SCPP')))
2523+
True
24602524
"""
24612525
b = self._box[0]
24622526
a = self._box[1]
24632527
c = self._box[2]
24642528

24652529
def Partitions_inside_lambda(la):
2466-
"Iterate over all partitions contained in la with the same number of parts including 0s."
2467-
if not la:
2468-
yield []
2469-
return
2470-
for mu_0 in range(la[0], 0, -1):
2471-
new_la = [min(mu_0, la[i]) for i in range(1, len(la))]
2472-
for mu in Partitions_inside_lambda(new_la):
2473-
yield [mu_0] + mu
2474-
yield [0] * len(la)
2475-
return
2530+
"""
2531+
Iterate over all partitions contained in la with the same number
2532+
of parts including 0s.
2533+
"""
2534+
from sage.combinat.partition import Partitions
2535+
for k in range(sum(la), -1, -1):
2536+
for mu in Partitions(k, outer=la):
2537+
yield mu + [0]*(len(la)-len(mu))
24762538

24772539
def Partitions_inside_lambda_with_smallest_at_least_k(la, k):
2478-
"Iterate over all partitions contained in la with the smallest entry at least k."
2479-
if not la:
2480-
yield []
2481-
return
2482-
if la[-1] < k:
2483-
yield
2484-
return
2485-
for mu in Partitions_inside_lambda([val-k for val in la]):
2540+
"""
2541+
Iterate over all partitions contained in la with the smallest
2542+
entry at least k.
2543+
"""
2544+
for mu in Partitions_inside_lambda([val - k for val in la]):
24862545
yield [mu[i] + k for i in range(len(la))]
2487-
return
24882546

24892547
def possible_middle_row_for_b_odd(a, c):
2490-
"Iterate over all possible middle row for SCPP inside box(a,b,c) when b is odd."
2548+
"""
2549+
Iterate over all possible middle row for SCPP inside box(a,b,c)
2550+
when b is odd.
2551+
"""
24912552
if a * c % 2 == 1:
24922553
yield
24932554
return
@@ -2496,18 +2557,22 @@ def possible_middle_row_for_b_odd(a, c):
24962557
if not a % 2:
24972558
la = nu + mu
24982559
else:
2499-
la = nu + [c//2] + mu
2560+
la = nu + [c // 2] + mu
25002561
yield la
2501-
return
25022562

25032563
def possible_middle_row_for_b_even(a, c):
2504-
"Iterate over all possible middle ((b/2)+1)st row for SCPP inside box(a,b,c) when b is even."
2564+
"""
2565+
Iterate over all possible middle ((b/2)+1)st row for SCPP inside
2566+
box(a,b,c) when b is even.
2567+
"""
25052568
for mu in Partitions_inside_lambda([c // 2 for i in range((a+1) // 2)]):
2569+
if not mu:
2570+
yield []
2571+
continue
25062572
nu = [c - mu[len(mu)-1-i] for i in range(a // 2)]
25072573
for tau in Partitions_inside_lambda_with_smallest_at_least_k(nu, mu[0]):
25082574
la = tau + mu
25092575
yield la
2510-
return
25112576

25122577
def PPs_with_first_row_la_and_with_k_rows(la, k):
25132578
"Iterate over PPs with first row la and with k rows in total."
@@ -2520,7 +2585,6 @@ def PPs_with_first_row_la_and_with_k_rows(la, k):
25202585
for mu in Partitions_inside_lambda(la):
25212586
for PP in PPs_with_first_row_la_and_with_k_rows(mu, k-1):
25222587
yield [la] + PP
2523-
return
25242588

25252589
def complement(PP, c):
25262590
"Return the complement of PP with respect to height c"
@@ -2531,18 +2595,19 @@ def complement(PP, c):
25312595
return [[c - PP[b-1-i][a-1-j] for j in range(a)] for i in range(b)]
25322596

25332597
if b % 2 == 1:
2534-
for la in possible_middle_row_for_b_odd(a, c): # la is the middle row of SCPP
2598+
# la is the middle row of SCPP
2599+
for la in possible_middle_row_for_b_odd(a, c):
25352600
for PP in PPs_with_first_row_la_and_with_k_rows(la, (b+1) // 2):
25362601
PP_below = PP[1:]
25372602
PP_above = complement(PP_below, c)
25382603
yield self.element_class(self, PP_above + [la] + PP_below)
25392604
else:
2540-
for la in possible_middle_row_for_b_even(a, c): # la is the middle ((a/2)+1)st row of SCPP
2605+
# la is the middle ((a/2)+1)st row of SCPP
2606+
for la in possible_middle_row_for_b_even(a, c):
25412607
for PP in PPs_with_first_row_la_and_with_k_rows(la, b // 2):
25422608
PP_below = PP
25432609
PP_above = complement(PP_below, c)
25442610
yield self.element_class(self, PP_above + PP_below)
2545-
return
25462611

25472612
def cardinality(self) -> Integer:
25482613
r"""
@@ -2718,7 +2783,6 @@ def __iter__(self) -> Iterator:
27182783
for p in PlanePartitions(self._box):
27192784
if p.is_TCPP():
27202785
yield self.element_class(self, p)
2721-
return
27222786

27232787
def cardinality(self) -> Integer:
27242788
r"""
@@ -2741,8 +2805,10 @@ def cardinality(self) -> Integer:
27412805
a = self._box[0]
27422806
c = self._box[2]
27432807
return Integer(binomial(c // 2 + a - 1, a - 1)
2744-
* prod((c + i + j + 1) / (i + j + 1)
2745-
for j in range(1, a - 1) for i in range(1, 1 + j)))
2808+
* prod(c + i + j + 1
2809+
for j in range(1, a - 1) for i in range(1, 1 + j))
2810+
// prod(i + j + 1
2811+
for j in range(1, a - 1) for i in range(1, 1 + j)))
27462812

27472813

27482814
# Class 7
@@ -2797,14 +2863,22 @@ def __iter__(self) -> Iterator:
27972863
EXAMPLES::
27982864
27992865
sage: list(PlanePartitions([4,4,2], symmetry='SSCPP'))
2800-
[Plane partition [[2, 2, 2, 1], [2, 2, 1], [2, 1], [1]],
2866+
[Plane partition [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]],
28012867
Plane partition [[2, 2, 2, 1], [2, 1, 1], [2, 1, 1], [1]],
28022868
Plane partition [[2, 2, 1, 1], [2, 2, 1, 1], [1, 1], [1, 1]],
2869+
Plane partition [[2, 2, 2, 1], [2, 2, 1], [2, 1], [1]],
28032870
Plane partition [[2, 2, 1, 1], [2, 1, 1, 1], [1, 1, 1], [1, 1]],
2804-
Plane partition [[2, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1]],
2805-
Plane partition [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]]
2871+
Plane partition [[2, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1]]]
2872+
2873+
TESTS::
2874+
2875+
sage: all(len(set(PP)) == PP.cardinality()
2876+
....: for a, b in cartesian_product([range(5), range(0, 5, 2)])
2877+
....: if (PP := PlanePartitions([a, a, b], symmetry='SSCPP')))
2878+
True
28062879
"""
2807-
for p in PlanePartitions(self._box):
2880+
# any SSCPP is a SPP
2881+
for p in PlanePartitions(self._box, symmetry='SPP'):
28082882
if p.is_SSCPP():
28092883
yield self.element_class(self, p)
28102884

@@ -2896,8 +2970,16 @@ def __iter__(self) -> Iterator:
28962970
28972971
sage: list(PlanePartitions([2,2,2], symmetry='CSTCPP'))
28982972
[Plane partition [[2, 1], [1]]]
2973+
2974+
TESTS::
2975+
2976+
sage: all(len(set(PP)) == PP.cardinality()
2977+
....: for n in range(0, 5, 2)
2978+
....: if (PP := PlanePartitions([n]*3, symmetry='CSTCPP')))
2979+
True
28992980
"""
2900-
for p in PlanePartitions(self._box):
2981+
# any CSTCPP is a TSPP, a SSCPP and a CSSCPP
2982+
for p in PlanePartitions(self._box, symmetry='TSPP'):
29012983
if p.is_CSTCPP():
29022984
yield self.element_class(self, p)
29032985

@@ -2973,7 +3055,8 @@ def __iter__(self) -> Iterator:
29733055
sage: list(PlanePartitions([2,2,2], symmetry='CSSCPP'))
29743056
[Plane partition [[2, 1], [1]]]
29753057
"""
2976-
for p in PlanePartitions(self._box):
3058+
# any CSSCPP is a SCPP and an CSPP, there are much fewer CSPP
3059+
for p in PlanePartitions(self._box, symmetry='CSPP'):
29773060
if p.is_CSSCPP():
29783061
yield self.element_class(self, p)
29793062

@@ -3191,7 +3274,6 @@ def __iter__(self) -> Iterator:
31913274
"""
31923275
for acl in self.to_poset().antichains_iterator():
31933276
yield self.from_antichain(acl)
3194-
return
31953277

31963278
def cardinality(self) -> Integer:
31973279
r"""

0 commit comments

Comments
 (0)