passagemath-combinat 10.6.42__cp314-cp314-musllinux_1_2_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (400) hide show
  1. passagemath_combinat/__init__.py +3 -0
  2. passagemath_combinat-10.6.42.dist-info/METADATA +160 -0
  3. passagemath_combinat-10.6.42.dist-info/RECORD +400 -0
  4. passagemath_combinat-10.6.42.dist-info/WHEEL +5 -0
  5. passagemath_combinat-10.6.42.dist-info/top_level.txt +3 -0
  6. passagemath_combinat.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  7. passagemath_combinat.libs/libsymmetrica-81fe8739.so.3.0.0 +0 -0
  8. sage/algebras/affine_nil_temperley_lieb.py +263 -0
  9. sage/algebras/all.py +24 -0
  10. sage/algebras/all__sagemath_combinat.py +35 -0
  11. sage/algebras/askey_wilson.py +935 -0
  12. sage/algebras/associated_graded.py +345 -0
  13. sage/algebras/cellular_basis.py +350 -0
  14. sage/algebras/cluster_algebra.py +2766 -0
  15. sage/algebras/down_up_algebra.py +860 -0
  16. sage/algebras/free_algebra.py +1698 -0
  17. sage/algebras/free_algebra_element.py +345 -0
  18. sage/algebras/free_algebra_quotient.py +405 -0
  19. sage/algebras/free_algebra_quotient_element.py +295 -0
  20. sage/algebras/free_zinbiel_algebra.py +885 -0
  21. sage/algebras/hall_algebra.py +783 -0
  22. sage/algebras/hecke_algebras/all.py +4 -0
  23. sage/algebras/hecke_algebras/ariki_koike_algebra.py +1796 -0
  24. sage/algebras/hecke_algebras/ariki_koike_specht_modules.py +475 -0
  25. sage/algebras/hecke_algebras/cubic_hecke_algebra.py +3520 -0
  26. sage/algebras/hecke_algebras/cubic_hecke_base_ring.py +1473 -0
  27. sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py +1079 -0
  28. sage/algebras/iwahori_hecke_algebra.py +3095 -0
  29. sage/algebras/jordan_algebra.py +1773 -0
  30. sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py +113 -0
  31. sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py +156 -0
  32. sage/algebras/lie_conformal_algebras/all.py +18 -0
  33. sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py +134 -0
  34. sage/algebras/lie_conformal_algebras/examples.py +43 -0
  35. sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py +131 -0
  36. sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py +139 -0
  37. sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py +174 -0
  38. sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py +167 -0
  39. sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py +107 -0
  40. sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py +135 -0
  41. sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py +353 -0
  42. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py +236 -0
  43. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py +78 -0
  44. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py +328 -0
  45. sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py +117 -0
  46. sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py +86 -0
  47. sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py +82 -0
  48. sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py +205 -0
  49. sage/algebras/nil_coxeter_algebra.py +191 -0
  50. sage/algebras/q_commuting_polynomials.py +673 -0
  51. sage/algebras/q_system.py +608 -0
  52. sage/algebras/quantum_clifford.py +959 -0
  53. sage/algebras/quantum_groups/ace_quantum_onsager.py +693 -0
  54. sage/algebras/quantum_groups/all.py +9 -0
  55. sage/algebras/quantum_groups/fock_space.py +2219 -0
  56. sage/algebras/quantum_groups/q_numbers.py +207 -0
  57. sage/algebras/quantum_groups/quantum_group_gap.py +2695 -0
  58. sage/algebras/quantum_groups/representations.py +591 -0
  59. sage/algebras/quantum_matrix_coordinate_algebra.py +1006 -0
  60. sage/algebras/quantum_oscillator.py +623 -0
  61. sage/algebras/quaternion_algebra.py +20 -0
  62. sage/algebras/quaternion_algebra_element.py +55 -0
  63. sage/algebras/rational_cherednik_algebra.py +525 -0
  64. sage/algebras/schur_algebra.py +670 -0
  65. sage/algebras/shuffle_algebra.py +1011 -0
  66. sage/algebras/splitting_algebra.py +779 -0
  67. sage/algebras/tensor_algebra.py +709 -0
  68. sage/algebras/yangian.py +1082 -0
  69. sage/algebras/yokonuma_hecke_algebra.py +1018 -0
  70. sage/all__sagemath_combinat.py +35 -0
  71. sage/combinat/SJT.py +255 -0
  72. sage/combinat/affine_permutation.py +2405 -0
  73. sage/combinat/algebraic_combinatorics.py +55 -0
  74. sage/combinat/all.py +53 -0
  75. sage/combinat/all__sagemath_combinat.py +195 -0
  76. sage/combinat/alternating_sign_matrix.py +2063 -0
  77. sage/combinat/baxter_permutations.py +346 -0
  78. sage/combinat/bijectionist.py +3220 -0
  79. sage/combinat/binary_recurrence_sequences.py +1180 -0
  80. sage/combinat/blob_algebra.py +685 -0
  81. sage/combinat/catalog_partitions.py +27 -0
  82. sage/combinat/chas/all.py +23 -0
  83. sage/combinat/chas/fsym.py +1180 -0
  84. sage/combinat/chas/wqsym.py +2601 -0
  85. sage/combinat/cluster_complex.py +326 -0
  86. sage/combinat/colored_permutations.py +2039 -0
  87. sage/combinat/colored_permutations_representations.py +964 -0
  88. sage/combinat/composition_signed.py +142 -0
  89. sage/combinat/composition_tableau.py +855 -0
  90. sage/combinat/constellation.py +1729 -0
  91. sage/combinat/core.py +751 -0
  92. sage/combinat/counting.py +12 -0
  93. sage/combinat/crystals/affine.py +742 -0
  94. sage/combinat/crystals/affine_factorization.py +518 -0
  95. sage/combinat/crystals/affinization.py +331 -0
  96. sage/combinat/crystals/alcove_path.py +2013 -0
  97. sage/combinat/crystals/all.py +22 -0
  98. sage/combinat/crystals/bkk_crystals.py +141 -0
  99. sage/combinat/crystals/catalog.py +115 -0
  100. sage/combinat/crystals/catalog_elementary_crystals.py +18 -0
  101. sage/combinat/crystals/catalog_infinity_crystals.py +33 -0
  102. sage/combinat/crystals/catalog_kirillov_reshetikhin.py +18 -0
  103. sage/combinat/crystals/crystals.py +257 -0
  104. sage/combinat/crystals/direct_sum.py +260 -0
  105. sage/combinat/crystals/elementary_crystals.py +1251 -0
  106. sage/combinat/crystals/fast_crystals.py +441 -0
  107. sage/combinat/crystals/fully_commutative_stable_grothendieck.py +1205 -0
  108. sage/combinat/crystals/generalized_young_walls.py +1076 -0
  109. sage/combinat/crystals/highest_weight_crystals.py +436 -0
  110. sage/combinat/crystals/induced_structure.py +695 -0
  111. sage/combinat/crystals/infinity_crystals.py +730 -0
  112. sage/combinat/crystals/kac_modules.py +863 -0
  113. sage/combinat/crystals/kirillov_reshetikhin.py +4196 -0
  114. sage/combinat/crystals/kyoto_path_model.py +497 -0
  115. sage/combinat/crystals/letters.cpython-314-x86_64-linux-musl.so +0 -0
  116. sage/combinat/crystals/letters.pxd +79 -0
  117. sage/combinat/crystals/letters.pyx +3056 -0
  118. sage/combinat/crystals/littelmann_path.py +1518 -0
  119. sage/combinat/crystals/monomial_crystals.py +1262 -0
  120. sage/combinat/crystals/multisegments.py +462 -0
  121. sage/combinat/crystals/mv_polytopes.py +467 -0
  122. sage/combinat/crystals/pbw_crystal.py +511 -0
  123. sage/combinat/crystals/pbw_datum.cpython-314-x86_64-linux-musl.so +0 -0
  124. sage/combinat/crystals/pbw_datum.pxd +4 -0
  125. sage/combinat/crystals/pbw_datum.pyx +487 -0
  126. sage/combinat/crystals/polyhedral_realization.py +372 -0
  127. sage/combinat/crystals/spins.cpython-314-x86_64-linux-musl.so +0 -0
  128. sage/combinat/crystals/spins.pxd +21 -0
  129. sage/combinat/crystals/spins.pyx +756 -0
  130. sage/combinat/crystals/star_crystal.py +290 -0
  131. sage/combinat/crystals/subcrystal.py +464 -0
  132. sage/combinat/crystals/tensor_product.py +1177 -0
  133. sage/combinat/crystals/tensor_product_element.cpython-314-x86_64-linux-musl.so +0 -0
  134. sage/combinat/crystals/tensor_product_element.pxd +35 -0
  135. sage/combinat/crystals/tensor_product_element.pyx +1870 -0
  136. sage/combinat/crystals/virtual_crystal.py +420 -0
  137. sage/combinat/cyclic_sieving_phenomenon.py +204 -0
  138. sage/combinat/debruijn_sequence.cpython-314-x86_64-linux-musl.so +0 -0
  139. sage/combinat/debruijn_sequence.pyx +355 -0
  140. sage/combinat/decorated_permutation.py +270 -0
  141. sage/combinat/degree_sequences.cpython-314-x86_64-linux-musl.so +0 -0
  142. sage/combinat/degree_sequences.pyx +588 -0
  143. sage/combinat/derangements.py +527 -0
  144. sage/combinat/descent_algebra.py +1008 -0
  145. sage/combinat/diagram.py +1551 -0
  146. sage/combinat/diagram_algebras.py +5886 -0
  147. sage/combinat/dyck_word.py +4349 -0
  148. sage/combinat/e_one_star.py +1623 -0
  149. sage/combinat/enumerated_sets.py +123 -0
  150. sage/combinat/expnums.cpython-314-x86_64-linux-musl.so +0 -0
  151. sage/combinat/expnums.pyx +148 -0
  152. sage/combinat/fast_vector_partitions.cpython-314-x86_64-linux-musl.so +0 -0
  153. sage/combinat/fast_vector_partitions.pyx +346 -0
  154. sage/combinat/fqsym.py +1977 -0
  155. sage/combinat/free_dendriform_algebra.py +954 -0
  156. sage/combinat/free_prelie_algebra.py +1141 -0
  157. sage/combinat/fully_commutative_elements.py +1077 -0
  158. sage/combinat/fully_packed_loop.py +1523 -0
  159. sage/combinat/gelfand_tsetlin_patterns.py +1409 -0
  160. sage/combinat/gray_codes.py +311 -0
  161. sage/combinat/grossman_larson_algebras.py +667 -0
  162. sage/combinat/growth.py +4352 -0
  163. sage/combinat/hall_polynomial.py +188 -0
  164. sage/combinat/hillman_grassl.py +866 -0
  165. sage/combinat/integer_matrices.py +329 -0
  166. sage/combinat/integer_vectors_mod_permgroup.py +1238 -0
  167. sage/combinat/k_tableau.py +4564 -0
  168. sage/combinat/kazhdan_lusztig.py +215 -0
  169. sage/combinat/key_polynomial.py +885 -0
  170. sage/combinat/knutson_tao_puzzles.py +2286 -0
  171. sage/combinat/lr_tableau.py +311 -0
  172. sage/combinat/matrices/all.py +24 -0
  173. sage/combinat/matrices/hadamard_matrix.py +3790 -0
  174. sage/combinat/matrices/latin.py +2912 -0
  175. sage/combinat/misc.py +401 -0
  176. sage/combinat/multiset_partition_into_sets_ordered.py +3541 -0
  177. sage/combinat/ncsf_qsym/all.py +21 -0
  178. sage/combinat/ncsf_qsym/combinatorics.py +317 -0
  179. sage/combinat/ncsf_qsym/generic_basis_code.py +1427 -0
  180. sage/combinat/ncsf_qsym/ncsf.py +5637 -0
  181. sage/combinat/ncsf_qsym/qsym.py +4053 -0
  182. sage/combinat/ncsf_qsym/tutorial.py +447 -0
  183. sage/combinat/ncsym/all.py +21 -0
  184. sage/combinat/ncsym/bases.py +855 -0
  185. sage/combinat/ncsym/dual.py +593 -0
  186. sage/combinat/ncsym/ncsym.py +2076 -0
  187. sage/combinat/necklace.py +551 -0
  188. sage/combinat/non_decreasing_parking_function.py +634 -0
  189. sage/combinat/nu_dyck_word.py +1474 -0
  190. sage/combinat/output.py +861 -0
  191. sage/combinat/parallelogram_polyomino.py +4326 -0
  192. sage/combinat/parking_functions.py +1602 -0
  193. sage/combinat/partition_algebra.py +1998 -0
  194. sage/combinat/partition_kleshchev.py +1982 -0
  195. sage/combinat/partition_shifting_algebras.py +584 -0
  196. sage/combinat/partition_tuple.py +3114 -0
  197. sage/combinat/path_tableaux/all.py +13 -0
  198. sage/combinat/path_tableaux/catalog.py +29 -0
  199. sage/combinat/path_tableaux/dyck_path.py +380 -0
  200. sage/combinat/path_tableaux/frieze.py +476 -0
  201. sage/combinat/path_tableaux/path_tableau.py +728 -0
  202. sage/combinat/path_tableaux/semistandard.py +510 -0
  203. sage/combinat/perfect_matching.py +779 -0
  204. sage/combinat/plane_partition.py +3300 -0
  205. sage/combinat/q_bernoulli.cpython-314-x86_64-linux-musl.so +0 -0
  206. sage/combinat/q_bernoulli.pyx +128 -0
  207. sage/combinat/quickref.py +81 -0
  208. sage/combinat/recognizable_series.py +2051 -0
  209. sage/combinat/regular_sequence.py +4316 -0
  210. sage/combinat/regular_sequence_bounded.py +543 -0
  211. sage/combinat/restricted_growth.py +81 -0
  212. sage/combinat/ribbon.py +20 -0
  213. sage/combinat/ribbon_shaped_tableau.py +489 -0
  214. sage/combinat/ribbon_tableau.py +1180 -0
  215. sage/combinat/rigged_configurations/all.py +46 -0
  216. sage/combinat/rigged_configurations/bij_abstract_class.py +548 -0
  217. sage/combinat/rigged_configurations/bij_infinity.py +370 -0
  218. sage/combinat/rigged_configurations/bij_type_A.py +163 -0
  219. sage/combinat/rigged_configurations/bij_type_A2_dual.py +338 -0
  220. sage/combinat/rigged_configurations/bij_type_A2_even.py +218 -0
  221. sage/combinat/rigged_configurations/bij_type_A2_odd.py +199 -0
  222. sage/combinat/rigged_configurations/bij_type_B.py +900 -0
  223. sage/combinat/rigged_configurations/bij_type_C.py +267 -0
  224. sage/combinat/rigged_configurations/bij_type_D.py +771 -0
  225. sage/combinat/rigged_configurations/bij_type_D_tri.py +392 -0
  226. sage/combinat/rigged_configurations/bij_type_D_twisted.py +576 -0
  227. sage/combinat/rigged_configurations/bij_type_E67.py +402 -0
  228. sage/combinat/rigged_configurations/bijection.py +143 -0
  229. sage/combinat/rigged_configurations/kleber_tree.py +1475 -0
  230. sage/combinat/rigged_configurations/kr_tableaux.py +1898 -0
  231. sage/combinat/rigged_configurations/rc_crystal.py +461 -0
  232. sage/combinat/rigged_configurations/rc_infinity.py +540 -0
  233. sage/combinat/rigged_configurations/rigged_configuration_element.py +2403 -0
  234. sage/combinat/rigged_configurations/rigged_configurations.py +1918 -0
  235. sage/combinat/rigged_configurations/rigged_partition.cpython-314-x86_64-linux-musl.so +0 -0
  236. sage/combinat/rigged_configurations/rigged_partition.pxd +15 -0
  237. sage/combinat/rigged_configurations/rigged_partition.pyx +680 -0
  238. sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +499 -0
  239. sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py +428 -0
  240. sage/combinat/rsk.py +3438 -0
  241. sage/combinat/schubert_polynomial.py +508 -0
  242. sage/combinat/set_partition.py +3318 -0
  243. sage/combinat/set_partition_iterator.cpython-314-x86_64-linux-musl.so +0 -0
  244. sage/combinat/set_partition_iterator.pyx +136 -0
  245. sage/combinat/set_partition_ordered.py +1590 -0
  246. sage/combinat/sf/abreu_nigro.py +346 -0
  247. sage/combinat/sf/all.py +52 -0
  248. sage/combinat/sf/character.py +576 -0
  249. sage/combinat/sf/classical.py +319 -0
  250. sage/combinat/sf/dual.py +996 -0
  251. sage/combinat/sf/elementary.py +549 -0
  252. sage/combinat/sf/hall_littlewood.py +1028 -0
  253. sage/combinat/sf/hecke.py +336 -0
  254. sage/combinat/sf/homogeneous.py +464 -0
  255. sage/combinat/sf/jack.py +1428 -0
  256. sage/combinat/sf/k_dual.py +1458 -0
  257. sage/combinat/sf/kfpoly.py +447 -0
  258. sage/combinat/sf/llt.py +789 -0
  259. sage/combinat/sf/macdonald.py +2019 -0
  260. sage/combinat/sf/monomial.py +525 -0
  261. sage/combinat/sf/multiplicative.py +113 -0
  262. sage/combinat/sf/new_kschur.py +1786 -0
  263. sage/combinat/sf/ns_macdonald.py +964 -0
  264. sage/combinat/sf/orthogonal.py +246 -0
  265. sage/combinat/sf/orthotriang.py +355 -0
  266. sage/combinat/sf/powersum.py +963 -0
  267. sage/combinat/sf/schur.py +880 -0
  268. sage/combinat/sf/sf.py +1653 -0
  269. sage/combinat/sf/sfa.py +7053 -0
  270. sage/combinat/sf/symplectic.py +253 -0
  271. sage/combinat/sf/witt.py +721 -0
  272. sage/combinat/shifted_primed_tableau.py +2735 -0
  273. sage/combinat/shuffle.py +830 -0
  274. sage/combinat/sidon_sets.py +146 -0
  275. sage/combinat/similarity_class_type.py +1721 -0
  276. sage/combinat/sine_gordon.py +618 -0
  277. sage/combinat/six_vertex_model.py +784 -0
  278. sage/combinat/skew_partition.py +2053 -0
  279. sage/combinat/skew_tableau.py +2989 -0
  280. sage/combinat/sloane_functions.py +8935 -0
  281. sage/combinat/specht_module.py +1403 -0
  282. sage/combinat/species/all.py +48 -0
  283. sage/combinat/species/characteristic_species.py +321 -0
  284. sage/combinat/species/composition_species.py +273 -0
  285. sage/combinat/species/cycle_species.py +284 -0
  286. sage/combinat/species/empty_species.py +155 -0
  287. sage/combinat/species/functorial_composition_species.py +148 -0
  288. sage/combinat/species/generating_series.py +673 -0
  289. sage/combinat/species/library.py +148 -0
  290. sage/combinat/species/linear_order_species.py +169 -0
  291. sage/combinat/species/misc.py +83 -0
  292. sage/combinat/species/partition_species.py +290 -0
  293. sage/combinat/species/permutation_species.py +268 -0
  294. sage/combinat/species/product_species.py +423 -0
  295. sage/combinat/species/recursive_species.py +476 -0
  296. sage/combinat/species/set_species.py +192 -0
  297. sage/combinat/species/species.py +820 -0
  298. sage/combinat/species/structure.py +539 -0
  299. sage/combinat/species/subset_species.py +243 -0
  300. sage/combinat/species/sum_species.py +225 -0
  301. sage/combinat/subword.py +564 -0
  302. sage/combinat/subword_complex.py +2122 -0
  303. sage/combinat/subword_complex_c.cpython-314-x86_64-linux-musl.so +0 -0
  304. sage/combinat/subword_complex_c.pyx +119 -0
  305. sage/combinat/super_tableau.py +821 -0
  306. sage/combinat/superpartition.py +1154 -0
  307. sage/combinat/symmetric_group_algebra.py +3774 -0
  308. sage/combinat/symmetric_group_representations.py +1830 -0
  309. sage/combinat/t_sequences.py +877 -0
  310. sage/combinat/tableau.py +9506 -0
  311. sage/combinat/tableau_residues.py +860 -0
  312. sage/combinat/tableau_tuple.py +5353 -0
  313. sage/combinat/tiling.py +2432 -0
  314. sage/combinat/triangles_FHM.py +777 -0
  315. sage/combinat/tutorial.py +1857 -0
  316. sage/combinat/vector_partition.py +337 -0
  317. sage/combinat/words/abstract_word.py +1722 -0
  318. sage/combinat/words/all.py +59 -0
  319. sage/combinat/words/alphabet.py +268 -0
  320. sage/combinat/words/finite_word.py +7201 -0
  321. sage/combinat/words/infinite_word.py +113 -0
  322. sage/combinat/words/lyndon_word.py +652 -0
  323. sage/combinat/words/morphic.py +351 -0
  324. sage/combinat/words/morphism.py +3878 -0
  325. sage/combinat/words/paths.py +2932 -0
  326. sage/combinat/words/shuffle_product.py +278 -0
  327. sage/combinat/words/suffix_trees.py +1873 -0
  328. sage/combinat/words/word.py +769 -0
  329. sage/combinat/words/word_char.cpython-314-x86_64-linux-musl.so +0 -0
  330. sage/combinat/words/word_char.pyx +847 -0
  331. sage/combinat/words/word_datatypes.cpython-314-x86_64-linux-musl.so +0 -0
  332. sage/combinat/words/word_datatypes.pxd +4 -0
  333. sage/combinat/words/word_datatypes.pyx +1067 -0
  334. sage/combinat/words/word_generators.py +2026 -0
  335. sage/combinat/words/word_infinite_datatypes.py +1218 -0
  336. sage/combinat/words/word_options.py +99 -0
  337. sage/combinat/words/words.py +2396 -0
  338. sage/data_structures/all__sagemath_combinat.py +1 -0
  339. sage/databases/all__sagemath_combinat.py +13 -0
  340. sage/databases/findstat.py +4897 -0
  341. sage/databases/oeis.py +2058 -0
  342. sage/databases/sloane.py +393 -0
  343. sage/dynamics/all__sagemath_combinat.py +14 -0
  344. sage/dynamics/cellular_automata/all.py +7 -0
  345. sage/dynamics/cellular_automata/catalog.py +34 -0
  346. sage/dynamics/cellular_automata/elementary.py +612 -0
  347. sage/dynamics/cellular_automata/glca.py +477 -0
  348. sage/dynamics/cellular_automata/solitons.py +1463 -0
  349. sage/dynamics/finite_dynamical_system.py +1249 -0
  350. sage/dynamics/finite_dynamical_system_catalog.py +382 -0
  351. sage/games/all.py +7 -0
  352. sage/games/hexad.py +704 -0
  353. sage/games/quantumino.py +591 -0
  354. sage/games/sudoku.py +889 -0
  355. sage/games/sudoku_backtrack.cpython-314-x86_64-linux-musl.so +0 -0
  356. sage/games/sudoku_backtrack.pyx +189 -0
  357. sage/groups/all__sagemath_combinat.py +1 -0
  358. sage/groups/indexed_free_group.py +489 -0
  359. sage/libs/all__sagemath_combinat.py +6 -0
  360. sage/libs/lrcalc/__init__.py +1 -0
  361. sage/libs/lrcalc/lrcalc.py +525 -0
  362. sage/libs/symmetrica/__init__.py +7 -0
  363. sage/libs/symmetrica/all.py +101 -0
  364. sage/libs/symmetrica/kostka.pxi +168 -0
  365. sage/libs/symmetrica/part.pxi +193 -0
  366. sage/libs/symmetrica/plet.pxi +42 -0
  367. sage/libs/symmetrica/sab.pxi +196 -0
  368. sage/libs/symmetrica/sb.pxi +332 -0
  369. sage/libs/symmetrica/sc.pxi +192 -0
  370. sage/libs/symmetrica/schur.pxi +956 -0
  371. sage/libs/symmetrica/symmetrica.cpython-314-x86_64-linux-musl.so +0 -0
  372. sage/libs/symmetrica/symmetrica.pxi +1172 -0
  373. sage/libs/symmetrica/symmetrica.pyx +39 -0
  374. sage/monoids/all.py +13 -0
  375. sage/monoids/automatic_semigroup.py +1054 -0
  376. sage/monoids/free_abelian_monoid.py +315 -0
  377. sage/monoids/free_abelian_monoid_element.cpython-314-x86_64-linux-musl.so +0 -0
  378. sage/monoids/free_abelian_monoid_element.pxd +16 -0
  379. sage/monoids/free_abelian_monoid_element.pyx +397 -0
  380. sage/monoids/free_monoid.py +335 -0
  381. sage/monoids/free_monoid_element.py +431 -0
  382. sage/monoids/hecke_monoid.py +65 -0
  383. sage/monoids/string_monoid.py +817 -0
  384. sage/monoids/string_monoid_element.py +547 -0
  385. sage/monoids/string_ops.py +143 -0
  386. sage/monoids/trace_monoid.py +972 -0
  387. sage/rings/all__sagemath_combinat.py +2 -0
  388. sage/sat/all.py +4 -0
  389. sage/sat/boolean_polynomials.py +405 -0
  390. sage/sat/converters/__init__.py +6 -0
  391. sage/sat/converters/anf2cnf.py +14 -0
  392. sage/sat/converters/polybori.py +611 -0
  393. sage/sat/solvers/__init__.py +5 -0
  394. sage/sat/solvers/cryptominisat.py +287 -0
  395. sage/sat/solvers/dimacs.py +783 -0
  396. sage/sat/solvers/picosat.py +228 -0
  397. sage/sat/solvers/sat_lp.py +156 -0
  398. sage/sat/solvers/satsolver.cpython-314-x86_64-linux-musl.so +0 -0
  399. sage/sat/solvers/satsolver.pxd +3 -0
  400. sage/sat/solvers/satsolver.pyx +405 -0
@@ -0,0 +1,3114 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ r"""
3
+ Partition tuples
4
+
5
+ A :class:`PartitionTuple` is a tuple of partitions. That is, an ordered
6
+ `k`-tuple of partitions `\mu=(\mu^{(1)},\mu^{(2)},...,\mu^{(k)})`. If
7
+
8
+ .. MATH::
9
+
10
+ n = \lvert \mu \rvert = \lvert \mu^{(1)} \rvert +
11
+ \lvert \mu^{(2)} \rvert + \cdots + \lvert \mu^{(k)} \rvert
12
+
13
+ then we say that `\mu` is a `k`-partition of `n`.
14
+
15
+ In representation theory partition tuples arise as the natural indexing
16
+ set for the ordinary irreducible representations of:
17
+
18
+ - the wreath products of cyclic groups with symmetric groups,
19
+ - the Ariki-Koike algebras, or the cyclotomic Hecke algebras of
20
+ the complex reflection groups of type `G(r,1,n)`,
21
+ - the degenerate cyclotomic Hecke algebras of type `G(r,1,n)`.
22
+
23
+ When these algebras are not semisimple, partition tuples index an important
24
+ class of modules for the algebras, which are generalisations of the Specht
25
+ modules of the symmetric groups.
26
+
27
+ Tuples of partitions also index the standard basis of the higher level
28
+ combinatorial Fock spaces. As a consequence, the combinatorics of partition
29
+ tuples encapsulates the canonical bases of crystal graphs for the irreducible
30
+ integrable highest weight modules of the (quantized) affine special linear
31
+ groups and the (quantized) affine general linear groups. By the
32
+ categorification theorems of Ariki, Varagnolo-Vasserot, Stroppel-Webster and
33
+ others, in characteristic zero the degenerate and non-degenerate cyclotomic
34
+ Hecke algebras, via their Khovanov-Lauda-Rouquier grading, categorify the
35
+ canonical bases of the quantum affine special and general linear groups.
36
+
37
+ Partitions are naturally in bijection with 1-tuples of partitions. Most of the
38
+ combinatorial operations defined on partitions extend to partition tuples in
39
+ a meaningful way. For example, the semisimple branching rules for the Specht
40
+ modules are described by adding and removing cells from partition tuples and
41
+ the modular branching rules correspond to adding and removing good and
42
+ cogood nodes, which is the underlying combinatorics for the associated
43
+ crystal graphs.
44
+
45
+ A :class:`PartitionTuple` belongs to :class:`PartitionTuples` and its derived
46
+ classes. :class:`PartitionTuples` is the parent class for all partitions
47
+ tuples. Four different classes of tuples of partitions are currently supported:
48
+
49
+ - ``PartitionTuples(level=k,size=n)`` are `k`-tuple of partitions of `n`.
50
+ - ``PartitionTuples(level=k)`` are `k`-tuple of partitions.
51
+ - ``PartitionTuples(size=n)`` are tuples of partitions of `n`.
52
+ - ``PartitionTuples()`` are tuples of partitions.
53
+
54
+ .. NOTE::
55
+
56
+ As with :class:`Partitions`, in sage the cells, or nodes, of partition
57
+ tuples are 0-based. For example, the (lexicographically) first cell in
58
+ any non-empty partition tuple is `[0,0,0]`.
59
+
60
+ EXAMPLES::
61
+
62
+ sage: PartitionTuple([[2,2],[1,1],[2]]).cells()
63
+ [(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0), (1, 1, 0), (2, 0, 0), (2, 0, 1)]
64
+
65
+ .. NOTE::
66
+
67
+ Many :class:`PartitionTuple` methods take the individual coordinates `(k,r,c)`
68
+ as their arguments, here `k` is the component, `r` is the row index and `c` is
69
+ the column index. If your coordinates are in the form ``(k,r,c)`` then use
70
+ Python's \*-operator.
71
+
72
+ EXAMPLES::
73
+
74
+ sage: mu=PartitionTuple([[1,1],[2],[2,1]])
75
+ sage: [ mu.arm_length(*c) for c in mu.cells()]
76
+ [0, 0, 1, 0, 1, 0, 0]
77
+
78
+ .. WARNING::
79
+
80
+ In sage, if ``mu`` is a partition tuple then ``mu[k]`` most naturally refers
81
+ to the `k`-th component of ``mu``, so we use the convention of the
82
+ `(k,r,c)`-th cell in a partition tuple refers to the cell in component `k`,
83
+ row `r`, and column `c`. In the literature, the cells of a partition tuple
84
+ are usually written in the form `(r,c,k)`, where `r` is the row index, `c`
85
+ is the column index, and `k` is the component index.
86
+
87
+ REFERENCES:
88
+
89
+ - [DJM1998]_
90
+ - [BK2009]_
91
+
92
+ AUTHORS:
93
+
94
+ - Andrew Mathas (2012-06-01): Initial classes.
95
+
96
+ EXAMPLES:
97
+
98
+ First is a finite enumerated set and the remaining classes are infinite
99
+ enumerated sets::
100
+
101
+ sage: PartitionTuples().an_element()
102
+ ([1, 1, 1, 1], [2, 1, 1], [3, 1], [4])
103
+ sage: PartitionTuples(4).an_element()
104
+ ([], [1], [2], [3])
105
+ sage: PartitionTuples(size=5).an_element()
106
+ ([1], [1], [1], [1], [1])
107
+ sage: PartitionTuples(4,5).an_element()
108
+ ([1], [], [], [4])
109
+ sage: PartitionTuples(3,2)[:] # needs sage.libs.flint
110
+ [([2], [], []),
111
+ ([1, 1], [], []),
112
+ ([1], [1], []),
113
+ ([1], [], [1]),
114
+ ([], [2], []),
115
+ ([], [1, 1], []),
116
+ ([], [1], [1]),
117
+ ([], [], [2]),
118
+ ([], [], [1, 1])]
119
+ sage: PartitionTuples(2,3).list() # needs sage.libs.flint
120
+ [([3], []),
121
+ ([2, 1], []),
122
+ ([1, 1, 1], []),
123
+ ([2], [1]),
124
+ ([1, 1], [1]),
125
+ ([1], [2]),
126
+ ([1], [1, 1]),
127
+ ([], [3]),
128
+ ([], [2, 1]),
129
+ ([], [1, 1, 1])]
130
+
131
+ One tuples of partitions are naturally in bijection with partitions and, as far
132
+ as possible, partition tuples attempts to identify one tuples with partitions::
133
+
134
+ sage: Partition([4,3]) == PartitionTuple([[4,3]])
135
+ True
136
+ sage: Partition([4,3]) == PartitionTuple([4,3])
137
+ True
138
+ sage: PartitionTuple([4,3])
139
+ [4, 3]
140
+ sage: Partition([4,3]) in PartitionTuples()
141
+ True
142
+
143
+ Partition tuples come equipped with many of the corresponding methods for
144
+ partitions. For example, it is possible to add and remove cells, to conjugate
145
+ partition tuples, to work with their diagrams, compare partition tuples in
146
+ dominance and so::
147
+
148
+ sage: PartitionTuple([[4,1],[],[2,2,1],[3]]).pp()
149
+ **** - ** ***
150
+ * **
151
+ *
152
+ sage: PartitionTuple([[4,1],[],[2,2,1],[3]]).conjugate()
153
+ ([1, 1, 1], [3, 2], [], [2, 1, 1, 1])
154
+ sage: PartitionTuple([[4,1],[],[2,2,1],[3]]).conjugate().pp()
155
+ * *** - **
156
+ * ** *
157
+ * *
158
+ *
159
+ sage: lam = PartitionTuples(3)([[3,2],[],[1,1,1,1]]); lam
160
+ ([3, 2], [], [1, 1, 1, 1])
161
+ sage: lam.level()
162
+ 3
163
+ sage: lam.size()
164
+ 9
165
+ sage: lam.category()
166
+ Category of elements of Partition tuples of level 3
167
+ sage: lam.parent()
168
+ Partition tuples of level 3
169
+ sage: lam[0]
170
+ [3, 2]
171
+ sage: lam[1]
172
+ []
173
+ sage: lam[2]
174
+ [1, 1, 1, 1]
175
+ sage: lam.pp()
176
+ *** - *
177
+ ** *
178
+ *
179
+ *
180
+ sage: lam.removable_cells()
181
+ [(0, 0, 2), (0, 1, 1), (2, 3, 0)]
182
+ sage: lam.down_list()
183
+ [([2, 2], [], [1, 1, 1, 1]),
184
+ ([3, 1], [], [1, 1, 1, 1]),
185
+ ([3, 2], [], [1, 1, 1])]
186
+ sage: lam.addable_cells()
187
+ [(0, 0, 3), (0, 1, 2), (0, 2, 0), (1, 0, 0), (2, 0, 1), (2, 4, 0)]
188
+ sage: lam.up_list()
189
+ [([4, 2], [], [1, 1, 1, 1]),
190
+ ([3, 3], [], [1, 1, 1, 1]),
191
+ ([3, 2, 1], [], [1, 1, 1, 1]),
192
+ ([3, 2], [1], [1, 1, 1, 1]),
193
+ ([3, 2], [], [2, 1, 1, 1]),
194
+ ([3, 2], [], [1, 1, 1, 1, 1])]
195
+ sage: lam.conjugate()
196
+ ([4], [], [2, 2, 1])
197
+ sage: lam.dominates( PartitionTuple([[3],[1],[2,2,1]]) )
198
+ False
199
+ sage: lam.dominates( PartitionTuple([[3],[2],[1,1,1]]))
200
+ True
201
+
202
+ Every partition tuple behaves every much like a tuple of partitions::
203
+
204
+ sage: mu = PartitionTuple([[4,1],[],[2,2,1],[3]])
205
+ sage: [ nu for nu in mu ]
206
+ [[4, 1], [], [2, 2, 1], [3]]
207
+ sage: Set([ type(nu) for nu in mu ])
208
+ {<class 'sage.combinat.partition.Partitions_all_with_category.element_class'>}
209
+ sage: mu[2][2]
210
+ 1
211
+ sage: mu[3]
212
+ [3]
213
+ sage: mu.components()
214
+ [[4, 1], [], [2, 2, 1], [3]]
215
+ sage: mu.components() == [ nu for nu in mu ]
216
+ True
217
+ sage: mu[0]
218
+ [4, 1]
219
+ sage: mu[1]
220
+ []
221
+ sage: mu[2]
222
+ [2, 2, 1]
223
+ sage: mu[2][0]
224
+ 2
225
+ sage: mu[2][1]
226
+ 2
227
+ sage: mu.level()
228
+ 4
229
+ sage: len(mu)
230
+ 4
231
+ sage: mu.cells()
232
+ [(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 1, 0), (2, 0, 0), (2, 0, 1),
233
+ (2, 1, 0), (2, 1, 1), (2, 2, 0), (3, 0, 0), (3, 0, 1), (3, 0, 2)]
234
+ sage: mu.addable_cells()
235
+ [(0, 0, 4), (0, 1, 1), (0, 2, 0), (1, 0, 0), (2, 0, 2), (2, 2, 1),
236
+ (2, 3, 0), (3, 0, 3), (3, 1, 0)]
237
+ sage: mu.removable_cells()
238
+ [(0, 0, 3), (0, 1, 0), (2, 1, 1), (2, 2, 0), (3, 0, 2)]
239
+
240
+ Attached to a partition tuple is the corresponding Young, or parabolic,
241
+ subgroup::
242
+
243
+ sage: mu.young_subgroup() # needs sage.groups
244
+ Permutation Group with generators
245
+ [(), (12,13), (11,12), (8,9), (6,7), (3,4), (2,3), (1,2)]
246
+ sage: mu.young_subgroup_generators() # needs sage.groups
247
+ [1, 2, 3, 6, 8, 11, 12]
248
+ """
249
+
250
+ # ****************************************************************************
251
+ # Copyright (C) 2012 Andrew Mathas <andrew.mathas@sydney.edu.au>
252
+ #
253
+ # This program is free software: you can redistribute it and/or modify
254
+ # it under the terms of the GNU General Public License as published by
255
+ # the Free Software Foundation, either version 2 of the License, or
256
+ # (at your option) any later version.
257
+ # https://www.gnu.org/licenses/
258
+ # ****************************************************************************
259
+
260
+ import itertools
261
+
262
+ from .combinat import CombinatorialElement
263
+ from .integer_vector import IntegerVectors
264
+ from .partition import (Partition, Partitions, Partitions_n, _Partitions,
265
+ RegularPartitions_all, RegularPartitions_n)
266
+ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
267
+ from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
268
+ from sage.misc.cachefunc import cached_method
269
+ from sage.misc.lazy_import import lazy_import
270
+ from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
271
+ from sage.rings.integer_ring import ZZ
272
+ from sage.rings.semirings.non_negative_integer_semiring import NN
273
+ from sage.rings.integer import Integer
274
+ from sage.sets.positive_integers import PositiveIntegers
275
+ from sage.structure.parent import Parent
276
+ from sage.structure.unique_representation import UniqueRepresentation
277
+
278
+ lazy_import('sage.groups.perm_gps.permgroup', 'PermutationGroup')
279
+ lazy_import('sage.libs.pari', 'pari')
280
+
281
+ # -------------------------------------------------
282
+ # Partition tuple - element class
283
+ # -------------------------------------------------
284
+
285
+
286
+ class PartitionTuple(CombinatorialElement):
287
+ r"""
288
+ A tuple of :class:`Partition`.
289
+
290
+ A tuple of partition comes equipped with many of methods available to
291
+ partitions. The ``level`` of the PartitionTuple is the length of the tuple.
292
+
293
+ This is an ordered `k`-tuple of partitions
294
+ `\mu=(\mu^{(1)},\mu^{(2)},...,\mu^{(k)})`. If
295
+
296
+ .. MATH::
297
+
298
+ n = \lvert \mu \rvert = \lvert \mu^{(1)} \rvert +
299
+ \lvert \mu^{(2)} \rvert + \cdots + \lvert \mu^{(k)} \rvert
300
+
301
+ then `\mu` is a `k`-partition of `n`.
302
+
303
+ In representation theory PartitionTuples arise as the natural indexing
304
+ set for the ordinary irreducible representations of:
305
+
306
+ - the wreath products of cyclic groups with symmetric groups
307
+ - the Ariki-Koike algebras, or the cyclotomic Hecke algebras of
308
+ the complex reflection groups of type `G(r,1,n)`
309
+ - the degenerate cyclotomic Hecke algebras of type `G(r,1,n)`
310
+
311
+ When these algebras are not semisimple, partition tuples index an important
312
+ class of modules for the algebras which are generalisations of the Specht
313
+ modules of the symmetric groups.
314
+
315
+ Tuples of partitions also index the standard basis of the higher level
316
+ combinatorial Fock spaces. As a consequence, the combinatorics of partition
317
+ tuples encapsulates the canonical bases of crystal graphs for the irreducible
318
+ integrable highest weight modules of the (quantized) affine special linear
319
+ groups and the (quantized) affine general linear groups. By the
320
+ categorification theorems of Ariki, Varagnolo-Vasserot, Stroppel-Webster and
321
+ others, in characteristic zero the degenerate and non-degenerate cyclotomic
322
+ Hecke algebras, via their Khovanov-Lauda-Rouquier grading, categorify the
323
+ canonical bases of the quantum affine special and general linear groups.
324
+
325
+ Partitions are naturally in bijection with 1-tuples of partitions. Most of the
326
+ combinatorial operations defined on partitions extend to PartitionTuples in
327
+ a meaningful way. For example, the semisimple branching rules for the Specht
328
+ modules are described by adding and removing cells from partition tuples and
329
+ the modular branching rules correspond to adding and removing good and
330
+ cogood nodes, which is the underlying combinatorics for the associated
331
+ crystal graphs.
332
+
333
+ .. WARNING::
334
+
335
+ In the literature, the cells of a partition tuple are usually written
336
+ in the form `(r,c,k)`, where `r` is the row index, `c` is the column
337
+ index, and `k` is the component index. In sage, if ``mu`` is a
338
+ partition tuple then ``mu[k]`` most naturally refers to the `k`-th
339
+ component of ``mu``, so we use the convention of the `(k,r,c)`-th cell
340
+ in a partition tuple refers to the cell in component `k`, row `r`, and
341
+ column `c`.
342
+
343
+ INPUT:
344
+
345
+ Anything which can reasonably be interpreted as a tuple of partitions.
346
+ That is, a list or tuple of partitions or valid input to
347
+ :class:`Partition`.
348
+
349
+ EXAMPLES::
350
+
351
+ sage: mu=PartitionTuple( [[3,2],[2,1],[],[1,1,1,1]] ); mu
352
+ ([3, 2], [2, 1], [], [1, 1, 1, 1])
353
+ sage: nu=PartitionTuple( ([3,2],[2,1],[],[1,1,1,1]) ); nu
354
+ ([3, 2], [2, 1], [], [1, 1, 1, 1])
355
+ sage: mu == nu
356
+ True
357
+ sage: mu is nu
358
+ False
359
+ sage: mu in PartitionTuples()
360
+ True
361
+ sage: mu.parent()
362
+ Partition tuples
363
+
364
+ sage: lam=PartitionTuples(3)([[3,2],[],[1,1,1,1]]); lam
365
+ ([3, 2], [], [1, 1, 1, 1])
366
+ sage: lam.level()
367
+ 3
368
+ sage: lam.size()
369
+ 9
370
+ sage: lam.category()
371
+ Category of elements of Partition tuples of level 3
372
+ sage: lam.parent()
373
+ Partition tuples of level 3
374
+ sage: lam[0]
375
+ [3, 2]
376
+ sage: lam[1]
377
+ []
378
+ sage: lam[2]
379
+ [1, 1, 1, 1]
380
+ sage: lam.pp()
381
+ *** - *
382
+ ** *
383
+ *
384
+ *
385
+ sage: lam.removable_cells()
386
+ [(0, 0, 2), (0, 1, 1), (2, 3, 0)]
387
+ sage: lam.down_list()
388
+ [([2, 2], [], [1, 1, 1, 1]), ([3, 1], [], [1, 1, 1, 1]), ([3, 2], [], [1, 1, 1])]
389
+ sage: lam.addable_cells()
390
+ [(0, 0, 3), (0, 1, 2), (0, 2, 0), (1, 0, 0), (2, 0, 1), (2, 4, 0)]
391
+ sage: lam.up_list()
392
+ [([4, 2], [], [1, 1, 1, 1]), ([3, 3], [], [1, 1, 1, 1]), ([3, 2, 1], [], [1, 1, 1, 1]), ([3, 2], [1], [1, 1, 1, 1]), ([3, 2], [], [2, 1, 1, 1]), ([3, 2], [], [1, 1, 1, 1, 1])]
393
+ sage: lam.conjugate()
394
+ ([4], [], [2, 2, 1])
395
+ sage: lam.dominates( PartitionTuple([[3],[1],[2,2,1]]) )
396
+ False
397
+ sage: lam.dominates( PartitionTuple([[3],[2],[1,1,1]]))
398
+ True
399
+
400
+ TESTS::
401
+
402
+ sage: TestSuite( PartitionTuple([4,3,2]) ).run()
403
+ sage: TestSuite( PartitionTuple([[4,3,2],[],[],[3,2,1]]) ).run()
404
+
405
+ .. SEEALSO::
406
+
407
+ - :class:`PartitionTuples`
408
+ - :class:`Partitions`
409
+ """
410
+ Element = Partition
411
+
412
+ @staticmethod
413
+ def __classcall_private__(self, mu):
414
+ """
415
+ This delegates the construction of a :class:`PartitionTuple` to the
416
+ ``element_class()`` call of the appropriate
417
+ :class:`PartitionTuples_level`.
418
+
419
+ TESTS::
420
+
421
+ sage: mu=PartitionTuple([[1,1],[1]])
422
+ sage: mu.category()
423
+ Category of elements of Partition tuples
424
+ sage: type(mu)
425
+ <class 'sage.combinat.partition_tuple.PartitionTuples_all_with_category.element_class'>
426
+ """
427
+ if isinstance(mu, (Partition, PartitionTuple)):
428
+ return mu
429
+
430
+ # one way or another these two cases need to be treated separately
431
+ if mu == [] or mu == [[]]:
432
+ return _Partitions([])
433
+
434
+ # We must check mu is a list of partitions
435
+ try:
436
+ mu = [_Partitions(mu)]
437
+ except ValueError:
438
+ try:
439
+ mu = [_Partitions(nu) for nu in mu]
440
+ except ValueError:
441
+ raise ValueError('%s is not a tuple of Partitions' % mu)
442
+
443
+ if len(mu) == 1:
444
+ return _Partitions(mu[0])
445
+ else:
446
+ return PartitionTuples_all().element_class(PartitionTuples_all(), mu)
447
+
448
+ def __init__(self, parent, mu):
449
+ """
450
+ Initialize ``self`` and checks that the input determines a tuple of
451
+ partitions.
452
+
453
+ EXAMPLES::
454
+
455
+ sage: PartitionTuple([])
456
+ []
457
+ sage: P = PartitionTuple([[2,1,1,0],[2,1]]); P
458
+ ([2, 1, 1], [2, 1])
459
+ sage: TestSuite(P).run()
460
+ sage: PartitionTuple([[],[],[2,1,2,1]])
461
+ Traceback (most recent call last):
462
+ ...
463
+ ValueError: [[], [], [2, 1, 2, 1]] is not a tuple of Partitions
464
+ """
465
+ mu = [_Partitions(nu) for nu in mu]
466
+ CombinatorialElement.__init__(self, parent, mu)
467
+
468
+ def level(self):
469
+ """
470
+ Return the level of this partition tuple.
471
+
472
+ The level is the length of the tuple.
473
+
474
+ EXAMPLES::
475
+
476
+ sage: PartitionTuple([[2,1,1,0],[2,1]]).level()
477
+ 2
478
+ sage: PartitionTuple([[],[],[2,1,1]]).level()
479
+ 3
480
+ """
481
+ return len(self._list)
482
+
483
+ def __len__(self):
484
+ """
485
+ Return the length of this partition tuple.
486
+
487
+ The length is also known as the level.
488
+
489
+ EXAMPLES::
490
+
491
+ sage: len( PartitionTuple([[2,1],[3,2],[1,1,1]]) )
492
+ 3
493
+ """
494
+ return self.level()
495
+
496
+ def _repr_(self, compact=None):
497
+ """
498
+ Return a string representation of ``self`` depending on
499
+ :meth:`PartitionTuples.options`.
500
+
501
+ EXAMPLES::
502
+
503
+ sage: mu=PartitionTuple(([2,1],[3,2],[1,1,1])) # indirect doctest
504
+
505
+ sage: PartitionTuples.options(display='list'); mu
506
+ ([2, 1], [3, 2], [1, 1, 1])
507
+ sage: PartitionTuples.options(display='diagram'); mu
508
+ ** *** *
509
+ * ** *
510
+ *
511
+ sage: PartitionTuples.options(display='compact_low'); mu
512
+ 1,2|2,3|1^3
513
+ sage: PartitionTuples.options(display='compact_high'); mu
514
+ 2,1|3,2|1^3
515
+ sage: PartitionTuples.options(display='exp_low'); mu
516
+ 1, 2 | 2, 3 | 1^3
517
+ sage: PartitionTuples.options(display='exp_high'); mu
518
+ 2, 1 | 3, 2 | 1^3
519
+ sage: PartitionTuples.options._reset()
520
+
521
+ sage: Partitions.options(convention='French')
522
+ sage: PartitionTuples.options(display='diagram'); mu
523
+ *
524
+ * ** *
525
+ ** *** *
526
+ sage: PartitionTuples.options(display='list'); mu
527
+ ([2, 1], [3, 2], [1, 1, 1])
528
+ sage: PartitionTuples.options(display='compact_low'); mu
529
+ 1,2|2,3|1^3
530
+ sage: PartitionTuples.options(display='compact_high'); mu
531
+ 2,1|3,2|1^3
532
+ sage: PartitionTuples.options(display='exp_low'); mu
533
+ 1, 2 | 2, 3 | 1^3
534
+ sage: PartitionTuples.options(display='exp_high'); mu
535
+ 2, 1 | 3, 2 | 1^3
536
+ sage: PartitionTuples.options._reset()
537
+ """
538
+ return self.parent().options._dispatch(self, '_repr_', 'display')
539
+
540
+ def _repr_diagram(self):
541
+ """
542
+ Return a string representation of ``self`` as a Ferrers diagram.
543
+
544
+ EXAMPLES::
545
+
546
+ sage: print(PartitionTuple(([2,1],[3,2],[1,1,1]))._repr_diagram())
547
+ ** *** *
548
+ * ** *
549
+ *
550
+ """
551
+ return self.diagram()
552
+
553
+ def _repr_list(self):
554
+ """
555
+ Return a string representation of ``self`` as a list.
556
+
557
+ EXAMPLES::
558
+
559
+ sage: PartitionTuple(([2,1],[3,2],[1,1,1]))._repr_list()
560
+ '([2, 1], [3, 2], [1, 1, 1])'
561
+ """
562
+ return '(' + ', '.join(nu._repr_() for nu in self) + ')'
563
+
564
+ def _repr_exp_low(self):
565
+ """
566
+ Return a string representation of ``self`` in compact form (exponential
567
+ form with highest first).
568
+
569
+ EXAMPLES::
570
+
571
+ sage: PartitionTuple(([2,1],[3,2],[1,1,1]))._repr_exp_low()
572
+ '1, 2 | 2, 3 | 1^3'
573
+ sage: PartitionTuple(([],[3,2],[1,1,1]))._repr_exp_low()
574
+ '- | 2, 3 | 1^3'
575
+ """
576
+ return ' | '.join(nu._repr_exp_low() for nu in self)
577
+
578
+ def _repr_exp_high(self):
579
+ """
580
+ Return a string representation of ``self`` in compact form (exponential
581
+ form with highest first).
582
+
583
+ EXAMPLES::
584
+
585
+ sage: PartitionTuple(([2,1],[3,2],[1,1,1,1,1,1,1,1,1,1]))._repr_exp_high()
586
+ '2, 1 | 3, 2 | 1^10'
587
+ sage: PartitionTuple(([],[3,2],[1,1,1]))._repr_exp_high()
588
+ '- | 3, 2 | 1^3'
589
+ """
590
+ return ' | '.join(nu._repr_exp_high() for nu in self)
591
+
592
+ def _repr_compact_low(self):
593
+ """
594
+ Return a string representation of ``self`` in compact form (exponential
595
+ form with highest first).
596
+
597
+ EXAMPLES::
598
+
599
+ sage: PartitionTuple(([2,1],[3,2],[1,1,1]))._repr_compact_low()
600
+ '1,2|2,3|1^3'
601
+ sage: PartitionTuple(([],[3,2],[1,1,1]))._repr_compact_low()
602
+ '-|2,3|1^3'
603
+ """
604
+ return '%s' % '|'.join(mu._repr_compact_low() for mu in self)
605
+
606
+ def _repr_compact_high(self):
607
+ """
608
+ Return a string representation of ``self`` in compact form (exponential
609
+ form with highest first).
610
+
611
+ EXAMPLES::
612
+
613
+ sage: PartitionTuple(([2,1],[3,2],[1,1,1]))._repr_compact_high()
614
+ '2,1|3,2|1^3'
615
+ sage: PartitionTuple(([],[3,2],[1,1,1]))._repr_compact_high()
616
+ '-|3,2|1^3'
617
+ """
618
+ return '|'.join(mu._repr_compact_high() for mu in self)
619
+
620
+ # override default string representation which is str(self._list)
621
+ __str__ = lambda self: self._repr_() # type:ignore
622
+
623
+ def _latex_(self):
624
+ r"""
625
+ Return a LaTeX version of ``self``.
626
+
627
+ For more on the latex options, see :meth:`Partitions.option`.
628
+
629
+ EXAMPLES::
630
+
631
+ sage: mu = PartitionTuple([[2, 1],[1,1,1]])
632
+ sage: PartitionTuples.options(latex='diagram'); latex(mu) # indirect doctest
633
+ {\def\lr#1{\multicolumn{1}{@{\hspace{.6ex}}c@{\hspace{.6ex}}}{\raisebox{-.3ex}{$#1$}}}
634
+ \raisebox{-.6ex}{$\begin{array}[b]{*{2}c}\\
635
+ \lr{\ast}&\lr{\ast}\\
636
+ \lr{\ast}\\
637
+ \end{array}$},\raisebox{-.6ex}{$\begin{array}[b]{*{1}c}\\
638
+ \lr{\ast}\\
639
+ \lr{\ast}\\
640
+ \lr{\ast}\\
641
+ \end{array}$}
642
+ }
643
+ sage: PartitionTuples.options(latex='exp_high'); latex(mu) # indirect doctest
644
+ (2,1|1^{3})
645
+ sage: PartitionTuples.options(latex='exp_low'); latex(mu) # indirect doctest
646
+ (1,2|1^{3})
647
+ sage: PartitionTuples.options(latex='list'); latex(mu) # indirect doctest
648
+ [[2, 1], [1, 1, 1]]
649
+ sage: PartitionTuples.options(latex='young_diagram'); latex(mu) # indirect doctest
650
+ {\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
651
+ \raisebox{-.6ex}{$\begin{array}[b]{*{2}c}\cline{1-2}
652
+ \lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{1-2}
653
+ \lr{\phantom{x}}\\\cline{1-1}
654
+ \end{array}$},\raisebox{-.6ex}{$\begin{array}[b]{*{1}c}\cline{1-1}
655
+ \lr{\phantom{x}}\\\cline{1-1}
656
+ \lr{\phantom{x}}\\\cline{1-1}
657
+ \lr{\phantom{x}}\\\cline{1-1}
658
+ \end{array}$}
659
+ }
660
+
661
+ sage: PartitionTuples.options(latex='young_diagram', convention='french')
662
+ sage: PartitionTuples.options(latex='exp_high'); latex(mu) # indirect doctest
663
+ (2,1|1^{3})
664
+ sage: PartitionTuples.options(latex='exp_low'); latex(mu) # indirect doctest
665
+ (1,2|1^{3})
666
+ sage: PartitionTuples.options(latex='list'); latex(mu) # indirect doctest
667
+ [[2, 1], [1, 1, 1]]
668
+ sage: PartitionTuples.options(latex='young_diagram'); latex(mu) # indirect doctest
669
+ {\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
670
+ \raisebox{-.6ex}{$\begin{array}[t]{*{2}c}\cline{1-1}
671
+ \lr{\phantom{x}}\\\cline{1-2}
672
+ \lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{1-2}
673
+ \end{array}$},\raisebox{-.6ex}{$\begin{array}[t]{*{1}c}\cline{1-1}
674
+ \lr{\phantom{x}}\\\cline{1-1}
675
+ \lr{\phantom{x}}\\\cline{1-1}
676
+ \lr{\phantom{x}}\\\cline{1-1}
677
+ \end{array}$}
678
+ }
679
+
680
+ sage: PartitionTuples.options._reset()
681
+ """
682
+ return self.parent().options._dispatch(self, '_latex_', 'latex')
683
+
684
+ def _latex_young_diagram(self):
685
+ """
686
+ LaTeX output as a Young diagram.
687
+
688
+ EXAMPLES::
689
+
690
+ sage: mu = PartitionTuple([[2, 1],[1,1,1]])._latex_young_diagram()
691
+ """
692
+ from sage.combinat.output import tex_from_array_tuple
693
+ return tex_from_array_tuple([[["\\phantom{x}"] * row for row in mu]
694
+ for mu in self._list])
695
+
696
+ def _latex_diagram(self):
697
+ """
698
+ LaTeX output as a Ferrers' diagram.
699
+
700
+ EXAMPLES::
701
+
702
+ sage: mu = PartitionTuple([[2, 1],[1,1,1]])._latex_diagram()
703
+ """
704
+ entry = self.parent().options("latex_diagram_str")
705
+ from sage.combinat.output import tex_from_array_tuple
706
+ return tex_from_array_tuple([[[entry] * row for row in mu]
707
+ for mu in self._list], with_lines=False)
708
+
709
+ def _latex_list(self):
710
+ """
711
+ LaTeX output as a list.
712
+
713
+ EXAMPLES::
714
+
715
+ sage: mu = PartitionTuple([[2, 1],[1,1,1]])._latex_list()
716
+ """
717
+ return repr(self._list)
718
+
719
+ def _latex_exp_low(self):
720
+ """
721
+ LaTeX output in exponential notation (lowest first).
722
+
723
+ EXAMPLES::
724
+
725
+ sage: mu = PartitionTuple([[2, 1],[1,1,1,1,1,1,1,1,1,1]])._latex_exp_low()
726
+ """
727
+ txt = '|'.join(','.join('%s%s' % (a + 1, '' if e == 1 else '^{%s}' % e)
728
+ for a, e in enumerate(mu))
729
+ for mu in self.to_exp())
730
+ return '(' + txt + ')'
731
+
732
+ def _latex_exp_high(self):
733
+ """
734
+ LaTeX output in exponential notation (highest first).
735
+
736
+ EXAMPLES::
737
+
738
+ sage: mu = PartitionTuple([[2, 1],[1,1,1,1,1,1,1,1,1,1]])._latex_exp_high()
739
+ """
740
+ txt = '|'.join(','.join(['%s%s' % (a + 1, '' if e == 1 else '^{%s}' % e)
741
+ for a, e in enumerate(mu)][::-1])
742
+ for mu in self.to_exp())
743
+ return '(' + txt + ')'
744
+
745
+ def components(self):
746
+ r"""
747
+ Return a list containing the shape of this partition.
748
+
749
+ This function exists in order to give a uniform way of iterating over
750
+ the \"components\" of partition tuples of level 1 (partitions) and for
751
+ higher levels.
752
+
753
+ EXAMPLES::
754
+
755
+ sage: for t in PartitionTuple([[2,1],[3,2],[3]]).components():
756
+ ....: print('%s\n' % t.ferrers_diagram())
757
+ **
758
+ *
759
+ <BLANKLINE>
760
+ ***
761
+ **
762
+ <BLANKLINE>
763
+ ***
764
+ <BLANKLINE>
765
+ sage: for t in PartitionTuple([3,2]).components():
766
+ ....: print('%s\n' % t.ferrers_diagram())
767
+ ***
768
+ **
769
+ """
770
+ return list(self)
771
+
772
+ def diagram(self):
773
+ r"""
774
+ Return a string for the Ferrers diagram of ``self``.
775
+
776
+ EXAMPLES::
777
+
778
+ sage: print(PartitionTuple([[2,1],[3,2],[1,1,1]]).diagram())
779
+ ** *** *
780
+ * ** *
781
+ *
782
+ sage: print(PartitionTuple([[3,2],[2,1],[],[1,1,1,1]]).diagram())
783
+ *** ** - *
784
+ ** * *
785
+ *
786
+ *
787
+ sage: PartitionTuples.options(convention='french')
788
+ sage: print(PartitionTuple([[3,2],[2,1],[],[1,1,1,1]]).diagram())
789
+ *
790
+ *
791
+ ** * *
792
+ *** ** - *
793
+ sage: PartitionTuples.options._reset()
794
+ """
795
+ col_len = [mu and mu[0] or 1 for mu in self] # columns per component
796
+ row_max = max(len(mu) for mu in self) # maximum row length
797
+ # There should be a fancier list compression for this but I couldn't get
798
+ # one to work in the cases where a component was the empty partition
799
+ diag = []
800
+ diag_str = PartitionTuples.options('diagram_str')
801
+ for row in range(row_max):
802
+ line = ''
803
+ for c in range(len(self)):
804
+ if row == 0 and self[c] == []:
805
+ line += ' -'
806
+ elif row < len(self[c]):
807
+ line += ' {:{}}'.format(diag_str*self[c][row],col_len[c])
808
+ else:
809
+ line += ' {:{}}'.format('',col_len[c])
810
+ diag.append(line.rstrip())
811
+ if PartitionTuples.options('convention') == "English":
812
+ return '\n'.join(map(str, diag))
813
+ else:
814
+ return '\n'.join(map(str, diag[::-1]))
815
+
816
+ ferrers_diagram = diagram
817
+
818
+ def pp(self):
819
+ r"""
820
+ Pretty print this partition tuple. See :meth:`diagram`.
821
+
822
+ EXAMPLES::
823
+
824
+ sage: PartitionTuple([[5,5,2,1],[3,2]]).pp()
825
+ ***** ***
826
+ ***** **
827
+ **
828
+ *
829
+ """
830
+ print(self.diagram())
831
+
832
+ def size(self):
833
+ """
834
+ Return the size of a partition tuple.
835
+
836
+ EXAMPLES::
837
+
838
+ sage: PartitionTuple([[2,1],[],[2,2]]).size()
839
+ 7
840
+ sage: PartitionTuple([[],[],[1],[3,2,1]]).size()
841
+ 7
842
+ """
843
+ return sum(mu.size() for mu in self)
844
+
845
+ def row_standard_tableaux(self):
846
+ """
847
+ Return the :class:`row standard tableau tuples
848
+ <sage.combinat.tableau_tuple.RowStandardTableauTuples>`
849
+ of shape ``self``.
850
+
851
+ EXAMPLES::
852
+
853
+ sage: PartitionTuple([[],[3,2,2,1],[2,2,1],[3]]).row_standard_tableaux()
854
+ Row standard tableau tuples of shape ([], [3, 2, 2, 1], [2, 2, 1], [3])
855
+ """
856
+ from .tableau_tuple import RowStandardTableauTuples
857
+ return RowStandardTableauTuples(shape=self)
858
+
859
+ def standard_tableaux(self):
860
+ """
861
+ Return the :class:`standard tableau tuples<StandardTableauTuples>`
862
+ of shape ``self``.
863
+
864
+ EXAMPLES::
865
+
866
+ sage: PartitionTuple([[],[3,2,2,1],[2,2,1],[3]]).standard_tableaux()
867
+ Standard tableau tuples of shape ([], [3, 2, 2, 1], [2, 2, 1], [3])
868
+ """
869
+ from .tableau_tuple import StandardTableauTuples
870
+ return StandardTableauTuples(shape=self)
871
+
872
+ def up(self):
873
+ r"""
874
+ Generator (iterator) for the partition tuples that are obtained from
875
+ ``self`` by adding a cell.
876
+
877
+ EXAMPLES::
878
+
879
+ sage: [mu for mu in PartitionTuple([[],[3,1],[1,1]]).up()]
880
+ [([1], [3, 1], [1, 1]), ([], [4, 1], [1, 1]), ([], [3, 2], [1, 1]), ([], [3, 1, 1], [1, 1]), ([], [3, 1], [2, 1]), ([], [3, 1], [1, 1, 1])]
881
+ sage: [mu for mu in PartitionTuple([[],[],[],[]]).up()]
882
+ [([1], [], [], []), ([], [1], [], []), ([], [], [1], []), ([], [], [], [1])]
883
+ """
884
+ for c in range(len(self)):
885
+ for nu in self[c].up():
886
+ up = list(self)
887
+ up[c] = nu
888
+ yield PartitionTuple(up)
889
+
890
+ def up_list(self):
891
+ """
892
+ Return a list of the partition tuples that can be formed from ``self``
893
+ by adding a cell.
894
+
895
+ EXAMPLES::
896
+
897
+ sage: PartitionTuple([[],[3,1],[1,1]]).up_list()
898
+ [([1], [3, 1], [1, 1]), ([], [4, 1], [1, 1]), ([], [3, 2], [1, 1]), ([], [3, 1, 1], [1, 1]), ([], [3, 1], [2, 1]), ([], [3, 1], [1, 1, 1])]
899
+ sage: PartitionTuple([[],[],[],[]]).up_list()
900
+ [([1], [], [], []), ([], [1], [], []), ([], [], [1], []), ([], [], [], [1])]
901
+ """
902
+ return list(self.up())
903
+
904
+ def down(self):
905
+ r"""
906
+ Generator (iterator) for the partition tuples that are obtained from
907
+ ``self`` by removing a cell.
908
+
909
+ EXAMPLES::
910
+
911
+ sage: [mu for mu in PartitionTuple([[],[3,1],[1,1]]).down()]
912
+ [([], [2, 1], [1, 1]), ([], [3], [1, 1]), ([], [3, 1], [1])]
913
+ sage: [mu for mu in PartitionTuple([[],[],[]]).down()]
914
+ []
915
+ """
916
+ for c in range(len(self)):
917
+ for nu in self[c].down():
918
+ down = list(self)
919
+ down[c] = nu
920
+ yield PartitionTuple(down)
921
+
922
+ def down_list(self):
923
+ """
924
+ Return a list of the partition tuples that can be formed from ``self``
925
+ by removing a cell.
926
+
927
+ EXAMPLES::
928
+
929
+ sage: PartitionTuple([[],[3,1],[1,1]]).down_list()
930
+ [([], [2, 1], [1, 1]), ([], [3], [1, 1]), ([], [3, 1], [1])]
931
+ sage: PartitionTuple([[],[],[]]).down_list()
932
+ []
933
+ """
934
+ return list(self.down())
935
+
936
+ def cells(self):
937
+ """
938
+ Return the coordinates of the cells of ``self``. Coordinates are given
939
+ as (component index, row index, column index) and are 0 based.
940
+
941
+ EXAMPLES::
942
+
943
+ sage: PartitionTuple([[2,1],[1],[1,1,1]]).cells()
944
+ [(0, 0, 0), (0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 0, 0), (2, 1, 0), (2, 2, 0)]
945
+ """
946
+ return [(c,a,b) for c in range(len(self)) for (a,b) in self[c].cells()]
947
+
948
+ def content(self, k, r, c, multicharge):
949
+ r"""
950
+ Return the content of the cell.
951
+
952
+ Let `m_k =` ``multicharge[k]``, then the content of a cell is
953
+ `m_k + c - r`.
954
+
955
+ If the ``multicharge`` is a list of integers then it simply offsets the
956
+ values of the contents in each component. On the other hand, if the
957
+ ``multicharge`` belongs to `\ZZ/e\ZZ` then the corresponding
958
+ `e`-residue is returned (that is, the content mod `e`).
959
+
960
+ As with the content method for partitions, the content of a cell does
961
+ not technically depend on the partition tuple, but this method is
962
+ included because it is often useful.
963
+
964
+ EXAMPLES::
965
+
966
+ sage: PartitionTuple([[2,1],[2],[1,1,1]]).content(0,1,0, [0,0,0])
967
+ -1
968
+ sage: PartitionTuple([[2,1],[2],[1,1,1]]).content(0,1,0, [1,0,0])
969
+ 0
970
+ sage: PartitionTuple([[2,1],[2],[1,1,1]]).content(2,1,0, [0,0,0])
971
+ -1
972
+
973
+ and now we return the 3-residue of a cell::
974
+
975
+ sage: multicharge = [IntegerModRing(3)(c) for c in [0,0,0]]
976
+ sage: PartitionTuple([[2,1],[2],[1,1,1]]).content(0,1,0, multicharge)
977
+ 2
978
+ """
979
+ return multicharge[k]-r+c
980
+
981
+ def content_tableau(self, multicharge):
982
+ """
983
+ Return the tableau which has (k,r,c)th entry equal to the content
984
+ ``multicharge[k]-r+c`` of this cell.
985
+
986
+ As with the content function, by setting the ``multicharge``
987
+ appropriately the tableau containing the residues is returned.
988
+
989
+ EXAMPLES::
990
+
991
+ sage: PartitionTuple([[2,1],[2],[1,1,1]]).content_tableau([0,0,0])
992
+ ([[0, 1], [-1]], [[0, 1]], [[0], [-1], [-2]])
993
+ sage: PartitionTuple([[2,1],[2],[1,1,1]]).content_tableau([0,0,1]).pp()
994
+ 0 1 0 1 1
995
+ -1 0
996
+ -1
997
+
998
+ as with the content function the multicharge can be used to return the
999
+ tableau containing the residues of the cells::
1000
+
1001
+ sage: multicharge=[ IntegerModRing(3)(c) for c in [0,0,1] ]
1002
+ sage: PartitionTuple([[2,1],[2],[1,1,1]]).content_tableau(multicharge).pp()
1003
+ 0 1 0 1 1
1004
+ 2 0
1005
+ 2
1006
+ """
1007
+ from sage.combinat.tableau_tuple import TableauTuple
1008
+ return TableauTuple([[[multicharge[k] - r + c
1009
+ for c in range(self[k][r])]
1010
+ for r in range(len(self[k]))]
1011
+ for k in range(len(self))])
1012
+
1013
+ def conjugate(self):
1014
+ """
1015
+ Return the conjugate partition tuple of ``self``.
1016
+
1017
+ The conjugate partition tuple is obtained by reversing the order of the
1018
+ components and then swapping the rows and columns in each component.
1019
+
1020
+ EXAMPLES::
1021
+
1022
+ sage: PartitionTuple([[2,1],[1],[1,1,1]]).conjugate()
1023
+ ([3], [1], [2, 1])
1024
+ """
1025
+ return PartitionTuple([nu.conjugate() for nu in self[::-1]])
1026
+
1027
+ def dominates(self, mu):
1028
+ r"""
1029
+ Return ``True`` if the PartitionTuple dominates or equals `\mu` and
1030
+ ``False`` otherwise.
1031
+
1032
+ Given partition tuples `\mu=(\mu^{(1)},...,\mu^{(m)})` and `\nu=(\nu^{(1)},...,\nu^{(n)})`
1033
+ then `\mu` dominates `\nu` if
1034
+
1035
+ .. MATH::
1036
+
1037
+ \sum_{k=1}^{l-1} |\mu^{(k)}| +\sum_{r \geq 1} \mu^{(l)}_r
1038
+ \geq \sum_{k=1}^{l-1} |\nu^{(k)}| + \sum_{r \geq 1} \nu^{(l)}_r
1039
+
1040
+ EXAMPLES::
1041
+
1042
+ sage: mu=PartitionTuple([[1,1],[2],[2,1]])
1043
+ sage: nu=PartitionTuple([[1,1],[1,1],[2,1]])
1044
+ sage: mu.dominates(mu)
1045
+ True
1046
+ sage: mu.dominates(nu)
1047
+ True
1048
+ sage: nu.dominates(mu)
1049
+ False
1050
+ sage: tau=PartitionTuple([[],[2,1],[]])
1051
+ sage: tau.dominates([[2,1],[],[]])
1052
+ False
1053
+ sage: tau.dominates([[],[],[2,1]])
1054
+ True
1055
+ """
1056
+ try:
1057
+ mu = PartitionTuple(mu)
1058
+ except ValueError:
1059
+ raise ValueError('%s must be a PartitionTuple' % mu)
1060
+
1061
+ if mu == self:
1062
+ return True
1063
+ level = 0
1064
+ ssum = 0 # sum of successive rows in self
1065
+ musum = 0 # sum of successive rows in self
1066
+ while level < self.level() and level < mu.level():
1067
+ row = 0
1068
+ while row < len(self[level]) and row < len(mu[level]):
1069
+ ssum += self[level][row]
1070
+ musum += mu[level][row]
1071
+ if musum > ssum:
1072
+ return False
1073
+ row += 1
1074
+ if row < len(self[level]):
1075
+ ssum += sum(self[level][row:])
1076
+ elif row < len(mu[level]):
1077
+ musum += sum(mu[level][row:])
1078
+ if musum > ssum:
1079
+ return False
1080
+ level += 1
1081
+ return True
1082
+
1083
+ @cached_method
1084
+ def initial_tableau(self):
1085
+ r"""
1086
+ Return the :class:`StandardTableauTuple` which has the numbers
1087
+ `1, 2, \ldots, n`, where `n` is the :meth:`size` of ``self``,
1088
+ entered in order from left to right along the rows of each component,
1089
+ where the components are ordered from left to right.
1090
+
1091
+ EXAMPLES::
1092
+
1093
+ sage: PartitionTuple([ [2,1],[3,2] ]).initial_tableau()
1094
+ ([[1, 2], [3]], [[4, 5, 6], [7, 8]])
1095
+ """
1096
+ from .tableau_tuple import StandardTableauTuples
1097
+ return StandardTableauTuples(self).first()
1098
+
1099
+ @cached_method
1100
+ def initial_column_tableau(self):
1101
+ r"""
1102
+ Return the initial column tableau of shape ``self``.
1103
+
1104
+ The initial column tableau of shape `\lambda` is the standard tableau
1105
+ that has the numbers `1` to `n`, where `n` is the :meth:`size`
1106
+ of `\lambda`, entered in order from top to bottom, and then left
1107
+ to right, down the columns of each component, starting from the
1108
+ rightmost component and working to the left.
1109
+
1110
+ EXAMPLES::
1111
+
1112
+ sage: PartitionTuple([ [3,1],[3,2] ]).initial_column_tableau()
1113
+ ([[6, 8, 9], [7]], [[1, 3, 5], [2, 4]])
1114
+ """
1115
+ return self.conjugate().initial_tableau().conjugate()
1116
+
1117
+ def garnir_tableau(self, *cell):
1118
+ r"""
1119
+ Return the Garnir tableau of shape ``self`` corresponding to the cell
1120
+ ``cell``.
1121
+
1122
+ If ``cell`` `= (k,a,c)` then `(k,a+1,c)` must belong to the diagram of
1123
+ the :class:`PartitionTuple`. If this is not the case then we return
1124
+ ``False``.
1125
+
1126
+ .. NOTE::
1127
+
1128
+ The function also sets ``g._garnir_cell`` equal to ``cell``
1129
+ which is used by some other functions.
1130
+
1131
+ The Garnir tableaux play an important role in integral and
1132
+ non-semisimple representation theory because they determine the
1133
+ "straightening" rules for the Specht modules over an arbitrary ring.
1134
+
1135
+ The Garnir tableau are the "first" non-standard tableaux which arise
1136
+ when you act by simple transpositions. If `(k,a,c)` is a cell in the
1137
+ Young diagram of a partition, which is not at the bottom of its
1138
+ column, then the corresponding Garnir tableau has the integers
1139
+ `1, 2, \ldots, n` entered in order from left to right along the rows
1140
+ of the diagram up to the cell `(k,a,c-1)`, then along the cells
1141
+ `(k,a+1,1)` to `(k,a+1,c)`, then `(k,a,c)` until the end of row `a`
1142
+ and then continuing from left to right in the remaining positions.
1143
+ The examples below probably make this clearer!
1144
+
1145
+ EXAMPLES::
1146
+
1147
+ sage: PartitionTuple([[5,3],[2,2],[4,3]]).garnir_tableau((0,0,2)).pp()
1148
+ 1 2 6 7 8 9 10 13 14 15 16
1149
+ 3 4 5 11 12 17 18 19
1150
+ sage: PartitionTuple([[5,3,3],[2,2],[4,3]]).garnir_tableau((0,0,2)).pp()
1151
+ 1 2 6 7 8 12 13 16 17 18 19
1152
+ 3 4 5 14 15 20 21 22
1153
+ 9 10 11
1154
+ sage: PartitionTuple([[5,3,3],[2,2],[4,3]]).garnir_tableau((0,1,2)).pp()
1155
+ 1 2 3 4 5 12 13 16 17 18 19
1156
+ 6 7 11 14 15 20 21 22
1157
+ 8 9 10
1158
+ sage: PartitionTuple([[5,3,3],[2,2],[4,3]]).garnir_tableau((1,0,0)).pp()
1159
+ 1 2 3 4 5 13 14 16 17 18 19
1160
+ 6 7 8 12 15 20 21 22
1161
+ 9 10 11
1162
+ sage: PartitionTuple([[5,3,3],[2,2],[4,3]]).garnir_tableau((1,0,1)).pp()
1163
+ 1 2 3 4 5 12 15 16 17 18 19
1164
+ 6 7 8 13 14 20 21 22
1165
+ 9 10 11
1166
+ sage: PartitionTuple([[5,3,3],[2,2],[4,3]]).garnir_tableau((2,0,1)).pp()
1167
+ 1 2 3 4 5 12 13 16 19 20 21
1168
+ 6 7 8 14 15 17 18 22
1169
+ 9 10 11
1170
+ sage: PartitionTuple([[5,3,3],[2,2],[4,3]]).garnir_tableau((2,1,1)).pp()
1171
+ Traceback (most recent call last):
1172
+ ...
1173
+ ValueError: (comp, row+1, col) must be inside the diagram
1174
+
1175
+ .. SEEALSO::
1176
+
1177
+ - :meth:`top_garnir_tableau`
1178
+ """
1179
+ try:
1180
+ (comp, row,col) = cell
1181
+ except ValueError:
1182
+ (comp, row,col) = cell[0]
1183
+
1184
+ if comp >= len(self) or row+1 >= len(self[comp]) or col >= self[comp][row+1]:
1185
+ raise ValueError('(comp, row+1, col) must be inside the diagram')
1186
+ g = self.initial_tableau().to_list()
1187
+ a = g[comp][row][col]
1188
+ g[comp][row][col:] = list(range(a+col+1, g[comp][row+1][col]+1))
1189
+ g[comp][row+1][:col+1] = list(range(a, a+col+1))
1190
+ from .tableau_tuple import TableauTuple
1191
+ g = TableauTuple(g)
1192
+ g._garnir_cell = (comp,row,col)
1193
+ return g
1194
+
1195
+ def top_garnir_tableau(self, e, cell):
1196
+ r"""
1197
+ Return the most dominant *standard* tableau which dominates the
1198
+ corresponding Garnir tableau and has the same residue that has shape
1199
+ ``self`` and is determined by ``e`` and ``cell``.
1200
+
1201
+ The Garnir tableau play an important role in integral and
1202
+ non-semisimple representation theory because they determine the
1203
+ "straightening" rules for the Specht modules over an arbitrary ring.
1204
+ The *top Garnir tableaux* arise in the graded representation theory of
1205
+ the symmetric groups and higher level Hecke algebras. They were
1206
+ introduced in [KMR2012]_.
1207
+
1208
+ If the Garnir node is ``cell=(k,r,c)`` and `m` and `M` are the entries
1209
+ in the cells ``(k,r,c)`` and ``(k,r+1,c)``, respectively, in the
1210
+ initial tableau then the top ``e``-Garnir tableau is obtained by
1211
+ inserting the numbers `m, m+1, \ldots, M` in order from left to right
1212
+ first in the cells in row ``r+1`` which are not in the ``e``-Garnir
1213
+ belt, then in the cell in rows ``r`` and ``r+1`` which are in the
1214
+ Garnir belt and then, finally, in the remaining cells in row ``r``
1215
+ which are not in the Garnir belt. All other entries in the tableau
1216
+ remain unchanged.
1217
+
1218
+ If ``e = 0``, or if there are no ``e``-bricks in either row ``r`` or
1219
+ ``r+1``, then the top Garnir tableau is the corresponding Garnir
1220
+ tableau.
1221
+
1222
+ EXAMPLES::
1223
+
1224
+ sage: PartitionTuple([[3,3,2],[5,4,3,2]]).top_garnir_tableau(2,(1,0,2)).pp()
1225
+ 1 2 3 9 10 12 13 16
1226
+ 4 5 6 11 14 15 17
1227
+ 7 8 18 19 20
1228
+ 21 22
1229
+ sage: PartitionTuple([[3,3,2],[5,4,3,2]]).top_garnir_tableau(2,(1,0,1)).pp()
1230
+ 1 2 3 9 10 11 12 13
1231
+ 4 5 6 14 15 16 17
1232
+ 7 8 18 19 20
1233
+ 21 22
1234
+ sage: PartitionTuple([[3,3,2],[5,4,3,2]]).top_garnir_tableau(3,(1,0,1)).pp()
1235
+ 1 2 3 9 12 13 14 15
1236
+ 4 5 6 10 11 16 17
1237
+ 7 8 18 19 20
1238
+ 21 22
1239
+
1240
+ sage: PartitionTuple([[3,3,2],[5,4,3,2]]).top_garnir_tableau(3,(3,0,1)).pp()
1241
+ Traceback (most recent call last):
1242
+ ...
1243
+ ValueError: (comp, row+1, col) must be inside the diagram
1244
+
1245
+ .. SEEALSO::
1246
+
1247
+ - :meth:`~sage.combinat.partition.Partition_tuple.garnir_tableau`
1248
+ """
1249
+ (comp,row,col) = cell
1250
+ if comp >= len(self) or row+1 >= len(self[comp]) or col >= self[comp][row+1]:
1251
+ raise ValueError('(comp, row+1, col) must be inside the diagram')
1252
+
1253
+ g = self.garnir_tableau(cell)
1254
+
1255
+ if e == 0:
1256
+ return # no more dominant tableau of the same residue
1257
+
1258
+ a = e*int((self[comp][row]-col)/e) # number of cells in the e-bricks in row `row`
1259
+ b = e*int((col+1)/e) # number of cells in the e-bricks in row `row+1`
1260
+
1261
+ if a == 0 or b == 0:
1262
+ return self.garnir_tableau(cell)
1263
+
1264
+ t = g.to_list()
1265
+ m = t[comp][row+1][0] # smallest number of 0-Garnir belt
1266
+ # now we will put the number m,m+1,...,t[row+1][col] in order into t
1267
+ t[comp][row][col:a+col] = [m+col-b+1+i for i in range(a)]
1268
+ t[comp][row+1][col-b+1:col+1] = [m+a+col-b+1+i for i in range(b)]
1269
+ from .tableau_tuple import StandardTableauTuple
1270
+ return StandardTableauTuple(t)
1271
+
1272
+ def arm_length(self, k, r, c):
1273
+ """
1274
+ Return the length of the arm of cell ``(k, r, c)`` in ``self``.
1275
+
1276
+ INPUT:
1277
+
1278
+ - ``k`` -- the component
1279
+ - ``r`` -- the row
1280
+ - ``c`` -- the cell
1281
+
1282
+ OUTPUT: the arm length as an integer
1283
+
1284
+ The arm of cell ``(k, r, c)`` is the number of cells in the ``k``-th
1285
+ component which are to the right of the cell in row ``r`` and column
1286
+ ``c``.
1287
+
1288
+ EXAMPLES::
1289
+
1290
+ sage: PartitionTuple([[],[2,1],[2,2,1],[3]]).arm_length(2,0,0)
1291
+ 1
1292
+ sage: PartitionTuple([[],[2,1],[2,2,1],[3]]).arm_length(2,0,1)
1293
+ 0
1294
+ sage: PartitionTuple([[],[2,1],[2,2,1],[3]]).arm_length(2,2,0)
1295
+ 0
1296
+ """
1297
+ try:
1298
+ return self[k][r]-(c+1)
1299
+ except IndexError:
1300
+ raise ValueError("The cell %s is not in the diagram" % ((k,r,c),))
1301
+
1302
+ def leg_length(self, k, r, c):
1303
+ """
1304
+ Return the length of the leg of cell ``(k, r, c)`` in ``self``.
1305
+
1306
+ INPUT:
1307
+
1308
+ - ``k`` -- the component
1309
+ - ``r`` -- the row
1310
+ - ``c`` -- the cell
1311
+
1312
+ OUTPUT: the leg length as an integer
1313
+
1314
+ The leg of cell ``(k, r, c)`` is the number of cells in the ``k``-th
1315
+ component which are below the node in row ``r`` and column ``c``.
1316
+
1317
+ EXAMPLES::
1318
+
1319
+ sage: PartitionTuple([[],[2,1],[2,2,1],[3]]).leg_length(2,0,0)
1320
+ 2
1321
+ sage: PartitionTuple([[],[2,1],[2,2,1],[3]]).leg_length(2,0,1)
1322
+ 1
1323
+ sage: PartitionTuple([[],[2,1],[2,2,1],[3]]).leg_length(2,2,0)
1324
+ 0
1325
+ """
1326
+ try:
1327
+ return self[k].leg_length(r,c)
1328
+ except IndexError:
1329
+ raise ValueError("The cell is not in the diagram")
1330
+
1331
+ def contains(self, mu):
1332
+ r"""
1333
+ Return ``True`` if this partition tuple contains `\mu`.
1334
+
1335
+ If `\lambda=(\lambda^{(1)}, \ldots, \lambda^{(l)})` and
1336
+ `\mu=(\mu^{(1)}, \ldots, \mu^{(m)})` are two partition tuples then
1337
+ `\lambda` contains `\mu` if `m \leq l` and
1338
+ `\mu^{(i)}_r \leq \lambda^{(i)}_r` for `1 \leq i \leq m` and `r \geq 0`.
1339
+
1340
+ EXAMPLES::
1341
+
1342
+ sage: PartitionTuple([[1,1],[2],[2,1]]).contains( PartitionTuple([[1,1],[2],[2,1]]) )
1343
+ True
1344
+ """
1345
+ return mu.level() <= self.level() and all(self[c].contains(mu[c]) for c in range(len(mu)))
1346
+
1347
+ def hook_length(self, k, r, c):
1348
+ r"""
1349
+ Return the length of the hook of cell ``(k, r, c)`` in the partition.
1350
+
1351
+ The hook of cell ``(k, r, c)`` is defined as the cells to the right or
1352
+ below (in the English convention). If your coordinates are in the
1353
+ form ``(k,r,c)``, use Python's \*-operator.
1354
+
1355
+ EXAMPLES::
1356
+
1357
+ sage: mu=PartitionTuple([[1,1],[2],[2,1]])
1358
+ sage: [ mu.hook_length(*c) for c in mu.cells()]
1359
+ [2, 1, 2, 1, 3, 1, 1]
1360
+ """
1361
+ try:
1362
+ return self[k].hook_length(r,c)
1363
+ except IndexError:
1364
+ raise ValueError("The cell is not in the diagram")
1365
+
1366
+ def to_exp(self, k=0):
1367
+ """
1368
+ Return a tuple of the multiplicities of the parts of a partition.
1369
+
1370
+ Use the optional parameter ``k`` to get a return list of length at
1371
+ least ``k``.
1372
+
1373
+ EXAMPLES::
1374
+
1375
+ sage: PartitionTuple([[1,1],[2],[2,1]]).to_exp()
1376
+ ([2], [0, 1], [1, 1])
1377
+ sage: PartitionTuple([[1,1],[2,2,2,2],[2,1]]).to_exp()
1378
+ ([2], [0, 4], [1, 1])
1379
+ """
1380
+ return tuple(self[c].to_exp(k) for c in range(len(self)))
1381
+
1382
+ def removable_cells(self):
1383
+ """
1384
+ Return a list of the removable cells of this partition tuple.
1385
+
1386
+ All indices are of the form ``(k, r, c)``, where ``r`` is the
1387
+ row-index, ``c`` is the column index and ``k`` is the component.
1388
+
1389
+ EXAMPLES::
1390
+
1391
+ sage: PartitionTuple([[1,1],[2],[2,1]]).removable_cells()
1392
+ [(0, 1, 0), (1, 0, 1), (2, 0, 1), (2, 1, 0)]
1393
+ sage: PartitionTuple([[1,1],[4,3],[2,1,1]]).removable_cells()
1394
+ [(0, 1, 0), (1, 0, 3), (1, 1, 2), (2, 0, 1), (2, 2, 0)]
1395
+ """
1396
+ return [(k,r,c) for k in range(len(self)) for (r,c) in self[k].removable_cells()]
1397
+
1398
+ corners = removable_cells # for compatibility with partitions
1399
+
1400
+ def addable_cells(self):
1401
+ """
1402
+ Return a list of the removable cells of this partition tuple.
1403
+
1404
+ All indices are of the form ``(k, r, c)``, where ``r`` is the
1405
+ row-index, ``c`` is the column index and ``k`` is the component.
1406
+
1407
+ EXAMPLES::
1408
+
1409
+ sage: PartitionTuple([[1,1],[2],[2,1]]).addable_cells()
1410
+ [(0, 0, 1), (0, 2, 0), (1, 0, 2), (1, 1, 0), (2, 0, 2), (2, 1, 1), (2, 2, 0)]
1411
+ sage: PartitionTuple([[1,1],[4,3],[2,1,1]]).addable_cells()
1412
+ [(0, 0, 1), (0, 2, 0), (1, 0, 4), (1, 1, 3), (1, 2, 0), (2, 0, 2), (2, 1, 1), (2, 3, 0)]
1413
+ """
1414
+ return [(k,r,c) for k in range(len(self)) for (r,c) in self[k].addable_cells()]
1415
+
1416
+ outside_corners = addable_cells # for compatibility with partitions
1417
+
1418
+ def add_cell(self, k, r, c):
1419
+ r"""
1420
+ Return the partition tuple obtained by adding a cell in row ``r``,
1421
+ column ``c``, and component ``k``.
1422
+
1423
+ This does not change ``self``.
1424
+
1425
+ EXAMPLES::
1426
+
1427
+ sage: PartitionTuple([[1,1],[4,3],[2,1,1]]).add_cell(0,0,1)
1428
+ ([2, 1], [4, 3], [2, 1, 1])
1429
+ """
1430
+ if (k, r, c) in self.addable_cells(): # an addable cell
1431
+ mu = self.to_list()
1432
+ if c == 0:
1433
+ mu[k].append(1)
1434
+ else:
1435
+ mu[k][r] += 1
1436
+ return PartitionTuple(mu)
1437
+ else:
1438
+ raise ValueError("%s is not an addable cell" % ((k, r, c),))
1439
+
1440
+ def remove_cell(self, k, r, c):
1441
+ """
1442
+ Return the partition tuple obtained by removing a cell in row ``r``,
1443
+ column ``c``, and component ``k``.
1444
+
1445
+ This does not change ``self``.
1446
+
1447
+ EXAMPLES::
1448
+
1449
+ sage: PartitionTuple([[1,1],[4,3],[2,1,1]]).remove_cell(0,1,0)
1450
+ ([1], [4, 3], [2, 1, 1])
1451
+ """
1452
+ if (k, r, c) in self.removable_cells(): # a removable cell
1453
+ mu = self.to_list()
1454
+ mu[k][r] -= 1
1455
+ return PartitionTuple(mu)
1456
+ else:
1457
+ raise ValueError("%s is not a removable cell" % ((k, r, c),))
1458
+
1459
+ def to_list(self):
1460
+ r"""
1461
+ Return ``self`` as a list of lists.
1462
+
1463
+ EXAMPLES::
1464
+
1465
+ sage: PartitionTuple([[1,1],[4,3],[2,1,1]]).to_list()
1466
+ [[1, 1], [4, 3], [2, 1, 1]]
1467
+
1468
+ TESTS::
1469
+
1470
+ sage: all(mu==PartitionTuple(mu.to_list()) for mu in PartitionTuples(4,4)) # needs sage.libs.flint
1471
+ True
1472
+ """
1473
+ return [mu.to_list() for mu in self]
1474
+
1475
+ def young_subgroup(self):
1476
+ """
1477
+ Return the corresponding Young, or parabolic, subgroup of the
1478
+ symmetric group.
1479
+
1480
+ EXAMPLES::
1481
+
1482
+ sage: PartitionTuple([[2,1],[4,2],[1]]).young_subgroup() # needs sage.groups
1483
+ Permutation Group with generators [(), (8,9), (6,7), (5,6), (4,5), (1,2)]
1484
+ """
1485
+ gens = []
1486
+ m = 0
1487
+ for comp in self:
1488
+ for row in comp:
1489
+ gens.extend((c, c + 1) for c in range(m + 1, m + row))
1490
+ m += row
1491
+ gens.append(list(range(1, self.size()+1))) # to ensure we get a subgroup of Sym_n
1492
+ return PermutationGroup(gens)
1493
+
1494
+ def young_subgroup_generators(self):
1495
+ """
1496
+ Return an indexing set for the generators of the corresponding Young
1497
+ subgroup.
1498
+
1499
+ EXAMPLES::
1500
+
1501
+ sage: PartitionTuple([[2,1],[4,2],[1]]).young_subgroup_generators()
1502
+ [1, 4, 5, 6, 8]
1503
+ """
1504
+ gens = []
1505
+ m = 0
1506
+ for comp in self:
1507
+ for row in comp:
1508
+ gens.extend(range(m + 1, m + row))
1509
+ m += row
1510
+ return gens
1511
+
1512
+ @cached_method
1513
+ def _initial_degree(self, e, multicharge):
1514
+ r"""
1515
+ Return the Brundan-Kleshchev-Wang degree of the initial tableau
1516
+ of shape ``self``.
1517
+
1518
+ This degree depends only the shape of the tableau and it is
1519
+ used as the base case for computing the degrees of all tableau of
1520
+ shape ``self``, which is why this method is cached. See
1521
+ :meth:`sage.combinat.tableau.Tableau.degree` for more information.
1522
+
1523
+ EXAMPLES::
1524
+
1525
+ sage: PartitionTuple([[2,1],[2,2]])._initial_degree(0,(0,0))
1526
+ 1
1527
+ sage: PartitionTuple([[2,1],[2,2]])._initial_degree(2,(0,0))
1528
+ 4
1529
+ sage: PartitionTuple([[2,1],[2,2]])._initial_degree(3,(0,0))
1530
+ 1
1531
+ sage: PartitionTuple([[2,1],[2,2]])._initial_degree(4,(0,0))
1532
+ 1
1533
+ """
1534
+ if e == 0:
1535
+ deg = 0
1536
+ else:
1537
+ deg = sum(mu._initial_degree(e) for mu in self)
1538
+ I = IntegerModRing(e)
1539
+ multires = [I(k) for k in multicharge]
1540
+ for (k,r,c) in self.cells():
1541
+ res = I(multicharge[k]-r+c)
1542
+ for l in range(k+1, self.level()):
1543
+ if res == multires[l]:
1544
+ deg += 1
1545
+ return deg
1546
+
1547
+ def degree(self, e):
1548
+ r"""
1549
+ Return the ``e``-th degree of ``self``.
1550
+
1551
+ The `e`-th degree is the sum of the degrees of the standard
1552
+ tableaux of shape `\lambda`. The `e`-th degree is the exponent
1553
+ of `\Phi_e(q)` in the Gram determinant of the Specht module for a
1554
+ semisimple cyclotomic Hecke algebra of type `A` with parameter `q`.
1555
+
1556
+ For this calculation the multicharge `(\kappa_1, \ldots, \kappa_l)`
1557
+ is chosen so that `\kappa_{r+1} - \kappa_r > n`, where `n` is
1558
+ the :meth:`size` of `\lambda` as this ensures that the Hecke algebra
1559
+ is semisimple.
1560
+
1561
+ INPUT:
1562
+
1563
+ - ``e`` -- integer `e > 1`
1564
+
1565
+ OUTPUT: nonnegative integer
1566
+
1567
+ EXAMPLES::
1568
+
1569
+ sage: PartitionTuple([[2,1],[2,2]]).degree(2)
1570
+ 532
1571
+ sage: PartitionTuple([[2,1],[2,2]]).degree(3)
1572
+ 259
1573
+ sage: PartitionTuple([[2,1],[2,2]]).degree(4)
1574
+ 196
1575
+ sage: PartitionTuple([[2,1],[2,2]]).degree(5)
1576
+ 105
1577
+ sage: PartitionTuple([[2,1],[2,2]]).degree(6)
1578
+ 105
1579
+ sage: PartitionTuple([[2,1],[2,2]]).degree(7)
1580
+ 0
1581
+
1582
+ Therefore, the Gram determinant of `S(2,1|2,2)` when the Hecke parameter
1583
+ `q` is "generic" is
1584
+
1585
+ .. MATH::
1586
+
1587
+ q^N \Phi_2(q)^{532}\Phi_3(q)^{259}\Phi_4(q)^{196}\Phi_5(q)^{105}\Phi_6(q)^{105}
1588
+
1589
+ for some integer `N`. Compare with :meth:`prime_degree`.
1590
+ """
1591
+ multicharge = tuple([i*self.size() for i in range(self.size())])
1592
+ return sum(t.degree(e, multicharge) for t in self.standard_tableaux())
1593
+
1594
+ def prime_degree(self, p):
1595
+ r"""
1596
+ Return the ``p``-th prime degree of ``self``.
1597
+
1598
+ The degree of a partition `\lambda` is the sum of the `e`-degrees`
1599
+ of the standard tableaux of shape `\lambda` (see :meth:`degree`),
1600
+ for `e` a power of the prime `p`. The prime degree gives the
1601
+ exponent of `p` in the Gram determinant of the integral Specht
1602
+ module of the symmetric group.
1603
+
1604
+ The `p`-th degree is the sum of the degrees of the standard tableaux
1605
+ of shape `\lambda`. The `p`-th degree is the exponent of `p` in the
1606
+ Gram determinant of a semisimple cyclotomic Hecke algebra of type `A`
1607
+ with parameter `q = 1`.
1608
+
1609
+ As with :meth:`degree`, for this calculation the multicharge
1610
+ `(\kappa_1, \ldots, \kappa_l)` is chosen so that
1611
+ `\kappa_{r+1} - \kappa_r > n`, where `n` is the :meth:`size`
1612
+ of `\lambda` as this ensures that the Hecke algebra is semisimple.
1613
+
1614
+ INPUT:
1615
+
1616
+ - ``e`` -- an integer `e > 1`
1617
+ - ``multicharge`` -- an `l`-tuple of integers, where `l` is
1618
+ the :meth:`level` of ``self``
1619
+
1620
+ OUTPUT: nonnegative integer
1621
+
1622
+ EXAMPLES::
1623
+
1624
+ sage: PartitionTuple([[2,1],[2,2]]).prime_degree(2)
1625
+ 728
1626
+ sage: PartitionTuple([[2,1],[2,2]]).prime_degree(3)
1627
+ 259
1628
+ sage: PartitionTuple([[2,1],[2,2]]).prime_degree(5)
1629
+ 105
1630
+ sage: PartitionTuple([[2,1],[2,2]]).prime_degree(7)
1631
+ 0
1632
+
1633
+ Therefore, the Gram determinant of `S(2,1|2,2)` when `q=1` is
1634
+ `2^{728} 3^{259}5^{105}`. Compare with :meth:`degree`.
1635
+ """
1636
+ ps = [p]
1637
+
1638
+ while ps[-1]*p < self.size():
1639
+ ps.append(ps[-1] * p)
1640
+ multicharge = tuple([i*self.size() for i in range(self.size())])
1641
+ return sum(t.degree(pk, multicharge) for pk in ps for t in self.standard_tableaux())
1642
+
1643
+ @cached_method
1644
+ def block(self, e, multicharge):
1645
+ r"""
1646
+ Return a dictionary `\beta` that determines the block associated to
1647
+ the partition ``self`` and the
1648
+ :meth:`~sage.combinat.tableau_residues.ResidueSequence.quantum_characteristic` ``e``.
1649
+
1650
+ INPUT:
1651
+
1652
+ - ``e`` -- the quantum characteristic
1653
+
1654
+ - ``multicharge`` -- the multicharge (default: `(0,)`)
1655
+
1656
+ OUTPUT:
1657
+
1658
+ - a dictionary giving the multiplicities of the residues in the
1659
+ partition tuple ``self``
1660
+
1661
+ In more detail, the value ``beta[i]`` is equal to the
1662
+ number of nodes of residue ``i``. This corresponds to
1663
+ the positive root
1664
+
1665
+ .. MATH::
1666
+
1667
+ \sum_{i\in I} \beta_i \alpha_i \in Q^+,
1668
+
1669
+ a element of the positive root lattice of the corresponding
1670
+ Kac-Moody algebra. See [DJM1998]_ and [BK2009]_ for more details.
1671
+
1672
+ This is a useful statistics because two Specht modules for a cyclotomic
1673
+ Hecke algebra of type `A` belong to the same block if and only if they
1674
+ correspond to same element `\beta` of the root lattice, given above.
1675
+
1676
+ We return a dictionary because when the quantum characteristic is `0`,
1677
+ the Cartan type is `A_{\infty}`, in which case the simple roots are
1678
+ indexed by the integers.
1679
+
1680
+ EXAMPLES::
1681
+
1682
+ sage: PartitionTuple([[2,2],[2,2]]).block(0,(0,0))
1683
+ {-1: 2, 0: 4, 1: 2}
1684
+ sage: PartitionTuple([[2,2],[2,2]]).block(2,(0,0))
1685
+ {0: 4, 1: 4}
1686
+ sage: PartitionTuple([[2,2],[2,2]]).block(2,(0,1))
1687
+ {0: 4, 1: 4}
1688
+ sage: PartitionTuple([[2,2],[2,2]]).block(3,(0,2))
1689
+ {0: 3, 1: 2, 2: 3}
1690
+ sage: PartitionTuple([[2,2],[2,2]]).block(3,(0,2))
1691
+ {0: 3, 1: 2, 2: 3}
1692
+ sage: PartitionTuple([[2,2],[2,2]]).block(3,(3,2))
1693
+ {0: 3, 1: 2, 2: 3}
1694
+ sage: PartitionTuple([[2,2],[2,2]]).block(4,(0,0))
1695
+ {0: 4, 1: 2, 3: 2}
1696
+ """
1697
+ block = {}
1698
+ Ie = IntegerModRing(e)
1699
+ for (k,r,c) in self.cells():
1700
+ i = Ie(multicharge[k] + c - r)
1701
+ block[i] = block.get(i, 0) + 1
1702
+ return block
1703
+
1704
+ def defect(self, e, multicharge):
1705
+ r"""
1706
+ Return the ``e``-defect or the ``e``-weight ``self``.
1707
+
1708
+ The `e`-defect is the number of (connected) `e`-rim hooks
1709
+ that can be removed from the partition.
1710
+
1711
+ The defect of a partition tuple is given by
1712
+
1713
+ .. MATH::
1714
+
1715
+ \text{defect}(\beta) = (\Lambda, \beta) - \tfrac12(\beta, \beta),
1716
+
1717
+ where `\Lambda = \sum_r \Lambda_{\kappa_r}` for the multicharge
1718
+ `(\kappa_1, \ldots, \kappa_{\ell})` and
1719
+ `\beta = \sum_{(r,c)} \alpha_{(c-r) \pmod e}`, with the sum
1720
+ being over the cells in the partition.
1721
+
1722
+ INPUT:
1723
+
1724
+ - ``e`` -- the quantum characteristic
1725
+
1726
+ - ``multicharge`` -- the multicharge (default: `(0,)`)
1727
+
1728
+ OUTPUT: a nonnegative integer, which is the defect of the block
1729
+ containing the partition tuple ``self``
1730
+
1731
+ EXAMPLES::
1732
+
1733
+ sage: PartitionTuple([[2,2],[2,2]]).defect(0,(0,0))
1734
+ 0
1735
+ sage: PartitionTuple([[2,2],[2,2]]).defect(2,(0,0))
1736
+ 8
1737
+ sage: PartitionTuple([[2,2],[2,2]]).defect(2,(0,1))
1738
+ 8
1739
+ sage: PartitionTuple([[2,2],[2,2]]).defect(3,(0,2))
1740
+ 5
1741
+ sage: PartitionTuple([[2,2],[2,2]]).defect(3,(0,2))
1742
+ 5
1743
+ sage: PartitionTuple([[2,2],[2,2]]).defect(3,(3,2))
1744
+ 2
1745
+ sage: PartitionTuple([[2,2],[2,2]]).defect(4,(0,0))
1746
+ 0
1747
+ """
1748
+ # Will correspond to an element of the positive root lattice
1749
+ # corresponding to the block.
1750
+ # We use a dictionary to cover the case when e = 0.
1751
+ beta = self.block(e, multicharge)
1752
+ Ie = IntegerModRing(e)
1753
+ return (sum(beta.get(r, 0) for r in multicharge)
1754
+ - sum(beta[r]**2 - beta[r] * beta.get(Ie(r+1), 0) for r in beta))
1755
+
1756
+ # -------------------------------------------------
1757
+ # Partition tuples - parent classes
1758
+ # -------------------------------------------------
1759
+
1760
+
1761
+ class PartitionTuples(UniqueRepresentation, Parent):
1762
+ r"""
1763
+ Class of all partition tuples.
1764
+
1765
+ For more information about partition tuples, see :class:`PartitionTuple`.
1766
+
1767
+ This is a factory class which returns the appropriate parent based on
1768
+ the values of ``level``, ``size``, and ``regular``
1769
+
1770
+ INPUT:
1771
+
1772
+ - ``level`` -- the length of the tuple
1773
+
1774
+ - ``size`` -- the total number of cells
1775
+
1776
+ - ``regular`` -- positive integer or a tuple of nonnegative
1777
+ integers; if an integer, the highest multiplicity an entry may
1778
+ have in a component plus `1`
1779
+
1780
+ If a level `k` is specified and ``regular`` is a tuple of integers
1781
+ `\ell_1, \ldots, \ell_k`, then this specifies partition tuples `\mu`
1782
+ such that `\mu_i` is `\ell_i`-regular, where `0` here
1783
+ represents `\infty`-regular partitions (equivalently, partitions
1784
+ without restrictions). If ``regular`` is an integer `\ell`, then
1785
+ we set `\ell_i = \ell` for all `i`.
1786
+
1787
+ TESTS::
1788
+
1789
+ sage: [ [2,1],[],[3] ] in PartitionTuples()
1790
+ True
1791
+ sage: ( [2,1],[],[3] ) in PartitionTuples()
1792
+ True
1793
+ sage: ( [] ) in PartitionTuples()
1794
+ True
1795
+ sage: PartitionTuples(level=1, regular=(0,))
1796
+ Partitions
1797
+ sage: PartitionTuples(level=1, size=3, regular=(0,))
1798
+ Partitions of the integer 3
1799
+
1800
+ Check that :issue:`14145` has been fixed::
1801
+
1802
+ sage: 1 in PartitionTuples()
1803
+ False
1804
+ """
1805
+
1806
+ @staticmethod
1807
+ def __classcall_private__(klass, level=None, size=None, regular=None):
1808
+ r"""
1809
+ Return the correct parent object based upon the input.
1810
+
1811
+ TESTS::
1812
+
1813
+ sage: PartitionTuples()
1814
+ Partition tuples
1815
+ sage: PartitionTuples(3)
1816
+ Partition tuples of level 3
1817
+ sage: PartitionTuples(size=3)
1818
+ Partition tuples of size 3
1819
+ sage: PartitionTuples(3,8)
1820
+ Partition tuples of level 3 and size 8
1821
+ sage: PartitionTuples(level=3, regular=(0,2,4))
1822
+ (0, 2, 4)-Regular partition tuples of level 3
1823
+ sage: PartitionTuples(level=1,regular=(4,)) is PartitionTuples(level=1, regular=4)
1824
+ True
1825
+ """
1826
+ # sanity testing
1827
+ if level is not None and (not isinstance(level, (int, Integer)) or level < 1):
1828
+ raise ValueError('the level must be a positive integer')
1829
+
1830
+ if size is not None and (not isinstance(size, (int, Integer)) or size < 0):
1831
+ raise ValueError('the size must be a nonnegative integer')
1832
+
1833
+ if isinstance(regular, (list, tuple)):
1834
+ if level is None:
1835
+ raise ValueError("When no level is specified, regular must be "
1836
+ "a positive integer")
1837
+ if len(regular) != level:
1838
+ raise ValueError("regular must be a list of length {}, got {}".format(
1839
+ level, regular))
1840
+ if regular == 0:
1841
+ raise ValueError("regular must be a positive integer or a tuple "
1842
+ "of nonnegative integers")
1843
+ if level is None:
1844
+ if size is None:
1845
+ if regular is None:
1846
+ return PartitionTuples_all()
1847
+ return RegularPartitionTuples_all(regular)
1848
+
1849
+ if regular is None:
1850
+ return PartitionTuples_size(size)
1851
+ return RegularPartitionTuples_size(size, regular)
1852
+
1853
+ elif level == 1:
1854
+ if isinstance(regular, (list, tuple)):
1855
+ regular = regular[0]
1856
+ if size is None:
1857
+ if regular is None or regular == 0:
1858
+ return _Partitions
1859
+ return RegularPartitions_all(regular)
1860
+
1861
+ if regular is None or regular == 0:
1862
+ return Partitions_n(size)
1863
+ return RegularPartitions_n(size, regular)
1864
+
1865
+ # Higher level
1866
+ if regular is not None:
1867
+ if not isinstance(regular, (list, tuple)):
1868
+ regular = (regular,) * level
1869
+ else:
1870
+ regular = tuple(regular)
1871
+ if size is None:
1872
+ if regular is None:
1873
+ return PartitionTuples_level(level)
1874
+ return RegularPartitionTuples_level(level, regular)
1875
+ if regular is None:
1876
+ return PartitionTuples_level_size(level, size)
1877
+ return RegularPartitionTuples_level_size(level, size, regular)
1878
+
1879
+ Element = PartitionTuple
1880
+ options = Partitions.options
1881
+
1882
+ # default for level
1883
+ _level = None
1884
+ _size = None
1885
+
1886
+ def _element_constructor_(self, mu):
1887
+ r"""
1888
+ Construct an element of :class:`PartitionTuple`.
1889
+
1890
+ INPUT:
1891
+
1892
+ - ``mu`` -- tuple of partitions
1893
+
1894
+ OUTPUT: the corresponding :class:`PartitionTuple` object
1895
+
1896
+ TESTS::
1897
+
1898
+ sage: PartitionTuple([[2],[2],[]]).parent()
1899
+ Partition tuples
1900
+ sage: parts = PartitionTuples(3)
1901
+ sage: parts([[2,1],[1],[2,2,2]]).parent() is parts
1902
+ True
1903
+ sage: PartitionTuples._element_constructor_(PartitionTuples(), [[2,1],[3,2],[1,1,1]])
1904
+ ([2, 1], [3, 2], [1, 1, 1])
1905
+ sage: parts([[1,2]])
1906
+ Traceback (most recent call last):
1907
+ ...
1908
+ ValueError: [[1, 2]] is not a Partition tuples of level 3
1909
+ """
1910
+ # one way or another these two cases need to be treated separately
1911
+ if mu == [] or mu == () or mu == [[]]:
1912
+ if mu not in self:
1913
+ raise ValueError('{} is not a {}'.format(mu, self))
1914
+ return self.element_class(self, [_Partitions([])])
1915
+
1916
+ # As partitions are 1-tuples of partitions we need to treat them separately
1917
+ try:
1918
+ mu = [_Partitions(mu)]
1919
+ except ValueError:
1920
+ try:
1921
+ mu = [_Partitions(nu) for nu in mu]
1922
+ except ValueError:
1923
+ raise ValueError('{} is not a {}'.format(mu, self))
1924
+
1925
+ if mu not in self:
1926
+ raise ValueError('{} is not a {}'.format(mu, self))
1927
+ return self.element_class(self, mu)
1928
+
1929
+ def __contains__(self, mu):
1930
+ r"""
1931
+ Return ``True`` if `\mu` is in ``self``.
1932
+
1933
+ TESTS::
1934
+
1935
+ sage: PartitionTuple([[3,2],[2]]) in PartitionTuples()
1936
+ True
1937
+ sage: PartitionTuple([[3,2],[],[],[],[2]]) in PartitionTuples()
1938
+ True
1939
+ sage: PartitionTuple([[2,1],[],[1,1],[],[2]]) in PartitionTuples()
1940
+ True
1941
+ sage: PartitionTuple([[2,1],[],[1,1],[],[3]]) in PartitionTuples()
1942
+ True
1943
+ sage: all(mu in PartitionTuples() for mu in PartitionTuples(3,8)) # needs sage.libs.flint
1944
+ True
1945
+ sage: [5,1,1] in PartitionTuples()
1946
+ True
1947
+ sage: [[5,1,1]] in PartitionTuples()
1948
+ True
1949
+ sage: la = Partition([3,3,1])
1950
+ sage: PT = PartitionTuples()
1951
+ sage: la in PT
1952
+ True
1953
+ sage: PT(la)
1954
+ ([3, 3, 1])
1955
+
1956
+ Check that :issue:`14145` is fixed::
1957
+
1958
+ sage: 1 in PartitionTuples()
1959
+ False
1960
+ """
1961
+ if isinstance(mu, (PartitionTuple, Partition)):
1962
+ return True
1963
+ if isinstance(mu, (tuple, list)):
1964
+ if not mu:
1965
+ return True
1966
+ if mu[0] in ZZ:
1967
+ return mu in _Partitions
1968
+ return all(m in _Partitions for m in mu)
1969
+ return False
1970
+
1971
+ def __getitem__(self, r):
1972
+ r"""
1973
+ The default implementation of ``__getitem__()`` for enumerated sets
1974
+ does not allow slices, so we override it.
1975
+
1976
+ EXAMPLES::
1977
+
1978
+ sage: PartitionTuples()[10:20] # needs sage.libs.flint
1979
+ [([1, 1, 1]),
1980
+ ([2], []),
1981
+ ([1, 1], []),
1982
+ ([1], [1]),
1983
+ ([], [2]),
1984
+ ([], [1, 1]),
1985
+ ([1], [], []),
1986
+ ([], [1], []),
1987
+ ([], [], [1]),
1988
+ ([], [], [], [])]
1989
+ """
1990
+ if isinstance(r,(int,Integer)):
1991
+ return self.unrank(r)
1992
+ elif isinstance(r,slice):
1993
+ start = 0 if r.start is None else r.start
1994
+ stop = r.stop
1995
+ if stop is None and not self.is_finite():
1996
+ raise ValueError('infinite set')
1997
+ else:
1998
+ raise ValueError('r must be an integer or a slice')
1999
+ count = 0
2000
+ parts = []
2001
+ for t in self:
2002
+ if count == stop:
2003
+ break
2004
+ if count >= start:
2005
+ parts.append(t)
2006
+ count += 1
2007
+
2008
+ # this is to cope with empty slice endpoints like [6:] or [:]
2009
+ if count == stop or stop is None:
2010
+ return parts
2011
+ raise IndexError('value out of range')
2012
+
2013
+ def level(self):
2014
+ """
2015
+ Return the level or ``None`` if it is not defined.
2016
+
2017
+ EXAMPLES::
2018
+
2019
+ sage: PartitionTuples().level() is None
2020
+ True
2021
+ sage: PartitionTuples(7).level()
2022
+ 7
2023
+ """
2024
+ return self._level
2025
+
2026
+ def size(self):
2027
+ """
2028
+ Return the size or ``None`` if it is not defined.
2029
+
2030
+ EXAMPLES::
2031
+
2032
+ sage: PartitionTuples().size() is None
2033
+ True
2034
+ sage: PartitionTuples(size=7).size()
2035
+ 7
2036
+ """
2037
+ return self._size
2038
+
2039
+ def _an_element_(self):
2040
+ """
2041
+ Return a generic element.
2042
+
2043
+ EXAMPLES::
2044
+
2045
+ sage: PartitionTuples().an_element()
2046
+ ([1, 1, 1, 1], [2, 1, 1], [3, 1], [4])
2047
+ """
2048
+ return PartitionTuple(([1, 1, 1, 1], [2, 1, 1], [3, 1], [4]))
2049
+
2050
+
2051
+ class PartitionTuples_all(PartitionTuples):
2052
+ """
2053
+ Class of partition tuples of a arbitrary level and arbitrary sum.
2054
+ """
2055
+
2056
+ def __init__(self):
2057
+ r"""
2058
+ Initialize the class.
2059
+
2060
+ EXAMPLES::
2061
+
2062
+ sage: TestSuite( PartitionTuples() ).run() # needs sage.libs.flint
2063
+ """
2064
+ super().__init__(category=InfiniteEnumeratedSets())
2065
+
2066
+ def _repr_(self):
2067
+ r"""
2068
+ Return a string representation of ``self``.
2069
+
2070
+ EXAMPLES::
2071
+
2072
+ sage: PartitionTuples()
2073
+ Partition tuples
2074
+ """
2075
+ return 'Partition tuples'
2076
+
2077
+ def __iter__(self):
2078
+ r"""
2079
+ Iterate through the infinite class of partition tuples of arbitrary
2080
+ level and size.
2081
+
2082
+ EXAMPLES::
2083
+
2084
+ sage: PartitionTuples()[:20] # needs sage.libs.flint
2085
+ [([]),
2086
+ ([1]),
2087
+ ([], []),
2088
+ ([2]),
2089
+ ([1, 1]),
2090
+ ([1], []),
2091
+ ([], [1]),
2092
+ ([], [], []),
2093
+ ([3]),
2094
+ ([2, 1]),
2095
+ ([1, 1, 1]),
2096
+ ([2], []),
2097
+ ([1, 1], []),
2098
+ ([1], [1]),
2099
+ ([], [2]),
2100
+ ([], [1, 1]),
2101
+ ([1], [], []),
2102
+ ([], [1], []),
2103
+ ([], [], [1]),
2104
+ ([], [], [], [])]
2105
+ """
2106
+ for size in NN:
2107
+ for level in range(size+1):
2108
+ for mu in PartitionTuples_level_size(level+1,size-level):
2109
+ yield self._element_constructor_(mu)
2110
+
2111
+ def _an_element_(self):
2112
+ """
2113
+ Return a generic element.
2114
+
2115
+ EXAMPLES::
2116
+
2117
+ sage: PartitionTuples().an_element()
2118
+ ([1, 1, 1, 1], [2, 1, 1], [3, 1], [4])
2119
+ """
2120
+ return self.element_class(self,([1,1,1,1],[2,1,1],[3,1],[4]))
2121
+
2122
+
2123
+ class PartitionTuples_level(PartitionTuples):
2124
+ """
2125
+ Class of partition tuples of a fixed level, but summing to an arbitrary
2126
+ integer.
2127
+ """
2128
+
2129
+ def __init__(self, level, category=None):
2130
+ r"""
2131
+ Initialize this class.
2132
+
2133
+ EXAMPLES::
2134
+
2135
+ sage: PartitionTuples(4)
2136
+ Partition tuples of level 4
2137
+ sage: PartitionTuples(level=6)
2138
+ Partition tuples of level 6
2139
+ sage: TestSuite( PartitionTuples(level=4) ).run() # needs sage.libs.flint
2140
+ """
2141
+ if level not in NN:
2142
+ raise ValueError('level must be a nonnegative integer')
2143
+ if category is None:
2144
+ category = InfiniteEnumeratedSets()
2145
+ super().__init__(category=category)
2146
+ self._level = level
2147
+
2148
+ def _repr_(self):
2149
+ """
2150
+ Return a string representation of ``self``.
2151
+
2152
+ EXAMPLES::
2153
+
2154
+ sage: PartitionTuples(2)
2155
+ Partition tuples of level 2
2156
+ """
2157
+ return 'Partition tuples of level {}'.format(self._level)
2158
+
2159
+ def __contains__(self, mu):
2160
+ r"""
2161
+ Return ``True`` if `\mu` is in ``self``.
2162
+
2163
+ TESTS::
2164
+
2165
+ sage: PartitionTuple([[3,2],[2]]) in PartitionTuples(2)
2166
+ True
2167
+ sage: PartitionTuple([[3,2],[2]]) in PartitionTuples(level=2)
2168
+ True
2169
+ sage: PartitionTuple([[2,2,1],[2]]) in PartitionTuples(level=2)
2170
+ True
2171
+ sage: PartitionTuple([[2,2,1],[],[2]]) in PartitionTuples(level=2)
2172
+ False
2173
+ sage: all(mu in PartitionTuples(3) for mu in PartitionTuples(3,8)) # needs sage.libs.flint
2174
+ True
2175
+
2176
+ Check that :issue:`14145` is fixed::
2177
+
2178
+ sage: 1 in PartitionTuples(level=2)
2179
+ False
2180
+ """
2181
+ # Note that self._level > 1
2182
+ return PartitionTuples.__contains__(self, mu) and len(mu) == self._level
2183
+
2184
+ def __iter__(self):
2185
+ r"""
2186
+ Iterate through the infinite class of partition tuples of fixed level.
2187
+
2188
+ EXAMPLES::
2189
+
2190
+ sage: parts = PartitionTuples(3)
2191
+ sage: [parts[k] for k in range(20)] # needs sage.libs.flint
2192
+ [([], [], []),
2193
+ ([1], [], []),
2194
+ ([], [1], []),
2195
+ ([], [], [1]),
2196
+ ([2], [], []),
2197
+ ([1, 1], [], []),
2198
+ ([1], [1], []),
2199
+ ([1], [], [1]),
2200
+ ([], [2], []),
2201
+ ([], [1, 1], []),
2202
+ ([], [1], [1]),
2203
+ ([], [], [2]),
2204
+ ([], [], [1, 1]),
2205
+ ([3], [], []),
2206
+ ([2, 1], [], []),
2207
+ ([1, 1, 1], [], []),
2208
+ ([2], [1], []),
2209
+ ([1, 1], [1], []),
2210
+ ([2], [], [1]),
2211
+ ([1, 1], [], [1])]
2212
+ """
2213
+ for size in NN:
2214
+ for mu in PartitionTuples_level_size(self._level, size):
2215
+ yield self.element_class(self, list(mu))
2216
+
2217
+ def _an_element_(self):
2218
+ """
2219
+ Return a generic element.
2220
+
2221
+ EXAMPLES::
2222
+
2223
+ sage: PartitionTuples(level=4).an_element()
2224
+ ([], [1], [2], [3])
2225
+ """
2226
+ return self.element_class(self, tuple([l] for l in range(self.level())))
2227
+
2228
+
2229
+ class PartitionTuples_size(PartitionTuples):
2230
+ """
2231
+ Class of partition tuples of a fixed size, but arbitrary level.
2232
+ """
2233
+
2234
+ def __init__(self, size):
2235
+ r"""
2236
+ Initialize this class.
2237
+
2238
+ EXAMPLES::
2239
+
2240
+ sage: PartitionTuples(size=4)
2241
+ Partition tuples of size 4
2242
+ sage: PartitionTuples(size=6)
2243
+ Partition tuples of size 6
2244
+
2245
+ sage: TestSuite( PartitionTuples(size=6) ).run() # needs sage.libs.flint
2246
+ """
2247
+ if size not in NN:
2248
+ raise ValueError('size must be a nonnegative integer')
2249
+ super().__init__(category=InfiniteEnumeratedSets())
2250
+ self._size = size
2251
+
2252
+ def _repr_(self):
2253
+ """
2254
+ Return a string representation of ``self``.
2255
+
2256
+ EXAMPLES::
2257
+
2258
+ sage: PartitionTuples(size=4) # indirect doctest
2259
+ Partition tuples of size 4
2260
+ """
2261
+ return 'Partition tuples of size {}'.format(self._size)
2262
+
2263
+ def __contains__(self, mu):
2264
+ r"""
2265
+ Return ``True`` if `\mu` is in ``self``.
2266
+
2267
+ TESTS::
2268
+
2269
+ sage: PartitionTuple([[3,2],[2]]) in PartitionTuples(size=7)
2270
+ True
2271
+ sage: PartitionTuple([[3,2],[],[],[],[2]]) in PartitionTuples(size=7)
2272
+ True
2273
+ sage: PartitionTuple([[2,1],[],[1,1],[],[2]]) in PartitionTuples(size=7)
2274
+ True
2275
+ sage: PartitionTuple([[2,1],[],[1,1],[],[3]]) in PartitionTuples(size=7)
2276
+ False
2277
+ sage: all(mu in PartitionTuples(size=8) for mu in PartitionTuples(3,8)) # needs sage.libs.flint
2278
+ True
2279
+ sage: [3, 2, 1] in PartitionTuples(size=7)
2280
+ False
2281
+
2282
+ Check that :issue:`14145` is fixed::
2283
+
2284
+ sage: 1 in PartitionTuples(size=7)
2285
+ False
2286
+ """
2287
+ if mu in _Partitions:
2288
+ return self._size == sum(mu)
2289
+ return PartitionTuples.__contains__(self, mu) and self._size == sum(map(sum, mu))
2290
+
2291
+ def __iter__(self):
2292
+ r"""
2293
+ Iterate through the infinite class of partition tuples of a fixed size.
2294
+
2295
+ EXAMPLES::
2296
+
2297
+ sage: PartitionTuples(size=3)[:20] # needs sage.libs.flint
2298
+ [([3]),
2299
+ ([2, 1]),
2300
+ ([1, 1, 1]),
2301
+ ([3], []),
2302
+ ([2, 1], []),
2303
+ ([1, 1, 1], []),
2304
+ ([2], [1]),
2305
+ ([1, 1], [1]),
2306
+ ([1], [2]),
2307
+ ([1], [1, 1]),
2308
+ ([], [3]),
2309
+ ([], [2, 1]),
2310
+ ([], [1, 1, 1]),
2311
+ ([3], [], []),
2312
+ ([2, 1], [], []),
2313
+ ([1, 1, 1], [], []),
2314
+ ([2], [1], []),
2315
+ ([1, 1], [1], []),
2316
+ ([2], [], [1]),
2317
+ ([1, 1], [], [1])]
2318
+ """
2319
+ for level in NN:
2320
+ for mu in PartitionTuples_level_size(level, self._size):
2321
+ yield self.element_class(self, list(mu))
2322
+
2323
+ def _an_element_(self):
2324
+ """
2325
+ Return a generic element.
2326
+
2327
+ EXAMPLES::
2328
+
2329
+ sage: PartitionTuples(size=4).an_element()
2330
+ ([1], [1], [1], [1])
2331
+ """
2332
+ return self.element_class(self, tuple([1] for l in range(self._size)))
2333
+
2334
+
2335
+ class PartitionTuples_level_size(PartitionTuples):
2336
+ """
2337
+ Class of partition tuples with a fixed level and a fixed size.
2338
+ """
2339
+
2340
+ def __init__(self, level, size):
2341
+ r"""
2342
+ Initialize this class.
2343
+
2344
+ EXAMPLES::
2345
+
2346
+ sage: TestSuite( PartitionTuples(4,2) ).run() # needs sage.libs.flint sage.libs.pari
2347
+ sage: TestSuite( PartitionTuples(level=4, size=5) ).run() # needs sage.libs.flint sage.libs.pari
2348
+ """
2349
+ if not (level in NN and size in NN):
2350
+ raise ValueError('n and level must be nonnegative integers')
2351
+ super().__init__(category=FiniteEnumeratedSets())
2352
+ self._level = level
2353
+ self._size = size
2354
+
2355
+ def _repr_(self):
2356
+ """
2357
+ Return a string representation of ``self``.
2358
+
2359
+ EXAMPLES::
2360
+
2361
+ sage: PartitionTuples(4,2)
2362
+ Partition tuples of level 4 and size 2
2363
+ sage: PartitionTuples(size=2, level=4)
2364
+ Partition tuples of level 4 and size 2
2365
+ """
2366
+ return 'Partition tuples of level {} and size {}'.format(self._level, self._size)
2367
+
2368
+ def __contains__(self, mu):
2369
+ r"""
2370
+ Return ``True`` if ``mu`` is in ``self``.
2371
+
2372
+ TESTS::
2373
+
2374
+ sage: PartitionTuple([[3,2],[2]]) in PartitionTuples(2,7)
2375
+ True
2376
+ sage: PartitionTuple([[3,2],[],[],[],[2]]) in PartitionTuples(5,7)
2377
+ True
2378
+ sage: PartitionTuple([[2,1],[],[1,1],[],[2]]) in PartitionTuples(5,7)
2379
+ True
2380
+ sage: PartitionTuple([[2,1],[],[1,1],[],[3]]) in PartitionTuples(2,8)
2381
+ False
2382
+ sage: all(mu in PartitionTuples(3,8) for mu in PartitionTuples(3,8)) # needs sage.libs.flint
2383
+ True
2384
+
2385
+ Check that :issue:`14145` is fixed::
2386
+
2387
+ sage: 1 in PartitionTuples(5,7)
2388
+ False
2389
+ """
2390
+ if self._level == 1 and mu in _Partitions:
2391
+ return self._size == sum(mu)
2392
+ return (PartitionTuples.__contains__(self, mu)
2393
+ and self._level == len(mu)
2394
+ and self._size == sum(map(sum,mu)))
2395
+
2396
+ def __iter__(self):
2397
+ r"""
2398
+ Iterate through the finite class of partition tuples of a fixed level
2399
+ and a fixed size.
2400
+
2401
+ EXAMPLES::
2402
+
2403
+ sage: # needs sage.libs.flint
2404
+ sage: PartitionTuples(2,0).list() #indirect doctest
2405
+ [([], [])]
2406
+ sage: PartitionTuples(2,1).list() #indirect doctest
2407
+ [([1], []), ([], [1])]
2408
+ sage: PartitionTuples(2,2).list() #indirect doctest
2409
+ [([2], []), ([1, 1], []), ([1], [1]), ([], [2]), ([], [1, 1])]
2410
+ sage: PartitionTuples(3,2).list() #indirect doctest
2411
+ [([2], [], []),
2412
+ ([1, 1], [], []),
2413
+ ([1], [1], []),
2414
+ ([1], [], [1]),
2415
+ ([], [2], []),
2416
+ ([], [1, 1], []),
2417
+ ([], [1], [1]),
2418
+ ([], [], [2]),
2419
+ ([], [], [1, 1])]
2420
+ """
2421
+ p = [Partitions_n(i) for i in range(self._size+1)]
2422
+ for iv in IntegerVectors(self._size, self._level):
2423
+ for cp in itertools.product(*[p[i] for i in iv]):
2424
+ yield self._element_constructor_(cp)
2425
+
2426
+ def _an_element_(self):
2427
+ """
2428
+ Return a generic element.
2429
+
2430
+ EXAMPLES::
2431
+
2432
+ sage: PartitionTuples(level=4,size=4).an_element()
2433
+ ([1], [], [], [3])
2434
+ """
2435
+ mu = [[] for _ in itertools.repeat(None, self._level)]
2436
+ if self._size > 0:
2437
+ if self._level == 1:
2438
+ mu = [self._size-1,1]
2439
+ else:
2440
+ mu[0] = [1]
2441
+ mu[-1] = [self._size-1]
2442
+ return self.element_class(self, mu)
2443
+
2444
+ def cardinality(self):
2445
+ r"""
2446
+ Return the number of ``level``-tuples of partitions of size ``n``.
2447
+
2448
+ Wraps a pari function call using :pari:`eta`.
2449
+
2450
+ EXAMPLES::
2451
+
2452
+ sage: PartitionTuples(2,3).cardinality() # needs sage.libs.pari
2453
+ 10
2454
+ sage: PartitionTuples(2,8).cardinality() # needs sage.libs.pari
2455
+ 185
2456
+
2457
+ TESTS:
2458
+
2459
+ The following calls used to fail (:issue:`11476`)::
2460
+
2461
+ sage: # needs sage.libs.pari
2462
+ sage: PartitionTuples(17,2).cardinality()
2463
+ 170
2464
+ sage: PartitionTuples(2,17).cardinality()
2465
+ 8470
2466
+ sage: PartitionTuples(100,13).cardinality()
2467
+ 110320020147886800
2468
+ sage: PartitionTuples(13,90).cardinality()
2469
+ 91506473741200186152352843611
2470
+
2471
+ These answers were checked against Gap4 (the last of which takes an
2472
+ awful long time for gap to compute).
2473
+ """
2474
+ eta = pari(f'Ser(x,x,{self.size()})').eta()
2475
+ return ZZ((1 / eta**self.level()).polcoef(self.size(), pari('x')))
2476
+
2477
+ def __setstate__(self, state):
2478
+ r"""
2479
+ In order to maintain backwards compatibility and be able to unpickle a
2480
+ old pickle from PartitionTuples_nk we have to override the default
2481
+ ``__setstate__``.
2482
+
2483
+ TESTS::
2484
+
2485
+ sage: loads(b"x\x9cM\x90\xcdN\xc30\x0c\x80\xd5\xc1\x06\xeb\x80\xf1{\xe0\r\xe0\xd2\x0b\x07\x1e\x02)B\x88\x9c-7\xb5\xba\xa8MR')\x12\x07$8p\xe0\xadq\x996q\xb1b\xfb\xb3\xf59\x9f3\x93\xb0\xa5\xca\x04W[\x8f\xb9\x1a0f\x9bm\xf0\xe5\xf3\xee\xf5:\x0e=%\xf0]\xc9\xc5\xfd\x17\xcf>\xf8\xe0N_\x83\xf5\xd2\xc5\x1e\xd0L\x10\xf46e>T\xba\x04r55\x8d\xf5-\xcf\x95p&\xf87\x8a\x19\x1c\xe5Mh\xc0\xa3#^(\xbd\x00\xd3`F>Rz\t\x063\xb5!\xbe\xf3\xf1\xd4\x98\x90\xc4K\xa5\x0b\xbf\xb5\x8b\xb2,U\xd6\x0bD\xb1t\xd8\x11\xec\x12.u\xf1\xf0\xfd\xc2+\xbd\x82\x96<E\xcc!&>Qz\x0e5&\xe2S\xa5\xd70X\xd3\xf5\x04\xe2\x91\xc4\x95\xcf\x9e\n\x11\xa3\x9e\x1c\xf9<\t\xa6\x1cG#\x83\xbcV\xfaf\x7f\xd9\xce\xfc\xef\xb4s\xa5o\xf7#\x13\x01\x03\xa6$!J\x81/~t\xd1m\xc4\xe5Q\\.\xff\xfd\x8e\t\x14\rmW\\\xa9\xb1\xae~\x01/\x8f\x85\x02")
2486
+ Partition tuples of level 7 and size 3
2487
+ sage: loads(dumps( PartitionTuples(7,3) )) # indirect doctest for unpickling a Tableau element
2488
+ Partition tuples of level 7 and size 3
2489
+ """
2490
+ if isinstance(state, dict): # for old pickles from Tableau_class
2491
+ parts = PartitionTuples(state['k'], state['n'])
2492
+ self.__class__ = parts.__class__
2493
+ self.__dict__ = parts.__dict__
2494
+ else:
2495
+ super().__setstate__(state)
2496
+
2497
+ ###############################################################################
2498
+ # Regular partition tuples
2499
+
2500
+
2501
+ class RegularPartitionTuples(PartitionTuples):
2502
+ r"""
2503
+ Abstract base class for `\ell`-regular partition tuples.
2504
+ """
2505
+
2506
+ def __init__(self, regular, **kwds):
2507
+ """
2508
+ Initialize ``self``.
2509
+
2510
+ TESTS::
2511
+
2512
+ sage: RPT = PartitionTuples(regular=3)
2513
+ sage: TestSuite(RPT).run() # needs sage.libs.flint
2514
+ """
2515
+ if regular not in ZZ or regular < 1:
2516
+ raise ValueError("regular must be an integer greater than 1")
2517
+ self._ell = regular
2518
+ PartitionTuples.__init__(self, **kwds)
2519
+
2520
+ def __contains__(self, mu):
2521
+ r"""
2522
+ Check if ``mu`` is an `\ell`-regular partition tuple.
2523
+
2524
+ TESTS::
2525
+
2526
+ sage: RPT = PartitionTuples(regular=2)
2527
+ sage: [[11,1], [2]] in RPT
2528
+ True
2529
+ sage: Partition([4,1]) in RPT
2530
+ True
2531
+ sage: [5,4,3,2,1] in RPT
2532
+ True
2533
+ sage: [[6,3,1], [], [], [3,1], [1], [1], [1]] in RPT
2534
+ True
2535
+ sage: [[10], [1], [1,1], [4,2]] in RPT
2536
+ False
2537
+ sage: [[5,2], [17, 1], [], [3,3,1], [1,1]] in RPT
2538
+ False
2539
+ sage: RPT = PartitionTuples(4,2,3)
2540
+ sage: elt = RPT([[1], [], [], [1]])
2541
+ sage: elt in RPT
2542
+ True
2543
+ """
2544
+ if not PartitionTuples.__contains__(self, mu):
2545
+ return False
2546
+ if isinstance(mu, Partition):
2547
+ return max(mu.to_exp() + [0]) < self._ell
2548
+ if isinstance(mu, PartitionTuple):
2549
+ return all(max(nu.to_exp() + [0]) < self._ell for nu in mu)
2550
+ if not mu:
2551
+ return True
2552
+ if mu in _Partitions:
2553
+ return all(mu.count(i) < self._ell for i in set(mu) if i > 0)
2554
+ return all(list(nu).count(i) < self._ell for nu in mu for i in set(nu) if i > 0)
2555
+
2556
+ def _an_element_(self):
2557
+ """
2558
+ Return a generic element.
2559
+
2560
+ EXAMPLES::
2561
+
2562
+ sage: PartitionTuples(regular=2).an_element()
2563
+ ([1], [], [], [2])
2564
+ """
2565
+ if self._level is None:
2566
+ lvl = 4
2567
+ else:
2568
+ lvl = self._level
2569
+ if self._size is None:
2570
+ size = 3
2571
+ else:
2572
+ size = self._size
2573
+ elt = RegularPartitionTuples_level_size(lvl, size, self._ell).an_element()
2574
+ return self.element_class(self, list(elt))
2575
+
2576
+
2577
+ class RegularPartitionTuples_all(RegularPartitionTuples):
2578
+ r"""
2579
+ Class of `\ell`-regular partition tuples.
2580
+ """
2581
+
2582
+ def __init__(self, regular):
2583
+ r"""
2584
+ Initialize ``self``.
2585
+
2586
+ EXAMPLES::
2587
+
2588
+ sage: RPT = PartitionTuples(regular=3)
2589
+ sage: TestSuite(RPT).run() # needs sage.libs.flint
2590
+ """
2591
+ RegularPartitionTuples.__init__(self, regular, category=InfiniteEnumeratedSets())
2592
+
2593
+ def _repr_(self):
2594
+ """
2595
+ Return a string representation of ``self``.
2596
+
2597
+ EXAMPLES::
2598
+
2599
+ sage: PartitionTuples(regular=3)
2600
+ 3-Regular partition tuples
2601
+ """
2602
+ return '{}-Regular partition tuples'.format(self._ell)
2603
+
2604
+ def __iter__(self):
2605
+ r"""
2606
+ Iterate through the class of `\ell`-regular partition tuples.
2607
+
2608
+ EXAMPLES::
2609
+
2610
+ sage: PartitionTuples(regular=2)[:20] # needs sage.libs.flint
2611
+ [([]),
2612
+ ([], []),
2613
+ ([1]),
2614
+ ([], [], []),
2615
+ ([1], []),
2616
+ ([], [1]),
2617
+ ([2]),
2618
+ ([], [], [], []),
2619
+ ([1], [], []),
2620
+ ([], [1], []),
2621
+ ([], [], [1]),
2622
+ ([2], []),
2623
+ ([1], [1]),
2624
+ ([], [2]),
2625
+ ([3]),
2626
+ ([2, 1]),
2627
+ ([], [], [], [], []),
2628
+ ([1], [], [], []),
2629
+ ([], [1], [], []),
2630
+ ([], [], [1], [])]
2631
+ """
2632
+ for N in NN:
2633
+ for size in range(N+1):
2634
+ for mu in RegularPartitionTuples_level_size(N-size+1, size, self._ell):
2635
+ yield self.element_class(self, list(mu))
2636
+
2637
+
2638
+ class RegularPartitionTuples_level(PartitionTuples_level):
2639
+ r"""
2640
+ Regular Partition tuples of a fixed level.
2641
+
2642
+ INPUT:
2643
+
2644
+ - ``level`` -- nonnegative integer; the level
2645
+ - ``regular`` -- positive integer or a tuple of nonnegative
2646
+ integers; if an integer, the highest multiplicity an entry may
2647
+ have in a component plus `1` with `0` representing `\infty`-regular
2648
+ (equivalently, partitions without restrictions)
2649
+
2650
+ ``regular`` is a tuple of integers `(\ell_1, \ldots, \ell_k)` that
2651
+ specifies partition tuples `\mu` such that `\mu_i` is `\ell_i`-regular.
2652
+ If ``regular`` is an integer `\ell`, then we set `\ell_i = \ell` for
2653
+ all `i`.
2654
+
2655
+ EXAMPLES::
2656
+
2657
+ sage: RPT = PartitionTuples(level=4, regular=(2,3,0,2))
2658
+ sage: RPT[:24] # needs sage.libs.flint
2659
+ [([], [], [], []),
2660
+ ([1], [], [], []),
2661
+ ([], [1], [], []),
2662
+ ([], [], [1], []),
2663
+ ([], [], [], [1]),
2664
+ ([2], [], [], []),
2665
+ ([1], [1], [], []),
2666
+ ([1], [], [1], []),
2667
+ ([1], [], [], [1]),
2668
+ ([], [2], [], []),
2669
+ ([], [1, 1], [], []),
2670
+ ([], [1], [1], []),
2671
+ ([], [1], [], [1]),
2672
+ ([], [], [2], []),
2673
+ ([], [], [1, 1], []),
2674
+ ([], [], [1], [1]),
2675
+ ([], [], [], [2]),
2676
+ ([3], [], [], []),
2677
+ ([2, 1], [], [], []),
2678
+ ([2], [1], [], []),
2679
+ ([2], [], [1], []),
2680
+ ([2], [], [], [1]),
2681
+ ([1], [2], [], []),
2682
+ ([1], [1, 1], [], [])]
2683
+ sage: [[1,1],[3],[5,5,5],[7,2]] in RPT
2684
+ False
2685
+ sage: [[3,1],[3],[5,5,5],[7,2]] in RPT
2686
+ True
2687
+ sage: [[3,1],[3],[5,5,5]] in RPT
2688
+ False
2689
+ """
2690
+
2691
+ def __init__(self, level, regular):
2692
+ r"""
2693
+ Initialize ``self``.
2694
+
2695
+ TESTS::
2696
+
2697
+ sage: RPT = PartitionTuples(level=2, regular=(0,0))
2698
+ sage: RPT.category()
2699
+ Category of infinite enumerated sets
2700
+ sage: RPT = PartitionTuples(level=4, regular=3)
2701
+ sage: TestSuite(RPT).run() # needs sage.libs.flint
2702
+ """
2703
+ if level not in NN:
2704
+ raise ValueError('level must be a nonnegative integer')
2705
+ if not isinstance(regular, tuple):
2706
+ # This should not happen if called from RegularPartitionTuples
2707
+ regular = (regular,) * level
2708
+ if any(r != 1 for r in regular):
2709
+ category = InfiniteEnumeratedSets()
2710
+ else:
2711
+ category = FiniteEnumeratedSets()
2712
+ if any(r not in NN for r in regular):
2713
+ raise ValueError('regular must be a tuple of nonnegative integers')
2714
+ if len(regular) != level:
2715
+ raise ValueError("regular must be a tuple with length {}".format(level))
2716
+ PartitionTuples_level.__init__(self, level, category=category)
2717
+ self._ell = regular
2718
+
2719
+ def _repr_(self):
2720
+ """
2721
+ Return a string representation of ``self``.
2722
+
2723
+ EXAMPLES::
2724
+
2725
+ sage: PartitionTuples(level=4, regular=3)
2726
+ 3-Regular partition tuples of level 4
2727
+ sage: PartitionTuples(level=4, regular=(2,3,0,2))
2728
+ (2, 3, 0, 2)-Regular partition tuples of level 4
2729
+ """
2730
+ if self._ell[1:] == self._ell[:-1]:
2731
+ return '{}-Regular partition tuples of level {}'.format(self._ell[0],
2732
+ self._level)
2733
+ return '{}-Regular partition tuples of level {}'.format(self._ell,
2734
+ self._level)
2735
+
2736
+ def __contains__(self, mu):
2737
+ r"""
2738
+ Return ``True`` if ``mu`` is in ``self``.
2739
+
2740
+ TESTS::
2741
+
2742
+ sage: RPT = PartitionTuples(level=4, regular=2)
2743
+ sage: [[4,2,1], [], [2], [2]] in RPT
2744
+ True
2745
+ sage: [[10], [1], [1,1], [4,2]] in RPT
2746
+ False
2747
+ sage: [[5,2], [], [3,3,1], [1,1]] in RPT
2748
+ False
2749
+ sage: [4, 3, 2] in RPT
2750
+ False
2751
+
2752
+ sage: RPT = PartitionTuples(level=3, regular=(2,1,4))
2753
+ sage: [[4], [2], [5]] in RPT
2754
+ False
2755
+ sage: [[4], [], [5]] in RPT
2756
+ True
2757
+ sage: [[4,3], [], [5]] in RPT
2758
+ True
2759
+ sage: [[4,4], [], [5]] in RPT
2760
+ False
2761
+ sage: [[4,3], [5]] in RPT
2762
+ False
2763
+ sage: [5, 4, 3] in RPT
2764
+ False
2765
+ sage: [] in RPT
2766
+ False
2767
+ sage: [[], [], []] in RPT
2768
+ True
2769
+ sage: [[], [], [], [2]] in RPT
2770
+ False
2771
+
2772
+ sage: from sage.combinat.partition_tuple import RegularPartitionTuples_level
2773
+ sage: RPT = RegularPartitionTuples_level(1, (3,)); RPT
2774
+ 3-Regular partition tuples of level 1
2775
+ sage: [[2,2]] in RPT
2776
+ True
2777
+ sage: [[2,2,2]] in RPT
2778
+ False
2779
+ """
2780
+ if self._level == 1:
2781
+ try:
2782
+ if mu[0] in ZZ:
2783
+ return mu in RegularPartitions_all(self._ell[0])
2784
+ except (TypeError, ValueError):
2785
+ return False
2786
+ return mu[0] in RegularPartitions_all(self._ell[0])
2787
+ if mu not in PartitionTuples_level(self._level):
2788
+ return False
2789
+ if isinstance(mu, Partition): # it is level 1
2790
+ return False
2791
+ if isinstance(mu, PartitionTuple):
2792
+ return all(max(p.to_exp() + [0]) < ell for p, ell in zip(mu, self._ell)
2793
+ if ell > 0)
2794
+ return all(p in RegularPartitions_all(ell) for p, ell in zip(mu, self._ell)
2795
+ if ell > 0)
2796
+
2797
+ def __iter__(self):
2798
+ r"""
2799
+ Iterate through the class of `\ell`-regular partition tuples
2800
+ of a fixed level.
2801
+
2802
+ EXAMPLES::
2803
+
2804
+ sage: PartitionTuples(level=3, regular=(2,1,4))[:24] # needs sage.libs.flint
2805
+ [([], [], []),
2806
+ ([1], [], []),
2807
+ ([], [], [1]),
2808
+ ([2], [], []),
2809
+ ([1], [], [1]),
2810
+ ([], [], [2]),
2811
+ ([], [], [1, 1]),
2812
+ ([3], [], []),
2813
+ ([2, 1], [], []),
2814
+ ([2], [], [1]),
2815
+ ([1], [], [2]),
2816
+ ([1], [], [1, 1]),
2817
+ ([], [], [3]),
2818
+ ([], [], [2, 1]),
2819
+ ([], [], [1, 1, 1]),
2820
+ ([4], [], []),
2821
+ ([3, 1], [], []),
2822
+ ([3], [], [1]),
2823
+ ([2, 1], [], [1]),
2824
+ ([2], [], [2]),
2825
+ ([2], [], [1, 1]),
2826
+ ([1], [], [3]),
2827
+ ([1], [], [2, 1]),
2828
+ ([1], [], [1, 1, 1])]
2829
+ sage: PartitionTuples(level=4, regular=2)[:20] # needs sage.libs.flint
2830
+ [([], [], [], []),
2831
+ ([1], [], [], []),
2832
+ ([], [1], [], []),
2833
+ ([], [], [1], []),
2834
+ ([], [], [], [1]),
2835
+ ([2], [], [], []),
2836
+ ([1], [1], [], []),
2837
+ ([1], [], [1], []),
2838
+ ([1], [], [], [1]),
2839
+ ([], [2], [], []),
2840
+ ([], [1], [1], []),
2841
+ ([], [1], [], [1]),
2842
+ ([], [], [2], []),
2843
+ ([], [], [1], [1]),
2844
+ ([], [], [], [2]),
2845
+ ([3], [], [], []),
2846
+ ([2, 1], [], [], []),
2847
+ ([2], [1], [], []),
2848
+ ([2], [], [1], []),
2849
+ ([2], [], [], [1])]
2850
+ """
2851
+ for size in NN:
2852
+ for mu in RegularPartitionTuples_level_size(self._level, size, self._ell):
2853
+ yield self.element_class(self, list(mu))
2854
+
2855
+
2856
+ class RegularPartitionTuples_size(RegularPartitionTuples):
2857
+ r"""
2858
+ Class of `\ell`-regular partition tuples with a fixed size.
2859
+ """
2860
+
2861
+ def __init__(self, size, regular):
2862
+ r"""
2863
+ Initialize ``self``.
2864
+
2865
+ EXAMPLES::
2866
+
2867
+ sage: RPT = PartitionTuples(size=4, regular=3)
2868
+ sage: TestSuite(RPT).run() # needs sage.libs.flint
2869
+ """
2870
+ if size not in NN:
2871
+ raise ValueError('size must be a nonnegative integer')
2872
+ RegularPartitionTuples.__init__(self, regular, category=InfiniteEnumeratedSets())
2873
+ self._size = size
2874
+
2875
+ def _repr_(self):
2876
+ """
2877
+ Return a string representation of ``self``.
2878
+
2879
+ EXAMPLES::
2880
+
2881
+ sage: PartitionTuples(size=4, regular=3)
2882
+ 3-Regular partition tuples of size 4
2883
+ """
2884
+ return '{}-Regular partition tuples of size {}'.format(self._ell, self._size)
2885
+
2886
+ def __contains__(self, mu):
2887
+ r"""
2888
+ Return ``True`` if ``mu`` is in ``self``.
2889
+
2890
+ TESTS::
2891
+
2892
+ sage: RPT = PartitionTuples(size=4, regular=2)
2893
+ sage: [[2, 1], [1]] in RPT
2894
+ True
2895
+ sage: [3, 1] in RPT
2896
+ True
2897
+ sage: [[1], [], [], [2,1]] in RPT
2898
+ True
2899
+ sage: [[1], [1], [1], [1]] in RPT
2900
+ True
2901
+ sage: [[1], [1,1,1]] in RPT
2902
+ False
2903
+ sage: [[2,1,1]] in RPT
2904
+ False
2905
+ sage: [2,1,1] in RPT
2906
+ False
2907
+ sage: RPT = PartitionTuples(size=7, regular=2)
2908
+ sage: [[], [3,2,2,1], [1], [1]] in RPT
2909
+ False
2910
+ sage: RPT = PartitionTuples(size=9, regular=2)
2911
+ sage: [4, 3, 2] in RPT
2912
+ True
2913
+ """
2914
+ return ((mu in RegularPartitions_all(self._ell)
2915
+ and self._size == sum(mu))
2916
+ or (RegularPartitionTuples.__contains__(self, mu)
2917
+ and self._size == sum(map(sum, mu))))
2918
+
2919
+ def __iter__(self):
2920
+ r"""
2921
+ Iterate through the class of `\ell`-regular partition tuples
2922
+ of a fixed size.
2923
+
2924
+ EXAMPLES::
2925
+
2926
+ sage: PartitionTuples(size=4, regular=2)[:10] # needs sage.libs.flint
2927
+ [([4]),
2928
+ ([3, 1]),
2929
+ ([4], []),
2930
+ ([3, 1], []),
2931
+ ([3], [1]),
2932
+ ([2, 1], [1]),
2933
+ ([2], [2]),
2934
+ ([1], [3]),
2935
+ ([1], [2, 1]),
2936
+ ([], [4])]
2937
+ """
2938
+ for level in PositiveIntegers():
2939
+ for mu in RegularPartitionTuples_level_size(level, self._size, self._ell):
2940
+ yield self.element_class(self, list(mu))
2941
+
2942
+
2943
+ class RegularPartitionTuples_level_size(PartitionTuples_level_size):
2944
+ r"""
2945
+ Class of `\ell`-regular partition tuples with a fixed level and
2946
+ a fixed size.
2947
+
2948
+ INPUT:
2949
+
2950
+ - ``level`` -- nonnegative integer; the level
2951
+ - ``size`` -- nonnegative integer; the size
2952
+ - ``regular`` -- positive integer or a tuple of nonnegative
2953
+ integers; if an integer, the highest multiplicity an entry may
2954
+ have in a component plus `1` with `0` representing `\infty`-regular
2955
+ (equivalently, partitions without restrictions)
2956
+
2957
+ ``regular`` is a tuple of integers `(\ell_1, \ldots, \ell_k)` that
2958
+ specifies partition tuples `\mu` such that `\mu_i` is `\ell_i`-regular.
2959
+ If ``regular`` is an integer `\ell`, then we set `\ell_i = \ell` for
2960
+ all `i`.
2961
+
2962
+ EXAMPLES::
2963
+
2964
+ sage: PartitionTuples(level=3, size=7, regular=(2,1,3))[0:24] # needs sage.libs.flint
2965
+ [([7], [], []),
2966
+ ([6, 1], [], []),
2967
+ ([5, 2], [], []),
2968
+ ([4, 3], [], []),
2969
+ ([4, 2, 1], [], []),
2970
+ ([6], [], [1]),
2971
+ ([5, 1], [], [1]),
2972
+ ([4, 2], [], [1]),
2973
+ ([3, 2, 1], [], [1]),
2974
+ ([5], [], [2]),
2975
+ ([5], [], [1, 1]),
2976
+ ([4, 1], [], [2]),
2977
+ ([4, 1], [], [1, 1]),
2978
+ ([3, 2], [], [2]),
2979
+ ([3, 2], [], [1, 1]),
2980
+ ([4], [], [3]),
2981
+ ([4], [], [2, 1]),
2982
+ ([3, 1], [], [3]),
2983
+ ([3, 1], [], [2, 1]),
2984
+ ([3], [], [4]),
2985
+ ([3], [], [3, 1]),
2986
+ ([3], [], [2, 2]),
2987
+ ([3], [], [2, 1, 1]),
2988
+ ([2, 1], [], [4])]
2989
+ """
2990
+
2991
+ def __init__(self, level, size, regular):
2992
+ r"""
2993
+ Initialize ``self``.
2994
+
2995
+ TESTS::
2996
+
2997
+ sage: RPT = PartitionTuples(4,2,3)
2998
+ sage: TestSuite(RPT).run() # needs sage.libs.flint sage.libs.pari
2999
+ """
3000
+ if size not in NN:
3001
+ raise ValueError('size must be a nonnegative integer')
3002
+ if not (level in ZZ and level > 0):
3003
+ raise ValueError('level must be a positive integer')
3004
+ if not isinstance(regular, tuple):
3005
+ # This should not happen if called from RegularPartitionTuples
3006
+ regular = (regular,) * level
3007
+ if len(regular) != level:
3008
+ raise ValueError(f'regular must be a list with length {level}')
3009
+ if any(i not in NN for i in regular):
3010
+ raise ValueError('regular must be a list of nonnegative integers')
3011
+ PartitionTuples_level_size.__init__(self, level, size)
3012
+ self._ell = regular
3013
+
3014
+ def _repr_(self):
3015
+ """
3016
+ Return a string representation of ``self``.
3017
+
3018
+ EXAMPLES::
3019
+
3020
+ sage: PartitionTuples(level=3, size=7, regular=(2,1,4))
3021
+ (2, 1, 4)-Regular partition tuples of level 3 and size 7
3022
+ sage: PartitionTuples(4,2,3)
3023
+ 3-Regular partition tuples of level 4 and size 2
3024
+ sage: PartitionTuples(size=2, level=4, regular=3)
3025
+ 3-Regular partition tuples of level 4 and size 2
3026
+ """
3027
+ if self._ell[1:] == self._ell[:-1]:
3028
+ return '{}-Regular partition tuples of level {} and size {}'.format(
3029
+ self._ell[0], self._level, self._size)
3030
+ return '{}-Regular partition tuples of level {} and size {}'.format(
3031
+ self._ell, self._level, self._size)
3032
+
3033
+ def __contains__(self, mu):
3034
+ r"""
3035
+ Return ``True`` if `\mu` is in ``self``.
3036
+
3037
+ TESTS::
3038
+
3039
+ sage: RPT = PartitionTuples(level=3, size=7, regular=(2,1,4))
3040
+ sage: RPT
3041
+ (2, 1, 4)-Regular partition tuples of level 3 and size 7
3042
+ sage: [[3,1],[],[3]] in RPT
3043
+ True
3044
+ sage: [[3],[1],[3]] in RPT
3045
+ False
3046
+ sage: [[3,2],[],[3]] in RPT
3047
+ False
3048
+ sage: [[3,3],[],[1]] in RPT
3049
+ False
3050
+ sage: RPT = PartitionTuples(4,3,2)
3051
+ sage: [[], [], [2], [1]] in RPT
3052
+ True
3053
+ sage: [[1], [1], [], [1]] in RPT
3054
+ True
3055
+ sage: [[1,1,1], [], [], []] in RPT
3056
+ False
3057
+ sage: RPT = PartitionTuples(9, 3, 2)
3058
+ sage: [4, 3, 2] in RPT
3059
+ False
3060
+ """
3061
+ if mu not in RegularPartitionTuples_level(self._level, self._ell):
3062
+ return False
3063
+ return self._size == sum(map(sum, mu))
3064
+
3065
+ def __iter__(self):
3066
+ r"""
3067
+ Iterate through the finite class of `\ell`-regular partition tuples
3068
+ of a fixed level and a fixed size.
3069
+
3070
+ EXAMPLES::
3071
+
3072
+ sage: list(PartitionTuples(3,3,2)) # needs sage.libs.pari
3073
+ [([3], [], []),
3074
+ ([2, 1], [], []),
3075
+ ([2], [1], []),
3076
+ ([2], [], [1]),
3077
+ ([1], [2], []),
3078
+ ([1], [1], [1]),
3079
+ ([1], [], [2]),
3080
+ ([], [3], []),
3081
+ ([], [2, 1], []),
3082
+ ([], [2], [1]),
3083
+ ([], [1], [2]),
3084
+ ([], [], [3]),
3085
+ ([], [], [2, 1])]
3086
+ """
3087
+ for iv in IntegerVectors(self._size, self._level):
3088
+ p = [RegularPartitions_n(v, ell) if ell > 0 else Partitions_n(v)
3089
+ for v, ell in zip(iv, self._ell)]
3090
+ for cp in itertools.product(*[p[i] for i in range(self._level)]):
3091
+ yield self._element_constructor_(cp)
3092
+
3093
+ def _an_element_(self):
3094
+ """
3095
+ Return a generic element.
3096
+
3097
+ EXAMPLES::
3098
+
3099
+ sage: PartitionTuples(level=4, size=4, regular=3).an_element()
3100
+ ([1], [], [], [3])
3101
+ """
3102
+ mu = [[] for _ in itertools.repeat(None, self._level)]
3103
+ if self._size > 0:
3104
+ if self._level == 1:
3105
+ mu = [[self._size - 1, 1]]
3106
+ else:
3107
+ mu[0] = [1]
3108
+ mu[-1] = [self._size - 1]
3109
+ return self.element_class(self, mu)
3110
+
3111
+
3112
+ from sage.misc.persist import register_unpickle_override
3113
+
3114
+ register_unpickle_override('sage.combinat.partition', 'PartitionTuples_nk', PartitionTuples_level_size)