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,3774 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ # sage.doctest: needs sage.combinat sage.modules sage.groups
3
+ r"""
4
+ Symmetric group algebra
5
+ """
6
+ # ****************************************************************************
7
+ # Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,
8
+ #
9
+ # Distributed under the terms of the GNU General Public License (GPL)
10
+ # https://www.gnu.org/licenses/
11
+ # ****************************************************************************
12
+ import itertools
13
+
14
+ from sage.algebras.cellular_basis import CellularBasis
15
+ from sage.algebras.group_algebra import GroupAlgebra_class
16
+ from sage.arith.misc import factorial
17
+ from sage.categories.algebras_with_basis import AlgebrasWithBasis
18
+ from sage.categories.weyl_groups import WeylGroups
19
+ from sage.combinat.free_module import CombinatorialFreeModule
20
+ from sage.combinat.partition import Partitions, Partitions_n, _Partitions
21
+ from sage.combinat.permutation import (
22
+ Permutation,
23
+ Permutations,
24
+ from_permutation_group_element,
25
+ )
26
+ from sage.combinat.permutation_cython import left_action_same_n, right_action_same_n
27
+ from sage.combinat.skew_tableau import SkewTableau
28
+ from sage.combinat.tableau import (
29
+ StandardTableaux,
30
+ StandardTableaux_shape,
31
+ StandardTableaux_size,
32
+ Tableau,
33
+ )
34
+ from sage.matrix.constructor import matrix
35
+ from sage.misc.cachefunc import cached_method
36
+ from sage.misc.lazy_attribute import lazy_attribute
37
+ from sage.misc.lazy_import import lazy_import
38
+ from sage.misc.persist import register_unpickle_override
39
+ from sage.modules.free_module_element import vector
40
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
41
+ from sage.rings.rational_field import QQ
42
+
43
+ lazy_import('sage.groups.perm_gps.permgroup_element',
44
+ 'PermutationGroupElement')
45
+
46
+
47
+ # TODO: Remove this function and replace it with the class
48
+ # TODO: Create parents for other bases (such as the seminormal basis)
49
+
50
+
51
+ def SymmetricGroupAlgebra(R, W, category=None):
52
+ r"""
53
+ Return the symmetric group algebra of order ``W`` over the ring ``R``.
54
+
55
+ INPUT:
56
+
57
+ - ``W`` -- a symmetric group; alternatively an integer `n` can be
58
+ provided, as shorthand for ``Permutations(n)``.
59
+ - ``R`` -- a base ring
60
+ - ``category`` -- a category (default: the category of ``W``)
61
+
62
+ This supports several implementations of the symmetric group. At
63
+ this point this has been tested with ``W=Permutations(n)`` and
64
+ ``W=SymmetricGroup(n)``.
65
+
66
+ .. WARNING::
67
+
68
+ Some features are failing in the latter case, in particular if
69
+ the domain of the symmetric group is not `1,\ldots,n`.
70
+
71
+ .. NOTE::
72
+
73
+ The brave can also try setting ``W=WeylGroup(['A',n-1])``, but
74
+ little support for this currently exists.
75
+
76
+ EXAMPLES::
77
+
78
+ sage: QS3 = SymmetricGroupAlgebra(QQ, 3); QS3
79
+ Symmetric group algebra of order 3 over Rational Field
80
+ sage: QS3(1)
81
+ [1, 2, 3]
82
+ sage: QS3(2)
83
+ 2*[1, 2, 3]
84
+ sage: basis = [QS3(p) for p in Permutations(3)]
85
+ sage: a = sum(basis); a
86
+ [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
87
+ sage: a^2
88
+ 6*[1, 2, 3] + 6*[1, 3, 2] + 6*[2, 1, 3] + 6*[2, 3, 1]
89
+ + 6*[3, 1, 2] + 6*[3, 2, 1]
90
+ sage: a^2 == 6*a
91
+ True
92
+ sage: b = QS3([3, 1, 2])
93
+ sage: b
94
+ [3, 1, 2]
95
+ sage: b*a
96
+ [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
97
+ sage: b*a == a
98
+ True
99
+
100
+ We now construct the symmetric group algebra by providing
101
+ explicitly the underlying group::
102
+
103
+ sage: SGA = SymmetricGroupAlgebra(QQ, Permutations(4)); SGA
104
+ Symmetric group algebra of order 4 over Rational Field
105
+ sage: SGA.group()
106
+ Standard permutations of 4
107
+ sage: SGA.an_element()
108
+ [1, 2, 3, 4] + 2*[1, 2, 4, 3] + 3*[1, 3, 2, 4] + [4, 1, 2, 3]
109
+
110
+ sage: SGA = SymmetricGroupAlgebra(QQ, SymmetricGroup(4)); SGA
111
+ Symmetric group algebra of order 4 over Rational Field
112
+ sage: SGA.group()
113
+ Symmetric group of order 4! as a permutation group
114
+ sage: SGA.an_element()
115
+ () + (2,3,4) + 2*(1,3)(2,4) + 3*(1,4)(2,3)
116
+
117
+ sage: SGA = SymmetricGroupAlgebra(QQ, WeylGroup(["A",3], prefix='s')); SGA
118
+ Symmetric group algebra of order 4 over Rational Field
119
+ sage: SGA.group()
120
+ Weyl Group of type ['A', 3] (as a matrix group acting
121
+ on the ambient space)
122
+ sage: SGA.an_element()
123
+ s1*s2*s3 + ... + 1
124
+
125
+ The preferred way to construct the symmetric group algebra is to
126
+ go through the usual ``algebra`` method::
127
+
128
+ sage: SGA = Permutations(3).algebra(QQ); SGA
129
+ Symmetric group algebra of order 3 over Rational Field
130
+ sage: SGA.group()
131
+ Standard permutations of 3
132
+
133
+ sage: SGA = SymmetricGroup(3).algebra(QQ); SGA
134
+ Symmetric group algebra of order 3 over Rational Field
135
+ sage: SGA.group()
136
+ Symmetric group of order 3! as a permutation group
137
+
138
+ The canonical embedding from the symmetric group algebra of order
139
+ `n` to the symmetric group algebra of order `p > n` is available as
140
+ a coercion::
141
+
142
+ sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
143
+ sage: QS4 = SymmetricGroupAlgebra(QQ, 4)
144
+ sage: QS4.coerce_map_from(QS3)
145
+ Generic morphism:
146
+ From: Symmetric group algebra of order 3 over Rational Field
147
+ To: Symmetric group algebra of order 4 over Rational Field
148
+
149
+ sage: x3 = QS3([3,1,2]) + 2 * QS3([2,3,1]); x3
150
+ 2*[2, 3, 1] + [3, 1, 2]
151
+ sage: QS4(x3)
152
+ 2*[2, 3, 1, 4] + [3, 1, 2, 4]
153
+
154
+ This allows for mixed expressions::
155
+
156
+ sage: x4 = 3 * QS4([3, 1, 4, 2])
157
+ sage: x3 + x4
158
+ 2*[2, 3, 1, 4] + [3, 1, 2, 4] + 3*[3, 1, 4, 2]
159
+
160
+ sage: QS0 = SymmetricGroupAlgebra(QQ, 0)
161
+ sage: QS1 = SymmetricGroupAlgebra(QQ, 1)
162
+ sage: x0 = QS0([])
163
+ sage: x1 = QS1([1])
164
+ sage: x0 * x1
165
+ [1]
166
+ sage: x3 - (2*x0 + x1) - x4
167
+ -3*[1, 2, 3, 4] + 2*[2, 3, 1, 4] + [3, 1, 2, 4] - 3*[3, 1, 4, 2]
168
+
169
+ Caveat: to achieve this, constructing ``SymmetricGroupAlgebra(QQ,
170
+ 10)`` currently triggers the construction of all symmetric group
171
+ algebras of smaller order. Is this a feature we really want to have?
172
+
173
+ .. WARNING::
174
+
175
+ The semantics of multiplication in symmetric group algebras
176
+ with index set ``Permutations(n)`` is determined by the order
177
+ in which permutations are multiplied, which currently defaults
178
+ to "in such a way that multiplication is associative with
179
+ permutations acting on integers from the right", but can be
180
+ changed to the opposite order at runtime by setting the global
181
+ variable ``Permutations.options['mult']`` (see
182
+ :meth:`sage.combinat.permutation.Permutations.options` ).
183
+ On the other hand, the semantics of multiplication in symmetric
184
+ group algebras with index set ``SymmetricGroup(n)`` does not
185
+ depend on this global variable. (This has the awkward
186
+ consequence that the coercions between these two sorts of
187
+ symmetric group algebras do not respect multiplication when
188
+ this global variable is set to ``'r2l'``.)
189
+ In view of this, it is recommended that code not rely on the
190
+ usual multiplication function, but rather use the methods
191
+ :meth:`left_action_product` and :meth:`right_action_product`
192
+ for multiplying permutations (these methods don't depend on the
193
+ setting). See :issue:`14885` for more information.
194
+
195
+ We conclude by constructing the algebra of the symmetric group as
196
+ a monoid algebra::
197
+
198
+ sage: QS3 = SymmetricGroupAlgebra(QQ, 3, category=Monoids())
199
+ sage: QS3.category()
200
+ Category of finite dimensional cellular monoid algebras
201
+ over Rational Field
202
+ sage: TestSuite(QS3).run(skip=['_test_construction'])
203
+
204
+
205
+ TESTS::
206
+
207
+ sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
208
+ sage: TestSuite(QS3).run()
209
+
210
+ sage: QS3.group()
211
+ Standard permutations of 3
212
+
213
+ sage: QS3.one_basis()
214
+ [1, 2, 3]
215
+
216
+ sage: p1 = Permutation([1,2,3])
217
+ sage: p2 = Permutation([2,1,3])
218
+ sage: QS3.product_on_basis(p1,p2)
219
+ [2, 1, 3]
220
+
221
+ sage: W = WeylGroup(["A",3])
222
+ sage: SGA = SymmetricGroupAlgebra(QQ, W)
223
+ sage: SGA.group() is W
224
+ True
225
+ sage: TestSuite(SGA).run(skip=["_test_cellular", "_test_construction"])
226
+ sage: W = WeylGroup(["A",2])
227
+ sage: SGA = SymmetricGroupAlgebra(QQ, W)
228
+ sage: SGA._test_cellular()
229
+
230
+ sage: SG = SymmetricGroupAlgebra(ZZ, 3)
231
+ sage: SG.group().conjugacy_classes_representatives()
232
+ [[1, 2, 3], [2, 1, 3], [2, 3, 1]]
233
+
234
+ sage: SGg = SymmetricGroup(3).algebra(ZZ)
235
+ sage: SGg.group().conjugacy_classes_representatives()
236
+ [(), (1,2), (1,2,3)]
237
+ """
238
+ from sage.rings.semirings.non_negative_integer_semiring import NN
239
+ if W in NN:
240
+ W = Permutations(W)
241
+ if category is None:
242
+ category = W.category()
243
+ return SymmetricGroupAlgebra_n(R, W, category.Algebras(R))
244
+
245
+
246
+ class SymmetricGroupAlgebra_n(GroupAlgebra_class):
247
+
248
+ def __init__(self, R, W, category):
249
+ """
250
+ TESTS::
251
+
252
+ sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
253
+ sage: TestSuite(QS3).run()
254
+
255
+ sage: QS3 in GroupAlgebras(QQ)
256
+ True
257
+ sage: QS3 in FiniteDimensionalAlgebrasWithBasis(QQ)
258
+ True
259
+
260
+ Check that :issue:`16926` works::
261
+
262
+ sage: S = SymmetricGroup(4)
263
+ sage: SGA = S.algebra(QQ)
264
+ sage: TestSuite(SGA).run(skip='_test_cellular')
265
+ sage: SGA._test_cellular() # long time
266
+
267
+ Checking that coercion works between equivalent indexing sets::
268
+
269
+ sage: G = SymmetricGroup(4).algebra(QQ)
270
+ sage: S = SymmetricGroupAlgebra(QQ,4)
271
+ sage: S(G.an_element())
272
+ [1, 2, 3, 4] + [1, 3, 4, 2] + 2*[3, 4, 1, 2] + 3*[4, 3, 2, 1]
273
+ sage: G(S.an_element())
274
+ () + 2*(3,4) + 3*(2,3) + (1,4,3,2)
275
+
276
+ Checking the recovery of `n`:
277
+
278
+ sage: SymmetricGroup(4).algebra(QQ).n
279
+ 4
280
+ sage: SymmetricGroup(1).algebra(QQ).n
281
+ 1
282
+ sage: SymmetricGroup(0).algebra(QQ).n
283
+ 0
284
+ sage: Permutations(4).algebra(QQ).n
285
+ 4
286
+ sage: Permutations(1).algebra(QQ).n
287
+ 1
288
+ sage: Permutations(0).algebra(QQ).n
289
+ 0
290
+ sage: SymmetricGroupAlgebra(QQ, WeylGroup(["A",3])).n
291
+ 4
292
+ sage: SymmetricGroupAlgebra(QQ, WeylGroup(["A",1])).n
293
+ 2
294
+ sage: SymmetricGroupAlgebra(QQ, WeylGroup(["A",0])).n # todo: not implemented
295
+ 1
296
+ """
297
+ if W not in WeylGroups or W.cartan_type().type() != 'A':
298
+ raise ValueError("W (=%s) should be a symmetric group or a nonnegative integer")
299
+ rank = W.cartan_type().rank()
300
+ if rank == 0: # Ambiguous: n=0 or n=1?
301
+ # The following trick works for both SymmetricGroup(n) and
302
+ # Permutations(n) and it's currently not possible to
303
+ # construct the WeylGroup for n=0
304
+ self.n = W.degree()
305
+ else:
306
+ self.n = W.cartan_type().rank() + 1
307
+ self._idempotent_cache = {}
308
+ category = category.Unital().FiniteDimensional().WithBasis().Cellular()
309
+ GroupAlgebra_class.__init__(self, R, W, prefix='',
310
+ latex_prefix='', category=category)
311
+
312
+ # Mixin class for extra methods for representations
313
+ from sage.combinat.specht_module import SymmetricGroupRepresentation
314
+ self._representation_mixin_class = SymmetricGroupRepresentation
315
+
316
+ def _repr_(self):
317
+ """
318
+ Return a string representation of ``self``.
319
+
320
+ EXAMPLES::
321
+
322
+ sage: SymmetricGroupAlgebra(QQ, 3)
323
+ Symmetric group algebra of order 3 over Rational Field
324
+ """
325
+ return "Symmetric group algebra of order {} over {}".format(self.n, self.base_ring())
326
+
327
+ def _coerce_map_from_(self, S):
328
+ """
329
+ Return ``True`` or a morphism if there exists a coercion from ``S``
330
+ into ``self`` or ``False`` otherwise.
331
+
332
+ EXAMPLES:
333
+
334
+ Symmetric group algebras::
335
+
336
+ sage: SGA4 = SymmetricGroupAlgebra(QQ, 4)
337
+ sage: SGA2 = SymmetricGroupAlgebra(QQ, 2)
338
+ sage: SGA4.has_coerce_map_from(SGA2)
339
+ True
340
+ sage: SGA2Z = SymmetricGroupAlgebra(ZZ, 2)
341
+ sage: SGA4.has_coerce_map_from(SGA2Z)
342
+ True
343
+ sage: p = Permutation([2,1])
344
+ sage: SGA4(-3*SGA2Z.monomial(p))
345
+ -3*[2, 1, 3, 4]
346
+
347
+ Descent algebras::
348
+
349
+ sage: DA = DescentAlgebra(QQ, 4)
350
+ sage: SGA4 = SymmetricGroupAlgebra(QQ, 4)
351
+ sage: SGA4.has_coerce_map_from(DA.D())
352
+ True
353
+ sage: SGA4.has_coerce_map_from(DA.B())
354
+ True
355
+ sage: SGA4.has_coerce_map_from(DA.I())
356
+ True
357
+ sage: x = DA.B()[4]
358
+ sage: SGA4(x)
359
+ [1, 2, 3, 4]
360
+
361
+ sage: DAB = DescentAlgebra(ZZ,2).B()
362
+ sage: SGA4.has_coerce_map_from(DAB)
363
+ True
364
+ sage: SGA4(DAB[2])
365
+ [1, 2, 3, 4]
366
+
367
+ sage: QSG4 = SymmetricGroup(4).algebra(ZZ)
368
+ sage: DAB = DescentAlgebra(ZZ,4).B()
369
+ sage: QSG4(DAB[1,2,1])
370
+ () + (3,4) + (2,3,4) + (1,2) + (1,2)(3,4) + (1,2,3,4)
371
+ + (1,3,2) + (1,3,4,2) + (1,3,4) + (1,4,3,2) + (1,4,2) + (1,4)
372
+ """
373
+ # Symmetric group algebras of smaller rank
374
+ if (isinstance(S, SymmetricGroupAlgebra_n) and S.n <= self.n and
375
+ self.base_ring().has_coerce_map_from(S.base_ring())):
376
+ return S.canonical_embedding(self)
377
+
378
+ # Descent algebras
379
+ from sage.combinat.descent_algebra import DescentAlgebra
380
+ # TODO: A better way to handle all of the bases
381
+ if isinstance(S, (DescentAlgebra.D, DescentAlgebra.B, DescentAlgebra.I)):
382
+ # Same rank and base ring, just the natural morphism
383
+ if (S.realization_of()._n == self.n and
384
+ self.base_ring() == S.base_ring() and
385
+ self._indices == Permutations(self.n)):
386
+ return S.to_symmetric_group_algebra
387
+ # Otherwise compose with the canonical embedding in order to ensure
388
+ # that the right base ring and the right index set are being used.
389
+ # Slightly hacky!
390
+ if (S.realization_of()._n <= self.n and
391
+ self.base_ring().has_coerce_map_from(S.base_ring())):
392
+ phi = S.to_symmetric_group_algebra
393
+ return phi.codomain().canonical_embedding(self) * phi
394
+
395
+ return super()._coerce_map_from_(S)
396
+
397
+ def _element_constructor_(self, x):
398
+ """
399
+ Construct an element of ``self``.
400
+
401
+ EXAMPLES::
402
+
403
+ sage: S = SymmetricGroupAlgebra(QQ, 4)
404
+ sage: G = SymmetricGroup(3)
405
+ sage: p = Permutation((1,2))
406
+ sage: S(p)
407
+ [2, 1, 3, 4]
408
+ sage: S(G(p))
409
+ [2, 1, 3, 4]
410
+ sage: S(p) == S(G(p))
411
+ True
412
+ """
413
+ if isinstance(x, Permutation):
414
+ return self.monomial_from_smaller_permutation(x)
415
+ if isinstance(x, PermutationGroupElement):
416
+ return self.monomial_from_smaller_permutation(
417
+ from_permutation_group_element(x))
418
+
419
+ return super()._element_constructor_(x)
420
+
421
+ def _sibling(self, n):
422
+ r"""
423
+ Return the sibling group algebra of order `n`.
424
+
425
+ EXAMPLES::
426
+
427
+ sage: SGA = SymmetricGroupAlgebra(QQ, Permutations(3))._sibling(4); SGA
428
+ Symmetric group algebra of order 4 over Rational Field
429
+ sage: SGA.group()
430
+ Standard permutations of 4
431
+
432
+ sage: SGA = SymmetricGroupAlgebra(QQ, SymmetricGroup(3))._sibling(4); SGA
433
+ Symmetric group algebra of order 4 over Rational Field
434
+ sage: SGA.group()
435
+ Symmetric group of order 4! as a permutation group
436
+
437
+ sage: SGA = SymmetricGroupAlgebra(QQ, WeylGroup(["A",2]))._sibling(4); SGA
438
+ Traceback (most recent call last):
439
+ ...
440
+ NotImplementedError: Constructing the sibling algebra of a different order
441
+ only implemented for PermutationGroup and SymmetricGroup
442
+ """
443
+ try:
444
+ W = self.basis().keys().__class__(n)
445
+ except (AttributeError, TypeError, ValueError):
446
+ raise NotImplementedError("Constructing the sibling algebra of a different order "
447
+ "only implemented for PermutationGroup and SymmetricGroup")
448
+ return SymmetricGroupAlgebra(self.base_ring(), W)
449
+
450
+ # _repr_ customization: output the basis element indexed by [1,2,3] as [1,2,3]
451
+ _repr_option_bracket = False
452
+
453
+ def left_action_product(self, left, right):
454
+ """
455
+ Return the product of two elements ``left`` and ``right`` of
456
+ ``self``, where multiplication is defined in such a way that
457
+ for two permutations `p` and `q`, the product `pq` is the
458
+ permutation obtained by first applying `q` and then applying
459
+ `p`. This definition of multiplication is tailored to make
460
+ multiplication of permutations associative with their action on
461
+ numbers if permutations are to act on numbers from the left.
462
+
463
+ EXAMPLES::
464
+
465
+ sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
466
+ sage: p1 = Permutation([2, 1, 3])
467
+ sage: p2 = Permutation([3, 1, 2])
468
+ sage: QS3.left_action_product(QS3(p1), QS3(p2))
469
+ [3, 2, 1]
470
+ sage: x = QS3([1, 2, 3]) - 2*QS3([1, 3, 2])
471
+ sage: y = 1/2 * QS3([3, 1, 2]) + 3*QS3([1, 2, 3])
472
+ sage: QS3.left_action_product(x, y)
473
+ 3*[1, 2, 3] - 6*[1, 3, 2] - [2, 1, 3] + 1/2*[3, 1, 2]
474
+ sage: QS3.left_action_product(0, x)
475
+ 0
476
+
477
+ The method coerces its input into the algebra ``self``::
478
+
479
+ sage: QS4 = SymmetricGroupAlgebra(QQ, 4)
480
+ sage: QS4.left_action_product(QS3([1, 2, 3]), QS3([2, 1, 3]))
481
+ [2, 1, 3, 4]
482
+ sage: QS4.left_action_product(1, Permutation([4, 1, 2, 3]))
483
+ [4, 1, 2, 3]
484
+
485
+ TESTS::
486
+
487
+ sage: QS4 = SymmetricGroup(4).algebra(QQ)
488
+ sage: QS4.left_action_product(QS4((1,2)), QS4((2,3)))
489
+ (1,2,3)
490
+ sage: QS4.left_action_product(1, QS4((1,2)))
491
+ (1,2)
492
+
493
+ .. WARNING::
494
+
495
+ Note that coercion presently works from permutations of ``n``
496
+ into the ``n``-th symmetric group algebra, and also from all
497
+ smaller symmetric group algebras into the ``n``-th symmetric
498
+ group algebra, but not from permutations of integers smaller
499
+ than ``n`` into the ``n``-th symmetric group algebra.
500
+ """
501
+ a = self(left)
502
+ b = self(right)
503
+ if not isinstance(self._indices, Permutations):
504
+ return b * a
505
+ P = Permutations(self.n)
506
+ return self.sum_of_terms([(P(left_action_same_n(p._list, q._list)), x * y)
507
+ for (p, x) in a for (q, y) in b])
508
+ # Why did we use left_action_same_n instead of
509
+ # left_action_product?
510
+ # Because having cast a and b into self, we already know that
511
+ # p and q are permutations of the same number of elements,
512
+ # and thus we don't need to waste our time on the input
513
+ # sanitizing of left_action_product.
514
+
515
+ def right_action_product(self, left, right):
516
+ """
517
+ Return the product of two elements ``left`` and ``right`` of
518
+ ``self``, where multiplication is defined in such a way that
519
+ for two permutations `p` and `q`, the product `pq` is the
520
+ permutation obtained by first applying `p` and then applying
521
+ `q`. This definition of multiplication is tailored to make
522
+ multiplication of permutations associative with their action on
523
+ numbers if permutations are to act on numbers from the right.
524
+
525
+ EXAMPLES::
526
+
527
+ sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
528
+ sage: p1 = Permutation([2, 1, 3])
529
+ sage: p2 = Permutation([3, 1, 2])
530
+ sage: QS3.right_action_product(QS3(p1), QS3(p2))
531
+ [1, 3, 2]
532
+ sage: x = QS3([1, 2, 3]) - 2*QS3([1, 3, 2])
533
+ sage: y = 1/2 * QS3([3, 1, 2]) + 3*QS3([1, 2, 3])
534
+ sage: QS3.right_action_product(x, y)
535
+ 3*[1, 2, 3] - 6*[1, 3, 2] + 1/2*[3, 1, 2] - [3, 2, 1]
536
+ sage: QS3.right_action_product(0, x)
537
+ 0
538
+
539
+ The method coerces its input into the algebra ``self``::
540
+
541
+ sage: QS4 = SymmetricGroupAlgebra(QQ, 4)
542
+ sage: QS4.right_action_product(QS3([1, 2, 3]), QS3([2, 1, 3]))
543
+ [2, 1, 3, 4]
544
+ sage: QS4.right_action_product(1, Permutation([4, 1, 2, 3]))
545
+ [4, 1, 2, 3]
546
+
547
+ TESTS::
548
+
549
+ sage: QS4 = SymmetricGroup(4).algebra(QQ)
550
+ sage: QS4.right_action_product(QS4((1,2)), QS4((2,3)))
551
+ (1,3,2)
552
+ sage: QS4.right_action_product(1, QS4((1,2)))
553
+ (1,2)
554
+
555
+ .. WARNING::
556
+
557
+ Note that coercion presently works from permutations of ``n``
558
+ into the ``n``-th symmetric group algebra, and also from all
559
+ smaller symmetric group algebras into the ``n``-th symmetric
560
+ group algebra, but not from permutations of integers smaller
561
+ than ``n`` into the ``n``-th symmetric group algebra.
562
+ """
563
+ a = self(left)
564
+ b = self(right)
565
+ if not isinstance(self._indices, Permutations):
566
+ return a * b
567
+ P = Permutations(self.n)
568
+ return self.sum_of_terms([(P(right_action_same_n(p._list, q._list)), x * y)
569
+ for (p, x) in a for (q, y) in b])
570
+ # Why did we use right_action_same_n instead of
571
+ # right_action_product?
572
+ # Because having cast a and b into self, we already know that
573
+ # p and q are permutations of the same number of elements,
574
+ # and thus we don't need to waste our time on the input
575
+ # sanitizing of right_action_product.
576
+
577
+ def canonical_embedding(self, other):
578
+ r"""
579
+ Return the canonical coercion of ``self`` into a symmetric
580
+ group algebra ``other``.
581
+
582
+ INPUT:
583
+
584
+ - ``other`` -- a symmetric group algebra with order `p`
585
+ satisfying `p \geq n`, where `n` is the order of ``self``,
586
+ over a ground ring into which the ground ring of ``self``
587
+ coerces.
588
+
589
+ EXAMPLES::
590
+
591
+ sage: QS2 = SymmetricGroupAlgebra(QQ, 2)
592
+ sage: QS4 = SymmetricGroupAlgebra(QQ, 4)
593
+ sage: phi = QS2.canonical_embedding(QS4); phi
594
+ Generic morphism:
595
+ From: Symmetric group algebra of order 2 over Rational Field
596
+ To: Symmetric group algebra of order 4 over Rational Field
597
+
598
+ sage: x = QS2([2,1]) + 2 * QS2([1,2])
599
+ sage: phi(x)
600
+ 2*[1, 2, 3, 4] + [2, 1, 3, 4]
601
+
602
+ sage: loads(dumps(phi))
603
+ Generic morphism:
604
+ From: Symmetric group algebra of order 2 over Rational Field
605
+ To: Symmetric group algebra of order 4 over Rational Field
606
+
607
+ sage: ZS2 = SymmetricGroupAlgebra(ZZ, 2)
608
+ sage: phi = ZS2.canonical_embedding(QS4); phi
609
+ Generic morphism:
610
+ From: Symmetric group algebra of order 2 over Integer Ring
611
+ To: Symmetric group algebra of order 4 over Rational Field
612
+
613
+ sage: phi = ZS2.canonical_embedding(QS2); phi
614
+ Generic morphism:
615
+ From: Symmetric group algebra of order 2 over Integer Ring
616
+ To: Symmetric group algebra of order 2 over Rational Field
617
+
618
+ sage: QS4.canonical_embedding(QS2)
619
+ Traceback (most recent call last):
620
+ ...
621
+ ValueError: There is no canonical embedding from Symmetric group
622
+ algebra of order 2 over Rational Field to Symmetric group
623
+ algebra of order 4 over Rational Field
624
+
625
+ sage: QS4g = SymmetricGroup(4).algebra(QQ)
626
+ sage: QS4.canonical_embedding(QS4g)(QS4([1,3,2,4]))
627
+ (2,3)
628
+ sage: QS4g.canonical_embedding(QS4)(QS4g((2,3)))
629
+ [1, 3, 2, 4]
630
+ sage: ZS2.canonical_embedding(QS4g)(ZS2([2,1]))
631
+ (1,2)
632
+ sage: ZS2g = SymmetricGroup(2).algebra(ZZ)
633
+ sage: ZS2g.canonical_embedding(QS4)(ZS2g((1,2)))
634
+ [2, 1, 3, 4]
635
+ """
636
+ if not isinstance(other, SymmetricGroupAlgebra_n) or self.n > other.n:
637
+ raise ValueError("There is no canonical embedding from {0} to {1}".format(other, self))
638
+ return self.module_morphism(other.monomial_from_smaller_permutation, codomain=other) # category = self.category() (currently broken)
639
+
640
+ def monomial_from_smaller_permutation(self, permutation):
641
+ """
642
+ Convert ``permutation`` into a permutation, possibly extending it
643
+ to the appropriate size, and return the corresponding basis
644
+ element of ``self``.
645
+
646
+ EXAMPLES::
647
+
648
+ sage: QS5 = SymmetricGroupAlgebra(QQ, 5)
649
+ sage: QS5.monomial_from_smaller_permutation([])
650
+ [1, 2, 3, 4, 5]
651
+ sage: QS5.monomial_from_smaller_permutation(Permutation([3,1,2]))
652
+ [3, 1, 2, 4, 5]
653
+ sage: QS5.monomial_from_smaller_permutation([5,3,4,1,2])
654
+ [5, 3, 4, 1, 2]
655
+ sage: QS5.monomial_from_smaller_permutation(SymmetricGroup(2)((1,2)))
656
+ [2, 1, 3, 4, 5]
657
+
658
+ sage: QS5g = SymmetricGroup(5).algebra(QQ)
659
+ sage: QS5g.monomial_from_smaller_permutation([2,1])
660
+ (1,2)
661
+
662
+ TESTS::
663
+
664
+ sage: QS5.monomial_from_smaller_permutation([5,3,4,1,2]).parent()
665
+ Symmetric group algebra of order 5 over Rational Field
666
+ """
667
+ P = self.basis().keys()
668
+ return self.monomial(P(permutation))
669
+
670
+ def antipode(self, x):
671
+ r"""
672
+ Return the image of the element ``x`` of ``self`` under the
673
+ antipode of the Hopf algebra ``self`` (where the
674
+ comultiplication is the usual one on a group algebra).
675
+
676
+ Explicitly, this is obtained by replacing each permutation
677
+ `\sigma` by `\sigma^{-1}` in ``x`` while keeping all
678
+ coefficients as they are.
679
+
680
+ EXAMPLES::
681
+
682
+ sage: QS4 = SymmetricGroupAlgebra(QQ, 4)
683
+ sage: QS4.antipode(2 * QS4([1, 3, 4, 2]) - 1/2 * QS4([1, 4, 2, 3]))
684
+ -1/2*[1, 3, 4, 2] + 2*[1, 4, 2, 3]
685
+ sage: all( QS4.antipode(QS4(p)) == QS4(p.inverse())
686
+ ....: for p in Permutations(4) )
687
+ True
688
+
689
+ sage: ZS3 = SymmetricGroupAlgebra(ZZ, 3)
690
+ sage: ZS3.antipode(ZS3.zero())
691
+ 0
692
+ sage: ZS3.antipode(-ZS3(Permutation([2, 3, 1])))
693
+ -[3, 1, 2]
694
+ """
695
+ return self.sum_of_terms([(p.inverse(), coeff) for
696
+ (p, coeff) in self(x)],
697
+ distinct=True)
698
+
699
+ @cached_method
700
+ def cell_poset(self):
701
+ """
702
+ Return the cell poset of ``self``.
703
+
704
+ EXAMPLES::
705
+
706
+ sage: S = SymmetricGroupAlgebra(QQ, 4)
707
+ sage: S.cell_poset()
708
+ Finite poset containing 5 elements
709
+ """
710
+ from sage.combinat.posets.posets import Poset
711
+ return Poset([Partitions_n(self.n), lambda x, y: y.dominates(x)])
712
+
713
+ def cell_module_indices(self, la):
714
+ r"""
715
+ Return the indices of the cell module of ``self``
716
+ indexed by ``la`` .
717
+
718
+ This is the finite set `M(\lambda)`.
719
+
720
+ EXAMPLES::
721
+
722
+ sage: S = SymmetricGroupAlgebra(QQ, 4)
723
+ sage: S.cell_module_indices([3,1])
724
+ Standard tableaux of shape [3, 1]
725
+ """
726
+ return StandardTableaux(la)
727
+
728
+ def _from_cellular_index(self, x):
729
+ r"""
730
+ Return the image in ``self`` from the index of the
731
+ cellular basis ``x``.
732
+
733
+ EXAMPLES::
734
+
735
+ sage: S = SymmetricGroupAlgebra(QQ, 3)
736
+ sage: C = S.cellular_basis()
737
+ sage: [S._from_cellular_index(i) for i in C.basis().keys()]
738
+ [1/6*[1, 2, 3] - 1/6*[1, 3, 2] - 1/6*[2, 1, 3] + 1/6*[2, 3, 1]
739
+ + 1/6*[3, 1, 2] - 1/6*[3, 2, 1],
740
+ 1/3*[1, 2, 3] + 1/6*[1, 3, 2] - 1/3*[2, 1, 3] - 1/6*[2, 3, 1]
741
+ - 1/6*[3, 1, 2] + 1/6*[3, 2, 1],
742
+ 1/3*[1, 3, 2] + 1/3*[2, 3, 1] - 1/3*[3, 1, 2] - 1/3*[3, 2, 1],
743
+ 1/4*[1, 3, 2] - 1/4*[2, 3, 1] + 1/4*[3, 1, 2] - 1/4*[3, 2, 1],
744
+ 1/3*[1, 2, 3] - 1/6*[1, 3, 2] + 1/3*[2, 1, 3] - 1/6*[2, 3, 1]
745
+ - 1/6*[3, 1, 2] - 1/6*[3, 2, 1],
746
+ 1/6*[1, 2, 3] + 1/6*[1, 3, 2] + 1/6*[2, 1, 3]
747
+ + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] + 1/6*[3, 2, 1]]
748
+
749
+ sage: S = SymmetricGroupAlgebra(GF(3), 3)
750
+ sage: C = S.cellular_basis()
751
+ sage: [S._from_cellular_index(i) for i in C.basis().keys()]
752
+ [[1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1],
753
+ [1, 2, 3] + [2, 1, 3],
754
+ [1, 3, 2] + [3, 1, 2],
755
+ [1, 3, 2] + [2, 3, 1],
756
+ [1, 2, 3] + [3, 2, 1],
757
+ [1, 2, 3]]
758
+ sage: TestSuite(C).run()
759
+ """
760
+ if ~factorial(self.n) not in self.base_ring():
761
+ func = self.murphy_basis_element
762
+ else:
763
+ func = self.epsilon_ik
764
+
765
+ SGA = SymmetricGroupAlgebra(self.base_ring(), self.n)
766
+ P = self.basis().keys()
767
+ if SGA.basis().keys() is P: # Indexed by permutations
768
+ return func(x[1], x[2])
769
+ from sage.groups.perm_gps.permgroup_named import SymmetricGroup
770
+ if P == SymmetricGroup(self.n):
771
+ return func(x[1], x[2])
772
+ ret = func(x[1], x[2], mult='r2l')
773
+ try:
774
+ return self(ret)
775
+ except TypeError:
776
+ P = self.basis().keys()
777
+ return self._from_dict({P(i.to_matrix()): c for i, c in ret},
778
+ remove_zeros=False)
779
+
780
+ def cell_module(self, la, **kwds):
781
+ """
782
+ Return the cell module indexed by ``la``.
783
+
784
+ EXAMPLES::
785
+
786
+ sage: S = SymmetricGroupAlgebra(QQ, 3)
787
+ sage: M = S.cell_module(Partition([2,1])); M
788
+ Cell module indexed by [2, 1] of Cellular basis of
789
+ Symmetric group algebra of order 3 over Rational Field
790
+
791
+ We check that the input ``la`` is standardized::
792
+
793
+ sage: N = S.cell_module([2,1])
794
+ sage: M is N
795
+ True
796
+ """
797
+ la = _Partitions(la)
798
+ kwds['bracket'] = kwds.get('bracket', False)
799
+ return super().cell_module(la, **kwds)
800
+
801
+ def retract_plain(self, f, m):
802
+ r"""
803
+ Return the plain retract of the element `f \in R S_n`
804
+ to `R S_m`, where `m \leq n` (and where `R S_n` is ``self``).
805
+
806
+ If `m` is a nonnegative integer less or equal to `n`, then the
807
+ plain retract from `S_n` to `S_m` is defined as an `R`-linear
808
+ map `S_n \to S_m` which sends every permutation `p \in S_n`
809
+ to
810
+
811
+ .. MATH::
812
+
813
+ \begin{cases} \mbox{pret}(p) &\mbox{if } \mbox{pret}(p)\mbox{ is defined;} \\
814
+ 0 & \mbox{otherwise} \end{cases}.
815
+
816
+ Here `\mbox{pret}(p)` denotes the plain retract of the
817
+ permutation `p` to `S_m`, which is defined in
818
+ :meth:`~sage.combinat.permutation.Permutation.retract_plain`.
819
+
820
+ EXAMPLES::
821
+
822
+ sage: SGA3 = SymmetricGroupAlgebra(QQ, 3)
823
+ sage: SGA3.retract_plain(2*SGA3([1,2,3]) - 4*SGA3([2,1,3]) + 7*SGA3([1,3,2]), 2)
824
+ 2*[1, 2] - 4*[2, 1]
825
+ sage: SGA3.retract_plain(2*SGA3([1,3,2]) - 5*SGA3([2,3,1]), 2)
826
+ 0
827
+
828
+ sage: SGA5 = SymmetricGroupAlgebra(QQ, 5)
829
+ sage: SGA5.retract_plain(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 4)
830
+ 11*[3, 2, 1, 4]
831
+ sage: SGA5.retract_plain(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 3)
832
+ 11*[3, 2, 1]
833
+ sage: SGA5.retract_plain(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 2)
834
+ 0
835
+ sage: SGA5.retract_plain(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 1)
836
+ 0
837
+
838
+ sage: SGA5.retract_plain(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 3)
839
+ 8*[1, 2, 3] - 6*[1, 3, 2]
840
+ sage: SGA5.retract_plain(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 1)
841
+ 8*[1]
842
+ sage: SGA5.retract_plain(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 0)
843
+ 8*[]
844
+
845
+ TESTS:
846
+
847
+ Check this works with other indexing sets::
848
+
849
+ sage: G = SymmetricGroup(4).algebra(QQ)
850
+ sage: G.retract_plain(G.an_element(), 3)
851
+ ()
852
+
853
+ .. SEEALSO::
854
+
855
+ :meth:`retract_direct_product`, :meth:`retract_okounkov_vershik`
856
+ """
857
+ RSm = self._sibling(m)
858
+ I = RSm.group()
859
+ pairs = []
860
+ P = Permutations(self.n)
861
+ for (p, coeff) in f.monomial_coefficients().items():
862
+ p_ret = P(p).retract_plain(m)
863
+ if p_ret is not None:
864
+ pairs.append((I(p_ret), coeff))
865
+ return RSm.sum_of_terms(pairs, distinct=True)
866
+
867
+ def retract_direct_product(self, f, m):
868
+ r"""
869
+ Return the direct-product retract of the element `f \in R S_n`
870
+ to `R S_m`, where `m \leq n` (and where `R S_n` is ``self``).
871
+
872
+ If `m` is a nonnegative integer less or equal to `n`, then the
873
+ direct-product retract from `S_n` to `S_m` is defined as an
874
+ `R`-linear map `S_n \to S_m` which sends every permutation
875
+ `p \in S_n` to
876
+
877
+ .. MATH::
878
+
879
+ \begin{cases} \mbox{dret}(p) &\mbox{if } \mbox{dret}(p)\mbox{ is defined;} \\
880
+ 0 & \mbox{otherwise} \end{cases}.
881
+
882
+ Here `\mbox{dret}(p)` denotes the direct-product retract of the
883
+ permutation `p` to `S_m`, which is defined in
884
+ :meth:`~sage.combinat.permutation.Permutation.retract_direct_product`.
885
+
886
+ EXAMPLES::
887
+
888
+ sage: SGA3 = SymmetricGroupAlgebra(QQ, 3)
889
+ sage: SGA3.retract_direct_product(2*SGA3([1,2,3]) - 4*SGA3([2,1,3]) + 7*SGA3([1,3,2]), 2)
890
+ 2*[1, 2] - 4*[2, 1]
891
+ sage: SGA3.retract_direct_product(2*SGA3([1,3,2]) - 5*SGA3([2,3,1]), 2)
892
+ 0
893
+
894
+ sage: SGA5 = SymmetricGroupAlgebra(QQ, 5)
895
+ sage: SGA5.retract_direct_product(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 4)
896
+ 11*[3, 2, 1, 4]
897
+ sage: SGA5.retract_direct_product(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 3)
898
+ -6*[1, 3, 2] + 11*[3, 2, 1]
899
+ sage: SGA5.retract_direct_product(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 2)
900
+ 0
901
+ sage: SGA5.retract_direct_product(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 1)
902
+ 2*[1]
903
+
904
+ sage: SGA5.retract_direct_product(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 3)
905
+ 8*[1, 2, 3] - 6*[1, 3, 2]
906
+ sage: SGA5.retract_direct_product(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 1)
907
+ 2*[1]
908
+ sage: SGA5.retract_direct_product(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 0)
909
+ 2*[]
910
+
911
+ TESTS:
912
+
913
+ Check this works with other indexing sets::
914
+
915
+ sage: G = SymmetricGroup(4).algebra(QQ)
916
+ sage: G.retract_direct_product(G.an_element(), 3)
917
+ ()
918
+
919
+ .. SEEALSO::
920
+
921
+ :meth:`retract_plain`, :meth:`retract_okounkov_vershik`
922
+ """
923
+ RSm = self._sibling(m)
924
+ I = RSm.group()
925
+ dct = {}
926
+ P = Permutations(self.n)
927
+ for (p, coeff) in f.monomial_coefficients().items():
928
+ p_ret = P(p).retract_direct_product(m)
929
+ if p_ret is not None:
930
+ p_ret = I(p_ret)
931
+ if p_ret not in dct:
932
+ dct[p_ret] = coeff
933
+ else:
934
+ dct[p_ret] += coeff
935
+ return RSm._from_dict(dct)
936
+
937
+ def retract_okounkov_vershik(self, f, m):
938
+ r"""
939
+ Return the Okounkov-Vershik retract of the element `f \in R S_n`
940
+ to `R S_m`, where `m \leq n` (and where `R S_n` is ``self``).
941
+
942
+ If `m` is a nonnegative integer less or equal to `n`, then the
943
+ Okounkov-Vershik retract from `S_n` to `S_m` is defined as an
944
+ `R`-linear map `S_n \to S_m` which sends every permutation
945
+ `p \in S_n` to the Okounkov-Vershik retract of the permutation
946
+ `p` to `S_m`, which is defined in
947
+ :meth:`~sage.combinat.permutation.Permutation.retract_okounkov_vershik`.
948
+
949
+ EXAMPLES::
950
+
951
+ sage: SGA3 = SymmetricGroupAlgebra(QQ, 3)
952
+ sage: SGA3.retract_okounkov_vershik(2*SGA3([1,2,3]) - 4*SGA3([2,1,3]) + 7*SGA3([1,3,2]), 2)
953
+ 9*[1, 2] - 4*[2, 1]
954
+ sage: SGA3.retract_okounkov_vershik(2*SGA3([1,3,2]) - 5*SGA3([2,3,1]), 2)
955
+ 2*[1, 2] - 5*[2, 1]
956
+
957
+ sage: SGA5 = SymmetricGroupAlgebra(QQ, 5)
958
+ sage: SGA5.retract_okounkov_vershik(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 4)
959
+ -6*[1, 3, 2, 4] + 8*[1, 4, 2, 3] + 11*[3, 2, 1, 4]
960
+ sage: SGA5.retract_okounkov_vershik(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 3)
961
+ 2*[1, 3, 2] + 11*[3, 2, 1]
962
+ sage: SGA5.retract_okounkov_vershik(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 2)
963
+ 13*[1, 2]
964
+ sage: SGA5.retract_okounkov_vershik(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 1)
965
+ 13*[1]
966
+
967
+ sage: SGA5.retract_okounkov_vershik(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 3)
968
+ 8*[1, 2, 3] - 6*[1, 3, 2]
969
+ sage: SGA5.retract_okounkov_vershik(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 1)
970
+ 2*[1]
971
+ sage: SGA5.retract_okounkov_vershik(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 0)
972
+ 2*[]
973
+
974
+ TESTS:
975
+
976
+ Check this works with other indexing sets::
977
+
978
+ sage: G = SymmetricGroup(4).algebra(QQ)
979
+ sage: G.retract_okounkov_vershik(G.an_element(), 3)
980
+ () + 4*(2,3) + 2*(1,3)
981
+
982
+ .. SEEALSO::
983
+
984
+ :meth:`retract_plain`, :meth:`retract_direct_product`
985
+ """
986
+ RSm = self._sibling(m)
987
+ I = RSm.group()
988
+ dct = {}
989
+ P = Permutations(self.n)
990
+ for (p, coeff) in f.monomial_coefficients().items():
991
+ p_ret = I(P(p).retract_okounkov_vershik(m))
992
+ if p_ret not in dct:
993
+ dct[p_ret] = coeff
994
+ else:
995
+ dct[p_ret] += coeff
996
+ return RSm._from_dict(dct)
997
+
998
+ def central_orthogonal_idempotents(self):
999
+ r"""
1000
+ Return a maximal list of central orthogonal idempotents for ``self``.
1001
+
1002
+ This method does not require that ``self`` be semisimple, relying
1003
+ on Nakayama's Conjecture whenever ``self.base_ring()`` has
1004
+ positive characteristic.
1005
+
1006
+ EXAMPLES::
1007
+
1008
+ sage: QS3 = SymmetricGroupAlgebra(QQ,3)
1009
+ sage: a = QS3.central_orthogonal_idempotents()
1010
+ sage: a[0] # [3]
1011
+ 1/6*[1, 2, 3] + 1/6*[1, 3, 2] + 1/6*[2, 1, 3] + 1/6*[2, 3, 1]
1012
+ + 1/6*[3, 1, 2] + 1/6*[3, 2, 1]
1013
+ sage: a[1] # [2, 1]
1014
+ 2/3*[1, 2, 3] - 1/3*[2, 3, 1] - 1/3*[3, 1, 2]
1015
+
1016
+ TESTS:
1017
+
1018
+ Check this works with other indexing sets::
1019
+
1020
+ sage: G = SymmetricGroup(3).algebra(QQ)
1021
+ sage: a = G.central_orthogonal_idempotents()
1022
+ sage: a[0]
1023
+ 1/6*() + 1/6*(2,3) + 1/6*(1,2) + 1/6*(1,2,3) + 1/6*(1,3,2) + 1/6*(1,3)
1024
+ sage: a[1]
1025
+ 2/3*() - 1/3*(1,2,3) - 1/3*(1,3,2)
1026
+
1027
+ sage: G = SymmetricGroup(3).algebra(GF(2))
1028
+ sage: a = G.central_orthogonal_idempotents()
1029
+ sage: a[0]
1030
+ (1,2,3) + (1,3,2)
1031
+ sage: a[1]
1032
+ () + (1,2,3) + (1,3,2)
1033
+
1034
+ Check this works in positive characteristic::
1035
+
1036
+ sage: def test_n_with_primes(n, primes):
1037
+ ....: Sn = {p:SymmetricGroupAlgebra(GF(p), n) for p in primes}
1038
+ ....: for p in primes:
1039
+ ....: idems = Sn[p].central_orthogonal_idempotents()
1040
+ ....: tst = [sum(idems)==Sn[p].one()]
1041
+ ....: for i in range(len(idems)-1):
1042
+ ....: e = idems[i]
1043
+ ....: for j in range(i, len(idems)):
1044
+ ....: f = idems[j]
1045
+ ....: if i == j:
1046
+ ....: tst.append(e*e == e)
1047
+ ....: else:
1048
+ ....: tst.append(e*f == 0)
1049
+ ....: print("{0} blocks for p={1} ... {2}".format( len(idems), p, all(tst) ))
1050
+ sage: test_n_with_primes(5, [2,3,5,7]) # long time
1051
+ 2 blocks for p=2 ... True
1052
+ 3 blocks for p=3 ... True
1053
+ 3 blocks for p=5 ... True
1054
+ 7 blocks for p=7 ... True
1055
+
1056
+ .. SEEALSO::
1057
+
1058
+ - :meth:`central_orthogonal_idempotent`
1059
+ """
1060
+ return [self.central_orthogonal_idempotent(key)
1061
+ for key in sorted(self._blocks_dictionary, reverse=True)]
1062
+
1063
+ def central_orthogonal_idempotent(self, la, block=True):
1064
+ r"""
1065
+ Return the central idempotent for the symmetric group of order `n`
1066
+ corresponding to the indecomposable block to which the partition
1067
+ ``la`` is associated.
1068
+
1069
+ If ``self.base_ring()`` contains `\QQ`, this corresponds to the
1070
+ classical central idempotent corresponding to the irreducible
1071
+ representation indexed by ``la``.
1072
+
1073
+ Alternatively, if ``self.base_ring()`` has characteristic `p > 0`,
1074
+ then Theorem 2.8 in [Mur1983]_ provides that ``la`` is associated
1075
+ to an idempotent `f_\mu`, where `\mu` is the `p`-core of ``la``.
1076
+ This `f_\mu` is a sum of classical idempotents,
1077
+
1078
+ .. MATH::
1079
+
1080
+ f_\mu = \sum_{c(\lambda)=\mu} e_\lambda,
1081
+
1082
+ where the sum ranges over the partitions `\lambda` of `n` with
1083
+ `p`-core equal to `\mu`.
1084
+
1085
+ INPUT:
1086
+
1087
+ - ``la`` -- a partition of ``self.n`` or a
1088
+ ``self.base_ring().characteristic()``-core of such
1089
+ a partition
1090
+
1091
+ - ``block`` -- boolean (default: ``True``); when ``False``,
1092
+ this returns the classical idempotent associated to ``la``
1093
+ (defined over `\QQ`)
1094
+
1095
+ OUTPUT:
1096
+
1097
+ If ``block=False`` and the corresponding coefficients are
1098
+ not defined over ``self.base_ring()``, then return ``None``.
1099
+ Otherwise return an element of ``self``.
1100
+
1101
+ EXAMPLES:
1102
+
1103
+ Asking for block idempotents in any characteristic, by
1104
+ passing a partition of ``self.n``::
1105
+
1106
+ sage: S0 = SymmetricGroup(4).algebra(QQ)
1107
+ sage: S2 = SymmetricGroup(4).algebra(GF(2))
1108
+ sage: S3 = SymmetricGroup(4).algebra(GF(3))
1109
+ sage: S0.central_orthogonal_idempotent([2,1,1])
1110
+ 3/8*() - 1/8*(3,4) - 1/8*(2,3) - 1/8*(2,4) - 1/8*(1,2)
1111
+ - 1/8*(1,2)(3,4) + 1/8*(1,2,3,4) + 1/8*(1,2,4,3)
1112
+ + 1/8*(1,3,4,2) - 1/8*(1,3) - 1/8*(1,3)(2,4)
1113
+ + 1/8*(1,3,2,4) + 1/8*(1,4,3,2) - 1/8*(1,4)
1114
+ + 1/8*(1,4,2,3) - 1/8*(1,4)(2,3)
1115
+ sage: S2.central_orthogonal_idempotent([2,1,1])
1116
+ ()
1117
+ sage: idem = S3.central_orthogonal_idempotent([4]); idem
1118
+ () + (1,2)(3,4) + (1,3)(2,4) + (1,4)(2,3)
1119
+ sage: idem == S3.central_orthogonal_idempotent([1,1,1,1])
1120
+ True
1121
+ sage: S3.central_orthogonal_idempotent([2,2])
1122
+ () + (1,2)(3,4) + (1,3)(2,4) + (1,4)(2,3)
1123
+
1124
+ Asking for block idempotents in any characteristic, by
1125
+ passing `p`-cores::
1126
+
1127
+ sage: S0.central_orthogonal_idempotent([1,1])
1128
+ Traceback (most recent call last):
1129
+ ...
1130
+ ValueError: [1, 1] is not a partition of integer 4
1131
+ sage: S2.central_orthogonal_idempotent([])
1132
+ ()
1133
+ sage: S2.central_orthogonal_idempotent([1])
1134
+ Traceback (most recent call last):
1135
+ ...
1136
+ ValueError: the 2-core of [1] is not a 2-core of a partition of 4
1137
+ sage: S3.central_orthogonal_idempotent([1])
1138
+ () + (1,2)(3,4) + (1,3)(2,4) + (1,4)(2,3)
1139
+ sage: S3.central_orthogonal_idempotent([7])
1140
+ () + (1,2)(3,4) + (1,3)(2,4) + (1,4)(2,3)
1141
+
1142
+ Asking for classical idempotents::
1143
+
1144
+ sage: S3.central_orthogonal_idempotent([2,2], block=False) is None
1145
+ True
1146
+ sage: S3.central_orthogonal_idempotent([2,1,1], block=False)
1147
+ (3,4) + (2,3) + (2,4) + (1,2) + (1,2)(3,4) + 2*(1,2,3,4)
1148
+ + 2*(1,2,4,3) + 2*(1,3,4,2) + (1,3) + (1,3)(2,4)
1149
+ + 2*(1,3,2,4) + 2*(1,4,3,2) + (1,4) + 2*(1,4,2,3)
1150
+ + (1,4)(2,3)
1151
+
1152
+ .. SEEALSO::
1153
+
1154
+ - :meth:`sage.combinat.partition.Partition.core`
1155
+ """
1156
+ la = _Partitions(la)
1157
+ R = self.base_ring()
1158
+ p = R.characteristic()
1159
+
1160
+ if not block or not p:
1161
+ if la in self._idempotent_cache:
1162
+ return self._idempotent_cache[la]
1163
+ if la.size() != self.n:
1164
+ raise ValueError("{0} is not a partition of integer {1}".format(la, self.n))
1165
+ else:
1166
+ mu = la.core(p)
1167
+ if mu in self._idempotent_cache:
1168
+ return self._idempotent_cache[mu]
1169
+ if mu not in self._blocks_dictionary:
1170
+ raise ValueError("the {1}-core of {0} is not a {1}-core of a partition of {2}".format(la, p, self.n))
1171
+
1172
+ from sage.data_structures.blas_dict import iaxpy
1173
+ from sage.libs.gap.libgap import libgap
1174
+ G = self._indices
1175
+ character_table = [c.sage() for c in libgap.Irr(libgap.SymmetricGroup(self.n))]
1176
+ Pn = Partitions_n(self.n)
1177
+ C = Pn.cardinality()
1178
+ # We get the indices of the partitions in the reverse lex order
1179
+ # (i.e., reverse of the iteration order of partitions).
1180
+ indices = {lam: C - 1 - i for i, lam in enumerate(Pn)}
1181
+
1182
+ if not block or not p:
1183
+ la_index = indices[la]
1184
+ big_coeff = character_table[la_index][0] / factorial(self.n)
1185
+ character_row = character_table[la_index]
1186
+ cpi = {g: big_coeff * character_row[indices[g.cycle_type()]]
1187
+ for g in G}
1188
+ else:
1189
+ # We compute the cycle types of the permutations
1190
+ cycles = {}
1191
+ for g in G:
1192
+ ind = indices[g.cycle_type()]
1193
+ if ind in cycles:
1194
+ cycles[ind].append(g)
1195
+ else:
1196
+ cycles[ind] = [g]
1197
+
1198
+ denom = factorial(self.n)
1199
+ cpi = {}
1200
+ for lam in self._blocks_dictionary[mu]:
1201
+ lam_index = indices[lam]
1202
+ big_coeff = character_table[lam_index][0] / denom
1203
+ character_row = character_table[lam_index]
1204
+ iaxpy(1,
1205
+ {g: big_coeff * character_row[ind]
1206
+ for ind in cycles for g in cycles[ind]},
1207
+ cpi)
1208
+
1209
+ if not all(R(cpi[g].denominator()) for g in cpi):
1210
+ return None
1211
+
1212
+ ret = self.element_class(self, {g: R(cpi[g]) for g in cpi if R(cpi[g])})
1213
+ if not block or not p:
1214
+ self._idempotent_cache[la] = ret
1215
+ else:
1216
+ self._idempotent_cache[mu] = ret
1217
+ return ret
1218
+
1219
+ @lazy_attribute
1220
+ def _blocks_dictionary(self):
1221
+ r"""
1222
+ Return the partitions of ``self.n``, themselves partitioned
1223
+ by their distinct `p`-cores, where `p` is the characteristic
1224
+ of ``self.base_ring()``
1225
+
1226
+ If the characteristic is zero, we take the `p`-core operation
1227
+ to be the identity map on partitions.
1228
+
1229
+ These lists of partitions, say with common `p`-core `\mu`,
1230
+ are components of the central orthogonal idempotent
1231
+ corresponding to `\mu`.
1232
+
1233
+ TESTS::
1234
+
1235
+ sage: B2 = SymmetricGroupAlgebra(GF(2), 4)._blocks_dictionary
1236
+ sage: [tuple(B2[key]) for key in sorted(B2)]
1237
+ [([4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1])]
1238
+ sage: B3 = SymmetricGroupAlgebra(GF(3), 4)._blocks_dictionary
1239
+ sage: [tuple(B3[key]) for key in sorted(B3)]
1240
+ [([4], [2, 2], [1, 1, 1, 1]), ([2, 1, 1],), ([3, 1],)]
1241
+ sage: B5 = SymmetricGroupAlgebra(GF(5), 4)._blocks_dictionary
1242
+ sage: [tuple(B5[key]) for key in sorted(B5)]
1243
+ [([1, 1, 1, 1],), ([2, 1, 1],), ([2, 2],), ([3, 1],), ([4],)]
1244
+ sage: B5 == SymmetricGroupAlgebra(QQ, 4)._blocks_dictionary
1245
+ True
1246
+
1247
+ .. SEEALSO::
1248
+
1249
+ :meth:`central_orthogonal_idempotent`
1250
+ """
1251
+ p = self.base_ring().characteristic()
1252
+ if not p:
1253
+ return {la: [la] for la in Partitions_n(self.n)}
1254
+
1255
+ blocks = {}
1256
+ for la in Partitions_n(self.n):
1257
+ c = la.core(p)
1258
+ if c in blocks:
1259
+ blocks[c].append(la)
1260
+ else:
1261
+ blocks[c] = [la]
1262
+ return blocks
1263
+
1264
+ def ladder_idempotent(self, la):
1265
+ r"""
1266
+ Return the ladder idempotent of ``self``.
1267
+
1268
+ Let `F` be a field of characteristic `p`. The *ladder idempotent*
1269
+ of shape `\lambda` is the idempotent of `F[S_n]` defined as follows.
1270
+ Let `T` be the :meth:`ladder tableau
1271
+ <sage.combinat.partition.Partition.ladder_tableau>` of shape `\lambda`.
1272
+ Let `[T]` be the set of standard tableaux whose residue sequence
1273
+ is the same as for `T`. Let `\alpha` be the sizes of the ladders
1274
+ of `\lambda`. Then the ladder idempotent is constructed as
1275
+
1276
+ .. MATH::
1277
+
1278
+ \widetilde{e}_{\lambda} := \frac{1}{\alpha!}
1279
+ \left( \sum_{\sigma \in S_{\alpha}} \sigma \right)
1280
+ \left( \overline{\sum_{U \in [T]} E_U} \right),
1281
+
1282
+ where `E_{UU}` is the :meth:`seminormal_basis` element over `\QQ`
1283
+ and we project the sum to `F`, `S_{\alpha}` is the Young subgroup
1284
+ corresponding to `\alpha`, and `\alpha! = \alpha_1! \cdots \alpha_k!`.
1285
+
1286
+ EXAMPLES::
1287
+
1288
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 4)
1289
+ sage: for la in Partitions(SGA.n):
1290
+ ....: idem = SGA.ladder_idempotent(la)
1291
+ ....: print(la)
1292
+ ....: print(idem)
1293
+ ....: assert idem^2 == idem
1294
+ [4]
1295
+ 2*[1, 2, 3, 4] + 2*[1, 2, 4, 3] + 2*[2, 1, 3, 4] + 2*[2, 1, 4, 3]
1296
+ + 2*[3, 4, 1, 2] + 2*[3, 4, 2, 1] + 2*[4, 3, 1, 2] + 2*[4, 3, 2, 1]
1297
+ [3, 1]
1298
+ 2*[1, 2, 3, 4] + 2*[1, 2, 4, 3] + 2*[2, 1, 3, 4] + 2*[2, 1, 4, 3]
1299
+ + [3, 4, 1, 2] + [3, 4, 2, 1] + [4, 3, 1, 2] + [4, 3, 2, 1]
1300
+ [2, 2]
1301
+ 2*[1, 2, 3, 4] + 2*[1, 2, 4, 3] + 2*[2, 1, 3, 4] + 2*[2, 1, 4, 3]
1302
+ + 2*[3, 4, 1, 2] + 2*[3, 4, 2, 1] + 2*[4, 3, 1, 2] + 2*[4, 3, 2, 1]
1303
+ [2, 1, 1]
1304
+ 2*[1, 2, 3, 4] + [1, 2, 4, 3] + 2*[1, 3, 2, 4] + [1, 3, 4, 2]
1305
+ + [1, 4, 2, 3] + 2*[1, 4, 3, 2] + 2*[2, 1, 3, 4] + [2, 1, 4, 3]
1306
+ + 2*[2, 3, 1, 4] + [2, 3, 4, 1] + [2, 4, 1, 3] + 2*[2, 4, 3, 1]
1307
+ + 2*[3, 1, 2, 4] + [3, 1, 4, 2] + 2*[3, 2, 1, 4] + [3, 2, 4, 1]
1308
+ + [4, 1, 2, 3] + 2*[4, 1, 3, 2] + [4, 2, 1, 3] + 2*[4, 2, 3, 1]
1309
+ [1, 1, 1, 1]
1310
+ 2*[1, 2, 3, 4] + [1, 2, 4, 3] + [2, 1, 3, 4] + 2*[2, 1, 4, 3]
1311
+ + 2*[3, 4, 1, 2] + [3, 4, 2, 1] + [4, 3, 1, 2] + 2*[4, 3, 2, 1]
1312
+
1313
+ When `p = 0`, these idempotents will generate all of the simple
1314
+ modules (which are the :meth:`Specht modules <specht_module>`
1315
+ and also projective modules)::
1316
+
1317
+ sage: SGA = SymmetricGroupAlgebra(QQ, 5)
1318
+ sage: for la in Partitions(SGA.n):
1319
+ ....: idem = SGA.ladder_idempotent(la)
1320
+ ....: assert idem^2 == idem
1321
+ ....: print(la, SGA.principal_ideal(idem).dimension())
1322
+ [5] 1
1323
+ [4, 1] 4
1324
+ [3, 2] 5
1325
+ [3, 1, 1] 6
1326
+ [2, 2, 1] 5
1327
+ [2, 1, 1, 1] 4
1328
+ [1, 1, 1, 1, 1] 1
1329
+ sage: [StandardTableaux(la).cardinality() for la in Partitions(SGA.n)]
1330
+ [1, 4, 5, 6, 5, 4, 1]
1331
+
1332
+ REFERENCES:
1333
+
1334
+ - [Ryom2015]_
1335
+ """
1336
+ R = self.base_ring()
1337
+ p = R.characteristic()
1338
+ n = self.n
1339
+ if not p:
1340
+ p = n + 1
1341
+ la = Partitions_n(n)(la)
1342
+ Tlad, alpha = la.ladder_tableau(p, ladder_lengths=True)
1343
+ if any(val >= p for val in alpha):
1344
+ raise ValueError(f"{la} is not {p}-ladder restricted")
1345
+ Tclass = Tlad.residue_sequence(p).standard_tableaux()
1346
+ Elad = sum(epsilon_ik(T, T) for T in Tclass)
1347
+ Elad = self.element_class(self, {sigma: R(c)
1348
+ for sigma, c in Elad._monomial_coefficients.items()})
1349
+ from sage.groups.perm_gps.permgroup_named import SymmetricGroup
1350
+ YG = SymmetricGroup(n).young_subgroup(alpha)
1351
+ coeff = ~R.prod(factorial(val) for val in alpha)
1352
+ G = self.group()
1353
+ eprod = self.element_class(self, {G(list(elt.tuple())): coeff
1354
+ for elt in YG})
1355
+ return Elad * eprod
1356
+
1357
+ @cached_method
1358
+ def algebra_generators(self):
1359
+ r"""
1360
+ Return generators of this group algebra (as algebra) as a
1361
+ list of permutations.
1362
+
1363
+ The generators used for the group algebra of `S_n` are the
1364
+ transposition `(2, 1)` and the `n`-cycle `(1, 2, \ldots, n)`,
1365
+ unless `n \leq 1` (in which case no generators are needed).
1366
+
1367
+ EXAMPLES::
1368
+
1369
+ sage: SymmetricGroupAlgebra(ZZ,5).algebra_generators()
1370
+ Family ([2, 1, 3, 4, 5], [2, 3, 4, 5, 1])
1371
+
1372
+ sage: SymmetricGroupAlgebra(QQ,0).algebra_generators()
1373
+ Family ()
1374
+
1375
+ sage: SymmetricGroupAlgebra(QQ,1).algebra_generators()
1376
+ Family ()
1377
+
1378
+ TESTS:
1379
+
1380
+ Check that :issue:`15309` is fixed::
1381
+
1382
+ sage: S3 = SymmetricGroupAlgebra(QQ, 3)
1383
+ sage: S3.algebra_generators()
1384
+ Family ([2, 1, 3], [2, 3, 1])
1385
+ sage: C = CombinatorialFreeModule(ZZ, ZZ)
1386
+ sage: M = C.module_morphism(lambda x: S3.zero(), codomain=S3)
1387
+ sage: M.register_as_coercion()
1388
+ """
1389
+ from sage.sets.family import Family
1390
+ if self.n <= 1:
1391
+ return Family([])
1392
+ a = list(range(1, self.n + 1))
1393
+ a[0] = 2
1394
+ a[1] = 1
1395
+ b = list(range(2, self.n + 2))
1396
+ b[self.n - 1] = 1
1397
+ return Family([self.monomial(self._indices(a)), self.monomial(self._indices(b))])
1398
+
1399
+ def _conjugacy_classes_representatives_underlying_group(self):
1400
+ r"""
1401
+ Return a complete list of representatives of conjugacy
1402
+ classes of the underlying symmetric group.
1403
+
1404
+ .. WARNING::
1405
+
1406
+ This currently is only implemented when ``self`` is built using
1407
+ the index set ``Permutations(n)``.
1408
+
1409
+ EXAMPLES::
1410
+
1411
+ sage: SG=SymmetricGroupAlgebra(ZZ,3)
1412
+ sage: SG._conjugacy_classes_representatives_underlying_group()
1413
+ [[2, 3, 1], [2, 1, 3], [1, 2, 3]]
1414
+
1415
+ sage: SGg = SymmetricGroup(3).algebra(ZZ)
1416
+ sage: SGg._conjugacy_classes_representatives_underlying_group() # not tested
1417
+ [(1,2,3), (1,2), ()]
1418
+ """
1419
+ P = self.basis().keys()
1420
+ return [P.element_in_conjugacy_classes(nu) for nu in Partitions_n(self.n)]
1421
+
1422
+ def rsw_shuffling_element(self, k):
1423
+ r"""
1424
+ Return the `k`-th Reiner-Saliola-Welker shuffling element in
1425
+ the group algebra ``self``.
1426
+
1427
+ The `k`-th Reiner-Saliola-Welker shuffling element in the
1428
+ symmetric group algebra `R S_n` over a ring `R` is defined as the
1429
+ sum `\sum_{\sigma \in S_n} \mathrm{noninv}_k(\sigma) \cdot \sigma`,
1430
+ where for every permutation `\sigma`, the number
1431
+ `\mathrm{noninv}_k(\sigma)` is the number of all
1432
+ `k`-noninversions of `\sigma` (that is, the number of all
1433
+ `k`-element subsets of `\{ 1, 2, \ldots, n \}` on which
1434
+ `\sigma` restricts to a strictly increasing map). See
1435
+ :meth:`sage.combinat.permutation.number_of_noninversions` for
1436
+ the `\mathrm{noninv}` map.
1437
+
1438
+ This element is more or less the operator `\nu_{k, 1^{n-k}}`
1439
+ introduced in [RSW2011]_; more precisely, `\nu_{k, 1^{n-k}}`
1440
+ is the left multiplication by this element.
1441
+
1442
+ It is a nontrivial theorem (Theorem 1.1 in [RSW2011]_) that
1443
+ the operators `\nu_{k, 1^{n-k}}` (for fixed `n` and varying
1444
+ `k`) pairwise commute. It is a conjecture (Conjecture 1.2 in
1445
+ [RSW2011]_) that all their eigenvalues are integers (which, in
1446
+ light of their commutativity and easily established symmetry,
1447
+ yields that they can be simultaneously diagonalized over `\QQ`
1448
+ with only integer eigenvalues).
1449
+
1450
+ EXAMPLES:
1451
+
1452
+ The Reiner-Saliola-Welker shuffling elements on `\QQ S_3`::
1453
+
1454
+ sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
1455
+ sage: QS3.rsw_shuffling_element(0)
1456
+ [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
1457
+ sage: QS3.rsw_shuffling_element(1)
1458
+ 3*[1, 2, 3] + 3*[1, 3, 2] + 3*[2, 1, 3] + 3*[2, 3, 1] + 3*[3, 1, 2] + 3*[3, 2, 1]
1459
+ sage: QS3.rsw_shuffling_element(2)
1460
+ 3*[1, 2, 3] + 2*[1, 3, 2] + 2*[2, 1, 3] + [2, 3, 1] + [3, 1, 2]
1461
+ sage: QS3.rsw_shuffling_element(3)
1462
+ [1, 2, 3]
1463
+ sage: QS3.rsw_shuffling_element(4)
1464
+ 0
1465
+
1466
+ Checking the commutativity of Reiner-Saliola-Welker shuffling
1467
+ elements (we leave out the ones for which it is trivial)::
1468
+
1469
+ sage: def test_rsw_comm(n):
1470
+ ....: QSn = SymmetricGroupAlgebra(QQ, n)
1471
+ ....: rsws = [QSn.rsw_shuffling_element(k) for k in range(2, n)]
1472
+ ....: return all(ri * rsws[j] == rsws[j] * ri
1473
+ ....: for i, ri in enumerate(rsws) for j in range(i))
1474
+ sage: test_rsw_comm(3)
1475
+ True
1476
+ sage: test_rsw_comm(4) # long time
1477
+ True
1478
+ sage: test_rsw_comm(5) # not tested
1479
+ True
1480
+
1481
+ .. NOTE::
1482
+
1483
+ For large ``k`` (relative to ``n``), it might be faster to call
1484
+ ``QSn.left_action_product(QSn.semi_rsw_element(k), QSn.antipode(binary_unshuffle_sum(k)))``
1485
+ than ``QSn.rsw_shuffling_element(n)``.
1486
+
1487
+ .. SEEALSO::
1488
+
1489
+ :meth:`semi_rsw_element`, :meth:`binary_unshuffle_sum`
1490
+ """
1491
+ P = self.basis().keys()
1492
+ I = Permutations(self.n)
1493
+ return self.sum_of_terms([(p, I(p).number_of_noninversions(k)) for p in P],
1494
+ distinct=True)
1495
+
1496
+ def semi_rsw_element(self, k):
1497
+ r"""
1498
+ Return the `k`-th semi-RSW element in the group algebra ``self``.
1499
+
1500
+ The `k`-th semi-RSW element in the symmetric group algebra
1501
+ `R S_n` over a ring `R` is defined as the sum of all permutations
1502
+ `\sigma \in S_n` satisfying
1503
+ `\sigma(1) < \sigma(2) < \cdots < \sigma(k)`.
1504
+
1505
+ This element has the property that, if it is denoted by `s_k`,
1506
+ then `s_k S(s_k)` is `(n-k)!` times the `k`-th
1507
+ Reiner-Saliola-Welker shuffling element of `R S_n` (see
1508
+ :meth:`rsw_shuffling_element`). Here, `S` denotes the antipode
1509
+ of the group algebra `R S_n`.
1510
+
1511
+ The `k`-th semi-RSW element is the image of the complete
1512
+ non-commutative symmetric function `S^{(k, 1^{n-k})}` in the
1513
+ ring of non-commutative symmetric functions under the canonical
1514
+ projection on the symmetric group algebra (through the descent
1515
+ algebra).
1516
+
1517
+ EXAMPLES:
1518
+
1519
+ The semi-RSW elements on `\QQ S_3`::
1520
+
1521
+ sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
1522
+ sage: QS3.semi_rsw_element(0)
1523
+ [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
1524
+ sage: QS3.semi_rsw_element(1)
1525
+ [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
1526
+ sage: QS3.semi_rsw_element(2)
1527
+ [1, 2, 3] + [1, 3, 2] + [2, 3, 1]
1528
+ sage: QS3.semi_rsw_element(3)
1529
+ [1, 2, 3]
1530
+ sage: QS3.semi_rsw_element(4)
1531
+ 0
1532
+
1533
+ Let us check the relation with the `k`-th Reiner-Saliola-Welker
1534
+ shuffling element stated in the docstring::
1535
+
1536
+ sage: def test_rsw(n):
1537
+ ....: ZSn = SymmetricGroupAlgebra(ZZ, n)
1538
+ ....: for k in range(1, n):
1539
+ ....: a = ZSn.semi_rsw_element(k)
1540
+ ....: b = ZSn.left_action_product(a, ZSn.antipode(a))
1541
+ ....: if factorial(n-k) * ZSn.rsw_shuffling_element(k) != b:
1542
+ ....: return False
1543
+ ....: return True
1544
+ sage: test_rsw(3)
1545
+ True
1546
+ sage: test_rsw(4)
1547
+ True
1548
+ sage: test_rsw(5) # long time
1549
+ True
1550
+
1551
+ Let us also check the statement about the complete
1552
+ non-commutative symmetric function::
1553
+
1554
+ sage: def test_rsw_ncsf(n):
1555
+ ....: ZSn = SymmetricGroupAlgebra(ZZ, n)
1556
+ ....: NSym = NonCommutativeSymmetricFunctions(ZZ)
1557
+ ....: S = NSym.S()
1558
+ ....: for k in range(1, n):
1559
+ ....: a = S(Composition([k] + [1]*(n-k))).to_symmetric_group_algebra()
1560
+ ....: if a != ZSn.semi_rsw_element(k):
1561
+ ....: return False
1562
+ ....: return True
1563
+ sage: test_rsw_ncsf(3)
1564
+ True
1565
+ sage: test_rsw_ncsf(4)
1566
+ True
1567
+ sage: test_rsw_ncsf(5) # long time
1568
+ True
1569
+ """
1570
+ n = self.n
1571
+ if n < k:
1572
+ return self.zero()
1573
+
1574
+ def complement(xs):
1575
+ res = list(range(1, n + 1))
1576
+ for x in xs:
1577
+ res.remove(x)
1578
+ return res
1579
+ P = Permutations(n)
1580
+ I = self._indices
1581
+ return self.sum_of_monomials([I(P(complement(q) + list(q)))
1582
+ for q in itertools.permutations(range(1, n + 1), int(n - k))])
1583
+
1584
+ def binary_unshuffle_sum(self, k):
1585
+ r"""
1586
+ Return the `k`-th binary unshuffle sum in the group algebra
1587
+ ``self``.
1588
+
1589
+ The `k`-th binary unshuffle sum in the symmetric group algebra
1590
+ `R S_n` over a ring `R` is defined as the sum of all permutations
1591
+ `\sigma \in S_n` satisfying
1592
+ `\sigma(1) < \sigma(2) < \cdots < \sigma(k)` and
1593
+ `\sigma(k+1) < \sigma(k+2) < \cdots < \sigma(n)`.
1594
+
1595
+ This element has the property that, if it is denoted by `t_k`,
1596
+ and if the `k`-th semi-RSW element (see :meth:`semi_rsw_element`)
1597
+ is denoted by `s_k`, then `s_k S(t_k)` and `t_k S(s_k)` both
1598
+ equal the `k`-th Reiner-Saliola-Welker shuffling element of
1599
+ `R S_n` (see :meth:`rsw_shuffling_element`).
1600
+
1601
+ The `k`-th binary unshuffle sum is the image of the complete
1602
+ non-commutative symmetric function `S^{(k, n-k)}` in the
1603
+ ring of non-commutative symmetric functions under the canonical
1604
+ projection on the symmetric group algebra (through the descent
1605
+ algebra).
1606
+
1607
+ EXAMPLES:
1608
+
1609
+ The binary unshuffle sums on `\QQ S_3`::
1610
+
1611
+ sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
1612
+ sage: QS3.binary_unshuffle_sum(0)
1613
+ [1, 2, 3]
1614
+ sage: QS3.binary_unshuffle_sum(1)
1615
+ [1, 2, 3] + [2, 1, 3] + [3, 1, 2]
1616
+ sage: QS3.binary_unshuffle_sum(2)
1617
+ [1, 2, 3] + [1, 3, 2] + [2, 3, 1]
1618
+ sage: QS3.binary_unshuffle_sum(3)
1619
+ [1, 2, 3]
1620
+ sage: QS3.binary_unshuffle_sum(4)
1621
+ 0
1622
+
1623
+ Let us check the relation with the `k`-th Reiner-Saliola-Welker
1624
+ shuffling element stated in the docstring::
1625
+
1626
+ sage: def test_rsw(n):
1627
+ ....: ZSn = SymmetricGroupAlgebra(ZZ, n)
1628
+ ....: for k in range(1, n):
1629
+ ....: a = ZSn.semi_rsw_element(k)
1630
+ ....: b = ZSn.binary_unshuffle_sum(k)
1631
+ ....: c = ZSn.left_action_product(a, ZSn.antipode(b))
1632
+ ....: d = ZSn.left_action_product(b, ZSn.antipode(a))
1633
+ ....: e = ZSn.rsw_shuffling_element(k)
1634
+ ....: if c != e or d != e:
1635
+ ....: return False
1636
+ ....: return True
1637
+ sage: test_rsw(3)
1638
+ True
1639
+ sage: test_rsw(4) # long time
1640
+ True
1641
+ sage: test_rsw(5) # long time
1642
+ True
1643
+
1644
+ Let us also check the statement about the complete
1645
+ non-commutative symmetric function::
1646
+
1647
+ sage: def test_rsw_ncsf(n):
1648
+ ....: ZSn = SymmetricGroupAlgebra(ZZ, n)
1649
+ ....: NSym = NonCommutativeSymmetricFunctions(ZZ)
1650
+ ....: S = NSym.S()
1651
+ ....: for k in range(1, n):
1652
+ ....: a = S(Composition([k, n-k])).to_symmetric_group_algebra()
1653
+ ....: if a != ZSn.binary_unshuffle_sum(k):
1654
+ ....: return False
1655
+ ....: return True
1656
+ sage: test_rsw_ncsf(3)
1657
+ True
1658
+ sage: test_rsw_ncsf(4)
1659
+ True
1660
+ sage: test_rsw_ncsf(5) # long time
1661
+ True
1662
+ """
1663
+ n = self.n
1664
+ if n < k:
1665
+ return self.zero()
1666
+
1667
+ def complement(xs):
1668
+ res = list(range(1, n + 1))
1669
+ for x in xs:
1670
+ res.remove(x)
1671
+ return res
1672
+ P = Permutations(n)
1673
+ return self.sum_of_monomials([self._indices(P(list(q) + complement(q)))
1674
+ for q in itertools.combinations(range(1, n + 1), int(k))])
1675
+
1676
+ def specht_module(self, D):
1677
+ r"""
1678
+ Return the Specht module of ``self`` indexed by the diagram ``D``.
1679
+
1680
+ EXAMPLES::
1681
+
1682
+ sage: SGA = SymmetricGroupAlgebra(QQ, 5)
1683
+ sage: SM = SGA.specht_module(Partition([3,1,1]))
1684
+ sage: SM
1685
+ Specht module of [3, 1, 1] over Rational Field
1686
+ sage: SM.frobenius_image()
1687
+ s[3, 1, 1]
1688
+
1689
+ sage: SM = SGA.specht_module([(1,1),(1,3),(2,2),(3,1),(3,2)])
1690
+ sage: SM
1691
+ Specht module of [(1, 1), (1, 3), (2, 2), (3, 1), (3, 2)] over Rational Field
1692
+ sage: SM.frobenius_image()
1693
+ s[2, 2, 1] + s[3, 1, 1] + s[3, 2]
1694
+ """
1695
+ from sage.combinat.specht_module import SpechtModule
1696
+ return SpechtModule(self, D)
1697
+
1698
+ def tabloid_module(self, D):
1699
+ r"""
1700
+ Return the module of tabloids with the natural action of ``self``.
1701
+
1702
+ .. SEEALSO::
1703
+
1704
+ :class:`~sage.combinat.specht_module.TabloidModule`
1705
+
1706
+ EXAMPLES::
1707
+
1708
+ sage: SGA = SymmetricGroupAlgebra(QQ, 5)
1709
+ sage: TM = SGA.tabloid_module(Partition([3,1,1]))
1710
+ sage: TM
1711
+ Tabloid module of [3, 1, 1] over Rational Field
1712
+ sage: s = SymmetricFunctions(QQ).s()
1713
+ sage: s(TM.frobenius_image())
1714
+ s[3, 1, 1] + s[3, 2] + 2*s[4, 1] + s[5]
1715
+ """
1716
+ from sage.combinat.specht_module import TabloidModule
1717
+ return TabloidModule(self, D)
1718
+
1719
+ def specht_module_dimension(self, D):
1720
+ r"""
1721
+ Return the dimension of the Specht module of ``self`` indexed by ``D``.
1722
+
1723
+ EXAMPLES::
1724
+
1725
+ sage: SGA = SymmetricGroupAlgebra(QQ, 5)
1726
+ sage: SGA.specht_module_dimension(Partition([3,1,1]))
1727
+ 6
1728
+ sage: SGA.specht_module_dimension([(1,1),(1,3),(2,2),(3,1),(3,2)])
1729
+ 16
1730
+ """
1731
+ from sage.combinat.specht_module import _to_diagram, specht_module_spanning_set
1732
+ D = _to_diagram(D)
1733
+ span_set = specht_module_spanning_set(D, self)
1734
+ return matrix(self.base_ring(), [v.to_vector() for v in span_set]).rank()
1735
+
1736
+ def simple_module_parameterization(self):
1737
+ r"""
1738
+ Return a parameterization of the simple modules of ``self``.
1739
+
1740
+ The symmetric group algebra of `S_n` over a field of characteristic `p`
1741
+ has its simple modules indexed by all `p`-regular partitions of `n`.
1742
+
1743
+ EXAMPLES::
1744
+
1745
+ sage: SGA = SymmetricGroupAlgebra(QQ, 6)
1746
+ sage: SGA.simple_module_parameterization()
1747
+ Partitions of the integer 6
1748
+
1749
+ sage: SGA = SymmetricGroupAlgebra(GF(2), 6)
1750
+ sage: SGA.simple_module_parameterization()
1751
+ 2-Regular Partitions of the integer 6
1752
+ """
1753
+ p = self.base_ring().characteristic()
1754
+ if p > 0:
1755
+ return Partitions(self.n, regular=p)
1756
+ return Partitions_n(self.n)
1757
+
1758
+ def simple_module(self, la):
1759
+ r"""
1760
+ Return the simple module of ``self`` indexed by the partition ``la``.
1761
+
1762
+ Over a field of characteristic `0`, this simply returns the Specht
1763
+ module.
1764
+
1765
+ .. SEEALSO::
1766
+
1767
+ :class:`sage.combinat.specht_module.SimpleModule`
1768
+
1769
+ EXAMPLES::
1770
+
1771
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 5)
1772
+ sage: D = SGA.simple_module(Partition([3,1,1]))
1773
+ sage: D
1774
+ Simple module of [3, 1, 1] over Finite Field of size 3
1775
+ sage: D.brauer_character()
1776
+ (6, 0, -2, 0, 1)
1777
+ """
1778
+ from sage.combinat.specht_module import SpechtModule
1779
+ return SpechtModule(self, la).simple_module()
1780
+
1781
+ def simple_module_dimension(self, la):
1782
+ r"""
1783
+ Return the dimension of the simple module of ``self`` indexed by the
1784
+ partition ``la``.
1785
+
1786
+ EXAMPLES::
1787
+
1788
+ sage: SGA = SymmetricGroupAlgebra(GF(5), 6)
1789
+ sage: SGA.simple_module_dimension(Partition([4,1,1]))
1790
+ 10
1791
+
1792
+ TESTS::
1793
+
1794
+ sage: SGA = SymmetricGroupAlgebra(GF(5), 6)
1795
+ sage: SGA.simple_module_dimension(Partition([3,1,1]))
1796
+ Traceback (most recent call last):
1797
+ ...
1798
+ ValueError: [3, 1, 1] is not a partition of 6
1799
+ """
1800
+ if sum(la) != self.n:
1801
+ raise ValueError(f"{la} is not a partition of {self.n}")
1802
+ from sage.combinat.specht_module import simple_module_rank
1803
+ return simple_module_rank(la, self.base_ring())
1804
+
1805
+ def garsia_procesi_module(self, la):
1806
+ r"""
1807
+ Return the :class:`Garsia-Procesi module
1808
+ <sage.combinat.symmetric_group_representations.GarsiaProcesiModule>`
1809
+ of ``self`` indexed by ``la``.
1810
+
1811
+ EXAMPLES::
1812
+
1813
+ sage: SGA = SymmetricGroupAlgebra(GF(2), 6)
1814
+ sage: SGA.garsia_procesi_module(Partition([2,2,1,1]))
1815
+ Garsia-Procesi module of shape [2, 2, 1, 1] over Finite Field of size 2
1816
+ """
1817
+ from sage.combinat.symmetric_group_representations import GarsiaProcesiModule
1818
+ return GarsiaProcesiModule(self, la)
1819
+
1820
+ def jucys_murphy(self, k):
1821
+ r"""
1822
+ Return the Jucys-Murphy element `J_k` (also known as a
1823
+ Young-Jucys-Murphy element) for the symmetric group
1824
+ algebra ``self``.
1825
+
1826
+ The Jucys-Murphy element `J_k` in the symmetric group algebra
1827
+ `R S_n` is defined for every `k \in \{ 1, 2, \ldots, n \}` by
1828
+
1829
+ .. MATH::
1830
+
1831
+ J_k = (1, k) + (2, k) + \cdots + (k-1, k) \in R S_n,
1832
+
1833
+ where the addends are transpositions in `S_n` (regarded as
1834
+ elements of `R S_n`). We note that there is not a dependence on `n`,
1835
+ so it is often suppressed in the notation.
1836
+
1837
+ EXAMPLES::
1838
+
1839
+ sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
1840
+ sage: QS3.jucys_murphy(1)
1841
+ 0
1842
+ sage: QS3.jucys_murphy(2)
1843
+ [2, 1, 3]
1844
+ sage: QS3.jucys_murphy(3)
1845
+ [1, 3, 2] + [3, 2, 1]
1846
+
1847
+ sage: QS4 = SymmetricGroupAlgebra(QQ, 4)
1848
+ sage: j3 = QS4.jucys_murphy(3); j3
1849
+ [1, 3, 2, 4] + [3, 2, 1, 4]
1850
+ sage: j4 = QS4.jucys_murphy(4); j4
1851
+ [1, 2, 4, 3] + [1, 4, 3, 2] + [4, 2, 3, 1]
1852
+ sage: j3*j4 == j4*j3
1853
+ True
1854
+
1855
+ sage: QS5 = SymmetricGroupAlgebra(QQ, 5)
1856
+ sage: QS5.jucys_murphy(4)
1857
+ [1, 2, 4, 3, 5] + [1, 4, 3, 2, 5] + [4, 2, 3, 1, 5]
1858
+
1859
+ TESTS::
1860
+
1861
+ sage: QS3.jucys_murphy(4)
1862
+ Traceback (most recent call last):
1863
+ ...
1864
+ ValueError: k (= 4) must be between 1 and n (= 3) (inclusive)
1865
+ """
1866
+ if k < 1 or k > self.n:
1867
+ raise ValueError("k (= {k}) must be between 1 and n (= {n}) (inclusive)".format(k=k, n=self.n))
1868
+
1869
+ res = self.zero()
1870
+
1871
+ for i in range(1, k):
1872
+ p = list(range(1, self.n + 1))
1873
+ p[i - 1] = k
1874
+ p[k - 1] = i
1875
+ res += self.monomial(self._indices(p))
1876
+ return res
1877
+
1878
+ def seminormal_basis(self, mult='l2r'):
1879
+ r"""
1880
+ Return a list of the seminormal basis elements of ``self``.
1881
+
1882
+ The seminormal basis of a symmetric group algebra is defined as
1883
+ follows:
1884
+
1885
+ Let `n` be a nonnegative integer. Let `R` be a `\QQ`-algebra.
1886
+ In the following, we will use the "left action" convention for
1887
+ multiplying permutations. This means that for all permutations
1888
+ `p` and `q` in `S_n`, the product `pq` is defined in such a way
1889
+ that `(pq)(i) = p(q(i))` for each `i \in \{ 1, 2, \ldots, n \}`
1890
+ (this is the same convention as in :meth:`left_action_product`,
1891
+ but not the default semantics of the `*` operator on
1892
+ permutations in Sage). Thus, for instance, `s_2 s_1` is the
1893
+ permutation obtained by first transposing `1` with `2` and
1894
+ then transposing `2` with `3` (where `s_i = (i, i+1)`).
1895
+
1896
+ For every partition `\lambda` of `n`, let
1897
+
1898
+ .. MATH::
1899
+
1900
+ \kappa_{\lambda} = \frac{n!}{f^{\lambda}}
1901
+
1902
+ where `f^{\lambda}` is the number of standard Young tableaux
1903
+ of shape `\lambda`. Note that `\kappa_{\lambda}` is an integer,
1904
+ namely the product of all hook lengths of `\lambda` (by the
1905
+ hook length formula). In Sage, this integer can be computed by
1906
+ using :func:`sage.combinat.symmetric_group_algebra.kappa()`.
1907
+
1908
+ Let `T` be a standard tableau of size `n`.
1909
+
1910
+ Let `a(T)` denote the formal sum (in `R S_n`) of all
1911
+ permutations in `S_n` which stabilize the rows of `T` (as
1912
+ sets), i. e., which map each entry `i` of `T` to an entry in
1913
+ the same row as `i`. (See
1914
+ :func:`sage.combinat.symmetric_group_algebra.a()` for
1915
+ an implementation of this.)
1916
+
1917
+ Let `b(T)` denote the signed formal sum (in `R S_n`) of all
1918
+ permutations in `S_n` which stabilize the columns of `T` (as
1919
+ sets). Here, "signed" means that each permutation is
1920
+ multiplied with its sign. (This is implemented in
1921
+ :func:`sage.combinat.symmetric_group_algebra.b()`.)
1922
+
1923
+ Define an element `e(T)` of `R S_n` to be `a(T) b(T)`. (This
1924
+ is implemented in :func:`sage.combinat.symmetric_group_algebra.e()`
1925
+ for `R = \QQ`.)
1926
+
1927
+ Let `\mathrm{sh}(T)` denote the shape of `T`.
1928
+ (See :meth:`~sage.combinat.tableau.Tableau.shape`.)
1929
+
1930
+ Let `\overline{T}` denote the standard tableau of size `n-1`
1931
+ obtained by removing the letter `n` (along with its cell) from
1932
+ `T` (if `n \geq 1`).
1933
+
1934
+ Now, we define an element `\epsilon(T)` of `R S_n`. We define
1935
+ it by induction on the size `n` of `T`, so we set
1936
+ `\epsilon(\emptyset) = 1` and only need to define `\epsilon(T)`
1937
+ for `n \geq 1`, assuming that `\epsilon(\overline{T})` is
1938
+ already defined. We do this by setting
1939
+
1940
+ .. MATH::
1941
+
1942
+ \epsilon(T) = \frac{1}{\kappa_{\mathrm{sh}(T)}}
1943
+ \epsilon(\overline{T})
1944
+ e(T) \epsilon(\overline{T}).
1945
+
1946
+ This element `\epsilon(T)` is implemented as
1947
+ :func:`sage.combinat.symmetric_group_algebra.epsilon` for
1948
+ `R = \QQ`, but it is also a particular case of the elements
1949
+ `\epsilon(T, S)` defined below.
1950
+
1951
+ Now let `S` be a further tableau of the same shape as `T`
1952
+ (possibly equal to `T`). Let `\pi_{T, S}` denote the
1953
+ permutation in `S_n` such that applying this permutation to
1954
+ the entries of `T` yields the tableau `S`. Define an element
1955
+ `\epsilon(T, S)` of `R S_n` by
1956
+
1957
+ .. MATH::
1958
+
1959
+ \epsilon(T, S) = \frac{1}{\kappa_{\mathrm{sh}(T)}}
1960
+ \epsilon(\overline S) \pi_{T, S}
1961
+ e(T) \epsilon(\overline T)
1962
+ = \frac{1}{\kappa_{\mathrm{sh}(T)}}
1963
+ \epsilon(\overline S) a(S) \pi_{T, S}
1964
+ b(T) \epsilon(\overline T).
1965
+
1966
+ This element `\epsilon(T, S)` is called *Young's seminormal
1967
+ unit corresponding to the bitableau `(T, S)`*, and is the
1968
+ return value of :meth:`epsilon_ik` applied to ``T`` and
1969
+ ``S``. Note that `\epsilon(T, T) = \epsilon(T)`.
1970
+
1971
+ If we let `\lambda` run through all partitions of `n`, and
1972
+ `(T, S)` run through all pairs of tableaux of shape
1973
+ `\lambda`, then the elements `\epsilon(T, S)` form a basis
1974
+ of `R S_n`. This basis is called *Young's seminormal basis*
1975
+ and has the properties that
1976
+
1977
+ .. MATH::
1978
+
1979
+ \epsilon(T, S) \epsilon(U, V) = \delta_{T, V} \epsilon(U, S)
1980
+
1981
+ (where `\delta` stands for the Kronecker delta).
1982
+
1983
+ .. WARNING::
1984
+
1985
+ Because of our convention, we are multiplying our elements in
1986
+ reverse of those given in some papers, for example [Ram1997]_.
1987
+ Using the other convention of multiplying permutations, we would
1988
+ instead have
1989
+ `\epsilon(U, V) \epsilon(T, S) = \delta_{T, V} \epsilon(U, S)`.
1990
+
1991
+ In other words, Young's seminormal basis consists of the matrix
1992
+ units in a (particular) Artin-Wedderburn decomposition of `R S_n`
1993
+ into a direct product of matrix algebras over `\QQ`.
1994
+
1995
+ The output of :meth:`seminormal_basis` is a list of all
1996
+ elements of the seminormal basis of ``self``.
1997
+
1998
+ INPUT:
1999
+
2000
+ - ``mult`` -- string (default: ``'l2r'``); if set to ``'r2l'``,
2001
+ this causes the method to return the list of the
2002
+ antipodes (:meth:`antipode`) of all `\epsilon(T, S)`
2003
+ instead of the `\epsilon(T, S)` themselves.
2004
+
2005
+ EXAMPLES::
2006
+
2007
+ sage: QS3 = SymmetricGroupAlgebra(QQ,3)
2008
+ sage: QS3.seminormal_basis()
2009
+ [1/6*[1, 2, 3] + 1/6*[1, 3, 2] + 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] + 1/6*[3, 2, 1],
2010
+ 1/3*[1, 2, 3] + 1/6*[1, 3, 2] - 1/3*[2, 1, 3] - 1/6*[2, 3, 1] - 1/6*[3, 1, 2] + 1/6*[3, 2, 1],
2011
+ 1/3*[1, 3, 2] + 1/3*[2, 3, 1] - 1/3*[3, 1, 2] - 1/3*[3, 2, 1],
2012
+ 1/4*[1, 3, 2] - 1/4*[2, 3, 1] + 1/4*[3, 1, 2] - 1/4*[3, 2, 1],
2013
+ 1/3*[1, 2, 3] - 1/6*[1, 3, 2] + 1/3*[2, 1, 3] - 1/6*[2, 3, 1] - 1/6*[3, 1, 2] - 1/6*[3, 2, 1],
2014
+ 1/6*[1, 2, 3] - 1/6*[1, 3, 2] - 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] - 1/6*[3, 2, 1]]
2015
+
2016
+ TESTS::
2017
+
2018
+ sage: QS3g = SymmetricGroup(3).algebra(QQ)
2019
+ sage: QS3g.seminormal_basis()
2020
+ [1/6*() + 1/6*(2,3) + 1/6*(1,2) + 1/6*(1,2,3) + 1/6*(1,3,2) + 1/6*(1,3),
2021
+ 1/3*() + 1/6*(2,3) - 1/3*(1,2) - 1/6*(1,2,3) - 1/6*(1,3,2) + 1/6*(1,3),
2022
+ 1/3*(2,3) + 1/3*(1,2,3) - 1/3*(1,3,2) - 1/3*(1,3),
2023
+ 1/4*(2,3) - 1/4*(1,2,3) + 1/4*(1,3,2) - 1/4*(1,3),
2024
+ 1/3*() - 1/6*(2,3) + 1/3*(1,2) - 1/6*(1,2,3) - 1/6*(1,3,2) - 1/6*(1,3),
2025
+ 1/6*() - 1/6*(2,3) - 1/6*(1,2) + 1/6*(1,2,3) + 1/6*(1,3,2) - 1/6*(1,3)]
2026
+ """
2027
+ basis = []
2028
+ for part in Partitions_n(self.n):
2029
+ stp = StandardTableaux_shape(part)
2030
+ basis.extend(self.epsilon_ik(t1, t2, mult=mult)
2031
+ for t1 in stp
2032
+ for t2 in stp)
2033
+ return basis
2034
+
2035
+ def dft(self, form=None, mult='l2r'):
2036
+ r"""
2037
+ Return the discrete Fourier transform for ``self``.
2038
+
2039
+ See [Mur1983]_ for the construction of central primitive orthogonal idempotents.
2040
+ For each idempotent `e_i` we have a homomorphic projection `v \mapsto v e_i`.
2041
+ Choose a basis for each submodule spanned by `\{\sigma e_i | \sigma \in S_n\}`.
2042
+ The change-of-basis from the standard basis `\{\sigma\}_\sigma` is returned.
2043
+
2044
+ INPUT:
2045
+
2046
+ - ``mult`` -- string (default: `l2r`); if set to `r2l`,
2047
+ this causes the method to use the antipodes
2048
+ (:meth:`antipode`) of the seminormal basis instead of
2049
+ the seminormal basis.
2050
+
2051
+ - ``form`` -- string (default: ``"modular"`` if `p|n!` else ``"seminormal"``);
2052
+ one of the following:
2053
+
2054
+ * ``"seminormal"`` -- use the seminormal basis
2055
+ * ``"modular"`` -- use the modular DFT, which uses the Peirce decomposition
2056
+ of the group algebra into blocks with central orthogonal idempotents
2057
+ * ``"unitary"`` -- use the unitary DFT, which computes the extended
2058
+ Cholesky decomposition of an `S_n`-invariant symmetric bilinear form as
2059
+ a change-of-basis matrix (for positive characteristics, it must be
2060
+ a finite field of square order)
2061
+
2062
+ EXAMPLES:
2063
+
2064
+ The default is the seminormal DFT when the characteristic does not divide the group order::
2065
+
2066
+ sage: QQ_S3 = SymmetricGroupAlgebra(QQ, 3)
2067
+ sage: QQ_S3.dft()
2068
+ [ 1 1 1 1 1 1]
2069
+ [ 1 1/2 -1 -1/2 -1/2 1/2]
2070
+ [ 0 3/4 0 3/4 -3/4 -3/4]
2071
+ [ 0 1 0 -1 1 -1]
2072
+ [ 1 -1/2 1 -1/2 -1/2 -1/2]
2073
+ [ 1 -1 -1 1 1 -1]
2074
+
2075
+ The unitary form works in characteristic zero::
2076
+
2077
+ sage: U = QQ_S3.dft(form='unitary'); U
2078
+ [-1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2]
2079
+ [ 1/3*sqrt3 1/6*sqrt3 -1/3*sqrt3 -1/6*sqrt3 -1/6*sqrt3 1/6*sqrt3]
2080
+ [ 0 1/2 0 1/2 -1/2 -1/2]
2081
+ [ 0 1/2 0 -1/2 1/2 -1/2]
2082
+ [ 1/3*sqrt3 -1/6*sqrt3 1/3*sqrt3 -1/6*sqrt3 -1/6*sqrt3 -1/6*sqrt3]
2083
+ [-1/6*sqrt3*sqrt2 1/6*sqrt3*sqrt2 1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 1/6*sqrt3*sqrt2]
2084
+ sage: U*U.H == 1
2085
+ True
2086
+
2087
+ Over finite fields of square order with characteristic `p > n`, we can perform the unitary DFT::
2088
+
2089
+ sage: GF25_S3 = SymmetricGroupAlgebra(GF(5**2), 3)
2090
+ sage: U = GF25_S3.dft(form='unitary'); U
2091
+ [ 1 1 1 1 1 1]
2092
+ [2*z2 + 4 z2 + 2 3*z2 + 1 4*z2 + 3 4*z2 + 3 z2 + 2]
2093
+ [ 0 2 0 2 3 3]
2094
+ [ 0 z2 + 1 0 4*z2 + 4 z2 + 1 4*z2 + 4]
2095
+ [2*z2 + 4 4*z2 + 3 2*z2 + 4 4*z2 + 3 4*z2 + 3 4*z2 + 3]
2096
+ [ 1 4 4 1 1 4]
2097
+ sage: U*U.H == 1
2098
+ True
2099
+
2100
+ Over fields of characteristic `p > 0` such that `p|n!`, we use the
2101
+ modular Fourier transform (:issue:`37751`)::
2102
+
2103
+ sage: GF2_S3 = SymmetricGroupAlgebra(GF(2), 3)
2104
+ sage: GF2_S3.dft()
2105
+ [1 0 0 0 1 0]
2106
+ [0 1 0 0 0 1]
2107
+ [0 0 1 0 0 1]
2108
+ [0 0 0 1 1 0]
2109
+ [1 0 0 1 1 0]
2110
+ [0 1 1 0 0 1]
2111
+ """
2112
+ if form is None:
2113
+ form = "modular" if self.base_ring().characteristic().divides(self.group().cardinality()) else "seminormal"
2114
+ if form == "seminormal":
2115
+ if self.base_ring().characteristic().divides(self.group().cardinality()):
2116
+ raise ValueError("seminormal does not work when p | n!")
2117
+ return self._dft_seminormal(mult=mult)
2118
+ if form == "modular":
2119
+ return self._dft_modular()
2120
+ if form == "unitary":
2121
+ return self._dft_unitary()
2122
+ raise ValueError(f"invalid form (= {form})")
2123
+
2124
+ def _dft_unitary(self):
2125
+ """
2126
+ Return the unitary form of the discrete Fourier transform for ``self``.
2127
+
2128
+ EXAMPLES::
2129
+
2130
+ sage: QQ_S3 = SymmetricGroupAlgebra(QQ, 3)
2131
+ sage: QQ_S3._dft_unitary()
2132
+ [-1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2]
2133
+ [ 1/3*sqrt3 1/6*sqrt3 -1/3*sqrt3 -1/6*sqrt3 -1/6*sqrt3 1/6*sqrt3]
2134
+ [ 0 1/2 0 1/2 -1/2 -1/2]
2135
+ [ 0 1/2 0 -1/2 1/2 -1/2]
2136
+ [ 1/3*sqrt3 -1/6*sqrt3 1/3*sqrt3 -1/6*sqrt3 -1/6*sqrt3 -1/6*sqrt3]
2137
+ [-1/6*sqrt3*sqrt2 1/6*sqrt3*sqrt2 1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 1/6*sqrt3*sqrt2]
2138
+ sage: GF49_S3 = SymmetricGroupAlgebra(GF(7**2), 3)
2139
+ sage: GF49_S3._dft_unitary()
2140
+ [5*z2 + 5 5*z2 + 5 5*z2 + 5 5*z2 + 5 5*z2 + 5 5*z2 + 5]
2141
+ [2*z2 + 5 z2 + 6 5*z2 + 2 6*z2 + 1 6*z2 + 1 z2 + 6]
2142
+ [ 0 4*z2 + 5 0 4*z2 + 5 3*z2 + 2 3*z2 + 2]
2143
+ [ 0 3*z2 + 2 0 4*z2 + 5 3*z2 + 2 4*z2 + 5]
2144
+ [2*z2 + 5 6*z2 + 1 2*z2 + 5 6*z2 + 1 6*z2 + 1 6*z2 + 1]
2145
+ [5*z2 + 5 2*z2 + 2 2*z2 + 2 5*z2 + 5 5*z2 + 5 2*z2 + 2]
2146
+
2147
+ TESTS::
2148
+
2149
+ sage: QQ_S3 = SymmetricGroupAlgebra(QQ, 3)
2150
+ sage: U = QQ_S3._dft_unitary()
2151
+ sage: U*U.H == 1
2152
+ True
2153
+ sage: GF25_S3 = SymmetricGroupAlgebra(GF(5**2), 3)
2154
+ sage: U = GF25_S3._dft_unitary()
2155
+ sage: U*U.H == 1
2156
+ True
2157
+ sage: GF5_S3 = SymmetricGroupAlgebra(GF(5), 3)
2158
+ sage: U = GF5_S3._dft_unitary()
2159
+ Traceback (most recent call last):
2160
+ ...
2161
+ ValueError: the base ring must be a finite field of square order
2162
+ sage: Z5_S3 = SymmetricGroupAlgebra(Integers(5), 3)
2163
+ sage: U = Z5_S3._dft_unitary()
2164
+ Traceback (most recent call last):
2165
+ ...
2166
+ ValueError: the base ring must be a finite field of square order
2167
+ sage: F.<x> = FunctionField(GF(3))
2168
+ sage: GF3_x_S3 = SymmetricGroupAlgebra(F, 5)
2169
+ sage: U = GF3_x_S3._dft_unitary()
2170
+ Traceback (most recent call last):
2171
+ ...
2172
+ ValueError: the base ring must be a finite field of square order
2173
+ sage: GF9_S3 = SymmetricGroupAlgebra(GF(3**2), 3)
2174
+ sage: U = GF9_S3._dft_unitary()
2175
+ Traceback (most recent call last):
2176
+ ...
2177
+ NotImplementedError: not implemented when p|n!; dimension of invariant forms may be greater than one
2178
+ """
2179
+ from sage.matrix.special import diagonal_matrix
2180
+ F = self.base_ring()
2181
+ G = self.group()
2182
+
2183
+ if F.characteristic() == 0:
2184
+ from sage.misc.functional import sqrt
2185
+ from sage.rings.number_field.number_field import NumberField
2186
+ dft_matrix = self.dft()
2187
+ n = dft_matrix.nrows()
2188
+ diag = [sum(dft_matrix[i, j] * dft_matrix[i, j].conjugate() for j in range(n))
2189
+ for i in range(n)]
2190
+ primes_needed = {factor for d in diag for factor, _ in d.squarefree_part().factor()}
2191
+ names = [f"sqrt{factor}" for factor in primes_needed]
2192
+ x = PolynomialRing(QQ, 'x').gen()
2193
+ K = NumberField([x**2 - d for d in primes_needed], names=names)
2194
+ dft_matrix = dft_matrix.change_ring(K)
2195
+ for i, d in enumerate(diag):
2196
+ dft_matrix[i] *= ~sqrt(K(d))
2197
+ return dft_matrix
2198
+
2199
+ # positive characteristic case
2200
+ assert F.characteristic() > 0, "F must have positive characteristic"
2201
+ if not (F.is_field() and F.is_finite() and F.order().is_square()):
2202
+ raise ValueError("the base ring must be a finite field of square order")
2203
+ if F.characteristic().divides(G.cardinality()):
2204
+ raise NotImplementedError("not implemented when p|n!; dimension of invariant forms may be greater than one")
2205
+ q = F.order().sqrt()
2206
+
2207
+ def conj_square_root(u):
2208
+ if not u:
2209
+ return F.zero()
2210
+ z = F.multiplicative_generator()
2211
+ k = u.log(z)
2212
+ if k % (q+1) != 0:
2213
+ raise ValueError(f"unable to factor as {u} is not in base field GF({q})")
2214
+ return z ** ((k//(q+1)) % (q-1))
2215
+
2216
+ dft_matrix = self.dft()
2217
+ n = dft_matrix.nrows()
2218
+ for i in range(n):
2219
+ d = sum(dft_matrix[i, j] * dft_matrix[i, j].conjugate() for j in range(n))
2220
+ dft_matrix[i] *= ~conj_square_root(d)
2221
+ return dft_matrix
2222
+
2223
+ def _dft_seminormal(self, mult='l2r'):
2224
+ """
2225
+ Return the seminormal form of the discrete Fourier transform for ``self``.
2226
+
2227
+ INPUT:
2228
+
2229
+ - ``mult`` -- string (default: `l2r`); if set to `r2l`,
2230
+ this causes the method to use the antipodes
2231
+ (:meth:`antipode`) of the seminormal basis instead of
2232
+ the seminormal basis.
2233
+
2234
+ EXAMPLES::
2235
+
2236
+ sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
2237
+ sage: QS3._dft_seminormal()
2238
+ [ 1 1 1 1 1 1]
2239
+ [ 1 1/2 -1 -1/2 -1/2 1/2]
2240
+ [ 0 3/4 0 3/4 -3/4 -3/4]
2241
+ [ 0 1 0 -1 1 -1]
2242
+ [ 1 -1/2 1 -1/2 -1/2 -1/2]
2243
+ [ 1 -1 -1 1 1 -1]
2244
+
2245
+ .. SEEALSO::
2246
+
2247
+ :meth:`seminormal_basis`
2248
+ """
2249
+ snb = self.seminormal_basis(mult=mult)
2250
+ return matrix([vector(b) for b in snb]).inverse().transpose()
2251
+
2252
+ def _dft_modular(self):
2253
+ r"""
2254
+ Return the discrete Fourier transform when the characteristic divides the order of the group.
2255
+
2256
+ EXAMPLES::
2257
+
2258
+ sage: GF3S3 = SymmetricGroupAlgebra(GF(3), 3)
2259
+ sage: GF3S3._dft_modular()
2260
+ [1 0 0 0 0 0]
2261
+ [0 1 0 0 0 0]
2262
+ [0 0 1 0 0 0]
2263
+ [0 0 0 1 0 0]
2264
+ [0 0 0 0 1 0]
2265
+ [0 0 0 0 0 1]
2266
+ """
2267
+ idempotents = self.central_orthogonal_idempotents()
2268
+ # project v onto each block U_i = F_p[S_n]*e_i via \pi_i: v |--> v*e_i
2269
+ B = self.basis()
2270
+ blocks = [self.submodule([b * idem for b in B]) for idem in idempotents]
2271
+ # compute the list of basis vectors lifted to the SGA from each block
2272
+ block_decomposition_basis = [u.lift() for block in blocks for u in block.basis()]
2273
+ # construct the matrix to the standard basis in the order given by the group
2274
+ G = self.group()
2275
+ mat = [[b[g] for b in block_decomposition_basis] for g in G]
2276
+ return matrix(self.base_ring(), mat)
2277
+
2278
+ def epsilon_ik(self, itab, ktab, star=0, mult='l2r'):
2279
+ r"""
2280
+ Return the seminormal basis element of ``self`` corresponding to the
2281
+ pair of tableaux ``itab`` and ``ktab`` (or restrictions of these
2282
+ tableaux, if the optional variable ``star`` is set).
2283
+
2284
+ INPUT:
2285
+
2286
+ - ``itab``, ``ktab`` -- two standard tableaux of size `n`
2287
+
2288
+ - ``star`` -- integer (default: `0`)
2289
+
2290
+ - ``mult`` -- string (default: `l2r`); if set to `r2l`,
2291
+ this causes the method to return the antipode
2292
+ (:meth:`antipode`) of `\epsilon(I, K)` instead of
2293
+ `\epsilon(I, K)` itself.
2294
+
2295
+ OUTPUT:
2296
+
2297
+ The element `\epsilon(I, K)`, where `I` and `K` are the tableaux
2298
+ obtained by removing all entries higher than `n - \mathrm{star}`
2299
+ from ``itab`` and ``ktab``, respectively. Here, we are using the
2300
+ notations from :meth:`seminormal_basis`.
2301
+
2302
+ EXAMPLES::
2303
+
2304
+ sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
2305
+ sage: a = QS3.epsilon_ik([[1,2,3]], [[1,2,3]]); a
2306
+ 1/6*[1, 2, 3] + 1/6*[1, 3, 2] + 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] + 1/6*[3, 2, 1]
2307
+ sage: QS3.dft()*vector(a)
2308
+ (1, 0, 0, 0, 0, 0)
2309
+ sage: a = QS3.epsilon_ik([[1,2],[3]], [[1,2],[3]]); a
2310
+ 1/3*[1, 2, 3] - 1/6*[1, 3, 2] + 1/3*[2, 1, 3] - 1/6*[2, 3, 1] - 1/6*[3, 1, 2] - 1/6*[3, 2, 1]
2311
+ sage: QS3.dft()*vector(a)
2312
+ (0, 0, 0, 0, 1, 0)
2313
+
2314
+ Let us take some properties of the seminormal basis listed in
2315
+ the docstring of :meth:`seminormal_basis`, and verify them on
2316
+ the situation of `S_3`.
2317
+
2318
+ First, check the formula
2319
+
2320
+ .. MATH::
2321
+
2322
+ \epsilon(T) = \frac{1}{\kappa_{\mathrm{sh}(T)}}
2323
+ \epsilon(\overline{T})
2324
+ e(T) \epsilon(\overline{T}).
2325
+
2326
+ In fact::
2327
+
2328
+ sage: from sage.combinat.symmetric_group_algebra import e
2329
+ sage: def test_sn1(n):
2330
+ ....: QSn = SymmetricGroupAlgebra(QQ, n)
2331
+ ....: QSn1 = SymmetricGroupAlgebra(QQ, n - 1)
2332
+ ....: for T in StandardTableaux(n):
2333
+ ....: TT = T.restrict(n-1)
2334
+ ....: eTT = QSn1.epsilon_ik(TT, TT)
2335
+ ....: eT = QSn.epsilon_ik(T, T)
2336
+ ....: kT = prod(T.shape().hooks())
2337
+ ....: if kT * eT != eTT * e(T) * eTT:
2338
+ ....: return False
2339
+ ....: return True
2340
+ sage: test_sn1(3)
2341
+ True
2342
+ sage: test_sn1(4) # long time
2343
+ True
2344
+
2345
+ Next, we check the identity
2346
+
2347
+ .. MATH::
2348
+
2349
+ \epsilon(T, S) = \frac{1}{\kappa_{\mathrm{sh}(T)}}
2350
+ \epsilon(\overline S) \pi_{T, S}
2351
+ e(T) \epsilon(\overline T)
2352
+
2353
+ which we used to define `\epsilon(T, S)`. In fact::
2354
+
2355
+ sage: from sage.combinat.symmetric_group_algebra import e
2356
+ sage: def test_sn2(n):
2357
+ ....: QSn = SymmetricGroupAlgebra(QQ, n)
2358
+ ....: mul = QSn.left_action_product
2359
+ ....: QSn1 = SymmetricGroupAlgebra(QQ, n - 1)
2360
+ ....: for lam in Partitions(n):
2361
+ ....: k = prod(lam.hooks())
2362
+ ....: for T in StandardTableaux(lam):
2363
+ ....: for S in StandardTableaux(lam):
2364
+ ....: TT = T.restrict(n-1)
2365
+ ....: SS = S.restrict(n-1)
2366
+ ....: eTT = QSn1.epsilon_ik(TT, TT)
2367
+ ....: eSS = QSn1.epsilon_ik(SS, SS)
2368
+ ....: eTS = QSn.epsilon_ik(T, S)
2369
+ ....: piTS = [0] * n
2370
+ ....: for (i, j) in T.cells():
2371
+ ....: piTS[T[i][j] - 1] = S[i][j]
2372
+ ....: piTS = QSn(Permutation(piTS))
2373
+ ....: if k * eTS != mul(mul(eSS, piTS), mul(e(T), eTT)):
2374
+ ....: return False
2375
+ ....: return True
2376
+ sage: test_sn2(3)
2377
+ True
2378
+ sage: test_sn2(4) # long time
2379
+ True
2380
+
2381
+ Let us finally check the identity
2382
+
2383
+ .. MATH::
2384
+
2385
+ \epsilon(T, S) \epsilon(U, V) = \delta_{T, V} \epsilon(U, S)
2386
+
2387
+ In fact::
2388
+
2389
+ sage: def test_sn3(lam):
2390
+ ....: n = lam.size()
2391
+ ....: QSn = SymmetricGroupAlgebra(QQ, n)
2392
+ ....: mul = QSn.left_action_product
2393
+ ....: for T in StandardTableaux(lam):
2394
+ ....: for S in StandardTableaux(lam):
2395
+ ....: for U in StandardTableaux(lam):
2396
+ ....: for V in StandardTableaux(lam):
2397
+ ....: lhs = mul(QSn.epsilon_ik(T, S), QSn.epsilon_ik(U, V))
2398
+ ....: if T == V:
2399
+ ....: rhs = QSn.epsilon_ik(U, S)
2400
+ ....: else:
2401
+ ....: rhs = QSn.zero()
2402
+ ....: if rhs != lhs:
2403
+ ....: return False
2404
+ ....: return True
2405
+ sage: all( test_sn3(lam) for lam in Partitions(3) )
2406
+ True
2407
+ sage: all( test_sn3(lam) for lam in Partitions(4) ) # long time
2408
+ True
2409
+ """
2410
+ it = Tableau(itab)
2411
+ kt = Tableau(ktab)
2412
+
2413
+ stn = StandardTableaux_size(self.n)
2414
+
2415
+ if it not in stn:
2416
+ raise TypeError("it must be a standard tableau of size %s" % self.n)
2417
+
2418
+ if kt not in stn:
2419
+ raise TypeError("kt must be a standard tableau of size %s" % self.n)
2420
+
2421
+ if it.shape() != kt.shape():
2422
+ raise ValueError("it and kt must be of the same shape")
2423
+
2424
+ BR = self.base_ring()
2425
+ I = self._indices
2426
+ z_elts = {}
2427
+ epik = epsilon_ik(it, kt, star=star)
2428
+ for m, c in epik._monomial_coefficients.items():
2429
+ z_elts[I(m)] = BR(c)
2430
+ z = self._from_dict(z_elts)
2431
+
2432
+ if mult == 'l2r':
2433
+ return z
2434
+ else:
2435
+ return z.map_support(lambda x: x.inverse())
2436
+
2437
+ def murphy_basis(self):
2438
+ r"""
2439
+ Return the :class:`Murphy basis
2440
+ <sage.combinat.symmetric_group_algebra.MurphyBasis>` of ``self``.
2441
+
2442
+ EXAMPLES::
2443
+
2444
+ sage: SGA = SymmetricGroupAlgebra(QQ, 3)
2445
+ sage: M = SGA.murphy_basis()
2446
+ sage: M(SGA.an_element())
2447
+ -C([1, 1, 1], [[1], [2], [3]], [[1], [2], [3]])
2448
+ + C([2, 1], [[1, 2], [3]], [[1, 2], [3]])
2449
+ + C([2, 1], [[1, 2], [3]], [[1, 3], [2]])
2450
+ + 2*C([2, 1], [[1, 3], [2]], [[1, 2], [3]])
2451
+ + 4*C([2, 1], [[1, 3], [2]], [[1, 3], [2]])
2452
+ - 3*C([3], [[1, 2, 3]], [[1, 2, 3]])
2453
+ """
2454
+ return MurphyBasis(self)
2455
+
2456
+ @cached_method(key=lambda s, X, Y: (StandardTableaux()(X), StandardTableaux()(Y)))
2457
+ def murphy_basis_element(self, S, T):
2458
+ r"""
2459
+ Return the Murphy basis element indexed by ``S`` and ``T``.
2460
+
2461
+ .. SEEALSO::
2462
+
2463
+ :class:`~sage.combinat.symmetric_group_algebra.MurphyBasis`
2464
+
2465
+ EXAMPLES::
2466
+
2467
+ sage: import itertools
2468
+ sage: SGA = SymmetricGroupAlgebra(QQ, 3)
2469
+ sage: for S, T in itertools.product(StandardTableaux([2,1]), repeat=2):
2470
+ ....: print(S, T, SGA.murphy_basis_element(S, T))
2471
+ [[1, 3], [2]] [[1, 3], [2]] [1, 2, 3] + [2, 1, 3]
2472
+ [[1, 3], [2]] [[1, 2], [3]] [1, 3, 2] + [3, 1, 2]
2473
+ [[1, 2], [3]] [[1, 3], [2]] [1, 3, 2] + [2, 3, 1]
2474
+ [[1, 2], [3]] [[1, 2], [3]] [1, 2, 3] + [3, 2, 1]
2475
+
2476
+ TESTS::
2477
+
2478
+ sage: SGA = SymmetricGroupAlgebra(QQ, 3)
2479
+ sage: SGA.murphy_basis_element([[1,2,3,4]], [[1,2],[3,4]])
2480
+ Traceback (most recent call last):
2481
+ ...
2482
+ ValueError: [[1, 2, 3, 4]] is not an element of Standard tableaux of size 3
2483
+ sage: SGA.murphy_basis_element([[1,2,3]], [[1,2],[3]])
2484
+ Traceback (most recent call last):
2485
+ ...
2486
+ ValueError: S and T must have the same shape
2487
+ """
2488
+ std_tab = StandardTableaux(self.n)
2489
+ S = std_tab(S)
2490
+ T = std_tab(T)
2491
+ S = S.conjugate()
2492
+ T = T.conjugate()
2493
+
2494
+ la = S.shape()
2495
+ if la != T.shape():
2496
+ raise ValueError("S and T must have the same shape")
2497
+
2498
+ G = self.group()
2499
+ ds = G(list(sum((row for row in S), ())))
2500
+ dt = G(list(sum((row for row in T), ())))
2501
+ return self.monomial(~ds) * self._row_stabilizer(la) * self.monomial(dt)
2502
+
2503
+ @cached_method
2504
+ def _row_stabilizer(self, la):
2505
+ """
2506
+ Return the row stabilizer element of a canonical standard tableau
2507
+ of shape ``la``.
2508
+
2509
+ EXAMPLES::
2510
+
2511
+ sage: SGA = SymmetricGroupAlgebra(QQ, 3)
2512
+ sage: for la in Partitions(3):
2513
+ ....: print(la, SGA._row_stabilizer(la))
2514
+ [3] [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
2515
+ [2, 1] [1, 2, 3] + [2, 1, 3]
2516
+ [1, 1, 1] [1, 2, 3]
2517
+ """
2518
+ G = self.group()
2519
+ return self.sum_of_monomials(G(list(w.tuple())) for w in la.young_subgroup())
2520
+
2521
+ @cached_method
2522
+ def _column_antistabilizer(self, la):
2523
+ """
2524
+ Return the column antistabilizer element of a canonical standard tableau
2525
+ of shape ``la``.
2526
+
2527
+ EXAMPLES::
2528
+
2529
+ sage: SGA = SymmetricGroupAlgebra(QQ, 3)
2530
+ sage: for la in Partitions(3):
2531
+ ....: print(la, SGA._column_antistabilizer(la))
2532
+ [3] [1, 2, 3]
2533
+ [2, 1] [1, 2, 3] - [3, 2, 1]
2534
+ [1, 1, 1] [1, 2, 3] - [1, 3, 2] - [2, 1, 3] + [2, 3, 1] + [3, 1, 2] - [3, 2, 1]
2535
+ """
2536
+ T = []
2537
+ total = 1 # make it 1-based
2538
+ for r in la:
2539
+ T.append(list(range(total, total+r)))
2540
+ total += r
2541
+ T = Tableau(T)
2542
+ G = self.group()
2543
+ R = self.base_ring()
2544
+ return self._from_dict({G(list(w.tuple())): R(w.sign()) for w in T.column_stabilizer()},
2545
+ remove_zeros=False)
2546
+
2547
+ @cached_method
2548
+ def _young_symmetrizer(self, la):
2549
+ """
2550
+ Return the Young symmetrizer of shape ``la`` of ``self``.
2551
+
2552
+ EXAMPLES::
2553
+
2554
+ sage: SGA = SymmetricGroupAlgebra(QQ, 3)
2555
+ sage: for la in Partitions(3):
2556
+ ....: print(la, SGA._young_symmetrizer(la))
2557
+ [3] [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
2558
+ [2, 1] [1, 2, 3] + [2, 1, 3] - [3, 1, 2] - [3, 2, 1]
2559
+ [1, 1, 1] [1, 2, 3] - [1, 3, 2] - [2, 1, 3] + [2, 3, 1] + [3, 1, 2] - [3, 2, 1]
2560
+ """
2561
+ return self._column_antistabilizer(la) * self._row_stabilizer(la)
2562
+
2563
+ def young_symmetrizer(self, la):
2564
+ """
2565
+ Return the Young symmetrizer of shape ``la`` of ``self``.
2566
+
2567
+ EXAMPLES::
2568
+
2569
+ sage: SGA = SymmetricGroupAlgebra(QQ, SymmetricGroup(3))
2570
+ sage: SGA.young_symmetrizer([2,1])
2571
+ () + (1,2) - (1,3,2) - (1,3)
2572
+ sage: SGA = SymmetricGroupAlgebra(QQ, 4)
2573
+ sage: SGA.young_symmetrizer([2,1,1])
2574
+ [1, 2, 3, 4] - [1, 2, 4, 3] + [2, 1, 3, 4] - [2, 1, 4, 3]
2575
+ - [3, 1, 2, 4] + [3, 1, 4, 2] - [3, 2, 1, 4] + [3, 2, 4, 1]
2576
+ + [4, 1, 2, 3] - [4, 1, 3, 2] + [4, 2, 1, 3] - [4, 2, 3, 1]
2577
+ sage: SGA.young_symmetrizer([5,1,1])
2578
+ Traceback (most recent call last):
2579
+ ...
2580
+ ValueError: the partition [5, 1, 1] is not of size 4
2581
+ """
2582
+ la = _Partitions(la)
2583
+ if la.size() != self.n:
2584
+ raise ValueError("the partition {} is not of size {}".format(la, self.n))
2585
+ return self._young_symmetrizer(la)
2586
+
2587
+ def kazhdan_lusztig_cellular_basis(self):
2588
+ r"""
2589
+ Return the Kazhdan-Lusztig basis (at `q = 1`) of ``self``
2590
+ as a cellular basis.
2591
+
2592
+ EXAMPLES::
2593
+
2594
+ sage: SGA = SymmetricGroupAlgebra(QQ, 3)
2595
+ sage: KL = SGA.kazhdan_lusztig_cellular_basis()
2596
+ sage: KL(SGA.an_element())
2597
+ C([2, 1], [[1, 2], [3]], [[1, 2], [3]])
2598
+ + C([2, 1], [[1, 3], [2]], [[1, 2], [3]])
2599
+ + 2*C([2, 1], [[1, 3], [2]], [[1, 3], [2]])
2600
+ - 3*C([3], [[1, 2, 3]], [[1, 2, 3]])
2601
+ """
2602
+ return KLCellularBasis(self)
2603
+
2604
+ @cached_method
2605
+ def kazhdan_lusztig_basis_element(self, w):
2606
+ r"""
2607
+ Return the Kazhdan-Lusztig `C'_w` basis element at `q = 1`.
2608
+
2609
+ EXAMPLES::
2610
+
2611
+ sage: SGA = SymmetricGroupAlgebra(QQ, 3)
2612
+ sage: for w in SGA.group():
2613
+ ....: print(w, SGA.kazhdan_lusztig_basis_element(w))
2614
+ [1, 2, 3] [1, 2, 3]
2615
+ [1, 3, 2] [1, 2, 3] + [1, 3, 2]
2616
+ [2, 1, 3] [1, 2, 3] + [2, 1, 3]
2617
+ [2, 3, 1] [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1]
2618
+ [3, 1, 2] [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [3, 1, 2]
2619
+ [3, 2, 1] [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
2620
+ """
2621
+ from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet
2622
+ G = self.basis().keys()
2623
+ R = self.base_ring()
2624
+ one = R.one()
2625
+ # check if the KL polynomials can be computed using ``coxeter3``
2626
+ try:
2627
+ from sage.libs.coxeter3.coxeter_group import CoxeterGroup as Coxeter3Group
2628
+ except ImportError:
2629
+ # Fallback to using the KL polynomial
2630
+ from sage.combinat.kazhdan_lusztig import KazhdanLusztigPolynomial
2631
+ from sage.groups.perm_gps.permgroup_named import SymmetricGroup
2632
+ q = PolynomialRing(R, 'q').gen()
2633
+ self._KLG = SymmetricGroup(self.n)
2634
+ self._cellular_KL = KazhdanLusztigPolynomial(self._KLG, q)
2635
+ polyfunc = self._cellular_KL.P
2636
+ else:
2637
+ self._cellular_KL = Coxeter3Group(['A', self.n+1])
2638
+ self._KLG = self._cellular_KL
2639
+ polyfunc = self._cellular_KL.kazhdan_lusztig_polynomial
2640
+
2641
+ if w.parent() is not self._KLG:
2642
+ w = self._KLG.from_reduced_word(w.reduced_word())
2643
+ bruhat = RecursivelyEnumeratedSet([w], lambda u: u.bruhat_lower_covers(), structure='graded')
2644
+ return self.element_class(self, {G.from_reduced_word(v.reduced_word()): R(c(q=one))
2645
+ for v in bruhat if (c := polyfunc(v, w))})
2646
+
2647
+
2648
+ epsilon_ik_cache = {}
2649
+
2650
+
2651
+ def epsilon_ik(itab, ktab, star=0):
2652
+ r"""
2653
+ Return the seminormal basis element of the symmetric group
2654
+ algebra `\QQ S_n` corresponding to the pair of tableaux
2655
+ ``itab`` and ``ktab`` (or restrictions of these tableaux,
2656
+ if the optional variable ``star`` is set).
2657
+
2658
+ INPUT:
2659
+
2660
+ - ``itab``, ``ktab`` -- two standard tableaux of same size
2661
+
2662
+ - ``star`` -- integer (default: `0`)
2663
+
2664
+ OUTPUT:
2665
+
2666
+ The element `\epsilon(I, K) \in \QQ S_n`, where `I` and `K`
2667
+ are the tableaux obtained by removing all entries higher
2668
+ than `n - \mathrm{star}` from ``itab`` and ``ktab``,
2669
+ respectively (where `n` is the size of ``itab`` and
2670
+ ``ktab``). Here, we are using the notations from
2671
+ :meth:`~sage.combinat.symmetric_group_algebra.SymmetricGroupAlgebra_n.seminormal_basis`.
2672
+
2673
+ EXAMPLES::
2674
+
2675
+ sage: from sage.combinat.symmetric_group_algebra import epsilon_ik
2676
+ sage: epsilon_ik([[1,2],[3]], [[1,3],[2]])
2677
+ 1/4*[1, 3, 2] - 1/4*[2, 3, 1] + 1/4*[3, 1, 2] - 1/4*[3, 2, 1]
2678
+ sage: epsilon_ik([[1,2],[3]], [[1,3],[2]], star=1)
2679
+ Traceback (most recent call last):
2680
+ ...
2681
+ ValueError: the two tableaux must be of the same shape
2682
+ """
2683
+ it = Tableau(itab)
2684
+ kt = Tableau(ktab)
2685
+ if star:
2686
+ it = it.restrict(it.size() - star)
2687
+ kt = kt.restrict(kt.size() - star)
2688
+
2689
+ if it.shape() != kt.shape():
2690
+ raise ValueError("the two tableaux must be of the same shape")
2691
+
2692
+ if kt == it:
2693
+ res = epsilon(itab)
2694
+ elif (it, kt) in epsilon_ik_cache:
2695
+ res = epsilon_ik_cache[(it, kt)]
2696
+ else:
2697
+ eik = e_ik(it, kt, star)
2698
+ QSn = eik.parent()
2699
+ mul = QSn.right_action_product
2700
+ epsilon_ik_cache[(it, kt)] = mul(mul(epsilon(it, star + 1), eik),
2701
+ epsilon(kt, star + 1)) * (1 / kappa(it.shape()))
2702
+ res = epsilon_ik_cache[(it, kt)]
2703
+
2704
+ return res
2705
+
2706
+
2707
+ epsilon_cache = {}
2708
+
2709
+
2710
+ def epsilon(tab, star=0):
2711
+ r"""
2712
+ The `(T, T)`-th element of the seminormal basis of the group
2713
+ algebra `\QQ[S_n]`, where `T` is the tableau ``tab`` (with its
2714
+ ``star`` highest entries removed if the optional variable
2715
+ ``star`` is set).
2716
+
2717
+ See the docstring of
2718
+ :meth:`~sage.combinat.symmetric_group_algebra.SymmetricGroupAlgebra_n.seminormal_basis`
2719
+ for the notation used herein.
2720
+
2721
+ EXAMPLES::
2722
+
2723
+ sage: from sage.combinat.symmetric_group_algebra import epsilon
2724
+ sage: epsilon([[1,2]])
2725
+ 1/2*[1, 2] + 1/2*[2, 1]
2726
+ sage: epsilon([[1],[2]])
2727
+ 1/2*[1, 2] - 1/2*[2, 1]
2728
+ """
2729
+ t = Tableau(tab)
2730
+
2731
+ if star:
2732
+ t = t.restrict(t.size() - star)
2733
+
2734
+ if t in epsilon_cache:
2735
+ res = epsilon_cache[t]
2736
+ else:
2737
+ if t.size() == 2:
2738
+ epsilon_cache[t] = e(t) * (1 / kappa(t.shape()))
2739
+ res = epsilon_cache[t]
2740
+ elif t == Tableau([[1]]):
2741
+ epsilon_cache[t] = e(t)
2742
+ res = epsilon_cache[t]
2743
+ else:
2744
+ et = e(t)
2745
+ QSn = et.parent()
2746
+ mul = QSn.right_action_product
2747
+ epsilon_cache[t] = mul(mul(epsilon(t, 1), e(t)),
2748
+ epsilon(t, 1)) * (1 / kappa(t.shape()))
2749
+ res = epsilon_cache[t]
2750
+
2751
+ return res
2752
+
2753
+
2754
+ def pi_ik(itab, ktab):
2755
+ r"""
2756
+ Return the permutation `p` which sends every entry of the
2757
+ tableau ``itab`` to the respective entry of the tableau
2758
+ ``ktab``, as an element of the corresponding symmetric group
2759
+ algebra.
2760
+
2761
+ This assumes that ``itab`` and ``ktab`` are tableaux (possibly
2762
+ given just as lists of lists) of the same shape. Both
2763
+ tableaux are allowed to be skew.
2764
+
2765
+ EXAMPLES::
2766
+
2767
+ sage: from sage.combinat.symmetric_group_algebra import pi_ik
2768
+ sage: pi_ik([[1,3],[2]], [[1,2],[3]])
2769
+ [1, 3, 2]
2770
+
2771
+ The same with skew tableaux::
2772
+
2773
+ sage: from sage.combinat.symmetric_group_algebra import pi_ik
2774
+ sage: pi_ik([[None,1,3],[2]], [[None,1,2],[3]])
2775
+ [1, 3, 2]
2776
+ """
2777
+ it = SkewTableau(itab)
2778
+ kt = SkewTableau(ktab)
2779
+ n = kt.size()
2780
+
2781
+ p = [None] * n
2782
+ for i in range(len(kt)):
2783
+ for j in range(len(kt[i])):
2784
+ if it[i][j] is not None:
2785
+ p[it[i][j] - 1] = kt[i][j]
2786
+
2787
+ QSn = SymmetricGroupAlgebra(QQ, n)
2788
+ p = Permutation(p)
2789
+ return QSn(p)
2790
+
2791
+
2792
+ def kappa(alpha):
2793
+ r"""
2794
+ Return `\kappa_\alpha`, which is `n!` divided by the number
2795
+ of standard tableaux of shape `\alpha` (where `\alpha` is a
2796
+ partition of `n`).
2797
+
2798
+ INPUT:
2799
+
2800
+ - ``alpha`` -- integer partition (can be encoded as a list)
2801
+
2802
+ OUTPUT:
2803
+
2804
+ The factorial of the size of ``alpha``, divided by the number of
2805
+ standard tableaux of shape ``alpha``. Equivalently, the product
2806
+ of all hook lengths of ``alpha``.
2807
+
2808
+ EXAMPLES::
2809
+
2810
+ sage: from sage.combinat.symmetric_group_algebra import kappa
2811
+ sage: kappa(Partition([2,1]))
2812
+ 3
2813
+ sage: kappa([2,1])
2814
+ 3
2815
+ """
2816
+ try:
2817
+ n = alpha.size()
2818
+ except AttributeError:
2819
+ n = sum(alpha)
2820
+ return factorial(n) / StandardTableaux(alpha).cardinality()
2821
+
2822
+
2823
+ def a(tableau, star=0, base_ring=QQ):
2824
+ r"""
2825
+ The row projection operator corresponding to the Young tableau
2826
+ ``tableau`` (which is supposed to contain every integer from
2827
+ `1` to its size precisely once, but may and may not be standard).
2828
+
2829
+ This is the sum (in the group algebra of the relevant symmetric
2830
+ group over `\QQ`) of all the permutations which preserve
2831
+ the rows of ``tableau``. It is called `a_{\text{tableau}}` in
2832
+ [EGHLSVY]_, Section 4.2.
2833
+
2834
+ INPUT:
2835
+
2836
+ - ``tableau`` -- Young tableau which contains every integer
2837
+ from `1` to its size precisely once
2838
+
2839
+ - ``star`` -- nonnegative integer (default: `0`); when this
2840
+ optional variable is set, the method computes not the row
2841
+ projection operator of ``tableau``, but the row projection
2842
+ operator of the restriction of ``tableau`` to the entries
2843
+ ``1, 2, ..., tableau.size() - star`` instead.
2844
+
2845
+ - ``base_ring`` -- commutative ring (default: ``QQ``); when this
2846
+ optional variable is set, the row projection operator is
2847
+ computed over a user-determined base ring instead of `\QQ`.
2848
+ (Note that symmetric group algebras currently don't preserve
2849
+ coercion, so e. g. a symmetric group algebra over `\ZZ`
2850
+ does not coerce into the corresponding one over `\QQ`; so
2851
+ convert manually or choose your base rings wisely!)
2852
+
2853
+ EXAMPLES::
2854
+
2855
+ sage: from sage.combinat.symmetric_group_algebra import a
2856
+ sage: a([[1,2]])
2857
+ [1, 2] + [2, 1]
2858
+ sage: a([[1],[2]])
2859
+ [1, 2]
2860
+ sage: a([])
2861
+ []
2862
+ sage: a([[1, 5], [2, 3], [4]])
2863
+ [1, 2, 3, 4, 5] + [1, 3, 2, 4, 5] + [5, 2, 3, 4, 1] + [5, 3, 2, 4, 1]
2864
+ sage: a([[1,4], [2,3]], base_ring=ZZ)
2865
+ [1, 2, 3, 4] + [1, 3, 2, 4] + [4, 2, 3, 1] + [4, 3, 2, 1]
2866
+
2867
+ The same with a skew tableau::
2868
+
2869
+ sage: a([[None,1,4], [2,3]], base_ring=ZZ)
2870
+ [1, 2, 3, 4] + [1, 3, 2, 4] + [4, 2, 3, 1] + [4, 3, 2, 1]
2871
+ """
2872
+ t = SkewTableau(tableau)
2873
+ if star:
2874
+ t = t.restrict(t.size() - star)
2875
+
2876
+ rs = t.row_stabilizer().list()
2877
+ n = t.size()
2878
+
2879
+ sgalg = SymmetricGroupAlgebra(base_ring, n)
2880
+ one = base_ring.one()
2881
+ P = Permutation
2882
+
2883
+ # Ugly hack for the case of an empty tableau, due to the
2884
+ # annoyance of Permutation(Tableau([]).row_stabilizer()[0])
2885
+ # being [1] rather than [] (which seems to have its origins in
2886
+ # permutation group code).
2887
+ # TODO: Fix this.
2888
+ if n <= 1:
2889
+ return sgalg.one()
2890
+
2891
+ rd = {P(h): one for h in rs}
2892
+ return sgalg._from_dict(rd)
2893
+
2894
+
2895
+ def b(tableau, star=0, base_ring=QQ):
2896
+ r"""
2897
+ The column projection operator corresponding to the Young tableau
2898
+ ``tableau`` (which is supposed to contain every integer from
2899
+ `1` to its size precisely once, but may and may not be standard).
2900
+
2901
+ This is the signed sum (in the group algebra of the relevant
2902
+ symmetric group over `\QQ`) of all the permutations which
2903
+ preserve the column of ``tableau`` (where the signs are the usual
2904
+ signs of the permutations). It is called `b_{\text{tableau}}` in
2905
+ [EGHLSVY]_, Section 4.2.
2906
+
2907
+ INPUT:
2908
+
2909
+ - ``tableau`` -- Young tableau which contains every integer
2910
+ from `1` to its size precisely once
2911
+
2912
+ - ``star`` -- nonnegative integer (default: `0`). When this
2913
+ optional variable is set, the method computes not the column
2914
+ projection operator of ``tableau``, but the column projection
2915
+ operator of the restriction of ``tableau`` to the entries
2916
+ ``1, 2, ..., tableau.size() - star`` instead.
2917
+
2918
+ - ``base_ring`` -- commutative ring (default: ``QQ``). When this
2919
+ optional variable is set, the column projection operator is
2920
+ computed over a user-determined base ring instead of `\QQ`.
2921
+ (Note that symmetric group algebras currently don't preserve
2922
+ coercion, so e. g. a symmetric group algebra over `\ZZ`
2923
+ does not coerce into the corresponding one over `\QQ`; so
2924
+ convert manually or choose your base rings wisely!)
2925
+
2926
+ EXAMPLES::
2927
+
2928
+ sage: from sage.combinat.symmetric_group_algebra import b
2929
+ sage: b([[1,2]])
2930
+ [1, 2]
2931
+ sage: b([[1],[2]])
2932
+ [1, 2] - [2, 1]
2933
+ sage: b([])
2934
+ []
2935
+ sage: b([[1, 2, 4], [5, 3]])
2936
+ [1, 2, 3, 4, 5] - [1, 3, 2, 4, 5] - [5, 2, 3, 4, 1] + [5, 3, 2, 4, 1]
2937
+ sage: b([[1, 4], [2, 3]], base_ring=ZZ)
2938
+ [1, 2, 3, 4] - [1, 2, 4, 3] - [2, 1, 3, 4] + [2, 1, 4, 3]
2939
+ sage: b([[1, 4], [2, 3]], base_ring=Integers(5))
2940
+ [1, 2, 3, 4] + 4*[1, 2, 4, 3] + 4*[2, 1, 3, 4] + [2, 1, 4, 3]
2941
+
2942
+ The same with a skew tableau::
2943
+
2944
+ sage: b([[None, 2, 4], [1, 3], [5]])
2945
+ [1, 2, 3, 4, 5] - [1, 3, 2, 4, 5] - [5, 2, 3, 4, 1] + [5, 3, 2, 4, 1]
2946
+
2947
+ With the ``l2r`` setting for multiplication, the unnormalized
2948
+ Young symmetrizer ``e(tableau)`` should be the product
2949
+ ``b(tableau) * a(tableau)`` for every ``tableau``. Let us check
2950
+ this on the standard tableaux of size 5::
2951
+
2952
+ sage: from sage.combinat.symmetric_group_algebra import a, b, e
2953
+ sage: all( e(t) == b(t) * a(t) for t in StandardTableaux(5) )
2954
+ True
2955
+ """
2956
+ t = SkewTableau(tableau)
2957
+ if star:
2958
+ t = t.restrict(t.size() - star)
2959
+
2960
+ cs = t.column_stabilizer().list()
2961
+ n = t.size()
2962
+
2963
+ sgalg = SymmetricGroupAlgebra(base_ring, n)
2964
+ one = base_ring.one()
2965
+ P = Permutation
2966
+
2967
+ # Ugly hack for the case of an empty tableau, due to the
2968
+ # annoyance of Permutation(Tableau([]).row_stabilizer()[0])
2969
+ # being [1] rather than [] (which seems to have its origins in
2970
+ # permutation group code).
2971
+ # TODO: Fix this.
2972
+ if n <= 1:
2973
+ return sgalg.one()
2974
+
2975
+ cd = {P(v): v.sign() * one for v in cs}
2976
+ return sgalg._from_dict(cd)
2977
+
2978
+
2979
+ e_cache = {}
2980
+
2981
+
2982
+ def e(tableau, star=0):
2983
+ r"""
2984
+ The unnormalized Young projection operator corresponding to
2985
+ the Young tableau ``tableau`` (which is supposed to contain
2986
+ every integer from `1` to its size precisely once, but may
2987
+ and may not be standard).
2988
+
2989
+ If `n` is a nonnegative integer, and `T` is a Young tableau
2990
+ containing every integer from `1` to `n` exactly once, then
2991
+ the unnormalized Young projection operator `e(T)` is defined by
2992
+
2993
+ .. MATH::
2994
+
2995
+ e(T) = a(T) b(T) \in \QQ S_n,
2996
+
2997
+ where `a(T) \in \QQ S_n` is the sum of all permutations in `S_n`
2998
+ which fix the rows of `T` (as sets), and `b(T) \in \QQ S_n` is the
2999
+ signed sum of all permutations in `S_n` which fix the columns of
3000
+ `T` (as sets). Here, "signed" means that each permutation is
3001
+ multiplied with its sign; and the product on the group `S_n` is
3002
+ defined in such a way that `(pq)(i) = p(q(i))` for any
3003
+ permutations `p` and `q` and any `1 \leq i \leq n`.
3004
+
3005
+ Note that the definition of `e(T)` is not uniform across
3006
+ literature. Others define it as `b(T) a(T)` instead, or include
3007
+ certain scalar factors (we do not, whence "unnormalized").
3008
+
3009
+ EXAMPLES::
3010
+
3011
+ sage: from sage.combinat.symmetric_group_algebra import e
3012
+ sage: e([[1,2]])
3013
+ [1, 2] + [2, 1]
3014
+ sage: e([[1],[2]])
3015
+ [1, 2] - [2, 1]
3016
+ sage: e([])
3017
+ []
3018
+
3019
+ There are differing conventions for the order of the symmetrizers
3020
+ and antisymmetrizers. This example illustrates our conventions::
3021
+
3022
+ sage: e([[1,2],[3]])
3023
+ [1, 2, 3] + [2, 1, 3] - [3, 1, 2] - [3, 2, 1]
3024
+
3025
+ To obtain the product `b(T) a(T)`, one has to take the antipode
3026
+ of this::
3027
+
3028
+ sage: QS3 = parent(e([[1,2],[3]]))
3029
+ sage: QS3.antipode(e([[1,2],[3]]))
3030
+ [1, 2, 3] + [2, 1, 3] - [2, 3, 1] - [3, 2, 1]
3031
+
3032
+ And here is an example for a skew tableau::
3033
+
3034
+ sage: e([[None, 2, 1], [4, 3]])
3035
+ [1, 2, 3, 4] + [1, 2, 4, 3] - [1, 3, 2, 4] - [1, 4, 2, 3]
3036
+ + [2, 1, 3, 4] + [2, 1, 4, 3] - [2, 3, 1, 4] - [2, 4, 1, 3]
3037
+
3038
+ .. SEEALSO::
3039
+
3040
+ :func:`e_hat`
3041
+ """
3042
+ # TODO:
3043
+ # The current method only computes the e's over QQ. There should be
3044
+ # a way to compute them over other base rings as well. Be careful
3045
+ # with the cache.
3046
+
3047
+ t = SkewTableau(tableau)
3048
+ if star:
3049
+ t = t.restrict(t.size() - star)
3050
+
3051
+ if t in e_cache:
3052
+ res = e_cache[t]
3053
+ else:
3054
+ rs = t.row_stabilizer().list()
3055
+ cs = t.column_stabilizer().list()
3056
+ n = t.size()
3057
+
3058
+ QSn = SymmetricGroupAlgebra(QQ, n)
3059
+ one = QQ.one()
3060
+ P = Permutation
3061
+
3062
+ rd = {P(h): one for h in rs}
3063
+ sym = QSn._from_dict(rd)
3064
+
3065
+ cd = {P(v): QQ(v.sign()) for v in cs}
3066
+ antisym = QSn._from_dict(cd)
3067
+
3068
+ res = QSn.right_action_product(antisym, sym)
3069
+
3070
+ # Ugly hack for the case of an empty tableau, due to the
3071
+ # annoyance of Permutation(Tableau([]).row_stabilizer()[0])
3072
+ # being [1] rather than [] (which seems to have its origins in
3073
+ # permutation group code).
3074
+ # TODO: Fix this.
3075
+ if n <= 1:
3076
+ return QSn.one()
3077
+
3078
+ e_cache[t] = res
3079
+
3080
+ return res
3081
+
3082
+
3083
+ ehat_cache = {}
3084
+
3085
+
3086
+ def e_hat(tab, star=0):
3087
+ r"""
3088
+ The Young projection operator corresponding to the Young tableau
3089
+ ``tab`` (which is supposed to contain every integer from `1` to
3090
+ its size precisely once, but may and may not be standard). This
3091
+ is an idempotent in the rational group algebra.
3092
+
3093
+ If `n` is a nonnegative integer, and `T` is a Young tableau
3094
+ containing every integer from `1` to `n` exactly once, then
3095
+ the Young projection operator `\widehat{e}(T)` is defined by
3096
+
3097
+ .. MATH::
3098
+
3099
+ \widehat{e}(T) = \frac{1}{\kappa_\lambda} a(T) b(T) \in \QQ S_n,
3100
+
3101
+ where `\lambda` is the shape of `T`, where `\kappa_\lambda` is
3102
+ `n!` divided by the number of standard tableaux of shape
3103
+ `\lambda`, where `a(T) \in \QQ S_n` is the sum of all
3104
+ permutations in `S_n` which fix the rows of `T` (as sets), and
3105
+ where `b(T) \in \QQ S_n` is the signed sum of all permutations
3106
+ in `S_n` which fix the columns of `T` (as sets). Here, "signed"
3107
+ means that each permutation is multiplied with its sign; and
3108
+ the product on the group `S_n` is defined in such a way that
3109
+ `(pq)(i) = p(q(i))` for any permutations `p` and `q` and any
3110
+ `1 \leq i \leq n`.
3111
+
3112
+ Note that the definition of `\widehat{e}(T)` is not uniform
3113
+ across literature. Others define it as
3114
+ `\frac{1}{\kappa_\lambda} b(T) a(T)` instead.
3115
+
3116
+ EXAMPLES::
3117
+
3118
+ sage: from sage.combinat.symmetric_group_algebra import e_hat
3119
+ sage: e_hat([[1,2,3]])
3120
+ 1/6*[1, 2, 3] + 1/6*[1, 3, 2] + 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] + 1/6*[3, 2, 1]
3121
+ sage: e_hat([[1],[2]])
3122
+ 1/2*[1, 2] - 1/2*[2, 1]
3123
+
3124
+ There are differing conventions for the order of the symmetrizers
3125
+ and antisymmetrizers. This example illustrates our conventions::
3126
+
3127
+ sage: e_hat([[1,2],[3]])
3128
+ 1/3*[1, 2, 3] + 1/3*[2, 1, 3] - 1/3*[3, 1, 2] - 1/3*[3, 2, 1]
3129
+
3130
+ .. SEEALSO::
3131
+
3132
+ :func:`e`
3133
+ """
3134
+ t = SkewTableau(tab)
3135
+ # This is for consistency's sake. This method is NOT meant
3136
+ # to be applied to skew tableaux, since the meaning of
3137
+ # \kappa is unclear in that case.
3138
+ if star:
3139
+ t = t.restrict(t.size() - star)
3140
+ if t in ehat_cache:
3141
+ res = ehat_cache[t]
3142
+ else:
3143
+ res = (1 / kappa(t.shape())) * e(t)
3144
+ return res
3145
+
3146
+
3147
+ e_ik_cache = {}
3148
+
3149
+
3150
+ def e_ik(itab, ktab, star=0):
3151
+ """
3152
+ EXAMPLES::
3153
+
3154
+ sage: from sage.combinat.symmetric_group_algebra import e_ik
3155
+ sage: e_ik([[1,2,3]], [[1,2,3]])
3156
+ [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
3157
+ sage: e_ik([[1,2,3]], [[1,2,3]], star=1)
3158
+ [1, 2] + [2, 1]
3159
+ """
3160
+ it = SkewTableau(itab)
3161
+ kt = SkewTableau(ktab)
3162
+ if star:
3163
+ it = it.restrict(it.size() - star)
3164
+ kt = kt.restrict(kt.size() - star)
3165
+
3166
+ if it.shape() != kt.shape():
3167
+ raise ValueError("the two tableaux must be of the same shape")
3168
+
3169
+ if kt == it:
3170
+ return e(it)
3171
+ if (it, kt) in e_ik_cache:
3172
+ return e_ik_cache[(it, kt)]
3173
+
3174
+ pi = pi_ik(it, kt)
3175
+ QSn = pi.parent()
3176
+ res = QSn.right_action_product(e(it), pi)
3177
+ e_ik_cache[(it, kt)] = res
3178
+ return res
3179
+
3180
+
3181
+ def seminormal_test(n):
3182
+ """
3183
+ Run a variety of tests to verify that the construction of the
3184
+ seminormal basis works as desired. The numbers appearing are
3185
+ results in James and Kerber's 'Representation Theory of the
3186
+ Symmetric Group' [JK1981]_.
3187
+
3188
+ EXAMPLES::
3189
+
3190
+ sage: from sage.combinat.symmetric_group_algebra import seminormal_test
3191
+ sage: seminormal_test(3)
3192
+ True
3193
+ """
3194
+ for part in Partitions_n(n):
3195
+ for tab in StandardTableaux(part):
3196
+ # Theorem 3.1.10
3197
+ if not e(tab) * (1 / kappa(part)) - e_hat(tab) == 0:
3198
+ raise ValueError("3.1.10 - %s" % tab)
3199
+
3200
+ # Lemma 3.2.12 (ii)
3201
+ value = e(tab) * epsilon(tab, 1) * e(tab) - e(tab) * kappa(part)
3202
+ if value != 0:
3203
+ print(value)
3204
+ raise ValueError("3.2.12.2 - %s" % tab)
3205
+
3206
+ for tab2 in StandardTableaux(part):
3207
+ # 3.2.8 (i)
3208
+ if e_ik(tab, tab2) - e(tab) * pi_ik(tab, tab2) * e(tab2) * (1 / kappa(part)) != 0:
3209
+ raise ValueError("3.2.8.1 - %s, %s" % (tab, tab2))
3210
+
3211
+ # 3.2.8 (ii)
3212
+ if e(tab) * e_ik(tab, tab2) - e_ik(tab, tab2) * kappa(part) != 0:
3213
+ raise ValueError("3.2.8.2 - %s, %s" % (tab, tab2))
3214
+
3215
+ if tab == tab2:
3216
+ continue
3217
+
3218
+ if tab.last_letter_lequal(tab2):
3219
+ # Lemma 3.1.20
3220
+ if e(tab2) * e(tab) != 0:
3221
+ raise ValueError("3.1.20 - %s, %s" % (tab, tab2))
3222
+ if e_hat(tab2) * e_hat(tab) != 0:
3223
+ raise ValueError("3.1.20 - %s, %s" % (tab, tab2))
3224
+ return True
3225
+
3226
+
3227
+ #######################
3228
+
3229
+
3230
+ class SGACellularBasis(CellularBasis):
3231
+ r"""
3232
+ A cellular basis of the symmetric group algebra.
3233
+ """
3234
+ def __init__(self, SGA):
3235
+ r"""
3236
+ Initialize ``self``.
3237
+
3238
+ EXAMPLES::
3239
+
3240
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 3)
3241
+ sage: M = SGA.murphy_basis()
3242
+ sage: TestSuite(M).run()
3243
+ sage: KL = SGA.kazhdan_lusztig_cellular_basis()
3244
+ sage: TestSuite(KL).run()
3245
+ """
3246
+ CellularBasis.__init__(self, SGA, self._to_sga)
3247
+
3248
+ def _repr_(self):
3249
+ r"""
3250
+ Return a string representation of ``self``.
3251
+
3252
+ EXAMPLES::
3253
+
3254
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 4)
3255
+ sage: SGA.murphy_basis()
3256
+ Murphy basis of Symmetric group algebra of order 4 over Finite Field of size 3
3257
+ sage: SGA.kazhdan_lusztig_cellular_basis()
3258
+ Kazhdan-Lusztig basis of Symmetric group algebra of order 4 over Finite Field of size 3
3259
+ """
3260
+ return self._name + " basis of {}".format(self._algebra)
3261
+
3262
+ @cached_method
3263
+ def one_basis(self):
3264
+ r"""
3265
+ Return the index of the basis element for the multiplicative identity.
3266
+
3267
+ EXAMPLES::
3268
+
3269
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 4)
3270
+ sage: M = SGA.murphy_basis()
3271
+ sage: M.one_basis()
3272
+ ([4], [[1, 2, 3, 4]], [[1, 2, 3, 4]])
3273
+ """
3274
+ la = _Partitions([self._algebra.n])
3275
+ col = la.standard_tableaux()[0]
3276
+ return (la, col, col)
3277
+
3278
+ @cached_method
3279
+ def one(self):
3280
+ r"""
3281
+ Return the element `1` in ``self``.
3282
+
3283
+ EXAMPLES::
3284
+
3285
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 4)
3286
+ sage: M = SGA.murphy_basis()
3287
+ sage: M.one()
3288
+ C([4], [[1, 2, 3, 4]], [[1, 2, 3, 4]])
3289
+ """
3290
+ return self.monomial(self.one_basis())
3291
+
3292
+
3293
+ class MurphyBasis(SGACellularBasis):
3294
+ r"""
3295
+ The Murphy basis of a symmetric group algebra.
3296
+
3297
+ Let `R` be a commutative ring, and let `A = R[S_n]` denote the group
3298
+ algebra (over `R`) of `S_n`. The *Murphy basis* is the basis of `A`
3299
+ defined as follows. Let `S, T` be standard tableaux of shape `\lambda`.
3300
+ Define `T^{\lambda}` as the standard tableau of shape `\lambda` with
3301
+ the first row filled with `1, \ldots, \lambda_1`, the second row
3302
+ `\lambda_1+1, \ldots, \lambda_1+\lambda_2`, and so on. Let `d(S)` be
3303
+ the unique permutation such that `S = T^{\lambda} d(S)` under the natural
3304
+ action. Then the Murphy basis element indexed by `S` and `T` is
3305
+
3306
+ .. MATH::
3307
+
3308
+ M_{S'T'} = d(S)^{-1} R_{\lambda} d(T),
3309
+
3310
+ where `S'` denotes the conjugate tableau.
3311
+ The Murphy basis is a :class:`cellular basis
3312
+ <sage.algebras.cellular_basis.CellularBasis>` of `A`.
3313
+
3314
+ EXAMPLES::
3315
+
3316
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 5)
3317
+ sage: M = SGA.murphy_basis()
3318
+ sage: for la in M.simple_module_parameterization():
3319
+ ....: CM = M.cell_module(la)
3320
+ ....: print(la, CM.dimension(), CM.simple_module().dimension())
3321
+ [2, 2, 1] 5 4
3322
+ [3, 1, 1] 6 6
3323
+ [3, 2] 5 1
3324
+ [4, 1] 4 4
3325
+ [5] 1 1
3326
+
3327
+ REFERENCES:
3328
+
3329
+ - [DJM1998]_
3330
+ - [Mathas2004]_
3331
+ """
3332
+ _name = "Murphy"
3333
+
3334
+ def _to_sga(self, ind):
3335
+ r"""
3336
+ Return the element in the symmetric group algebra indexed by ``ind``.
3337
+
3338
+ EXAMPLES::
3339
+
3340
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 3)
3341
+ sage: M = SGA.murphy_basis()
3342
+ sage: for ind in M.basis().keys():
3343
+ ....: print(ind, M._to_sga(ind))
3344
+ ([1, 1, 1], [[1], [2], [3]], [[1], [2], [3]]) [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
3345
+ ([2, 1], [[1, 3], [2]], [[1, 3], [2]]) [1, 2, 3] + [2, 1, 3]
3346
+ ([2, 1], [[1, 3], [2]], [[1, 2], [3]]) [1, 3, 2] + [3, 1, 2]
3347
+ ([2, 1], [[1, 2], [3]], [[1, 3], [2]]) [1, 3, 2] + [2, 3, 1]
3348
+ ([2, 1], [[1, 2], [3]], [[1, 2], [3]]) [1, 2, 3] + [3, 2, 1]
3349
+ ([3], [[1, 2, 3]], [[1, 2, 3]]) [1, 2, 3]
3350
+ """
3351
+ return self._algebra.murphy_basis_element(ind[1], ind[2])
3352
+
3353
+
3354
+ class KLCellularBasis(SGACellularBasis):
3355
+ """
3356
+ The Kazhdan-Lusztig `C'` basis (at `q = 1`) of the symmetric group
3357
+ algebra realized as a :class:`cellular basis
3358
+ <sage.algebras.cellular_basis.CellularBasis>`
3359
+
3360
+ EXAMPLES::
3361
+
3362
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 5)
3363
+ sage: KL = SGA.kazhdan_lusztig_cellular_basis()
3364
+ sage: for la in KL.simple_module_parameterization():
3365
+ ....: CM = KL.cell_module(la)
3366
+ ....: print(la, CM.dimension(), CM.simple_module().dimension())
3367
+ [2, 2, 1] 5 4
3368
+ [3, 1, 1] 6 6
3369
+ [3, 2] 5 1
3370
+ [4, 1] 4 4
3371
+ [5] 1 1
3372
+ """
3373
+ _name = "Kazhdan-Lusztig"
3374
+
3375
+ def _to_sga(self, ind):
3376
+ r"""
3377
+ Return the element in the symmetric group algebra indexed by ``ind``.
3378
+
3379
+ EXAMPLES::
3380
+
3381
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 3)
3382
+ sage: KL = SGA.kazhdan_lusztig_cellular_basis()
3383
+ sage: for ind in KL.basis().keys():
3384
+ ....: print(ind, KL._to_sga(ind))
3385
+ ([1, 1, 1], [[1], [2], [3]], [[1], [2], [3]]) [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
3386
+ ([2, 1], [[1, 3], [2]], [[1, 3], [2]]) [1, 2, 3] + [2, 1, 3]
3387
+ ([2, 1], [[1, 3], [2]], [[1, 2], [3]]) [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [3, 1, 2]
3388
+ ([2, 1], [[1, 2], [3]], [[1, 3], [2]]) [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1]
3389
+ ([2, 1], [[1, 2], [3]], [[1, 2], [3]]) [1, 2, 3] + [1, 3, 2]
3390
+ ([3], [[1, 2, 3]], [[1, 2, 3]]) [1, 2, 3]
3391
+ """
3392
+ from sage.combinat.rsk import RSK_inverse
3393
+ S = ind[1]
3394
+ T = ind[2]
3395
+ w = RSK_inverse(T, S, output='permutation')
3396
+ return self._algebra.kazhdan_lusztig_basis_element(w)
3397
+
3398
+
3399
+ #######################
3400
+
3401
+
3402
+ def HeckeAlgebraSymmetricGroupT(R, n, q=None):
3403
+ r"""
3404
+ Return the Hecke algebra of the symmetric group `S_n` on the T-basis
3405
+ with quantum parameter ``q`` over the ring `R`.
3406
+
3407
+ If `R` is a commutative ring and `q` is an invertible element of `R`,
3408
+ and if `n` is a nonnegative integer, then the Hecke algebra of the
3409
+ symmetric group `S_n` over `R` with quantum parameter `q` is defined
3410
+ as the algebra generated by the generators `T_1, T_2, \ldots, T_{n-1}`
3411
+ with relations
3412
+
3413
+ .. MATH::
3414
+
3415
+ T_i T_{i+1} T_i = T_{i+1} T_i T_{i+1}
3416
+
3417
+ for all `i < n-1` ("braid relations"),
3418
+
3419
+ .. MATH::
3420
+
3421
+ T_i T_j = T_j T_i
3422
+
3423
+ for all `i` and `j` such that `| i-j | > 1` ("locality relations"),
3424
+ and
3425
+
3426
+ .. MATH::
3427
+
3428
+ T_i^2 = q + (q-1) T_i
3429
+
3430
+ for all `i` (the "quadratic relations", also known in the form
3431
+ `(T_i + 1) (T_i - q) = 0`). (This is only one of several existing
3432
+ definitions in literature, not all of which are fully equivalent.
3433
+ We are following the conventions of [Go1993]_.) For any permutation
3434
+ `w \in S_n`, we can define an element `T_w` of this Hecke algebra by
3435
+ setting `T_w = T_{i_1} T_{i_2} \cdots T_{i_k}`, where
3436
+ `w = s_{i_1} s_{i_2} \cdots s_{i_k}` is a reduced word for `w`
3437
+ (with `s_i` meaning the transposition `(i, i+1)`, and the product of
3438
+ permutations being evaluated by first applying `s_{i_k}`, then
3439
+ `s_{i_{k-1}}`, etc.). This element is independent of the choice of
3440
+ the reduced decomposition, and can be computed in Sage by calling
3441
+ ``H[w]`` where ``H`` is the Hecke algebra and ``w`` is the
3442
+ permutation.
3443
+
3444
+ The Hecke algebra of the symmetric group `S_n` with quantum parameter
3445
+ `q` over `R` can be seen as a deformation of the group algebra
3446
+ `R S_n`; indeed, it becomes `R S_n` when `q = 1`.
3447
+
3448
+ .. WARNING::
3449
+
3450
+ The multiplication on the Hecke algebra of the symmetric group
3451
+ does *not* follow the global option ``mult`` of the
3452
+ :class:`Permutations` class (see
3453
+ :meth:`~sage.combinat.permutation.Permutations.options`).
3454
+ It is always as defined above. It does not match the default
3455
+ option (``mult=l2r``) of the symmetric group algebra!
3456
+
3457
+ EXAMPLES::
3458
+
3459
+ sage: HeckeAlgebraSymmetricGroupT(QQ, 3)
3460
+ Hecke algebra of the symmetric group of order 3 on the T basis over Univariate Polynomial Ring in q over Rational Field
3461
+
3462
+ ::
3463
+
3464
+ sage: HeckeAlgebraSymmetricGroupT(QQ, 3, 2)
3465
+ Hecke algebra of the symmetric group of order 3 with q=2 on the T basis over Rational Field
3466
+
3467
+ The multiplication on the Hecke algebra follows a different convention
3468
+ than the one on the symmetric group algebra does by default::
3469
+
3470
+ sage: H3 = HeckeAlgebraSymmetricGroupT(QQ, 3)
3471
+ sage: H3([1,3,2]) * H3([2,1,3])
3472
+ T[3, 1, 2]
3473
+ sage: S3 = SymmetricGroupAlgebra(QQ, 3)
3474
+ sage: S3([1,3,2]) * S3([2,1,3])
3475
+ [2, 3, 1]
3476
+
3477
+ sage: TestSuite(H3).run()
3478
+
3479
+ .. NOTE::
3480
+
3481
+ :class:`~sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra` gives
3482
+ a different implementation of the Iwahori-Hecke algebras of a Coxeter
3483
+ system `(W,S)`. This includes the Hecke algebras of the symmetric group
3484
+ as special case.
3485
+ """
3486
+ return HeckeAlgebraSymmetricGroup_t(R, n, q)
3487
+
3488
+
3489
+ class HeckeAlgebraSymmetricGroup_generic(CombinatorialFreeModule):
3490
+ def __init__(self, R, n, q=None):
3491
+ """
3492
+ TESTS::
3493
+
3494
+ sage: HeckeAlgebraSymmetricGroupT(QQ, 3)
3495
+ Hecke algebra of the symmetric group of order 3 on the T basis over Univariate Polynomial Ring in q over Rational Field
3496
+
3497
+ ::
3498
+
3499
+ sage: HeckeAlgebraSymmetricGroupT(QQ, 3, q=1)
3500
+ Hecke algebra of the symmetric group of order 3 with q=1 on the T basis over Rational Field
3501
+ """
3502
+ self.n = n
3503
+ self._indices = Permutations(n)
3504
+ self._name = "Hecke algebra of the symmetric group of order {}".format(n)
3505
+ if q is None:
3506
+ q = PolynomialRing(R, 'q').gen()
3507
+ R = q.parent()
3508
+ else:
3509
+ if q not in R:
3510
+ raise ValueError("q must be in R (= {})".format(R))
3511
+ self._name += " with q={}".format(q)
3512
+
3513
+ self._q = q
3514
+
3515
+ CombinatorialFreeModule.__init__(self, R, self._indices,
3516
+ category=AlgebrasWithBasis(R),
3517
+ prefix="")
3518
+
3519
+ _repr_option_bracket = False
3520
+
3521
+ @cached_method
3522
+ def one_basis(self):
3523
+ """
3524
+ Return the identity permutation.
3525
+
3526
+ EXAMPLES::
3527
+
3528
+ sage: HeckeAlgebraSymmetricGroupT(QQ, 3).one() # indirect doctest
3529
+ T[1, 2, 3]
3530
+ """
3531
+ return self._indices.one()
3532
+
3533
+ def q(self):
3534
+ """
3535
+ Return the variable or parameter `q`.
3536
+
3537
+ EXAMPLES::
3538
+
3539
+ sage: HeckeAlgebraSymmetricGroupT(QQ, 3).q()
3540
+ q
3541
+ sage: HeckeAlgebraSymmetricGroupT(QQ, 3, 2).q()
3542
+ 2
3543
+ """
3544
+ return self._q
3545
+
3546
+ def _element_constructor_(self, x):
3547
+ """
3548
+ EXAMPLES::
3549
+
3550
+ sage: H3 = HeckeAlgebraSymmetricGroupT(QQ, 3)
3551
+ sage: H3([2,1]) # indirect doc test
3552
+ T[2, 1, 3]
3553
+ sage: H3( Permutations(3).an_element() )
3554
+ T[3, 1, 2]
3555
+ sage: H3( SymmetricGroup(3).an_element() )
3556
+ [1, 3, 2]
3557
+ sage: H3( [2, 1, 3, 4, 5, 6] )
3558
+ T[2, 1, 3]
3559
+ """
3560
+ ###################################################
3561
+ # Coerce permutations of size smaller that self.n #
3562
+ ###################################################
3563
+ if not x:
3564
+ return self.one()
3565
+ if x in Permutations():
3566
+ if len(x) < self.n:
3567
+ return self.monomial(self._indices(
3568
+ list(x) + list(range(len(x) + 1, self.n + 1))
3569
+ ))
3570
+ if all(x[i] == i+1 for i in range(self.n, len(x))):
3571
+ return self.monomial(self._indices(x[:self.n]))
3572
+
3573
+ return self._indices(x)
3574
+
3575
+
3576
+ class HeckeAlgebraSymmetricGroup_t(HeckeAlgebraSymmetricGroup_generic):
3577
+
3578
+ def __init__(self, R, n, q=None):
3579
+ """
3580
+ TESTS::
3581
+
3582
+ sage: H3 = HeckeAlgebraSymmetricGroupT(QQ, 3)
3583
+ sage: H3 == loads(dumps(H3))
3584
+ True
3585
+ """
3586
+ HeckeAlgebraSymmetricGroup_generic.__init__(self, R, n, q)
3587
+ self._name += " on the T basis"
3588
+ self.print_options(prefix='T')
3589
+
3590
+ def t_action_on_basis(self, perm, i):
3591
+ r"""
3592
+ Return the product `T_i \cdot T_{perm}`, where ``perm`` is a
3593
+ permutation in the symmetric group `S_n`.
3594
+
3595
+ EXAMPLES::
3596
+
3597
+ sage: H3 = HeckeAlgebraSymmetricGroupT(QQ, 3)
3598
+ sage: H3.t_action_on_basis(Permutation([2,1,3]), 1)
3599
+ q*T[1, 2, 3] + (q-1)*T[2, 1, 3]
3600
+ sage: H3.t_action_on_basis(Permutation([1,2,3]), 1)
3601
+ T[2, 1, 3]
3602
+ sage: H3 = HeckeAlgebraSymmetricGroupT(QQ, 3, 1)
3603
+ sage: H3.t_action_on_basis(Permutation([2,1,3]), 1)
3604
+ T[1, 2, 3]
3605
+ sage: H3.t_action_on_basis(Permutation([1,3,2]), 2)
3606
+ T[1, 2, 3]
3607
+ """
3608
+ if i not in range(1, self.n):
3609
+ raise ValueError(f"i (= {i}) must be between 1 and n (={self.n})")
3610
+
3611
+ t_i = Permutation((i, i + 1))
3612
+ perm_i = t_i.right_action_product(perm)
3613
+ # This used to be perm_i = t_i * perm. I have changed it to
3614
+ # perm_i = t_i.right_action_product(perm) because it would
3615
+ # otherwise cause TestSuite(H3) to fail when
3616
+ # Permutations.options(mult) would be set to "r2l".
3617
+ # -- Darij, 19 Nov 2013
3618
+
3619
+ if perm[i - 1] < perm[i]:
3620
+ return self.monomial(self._indices(perm_i))
3621
+ else:
3622
+ # Ti^2 = (q - q^(-1))*Ti - q1*q2
3623
+ q = self.q()
3624
+ z_elt = {perm_i: q, perm: q - 1}
3625
+ return self._from_dict(z_elt)
3626
+
3627
+ def t_action(self, a, i):
3628
+ r"""
3629
+ Return the product `T_i \cdot a`.
3630
+
3631
+ EXAMPLES::
3632
+
3633
+ sage: H3 = HeckeAlgebraSymmetricGroupT(QQ, 3)
3634
+ sage: a = H3([2,1,3])+2*H3([1,2,3])
3635
+ sage: H3.t_action(a, 1)
3636
+ q*T[1, 2, 3] + (q+1)*T[2, 1, 3]
3637
+ sage: H3.t(1)*a
3638
+ q*T[1, 2, 3] + (q+1)*T[2, 1, 3]
3639
+ """
3640
+ def t_i(x):
3641
+ return self.t_action_on_basis(x, i)
3642
+ return self._apply_module_endomorphism(a, t_i)
3643
+
3644
+ def product_on_basis(self, perm1, perm2):
3645
+ """
3646
+ EXAMPLES::
3647
+
3648
+ sage: H3 = HeckeAlgebraSymmetricGroupT(QQ, 3, 1)
3649
+ sage: a = H3([2,1,3])+2*H3([1,2,3])-H3([3,2,1])
3650
+ sage: a^2 #indirect doctest
3651
+ 6*T[1, 2, 3] + 4*T[2, 1, 3] - T[2, 3, 1]
3652
+ - T[3, 1, 2] - 4*T[3, 2, 1]
3653
+
3654
+ ::
3655
+
3656
+ sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
3657
+ sage: a = QS3([2,1,3])+2*QS3([1,2,3])-QS3([3,2,1])
3658
+ sage: a^2
3659
+ 6*[1, 2, 3] + 4*[2, 1, 3] - [2, 3, 1] - [3, 1, 2] - 4*[3, 2, 1]
3660
+ """
3661
+ res = self(perm1)
3662
+ for i in perm2.reduced_word():
3663
+ res = self.t_action(res, i)
3664
+ return res
3665
+
3666
+ def t(self, i):
3667
+ """
3668
+ Return the element `T_i` of the Hecke algebra ``self``.
3669
+
3670
+ EXAMPLES::
3671
+
3672
+ sage: H3 = HeckeAlgebraSymmetricGroupT(QQ,3)
3673
+ sage: H3.t(1)
3674
+ T[2, 1, 3]
3675
+ sage: H3.t(2)
3676
+ T[1, 3, 2]
3677
+ sage: H3.t(0)
3678
+ Traceback (most recent call last):
3679
+ ...
3680
+ ValueError: i (= 0) must be between 1 and n-1 (= 2)
3681
+ """
3682
+ if i not in range(1, self.n):
3683
+ raise ValueError(f"i (= {i}) must be between 1 and n-1 (= {self.n - 1})")
3684
+
3685
+ P = self.basis().keys()
3686
+ return self.monomial(P(list(range(1, i)) + [i + 1, i] +
3687
+ list(range(i + 2, self.n + 1))))
3688
+ # The permutation here is simply the transposition (i, i+1).
3689
+
3690
+ def algebra_generators(self):
3691
+ """
3692
+ Return the generators of the algebra.
3693
+
3694
+ EXAMPLES::
3695
+
3696
+ sage: HeckeAlgebraSymmetricGroupT(QQ,3).algebra_generators()
3697
+ [T[2, 1, 3], T[1, 3, 2]]
3698
+ """
3699
+ return [self.t(i) for i in range(1, self.n)]
3700
+
3701
+ def jucys_murphy(self, k):
3702
+ r"""
3703
+ Return the Jucys-Murphy element `J_k` of the Hecke algebra.
3704
+
3705
+ These Jucys-Murphy elements are defined by
3706
+
3707
+ .. MATH::
3708
+
3709
+ J_k = (T_{k-1} T_{k-2} \cdots T_1) (T_1 T_2 \cdots T_{k-1}).
3710
+
3711
+ More explicitly,
3712
+
3713
+ .. MATH::
3714
+
3715
+ J_k = q^{k-1} + \sum_{l=1}^{k-1} (q^l - q^{l-1}) T_{(l, k)}.
3716
+
3717
+ For generic `q`, the `J_k` generate a maximal commutative
3718
+ sub-algebra of the Hecke algebra.
3719
+
3720
+ .. WARNING::
3721
+
3722
+ The specialization `q = 1` does *not* map these elements
3723
+ `J_k` to the Young-Jucys-Murphy elements of the group
3724
+ algebra `R S_n`. (Instead, it maps the "reduced"
3725
+ Jucys-Murphy elements `(J_k - q^{k-1}) / (q - 1)` to the
3726
+ Young-Jucys-Murphy elements of `R S_n`.)
3727
+
3728
+ EXAMPLES::
3729
+
3730
+ sage: H3 = HeckeAlgebraSymmetricGroupT(QQ,3)
3731
+ sage: j2 = H3.jucys_murphy(2); j2
3732
+ q*T[1, 2, 3] + (q-1)*T[2, 1, 3]
3733
+ sage: j3 = H3.jucys_murphy(3); j3
3734
+ q^2*T[1, 2, 3] + (q^2-q)*T[1, 3, 2] + (q-1)*T[3, 2, 1]
3735
+ sage: j2*j3 == j3*j2
3736
+ True
3737
+ sage: j0 = H3.jucys_murphy(1); j0 == H3.one()
3738
+ True
3739
+ sage: H3.jucys_murphy(0)
3740
+ Traceback (most recent call last):
3741
+ ...
3742
+ ValueError: k (= 0) must be between 1 and n (= 3)
3743
+ """
3744
+ if k not in range(2, self.n + 1):
3745
+ if k == 1:
3746
+ return self.one()
3747
+ raise ValueError(f"k (= {k}) must be between 1 and n (= {self.n})")
3748
+
3749
+ q = self.q()
3750
+ P = self._indices
3751
+ v = self.sum_of_terms(((P(list(range(1, l)) + [k] +
3752
+ list(range(l + 1, k)) + [l]),
3753
+ q**l - q**(l - 1))
3754
+ for l in range(1, k)),
3755
+ distinct=True)
3756
+ v += q**(k - 1) * self.one()
3757
+ return v
3758
+
3759
+ # old algorithm:
3760
+ # left = 1
3761
+ # right = 1
3762
+ # for j in range(1, k):
3763
+ # left *= self.t(k-j)
3764
+ # right *= self.t(j)
3765
+ # return left*right
3766
+
3767
+
3768
+ # For unpickling backward compatibility (Sage <= 4.1)
3769
+ register_unpickle_override('sage.combinat.symmetric_group_algebra',
3770
+ 'HeckeAlgebraSymmetricGroupElement_t',
3771
+ CombinatorialFreeModule.Element)
3772
+ register_unpickle_override('sage.combinat.symmetric_group_algebra',
3773
+ 'SymmetricGroupAlgebraElement_n',
3774
+ CombinatorialFreeModule.Element)