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,1982 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ # sage.doctest: needs sage.combinat sage.modules
3
+ r"""
4
+ Kleshchev partitions
5
+ ====================
6
+
7
+ A partition (tuple) `\mu` is Kleshchev if it can be recursively
8
+ obtained by adding a sequence of good nodes to the empty
9
+ :class:`PartitionTuple` of the same :meth:`~PartitionTuple.level`
10
+ and *multicharge*. In this way, the set of Kleshchev multipartitions becomes
11
+ a realization of a Kashiwara crystal :mod:`sage.combinat.crystals.crystals`
12
+ for a irreducible integral highest weight representation of
13
+ `U_q(\widehat{\mathfrak{sl}}_e)`.
14
+
15
+ The Kleshchev multipartitions first appeared in the work of Ariki and Mathas
16
+ [AM2000]_ where it was shown that they index the irreducible representations
17
+ of the cyclotomic Hecke algebras of type `A` [AK1994]_. Soon afterwards Ariki
18
+ [Ariki2001]_ showed that the set of Kleshchev multipartitions naturally label
19
+ the irreducible representations of these algebras. As a far reaching
20
+ generalization of these ideas the Ariki-Brundan-Kleshchev categorification
21
+ theorem [Ariki1996]_ [BK2009]_ says that these algebras categorify the
22
+ irreducible integral highest weight representations of the quantum group
23
+ `U_q(\widehat{\mathfrak{sl}}_e)` of the affine special linear group. Under
24
+ this categorification, `q` corresponds to the grading shift on the
25
+ cyclotomic Hecke algebras, where the grading from the Brundan-Kleshchev
26
+ graded isomorphism theorem to the *KLR algebras* of type `A` [BK2009]_.
27
+
28
+ The group algebras of the symmetric group in characteristic `p` are an
29
+ important special case of the cyclotomic Hecke algebras of type `A`.
30
+ In this case, depending on your prefer convention, the set of Kleshchev
31
+ partitions is the set of *`p`-regular* or *`p`-restricted*
32
+ :class:`~sage.combinat.partition.Partitions`. In this case, Kleshchev
33
+ [Kle1995]_ proved that the *modular branching rules* were given by adding
34
+ and removing *good nodes*; see :meth:`~KleshchevPartition.good_cells`.
35
+ Lascoux, Leclerc and Thibon [LLT1996]_ noticed that Kleshchev's branching
36
+ rules coincided with Kashiwara's crystal operators for the fundamental
37
+ representation of `L(\Lambda_0)` of `U_q(\widehat{\mathfrak{sl}}_p)`
38
+ and their celebrated *LLT conjecture* said that decomposition matrices of
39
+ the :class:`sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra` of
40
+ the symmetric group should be computable using the canonical basis of
41
+ `L(\Lambda_0)`. This was proved and generalised to all cyclotomic Hecke
42
+ algebras of type `A` by Ariki [Ariki1996]_ and then further generalized
43
+ to the graded setting by Brundan and Kleshchev [BK2009]_.
44
+
45
+ The main class for accessing Kleshchev partition (tuples) is
46
+ :class:`~KleshchevPartitions`. Unfortunately, just as with the
47
+ symmetric group, different authors use different conventions when
48
+ defining Kleshchev partitions, which depends on whether you read
49
+ components from left to right, or right to left, and whether you
50
+ read the nodes in the partition in each component from top to bottom
51
+ or bottom to top. The :class:`~KleshchevPartitions` class supports
52
+ these four different conventions::
53
+
54
+ sage: KleshchevPartitions(2, [0,0], size=2, convention='left regular')[:]
55
+ [([1], [1]), ([2], [])]
56
+ sage: KleshchevPartitions(2, [0,0], size=2, convention='left restricted')[:]
57
+ [([1], [1]), ([], [1, 1])]
58
+ sage: KleshchevPartitions(2, [0,0], size=2, convention='right regular')[:]
59
+ [([1], [1]), ([], [2])]
60
+ sage: KleshchevPartitions(2, [0,0], size=2, convention='right restricted')[:]
61
+ [([1], [1]), ([1, 1], [])]
62
+
63
+ By default, the ``left restricted`` convention is used. As a shorthand,
64
+ ``LG``, ``LS``, ``RG`` and ``RS``, respectively, can be used to specify the
65
+ ``convention`` With the ``left`` convention the partition tuples should be
66
+ ordered with the most dominant partitions in the partition tuple on the left
67
+ and with the ``right`` convention the most dominant partition is on the right.
68
+
69
+ The :class:`~KleshchevPartitions` class can automatically convert between
70
+ these four different conventions::
71
+
72
+ sage: KPlg = KleshchevPartitions(2, [0,0], size=2, convention='left regular')
73
+ sage: KPls = KleshchevPartitions(2, [0,0], size=2, convention='left restricted')
74
+ sage: [KPlg(mu) for mu in KPls] # indirect doc test
75
+ [([1], [1]), ([2], [])]
76
+
77
+ AUTHORS:
78
+
79
+ - Andrew Mathas and Travis Scrimshaw (2018-05-1): Initial version
80
+ """
81
+
82
+ from .partition import Partition, Partitions
83
+ from .partition_tuple import PartitionTuple, PartitionTuples
84
+
85
+ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
86
+ from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
87
+ from sage.misc.lazy_attribute import lazy_attribute
88
+ from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
89
+ from sage.rings.integer_ring import ZZ
90
+ from sage.rings.semirings.non_negative_integer_semiring import NN
91
+ from sage.cpython.getattr import getattr_from_other_class
92
+
93
+ from collections import defaultdict
94
+
95
+ #--------------------------------------------------
96
+ # Kleshchev partition - element classes
97
+ #--------------------------------------------------
98
+
99
+
100
+ class KleshchevPartition(Partition):
101
+ r"""
102
+ Abstract base class for Kleshchev partitions. See
103
+ :class:`~KleshchevPartitions`.
104
+ """
105
+
106
+ def conormal_cells(self, i=None):
107
+ r"""
108
+ Return a dictionary of the cells of ``self`` which are conormal.
109
+
110
+ Following [Kle1995]_, the *conormal* cells are computed by
111
+ reading up (or down) the rows of the partition and marking all
112
+ of the addable and removable cells of `e`-residue `i` and then
113
+ recursively removing all adjacent pairs of removable and addable
114
+ cells (in that order) from this list. The addable `i`-cells that
115
+ remain at the end of the this process are the conormal `i`-cells.
116
+
117
+ When computing conormal cells you can either read the cells in order
118
+ from top to bottom (this corresponds to labeling the simple modules
119
+ of the symmetric group by regular partitions) or from bottom to top
120
+ (corresponding to labeling the simples by restricted partitions).
121
+ By default we read down the partition but this can be changed by
122
+ setting ``convention = 'RS'``.
123
+
124
+ INPUT:
125
+
126
+ - ``i`` -- (optional) a residue
127
+
128
+ OUTPUT:
129
+
130
+ If no residue ``i`` is specified then a dictionary of conormal cells
131
+ is returned, which gives the conormal cells for ``0 <= i < e``.
132
+
133
+ EXAMPLES::
134
+
135
+ sage: KP = KleshchevPartitions(3, convention='regular')
136
+ sage: KP([5,4,4,3,2]).conormal_cells()
137
+ {0: [(1, 4)], 1: [(5, 0), (4, 2)]}
138
+ sage: KP([5,4,4,3,2]).conormal_cells(0)
139
+ [(1, 4)]
140
+ sage: KP([5,4,4,3,2]).conormal_cells(1)
141
+ [(5, 0), (4, 2)]
142
+ sage: KP = KleshchevPartitions(3, convention='restricted')
143
+ sage: KP([5,4,4,3,2]).conormal_cells()
144
+ {0: [(1, 4), (3, 3)], 2: [(0, 5)]}
145
+ """
146
+ # We use a dictionary for the conormal nodes as the indexing set is Z when e=0
147
+ conormals = defaultdict(list) # the conormal cells of each residue
148
+ carry = defaultdict(int) # a tally of #(removable cells) - #(addable cells)
149
+
150
+ # determine if we read up or down the partition
151
+ KP = self.parent()
152
+ rows = list(range(len(self)+1))
153
+ if KP._convention[1] == 'G':
154
+ rows.reverse()
155
+
156
+ # work through the rows
157
+ for row in rows:
158
+ if row == len(self): # addable cell at bottom of partition
159
+ res = KP._multicharge[0] - row
160
+ if carry[res] == 0:
161
+ conormals[res].append((row, 0))
162
+ else:
163
+ carry[res] += 1
164
+ else:
165
+ res = KP._multicharge[0] + self[row] - row - 1
166
+ if row == len(self)-1 or self[row] > self[row+1]: # removable cell
167
+ carry[res] -= 1
168
+ if row == 0 or self[row-1] > self[row]: # addable cell
169
+ if carry[res+1] >= 0:
170
+ conormals[res+1].append((row, self[row]))
171
+ else:
172
+ carry[res+1] += 1
173
+
174
+ # finally return the result
175
+ return dict(conormals) if i is None else conormals[i]
176
+
177
+ def cogood_cells(self, i=None):
178
+ r"""
179
+ Return a list of the cells of ``self`` that are cogood.
180
+
181
+ The cogood `i`-cell is the 'last' conormal `i`-cell. As with the
182
+ conormal cells we can choose to read either up or down the partition as
183
+ specified by :meth:`~KleshchevPartitions.convention`.
184
+
185
+ INPUT:
186
+
187
+ - ``i`` -- (optional) a residue
188
+
189
+ OUTPUT:
190
+
191
+ If no residue ``i`` is specified then a dictionary of cogood cells
192
+ is returned, which gives the cogood cells for ``0 <= i < e``.
193
+
194
+ EXAMPLES::
195
+
196
+ sage: KP = KleshchevPartitions(3, convention='regular')
197
+ sage: KP([5,4,4,3,2]).cogood_cells()
198
+ {0: (1, 4), 1: (4, 2)}
199
+ sage: KP([5,4,4,3,2]).cogood_cells(0)
200
+ (1, 4)
201
+ sage: KP([5,4,4,3,2]).cogood_cells(1)
202
+ (4, 2)
203
+ sage: KP = KleshchevPartitions(4, convention='restricted')
204
+ sage: KP([5,4,4,3,2]).cogood_cells()
205
+ {1: (0, 5), 2: (4, 2), 3: (1, 4)}
206
+ sage: KP([5,4,4,3,2]).cogood_cells(0)
207
+ sage: KP([5,4,4,3,2]).cogood_cells(2)
208
+ (4, 2)
209
+ """
210
+ conormal_cells = self.conormal_cells(i)
211
+ if i is None:
212
+ return {i: conormal_cells[i][-1] for i in conormal_cells}
213
+ elif not conormal_cells:
214
+ return None
215
+
216
+ return conormal_cells[-1]
217
+
218
+ def normal_cells(self, i=None):
219
+ r"""
220
+ Return a dictionary of the cells of the partition that are normal.
221
+
222
+ Following [Kle1995]_, the *normal* cells are computed by
223
+ reading up (or down) the rows of the partition and marking all
224
+ of the addable and removable cells of `e`-residue `i` and then
225
+ recursively removing all adjacent pairs of removable and
226
+ addable cells (in that order) from this list. The removable
227
+ `i`-cells that remain at the end of the this process are the
228
+ normal `i`-cells.
229
+
230
+ When computing normal cells you can either read the cells in order
231
+ from top to bottom (this corresponds to labeling the simple modules
232
+ of the symmetric group by regular partitions) or from bottom to top
233
+ (corresponding to labeling the simples by restricted partitions).
234
+ By default we read down the partition but this can be changed by
235
+ setting ``convention = 'RS'``.
236
+
237
+ INPUT:
238
+
239
+ - ``i`` -- (optional) a residue
240
+
241
+ OUTPUT:
242
+
243
+ If no residue ``i`` is specified then a dictionary of normal cells
244
+ is returned, which gives the normal cells for ``0 <= i < e``.
245
+
246
+ EXAMPLES::
247
+
248
+ sage: KP = KleshchevPartitions(3, convention='regular')
249
+ sage: KP([5,4,4,3,2]).normal_cells()
250
+ {1: [(2, 3), (0, 4)]}
251
+ sage: KP([5,4,4,3,2]).normal_cells(1)
252
+ [(2, 3), (0, 4)]
253
+ sage: KP = KleshchevPartitions(3, convention='restricted')
254
+ sage: KP([5,4,4,3,2]).normal_cells()
255
+ {0: [(4, 1)], 2: [(3, 2)]}
256
+ sage: KP([5,4,4,3,2]).normal_cells(2)
257
+ [(3, 2)]
258
+ """
259
+ # We use a dictionary for the normal nodes as the indexing set is Z when e=0
260
+ normals = defaultdict(list) # the normal cells of each residue
261
+ carry = defaultdict(int) # a tally of #(removable cells)-#(addable cells)
262
+
263
+ # determine if we read up or down the partition
264
+ KP = self.parent()
265
+ rows = list(range(len(self)+1))
266
+ if KP._convention[1] == 'S':
267
+ rows.reverse()
268
+
269
+ # work through the rows
270
+ for row in rows:
271
+ if row == len(self): # addable cell at bottom of partition
272
+ carry[KP._multicharge[0]-row] += 1
273
+ else:
274
+ res = KP._multicharge[0] + self[row] - row - 1
275
+ if row == len(self) - 1 or self[row] > self[row+1]: # removable cell
276
+ if carry[res] == 0:
277
+ normals[res].insert(0, (row, self[row]-1))
278
+ else:
279
+ carry[res] -= 1
280
+ if row == 0 or self[row-1] > self[row]: # addable cell
281
+ carry[res+1] += 1
282
+
283
+ # finally return the result
284
+ return dict(normals) if i is None else normals[i]
285
+
286
+ def good_cells(self, i=None):
287
+ """
288
+ Return a list of the cells of ``self`` that are good.
289
+
290
+ The good `i`-cell is the 'first' normal `i`-cell. As with the normal
291
+ cells we can choose to read either up or down the partition as
292
+ specified by :meth:`~KleshchevPartitions.convention`.
293
+
294
+ INPUT:
295
+
296
+ - ``i`` -- (optional) a residue
297
+
298
+ OUTPUT:
299
+
300
+ If no residue ``i`` is specified then a dictionary of good cells
301
+ is returned, which gives the good cells for ``0 <= i < e``.
302
+
303
+ EXAMPLES::
304
+
305
+ sage: KP3 = KleshchevPartitions(3, convention='regular')
306
+ sage: KP3([5,4,4,3,2]).good_cells()
307
+ {1: (2, 3)}
308
+ sage: KP3([5,4,4,3,2]).good_cells(1)
309
+ (2, 3)
310
+ sage: KP4 = KleshchevPartitions(4, convention='restricted')
311
+ sage: KP4([5,4,4,3,2]).good_cells()
312
+ {1: (2, 3)}
313
+ sage: KP4([5,4,4,3,2]).good_cells(0)
314
+ sage: KP4([5,4,4,3,2]).good_cells(1)
315
+ (2, 3)
316
+ """
317
+ normal_cells = self.normal_cells(i)
318
+ if i is None:
319
+ return {j: normal_cells[j][0] for j in normal_cells}
320
+ elif not normal_cells:
321
+ return None
322
+
323
+ return normal_cells[0]
324
+
325
+ def good_residue_sequence(self):
326
+ """
327
+ Return a sequence of good nodes from the empty partition
328
+ to ``self``, or ``None`` if no such sequence exists.
329
+
330
+ EXAMPLES::
331
+
332
+ sage: KP = KleshchevPartitions(3, convention='regular')
333
+ sage: KP([5,4,4,3,2]).good_residue_sequence()
334
+ [0, 2, 1, 1, 0, 2, 0, 2, 1, 1, 0, 2, 0, 2, 2, 0, 1, 1]
335
+ sage: KP = KleshchevPartitions(3, convention='restricted')
336
+ sage: KP([5,4,4,3,2]).good_residue_sequence()
337
+ [0, 1, 2, 2, 0, 1, 0, 2, 1, 2, 0, 1, 0, 2, 1, 2, 1, 0]
338
+ """
339
+ if not self:
340
+ return []
341
+
342
+ good_cells = self.good_cells()
343
+ assert good_cells
344
+
345
+ res = sorted(good_cells)[0]
346
+ r, c = good_cells[res]
347
+ good_seq = type(self)(self.parent(), self.remove_cell(r,c)).good_residue_sequence()
348
+ good_seq.append(self.parent()._index_set(res))
349
+ return good_seq
350
+
351
+ def good_cell_sequence(self):
352
+ """
353
+ Return a sequence of good nodes from the empty partition
354
+ to ``self``, or ``None`` if no such sequence exists.
355
+
356
+ EXAMPLES::
357
+
358
+ sage: KP = KleshchevPartitions(3, convention='regular')
359
+ sage: KP([5,4,4,3,2]).good_cell_sequence()
360
+ [(0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2),
361
+ (3, 0), (2, 1), (1, 2), (3, 1), (0, 3), (1, 3),
362
+ (2, 2), (3, 2), (4, 0), (4, 1), (0, 4), (2, 3)]
363
+ sage: KP = KleshchevPartitions(3, convention='restricted')
364
+ sage: KP([5,4,4,3,2]).good_cell_sequence()
365
+ [(0, 0), (0, 1), (1, 0), (0, 2), (1, 1), (2, 0),
366
+ (0, 3), (2, 1), (1, 2), (1, 3), (3, 0), (3, 1),
367
+ (2, 2), (4, 0), (2, 3), (3, 2), (0, 4), (4, 1)]
368
+ """
369
+ if not self:
370
+ return []
371
+
372
+ good_cells = self.good_cells()
373
+ assert good_cells
374
+
375
+ cell = good_cells[sorted(good_cells)[0]]
376
+ good_seq = type(self)(self.parent(), self.remove_cell(*cell)).good_cell_sequence()
377
+ good_seq.append(cell)
378
+ return good_seq
379
+
380
+ def mullineux_conjugate(self):
381
+ r"""
382
+ Return the partition tuple that is the Mullineux conjugate of ``self``.
383
+
384
+ It follows from results in [BK2009]_, [Mat2015]_ that if `\nu` is the
385
+ Mullineux conjugate of the Kleshchev partition tuple `\mu` then the
386
+ simple module `D^\nu =(D^\mu)^{\text{sgn}}` is obtained from `D^\mu`
387
+ by twisting by the `\text{sgn}`-automorphism with is the
388
+ Iwahori-Hecke algebra analogue of tensoring with the one
389
+ dimensional sign representation.
390
+
391
+ EXAMPLES::
392
+
393
+ sage: KP = KleshchevPartitions(3, convention='regular')
394
+ sage: KP([5,4,4,3,2]).mullineux_conjugate()
395
+ [9, 7, 1, 1]
396
+ sage: KP = KleshchevPartitions(3, convention='restricted')
397
+ sage: KP([5,4,4,3,2]).mullineux_conjugate()
398
+ [3, 2, 2, 2, 2, 2, 2, 1, 1, 1]
399
+ sage: KP = KleshchevPartitions(3, [2], convention='regular')
400
+ sage: mc = KP([5,4,4,3,2]).mullineux_conjugate(); mc
401
+ [9, 7, 1, 1]
402
+ sage: mc.parent().multicharge()
403
+ (1,)
404
+ sage: KP = KleshchevPartitions(3, [2], convention='restricted')
405
+ sage: mc = KP([5,4,4,3,2]).mullineux_conjugate(); mc
406
+ [3, 2, 2, 2, 2, 2, 2, 1, 1, 1]
407
+ sage: mc.parent().multicharge()
408
+ (1,)
409
+ """
410
+ P = self.parent()
411
+ if not self:
412
+ size = None
413
+ if isinstance(P, KleshchevPartitions_size):
414
+ size = P._size
415
+ KP = KleshchevPartitions(P._e, [-c for c in P._multicharge],
416
+ size=size, convention=P._convention)
417
+ return KP.element_class(KP, [])
418
+
419
+ good_cells = self.good_cells()
420
+ assert good_cells
421
+
422
+ r, c = sorted(good_cells.values())[0]
423
+ # This is technically wrong when the parent has a fixed size because
424
+ # the resulting Kleshchev partition after removing a cell has abs
425
+ # smaller size. However, this is useful to avoid constructing
426
+ # transient parents.
427
+ mu = P.element_class(P, self.remove_cell(r, c)).mullineux_conjugate()
428
+ # add back on a cogood cell of residue -residue(k,r,c)
429
+ KP = mu.parent()
430
+ return KP.element_class(KP, mu.add_cell(*mu.cogood_cells( r-c-self.parent()._multicharge[0]) ))
431
+
432
+ def is_regular(self):
433
+ r"""
434
+ Return ``True`` if ``self`` is a `e`-regular partition tuple.
435
+
436
+ A partition tuple is `e`-regular if we can get to the empty partition
437
+ tuple by successively removing a sequence of good cells in the down
438
+ direction. Equivalently, all partitions are `0`-regular and if `e > 0`
439
+ then a partition is `e`-regular if no `e` nonzero parts of ``self``
440
+ are equal.
441
+
442
+ EXAMPLES::
443
+
444
+ sage: KP = KleshchevPartitions(2)
445
+ sage: KP([2,1,1]).is_regular()
446
+ False
447
+ sage: KP = KleshchevPartitions(3)
448
+ sage: KP([2,1,1]).is_regular()
449
+ True
450
+ sage: KP([]).is_regular()
451
+ True
452
+ """
453
+ if self.size() == 0 or self.parent()._e == 0:
454
+ return True
455
+ KP = self.parent()
456
+ return super().is_regular(KP._e, KP._multicharge)
457
+
458
+ def is_restricted(self):
459
+ r"""
460
+ Return ``True`` if ``self`` is an `e`-restricted partition tuple.
461
+
462
+ A partition tuple is `e`-restricted if we can get to the empty
463
+ partition tuple by successively removing a sequence of good cells in
464
+ the up direction. Equivalently, all partitions are `0`-restricted and
465
+ if `e > 0` then a partition is `e`-restricted if the difference of
466
+ successive parts of ``self`` are always strictly less than `e`.
467
+
468
+ EXAMPLES::
469
+
470
+ sage: KP = KleshchevPartitions(2, convention='regular')
471
+ sage: KP([3,1]).is_restricted()
472
+ False
473
+ sage: KP = KleshchevPartitions(3, convention='regular')
474
+ sage: KP([3,1]).is_restricted()
475
+ True
476
+ sage: KP([]).is_restricted()
477
+ True
478
+ """
479
+ if self.size() == 0 or self.parent()._e == 0:
480
+ return True
481
+ KP = self.parent()
482
+ return super().is_restricted(KP._e, KP._multicharge)
483
+
484
+
485
+ class KleshchevPartitionTuple(PartitionTuple):
486
+ r"""
487
+ Abstract base class for Kleshchev partition tuples. See
488
+ :class:`~KleshchevPartitions`.
489
+ """
490
+
491
+ def conormal_cells(self, i=None):
492
+ r"""
493
+ Return a dictionary of the cells of the partition that are conormal.
494
+
495
+ Following [Kle1995]_, the *conormal* cells are computed by
496
+ reading up (or down) the rows of the partition and marking all
497
+ of the addable and removable cells of `e`-residue `i` and then
498
+ recursively removing all adjacent pairs of removable and addable
499
+ cells (in that order) from this list. The addable `i`-cells that
500
+ remain at the end of the this process are the conormal `i`-cells.
501
+
502
+ When computing conormal cells you can either read the cells in order
503
+ from top to bottom (this corresponds to labeling the simple modules
504
+ of the symmetric group by regular partitions) or from bottom to top
505
+ (corresponding to labeling the simples by restricted partitions).
506
+ By default we read down the partition but this can be changed by
507
+ setting ``convention = 'RS'``.
508
+
509
+ INPUT:
510
+
511
+ - ``i`` -- (optional) a residue
512
+
513
+ OUTPUT:
514
+
515
+ If no residue ``i`` is specified then a dictionary of conormal cells
516
+ is returned, which gives the conormal cells for ``0 <= i < e``.
517
+
518
+ EXAMPLES::
519
+
520
+ sage: KP = KleshchevPartitions(3, [0,1], convention="left regular")
521
+ sage: KP([[4, 2], [5, 3, 1]]).conormal_cells()
522
+ {0: [(1, 2, 1), (1, 1, 3), (1, 0, 5)],
523
+ 1: [(1, 3, 0), (0, 2, 0), (0, 1, 2), (0, 0, 4)]}
524
+ sage: KP([[4, 2], [5, 3, 1]]).conormal_cells(1)
525
+ [(1, 3, 0), (0, 2, 0), (0, 1, 2), (0, 0, 4)]
526
+ sage: KP([[4, 2], [5, 3, 1]]).conormal_cells(2)
527
+ []
528
+ sage: KP = KleshchevPartitions(3, [0,1], convention="right restricted")
529
+ sage: KP([[4, 2], [5, 3, 1]]).conormal_cells(0)
530
+ [(1, 0, 5), (1, 1, 3), (1, 2, 1)]
531
+ """
532
+ # We use a dictionary for the conormal nodes as the indexing set is Z when e=0
533
+ conormals = defaultdict(list) # the conormal cells of each residue
534
+ carry = defaultdict(int) # a tally of #(removable cells)-#(addable cells)
535
+
536
+ part_lens = [len(part) for part in self] # so we don't repeatedly call these
537
+ # the indices for the rows ending in addable nodes
538
+ KP = self.parent()
539
+ if KP._convention[0] == 'L':
540
+ rows = [(k,r) for k,ell in enumerate(part_lens) for r in range(ell+1)]
541
+ else:
542
+ rows = [(k,r) for k,ell in reversed(list(enumerate(part_lens))) for r in range(ell+1)]
543
+ if KP._convention[1] == 'G':
544
+ rows.reverse()
545
+
546
+ for row in rows:
547
+ k,r = row
548
+ if r == part_lens[k]: # addable cell at bottom of a component
549
+ res = KP._multicharge[k] - r
550
+ if carry[res] == 0:
551
+ conormals[res].append((k, r, 0))
552
+ else:
553
+ carry[res] += 1
554
+ else:
555
+ part = self[k]
556
+ res = KP._multicharge[k] + (part[r] - r - 1)
557
+ if r == part_lens[k] - 1 or part[r] > part[r+1]: # removable cell
558
+ carry[res] -= 1
559
+ if r == 0 or part[r-1] > part[r]: # addable cell
560
+ if carry[res+1] == 0:
561
+ conormals[res+1].append((k, r, part[r]))
562
+ else:
563
+ carry[res+1] += 1
564
+
565
+ # finally return the result
566
+ if i is None:
567
+ return dict(conormals)
568
+ return conormals[i]
569
+
570
+ def cogood_cells(self, i=None):
571
+ r"""
572
+ Return a list of the cells of the partition that are cogood.
573
+
574
+ The cogood `i`-cell is the 'last' conormal `i`-cell. As with the
575
+ conormal cells we can choose to read either up or down the partition
576
+ as specified by :meth:`~KleshchevPartitions.convention`.
577
+
578
+ INPUT:
579
+
580
+ - ``i`` -- (optional) a residue
581
+
582
+ OUTPUT:
583
+
584
+ If no residue ``i`` is specified then a dictionary of cogood cells
585
+ is returned, which gives the cogood cells for ``0 <= i < e``.
586
+
587
+ EXAMPLES::
588
+
589
+ sage: KP = KleshchevPartitions(3, [0,1])
590
+ sage: pt = KP([[4, 2], [5, 3, 1]])
591
+ sage: pt.cogood_cells()
592
+ {0: (1, 2, 1), 1: (1, 3, 0)}
593
+ sage: pt.cogood_cells(0)
594
+ (1, 2, 1)
595
+ sage: KP = KleshchevPartitions(4, [0,1], convention="left regular")
596
+ sage: pt = KP([[5, 2, 2], [6, 1, 1]])
597
+ sage: pt.cogood_cells()
598
+ {1: (0, 0, 5), 2: (1, 3, 0)}
599
+ sage: pt.cogood_cells(0) is None
600
+ True
601
+ sage: pt.cogood_cells(1) is None
602
+ False
603
+ """
604
+ conormal_cells = self.conormal_cells(i)
605
+ if i is None:
606
+ return {j: conormal_cells[j][-1] for j in conormal_cells}
607
+ elif not conormal_cells:
608
+ return None
609
+
610
+ return conormal_cells[-1]
611
+
612
+ def normal_cells(self, i=None):
613
+ r"""
614
+ Return a dictionary of the removable cells of the partition that
615
+ are normal.
616
+
617
+ Following [Kle1995]_, the *normal* cells are computed by
618
+ reading up (or down) the rows of the partition and marking all
619
+ of the addable and removable cells of `e`-residue `i` and then
620
+ recursively removing all adjacent pairs of removable and
621
+ addable cells (in that order) from this list. The removable
622
+ `i`-cells that remain at the end of the this process are the
623
+ normal `i`-cells.
624
+
625
+ When computing normal cells you can either read the cells in order
626
+ from top to bottom (this corresponds to labeling the simple modules
627
+ of the symmetric group by regular partitions) or from bottom to top
628
+ (corresponding to labeling the simples by restricted partitions).
629
+ By default we read down the partition but this can be changed by
630
+ setting ``convention = 'RS'``.
631
+
632
+ INPUT:
633
+
634
+ - ``i`` -- (optional) a residue
635
+
636
+ OUTPUT:
637
+
638
+ If no residue ``i`` is specified then a dictionary of normal cells
639
+ is returned, which gives the normal cells for ``0 <= i < e``.
640
+
641
+ EXAMPLES::
642
+
643
+ sage: KP = KleshchevPartitions(3, [0,1], convention="left restricted")
644
+ sage: KP([[4, 2], [5, 3, 1]]).normal_cells()
645
+ {2: [(1, 0, 4), (1, 1, 2), (1, 2, 0)]}
646
+ sage: KP([[4, 2], [5, 3, 1]]).normal_cells(1)
647
+ []
648
+ sage: KP = KleshchevPartitions(3, [0,1], convention="left regular")
649
+ sage: KP([[4, 2], [5, 3, 1]]).normal_cells()
650
+ {0: [(0, 1, 1), (0, 0, 3)], 2: [(1, 2, 0), (1, 1, 2), (1, 0, 4)]}
651
+ sage: KP = KleshchevPartitions(3, [0,1], convention="right regular")
652
+ sage: KP([[4, 2], [5, 3, 1]]).normal_cells()
653
+ {2: [(1, 2, 0), (1, 1, 2), (1, 0, 4)]}
654
+ sage: KP = KleshchevPartitions(3, [0,1], convention="right restricted")
655
+ sage: KP([[4, 2], [5, 3, 1]]).normal_cells()
656
+ {0: [(0, 0, 3), (0, 1, 1)], 2: [(1, 0, 4), (1, 1, 2), (1, 2, 0)]}
657
+ """
658
+ # We use a dictionary for the normal nodes as the indexing set is Z when e=0
659
+ normals = defaultdict(list) # the normal cells of each residue
660
+ carry = defaultdict(int) # a tally of #(removable cells)-#(addable cells)
661
+
662
+ part_lens = [len(part) for part in self] # so we don't repeatedly call these
663
+ KP = self.parent()
664
+ if KP._convention[0] == 'L':
665
+ rows = [(k, r) for k, ell in enumerate(part_lens) for r in range(ell+1)]
666
+ else:
667
+ rows = [(k, r) for k, ell in reversed(list(enumerate(part_lens))) for r in range(ell+1)]
668
+ if KP._convention[1] == 'S':
669
+ rows.reverse()
670
+
671
+ for row in rows:
672
+ k, r = row
673
+ if r == part_lens[k]: # addable cell at bottom of a component
674
+ carry[KP._multicharge[k]-r] += 1
675
+ else:
676
+ part = self[k]
677
+ res = KP._multicharge[k] + (part[r] - r - 1)
678
+ if r == part_lens[k]-1 or part[r] > part[r+1]: # removable cell
679
+ if carry[res] == 0:
680
+ normals[res].insert(0, (k, r, part[r]-1))
681
+ else:
682
+ carry[res] -= 1
683
+ if r == 0 or part[r-1] > part[r]: # addable cell
684
+ carry[res+1] += 1
685
+
686
+ # finally return the result
687
+ if i is None:
688
+ return dict(normals) # change the defaultdict into a dict
689
+
690
+ return normals[i]
691
+
692
+ def good_cells(self, i=None):
693
+ r"""
694
+ Return a list of the cells of the partition tuple which are good.
695
+
696
+ The good `i`-cell is the 'first' normal `i`-cell. As with the normal
697
+ cells we can choose to read either up or down the partition as specified
698
+ by :meth:`~KleshchevPartitions.convention`.
699
+
700
+ INPUT:
701
+
702
+ - ``i`` -- (optional) a residue
703
+
704
+ OUTPUT:
705
+
706
+ If no residue ``i`` is specified then a dictionary of good cells
707
+ is returned, which gives the good cells for ``0 <= i < e``.
708
+
709
+ EXAMPLES::
710
+
711
+ sage: KP = KleshchevPartitions(3, [0,1])
712
+ sage: pt = KP([[4, 2], [5, 3, 1]])
713
+ sage: pt.good_cells()
714
+ {2: (1, 0, 4)}
715
+ sage: pt.good_cells(2)
716
+ (1, 0, 4)
717
+ sage: KP = KleshchevPartitions(4, [0,1], convention="left regular")
718
+ sage: pt = KP([[5, 2, 2], [6, 2, 1]])
719
+ sage: pt.good_cells()
720
+ {0: (0, 0, 4), 2: (1, 0, 5), 3: (0, 2, 1)}
721
+ sage: pt.good_cells(1) is None
722
+ True
723
+ """
724
+ normal_cells = self.normal_cells(i)
725
+ if i is None:
726
+ return {j: normal_cells[j][0] for j in normal_cells}
727
+ elif not normal_cells:
728
+ return None
729
+
730
+ return normal_cells[0]
731
+
732
+ def good_residue_sequence(self):
733
+ """
734
+ Return a sequence of good nodes from the empty partition to ``self``.
735
+
736
+ EXAMPLES::
737
+
738
+ sage: KP = KleshchevPartitions(3, [0,1])
739
+ sage: KP([[4, 2], [5, 3, 1]]).good_residue_sequence()
740
+ [0, 1, 2, 1, 2, 0, 1, 0, 2, 2, 0, 1, 0, 2, 2]
741
+ """
742
+ if self.size() == 0:
743
+ return []
744
+ good_cells = self.good_cells()
745
+ assert good_cells
746
+
747
+ res = sorted(good_cells.keys())[0]
748
+ k, r, c = good_cells[res]
749
+ good_seq = type(self)(self.parent(), self.remove_cell(k,r,c)).good_residue_sequence()
750
+ good_seq.append( self.parent()._index_set(res) )
751
+ return good_seq
752
+
753
+ def good_cell_sequence(self):
754
+ """
755
+ Return a sequence of good nodes from the empty partition to ``self``.
756
+
757
+ EXAMPLES::
758
+
759
+ sage: KP = KleshchevPartitions(3,[0,1])
760
+ sage: KP([[4, 2], [5, 3, 1]]).good_cell_sequence()
761
+ [(0, 0, 0), (1, 0, 0), (1, 0, 1), (0, 0, 1), (0, 1, 0),
762
+ (1, 1, 0), (1, 1, 1), (1, 0, 2), (1, 2, 0), (0, 0, 2),
763
+ (0, 1, 1), (1, 0, 3), (0, 0, 3), (1, 1, 2), (1, 0, 4)]
764
+ """
765
+ if self.size() == 0:
766
+ return []
767
+ good_cells = self.good_cells()
768
+ assert good_cells
769
+
770
+ cell = good_cells[sorted(good_cells)[0]]
771
+ good_seq = type(self)(self.parent(), self.remove_cell(*cell)).good_cell_sequence()
772
+ good_seq.append(cell)
773
+ return good_seq
774
+
775
+ def mullineux_conjugate(self):
776
+ r"""
777
+ Return the partition that is the Mullineux conjugate of ``self``.
778
+
779
+ It follows from results in [Kle1996]_ [Bru1998]_ that if `\nu` is the
780
+ Mullineux conjugate of the Kleshchev partition tuple `\mu` then the
781
+ simple module `D^\nu =(D^\mu)^{\text{sgn}}` is obtained from `D^\mu`
782
+ by twisting by the `\text{sgn}`-automorphism with is the Hecke algebra
783
+ analogue of tensoring with the one dimensional sign representation.
784
+
785
+ EXAMPLES::
786
+
787
+ sage: KP = KleshchevPartitions(3, [0,1])
788
+ sage: mc = KP([[4, 2], [5, 3, 1]]).mullineux_conjugate(); mc
789
+ ([2, 2, 1, 1], [3, 2, 2, 1, 1])
790
+ sage: mc.parent()
791
+ Kleshchev partitions with e=3 and multicharge=(0,2)
792
+ """
793
+ P = self.parent()
794
+ if self.size() == 0:
795
+ size = None
796
+ if isinstance(P, KleshchevPartitions_size):
797
+ size = P._size
798
+ KP = KleshchevPartitions(P._e, [-c for c in P._multicharge],
799
+ size=size, convention=P._convention)
800
+ return KP.element_class(KP, [[]]*P._level)
801
+
802
+ good_cells = self.good_cells()
803
+ assert good_cells
804
+
805
+ k,r,c = sorted(good_cells.values())[0]
806
+ # This is technically wrong when the parent has a fixed size because
807
+ # the resulting Kleshchev partition after removing a cell has abs
808
+ # smaller size. However, this is useful to avoid constructing
809
+ # transient parents.
810
+ mu = P.element_class(P, self.remove_cell(k,r,c)).mullineux_conjugate()
811
+ # add back on a cogood cell of residue -residue(k,r,c)
812
+ KP = mu.parent()
813
+ return KP.element_class(KP, mu.add_cell(*mu.cogood_cells( r-c-self.parent()._multicharge[k])))
814
+
815
+ def is_regular(self):
816
+ r"""
817
+ Return ``True`` if ``self`` is a `e`-regular partition tuple.
818
+
819
+ A partition tuple is `e`-regular if we can get to the
820
+ empty partition tuple by successively removing a sequence
821
+ of good cells in the down direction.
822
+
823
+ EXAMPLES::
824
+
825
+ sage: KP = KleshchevPartitions(2, [0,2], convention="right restricted")
826
+ sage: KP([[3,2,1], [2,1,1]]).is_regular()
827
+ False
828
+ sage: KP = KleshchevPartitions(4, [0,2], convention="right restricted")
829
+ sage: KP([[3,2,1], [2,1,1]]).is_regular()
830
+ True
831
+ sage: KP([[], []]).is_regular()
832
+ True
833
+ """
834
+ if self.size() == 0:
835
+ return True
836
+ KP = self.parent()
837
+ return _is_regular(self.to_list(), KP._multicharge, KP._convention)
838
+
839
+ def is_restricted(self):
840
+ r"""
841
+ Return ``True`` if ``self`` is an `e`-restricted partition tuple.
842
+
843
+ A partition tuple is `e`-restricted if we can get to the
844
+ empty partition tuple by successively removing a sequence
845
+ of good cells in the up direction.
846
+
847
+ EXAMPLES::
848
+
849
+ sage: KP = KleshchevPartitions(2, [0,2], convention="left regular")
850
+ sage: KP([[3,2,1], [3,1]]).is_restricted()
851
+ False
852
+ sage: KP = KleshchevPartitions(3, [0,2], convention="left regular")
853
+ sage: KP([[3,2,1], [3,1]]).is_restricted()
854
+ True
855
+ sage: KP([[], []]).is_restricted()
856
+ True
857
+ """
858
+ if self.size() == 0:
859
+ return True
860
+ KP = self.parent()
861
+ return _is_restricted(self.to_list(), KP._multicharge, KP._convention)
862
+
863
+
864
+ class KleshchevCrystalMixin:
865
+ """
866
+ Mixin class for the crystal structure of a Kleshchev partition.
867
+ """
868
+
869
+ def epsilon(self, i):
870
+ r"""
871
+ Return the Kashiwara crystal operator `\varepsilon_i` applied to ``self``.
872
+
873
+ INPUT:
874
+
875
+ - ``i`` -- an element of the index set
876
+
877
+ EXAMPLES::
878
+
879
+ sage: C = crystals.KleshchevPartitions(3, [0,2], convention="left regular")
880
+ sage: x = C([[5,4,1],[3,2,1,1]])
881
+ sage: [x.epsilon(i) for i in C.index_set()]
882
+ [0, 3, 0]
883
+ """
884
+ return len(self.normal_cells(i))
885
+
886
+ def phi(self, i):
887
+ r"""
888
+ Return the Kashiwara crystal operator `\varphi_i` applied to ``self``.
889
+
890
+ INPUT:
891
+
892
+ - ``i`` -- an element of the index set
893
+
894
+ EXAMPLES::
895
+
896
+ sage: C = crystals.KleshchevPartitions(3, [0,2], convention="left regular")
897
+ sage: x = C([[5,4,1],[3,2,1,1]])
898
+ sage: [x.phi(i) for i in C.index_set()]
899
+ [3, 2, 0]
900
+ """
901
+ return len(self.conormal_cells(i))
902
+
903
+ def Epsilon(self):
904
+ r"""
905
+ Return `\varepsilon` of ``self``.
906
+
907
+ EXAMPLES::
908
+
909
+ sage: C = crystals.KleshchevPartitions(3, [0,2], convention="left regular")
910
+ sage: x = C([[5,4,1],[3,2,1,1]])
911
+ sage: x.Epsilon()
912
+ 3*Lambda[1]
913
+ """
914
+ P = self.parent()
915
+ WLR = P.weight_lattice_realization()
916
+ La = WLR.fundamental_weights()
917
+ n = self.normal_cells()
918
+ return WLR.sum(len(n[i])*La[i] for i in P.index_set() if i in n)
919
+
920
+ def Phi(self):
921
+ r"""
922
+ Return `\phi` of ``self``.
923
+
924
+ EXAMPLES::
925
+
926
+ sage: C = crystals.KleshchevPartitions(3, [0,2], convention="left regular")
927
+ sage: x = C([[5,4,1],[3,2,1,1]])
928
+ sage: x.Phi()
929
+ 3*Lambda[0] + 2*Lambda[1]
930
+ """
931
+ P = self.parent()
932
+ WLR = P.weight_lattice_realization()
933
+ La = WLR.fundamental_weights()
934
+ c = self.conormal_cells()
935
+ return WLR.sum(len(c[i])*La[i] for i in P.index_set() if i in c)
936
+
937
+ def weight(self):
938
+ r"""
939
+ Return the weight of ``self``.
940
+
941
+ EXAMPLES::
942
+
943
+ sage: # needs sage.graphs
944
+ sage: C = crystals.KleshchevPartitions(3, [0,2], convention="left regular")
945
+ sage: x = C([[5,4,1], [3,2,1,1]])
946
+ sage: x.weight()
947
+ 3*Lambda[0] - Lambda[1] - 5*delta
948
+ sage: x.Phi() - x.Epsilon()
949
+ 3*Lambda[0] - Lambda[1]
950
+
951
+ sage: # needs sage.graphs
952
+ sage: C = crystals.KleshchevPartitions(3, [0,2], convention="right regular")
953
+ sage: y = C([[5,1,1], [4,2,2,1,1]])
954
+ sage: y.weight()
955
+ 6*Lambda[0] - 4*Lambda[1] - 4*delta
956
+ sage: y.Phi() - y.Epsilon()
957
+ 6*Lambda[0] - 4*Lambda[1]
958
+
959
+ sage: # needs sage.graphs
960
+ sage: C = crystals.KleshchevPartitions(3, [0,2], convention="left regular")
961
+ sage: y = C([[5,1,1], [4,2,2,1,1]])
962
+ sage: y.weight()
963
+ 6*Lambda[0] - 4*Lambda[1] - 4*delta
964
+ sage: y.Phi() - y.Epsilon()
965
+ 6*Lambda[0] - 4*Lambda[1]
966
+ """
967
+ WLR = self.parent().weight_lattice_realization()
968
+ alpha = WLR.simple_roots()
969
+ La = WLR.fundamental_weights()
970
+ r = self.parent()._multicharge
971
+ wt = WLR.sum(La[ZZ(x)] for x in r)
972
+ return wt - WLR.sum(alpha[self.content(*c, multicharge=r)]
973
+ for c in self.cells())
974
+
975
+
976
+ class KleshchevPartitionCrystal(KleshchevPartition, KleshchevCrystalMixin):
977
+ """
978
+ Kleshchev partition with the crystal structure.
979
+ """
980
+
981
+ def e(self, i):
982
+ r"""
983
+ Return the action of `e_i` on ``self``.
984
+
985
+ INPUT:
986
+
987
+ - ``i`` -- an element of the index set
988
+
989
+ EXAMPLES::
990
+
991
+ sage: C = crystals.KleshchevPartitions(3, convention="left regular")
992
+ sage: x = C([5,4,1])
993
+ sage: x.e(0)
994
+ sage: x.e(1)
995
+ [5, 4]
996
+ """
997
+ P = self.parent()
998
+ cell = self.good_cells(i)
999
+ if cell is None:
1000
+ return None
1001
+ r, _ = cell
1002
+ mu = list(self)
1003
+ mu[r] -= 1
1004
+ return type(self)(P, mu)
1005
+
1006
+ def f(self, i):
1007
+ r"""
1008
+ Return the action of `f_i` on ``self``.
1009
+
1010
+ INPUT:
1011
+
1012
+ - ``i`` -- an element of the index set
1013
+
1014
+ EXAMPLES::
1015
+
1016
+ sage: C = crystals.KleshchevPartitions(3, convention="left regular")
1017
+ sage: x = C([5,4,1])
1018
+ sage: x.f(0)
1019
+ [5, 5, 1]
1020
+ sage: x.f(1)
1021
+ sage: x.f(2)
1022
+ [5, 4, 2]
1023
+ """
1024
+ P = self.parent()
1025
+ cell = self.cogood_cells(i)
1026
+ if cell is None:
1027
+ return None
1028
+ r,c = cell
1029
+ mu = list(self)
1030
+ if c == 0:
1031
+ mu.append(1)
1032
+ else:
1033
+ mu[r] += 1
1034
+ return type(self)(P, mu)
1035
+
1036
+
1037
+ class KleshchevPartitionTupleCrystal(KleshchevPartitionTuple, KleshchevCrystalMixin):
1038
+ """
1039
+ Kleshchev partition tuple with the crystal structure.
1040
+ """
1041
+
1042
+ def e(self, i):
1043
+ r"""
1044
+ Return the action of `e_i` on ``self``.
1045
+
1046
+ INPUT:
1047
+
1048
+ - ``i`` -- an element of the index set
1049
+
1050
+ EXAMPLES::
1051
+
1052
+ sage: C = crystals.KleshchevPartitions(3, [0,2], convention="left regular")
1053
+ sage: x = C([[5,4,1],[3,2,1,1]])
1054
+ sage: x.e(0)
1055
+ sage: x.e(1)
1056
+ ([5, 4, 1], [2, 2, 1, 1])
1057
+ """
1058
+ P = self.parent()
1059
+ cell = self.good_cells(i)
1060
+ if cell is None:
1061
+ return None
1062
+ k, r, _ = cell
1063
+ mu = self.to_list()
1064
+ mu[k][r] -= 1
1065
+ return type(self)(P, mu)
1066
+
1067
+ def f(self, i):
1068
+ r"""
1069
+ Return the action of `f_i` on ``self``.
1070
+
1071
+ INPUT:
1072
+
1073
+ - ``i`` -- an element of the index set
1074
+
1075
+ EXAMPLES::
1076
+
1077
+ sage: C = crystals.KleshchevPartitions(3, [0,2], convention="left regular")
1078
+ sage: x = C([[5,4,1],[3,2,1,1]])
1079
+ sage: x.f(0)
1080
+ ([5, 5, 1], [3, 2, 1, 1])
1081
+ sage: x.f(1)
1082
+ ([5, 4, 1], [3, 2, 2, 1])
1083
+ sage: x.f(2)
1084
+ """
1085
+ P = self.parent()
1086
+ cell = self.cogood_cells(i)
1087
+ if cell is None:
1088
+ return None
1089
+ k,r,c = cell
1090
+ mu = self.to_list()
1091
+ if c == 0:
1092
+ mu[k].append(1)
1093
+ else:
1094
+ mu[k][r] += 1
1095
+ return type(self)(P, mu)
1096
+
1097
+ #--------------------------------------------------
1098
+ # Kleshchev partitions - parent classes
1099
+ #--------------------------------------------------
1100
+
1101
+
1102
+ class KleshchevPartitions(PartitionTuples):
1103
+ r"""
1104
+ Kleshchev partitions.
1105
+
1106
+ A partition (tuple) `\mu` is Kleshchev if it can be recursively
1107
+ obtained by adding a sequence of good nodes to the empty
1108
+ :class:`PartitionTuple` of the same :meth:`~PartitionTuple.level`
1109
+ and multicharge.
1110
+
1111
+ There are four different conventions that are used in the literature for
1112
+ Kleshchev partitions, depending on whether we read partitions from top
1113
+ to bottom (regular) or bottom to top (restricted) and whether we read
1114
+ partition tuples from left to right or right to left. All of these
1115
+ conventions are supported::
1116
+
1117
+ sage: KleshchevPartitions(2, [0,0], size=2, convention='left regular')[:]
1118
+ [([1], [1]), ([2], [])]
1119
+ sage: KleshchevPartitions(2, [0,0], size=2, convention='left restricted')[:]
1120
+ [([1], [1]), ([], [1, 1])]
1121
+ sage: KleshchevPartitions(2, [0,0], size=2, convention='right regular')[:]
1122
+ [([1], [1]), ([], [2])]
1123
+ sage: KleshchevPartitions(2, [0,0], size=2, convention='right restricted')[:]
1124
+ [([1], [1]), ([1, 1], [])]
1125
+
1126
+ By default, the ``left restricted`` convention is used. As a shorthand,
1127
+ ``LG``, ``LS``, ``RG`` and ``RS``, respectively, can be used to specify
1128
+ the ``convention``. With the ``left`` convention the partition tuples
1129
+ should be ordered with the most dominant partitions in the partition
1130
+ tuple on the left and with the ``right`` convention the most dominant
1131
+ partition is on the right.
1132
+
1133
+ The :class:`~KleshchevPartitions` class will automatically convert
1134
+ between these four different conventions::
1135
+
1136
+ sage: KPlg = KleshchevPartitions(2, [0,0], size=2, convention='left regular')
1137
+ sage: KPls = KleshchevPartitions(2, [0,0], size=2, convention='left restricted')
1138
+ sage: [KPlg(mu) for mu in KPls]
1139
+ [([1], [1]), ([2], [])]
1140
+
1141
+ EXAMPLES::
1142
+
1143
+ sage: sorted(KleshchevPartitions(5,[3,2,1],1, convention='RS'))
1144
+ [([], [], [1]), ([], [1], []), ([1], [], [])]
1145
+ sage: sorted(KleshchevPartitions(5, [3,2,1], 1, convention='LS'))
1146
+ [([], [], [1]), ([], [1], []), ([1], [], [])]
1147
+ sage: sorted(KleshchevPartitions(5, [3,2,1], 3))
1148
+ [([], [], [1, 1, 1]),
1149
+ ([], [], [2, 1]),
1150
+ ([], [], [3]),
1151
+ ([], [1], [1, 1]),
1152
+ ([], [1], [2]),
1153
+ ([], [1, 1], [1]),
1154
+ ([], [2], [1]),
1155
+ ([], [3], []),
1156
+ ([1], [], [1, 1]),
1157
+ ([1], [], [2]),
1158
+ ([1], [1], [1]),
1159
+ ([1], [2], []),
1160
+ ([1, 1], [1], []),
1161
+ ([2], [], [1]),
1162
+ ([2], [1], []),
1163
+ ([3], [], [])]
1164
+ sage: sorted(KleshchevPartitions(5, [3,2,1], 3, convention="left regular"))
1165
+ [([], [], [1, 1, 1]),
1166
+ ([], [1], [1, 1]),
1167
+ ([], [1], [2]),
1168
+ ([], [1, 1], [1]),
1169
+ ([], [1, 1, 1], []),
1170
+ ([1], [], [1, 1]),
1171
+ ([1], [1], [1]),
1172
+ ([1], [1, 1], []),
1173
+ ([1], [2], []),
1174
+ ([1, 1], [], [1]),
1175
+ ([1, 1], [1], []),
1176
+ ([1, 1, 1], [], []),
1177
+ ([2], [], [1]),
1178
+ ([2], [1], []),
1179
+ ([2, 1], [], []),
1180
+ ([3], [], [])]
1181
+
1182
+ REFERENCES:
1183
+
1184
+ - [AM2000]_
1185
+ - [Ariki2001]_
1186
+ - [BK2009]_
1187
+ - [Kle2009]_
1188
+ """
1189
+ @staticmethod
1190
+ def __classcall_private__(cls, e, multicharge=(0,), size=None,
1191
+ convention="left restricted"):
1192
+ r"""
1193
+ This is a factory class which returns the appropriate parent based on
1194
+ the values of `level` and `size`.
1195
+
1196
+ EXAMPLES::
1197
+
1198
+ sage: sorted(KleshchevPartitions(5, [3,2,1], 1, convention='RS'))
1199
+ [([], [], [1]), ([], [1], []), ([1], [], [])]
1200
+ sage: sorted(KleshchevPartitions(5, [3,2,1], 1, convention='LS'))
1201
+ [([], [], [1]), ([], [1], []), ([1], [], [])]
1202
+ """
1203
+ if size is None and multicharge in ZZ:
1204
+ size = ZZ(multicharge)
1205
+ multicharge = (0,)
1206
+
1207
+ I = IntegerModRing(e)
1208
+ multicharge = tuple([I(x) for x in multicharge])
1209
+
1210
+ convention = convention.upper()
1211
+ if 'S' in convention:
1212
+ convention = convention[0] + 'S'
1213
+ elif 'G' in convention:
1214
+ convention = convention[0] + 'G'
1215
+ if convention not in ['RG','LG', 'RS', 'LS']:
1216
+ raise ValueError('invalid convention')
1217
+
1218
+ if size is None:
1219
+ return KleshchevPartitions_all(e, multicharge, convention)
1220
+
1221
+ return KleshchevPartitions_size(e, multicharge, size, convention)
1222
+
1223
+ def multicharge(self):
1224
+ """
1225
+ Return the multicharge of ``self``.
1226
+
1227
+ EXAMPLES::
1228
+
1229
+ sage: KP = KleshchevPartitions(6, [2])
1230
+ sage: KP.multicharge()
1231
+ (2,)
1232
+ sage: KP = KleshchevPartitions(5, [3,0,1], 1, convention='LS')
1233
+ sage: KP.multicharge()
1234
+ (3, 0, 1)
1235
+ """
1236
+ return self._multicharge
1237
+
1238
+ def convention(self):
1239
+ """
1240
+ Return the convention of ``self``.
1241
+
1242
+ EXAMPLES::
1243
+
1244
+ sage: KP = KleshchevPartitions(4)
1245
+ sage: KP.convention()
1246
+ 'restricted'
1247
+ sage: KP = KleshchevPartitions(6, [4], 3, convention="right regular")
1248
+ sage: KP.convention()
1249
+ 'regular'
1250
+ sage: KP = KleshchevPartitions(5, [3,0,1], 1)
1251
+ sage: KP.convention()
1252
+ 'left restricted'
1253
+ sage: KP = KleshchevPartitions(5, [3,0,1], 1, convention='right regular')
1254
+ sage: KP.convention()
1255
+ 'right regular'
1256
+ """
1257
+ if self._convention[1] == 'S':
1258
+ convention = "restricted"
1259
+ else:
1260
+ convention = "regular"
1261
+
1262
+ if self._level == 1:
1263
+ return convention
1264
+
1265
+ if self._convention[0] == 'R':
1266
+ return "right " + convention
1267
+
1268
+ return "left " + convention
1269
+
1270
+ def _element_constructor_(self, mu):
1271
+ r"""
1272
+ Return ``mu`` as an element of :class:`~KleshchevPartitions`, or
1273
+ or raise an error if ``mu`` is not a Kleshchev partition (tuple).
1274
+
1275
+ The main purpose of the element constructor code is to allow automatic
1276
+ conversion between the four possible conventions for Kleshchev
1277
+ partitions.
1278
+
1279
+ EXAMPLES::
1280
+
1281
+ sage: KPlg = KleshchevPartitions(2, [0,0], size=2, convention='left regular')
1282
+ sage: KPls = KleshchevPartitions(2, [0,0], size=2, convention='left restricted')
1283
+ sage: [KPlg(mu) for mu in KPls] # indirect doc test
1284
+ [([1], [1]), ([2], [])]
1285
+ """
1286
+ if isinstance(mu, (KleshchevPartition, KleshchevPartitionTuple)):
1287
+ KPmu = mu.parent()
1288
+ if KPmu == self:
1289
+ return mu
1290
+
1291
+ if KPmu._level != self._level or KPmu._e != self._e:
1292
+ raise ValueError('%s is not an element of %s' % (mu, self))
1293
+
1294
+ if KPmu._convention[1] != self._convention[1]:
1295
+ mu = [nu.conjugate() for nu in mu]
1296
+ if self._level > 1 and KPmu._convention[0] == self._convention[0]:
1297
+ mu = mu[::-1]
1298
+
1299
+ return super()._element_constructor_(mu)
1300
+
1301
+
1302
+ class KleshchevPartitions_all(KleshchevPartitions):
1303
+ r"""
1304
+ Class of all Kleshchev partitions.
1305
+
1306
+ .. RUBRIC:: Crystal structure
1307
+
1308
+ We consider type `A_{e-1}^{(1)}` crystals, and let `r = (r_i |
1309
+ r_i \in \ZZ / e \ZZ)` be a finite sequence of length `k`, which
1310
+ is the *level*, and `\lambda = \sum_i \Lambda_{r_i}`. We will
1311
+ model the highest weight `U_q(\mathfrak{g})`-crystal `B(\lambda)`
1312
+ by a particular subset of partition tuples of level `k`.
1313
+
1314
+ Consider a partition tuple `\mu` with multicharge `r`.
1315
+ We define `e_i(\mu)` as the partition tuple obtained after the
1316
+ deletion of the `i`-:meth:`good cell
1317
+ <~sage.combinat.partition_kleshchev.KleshchevPartitionTuple.good_cell>`
1318
+ to `\mu` and `0` if there is no `i`-good cell. We define `f_i(\mu)` as
1319
+ the partition tuple obtained by the addition of the `i`-:meth:`cogood cell
1320
+ <~sage.combinat.partition_kleshchev.KleshchevPartitionTuple.cogood_cell>`
1321
+ to `\mu` and `0` if there is no `i`-good cell.
1322
+
1323
+ The crystal `B(\lambda)` is the crystal generated by the empty
1324
+ partition tuple. We can compute the weight of an element `\mu` by taking
1325
+ `\lambda - \sum_{i=0}^n c_i \alpha_i` where `c_i` is the number of cells
1326
+ of `n`-residue `i` in `\mu`. Partition tuples in the crystal are known
1327
+ as *Kleshchev partitions*.
1328
+
1329
+ .. NOTE::
1330
+
1331
+ We can describe normal (not restricted) Kleshchev partition tuples
1332
+ in `B(\lambda)` as partition tuples `\mu` such that
1333
+ `\mu^{(t)}_{r_t - r_{t+1} + x} < \mu^{(t+1)}_x`
1334
+ for all `x \geq 1` and `1 \leq t \leq k - 1`.
1335
+
1336
+ INPUT:
1337
+
1338
+ - ``e`` -- for type `A_{e-1}^{(1)}` or `0`
1339
+ - ``multicharge`` -- the multicharge sequence `r`
1340
+ - ``convention`` -- (default: ``'LS'``) the reading convention
1341
+
1342
+ EXAMPLES:
1343
+
1344
+ We first do an example of a level 1 crystal::
1345
+
1346
+ sage: C = crystals.KleshchevPartitions(3, [0], convention="left restricted")
1347
+ sage: C
1348
+ Kleshchev partitions with e=3
1349
+ sage: mg = C.highest_weight_vector()
1350
+ sage: mg
1351
+ []
1352
+ sage: mg.f(0)
1353
+ [1]
1354
+ sage: mg.f(1)
1355
+ sage: mg.f(2)
1356
+ sage: mg.f_string([0,2,1,0])
1357
+ [1, 1, 1, 1]
1358
+ sage: mg.f_string([0,1,2,0])
1359
+ [2, 2]
1360
+ sage: GC = C.subcrystal(max_depth=5).digraph() # needs sage.graphs
1361
+ sage: B = crystals.LSPaths(['A',2,1], [1,0,0]) # needs sage.graphs
1362
+ sage: GB = B.subcrystal(max_depth=5).digraph() # needs sage.graphs
1363
+ sage: GC.is_isomorphic(GB, edge_labels=True) # needs sage.graphs
1364
+ True
1365
+
1366
+ Now a higher level crystal::
1367
+
1368
+ sage: C = crystals.KleshchevPartitions(3, [0,2], convention="right restricted")
1369
+ sage: mg = C.highest_weight_vector()
1370
+ sage: mg
1371
+ ([], [])
1372
+ sage: mg.f(0)
1373
+ ([1], [])
1374
+ sage: mg.f(2)
1375
+ ([], [1])
1376
+ sage: mg.f_string([0,1,2,0])
1377
+ ([2, 2], [])
1378
+ sage: mg.f_string([0,2,1,0])
1379
+ ([1, 1, 1, 1], [])
1380
+ sage: mg.f_string([2,0,1,0])
1381
+ ([2], [2])
1382
+ sage: GC = C.subcrystal(max_depth=5).digraph() # needs sage.graphs
1383
+ sage: B = crystals.LSPaths(['A',2,1], [1,0,1]) # needs sage.graphs
1384
+ sage: GB = B.subcrystal(max_depth=5).digraph() # needs sage.graphs
1385
+ sage: GC.is_isomorphic(GB, edge_labels=True) # needs sage.graphs
1386
+ True
1387
+
1388
+ The ordering of the residues gives a different representation of the
1389
+ higher level crystals (but it is still isomorphic)::
1390
+
1391
+ sage: C2 = crystals.KleshchevPartitions(3, [2,0], convention="right restricted")
1392
+ sage: mg2 = C2.highest_weight_vector()
1393
+ sage: mg2.f_string([0,1,2,0])
1394
+ ([2], [2])
1395
+ sage: mg2.f_string([0,2,1,0])
1396
+ ([1, 1, 1], [1])
1397
+ sage: mg2.f_string([2,0,1,0])
1398
+ ([2, 1], [1])
1399
+ sage: GC2 = C2.subcrystal(max_depth=5).digraph() # needs sage.graphs
1400
+ sage: GC.is_isomorphic(GC2, edge_labels=True) # needs sage.graphs
1401
+ True
1402
+
1403
+ TESTS:
1404
+
1405
+ We check that all conventions give isomorphic crystals::
1406
+
1407
+ sage: CLS = crystals.KleshchevPartitions(3, [2,0], convention="left restricted")
1408
+ sage: CRS = crystals.KleshchevPartitions(3, [2,0], convention="right restricted")
1409
+ sage: CLG = crystals.KleshchevPartitions(3, [2,0], convention="left regular")
1410
+ sage: CRG = crystals.KleshchevPartitions(3, [2,0], convention="right regular")
1411
+ sage: C = [CLS, CRS, CLG, CRG]
1412
+ sage: G = [B.subcrystal(max_depth=6).digraph() for B in C] # needs sage.graphs
1413
+ sage: G[0].is_isomorphic(G[1], edge_labels=True) # needs sage.graphs
1414
+ True
1415
+ sage: G[0].is_isomorphic(G[2], edge_labels=True) # needs sage.graphs
1416
+ True
1417
+ sage: G[0].is_isomorphic(G[3], edge_labels=True) # needs sage.graphs
1418
+ True
1419
+
1420
+ REFERENCES:
1421
+
1422
+ - [Ariki1996]_
1423
+ - [Ariki2001]_
1424
+ - [Tingley2007]_
1425
+ - [TingleyLN]_
1426
+ - [Vazirani2002]_
1427
+ """
1428
+
1429
+ def __init__(self, e, multicharge, convention):
1430
+ r"""
1431
+ Initialize ``self``.
1432
+
1433
+ EXAMPLES::
1434
+
1435
+ sage: K = KleshchevPartitions(4, [2])
1436
+ sage: TestSuite(K).run() # long time
1437
+ sage: K = KleshchevPartitions(4, [0,2,1])
1438
+ sage: TestSuite(K).run() # long time
1439
+
1440
+ sage: K = KleshchevPartitions(0, [2])
1441
+ sage: TestSuite(K).run()
1442
+ sage: K = KleshchevPartitions(0, [0,2,1])
1443
+ sage: TestSuite(K).run() # long time
1444
+ """
1445
+ if e not in NN or e == 1:
1446
+ raise ValueError('e must belong to {0,2,3,4,5,6,...}')
1447
+ if e > 0:
1448
+ from sage.combinat.root_system.cartan_type import CartanType
1449
+ from sage.categories.highest_weight_crystals import HighestWeightCrystals
1450
+ from sage.categories.regular_crystals import RegularCrystals
1451
+ self._cartan_type = CartanType(['A', e-1, 1])
1452
+ cat = (HighestWeightCrystals(), RegularCrystals().Infinite())
1453
+ else:
1454
+ cat = InfiniteEnumeratedSets()
1455
+
1456
+ self._level = len(multicharge)
1457
+ if self._level == 1:
1458
+ self.Element = KleshchevPartitionCrystal
1459
+ self._element_constructor_ = getattr_from_other_class(self, Partitions, '_element_constructor_')
1460
+ else:
1461
+ self.Element = KleshchevPartitionTupleCrystal
1462
+
1463
+ super().__init__(category=cat)
1464
+ self._e = e # for printing
1465
+ self._index_set = IntegerModRing(e)
1466
+ self._multicharge = multicharge
1467
+ self._convention = convention
1468
+ if e > 0:
1469
+ if self._level == 1:
1470
+ self.module_generators = (self.element_class(self, []),)
1471
+ else:
1472
+ self.module_generators = (self.element_class(self, [[]]*self._level),)
1473
+
1474
+ def _repr_(self):
1475
+ """
1476
+ EXAMPLES::
1477
+
1478
+ sage: KleshchevPartitions(4, [2])
1479
+ Kleshchev partitions with e=4
1480
+ sage: KleshchevPartitions(3,[0,0,0])
1481
+ Kleshchev partitions with e=3 and multicharge=(0,0,0)
1482
+ sage: KleshchevPartitions(3,[0,0,1])
1483
+ Kleshchev partitions with e=3 and multicharge=(0,0,1)
1484
+ """
1485
+ if self._level == 1:
1486
+ return 'Kleshchev partitions with e=%s' % (self._e)
1487
+
1488
+ return 'Kleshchev partitions with e=%s and multicharge=(%s)' % (
1489
+ self._e,','.join('%s' % m for m in self._multicharge))
1490
+
1491
+ def __contains__(self, mu):
1492
+ """
1493
+ Containment test for Kleshchev partitions.
1494
+
1495
+ EXAMPLES::
1496
+
1497
+ sage: PartitionTuple([[3,2],[2]]) in KleshchevPartitions(2, [0,0], 7)
1498
+ False
1499
+ sage: PartitionTuple([[],[2,1],[3,2]]) in KleshchevPartitions(5, [0,0,1], 7)
1500
+ False
1501
+ sage: PartitionTuple([[],[2,1],[3,2]]) in KleshchevPartitions(5, [0,1,1], 7)
1502
+ False
1503
+ sage: PartitionTuple([[],[2,1],[3,2]]) in KleshchevPartitions(5, [0,1,1], 8)
1504
+ True
1505
+ sage: all(mu in PartitionTuples(3,8) for mu in KleshchevPartitions(2, [0,0,0], 8))
1506
+ True
1507
+ """
1508
+ if isinstance(mu, (KleshchevPartition, KleshchevPartitionTuple)):
1509
+ if mu.level() != self._level:
1510
+ return False
1511
+ mu = self.element_class(self, list(mu))
1512
+ if self._convention[1] == 'G':
1513
+ return mu.is_regular()
1514
+
1515
+ return mu.is_restricted()
1516
+
1517
+ try:
1518
+ mu = self.element_class(self, mu)
1519
+ except ValueError:
1520
+ return False
1521
+ return mu in self
1522
+
1523
+ def __iter__(self):
1524
+ r"""
1525
+ Iterate over ``self``.
1526
+
1527
+ EXAMPLES::
1528
+
1529
+ sage: it = iter(KleshchevPartitions(2))
1530
+ sage: [next(it) for _ in range(10)]
1531
+ [[], [1], [1, 1], [2, 1], [1, 1, 1], [2, 1, 1],
1532
+ [1, 1, 1, 1], [2, 2, 1], [2, 1, 1, 1], [1, 1, 1, 1, 1]]
1533
+ sage: it = iter(KleshchevPartitions(2, convention='LG'))
1534
+ sage: [next(it) for _ in range(10)]
1535
+ [[], [1], [2], [3], [2, 1], [4], [3, 1], [5], [4, 1], [3, 2]]
1536
+
1537
+ sage: it = iter(KleshchevPartitions(2, [0,1], convention='LS'))
1538
+ sage: [next(it) for _ in range(10)]
1539
+ [([], []),
1540
+ ([1], []),
1541
+ ([], [1]),
1542
+ ([1], [1]),
1543
+ ([], [1, 1]),
1544
+ ([1, 1], [1]),
1545
+ ([1], [1, 1]),
1546
+ ([], [2, 1]),
1547
+ ([], [1, 1, 1]),
1548
+ ([2, 1], [1])]
1549
+ sage: it = iter(KleshchevPartitions(2, [0,1], convention='RS'))
1550
+ sage: [next(it) for _ in range(10)]
1551
+ [([], []),
1552
+ ([1], []),
1553
+ ([], [1]),
1554
+ ([1, 1], []),
1555
+ ([1], [1]),
1556
+ ([2, 1], []),
1557
+ ([1, 1, 1], []),
1558
+ ([1, 1], [1]),
1559
+ ([1], [1, 1]),
1560
+ ([2, 1, 1], [])]
1561
+ sage: it = iter(KleshchevPartitions(2, [0,1], convention='LG'))
1562
+ sage: [next(it) for _ in range(10)]
1563
+ [([], []),
1564
+ ([1], []),
1565
+ ([], [1]),
1566
+ ([2], []),
1567
+ ([1], [1]),
1568
+ ([3], []),
1569
+ ([2, 1], []),
1570
+ ([2], [1]),
1571
+ ([1], [2]),
1572
+ ([4], [])]
1573
+ sage: it = iter(KleshchevPartitions(2, [0,1], convention='RG'))
1574
+ sage: [next(it) for _ in range(10)]
1575
+ [([], []),
1576
+ ([1], []),
1577
+ ([], [1]),
1578
+ ([1], [1]),
1579
+ ([], [2]),
1580
+ ([2], [1]),
1581
+ ([1], [2]),
1582
+ ([], [3]),
1583
+ ([], [2, 1]),
1584
+ ([2, 1], [1])]
1585
+
1586
+ sage: it = iter(KleshchevPartitions(3, [0,1,2]))
1587
+ sage: [next(it) for _ in range(10)]
1588
+ [([], [], []), ([1], [], []), ([], [1], []), ([], [], [1]),
1589
+ ([1], [1], []), ([1], [], [1]), ([], [1, 1], []),
1590
+ ([], [1], [1]), ([], [], [2]), ([], [], [1, 1])]
1591
+ """
1592
+ # This is a modified form of what appears in the fixed size code
1593
+ if self._level == 1:
1594
+ if self._e == 0:
1595
+ P = Partitions()
1596
+ elif self._convention[1] == 'G':
1597
+ P = Partitions(regular=self._e)
1598
+ else:
1599
+ P = Partitions(restricted=self._e)
1600
+
1601
+ for mu in P:
1602
+ yield self.element_class(self, list(mu))
1603
+ else:
1604
+ next_level = [self.element_class(self, [[]]*len(self._multicharge))]
1605
+ while True:
1606
+ cur = next_level
1607
+ next_level = []
1608
+ for mu in cur:
1609
+ yield mu
1610
+ mu_list = mu.to_list()
1611
+ for cell in sorted(mu.cogood_cells().values()):
1612
+ data = [list(p) for p in mu_list]
1613
+ k, r, c = cell
1614
+ if c == 0:
1615
+ data[k].append(1)
1616
+ else:
1617
+ data[k][r] += 1
1618
+ nu = self.element_class(self, data)
1619
+ good_cells = nu.good_cells().values()
1620
+ if self._convention[1] == "S":
1621
+ if all(cell >= c for c in good_cells):
1622
+ next_level.append(nu)
1623
+ else:
1624
+ if all(cell <= c for c in good_cells):
1625
+ next_level.append(nu)
1626
+
1627
+ def _an_element_(self):
1628
+ """
1629
+ Return a generic element.
1630
+
1631
+ EXAMPLES::
1632
+
1633
+ sage: KleshchevPartitions(3, [0,0,0,0], size=4).an_element()
1634
+ ([1], [1], [1], [1])
1635
+ """
1636
+ return self[12]
1637
+
1638
+
1639
+ class KleshchevPartitions_size(KleshchevPartitions):
1640
+ """
1641
+ Kleshchev partitions of a fixed size.
1642
+ """
1643
+
1644
+ def __init__(self, e, multicharge=(0,), size=0, convention='RS'):
1645
+ r"""
1646
+ Initialize ``self``.
1647
+
1648
+ EXAMPLES::
1649
+
1650
+ sage: K = KleshchevPartitions(4, 2)
1651
+ sage: TestSuite(K).run()
1652
+ sage: K = KleshchevPartitions(4, 4, convention='left regular')
1653
+ sage: TestSuite(K).run()
1654
+ sage: K = KleshchevPartitions(4, 4, convention='left restricted')
1655
+ sage: TestSuite(K).run()
1656
+ sage: K = KleshchevPartitions(4, [0,2,1], 4, convention='left regular')
1657
+ sage: TestSuite(K).run()
1658
+ sage: K = KleshchevPartitions(0, 2, convention='right restricted')
1659
+ sage: TestSuite(K).run()
1660
+ sage: K = KleshchevPartitions(0, [0,2,1], 4, convention='left restricted')
1661
+ sage: TestSuite(K).run()
1662
+ sage: K = KleshchevPartitions(0, [0,2,1], 4, convention='left regular')
1663
+ sage: TestSuite(K).run()
1664
+
1665
+ We verify that we obtain the same size for all conventions
1666
+ and that the result is equal to the number of elements in
1667
+ the crystal at the corresponding depth::
1668
+
1669
+ sage: # needs sage.graphs
1670
+ sage: B = crystals.LSPaths(['A',2,1], [1,0,1])
1671
+ sage: nd4 = (B.subcrystal(max_depth=4).cardinality()
1672
+ ....: - B.subcrystal(max_depth=3).cardinality())
1673
+ sage: K = KleshchevPartitions(3, [0,2], 4, convention='RS')
1674
+ sage: K.cardinality() == nd4
1675
+ True
1676
+ sage: K = KleshchevPartitions(3, [0,2], 4, convention='RG')
1677
+ sage: K.cardinality() == nd4
1678
+ True
1679
+ sage: K = KleshchevPartitions(3, [0,2], 4, convention='LS')
1680
+ sage: K.cardinality() == nd4
1681
+ True
1682
+ sage: K = KleshchevPartitions(3, [0,2], 4, convention='LG')
1683
+ sage: K.cardinality() == nd4
1684
+ True
1685
+ """
1686
+ self._level = len(multicharge)
1687
+ if self._level == 1:
1688
+ self.Element = KleshchevPartition
1689
+ self._element_constructor_ = getattr_from_other_class(self, Partitions, '_element_constructor_')
1690
+ else:
1691
+ self.Element = KleshchevPartitionTuple
1692
+ super().__init__(category=FiniteEnumeratedSets())
1693
+ self._size = size
1694
+ # As lists do not take negative indices the case e=0 needs to be handled
1695
+ # differently. Rather than doing this we set e equal to a "really big"
1696
+ # number. Mathematically, this is equivalent and it means that we don't
1697
+ # have an exception to cater for.
1698
+ self._e = e
1699
+ self._I = IntegerModRing(e)
1700
+ self._multicharge = tuple(self._I(m) for m in multicharge)
1701
+ self._convention = convention
1702
+
1703
+ def _repr_(self):
1704
+ """
1705
+ EXAMPLES::
1706
+
1707
+ sage: KleshchevPartitions(4, [0,0], 3)
1708
+ Kleshchev partitions with e=4 and multicharge=(0,0) and size 3
1709
+ """
1710
+ if self._level == 1:
1711
+ return 'Kleshchev partitions with e=%s and size %s' % (self._e, self._size)
1712
+
1713
+ return 'Kleshchev partitions with e=%s and multicharge=(%s) and size %s' % (
1714
+ self._e,','.join('%s' % m for m in self._multicharge), self._size
1715
+ )
1716
+
1717
+ def __contains__(self, mu):
1718
+ """
1719
+ Check if ``mu`` is in ``self``.
1720
+
1721
+ TESTS::
1722
+
1723
+ sage: PartitionTuple([[3,2],[2]]) in KleshchevPartitions(2,[0,0],7)
1724
+ False
1725
+ sage: PartitionTuple([[3,2],[],[],[],[2]]) in KleshchevPartitions(5,[0,0,0,0,0],7)
1726
+ False
1727
+ sage: PartitionTuple([[2,1],[],[1,1],[],[2]]) in KleshchevPartitions(5,[0,0,0,0,0],7, convention='RG')
1728
+ False
1729
+ sage: PartitionTuple([[2,1],[],[1,1],[],[3]]) in KleshchevPartitions(2,[0,0,0,0,0],9, convention='RS')
1730
+ False
1731
+ sage: all(mu in PartitionTuples(3,8) for mu in KleshchevPartitions(0,[0,0,0],8))
1732
+ True
1733
+ """
1734
+ if isinstance(mu, (KleshchevPartition, KleshchevPartitionTuple)):
1735
+ if not (mu.level() == self._level and mu.size() == self._size):
1736
+ return False
1737
+ mu = self.element_class(self, list(mu))
1738
+ if self._convention[1] == 'G':
1739
+ return mu.is_regular()
1740
+
1741
+ return mu.is_restricted()
1742
+
1743
+ try:
1744
+ mu = self.element_class(self, mu)
1745
+ except ValueError:
1746
+ return False
1747
+ return mu in self
1748
+
1749
+ def __iter__level_one(self):
1750
+ r"""
1751
+ Iterate over all Kleshchev partitions of level one and a fixed size.
1752
+
1753
+ EXAMPLES::
1754
+
1755
+ sage: KleshchevPartitions(2,0)[:] # indirect doctest
1756
+ [[]]
1757
+ sage: KleshchevPartitions(2,1)[:] # indirect doctest
1758
+ [[1]]
1759
+ sage: KleshchevPartitions(2,2)[:] # indirect doctest
1760
+ [[1, 1]]
1761
+ sage: KleshchevPartitions(3,2)[:] # indirect doctest
1762
+ [[2], [1, 1]]
1763
+ """
1764
+ if self._size == 0:
1765
+ yield self.element_class(self, [])
1766
+ else:
1767
+ if self._e == 0:
1768
+ P = Partitions(self._size)
1769
+ elif self._convention[1] == 'G':
1770
+ P = Partitions(self._size, regular=self._e)
1771
+ else:
1772
+ P = Partitions(self._size, restricted=self._e)
1773
+
1774
+ for mu in P:
1775
+ yield self.element_class(self, list(mu))
1776
+
1777
+ def __iter__higher_levels(self):
1778
+ r"""
1779
+ Iterate over all KleshchevPartitions of a fixed level greater than 1
1780
+ and a fixed size.
1781
+
1782
+ EXAMPLES::
1783
+
1784
+ sage: KleshchevPartitions(2,[0,0],1)[:] # indirect doctest
1785
+ [([], [1])]
1786
+ sage: KleshchevPartitions(2,[0,0],2)[:] # indirect doctest
1787
+ [([1], [1]), ([], [1, 1])]
1788
+ sage: KleshchevPartitions(3,[0,0],2)[:] # indirect doctest
1789
+ [([1], [1]), ([], [2]), ([], [1, 1])]
1790
+ """
1791
+ if self._size == 0:
1792
+ yield self.element_class(self, [[]]*len(self._multicharge))
1793
+ return
1794
+
1795
+ # For higher levels we have to recursively construct the restricted partitions
1796
+ # by adding on co-good nodes to smaller restricted partition. To avoid over
1797
+ # counting we return a new restricted partition only if we added on its lowest
1798
+ # good node.
1799
+ for mu in KleshchevPartitions_size(self._e, self._multicharge,
1800
+ size=self._size-1,
1801
+ convention=self._convention):
1802
+ mu_list = mu.to_list()
1803
+ for cell in mu.cogood_cells().values():
1804
+ data = [list(p) for p in mu_list]
1805
+ k,r,c = cell
1806
+ if c == 0:
1807
+ data[k].append(1)
1808
+ else:
1809
+ data[k][r] += 1
1810
+ nu = self.element_class(self, data)
1811
+ good_cells = nu.good_cells().values()
1812
+ if self._convention[1] == "S":
1813
+ if all(cell >= c for c in good_cells):
1814
+ yield nu
1815
+ else:
1816
+ if all(cell <= c for c in good_cells):
1817
+ yield nu
1818
+
1819
+ @lazy_attribute
1820
+ def __iter__(self):
1821
+ """
1822
+ Wrapper to return the correct iterator which is different for
1823
+ :class:`Partitions` (level 1) and for :class:PartitionTuples`
1824
+ (higher levels).
1825
+
1826
+ EXAMPLES::
1827
+
1828
+ sage: KleshchevPartitions(3, 3, convention='RS')[:]
1829
+ [[2, 1], [1, 1, 1]]
1830
+ sage: KleshchevPartitions(3, 3, convention='RG')[:]
1831
+ [[3], [2, 1]]
1832
+ sage: KleshchevPartitions(3, [0], 3)[:]
1833
+ [[2, 1], [1, 1, 1]]
1834
+ sage: KleshchevPartitions(3, [0,0], 3)[:]
1835
+ [([1], [2]), ([1], [1, 1]), ([], [2, 1]), ([], [1, 1, 1])]
1836
+ sage: KleshchevPartitions(2, [0,1], size=0)[:]
1837
+ [([], [])]
1838
+ sage: KleshchevPartitions(2, [0,1], size=1)[:]
1839
+ [([1], []), ([], [1])]
1840
+ sage: KleshchevPartitions(2, [0,1], size=2)[:]
1841
+ [([1], [1]), ([], [1, 1])]
1842
+ sage: KleshchevPartitions(3, [0,1,2], size=2)[:]
1843
+ [([1], [1], []), ([1], [], [1]), ([], [1, 1], []),
1844
+ ([], [1], [1]), ([], [], [2]), ([], [], [1, 1])]
1845
+ """
1846
+ if self.level() == 1:
1847
+ return self.__iter__level_one
1848
+
1849
+ return self.__iter__higher_levels
1850
+
1851
+ def _an_element_(self):
1852
+ """
1853
+ Return a generic element.
1854
+
1855
+ EXAMPLES::
1856
+
1857
+ sage: KleshchevPartitions(4, [0,0,0,0], 4).an_element()
1858
+ ([1], [1], [1], [1])
1859
+ sage: KleshchevPartitions(4, [2], 4).an_element()
1860
+ [3, 1]
1861
+ """
1862
+ return self[0]
1863
+
1864
+ Element = KleshchevPartitionTuple
1865
+
1866
+ #--------------------------------------------------
1867
+ # helper functions
1868
+ #--------------------------------------------------
1869
+
1870
+
1871
+ def _a_good_cell(kpt, multicharge, convention):
1872
+ """
1873
+ Return a good cell from ``kpt`` considered as a Kleshchev partition
1874
+ with ``multicharge`` under ``convention``.
1875
+
1876
+ EXAMPLES::
1877
+
1878
+ sage: from sage.combinat.partition_kleshchev import _a_good_cell
1879
+ sage: I2 = IntegerModRing(2)
1880
+ sage: _a_good_cell([[3,2,1], [3,1,1]], [I2(0),I2(2)], 'RS')
1881
+ (1, 2, 0)
1882
+ sage: _a_good_cell([[3,1,1], [3,2]], [I2(0),I2(2)], 'LG')
1883
+ (1, 1, 1)
1884
+ sage: I3 = IntegerModRing(3)
1885
+ sage: _a_good_cell([[3,2,1], [3,1,1]], [I3(0),I3(2)], 'RS')
1886
+ (0, 2, 0)
1887
+ sage: _a_good_cell([[3,1,1], [3,2]], [I3(0),I3(2)], 'LG')
1888
+ (1, 0, 2)
1889
+ sage: _a_good_cell([[], []], [I3(0),I3(2)], 'RS') is None
1890
+ True
1891
+ sage: _a_good_cell([[1,1], []], [I3(0),I3(2)], 'LS') is None
1892
+ True
1893
+ """
1894
+ # We use a dictionary for the normal nodes as the indexing set is Z when e=0
1895
+ carry = defaultdict(int) # a tally of #(removable cells)-#(addable cells)
1896
+ ret = None
1897
+
1898
+ if convention[0] == 'L':
1899
+ rows = [(k,r) for k,part in enumerate(kpt) for r in range(len(part)+1)]
1900
+ else:
1901
+ rows = [(k,r) for k,part in reversed(list(enumerate(kpt))) for r in range(len(part)+1)]
1902
+ if convention[1] == 'S':
1903
+ rows.reverse()
1904
+
1905
+ for row in rows:
1906
+ k,r = row
1907
+ if r == len(kpt[k]): # addable cell at bottom of a component
1908
+ carry[multicharge[k]-r] += 1
1909
+ else:
1910
+ res = multicharge[k] + kpt[k][r] - r - 1
1911
+ if r == len(kpt[k])-1 or kpt[k][r] > kpt[k][r+1]: # removable cell
1912
+ if carry[res] == 0:
1913
+ ret = (k, r, kpt[k][r]-1)
1914
+ else:
1915
+ carry[res] -= 1
1916
+ if r == 0 or kpt[k][r-1] > kpt[k][r]: # addable cell
1917
+ carry[res+1] += 1
1918
+
1919
+ # finally return the result
1920
+ return ret
1921
+
1922
+
1923
+ def _is_regular(kpt, multicharge, convention):
1924
+ """
1925
+ Return ``True`` if ``kpt`` is a ``multicharge``-regular
1926
+ Kleshchev partition.
1927
+
1928
+ EXAMPLES::
1929
+
1930
+ sage: from sage.combinat.partition_kleshchev import _is_regular
1931
+ sage: I2 = IntegerModRing(2)
1932
+ sage: _is_regular([[3,1,1], [3,2]], [I2(0),I2(2)], 'LS')
1933
+ False
1934
+ sage: I3 = IntegerModRing(3)
1935
+ sage: _is_regular([[3,1,1], [3,2]], [I3(0),I3(2)], 'LS')
1936
+ True
1937
+ sage: _is_regular([[], []], [I3(0),I3(2)], 'LS')
1938
+ True
1939
+ """
1940
+ if all(part == [] for part in kpt):
1941
+ return True
1942
+ convention = convention[0] + 'G'
1943
+ cell = _a_good_cell(kpt, multicharge, convention)
1944
+ while cell is not None:
1945
+ k, r, _ = cell
1946
+ if kpt[k][r] == 1:
1947
+ kpt[k].pop()
1948
+ else:
1949
+ kpt[k][r] -= 1
1950
+ cell = _a_good_cell(kpt, multicharge, convention)
1951
+ return all(part == [] for part in kpt)
1952
+
1953
+
1954
+ def _is_restricted(kpt, multicharge, convention):
1955
+ """
1956
+ Return ``True`` if ``kpt`` is an ``multicharge``-restricted
1957
+ Kleshchev partition.
1958
+
1959
+ EXAMPLES::
1960
+
1961
+ sage: from sage.combinat.partition_kleshchev import _is_restricted
1962
+ sage: I2 = IntegerModRing(2)
1963
+ sage: _is_restricted([[3,2,1], [3,1,1]], [I2(0),I2(2)], 'RG')
1964
+ False
1965
+ sage: I3 = IntegerModRing(3)
1966
+ sage: _is_restricted([[3,2,1], [3,1,1]], [I3(0),I3(2)], 'RG')
1967
+ True
1968
+ sage: _is_restricted([[], []], [I3(0),I3(2)], 'RG')
1969
+ True
1970
+ """
1971
+ if all(not part for part in kpt):
1972
+ return True
1973
+ convention = convention[0] + 'S'
1974
+ cell = _a_good_cell(kpt, multicharge, convention)
1975
+ while cell is not None:
1976
+ k, r, _ = cell
1977
+ if kpt[k][r] == 1:
1978
+ kpt[k].pop()
1979
+ else:
1980
+ kpt[k][r] -= 1
1981
+ cell = _a_good_cell(kpt, multicharge, convention)
1982
+ return all(not part for part in kpt)