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,4053 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ # sage.doctest: needs sage.combinat sage.modules
3
+ r"""
4
+ Quasisymmetric functions
5
+
6
+ REFERENCES:
7
+
8
+ .. [Ges] \I. Gessel, *Multipartite P-partitions and inner products of skew Schur
9
+ functions*, Contemp. Math. **34** (1984), 289-301.
10
+ http://people.brandeis.edu/~gessel/homepage/papers/multipartite.pdf
11
+
12
+ .. [MR] \C. Malvenuto and C. Reutenauer, *Duality between quasi-symmetric
13
+ functions and the Solomon descent algebra*, J. Algebra **177** (1995),
14
+ no. 3, 967-982. http://www.mat.uniroma1.it/people/malvenuto/Duality.pdf
15
+
16
+ .. [GriRei18]_
17
+
18
+ .. [Mal1993] Claudia Malvenuto, *Produits et coproduits des fonctions
19
+ quasi-symétriques et de l'algèbre des descentes*,
20
+ thesis, November 1993.
21
+ http://www1.mat.uniroma1.it/people/malvenuto/Thesis.pdf
22
+
23
+ .. [Haz2004] Michiel Hazewinkel, *Explicit polynomial generators for the
24
+ ring of quasisymmetric functions over the integers*.
25
+ :arxiv:`math/0410366v1`
26
+
27
+ .. [Rad1979] David E. Radford, *A natural ring basis for the shuffle algebra
28
+ and an application to group schemes*, J. Algebra **58** (1979), 432-454.
29
+
30
+ .. [NCSF1] Israel Gelfand, D. Krob, Alain Lascoux, B. Leclerc,
31
+ V. S. Retakh, J.-Y. Thibon,
32
+ *Noncommutative symmetric functions*.
33
+ :arxiv:`hep-th/9407124v1`
34
+
35
+ .. [NCSF2] \D. Krob, B. Leclerc, J.-Y. Thibon,
36
+ *Noncommutative symmetric functions II: Transformations of alphabets*.
37
+ http://www-igm.univ-mlv.fr/~jyt/ARTICLES/NCSF2.ps
38
+
39
+ .. [HLNT09] \F. Hivert, J.-G. Luque, J.-C. Novelli, J.-Y. Thibon,
40
+ *The (1-E)-transform in combinatorial Hopf algebras*.
41
+ :arxiv:`math/0912.0184v2`
42
+
43
+ .. [LMvW13] Kurt Luoto, Stefan Mykytiuk and Stephanie van Willigenburg,
44
+ *An introduction to quasisymmetric Schur functions -- Hopf algebras,
45
+ quasisymmetric functions, and Young composition tableaux*,
46
+ May 23, 2013, Springer.
47
+ http://www.math.ubc.ca/%7Esteph/papers/QuasiSchurBook.pdf
48
+
49
+ .. [BBSSZ2012] Chris Berg, Nantel Bergeron, Franco Saliola,
50
+ Luis Serrano, Mike Zabrocki,
51
+ *A lift of the Schur and Hall-Littlewood bases to
52
+ non-commutative symmetric functions*,
53
+ :arxiv:`1208.5191v3`.
54
+
55
+ .. [Hoff2015] Michael Hoffman.
56
+ *Quasi-symmetric functions and mod* `p` *multiple harmonic sums*.
57
+ Kyushu J. Math. **69** (2015), pp. 345-366.
58
+ :doi:`10.2206/kyushujm.69.345`, :arxiv:`math/0401319v3`.
59
+
60
+ .. [BDHMN2017] Cristina Ballantine, Zajj Daugherty, Angela Hicks, Sarah Mason,
61
+ Elizabeth Niese. *Quasisymmetric power sums*. :arxiv:`1710.11613`.
62
+
63
+ .. [AHM2018] Edward Allen, Joshua Hallam, Sarah Mason, *Dual Immaculate
64
+ Quasisymmetric Functions Expand Positively into Young Quasisymmetric
65
+ Schur Functions*. :arxiv:`1606.03519`
66
+
67
+ .. [SW2010] John Shareshian and Michelle Wachs.
68
+ *Eulerian quasisymmetric functions*. (2010).
69
+ :arxiv:`0812.0764v2`
70
+
71
+ AUTHOR:
72
+
73
+ - Jason Bandlow
74
+ - Franco Saliola
75
+ - Chris Berg
76
+ - Darij Grinberg
77
+ """
78
+ # ****************************************************************************
79
+ # Copyright (C) 2010 Jason Bandlow <jbandlow@gmail.com>,
80
+ # 2012 Franco Saliola <saliola@gmail.com>,
81
+ # 2012 Chris Berg <chrisjamesberg@gmail.com>
82
+ # Distributed under the terms of the GNU General Public License (GPL)
83
+ # https://www.gnu.org/licenses/
84
+ # ****************************************************************************
85
+ from sage.categories.graded_hopf_algebras import GradedHopfAlgebras
86
+ from sage.categories.rings import Rings
87
+ from sage.categories.fields import Fields
88
+ from sage.categories.realizations import Category_realization_of_parent
89
+ from sage.combinat.permutation import Permutations
90
+ from sage.combinat.composition import Composition, Compositions
91
+ from sage.combinat.partition import Partitions, _Partitions
92
+ from sage.combinat.free_module import CombinatorialFreeModule
93
+ from sage.combinat.sf.sf import SymmetricFunctions
94
+ from sage.combinat.ncsf_qsym.generic_basis_code import BasesOfQSymOrNCSF
95
+ from sage.combinat.ncsf_qsym.combinatorics import (number_of_fCT, number_of_SSRCT,
96
+ compositions_order, coeff_pi, coeff_lp, coeff_sp, coeff_ell)
97
+ from sage.combinat.ncsf_qsym.ncsf import NonCommutativeSymmetricFunctions
98
+ from sage.combinat.words.word import Word
99
+ from sage.combinat.tableau import StandardTableaux
100
+ from sage.misc.bindable_class import BindableClass
101
+ from sage.misc.cachefunc import cached_method
102
+ from sage.misc.lazy_import import lazy_import
103
+ from sage.misc.superseded import deprecated_function_alias
104
+ from sage.structure.parent import Parent
105
+ from sage.structure.unique_representation import UniqueRepresentation
106
+
107
+ lazy_import('sage.matrix.constructor', 'matrix')
108
+ lazy_import('sage.matrix.matrix_space', 'MatrixSpace')
109
+
110
+
111
+ class QuasiSymmetricFunctions(UniqueRepresentation, Parent):
112
+ r"""
113
+ .. rubric:: The Hopf algebra of quasisymmetric functions.
114
+
115
+ Let `R` be a commutative ring with unity.
116
+ The `R`-algebra of quasi-symmetric functions may be realized as an
117
+ `R`-subalgebra of the ring of power series in countably many
118
+ variables `R[[x_1, x_2, x_3, \ldots]]`. It consists of those
119
+ formal power series `p` which are degree-bounded (i. e., the degrees
120
+ of all monomials occurring with nonzero coefficient in `p` are bounded
121
+ from above, although the bound can depend on `p`) and satisfy the
122
+ following condition: For every tuple `(a_1, a_2, \ldots, a_m)` of
123
+ positive integers, the coefficient of the monomial
124
+ `x_{i_1}^{a_1} x_{i_2}^{a_2} \cdots x_{i_m}^{a_m}` in `p` is the same
125
+ for all strictly increasing sequences `(i_1 < i_2 < \cdots < i_m)` of
126
+ positive integers. (In other words, the coefficient of a monomial in `p`
127
+ depends only on the sequence of nonzero exponents in the monomial. If
128
+ "sequence" were to be replaced by "multiset" here, we would obtain
129
+ the definition of a symmetric function.)
130
+
131
+ The `R`-algebra of quasi-symmetric functions is commonly called
132
+ `\mathrm{QSym}_R` or occasionally just `\mathrm{QSym}` (when
133
+ `R` is clear from the context or `\ZZ` or `\QQ`). It is graded by
134
+ the total degree of the power series. Its homogeneous elements of degree
135
+ `k` form a free `R`-submodule of rank equal to the number of
136
+ compositions of `k` (that is, `2^{k-1}` if `k \geq 1`, else `1`).
137
+
138
+ The two classical bases of `\mathrm{QSym}`, the monomial basis
139
+ `(M_I)_I` and the fundamental basis `(F_I)_I`, are indexed by
140
+ compositions `I = (I_1, I_2, \cdots, I_\ell )` and defined by the
141
+ formulas:
142
+
143
+ .. MATH::
144
+
145
+ M_I = \sum_{1 \leq i_1 < i_2 < \cdots < i_\ell} x_{i_1}^{I_1}
146
+ x_{i_2}^{I_2} \cdots x_{i_\ell}^{I_\ell}
147
+
148
+ and
149
+
150
+ .. MATH::
151
+
152
+ F_I = \sum_{(j_1, j_2, \ldots, j_n)} x_{j_1} x_{j_2} \cdots
153
+ x_{j_n}
154
+
155
+ where in the second equation the sum runs over all weakly increasing
156
+ `n`-tuples `(j_1, j_2, \ldots, j_n)` of positive integers
157
+ (where `n` is the size of `I`) which increase strictly from `j_r`
158
+ to `j_{r+1}` if `r` is a descent of the composition `I`.
159
+
160
+ These bases are related by the formula
161
+
162
+ `F_I = \sum_{J \leq I} M_J`
163
+
164
+ where the inequality `J \leq I` indicates that `J` is finer than `I`.
165
+
166
+ The `R`-algebra of quasi-symmetric functions is a Hopf algebra,
167
+ with the coproduct satisfying
168
+
169
+ .. MATH::
170
+
171
+ \Delta M_I = \sum_{k=0}^{\ell} M_{(I_1, I_2, \cdots, I_k)} \otimes
172
+ M_{(I_{k+1}, I_{k+2}, \cdots , I_{\ell})}
173
+
174
+ for every composition `I = (I_1, I_2, \cdots , I_\ell )`.
175
+
176
+ It is possible to define an `R`-algebra of quasi-symmetric
177
+ functions in a finite number of variables as well (but it is not
178
+ a bialgebra). These quasi-symmetric functions are actual polynomials
179
+ then, not just power series.
180
+
181
+ Chapter 5 of [GriRei18]_ and Section 11 of [HazWitt1]_ are devoted
182
+ to quasi-symmetric functions, as are Malvenuto's thesis [Mal1993]_
183
+ and part of Chapter 7 of [Sta-EC2]_.
184
+
185
+ .. rubric:: The implementation of the quasi-symmetric function Hopf algebra
186
+
187
+ We realize the `R`-algebra of quasi-symmetric functions in Sage as
188
+ a graded Hopf algebra with basis elements indexed by compositions::
189
+
190
+ sage: QSym = QuasiSymmetricFunctions(QQ)
191
+ sage: QSym.category()
192
+ Join of Category of Hopf algebras over Rational Field
193
+ and Category of graded algebras over Rational Field
194
+ and Category of commutative algebras over Rational Field
195
+ and Category of monoids with realizations
196
+ and Category of graded coalgebras over Rational Field
197
+ and Category of coalgebras over Rational Field with realizations
198
+
199
+ The most standard two bases for this `R`-algebra are the monomial and
200
+ fundamental bases, and are accessible by the ``M()`` and ``F()`` methods::
201
+
202
+ sage: M = QSym.M()
203
+ sage: F = QSym.F()
204
+ sage: M(F[2,1,2])
205
+ M[1, 1, 1, 1, 1] + M[1, 1, 1, 2] + M[2, 1, 1, 1] + M[2, 1, 2]
206
+ sage: F(M[2,1,2])
207
+ F[1, 1, 1, 1, 1] - F[1, 1, 1, 2] - F[2, 1, 1, 1] + F[2, 1, 2]
208
+
209
+ The product on this space is commutative and is inherited from the product
210
+ on the realization within the ring of power series::
211
+
212
+ sage: M[3]*M[1,1] == M[1,1]*M[3]
213
+ True
214
+ sage: M[3]*M[1,1]
215
+ M[1, 1, 3] + M[1, 3, 1] + M[1, 4] + M[3, 1, 1] + M[4, 1]
216
+ sage: F[3]*F[1,1]
217
+ F[1, 1, 3] + F[1, 2, 2] + F[1, 3, 1] + F[1, 4] + F[2, 1, 2]
218
+ + F[2, 2, 1] + F[2, 3] + F[3, 1, 1] + F[3, 2] + F[4, 1]
219
+ sage: M[3]*F[2]
220
+ M[1, 1, 3] + M[1, 3, 1] + M[1, 4] + M[2, 3] + M[3, 1, 1] + M[3, 2]
221
+ + M[4, 1] + M[5]
222
+ sage: F[2]*M[3]
223
+ F[1, 1, 1, 2] - F[1, 2, 2] + F[2, 1, 1, 1] - F[2, 1, 2] - F[2, 2, 1]
224
+ + F[5]
225
+
226
+ There is a coproduct on `\mathrm{QSym}` as well, which in the Monomial
227
+ basis acts by cutting the composition into a left half and a right
228
+ half. The coproduct is not co-commutative::
229
+
230
+ sage: M[1,3,1].coproduct()
231
+ M[] # M[1, 3, 1] + M[1] # M[3, 1] + M[1, 3] # M[1] + M[1, 3, 1] # M[]
232
+ sage: F[1,3,1].coproduct()
233
+ F[] # F[1, 3, 1] + F[1] # F[3, 1] + F[1, 1] # F[2, 1]
234
+ + F[1, 2] # F[1, 1] + F[1, 3] # F[1] + F[1, 3, 1] # F[]
235
+
236
+ .. rubric:: The duality pairing with non-commutative symmetric functions
237
+
238
+ These two operations endow the quasi-symmetric functions
239
+ `\mathrm{QSym}` with the structure of a Hopf algebra. It is the graded
240
+ dual Hopf algebra of the non-commutative symmetric functions `NCSF`.
241
+ Under this duality, the Monomial basis of `\mathrm{QSym}` is dual to
242
+ the Complete basis of `NCSF`, and the Fundamental basis of
243
+ `\mathrm{QSym}` is dual to the Ribbon basis of `NCSF` (see [MR]_).
244
+
245
+ ::
246
+
247
+ sage: S = M.dual(); S
248
+ Non-Commutative Symmetric Functions over the Rational Field in the Complete basis
249
+ sage: M[1,3,1].duality_pairing( S[1,3,1] )
250
+ 1
251
+ sage: M.duality_pairing_matrix( S, degree=4 )
252
+ [1 0 0 0 0 0 0 0]
253
+ [0 1 0 0 0 0 0 0]
254
+ [0 0 1 0 0 0 0 0]
255
+ [0 0 0 1 0 0 0 0]
256
+ [0 0 0 0 1 0 0 0]
257
+ [0 0 0 0 0 1 0 0]
258
+ [0 0 0 0 0 0 1 0]
259
+ [0 0 0 0 0 0 0 1]
260
+ sage: F.duality_pairing_matrix( S, degree=4 )
261
+ [1 0 0 0 0 0 0 0]
262
+ [1 1 0 0 0 0 0 0]
263
+ [1 0 1 0 0 0 0 0]
264
+ [1 1 1 1 0 0 0 0]
265
+ [1 0 0 0 1 0 0 0]
266
+ [1 1 0 0 1 1 0 0]
267
+ [1 0 1 0 1 0 1 0]
268
+ [1 1 1 1 1 1 1 1]
269
+ sage: NCSF = M.realization_of().dual()
270
+ sage: R = NCSF.Ribbon()
271
+ sage: F.duality_pairing_matrix( R, degree=4 )
272
+ [1 0 0 0 0 0 0 0]
273
+ [0 1 0 0 0 0 0 0]
274
+ [0 0 1 0 0 0 0 0]
275
+ [0 0 0 1 0 0 0 0]
276
+ [0 0 0 0 1 0 0 0]
277
+ [0 0 0 0 0 1 0 0]
278
+ [0 0 0 0 0 0 1 0]
279
+ [0 0 0 0 0 0 0 1]
280
+ sage: M.duality_pairing_matrix( R, degree=4 )
281
+ [ 1 0 0 0 0 0 0 0]
282
+ [-1 1 0 0 0 0 0 0]
283
+ [-1 0 1 0 0 0 0 0]
284
+ [ 1 -1 -1 1 0 0 0 0]
285
+ [-1 0 0 0 1 0 0 0]
286
+ [ 1 -1 0 0 -1 1 0 0]
287
+ [ 1 0 -1 0 -1 0 1 0]
288
+ [-1 1 1 -1 1 -1 -1 1]
289
+
290
+ Let `H` and `G` be elements of `\mathrm{QSym}`, and `h` an element of
291
+ `NCSF`. Then, if we represent the duality pairing with the
292
+ mathematical notation `[ \cdot, \cdot ]`,
293
+
294
+ `[H G, h] = [H \otimes G, \Delta(h)]~.`
295
+
296
+ For example, the coefficient of ``M[2,1,4,1]`` in ``M[1,3]*M[2,1,1]`` may be
297
+ computed with the duality pairing::
298
+
299
+ sage: I, J = Composition([1,3]), Composition([2,1,1])
300
+ sage: (M[I]*M[J]).duality_pairing(S[2,1,4,1])
301
+ 1
302
+
303
+ And the coefficient of ``S[1,3] # S[2,1,1]`` in ``S[2,1,4,1].coproduct()`` is
304
+ equal to this result::
305
+
306
+ sage: S[2,1,4,1].coproduct()
307
+ S[] # S[2, 1, 4, 1] + ... + S[1, 3] # S[2, 1, 1] + ... + S[4, 1] # S[2, 1]
308
+
309
+ The duality pairing on the tensor space is another way of getting this
310
+ coefficient, but currently the method ``duality_pairing`` is not defined on
311
+ the tensor squared space. However, we can extend this functionality by
312
+ applying a linear morphism to the terms in the coproduct, as follows::
313
+
314
+ sage: X = S[2,1,4,1].coproduct()
315
+ sage: def linear_morphism(x, y):
316
+ ....: return x.duality_pairing(M[1,3]) * y.duality_pairing(M[2,1,1])
317
+ sage: X.apply_multilinear_morphism(linear_morphism, codomain=ZZ)
318
+ 1
319
+
320
+ Similarly, if `H` is an element of `\mathrm{QSym}` and `g` and `h` are
321
+ elements of `NCSF`, then
322
+
323
+ .. MATH::
324
+
325
+ [ H, g h ] = [ \Delta(H), g \otimes h ].
326
+
327
+ For example, the coefficient of ``R[2,3,1]`` in ``R[2,1]*R[2,1]`` is
328
+ computed with the duality pairing by the following command::
329
+
330
+ sage: (R[2,1]*R[2,1]).duality_pairing(F[2,3,1])
331
+ 1
332
+ sage: R[2,1]*R[2,1]
333
+ R[2, 1, 2, 1] + R[2, 3, 1]
334
+
335
+ This coefficient should then be equal to the coefficient of
336
+ ``F[2,1] # F[2,1]`` in ``F[2,3,1].coproduct()``::
337
+
338
+ sage: F[2,3,1].coproduct()
339
+ F[] # F[2, 3, 1] + ... + F[2, 1] # F[2, 1] + ... + F[2, 3, 1] # F[]
340
+
341
+ This can also be computed by the duality pairing on the tensor space,
342
+ as above::
343
+
344
+ sage: X = F[2,3,1].coproduct()
345
+ sage: def linear_morphism(x, y):
346
+ ....: return x.duality_pairing(R[2,1]) * y.duality_pairing(R[2,1])
347
+ sage: X.apply_multilinear_morphism(linear_morphism, codomain=ZZ)
348
+ 1
349
+
350
+ .. rubric:: The operation dual to multiplication by a non-commutative symmetric function
351
+
352
+ Let `g \in NCSF` and consider the linear endomorphism of `NCSF` defined by
353
+ left (respectively, right) multiplication by `g`. Since there is a duality
354
+ between `\mathrm{QSym}` and `NCSF`, this linear transformation induces an
355
+ operator `g^{\perp}` on `\mathrm{QSym}` satisfying
356
+
357
+ .. MATH::
358
+
359
+ [ g^{\perp}(H), h ] = [ H, gh ].
360
+
361
+ for any non-commutative symmetric function `h`.
362
+
363
+ This is implemented by the method
364
+ :meth:`~sage.combinat.ncsf_qsym.generic_basis_code.BasesOfQSymOrNCSF.ElementMethods.skew_by`.
365
+ Explicitly, if ``H`` is a quasi-symmetric function and ``g``
366
+ a non-commutative symmetric function, then ``H.skew_by(g)`` and
367
+ ``H.skew_by(g, side='right')`` are expressions that satisfy,
368
+ for any non-commutative symmetric function ``h``, the following
369
+ equalities::
370
+
371
+ H.skew_by(g).duality_pairing(h) == H.duality_pairing(g*h)
372
+ H.skew_by(g, side='right').duality_pairing(h) == H.duality_pairing(h*g)
373
+
374
+ For example, ``M[J].skew_by(S[I])`` is `0` unless the composition ``J``
375
+ begins with ``I`` and ``M(J).skew_by(S(I), side='right')`` is `0` unless
376
+ the composition ``J`` ends with ``I``. For example::
377
+
378
+ sage: M[3,2,2].skew_by(S[3])
379
+ M[2, 2]
380
+ sage: M[3,2,2].skew_by(S[2])
381
+ 0
382
+ sage: M[3,2,2].coproduct().apply_multilinear_morphism( lambda x,y: x.duality_pairing(S[3])*y )
383
+ M[2, 2]
384
+ sage: M[3,2,2].skew_by(S[3], side='right')
385
+ 0
386
+ sage: M[3,2,2].skew_by(S[2], side='right')
387
+ M[3, 2]
388
+
389
+ .. rubric:: The counit
390
+
391
+ The counit is defined by sending all elements of positive degree to zero::
392
+
393
+ sage: M[3].degree(), M[3,1,2].degree(), M.one().degree()
394
+ (3, 6, 0)
395
+ sage: M[3].counit()
396
+ 0
397
+ sage: M[3,1,2].counit()
398
+ 0
399
+ sage: M.one().counit()
400
+ 1
401
+ sage: (M[3] - 2*M[3,1,2] + 7).counit()
402
+ 7
403
+ sage: (F[3] - 2*F[3,1,2] + 7).counit()
404
+ 7
405
+
406
+ .. rubric:: The antipode
407
+
408
+ The antipode sends the Fundamental basis element indexed by the
409
+ composition `I` to `(-1)^{|I|}` times the Fundamental
410
+ basis element indexed by the conjugate composition to `I`
411
+ (where `|I|` stands for the size of `I`, that is, the sum of all
412
+ entries of `I`).
413
+ ::
414
+
415
+ sage: F[3,2,2].antipode()
416
+ -F[1, 2, 2, 1, 1]
417
+ sage: Composition([3,2,2]).conjugate()
418
+ [1, 2, 2, 1, 1]
419
+
420
+ The antipodes of the Monomial quasisymmetric functions can also be
421
+ computed easily: Every composition `I` satisfies
422
+
423
+ .. MATH::
424
+
425
+ \omega(M_I) = (-1)^{\ell(I)} \sum M_J,
426
+
427
+ where the sum ranges over all compositions `J` of `|I|`
428
+ which are coarser than the reversed composition `I^r` of
429
+ `I`. Here, `\ell(I)` denotes the length of the composition `I`
430
+ (that is, the number of its parts). ::
431
+
432
+ sage: M[3,2,1].antipode()
433
+ -M[1, 2, 3] - M[1, 5] - M[3, 3] - M[6]
434
+ sage: M[3,2,2].antipode()
435
+ -M[2, 2, 3] - M[2, 5] - M[4, 3] - M[7]
436
+
437
+ We demonstrate here the defining relation of the antipode::
438
+
439
+ sage: X = F[3,2,2].coproduct()
440
+ sage: X.apply_multilinear_morphism(lambda x,y: x*y.antipode())
441
+ 0
442
+ sage: X.apply_multilinear_morphism(lambda x,y: x.antipode()*y)
443
+ 0
444
+
445
+ .. rubric:: The relation with symmetric functions
446
+
447
+ The quasi-symmetric functions are a ring which contain the
448
+ symmetric functions as a subring. The Monomial quasi-symmetric
449
+ functions are related to the monomial symmetric functions by
450
+
451
+ .. MATH::
452
+
453
+ m_\lambda = \sum_{\operatorname{sort}(I) = \lambda} M_I
454
+
455
+ (where `\operatorname{sort}(I)` denotes the result of sorting
456
+ the entries of `I` in decreasing order).
457
+
458
+ There are methods to test if an expression in the quasi-symmetric
459
+ functions is a symmetric function and, if it is, send it to an
460
+ expression in the symmetric functions::
461
+
462
+ sage: f = M[1,1,2] + M[1,2,1]
463
+ sage: f.is_symmetric()
464
+ False
465
+ sage: g = M[3,1] + M[1,3]
466
+ sage: g.is_symmetric()
467
+ True
468
+ sage: g.to_symmetric_function()
469
+ m[3, 1]
470
+
471
+ The expansion of the Schur function in terms of the Fundamental quasi-symmetric
472
+ functions is due to [Ges]_. There is one term in the expansion for each standard
473
+ tableau of shape equal to the partition indexing the Schur function.
474
+ ::
475
+
476
+ sage: f = F[3,2] + F[2,2,1] + F[2,3] + F[1,3,1] + F[1,2,2]
477
+ sage: f.is_symmetric()
478
+ True
479
+ sage: f.to_symmetric_function()
480
+ 5*m[1, 1, 1, 1, 1] + 3*m[2, 1, 1, 1] + 2*m[2, 2, 1] + m[3, 1, 1] + m[3, 2]
481
+ sage: s = SymmetricFunctions(QQ).s()
482
+ sage: s(f.to_symmetric_function())
483
+ s[3, 2]
484
+
485
+ It is also possible to convert a symmetric function to a
486
+ quasi-symmetric function::
487
+
488
+ sage: m = SymmetricFunctions(QQ).m()
489
+ sage: M( m[3,1,1] )
490
+ M[1, 1, 3] + M[1, 3, 1] + M[3, 1, 1]
491
+ sage: F( s[2,2,1] )
492
+ F[1, 1, 2, 1] + F[1, 2, 1, 1] + F[1, 2, 2] + F[2, 1, 2] + F[2, 2, 1]
493
+
494
+ It is possible to experiment with the quasi-symmetric function expansion of other
495
+ bases, but it is important that the base ring be the same for both algebras.
496
+ ::
497
+
498
+ sage: R = QQ['t']
499
+ sage: Qp = SymmetricFunctions(R).hall_littlewood().Qp()
500
+ sage: QSymt = QuasiSymmetricFunctions(R)
501
+ sage: Ft = QSymt.F()
502
+ sage: Ft( Qp[2,2] )
503
+ F[1, 2, 1] + t*F[1, 3] + (t+1)*F[2, 2] + t*F[3, 1] + t^2*F[4]
504
+
505
+ ::
506
+
507
+ sage: K = QQ['q','t'].fraction_field()
508
+ sage: Ht = SymmetricFunctions(K).macdonald().Ht()
509
+ sage: Fqt = QuasiSymmetricFunctions(Ht.base_ring()).F()
510
+ sage: Fqt(Ht[2,1])
511
+ q*t*F[1, 1, 1] + (q+t)*F[1, 2] + (q+t)*F[2, 1] + F[3]
512
+
513
+ The following will raise an error because the base ring of ``F`` is not
514
+ equal to the base ring of ``Ht``::
515
+
516
+ sage: F(Ht[2,1])
517
+ Traceback (most recent call last):
518
+ ...
519
+ TypeError: do not know how to make x (= McdHt[2, 1]) an element of self (=Quasisymmetric functions over the Rational Field in the Fundamental basis)
520
+
521
+ .. rubric:: The map to the ring of polynomials
522
+
523
+ The quasi-symmetric functions can be seen as an inverse limit
524
+ of a subring of a polynomial ring as the number of variables
525
+ increases. Indeed, there exists a projection from the
526
+ quasi-symmetric functions onto the polynomial ring
527
+ `R[x_1, x_2, \ldots, x_n]`. This projection is defined by
528
+ sending the variables `x_{n+1}, x_{n+2}, \cdots` to `0`, while
529
+ the remaining `n` variables remain fixed. Note that this
530
+ projection sends `M_I` to `0` if the length of the composition
531
+ `I` is higher than `n`. ::
532
+
533
+ sage: M[1,3,1].expand(4)
534
+ x0*x1^3*x2 + x0*x1^3*x3 + x0*x2^3*x3 + x1*x2^3*x3
535
+ sage: F[1,3,1].expand(4)
536
+ x0*x1^3*x2 + x0*x1^3*x3 + x0*x1^2*x2*x3 + x0*x1*x2^2*x3 + x0*x2^3*x3 + x1*x2^3*x3
537
+ sage: M[1,3,1].expand(2)
538
+ 0
539
+
540
+ TESTS::
541
+
542
+ sage: QSym = QuasiSymmetricFunctions(QQ); QSym
543
+ Quasisymmetric functions over the Rational Field
544
+ sage: QSym.base_ring()
545
+ Rational Field
546
+ sage: algebras.QSym(QQ) is QSym
547
+ True
548
+ """
549
+
550
+ def __init__(self, R):
551
+ """
552
+ The Hopf algebra of quasi-symmetric functions.
553
+ See ``QuasiSymmetricFunctions`` for full documentation.
554
+
555
+ EXAMPLES::
556
+
557
+ sage: QuasiSymmetricFunctions(QQ)
558
+ Quasisymmetric functions over the Rational Field
559
+ sage: QSym1 = QuasiSymmetricFunctions(FiniteField(23))
560
+ sage: QSym2 = QuasiSymmetricFunctions(Integers(23))
561
+ sage: TestSuite(QuasiSymmetricFunctions(QQ)).run()
562
+ """
563
+ # change the line below to assert R in Rings() once MRO issues from #15536, #15475 are resolved
564
+ assert R in Fields() or R in Rings() # side effect of this statement assures MRO exists for R
565
+ self._base = R # Won't be needed once CategoryObject won't override base_ring
566
+ category = GradedHopfAlgebras(R).Commutative()
567
+ self._category = category
568
+ Parent.__init__(self, category=category.WithRealizations())
569
+
570
+ # Bases
571
+ Monomial = self.Monomial()
572
+ Fundamental = self.Fundamental()
573
+ dualImmaculate = self.dualImmaculate()
574
+ QS = self.Quasisymmetric_Schur()
575
+
576
+ # Change of bases
577
+ Fundamental.module_morphism(Monomial.sum_of_finer_compositions,
578
+ codomain=Monomial, category=category
579
+ ).register_as_coercion()
580
+ Monomial .module_morphism(Fundamental.alternating_sum_of_finer_compositions,
581
+ codomain=Fundamental, category=category
582
+ ).register_as_coercion()
583
+ #This changes dualImmaculate into Monomial
584
+ dualImmaculate.module_morphism(dualImmaculate._to_Monomial_on_basis,
585
+ codomain=Monomial, category=category
586
+ ).register_as_coercion()
587
+ #This changes Monomial into dualImmaculate
588
+ Monomial.module_morphism(dualImmaculate._from_Monomial_on_basis,
589
+ codomain=dualImmaculate, category=category
590
+ ).register_as_coercion()
591
+ #This changes Quasisymmetric Schur into Monomial
592
+ QS .module_morphism(QS._to_monomial_on_basis,
593
+ codomain=Monomial, category=category
594
+ ).register_as_coercion()
595
+ #This changes Monomial into Quasisymmetric Schur
596
+ Monomial.module_morphism(QS._from_monomial_on_basis,
597
+ codomain=QS, category=category
598
+ ).register_as_coercion()
599
+
600
+ # Embedding of Sym into QSym in the monomial bases
601
+ Sym = SymmetricFunctions(self.base_ring())
602
+ Sym_m_to_M = Sym.m().module_morphism(Monomial.sum_of_partition_rearrangements,
603
+ triangular='upper', inverse_on_support=Monomial._comp_to_par,
604
+ codomain=Monomial, category=category)
605
+ Sym_m_to_M.register_as_coercion()
606
+ self.to_symmetric_function = Sym_m_to_M.section()
607
+
608
+ Sym_s_to_F = Sym.s().module_morphism(Fundamental._from_schur_on_basis,
609
+ unitriangular='upper',
610
+ codomain=Fundamental, category=category)
611
+ Sym_s_to_F.register_as_coercion()
612
+
613
+ def _repr_(self):
614
+ r"""
615
+ EXAMPLES::
616
+
617
+ sage: M = QuasiSymmetricFunctions(ZZ).M()
618
+ sage: M._repr_()
619
+ 'Quasisymmetric functions over the Integer Ring in the Monomial basis'
620
+ """
621
+ return "Quasisymmetric functions over the %s" % self.base_ring()
622
+
623
+ def a_realization(self):
624
+ r"""
625
+ Return the realization of the Monomial basis of the ring of quasi-symmetric functions.
626
+
627
+ OUTPUT: the Monomial basis of quasi-symmetric functions
628
+
629
+ EXAMPLES::
630
+
631
+ sage: QuasiSymmetricFunctions(QQ).a_realization()
632
+ Quasisymmetric functions over the Rational Field in the Monomial basis
633
+ """
634
+ return self.Monomial()
635
+
636
+ _shorthands = tuple(['M', 'F', 'E', 'dI', 'QS', 'YQS', 'phi', 'psi'])
637
+
638
+ def dual(self):
639
+ r"""
640
+ Return the dual Hopf algebra of the quasi-symmetric functions, which is the
641
+ non-commutative symmetric functions.
642
+
643
+ OUTPUT: the non-commutative symmetric functions
644
+
645
+ EXAMPLES::
646
+
647
+ sage: QSym = QuasiSymmetricFunctions(QQ)
648
+ sage: QSym.dual()
649
+ Non-Commutative Symmetric Functions over the Rational Field
650
+ """
651
+ return NonCommutativeSymmetricFunctions(self.base_ring())
652
+
653
+ def from_polynomial(self, f, check=True):
654
+ """
655
+ Return the quasi-symmetric function in the Monomial basis
656
+ corresponding to the quasi-symmetric polynomial ``f``.
657
+
658
+ INPUT:
659
+
660
+ - ``f`` -- a polynomial in finitely many variables over the same base
661
+ ring as ``self``. It is assumed that this polynomial is
662
+ quasi-symmetric.
663
+ - ``check`` -- boolean (default: ``True``); checks whether the
664
+ polynomial is indeed quasi-symmetric
665
+
666
+ OUTPUT: quasi-symmetric function in the Monomial basis
667
+
668
+ EXAMPLES::
669
+
670
+ sage: P = PolynomialRing(QQ, 'x', 3)
671
+ sage: x = P.gens()
672
+ sage: f = x[0] + x[1] + x[2]
673
+ sage: QSym = QuasiSymmetricFunctions(QQ)
674
+ sage: QSym.from_polynomial(f)
675
+ M[1]
676
+
677
+ Beware of setting ``check=False``::
678
+
679
+ sage: f = x[0] + 2*x[1] + x[2]
680
+ sage: QSym.from_polynomial(f, check=True)
681
+ Traceback (most recent call last):
682
+ ...
683
+ ValueError: x0 + 2*x1 + x2 is not a quasi-symmetric polynomial
684
+ sage: QSym.from_polynomial(f, check=False)
685
+ M[1]
686
+
687
+ To expand the quasi-symmetric function in a basis other than the
688
+ Monomial basis, the following shorthands are provided::
689
+
690
+ sage: M = QSym.Monomial()
691
+ sage: f = x[0]**2+x[1]**2+x[2]**2
692
+ sage: g = M.from_polynomial(f); g
693
+ M[2]
694
+ sage: F = QSym.Fundamental()
695
+ sage: F(g)
696
+ -F[1, 1] + F[2]
697
+ sage: F.from_polynomial(f)
698
+ -F[1, 1] + F[2]
699
+ """
700
+ assert self.base_ring() == f.base_ring()
701
+ exponent_coefficient = f.monomial_coefficients()
702
+ z = {}
703
+ for e, c in exponent_coefficient.items():
704
+ I = Compositions()([ei for ei in e if ei])
705
+ if I not in z:
706
+ z[I] = c
707
+ out = self.Monomial()._from_dict(z)
708
+ if check and out.expand(f.parent().ngens(), f.parent().variable_names()) != f:
709
+ raise ValueError("%s is not a quasi-symmetric polynomial" % f)
710
+ return out
711
+
712
+ class Bases(Category_realization_of_parent):
713
+ r"""
714
+ Category of bases of quasi-symmetric functions.
715
+
716
+ EXAMPLES::
717
+
718
+ sage: QSym = QuasiSymmetricFunctions(QQ)
719
+ sage: QSym.Bases()
720
+ Category of bases of Quasisymmetric functions over the Rational Field
721
+ """
722
+
723
+ def super_categories(self):
724
+ r"""
725
+ Return the super categories of bases of the Quasi-symmetric functions.
726
+
727
+ OUTPUT: list of categories
728
+
729
+ TESTS::
730
+
731
+ sage: QSym = QuasiSymmetricFunctions(QQ)
732
+ sage: QSym.Bases().super_categories()
733
+ [Category of commutative bases of Non-Commutative Symmetric Functions or Quasisymmetric functions over the Rational Field]
734
+ """
735
+ return [BasesOfQSymOrNCSF(self.base()).Commutative()]
736
+
737
+ class ParentMethods:
738
+ r"""
739
+ Methods common to all bases of ``QuasiSymmetricFunctions``.
740
+ """
741
+
742
+ def from_polynomial(self, f, check=True):
743
+ """
744
+ The quasi-symmetric function expanded in this basis
745
+ corresponding to the quasi-symmetric polynomial ``f``.
746
+
747
+ This is a default implementation that computes
748
+ the expansion in the Monomial basis and converts
749
+ to this basis.
750
+
751
+ INPUT:
752
+
753
+ - ``f`` -- a polynomial in finitely many variables over the same base
754
+ ring as ``self``. It is assumed that this polynomial is
755
+ quasi-symmetric.
756
+ - ``check`` -- boolean (default: ``True``); checks whether the
757
+ polynomial is indeed quasi-symmetric
758
+
759
+ OUTPUT: quasi-symmetric function
760
+
761
+ EXAMPLES::
762
+
763
+ sage: M = QuasiSymmetricFunctions(QQ).Monomial()
764
+ sage: F = QuasiSymmetricFunctions(QQ).Fundamental()
765
+ sage: P = PolynomialRing(QQ, 'x', 3)
766
+ sage: x = P.gens()
767
+ sage: f = x[0] + x[1] + x[2]
768
+ sage: M.from_polynomial(f)
769
+ M[1]
770
+ sage: F.from_polynomial(f)
771
+ F[1]
772
+ sage: f = x[0]**2+x[1]**2+x[2]**2
773
+ sage: M.from_polynomial(f)
774
+ M[2]
775
+ sage: F.from_polynomial(f)
776
+ -F[1, 1] + F[2]
777
+
778
+ If the polynomial is not quasi-symmetric, an error
779
+ is raised::
780
+
781
+ sage: f = x[0]^2+x[1]
782
+ sage: M.from_polynomial(f)
783
+ Traceback (most recent call last):
784
+ ...
785
+ ValueError: x0^2 + x1 is not a quasi-symmetric polynomial
786
+ sage: F.from_polynomial(f)
787
+ Traceback (most recent call last):
788
+ ...
789
+ ValueError: x0^2 + x1 is not a quasi-symmetric polynomial
790
+
791
+ TESTS:
792
+
793
+ We convert some quasi-symmetric functions to quasi-symmetric
794
+ polynomials and back::
795
+
796
+ sage: f = (M[1,2] + M[1,1]).expand(3); f
797
+ x0*x1^2 + x0*x2^2 + x1*x2^2 + x0*x1 + x0*x2 + x1*x2
798
+ sage: M.from_polynomial(f)
799
+ M[1, 1] + M[1, 2]
800
+ sage: f = (2*M[2,1]+M[1,1]+3*M[3]).expand(3)
801
+ sage: M.from_polynomial(f)
802
+ M[1, 1] + 2*M[2, 1] + 3*M[3]
803
+ sage: f = (F[1,2] + F[1,1]).expand(3); f
804
+ x0*x1^2 + x0*x1*x2 + x0*x2^2 + x1*x2^2 + x0*x1 + x0*x2 + x1*x2
805
+ sage: F.from_polynomial(f)
806
+ F[1, 1] + F[1, 2]
807
+ sage: f = (2*F[2,1]+F[1,1]+3*F[3]).expand(3)
808
+ sage: F.from_polynomial(f)
809
+ F[1, 1] + 2*F[2, 1] + 3*F[3]
810
+ """
811
+ g = self.realization_of().from_polynomial(f, check=check)
812
+ return self(g)
813
+
814
+ def Eulerian(self, n, j, k=None):
815
+ """
816
+ Return the Eulerian (quasi)symmetric function `Q_{n,j}` in
817
+ terms of ``self``.
818
+
819
+ INPUT:
820
+
821
+ - ``n`` -- the value `n` or a partition
822
+ - ``j`` -- the number of excedances
823
+ - ``k`` -- (optional) if specified, determines the number of
824
+ fixed points of the permutation
825
+
826
+ EXAMPLES::
827
+
828
+ sage: QSym = QuasiSymmetricFunctions(QQ)
829
+ sage: M = QSym.M()
830
+ sage: M.Eulerian(3, 1)
831
+ 4*M[1, 1, 1] + 3*M[1, 2] + 3*M[2, 1] + 2*M[3]
832
+ sage: M.Eulerian(4, 1, 2)
833
+ 6*M[1, 1, 1, 1] + 4*M[1, 1, 2] + 4*M[1, 2, 1]
834
+ + 2*M[1, 3] + 4*M[2, 1, 1] + 3*M[2, 2] + 2*M[3, 1] + M[4]
835
+ sage: QS = QSym.QS()
836
+ sage: QS.Eulerian(4, 2)
837
+ 2*QS[1, 3] + QS[2, 2] + 2*QS[3, 1] + 3*QS[4]
838
+ sage: QS.Eulerian([2, 2, 1], 2)
839
+ QS[1, 2, 2] + QS[1, 4] + QS[2, 1, 2] + QS[2, 2, 1]
840
+ + QS[2, 3] + QS[3, 2] + QS[4, 1] + QS[5]
841
+ sage: dI = QSym.dI()
842
+ sage: dI.Eulerian(5, 2)
843
+ -dI[1, 3, 1] - 5*dI[1, 4] + dI[2, 2, 1] + dI[3, 1, 1]
844
+ + 5*dI[3, 2] + 6*dI[4, 1] + 6*dI[5]
845
+ """
846
+ F = self.realization_of().F()
847
+ if n in _Partitions:
848
+ n = _Partitions(n)
849
+ return self(F.Eulerian(n, j, k))
850
+
851
+ class ElementMethods:
852
+ r"""
853
+ Methods common to all elements of ``QuasiSymmetricFunctions``.
854
+ """
855
+
856
+ def internal_coproduct(self):
857
+ r"""
858
+ Return the inner coproduct of ``self`` in the basis of ``self``.
859
+
860
+ The inner coproduct (also known as the Kronecker coproduct,
861
+ or as the second comultiplication on the `R`-algebra of
862
+ quasi-symmetric functions) is an `R`-algebra homomorphism
863
+ `\Delta^{\times}` from the `R`-algebra of quasi-symmetric
864
+ functions to the tensor square (over `R`) of quasi-symmetric
865
+ functions. It can be defined in the following two ways:
866
+
867
+ #. If `I` is a composition, then a `(0, I)`-matrix will mean a
868
+ matrix whose entries are nonnegative integers such that no
869
+ row and no column of this matrix is zero, and such that if
870
+ all the nonzero entries of the matrix are read (row by row,
871
+ starting at the topmost row, reading every row from left to
872
+ right), then the reading word obtained is `I`. If `A` is
873
+ a `(0, I)`-matrix, then `\mathrm{row}(A)` will denote the
874
+ vector of row sums of `A` (regarded as a composition), and
875
+ `\mathrm{column}(A)` will denote the vector of column sums
876
+ of `A` (regarded as a composition).
877
+
878
+ For every composition `I`, the internal coproduct
879
+ `\Delta^{\times}(M_I)` of the `I`-th monomial quasisymmetric
880
+ function `M_I` is the sum
881
+
882
+ .. MATH::
883
+
884
+ \sum_{A \hbox{ is a } (0, I) \text{-matrix}}
885
+ M_{\mathrm{row}(A)} \otimes M_{\mathrm{column}(A)}.
886
+
887
+ See Section 11.39 of [HazWitt1]_.
888
+
889
+ #. For every permutation `w`, let `C(w)` denote the descent
890
+ composition of `w`. Then, for any composition `I` of size
891
+ `n`, the internal coproduct `\Delta^{\times}(F_I)` of the
892
+ `I`-th fundamental quasisymmetric function `F_I` is the sum
893
+
894
+ .. MATH::
895
+
896
+ \sum_{\substack{\sigma \in S_n,\\ \tau \in S_n,\\
897
+ \tau \sigma = \pi}} F_{C(\sigma)} \otimes F_{C(\tau)},
898
+
899
+ where `\pi` is any permutation in `S_n` having descent
900
+ composition `I` and where permutations act from the left and
901
+ multiply accordingly, so `\tau \sigma` means first applying
902
+ `\sigma` and then `\tau`. See Theorem 4.23 in [Mal1993]_,
903
+ but beware of the notations which are apparently different
904
+ from those in [HazWitt1]_.
905
+
906
+ The restriction of the internal coproduct to the
907
+ `R`-algebra of symmetric functions is the well-known
908
+ internal coproduct on the symmetric functions.
909
+
910
+ The method :meth:`kronecker_coproduct` is a synonym of this one.
911
+
912
+ EXAMPLES:
913
+
914
+ Let us compute the internal coproduct of `M_{21}` (which is
915
+ short for `M_{[2, 1]}`). The `(0, [2,1])`-matrices are
916
+
917
+ .. MATH::
918
+
919
+ \begin{bmatrix} 2 & 1 \end{bmatrix},
920
+ \begin{bmatrix} 2 \\ 1 \end{bmatrix},
921
+ \begin{bmatrix} 2 & 0 \\ 0 & 1 \end{bmatrix}, \hbox{ and }
922
+ \begin{bmatrix} 0 & 2 \\ 1 & 0 \end{bmatrix}
923
+
924
+ so
925
+
926
+ .. MATH::
927
+
928
+ \Delta^\times(M_{21}) = M_{3} \otimes M_{21} +
929
+ M_{21} \otimes M_3 + M_{21} \otimes M_{21} +
930
+ M_{21} \otimes M_{12}.
931
+
932
+ This is confirmed by the following Sage computation
933
+ (incidentally demonstrating the non-cocommutativity of
934
+ the internal coproduct)::
935
+
936
+ sage: M = QuasiSymmetricFunctions(ZZ).M()
937
+ sage: a = M([2,1])
938
+ sage: a.internal_coproduct()
939
+ M[2, 1] # M[1, 2] + M[2, 1] # M[2, 1] + M[2, 1] # M[3] + M[3] # M[2, 1]
940
+
941
+ Further examples::
942
+
943
+ sage: all( M([i]).internal_coproduct() == tensor([M([i]), M([i])])
944
+ ....: for i in range(1, 4) )
945
+ True
946
+
947
+ sage: M([1, 2]).internal_coproduct()
948
+ M[1, 2] # M[1, 2] + M[1, 2] # M[2, 1] + M[1, 2] # M[3] + M[3] # M[1, 2]
949
+
950
+ The definition of `\Delta^{\times}(M_I)` in terms of
951
+ `(0, I)`-matrices is not suitable for computation in
952
+ cases where the length of `I` is large, but we can use
953
+ it as a doctest. Here is a naive implementation::
954
+
955
+ sage: def naive_internal_coproduct_on_M(I):
956
+ ....: # INPUT: composition I
957
+ ....: # (not quasi-symmetric function)
958
+ ....: # OUTPUT: interior coproduct of M_I
959
+ ....: M = QuasiSymmetricFunctions(ZZ).M()
960
+ ....: M2 = M.tensor(M)
961
+ ....: res = M2.zero()
962
+ ....: l = len(I)
963
+ ....: n = I.size()
964
+ ....: for S in Subsets(range(l**2), l):
965
+ ....: M_list = sorted(S)
966
+ ....: row_M = [sum([I[M_list.index(l * i + j)]
967
+ ....: for j in range(l) if
968
+ ....: l * i + j in S])
969
+ ....: for i in range(l)]
970
+ ....: col_M = [sum([I[M_list.index(l * i + j)]
971
+ ....: for i in range(l) if
972
+ ....: l * i + j in S])
973
+ ....: for j in range(l)]
974
+ ....: if 0 in row_M:
975
+ ....: first_zero = row_M.index(0)
976
+ ....: row_M = row_M[:first_zero]
977
+ ....: if sum(row_M) != n:
978
+ ....: continue
979
+ ....: if 0 in col_M:
980
+ ....: first_zero = col_M.index(0)
981
+ ....: col_M = col_M[:first_zero]
982
+ ....: if sum(col_M) != n:
983
+ ....: continue
984
+ ....: res += tensor([M(Compositions(n)(row_M)),
985
+ ....: M(Compositions(n)(col_M))])
986
+ ....: return res
987
+ sage: all( naive_internal_coproduct_on_M(I)
988
+ ....: == M(I).internal_coproduct()
989
+ ....: for I in Compositions(3) )
990
+ True
991
+
992
+ TESTS:
993
+
994
+ Border cases::
995
+
996
+ sage: M = QuasiSymmetricFunctions(ZZ).M()
997
+ sage: F = QuasiSymmetricFunctions(ZZ).F()
998
+ sage: M([]).internal_coproduct()
999
+ M[] # M[]
1000
+ sage: F([]).internal_coproduct()
1001
+ F[] # F[]
1002
+
1003
+ The implementations on the ``F`` and ``M`` bases agree
1004
+ with each other::
1005
+
1006
+ sage: M = QuasiSymmetricFunctions(ZZ).M()
1007
+ sage: F = QuasiSymmetricFunctions(ZZ).F()
1008
+ sage: def int_copr_on_F_via_M(I):
1009
+ ....: result = tensor([F.zero(), F.zero()])
1010
+ ....: w = M(F(I)).internal_coproduct()
1011
+ ....: for lam, a in w:
1012
+ ....: (U, V) = lam
1013
+ ....: result += a * tensor([F(M(U)), F(M(V))])
1014
+ ....: return result
1015
+ sage: all( int_copr_on_F_via_M(I) == F(I).internal_coproduct()
1016
+ ....: for I in Compositions(3) )
1017
+ True
1018
+ sage: all( int_copr_on_F_via_M(I) == F(I).internal_coproduct()
1019
+ ....: for I in Compositions(4) )
1020
+ True
1021
+
1022
+ Restricting to the subring of symmetric functions gives the
1023
+ standard internal coproduct on the latter::
1024
+
1025
+ sage: M = QuasiSymmetricFunctions(ZZ).M()
1026
+ sage: e = SymmetricFunctions(ZZ).e()
1027
+ sage: def int_copr_of_e_in_M(mu):
1028
+ ....: result = tensor([M.zero(), M.zero()])
1029
+ ....: w = e(mu).internal_coproduct()
1030
+ ....: for lam, a in w:
1031
+ ....: (nu, kappa) = lam
1032
+ ....: result += a * tensor([M(e(nu)), M(e(kappa))])
1033
+ ....: return result
1034
+ sage: all( int_copr_of_e_in_M(mu) == M(e(mu)).internal_coproduct()
1035
+ ....: for mu in Partitions(3) )
1036
+ True
1037
+ sage: all( int_copr_of_e_in_M(mu) == M(e(mu)).internal_coproduct()
1038
+ ....: for mu in Partitions(4) )
1039
+ True
1040
+
1041
+ .. TODO::
1042
+
1043
+ Implement this directly on the monomial basis maybe?
1044
+ The `(0, I)`-matrices are a pain to generate from their
1045
+ definition, but maybe there is a good algorithm.
1046
+ If so, the above "further examples" should be moved
1047
+ to the M-method.
1048
+ """
1049
+ # Coerce to F basis and back, doing the actual computation in that basis.
1050
+ parent = self.parent()
1051
+ F = parent.realization_of().F()
1052
+ from sage.categories.tensor import tensor
1053
+ result = tensor([parent.zero(), parent.zero()])
1054
+ for lam, a in F(self).internal_coproduct():
1055
+ (I, J) = lam
1056
+ result += a * tensor([parent(F(I)), parent(F(J))])
1057
+ return result
1058
+
1059
+ kronecker_coproduct = internal_coproduct
1060
+
1061
+ def adams_operator(self, n):
1062
+ r"""
1063
+ Return the image of the quasi-symmetric function ``self``
1064
+ under the `n`-th Adams operator.
1065
+
1066
+ The `n`-th Adams operator `\mathbf{f}_n` is defined to be
1067
+ the map from the `R`-algebra of quasi-symmetric functions
1068
+ to itself that sends every symmetric function
1069
+ `P(x_1, x_2, x_3, \ldots)` to
1070
+ `P(x_1^n, x_2^n, x_3^n, \ldots)`. This operator `\mathbf{f}_n`
1071
+ is a Hopf algebra endomorphism, and satisfies
1072
+
1073
+ .. MATH::
1074
+
1075
+ f_n M_{(i_1, i_2, i_3, \ldots)} =
1076
+ M_{(ni_1, ni_2, ni_3, \ldots)}
1077
+
1078
+ for every composition `(i_1, i_2, i_3, \ldots)`
1079
+ (where `M` means the monomial basis).
1080
+
1081
+ The `n`-th Adams operator is also called the `n`-th
1082
+ Frobenius endomorphism. It is not related to the Frobenius map
1083
+ which connects the ring of symmetric functions with the
1084
+ representation theory of the symmetric group.
1085
+
1086
+ The `n`-th Adams operator is the `n`-th Adams operator
1087
+ of the `\Lambda`-ring of quasi-symmetric functions over the
1088
+ integers.
1089
+
1090
+ The restriction of the `n`-th Adams operator to the
1091
+ subring formed by all symmetric functions is, not
1092
+ unexpectedly, the `n`-th Adams operator of the ring of
1093
+ symmetric functions.
1094
+
1095
+ .. SEEALSO::
1096
+
1097
+ :meth:`Symmetric functions plethysm
1098
+ <sage.combinat.sf.sfa.SymmetricFunctionAlgebra_generic_Element.plethysm>`
1099
+
1100
+ INPUT:
1101
+
1102
+ - ``n`` -- positive integer
1103
+
1104
+ OUTPUT:
1105
+
1106
+ The result of applying the `n`-th Adams operator (on the
1107
+ ring of quasi-symmetric functions) to ``self``.
1108
+
1109
+ EXAMPLES::
1110
+
1111
+ sage: QSym = QuasiSymmetricFunctions(ZZ)
1112
+ sage: M = QSym.M()
1113
+ sage: F = QSym.F()
1114
+ sage: M[3,2].adams_operator(2)
1115
+ M[6, 4]
1116
+ sage: (M[2,1] - 2*M[3]).adams_operator(4)
1117
+ M[8, 4] - 2*M[12]
1118
+ sage: M([]).adams_operator(3)
1119
+ M[]
1120
+ sage: F[1,1].adams_operator(2)
1121
+ F[1, 1, 1, 1] - F[1, 1, 2] - F[2, 1, 1] + F[2, 2]
1122
+
1123
+ The Adams endomorphisms are multiplicative::
1124
+
1125
+ sage: all( all( M(I).adams_operator(3) * M(J).adams_operator(3)
1126
+ ....: == (M(I) * M(J)).adams_operator(3)
1127
+ ....: for I in Compositions(3) )
1128
+ ....: for J in Compositions(2) )
1129
+ True
1130
+
1131
+ Being Hopf algebra endomorphisms, the Adams operators
1132
+ commute with the antipode::
1133
+
1134
+ sage: all( M(I).adams_operator(4).antipode()
1135
+ ....: == M(I).antipode().adams_operator(4)
1136
+ ....: for I in Compositions(3) )
1137
+ True
1138
+
1139
+ The restriction of the Adams operators to the subring
1140
+ of symmetric functions are the Adams operators of
1141
+ the latter::
1142
+
1143
+ sage: e = SymmetricFunctions(ZZ).e()
1144
+ sage: all( M(e(lam)).adams_operator(3)
1145
+ ....: == M(e(lam).adams_operator(3))
1146
+ ....: for lam in Partitions(3) )
1147
+ True
1148
+ """
1149
+ # Convert to the monomial basis, there apply componentwise,
1150
+ # then convert back.
1151
+ parent = self.parent()
1152
+ M = parent.realization_of().M()
1153
+ C = parent._indices
1154
+ dct = {C([n * i for i in I]): coeff
1155
+ for (I, coeff) in M(self)}
1156
+ result_in_M_basis = M._from_dict(dct)
1157
+ return parent(result_in_M_basis)
1158
+
1159
+ frobenius = deprecated_function_alias(36396, adams_operator)
1160
+
1161
+ def star_involution(self):
1162
+ r"""
1163
+ Return the image of the quasisymmetric function ``self`` under
1164
+ the star involution.
1165
+
1166
+ The star involution is defined as the linear map
1167
+ `QSym \to QSym` which, for every composition `I`, sends the
1168
+ monomial quasisymmetric function `M_I` to `M_{I^r}`. Here, if
1169
+ `I` is a composition, we denote by `I^r` the reversed
1170
+ composition of `I`. Denoting by `f^{\ast}` the image of an
1171
+ element `f \in QSym` under the star involution, it can be shown
1172
+ that every composition `I` satisfies
1173
+
1174
+ .. MATH::
1175
+
1176
+ (M_I)^{\ast} = M_{I^r}, \quad (F_I)^{\ast} = F_{I^r},
1177
+
1178
+ where `F_I` denotes the fundamental quasisymmetric function
1179
+ corresponding to the composition `I`. The star involution is an
1180
+ involution, an algebra automorphism and a coalgebra
1181
+ anti-automorphism of `QSym`. It also is an automorphism of the
1182
+ graded vector space `QSym`, and is the identity on the subspace
1183
+ `Sym` of `QSym`. It is adjoint to the star involution on `NCSF`
1184
+ by the standard adjunction between `NCSF` and `QSym`.
1185
+
1186
+ The star involution has been denoted by `\rho` in [LMvW13]_,
1187
+ section 3.6.
1188
+
1189
+ .. SEEALSO::
1190
+
1191
+ :meth:`star involution on NCSF
1192
+ <sage.combinat.ncsf_qsym.ncsf.NonCommutativeSymmetricFunctions.Bases.ElementMethods.star_involution>`.
1193
+
1194
+ EXAMPLES::
1195
+
1196
+ sage: QSym = QuasiSymmetricFunctions(ZZ)
1197
+ sage: M = QSym.M()
1198
+ sage: M[3,2].star_involution()
1199
+ M[2, 3]
1200
+ sage: M[6,3].star_involution()
1201
+ M[3, 6]
1202
+ sage: (M[9,1] - M[6,2] + 2*M[6,4] - 3*M[3] + 4*M[[]]).star_involution()
1203
+ 4*M[] + M[1, 9] - M[2, 6] - 3*M[3] + 2*M[4, 6]
1204
+ sage: (M[3,3] - 2*M[2]).star_involution()
1205
+ -2*M[2] + M[3, 3]
1206
+ sage: M([4,2]).star_involution()
1207
+ M[2, 4]
1208
+ sage: dI = QSym.dI()
1209
+ sage: dI([1,2]).star_involution()
1210
+ -dI[1, 2] + dI[2, 1]
1211
+ sage: dI.zero().star_involution()
1212
+ 0
1213
+
1214
+ The star involution commutes with the antipode::
1215
+
1216
+ sage: all( M(I).star_involution().antipode()
1217
+ ....: == M(I).antipode().star_involution()
1218
+ ....: for I in Compositions(4) )
1219
+ True
1220
+
1221
+ The star involution is the identity on `Sym`::
1222
+
1223
+ sage: Sym = SymmetricFunctions(ZZ)
1224
+ sage: e = Sym.e()
1225
+ sage: all( M(e(lam)).star_involution() == M(e(lam))
1226
+ ....: for lam in Partitions(4) )
1227
+ True
1228
+ """
1229
+ # Convert to the homogeneous basis, there apply the star
1230
+ # involution componentwise, then convert back.
1231
+ parent = self.parent()
1232
+ M = parent.realization_of().M()
1233
+ dct = {I.reversed(): coeff for (I, coeff) in M(self)}
1234
+ return parent(M._from_dict(dct))
1235
+
1236
+ def omega_involution(self):
1237
+ r"""
1238
+ Return the image of the quasisymmetric function
1239
+ ``self`` under the omega involution.
1240
+
1241
+ The omega involution is defined as the linear map
1242
+ `QSym \to QSym` which, for every composition `I`, sends
1243
+ the fundamental quasisymmetric function `F_I` to
1244
+ `F_{I^t}`, where `I^t` denotes the conjugate
1245
+ (:meth:`~sage.combinat.composition.Composition.conjugate`)
1246
+ of the composition `I`. This map is commonly denoted by
1247
+ `\omega`. It is an algebra homomorphism and a coalgebra
1248
+ antihomomorphism; it also is an involution and an
1249
+ automorphism of the graded vector space `QSym`. Also,
1250
+ every composition `I` satisfies
1251
+
1252
+ .. MATH::
1253
+
1254
+ \omega(M_I) = (-1)^{|I|-\ell(I)} \sum M_J,
1255
+
1256
+ where the sum ranges over all compositions `J` of `|I|`
1257
+ which are coarser than the reversed composition `I^r` of
1258
+ `I`. Here, `\ell(I)` denotes the length of the composition
1259
+ `I` (that is, the number of parts of `I`).
1260
+
1261
+ If `f` is a homogeneous element of `NCSF` of degree `n`,
1262
+ then
1263
+
1264
+ .. MATH::
1265
+
1266
+ \omega(f) = (-1)^n S(f),
1267
+
1268
+ where `S` denotes the antipode of `QSym`.
1269
+
1270
+ The restriction of `\omega` to the ring of symmetric
1271
+ functions (which is a subring of `QSym`) is precisely the
1272
+ omega involution
1273
+ (:meth:`~sage.combinat.sf.sfa.SymmetricFunctionAlgebra_generic_Element.omega`)
1274
+ of said ring.
1275
+
1276
+ The omega involution on `QSym` is adjoint to the omega
1277
+ involution on `NCSF` by the standard adjunction between `NCSF`
1278
+ and `QSym`.
1279
+
1280
+ The omega involution has been denoted by `\omega` in [LMvW13]_,
1281
+ section 3.6.
1282
+
1283
+ .. SEEALSO::
1284
+
1285
+ :meth:`omega involution on NCSF
1286
+ <sage.combinat.ncsf_qsym.ncsf.NonCommutativeSymmetricFunctions.Bases.ElementMethods.omega_involution>`,
1287
+ :meth:`psi involution on QSym
1288
+ <sage.combinat.ncsf_qsym.qsym.QuasiSymmetricFunctions.Bases.ElementMethods.psi_involution>`,
1289
+ :meth:`star involution on QSym
1290
+ <sage.combinat.ncsf_qsym.qsym.QuasiSymmetricFunctions.Bases.ElementMethods.star_involution>`.
1291
+
1292
+ EXAMPLES::
1293
+
1294
+ sage: QSym = QuasiSymmetricFunctions(ZZ)
1295
+ sage: F = QSym.F()
1296
+ sage: F[3,2].omega_involution()
1297
+ F[1, 2, 1, 1]
1298
+ sage: F[6,3].omega_involution()
1299
+ F[1, 1, 2, 1, 1, 1, 1, 1]
1300
+ sage: (F[9,1] - F[8,2] + 2*F[2,4] - 3*F[3] + 4*F[[]]).omega_involution()
1301
+ 4*F[] - 3*F[1, 1, 1] + 2*F[1, 1, 1, 2, 1] - F[1, 2, 1, 1, 1, 1, 1, 1, 1] + F[2, 1, 1, 1, 1, 1, 1, 1, 1]
1302
+ sage: (F[3,3] - 2*F[2]).omega_involution()
1303
+ -2*F[1, 1] + F[1, 1, 2, 1, 1]
1304
+ sage: F([2,1,1]).omega_involution()
1305
+ F[3, 1]
1306
+ sage: M = QSym.M()
1307
+ sage: M([2,1]).omega_involution()
1308
+ -M[1, 2] - M[3]
1309
+ sage: M.zero().omega_involution()
1310
+ 0
1311
+
1312
+ Testing the fact that the restriction of `\omega` to `Sym`
1313
+ is the omega automorphism of `Sym`::
1314
+
1315
+ sage: Sym = SymmetricFunctions(ZZ)
1316
+ sage: e = Sym.e()
1317
+ sage: all( F(e[lam]).omega_involution() == F(e[lam].omega())
1318
+ ....: for lam in Partitions(4) )
1319
+ True
1320
+ """
1321
+ # Use the `\omega(f) = (-1)^n S(f)` formula.
1322
+ return self.antipode().degree_negation()
1323
+
1324
+ def psi_involution(self):
1325
+ r"""
1326
+ Return the image of the quasisymmetric function ``self``
1327
+ under the involution `\psi`.
1328
+
1329
+ The involution `\psi` is defined as the linear map
1330
+ `QSym \to QSym` which, for every composition `I`, sends the
1331
+ fundamental quasisymmetric function `F_I` to `F_{I^c}`, where
1332
+ `I^c` denotes the complement of the composition `I`.
1333
+ The map `\psi` is an involution and a graded Hopf algebra
1334
+ automorphism of `QSym`. Its restriction to the ring of
1335
+ symmetric functions coincides with the omega automorphism of
1336
+ the latter ring.
1337
+
1338
+ The involution `\psi` of `QSym` is adjoint to the involution
1339
+ `\psi` of `NCSF` by the standard adjunction between `NCSF` and
1340
+ `QSym`.
1341
+
1342
+ The involution `\psi` has been denoted by `\psi` in [LMvW13]_,
1343
+ section 3.6.
1344
+
1345
+ .. SEEALSO::
1346
+
1347
+ :meth:`psi involution on NCSF
1348
+ <sage.combinat.ncsf_qsym.ncsf.NonCommutativeSymmetricFunctions.Bases.ElementMethods.psi_involution>`,
1349
+ :meth:`star involution on QSym
1350
+ <sage.combinat.ncsf_qsym.qsym.QuasiSymmetricFunctions.Bases.ElementMethods.star_involution>`.
1351
+
1352
+ EXAMPLES::
1353
+
1354
+ sage: QSym = QuasiSymmetricFunctions(ZZ)
1355
+ sage: F = QSym.F()
1356
+ sage: F[3,2].psi_involution()
1357
+ F[1, 1, 2, 1]
1358
+ sage: F[6,3].psi_involution()
1359
+ F[1, 1, 1, 1, 1, 2, 1, 1]
1360
+ sage: (F[9,1] - F[8,2] + 2*F[2,4] - 3*F[3] + 4*F[[]]).psi_involution()
1361
+ 4*F[] - 3*F[1, 1, 1] + F[1, 1, 1, 1, 1, 1, 1, 1, 2] - F[1, 1, 1, 1, 1, 1, 1, 2, 1] + 2*F[1, 2, 1, 1, 1]
1362
+ sage: (F[3,3] - 2*F[2]).psi_involution()
1363
+ -2*F[1, 1] + F[1, 1, 2, 1, 1]
1364
+ sage: F([2,1,1]).psi_involution()
1365
+ F[1, 3]
1366
+ sage: M = QSym.M()
1367
+ sage: M([2,1]).psi_involution()
1368
+ -M[2, 1] - M[3]
1369
+ sage: M.zero().psi_involution()
1370
+ 0
1371
+
1372
+ The involution `\psi` commutes with the antipode::
1373
+
1374
+ sage: all( F(I).psi_involution().antipode()
1375
+ ....: == F(I).antipode().psi_involution()
1376
+ ....: for I in Compositions(4) )
1377
+ True
1378
+
1379
+ Testing the fact that the restriction of `\psi` to `Sym`
1380
+ is the omega automorphism of `Sym`::
1381
+
1382
+ sage: Sym = SymmetricFunctions(ZZ)
1383
+ sage: e = Sym.e()
1384
+ sage: all( F(e[lam]).psi_involution() == F(e[lam].omega())
1385
+ ....: for lam in Partitions(4) )
1386
+ True
1387
+ """
1388
+ # Convert to the fundamental basis, there apply the psi
1389
+ # involution componentwise, then convert back.
1390
+ parent = self.parent()
1391
+ F = parent.realization_of().F()
1392
+ dct = {I.complement(): coeff for (I, coeff) in F(self)}
1393
+ return parent(F._from_dict(dct))
1394
+
1395
+ def dendriform_less(self, other):
1396
+ r"""
1397
+ Return the result of applying the dendriform smaller
1398
+ operation to the two quasi-symmetric functions ``self``
1399
+ and ``other``.
1400
+
1401
+ The dendriform smaller operation is a binary operation,
1402
+ denoted by `\prec` and written infix, on the ring of
1403
+ quasi-symmetric functions. It can be defined as a
1404
+ restriction of a binary operation (denoted by `\prec`
1405
+ and written infix as well) on the ring of formal power
1406
+ series `R[[x_1, x_2, x_3, \ldots]]`, which is defined
1407
+ as follows: If `m` and `n` are two monomials in
1408
+ `x_1, x_2, x_3, \ldots`, then we let `m \prec n` be
1409
+ the product `mn` if the smallest positive integer `i`
1410
+ for which `x_i` occurs in `m` is smaller than the
1411
+ smallest positive integer `j` for which `x_j` occurs
1412
+ in `n` (this is understood to be false when `m = 1`,
1413
+ and true when `m \neq 1` and `n = 1`), and we let
1414
+ `m \prec n` be `0` otherwise. Having thus defined
1415
+ `\prec` on monomials, we extend `\prec` to a binary
1416
+ operation on `R[[x_1, x_2, x_3, \ldots]]` by requiring
1417
+ it to be continuous (in both inputs) and `R`-bilinear.
1418
+ It is easily seen that `QSym \prec QSym \subseteq
1419
+ QSym`, so that `\prec` restricts to a binary operation
1420
+ on `QSym`.
1421
+
1422
+ .. SEEALSO::
1423
+
1424
+ :meth:`dendriform_leq`
1425
+
1426
+ INPUT:
1427
+
1428
+ - ``other`` -- a quasi-symmetric function over the
1429
+ same base ring as ``self``
1430
+
1431
+ OUTPUT:
1432
+
1433
+ The quasi-symmetric function ``self`` `\prec`
1434
+ ``other``, written in the basis of ``self``.
1435
+
1436
+ EXAMPLES::
1437
+
1438
+ sage: QSym = QuasiSymmetricFunctions(QQ)
1439
+ sage: M = QSym.M()
1440
+ sage: M[2, 1].dendriform_less(M[1, 2])
1441
+ 2*M[2, 1, 1, 2] + M[2, 1, 2, 1] + M[2, 1, 3] + M[2, 2, 2]
1442
+ sage: F = QSym.F()
1443
+ sage: F[2, 1].dendriform_less(F[1, 2])
1444
+ F[1, 1, 2, 1, 1] + F[1, 1, 2, 2] + F[1, 1, 3, 1]
1445
+ + F[1, 2, 1, 2] + F[1, 2, 2, 1] + F[1, 2, 3]
1446
+ + F[2, 1, 1, 2] + F[2, 1, 2, 1] + F[2, 1, 3] + F[2, 2, 2]
1447
+
1448
+ The operation `\prec` can be used to recursively
1449
+ construct the dual immaculate basis: For every positive
1450
+ integer `m` and every composition `I`, the dual
1451
+ immaculate function `\operatorname{dI}_{[m, I]}` of the
1452
+ composition `[m, I]` (this composition is `I` with `m`
1453
+ prepended to it) is `F_{[m]} \prec \operatorname{dI}_I`. ::
1454
+
1455
+ sage: dI = QSym.dI()
1456
+ sage: dI(F[2]).dendriform_less(dI[1, 2])
1457
+ dI[2, 1, 2]
1458
+
1459
+ We check with the identity element::
1460
+
1461
+ sage: M.one().dendriform_less(M[1,2])
1462
+ 0
1463
+ sage: M[1,2].dendriform_less(M.one())
1464
+ M[1, 2]
1465
+
1466
+ The operation `\prec` is not symmetric, nor if
1467
+ `a \prec b \neq 0`, then `b \prec a = 0` (as it would be
1468
+ for a single monomial)::
1469
+
1470
+ sage: M[1,2,1].dendriform_less(M[1,2])
1471
+ M[1, 1, 2, 1, 2] + 2*M[1, 1, 2, 2, 1] + M[1, 1, 2, 3]
1472
+ + M[1, 1, 4, 1] + 2*M[1, 2, 1, 1, 2] + M[1, 2, 1, 2, 1]
1473
+ + M[1, 2, 1, 3] + M[1, 2, 2, 2] + M[1, 3, 1, 2]
1474
+ + M[1, 3, 2, 1] + M[1, 3, 3]
1475
+ sage: M[1,2].dendriform_less(M[1,2,1])
1476
+ M[1, 1, 2, 1, 2] + 2*M[1, 1, 2, 2, 1] + M[1, 1, 2, 3]
1477
+ + M[1, 1, 4, 1] + M[1, 2, 1, 2, 1] + M[1, 3, 2, 1]
1478
+ """
1479
+ # Convert to the monomial basis, there do restricted
1480
+ # shuffle product, then convert back to self.parent().
1481
+ P = self.parent()
1482
+ M = P.realization_of().M()
1483
+ a = M(self)
1484
+ b = M(other)
1485
+ res = M.zero()
1486
+ for I, I_coeff in a:
1487
+ if not I:
1488
+ continue
1489
+ i_head = I[0]
1490
+ I_tail = Composition(I[1:])
1491
+ for J, J_coeff in b:
1492
+ shufpro = I_tail.shuffle_product(J, overlap=True)
1493
+ res += J_coeff * M.sum_of_monomials(Composition([i_head] + list(K))
1494
+ for K in shufpro)
1495
+ return P(res)
1496
+
1497
+ def dendriform_leq(self, other):
1498
+ r"""
1499
+ Return the result of applying the dendriform
1500
+ smaller-or-equal operation to the two quasi-symmetric
1501
+ functions ``self`` and ``other``.
1502
+
1503
+ The dendriform smaller-or-equal operation is a binary
1504
+ operation, denoted by `\preceq` and written infix, on
1505
+ the ring of quasi-symmetric functions. It can be
1506
+ defined as a restriction of a binary operation
1507
+ (denoted by `\preceq` and written infix as well) on
1508
+ the ring of formal power series
1509
+ `R[[x_1, x_2, x_3, \ldots]]`, which is defined as
1510
+ follows: If `m` and `n` are two monomials in
1511
+ `x_1, x_2, x_3, \ldots`, then we let `m \preceq n` be
1512
+ the product `mn` if the smallest positive integer `i`
1513
+ for which `x_i` occurs in `m` is smaller or equal to
1514
+ the smallest positive integer `j` for which `x_j`
1515
+ occurs in `n` (this is understood to be false when
1516
+ `m = 1` and `n \neq 1`, and true when `n = 1`), and we
1517
+ let `m \preceq n` be `0` otherwise. Having thus
1518
+ defined `\preceq` on monomials, we extend `\preceq` to
1519
+ a binary operation on `R[[x_1, x_2, x_3, \ldots]]` by
1520
+ requiring it to be continuous (in both inputs) and
1521
+ `R`-bilinear. It is easily seen that
1522
+ `QSym \preceq QSym \subseteq QSym`, so that `\preceq`
1523
+ restricts to a binary operation on `QSym`.
1524
+
1525
+ This operation `\preceq` is related to the dendriform
1526
+ smaller relation `\prec` (:meth:`dendriform_less`).
1527
+ Namely, if we define a binary operation `\succ` on
1528
+ `QSym` by `a \succ b = b \prec a`, then
1529
+ `(QSym, \preceq, \succ)` is a dendriform `R`-algebra.
1530
+ Thus, any `a, b \in QSym` satisfy
1531
+ `a \preceq b = ab - b \prec a`.
1532
+
1533
+ .. SEEALSO::
1534
+
1535
+ :meth:`dendriform_less`
1536
+
1537
+ INPUT:
1538
+
1539
+ - ``other`` -- a quasi-symmetric function over the
1540
+ same base ring as ``self``
1541
+
1542
+ OUTPUT:
1543
+
1544
+ The quasi-symmetric function ``self`` `\preceq`
1545
+ ``other``, written in the basis of ``self``.
1546
+
1547
+ EXAMPLES::
1548
+
1549
+ sage: QSym = QuasiSymmetricFunctions(QQ)
1550
+ sage: M = QSym.M()
1551
+ sage: M[2, 1].dendriform_leq(M[1, 2])
1552
+ 2*M[2, 1, 1, 2] + M[2, 1, 2, 1] + M[2, 1, 3] + M[2, 2, 2]
1553
+ + M[3, 1, 2] + M[3, 2, 1] + M[3, 3]
1554
+ sage: F = QSym.F()
1555
+ sage: F[2, 1].dendriform_leq(F[1, 2])
1556
+ F[2, 1, 1, 2] + F[2, 1, 2, 1] + F[2, 1, 3] + F[2, 2, 1, 1]
1557
+ + 2*F[2, 2, 2] + F[2, 3, 1] + F[3, 1, 2] + F[3, 2, 1] + F[3, 3]
1558
+ """
1559
+ # This might be somewhat slow...
1560
+ P = self.parent()
1561
+ return self * P(other) - P(other.dendriform_less(self))
1562
+
1563
+ def expand(self, n, alphabet='x'):
1564
+ r"""
1565
+ Expand the quasi-symmetric function into ``n`` variables in
1566
+ an alphabet, which by default is ``'x'``.
1567
+
1568
+ INPUT:
1569
+
1570
+ - ``n`` -- nonnegative integer; the number of variables
1571
+ in the expansion
1572
+ - ``alphabet`` -- (default: ``'x'``) the alphabet in
1573
+ which ``self`` is to be expanded
1574
+
1575
+ OUTPUT: an expansion of ``self`` into the ``n`` variables
1576
+ specified by ``alphabet``
1577
+
1578
+ EXAMPLES::
1579
+
1580
+ sage: F = QuasiSymmetricFunctions(QQ).Fundamental()
1581
+ sage: F[3].expand(3)
1582
+ x0^3 + x0^2*x1 + x0*x1^2 + x1^3 + x0^2*x2 + x0*x1*x2 + x1^2*x2 + x0*x2^2 + x1*x2^2 + x2^3
1583
+ sage: F[2,1].expand(3)
1584
+ x0^2*x1 + x0^2*x2 + x0*x1*x2 + x1^2*x2
1585
+
1586
+ One can use a different set of variable by adding an optional
1587
+ argument ``alphabet=...`` ::
1588
+
1589
+ sage: F = QuasiSymmetricFunctions(QQ).Fundamental()
1590
+ sage: F[3].expand(2,alphabet='y')
1591
+ y0^3 + y0^2*y1 + y0*y1^2 + y1^3
1592
+
1593
+ TESTS::
1594
+
1595
+ sage: (3*F([])).expand(2)
1596
+ 3
1597
+ sage: F[4,2].expand(0)
1598
+ 0
1599
+ sage: F([]).expand(0)
1600
+ 1
1601
+ """
1602
+ M = self.parent().realization_of().Monomial()
1603
+ return M(self).expand(n,alphabet)
1604
+
1605
+ def is_symmetric(self):
1606
+ r"""
1607
+ Return ``True`` if ``self`` is an element of the symmetric
1608
+ functions.
1609
+
1610
+ This is being tested by looking at the expansion in
1611
+ the Monomial basis and checking if the coefficients are
1612
+ the same if the indexing compositions are permutations
1613
+ of each other.
1614
+
1615
+ OUTPUT:
1616
+
1617
+ - ``True`` if ``self`` is symmetric.
1618
+ ``False`` if ``self`` is not symmetric.
1619
+
1620
+ EXAMPLES::
1621
+
1622
+ sage: QSym = QuasiSymmetricFunctions(QQ)
1623
+ sage: F = QSym.Fundamental()
1624
+ sage: (F[3,2] + F[2,3]).is_symmetric()
1625
+ False
1626
+ sage: (F[1, 1, 1, 2] + F[1, 1, 3] + F[1, 3, 1] + F[2, 1, 1, 1] + F[3, 1, 1]).is_symmetric()
1627
+ True
1628
+ sage: F([]).is_symmetric()
1629
+ True
1630
+ """
1631
+ M = self.parent().realization_of().Monomial()
1632
+ return M(self).is_symmetric()
1633
+
1634
+ def to_symmetric_function(self):
1635
+ r"""
1636
+ Convert a quasi-symmetric function to a symmetric function.
1637
+
1638
+ OUTPUT:
1639
+
1640
+ - If ``self`` is a symmetric function, then return the expansion
1641
+ in the monomial basis. Otherwise raise an error.
1642
+
1643
+ EXAMPLES::
1644
+
1645
+ sage: QSym = QuasiSymmetricFunctions(QQ)
1646
+ sage: F = QSym.Fundamental()
1647
+ sage: (F[3,2] + F[2,3]).to_symmetric_function()
1648
+ Traceback (most recent call last):
1649
+ ...
1650
+ ValueError: F[2, 3] + F[3, 2] is not a symmetric function
1651
+ sage: m = SymmetricFunctions(QQ).m()
1652
+ sage: s = SymmetricFunctions(QQ).s()
1653
+ sage: F(s[3,1,1]).to_symmetric_function()
1654
+ 6*m[1, 1, 1, 1, 1] + 3*m[2, 1, 1, 1] + m[2, 2, 1] + m[3, 1, 1]
1655
+ sage: m(s[3,1,1])
1656
+ 6*m[1, 1, 1, 1, 1] + 3*m[2, 1, 1, 1] + m[2, 2, 1] + m[3, 1, 1]
1657
+ """
1658
+ if self.is_symmetric():
1659
+ M = self.parent().realization_of().Monomial()
1660
+ return M( self ).to_symmetric_function()
1661
+ else:
1662
+ raise ValueError("%s is not a symmetric function" % self)
1663
+
1664
+ class Monomial(CombinatorialFreeModule, BindableClass):
1665
+ r"""
1666
+ The Hopf algebra of quasi-symmetric function in the Monomial basis.
1667
+
1668
+ EXAMPLES::
1669
+
1670
+ sage: QSym = QuasiSymmetricFunctions(QQ)
1671
+ sage: M = QSym.M()
1672
+ sage: F = QSym.F()
1673
+ sage: M(F[2,2])
1674
+ M[1, 1, 1, 1] + M[1, 1, 2] + M[2, 1, 1] + M[2, 2]
1675
+ sage: m = SymmetricFunctions(QQ).m()
1676
+ sage: M(m[3,1,1])
1677
+ M[1, 1, 3] + M[1, 3, 1] + M[3, 1, 1]
1678
+ sage: (1+M[1])^3
1679
+ M[] + 3*M[1] + 6*M[1, 1] + 6*M[1, 1, 1] + 3*M[1, 2] + 3*M[2] + 3*M[2, 1] + M[3]
1680
+ sage: M[1,2,1].coproduct()
1681
+ M[] # M[1, 2, 1] + M[1] # M[2, 1] + M[1, 2] # M[1] + M[1, 2, 1] # M[]
1682
+
1683
+ The following is an alias for this basis::
1684
+
1685
+ sage: QSym.Monomial()
1686
+ Quasisymmetric functions over the Rational Field in the Monomial basis
1687
+
1688
+ TESTS::
1689
+
1690
+ sage: M(F([]))
1691
+ M[]
1692
+ sage: M(F(0))
1693
+ 0
1694
+ sage: M(m([]))
1695
+ M[]
1696
+ """
1697
+
1698
+ def __init__(self, QSym):
1699
+ """
1700
+ EXAMPLES::
1701
+
1702
+ sage: M = QuasiSymmetricFunctions(QQ).Monomial(); M
1703
+ Quasisymmetric functions over the Rational Field in the Monomial basis
1704
+ sage: TestSuite(M).run()
1705
+ """
1706
+ CombinatorialFreeModule.__init__(self, QSym.base_ring(), Compositions(),
1707
+ prefix='M', bracket=False,
1708
+ category=QSym.Bases())
1709
+
1710
+ def dual(self):
1711
+ r"""
1712
+ Return the dual basis to the Monomial basis. This is the complete basis of the
1713
+ non-commutative symmetric functions.
1714
+
1715
+ OUTPUT: the complete basis of the non-commutative symmetric functions
1716
+
1717
+ EXAMPLES::
1718
+
1719
+ sage: M = QuasiSymmetricFunctions(QQ).M()
1720
+ sage: M.dual()
1721
+ Non-Commutative Symmetric Functions over the Rational Field in the Complete basis
1722
+ """
1723
+ return self.realization_of().dual().Complete()
1724
+
1725
+ def product_on_basis(self, I, J):
1726
+ """
1727
+ The product on Monomial basis elements.
1728
+
1729
+ The product of the basis elements indexed by two compositions
1730
+ `I` and `J` is the sum of the basis elements indexed by
1731
+ compositions in the stuffle product (also called the
1732
+ overlapping shuffle product) of `I` and `J`.
1733
+
1734
+ INPUT:
1735
+
1736
+ - ``I``, ``J`` -- compositions
1737
+
1738
+ OUTPUT:
1739
+
1740
+ - The product of the Monomial quasi-symmetric functions indexed by ``I`` and
1741
+ ``J``, expressed in the Monomial basis.
1742
+
1743
+ EXAMPLES::
1744
+
1745
+ sage: M = QuasiSymmetricFunctions(QQ).Monomial()
1746
+ sage: c1 = Composition([2])
1747
+ sage: c2 = Composition([1,3])
1748
+ sage: M.product_on_basis(c1, c2)
1749
+ M[1, 2, 3] + M[1, 3, 2] + M[1, 5] + M[2, 1, 3] + M[3, 3]
1750
+ sage: M.product_on_basis(c1, Composition([]))
1751
+ M[2]
1752
+ """
1753
+ return self.sum_of_monomials(I.shuffle_product(J, overlap=True))
1754
+
1755
+ def antipode_on_basis(self, compo):
1756
+ r"""
1757
+ Return the result of the antipode applied to a quasi-symmetric Monomial basis
1758
+ element.
1759
+
1760
+ INPUT:
1761
+
1762
+ - ``compo`` -- composition
1763
+
1764
+ OUTPUT:
1765
+
1766
+ - The result of the antipode applied to the composition ``compo``, expressed
1767
+ in the Monomial basis.
1768
+
1769
+ EXAMPLES::
1770
+
1771
+ sage: M = QuasiSymmetricFunctions(QQ).M()
1772
+ sage: M.antipode_on_basis(Composition([2,1]))
1773
+ M[1, 2] + M[3]
1774
+ sage: M.antipode_on_basis(Composition([]))
1775
+ M[]
1776
+ """
1777
+ return (-1)**(len(compo)) * self.sum_of_fatter_compositions(compo.reversed())
1778
+
1779
+ def coproduct_on_basis(self, compo):
1780
+ r"""
1781
+ Return the coproduct of a Monomial basis element.
1782
+
1783
+ Combinatorial rule: deconcatenation.
1784
+
1785
+ INPUT:
1786
+
1787
+ - ``compo`` -- composition
1788
+
1789
+ OUTPUT:
1790
+
1791
+ - The coproduct applied to the Monomial quasi-symmetric function indexed by
1792
+ ``compo``, expressed in the Monomial basis.
1793
+
1794
+ EXAMPLES::
1795
+
1796
+ sage: M = QuasiSymmetricFunctions(QQ).Monomial()
1797
+ sage: M[4,2,3].coproduct()
1798
+ M[] # M[4, 2, 3] + M[4] # M[2, 3] + M[4, 2] # M[3] + M[4, 2, 3] # M[]
1799
+ sage: M.coproduct_on_basis(Composition([]))
1800
+ M[] # M[]
1801
+ """
1802
+ return self.tensor_square().sum_of_monomials((self._indices(compo[:i]),
1803
+ self._indices(compo[i:]))
1804
+ for i in range(len(compo)+1))
1805
+
1806
+ def lambda_of_monomial(self, I, n):
1807
+ r"""
1808
+ Return the image of the monomial quasi-symmetric function
1809
+ `M_I` under the lambda-map `\lambda^n`, expanded in the
1810
+ monomial basis.
1811
+
1812
+ The ring of quasi-symmetric functions over the integers,
1813
+ `\mathrm{QSym}_{\ZZ}` (and more generally, the ring of
1814
+ quasi-symmetric functions over any binomial ring) becomes
1815
+ a `\lambda`-ring (with the `\lambda`-structure inherited
1816
+ from the ring of formal power series, so that
1817
+ `\lambda^i(x_j)` is `x_j` if `i = 1` and `0` if `i > 1`).
1818
+
1819
+ The Adams operations of this `\lambda`-ring are the
1820
+ Adams endomorphisms `\mathbf{f}_n` (see
1821
+ :meth:`~sage.combinat.ncsf_qsym.qsym.QuasiSymmetricFunctions.Bases.ElementMethods.adams_operator`
1822
+ for their definition). Using these endomorphisms, the
1823
+ `\lambda`-operations can be explicitly computed via the formula
1824
+
1825
+ .. MATH::
1826
+
1827
+ \exp \left(- \sum_{n=1}^{\infty}
1828
+ \frac{1}{n} \mathbf{f}_n(x) t^n \right)
1829
+ = \sum_{j=0}^{\infty} (-1)^j \lambda^j(x) t^j
1830
+
1831
+ in the ring of formal power series in a variable `t` over
1832
+ the ring of quasi-symmetric functions. In particular,
1833
+ every composition `I = (I_1, I_2, \cdots, I_\ell )` satisfies
1834
+
1835
+ .. MATH::
1836
+
1837
+ \exp \left(- \sum_{n=1}^{\infty}
1838
+ \frac{1}{n} M_{(nI_1, nI_2, \cdots, nI_\ell )} t^n \right)
1839
+ = \sum_{j=0}^{\infty} (-1)^j \lambda^j(M_I) t^j
1840
+
1841
+ (corrected version of Remark 2.4 in [Haz2004]_).
1842
+
1843
+ The quasi-symmetric functions `\lambda^i(M_I)` with `n`
1844
+ ranging over the positive integers and `I` ranging over
1845
+ the reduced Lyndon compositions (i. e., compositions
1846
+ which are Lyndon words and have the gcd of their entries
1847
+ equal to `1`) form a set of free polynomial generators
1848
+ for `\mathrm{QSym}`. See [GriRei18]_, Chapter 6, for
1849
+ the proof, and [Haz2004]_ for a major part of it.
1850
+
1851
+ INPUT:
1852
+
1853
+ - ``I`` -- composition
1854
+ - ``n`` -- nonnegative integer
1855
+
1856
+ OUTPUT:
1857
+
1858
+ The quasi-symmetric function `\lambda^n(M_I)`, expanded in
1859
+ the monomial basis over the ground ring of ``self``.
1860
+
1861
+ EXAMPLES::
1862
+
1863
+ sage: # needs sage.rings.number_field
1864
+ sage: M = QuasiSymmetricFunctions(CyclotomicField()).Monomial()
1865
+ sage: M.lambda_of_monomial([1, 2], 2)
1866
+ 2*M[1, 1, 2, 2] + M[1, 1, 4] + M[1, 2, 1, 2] + M[1, 3, 2] + M[2, 2, 2]
1867
+ sage: M.lambda_of_monomial([1, 1], 2)
1868
+ 3*M[1, 1, 1, 1] + M[1, 1, 2] + M[1, 2, 1] + M[2, 1, 1]
1869
+ sage: M = QuasiSymmetricFunctions(Integers(19)).Monomial()
1870
+ sage: M.lambda_of_monomial([1, 2], 3)
1871
+ 6*M[1, 1, 1, 2, 2, 2] + 3*M[1, 1, 1, 2, 4] + 3*M[1, 1, 1, 4, 2]
1872
+ + M[1, 1, 1, 6] + 4*M[1, 1, 2, 1, 2, 2] + 2*M[1, 1, 2, 1, 4]
1873
+ + 2*M[1, 1, 2, 2, 1, 2] + 2*M[1, 1, 2, 3, 2] + 4*M[1, 1, 3, 2, 2]
1874
+ + 2*M[1, 1, 3, 4] + M[1, 1, 4, 1, 2] + M[1, 1, 5, 2]
1875
+ + 2*M[1, 2, 1, 1, 2, 2] + M[1, 2, 1, 1, 4] + M[1, 2, 1, 2, 1, 2]
1876
+ + M[1, 2, 1, 3, 2] + 4*M[1, 2, 2, 2, 2] + M[1, 2, 2, 4] + M[1, 2, 4, 2]
1877
+ + 2*M[1, 3, 1, 2, 2] + M[1, 3, 1, 4] + M[1, 3, 2, 1, 2] + M[1, 3, 3, 2]
1878
+ + M[1, 4, 2, 2] + 3*M[2, 1, 2, 2, 2] + M[2, 1, 2, 4] + M[2, 1, 4, 2]
1879
+ + 2*M[2, 2, 1, 2, 2] + M[2, 2, 1, 4] + M[2, 2, 2, 1, 2] + M[2, 2, 3, 2]
1880
+ + 2*M[2, 3, 2, 2] + M[2, 3, 4] + M[3, 2, 2, 2]
1881
+
1882
+ The map `\lambda^0` sends everything to `1`::
1883
+
1884
+ sage: M = QuasiSymmetricFunctions(ZZ).Monomial()
1885
+ sage: all( M.lambda_of_monomial(I, 0) == M.one()
1886
+ ....: for I in Compositions(3) )
1887
+ True
1888
+
1889
+ The map `\lambda^1` is the identity map::
1890
+
1891
+ sage: M = QuasiSymmetricFunctions(QQ).Monomial()
1892
+ sage: all( M.lambda_of_monomial(I, 1) == M(I)
1893
+ ....: for I in Compositions(3) )
1894
+ True
1895
+ sage: M = QuasiSymmetricFunctions(Integers(5)).Monomial()
1896
+ sage: all( M.lambda_of_monomial(I, 1) == M(I)
1897
+ ....: for I in Compositions(3) )
1898
+ True
1899
+ sage: M = QuasiSymmetricFunctions(ZZ).Monomial()
1900
+ sage: all( M.lambda_of_monomial(I, 1) == M(I)
1901
+ ....: for I in Compositions(3) )
1902
+ True
1903
+ """
1904
+ # The following algorithm is a rewriting of the formula in the docstring.
1905
+ # We are working over QQ because there are denominators which don't
1906
+ # immediately cancel.
1907
+ from sage.rings.integer_ring import ZZ
1908
+ from sage.rings.rational_field import QQ
1909
+ QQM = QuasiSymmetricFunctions(QQ).M()
1910
+ QQ_result = QQM.zero()
1911
+ for lam in Partitions(n):
1912
+ coeff = QQ((-1) ** len(lam)) / lam.centralizer_size()
1913
+ QQ_result += coeff * QQM.prod([QQM(self._indices([k * i for i in I]))
1914
+ for k in lam])
1915
+ QQ_result *= (-1) ** n
1916
+ # QQ_result is now \lambda^n(M_I) over QQ.
1917
+ result = self.sum_of_terms([(J, ZZ(coeff)) for (J, coeff) in QQ_result],
1918
+ distinct=True)
1919
+ return result
1920
+
1921
+ class Element(CombinatorialFreeModule.Element):
1922
+ r"""
1923
+ Element methods of the ``Monomial`` basis of ``QuasiSymmetricFunctions``.
1924
+ """
1925
+
1926
+ def psi_involution(self):
1927
+ r"""
1928
+ Return the image of the quasisymmetric function ``self``
1929
+ under the involution `\psi`.
1930
+
1931
+ The involution `\psi` is defined as the linear map
1932
+ `QSym \to QSym` which, for every composition `I`, sends the
1933
+ fundamental quasisymmetric function `F_I` to `F_{I^c}`, where
1934
+ `I^c` denotes the complement of the composition `I`.
1935
+ The map `\psi` is an involution and a graded Hopf algebra
1936
+ automorphism of `QSym`. Its restriction to the ring of
1937
+ symmetric functions coincides with the omega automorphism of
1938
+ the latter ring.
1939
+
1940
+ The involution `\psi` of `QSym` is adjoint to the involution
1941
+ `\psi` of `NCSF` by the standard adjunction between `NCSF` and
1942
+ `QSym`.
1943
+
1944
+ The involution `\psi` has been denoted by `\psi` in [LMvW13]_,
1945
+ section 3.6.
1946
+
1947
+ .. SEEALSO::
1948
+
1949
+ :meth:`psi involution on QSym
1950
+ <sage.combinat.ncsf_qsym.qsym.QuasiSymmetricFunctions.Bases.ElementMethods.psi_involution>`,
1951
+ :meth:`psi involution on NCSF
1952
+ <sage.combinat.ncsf_qsym.ncsf.NonCommutativeSymmetricFunctions.Bases.ElementMethods.psi_involution>`,
1953
+ :meth:`star involution on QSym
1954
+ <sage.combinat.ncsf_qsym.qsym.QuasiSymmetricFunctions.Bases.ElementMethods.star_involution>`.
1955
+
1956
+ EXAMPLES::
1957
+
1958
+ sage: QSym = QuasiSymmetricFunctions(ZZ)
1959
+ sage: M = QSym.M()
1960
+ sage: M[3,2].psi_involution()
1961
+ -M[3, 2] - M[5]
1962
+ sage: M[3,1].psi_involution()
1963
+ M[3, 1] + M[4]
1964
+ sage: M[3,1,1].psi_involution()
1965
+ M[3, 1, 1] + M[3, 2] + M[4, 1] + M[5]
1966
+ sage: M[1,1,1].psi_involution()
1967
+ M[1, 1, 1] + M[1, 2] + M[2, 1] + M[3]
1968
+ sage: M[[]].psi_involution()
1969
+ M[]
1970
+ sage: M(0).psi_involution()
1971
+ 0
1972
+ sage: (2*M[[]] - M[3,1] + 4*M[2]).psi_involution()
1973
+ 2*M[] - 4*M[2] - M[3, 1] - M[4]
1974
+
1975
+ This particular implementation is tailored to the monomial
1976
+ basis. It is semantically equivalent to the generic
1977
+ implementation it overshadows::
1978
+
1979
+ sage: F = QSym.F()
1980
+ sage: all( F(M[I].psi_involution()) == F(M[I]).psi_involution()
1981
+ ....: for I in Compositions(3) )
1982
+ True
1983
+
1984
+ sage: F = QSym.F()
1985
+ sage: all( F(M[I].psi_involution()) == F(M[I]).psi_involution()
1986
+ ....: for I in Compositions(4) )
1987
+ True
1988
+ """
1989
+ parent = self.parent()
1990
+ return parent.sum( (-1) ** (I.size() - len(I)) * coeff
1991
+ * parent.sum_of_fatter_compositions(I)
1992
+ for I, coeff in
1993
+ self._monomial_coefficients.items() )
1994
+
1995
+ def expand(self, n, alphabet='x'):
1996
+ r"""
1997
+ Expand the quasi-symmetric function written in the monomial basis in
1998
+ `n` variables.
1999
+
2000
+ INPUT:
2001
+
2002
+ - ``n`` -- integer
2003
+ - ``alphabet`` -- string (default: ``'x'``)
2004
+
2005
+ OUTPUT: the quasi-symmetric function ``self`` expressed in the
2006
+ `n` variables described by ``alphabet``
2007
+
2008
+ .. TODO:: accept an *alphabet* as input
2009
+
2010
+ EXAMPLES::
2011
+
2012
+ sage: M = QuasiSymmetricFunctions(QQ).Monomial()
2013
+ sage: M[4,2].expand(3)
2014
+ x0^4*x1^2 + x0^4*x2^2 + x1^4*x2^2
2015
+
2016
+ One can use a different set of variables by using the
2017
+ optional argument ``alphabet``::
2018
+
2019
+ sage: M = QuasiSymmetricFunctions(QQ).Monomial()
2020
+ sage: M[2,1,1].expand(4,alphabet='y')
2021
+ y0^2*y1*y2 + y0^2*y1*y3 + y0^2*y2*y3 + y1^2*y2*y3
2022
+
2023
+ TESTS::
2024
+
2025
+ sage: (3*M([])).expand(2)
2026
+ 3
2027
+ sage: M[4,2].expand(0)
2028
+ 0
2029
+ sage: M([]).expand(0)
2030
+ 1
2031
+ """
2032
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
2033
+ M = self.parent()
2034
+ P = PolynomialRing(M.base_ring(), n, alphabet)
2035
+ x = P.gens()
2036
+
2037
+ def on_basis(comp, i):
2038
+ if not comp:
2039
+ return P.one()
2040
+ elif len(comp) > i:
2041
+ return P.zero()
2042
+ else:
2043
+ return x[i-1]**comp[-1] * on_basis(comp[:-1], i-1) + \
2044
+ on_basis(comp, i-1)
2045
+ return M._apply_module_morphism(self, lambda comp: on_basis(comp,n),
2046
+ codomain=P)
2047
+
2048
+ def is_symmetric( self ):
2049
+ r"""
2050
+ Determine if a quasi-symmetric function, written in the Monomial basis,
2051
+ is symmetric.
2052
+
2053
+ This is being tested by looking at the expansion in the Monomial
2054
+ basis and checking if the coefficients are the same if the indexing
2055
+ compositions are permutations of each other.
2056
+
2057
+ OUTPUT:
2058
+
2059
+ - ``True`` if ``self`` is an element of the symmetric
2060
+ functions and ``False`` otherwise.
2061
+
2062
+ EXAMPLES::
2063
+
2064
+ sage: QSym = QuasiSymmetricFunctions(QQ)
2065
+ sage: M = QSym.Monomial()
2066
+ sage: (M[3,2] + M[2,3] + M[4,1]).is_symmetric()
2067
+ False
2068
+ sage: (M[3,2] + M[2,3]).is_symmetric()
2069
+ True
2070
+ sage: (M[1,2,1] + M[1,1,2]).is_symmetric()
2071
+ False
2072
+ sage: (M[1,2,1] + M[1,1,2] + M[2,1,1]).is_symmetric()
2073
+ True
2074
+ """
2075
+ # We must check that every rearrangement of a composition
2076
+ # that appears in self appears with the same coefficient.
2077
+ # We use a dictionary to keep track of the coefficient
2078
+ # and how many rearrangements of the composition we've seen.
2079
+ from sage.combinat.permutation import Permutations_mset
2080
+ d = {}
2081
+ for (I, coeff) in self:
2082
+ partition = I.to_partition()
2083
+ if partition not in d:
2084
+ d[partition] = [coeff, 1]
2085
+ else:
2086
+ if d[partition][0] != coeff:
2087
+ return False
2088
+ else:
2089
+ d[partition][1] += 1
2090
+ # make sure we've seen each rearrangement of the composition
2091
+ return all(d[partition][1] == Permutations_mset(partition).cardinality()
2092
+ for partition in d)
2093
+
2094
+ def to_symmetric_function(self):
2095
+ r"""
2096
+ Take a quasi-symmetric function, expressed in the monomial basis, and
2097
+ return its symmetric realization, when possible, expressed in the
2098
+ monomial basis of symmetric functions.
2099
+
2100
+ OUTPUT:
2101
+
2102
+ - If ``self`` is a symmetric function, then the expansion
2103
+ in the monomial basis of the symmetric functions is returned.
2104
+ Otherwise an error is raised.
2105
+
2106
+ EXAMPLES::
2107
+
2108
+ sage: QSym = QuasiSymmetricFunctions(QQ)
2109
+ sage: M = QSym.Monomial()
2110
+ sage: (M[3,2] + M[2,3] + M[4,1]).to_symmetric_function()
2111
+ Traceback (most recent call last):
2112
+ ...
2113
+ ValueError: M[2, 3] + M[3, 2] + M[4, 1] is not a symmetric function
2114
+ sage: (M[3,2] + M[2,3] + 2*M[4,1] + 2*M[1,4]).to_symmetric_function()
2115
+ m[3, 2] + 2*m[4, 1]
2116
+ sage: m = SymmetricFunctions(QQ).m()
2117
+ sage: M(m[3,1,1]).to_symmetric_function()
2118
+ m[3, 1, 1]
2119
+ sage: (M(m[2,1])*M(m[2,1])).to_symmetric_function()-m[2,1]*m[2,1]
2120
+ 0
2121
+
2122
+ TESTS::
2123
+
2124
+ sage: (M(0)).to_symmetric_function()
2125
+ 0
2126
+ sage: (M([])).to_symmetric_function()
2127
+ m[]
2128
+ sage: (2*M([])).to_symmetric_function()
2129
+ 2*m[]
2130
+
2131
+ We check that the result is indexed by partitions::
2132
+
2133
+ sage: M([]).to_symmetric_function().leading_support().parent()
2134
+ Partitions
2135
+ """
2136
+ m = SymmetricFunctions(self.parent().base_ring()).monomial()
2137
+ if self.is_symmetric():
2138
+ return m._from_dict({_Partitions(list(I)): coeff
2139
+ for I, coeff in self
2140
+ if list(I) in _Partitions}, remove_zeros=False)
2141
+ else:
2142
+ raise ValueError("%s is not a symmetric function" % self)
2143
+
2144
+ M = Monomial
2145
+
2146
+ class Fundamental(CombinatorialFreeModule, BindableClass):
2147
+ r"""
2148
+ The Hopf algebra of quasi-symmetric functions in the Fundamental basis.
2149
+
2150
+ EXAMPLES::
2151
+
2152
+ sage: QSym = QuasiSymmetricFunctions(QQ)
2153
+ sage: F = QSym.F()
2154
+ sage: M = QSym.M()
2155
+ sage: F(M[2,2])
2156
+ F[1, 1, 1, 1] - F[1, 1, 2] - F[2, 1, 1] + F[2, 2]
2157
+ sage: s = SymmetricFunctions(QQ).s()
2158
+ sage: F(s[3,2])
2159
+ F[1, 2, 2] + F[1, 3, 1] + F[2, 2, 1] + F[2, 3] + F[3, 2]
2160
+ sage: (1+F[1])^3
2161
+ F[] + 3*F[1] + 3*F[1, 1] + F[1, 1, 1] + 2*F[1, 2] + 3*F[2] + 2*F[2, 1] + F[3]
2162
+ sage: F[1,2,1].coproduct()
2163
+ F[] # F[1, 2, 1] + F[1] # F[2, 1] + F[1, 1] # F[1, 1] + F[1, 2] # F[1] + F[1, 2, 1] # F[]
2164
+
2165
+ The following is an alias for this basis::
2166
+
2167
+ sage: QSym.Fundamental()
2168
+ Quasisymmetric functions over the Rational Field in the Fundamental basis
2169
+
2170
+ TESTS::
2171
+
2172
+ sage: F(M([]))
2173
+ F[]
2174
+ sage: F(M(0))
2175
+ 0
2176
+ sage: F(s([]))
2177
+ F[]
2178
+ sage: F(s(0))
2179
+ 0
2180
+ """
2181
+
2182
+ def __init__(self, QSym):
2183
+ """
2184
+ EXAMPLES::
2185
+
2186
+ sage: F = QuasiSymmetricFunctions(QQ).Fundamental(); F
2187
+ Quasisymmetric functions over the Rational Field in the Fundamental basis
2188
+ sage: TestSuite(F).run()
2189
+ """
2190
+ CombinatorialFreeModule.__init__(self, QSym.base_ring(), Compositions(),
2191
+ prefix='F', bracket=False,
2192
+ category=QSym.Bases())
2193
+
2194
+ def _from_schur_on_basis(self, la):
2195
+ r"""
2196
+ Map the Schur symmetric function indexed by ``la`` to the
2197
+ Fundamental basis.
2198
+
2199
+ EXAMPLES::
2200
+
2201
+ sage: s = SymmetricFunctions(QQ).schur()
2202
+ sage: F = QuasiSymmetricFunctions(QQ).Fundamental()
2203
+ sage: F(s[2,2]-s[3,1]) # indirect doctest
2204
+ F[1, 2, 1] - F[1, 3] - F[3, 1]
2205
+
2206
+ sage: F._from_schur_on_basis(Partition([]))
2207
+ F[]
2208
+
2209
+ sage: F._from_schur_on_basis(Partition([2,2,2]))
2210
+ F[1, 1, 2, 1, 1] + F[1, 2, 1, 2] + F[1, 2, 2, 1] + F[2, 1, 2, 1] + F[2, 2, 2]
2211
+ """
2212
+ C = self._indices
2213
+ res = 0
2214
+ n = la.size()
2215
+ for T in StandardTableaux(la):
2216
+ des = T.standard_descents()
2217
+ comp = C.from_descents([d-1 for d in des], n)
2218
+ res += self.monomial(comp)
2219
+ return res
2220
+
2221
+ def dual(self):
2222
+ r"""
2223
+ Return the dual basis to the Fundamental basis. This is the ribbon
2224
+ basis of the non-commutative symmetric functions.
2225
+
2226
+ OUTPUT: the ribbon basis of the non-commutative symmetric functions
2227
+
2228
+ EXAMPLES::
2229
+
2230
+ sage: F = QuasiSymmetricFunctions(QQ).F()
2231
+ sage: F.dual()
2232
+ Non-Commutative Symmetric Functions over the Rational Field in the Ribbon basis
2233
+ """
2234
+ return self.realization_of().dual().Ribbon()
2235
+
2236
+ def antipode_on_basis(self, compo):
2237
+ r"""
2238
+ Return the antipode to a Fundamental quasi-symmetric basis element.
2239
+
2240
+ INPUT:
2241
+
2242
+ - ``compo`` -- composition
2243
+
2244
+ OUTPUT:
2245
+
2246
+ - The result of the antipode applied to the quasi-symmetric
2247
+ Fundamental basis element indexed by ``compo``.
2248
+
2249
+ EXAMPLES::
2250
+
2251
+ sage: F = QuasiSymmetricFunctions(QQ).F()
2252
+ sage: F.antipode_on_basis(Composition([2,1]))
2253
+ -F[2, 1]
2254
+ """
2255
+ return (-1)**(compo.size()) * self.monomial(compo.conjugate())
2256
+
2257
+ def coproduct_on_basis(self, compo):
2258
+ r"""
2259
+ Return the coproduct to a Fundamental quasi-symmetric basis element.
2260
+
2261
+ Combinatorial rule: quasi-deconcatenation.
2262
+
2263
+ INPUT:
2264
+
2265
+ - ``compo`` -- composition
2266
+
2267
+ OUTPUT:
2268
+
2269
+ - The application of the coproduct to the Fundamental quasi-symmetric
2270
+ function indexed by the composition ``compo``.
2271
+
2272
+ EXAMPLES::
2273
+
2274
+ sage: F = QuasiSymmetricFunctions(QQ).Fundamental()
2275
+ sage: F[4].coproduct()
2276
+ F[] # F[4] + F[1] # F[3] + F[2] # F[2] + F[3] # F[1] + F[4] # F[]
2277
+ sage: F[2,1,3].coproduct()
2278
+ F[] # F[2, 1, 3] + F[1] # F[1, 1, 3] + F[2] # F[1, 3] + F[2, 1] # F[3] + F[2, 1, 1] # F[2] + F[2, 1, 2] # F[1] + F[2, 1, 3] # F[]
2279
+
2280
+ TESTS::
2281
+
2282
+ sage: F.coproduct_on_basis(Composition([2,1,3]))
2283
+ F[] # F[2, 1, 3] + F[1] # F[1, 1, 3] + F[2] # F[1, 3] + F[2, 1] # F[3] + F[2, 1, 1] # F[2] + F[2, 1, 2] # F[1] + F[2, 1, 3] # F[]
2284
+ sage: F.one().coproduct() # generic for graded / graded connected
2285
+ F[] # F[]
2286
+ """
2287
+ T = self.tensor_square()
2288
+ C = Composition
2289
+ return T.sum_of_monomials( ( C(compo[:i]), C(compo[i:]) ) for i in range(len(compo)+1) ) + \
2290
+ T.sum_of_monomials( ( C(compo[:i]+[j]), C([compo[i]-j]+compo[i+1:]) )
2291
+ for i in range(len(compo))
2292
+ for j in range(1, compo[i]) )
2293
+
2294
+ @cached_method
2295
+ def Eulerian(self, n, j, k=None):
2296
+ r"""
2297
+ Return the Eulerian (quasi)symmetric function `Q_{n,j}` (with
2298
+ `n` either an integer or a partition) defined in [SW2010]_ in
2299
+ terms of the fundamental quasisymmetric functions.
2300
+ Or, if the optional argument ``k`` is specified, return the
2301
+ function `Q_{n,j,k}` defined ibidem.
2302
+
2303
+ If `n` and `j` are nonnegative integers, then the Eulerian
2304
+ quasisymmetric function `Q_{n,j}` is defined as
2305
+
2306
+ .. MATH::
2307
+
2308
+ Q_{n,j} := \sum_{\sigma} F_{\mathrm{Dex}(\sigma)},
2309
+
2310
+ where we sum over all permutations `\sigma \in S_n` such that
2311
+ the number of excedances of `\sigma` is `j`, and where
2312
+ `\mathrm{Dex}(\sigma)` is a composition of `n` defined as follows:
2313
+ Let `S` be the set of all `i \in \{ 1, 2, \ldots, n-1 \}` such
2314
+ that either `\sigma_i > \sigma_{i+1} > i+1` or
2315
+ `i \geq \sigma_i > \sigma_{i+1}` or
2316
+ `\sigma_{i+1} > i + 1 > \sigma_i`. Then,
2317
+ `\mathrm{Dex}(\sigma)` is set to be the composition of `n` whose
2318
+ descent set is `S`.
2319
+
2320
+ Here, an excedance of a permutation `\sigma \in S_n` means an
2321
+ element `i \in \{ 1, 2, \ldots, n-1 \}` satisfying `\sigma_i > i`.
2322
+
2323
+ Similarly we can define a quasisymmetric function `Q_{\lambda, j}`
2324
+ for every partition `\lambda` and every nonnegative integer `j`.
2325
+ This differs from `Q_{n,j}` only in that the sum is restricted to
2326
+ all permutations `\sigma \in S_n` whose cycle type is `\lambda`
2327
+ (where `n = |\lambda|`, and where we still require the number of
2328
+ excedances to be `j`). The method at hand allows computing these
2329
+ functions by passing `\lambda` as the ``n`` parameter.
2330
+
2331
+ Analogously we can define a quasisymmetric function `Q_{n,j,k}` for
2332
+ any nonnegative integers `n`, `j` and `k` by restricting the sum to
2333
+ all permutations `\sigma \in S_n` that have exactly `k` fixed
2334
+ points (and `j` excedances). This can be obtained by specifying the
2335
+ optional ``k`` argument in this method.
2336
+
2337
+ All three versions of Eulerian quasisymmetric functions
2338
+ (`Q_{n,j}`, `Q_{\lambda,j}` and `Q_{n,j,k}`) are actually
2339
+ symmetric functions. See
2340
+ :meth:`~sage.combinat.sf.SymmetricFunctionsBases.ParentMethods.Eulerian`.
2341
+
2342
+ INPUT:
2343
+
2344
+ - ``n`` -- the nonnegative integer `n` or a partition
2345
+ - ``j`` -- the number of excedances
2346
+ - ``k`` -- (optional) if specified, determines the number of fixed
2347
+ points of the permutations which are being summed over
2348
+
2349
+ EXAMPLES::
2350
+
2351
+ sage: F = QuasiSymmetricFunctions(QQ).F()
2352
+ sage: F.Eulerian(3, 1)
2353
+ F[1, 2] + F[2, 1] + 2*F[3]
2354
+ sage: F.Eulerian(4, 2)
2355
+ F[1, 2, 1] + 2*F[1, 3] + 3*F[2, 2] + 2*F[3, 1] + 3*F[4]
2356
+ sage: F.Eulerian(5, 2)
2357
+ F[1, 1, 2, 1] + F[1, 1, 3] + F[1, 2, 1, 1] + 7*F[1, 2, 2] + 6*F[1, 3, 1] + 6*F[1, 4] + 2*F[2, 1, 2] + 7*F[2, 2, 1] + 11*F[2, 3] + F[3, 1, 1] + 11*F[3, 2] + 6*F[4, 1] + 6*F[5]
2358
+ sage: F.Eulerian(4, 0)
2359
+ F[4]
2360
+ sage: F.Eulerian(4, 3)
2361
+ F[4]
2362
+ sage: F.Eulerian(4, 1, 2)
2363
+ F[1, 2, 1] + F[1, 3] + 2*F[2, 2] + F[3, 1] + F[4]
2364
+ sage: F.Eulerian(Partition([2, 2, 1]), 2)
2365
+ F[1, 1, 2, 1] + F[1, 2, 1, 1] + 2*F[1, 2, 2] + F[1, 3, 1]
2366
+ + F[1, 4] + F[2, 1, 2] + 2*F[2, 2, 1] + 2*F[2, 3]
2367
+ + 2*F[3, 2] + F[4, 1] + F[5]
2368
+ sage: F.Eulerian(0, 0)
2369
+ F[]
2370
+ sage: F.Eulerian(0, 1)
2371
+ 0
2372
+ sage: F.Eulerian(1, 0)
2373
+ F[1]
2374
+ sage: F.Eulerian(1, 1)
2375
+ 0
2376
+
2377
+ TESTS::
2378
+
2379
+ sage: F = QuasiSymmetricFunctions(QQ).F()
2380
+ sage: F.Eulerian(Partition([3, 1]), 1, 1)
2381
+ Traceback (most recent call last):
2382
+ ...
2383
+ ValueError: invalid input, k cannot be specified
2384
+ """
2385
+ from sage.combinat.partition import _Partitions
2386
+ if n in _Partitions:
2387
+ if k is not None:
2388
+ raise ValueError("invalid input, k cannot be specified")
2389
+ la = _Partitions(n)
2390
+ n = sum(la)
2391
+ else:
2392
+ la = None
2393
+
2394
+ if n == 0:
2395
+ if k is not None and k != 0:
2396
+ return self.zero()
2397
+ if j != 0:
2398
+ return self.zero()
2399
+ return self.one()
2400
+
2401
+ monomials = []
2402
+ for p in Permutations(n):
2403
+ dex = []
2404
+ exc = 0
2405
+ for i in range(n-1):
2406
+ if p[i] > i + 1:
2407
+ exc += 1
2408
+ if (p[i] > p[i+1] or (p[i] <= i+1 and p[i+1] > i+2)) \
2409
+ and not (p[i] > i+1 and p[i+1] <= i+2):
2410
+ dex.append(i)
2411
+
2412
+ if exc != j:
2413
+ continue
2414
+ if k is not None and p.number_of_fixed_points() != k:
2415
+ continue
2416
+ if la is not None and p.cycle_type() != la:
2417
+ continue
2418
+
2419
+ # Converting to a composition
2420
+ d = [-1] + dex + [n-1]
2421
+ monomials.append(Compositions()( [d[i+1]-d[i] for i in range(len(d)-1)] ))
2422
+
2423
+ return self.sum_of_monomials(monomials)
2424
+
2425
+ class Element(CombinatorialFreeModule.Element):
2426
+
2427
+ def internal_coproduct(self):
2428
+ r"""
2429
+ Return the inner coproduct of ``self`` in the Fundamental basis.
2430
+
2431
+ The inner coproduct (also known as the Kronecker coproduct,
2432
+ or as the second comultiplication on the `R`-algebra of
2433
+ quasi-symmetric functions) is an `R`-algebra homomorphism
2434
+ `\Delta^{\times}` from the `R`-algebra of quasi-symmetric
2435
+ functions to the tensor square (over `R`) of quasi-symmetric
2436
+ functions. It can be defined in the following two ways:
2437
+
2438
+ #. If `I` is a composition, then a `(0, I)`-matrix will mean a
2439
+ matrix whose entries are nonnegative integers such that no
2440
+ row and no column of this matrix is zero, and such that if
2441
+ all the nonzero entries of the matrix are read (row by row,
2442
+ starting at the topmost row, reading every row from left to
2443
+ right), then the reading word obtained is `I`. If `A` is
2444
+ a `(0, I)`-matrix, then `\mathrm{row}(A)` will denote the
2445
+ vector of row sums of `A` (regarded as a composition), and
2446
+ `\mathrm{column}(A)` will denote the vector of column sums
2447
+ of `A` (regarded as a composition).
2448
+
2449
+ For every composition `I`, the internal coproduct
2450
+ `\Delta^{\times}(M_I)` of the `I`-th monomial quasisymmetric
2451
+ function `M_I` is the sum
2452
+
2453
+ .. MATH::
2454
+
2455
+ \sum_{A \hbox{ is a } (0, I) \text{-matrix}}
2456
+ M_{\mathrm{row}(A)} \otimes M_{\mathrm{column}(A)}.
2457
+
2458
+ See Section 11.39 of [HazWitt1]_.
2459
+
2460
+ #. For every permutation `w`, let `C(w)` denote the descent
2461
+ composition of `w`. Then, for any composition `I` of size
2462
+ `n`, the internal coproduct `\Delta^{\times}(F_I)` of the
2463
+ `I`-th fundamental quasisymmetric function `F_I` is the sum
2464
+
2465
+ .. MATH::
2466
+
2467
+ \sum_{\substack{\sigma \in S_n,\\ \tau \in S_n,\\
2468
+ \tau \sigma = \pi}} F_{C(\sigma)} \otimes F_{C(\tau)},
2469
+
2470
+ where `\pi` is any permutation in `S_n` having descent
2471
+ composition `I` and where permutations act from the left and
2472
+ multiply accordingly, so `\tau \sigma` means first applying
2473
+ `\sigma` and then `\tau`. See Theorem 4.23 in [Mal1993]_,
2474
+ but beware of the notations which are apparently different
2475
+ from those in [HazWitt1]_.
2476
+
2477
+ The restriction of the internal coproduct to the
2478
+ `R`-algebra of symmetric functions is the well-known
2479
+ internal coproduct on the symmetric functions.
2480
+
2481
+ The method :meth:`kronecker_coproduct` is a synonym of this one.
2482
+
2483
+ EXAMPLES:
2484
+
2485
+ Let us compute the internal coproduct of `M_{21}` (which is
2486
+ short for `M_{[2, 1]}`). The `(0, [2,1])`-matrices are
2487
+
2488
+ .. MATH::
2489
+
2490
+ \begin{bmatrix}2& 1\end{bmatrix},
2491
+ \begin{bmatrix}2\\1\end{bmatrix},
2492
+ \begin{bmatrix}2& 0\\0& 1\end{bmatrix}, \hbox{ and }
2493
+ \begin{bmatrix}0&2\\1&0\end{bmatrix}
2494
+
2495
+ so
2496
+
2497
+ .. MATH::
2498
+
2499
+ \Delta^\times(M_{21}) = M_{3} \otimes M_{21} +
2500
+ M_{21} \otimes M_3 + M_{21} \otimes M_{21} +
2501
+ M_{21} \otimes M_{12}.
2502
+
2503
+ This is confirmed by the following Sage computation (incidentally
2504
+ demonstrating the non-cocommutativity of the internal
2505
+ coproduct)::
2506
+
2507
+ sage: M = QuasiSymmetricFunctions(ZZ).M()
2508
+ sage: a = M([2,1])
2509
+ sage: a.internal_coproduct()
2510
+ M[2, 1] # M[1, 2] + M[2, 1] # M[2, 1] + M[2, 1] # M[3] + M[3] # M[2, 1]
2511
+
2512
+ Some examples on the Fundamental basis::
2513
+
2514
+ sage: F = QuasiSymmetricFunctions(ZZ).F()
2515
+ sage: F([1,1]).internal_coproduct()
2516
+ F[1, 1] # F[2] + F[2] # F[1, 1]
2517
+ sage: F([2]).internal_coproduct()
2518
+ F[1, 1] # F[1, 1] + F[2] # F[2]
2519
+ sage: F([3]).internal_coproduct()
2520
+ F[1, 1, 1] # F[1, 1, 1] + F[1, 2] # F[1, 2] + F[1, 2] # F[2, 1]
2521
+ + F[2, 1] # F[1, 2] + F[2, 1] # F[2, 1] + F[3] # F[3]
2522
+ sage: F([1,2]).internal_coproduct()
2523
+ F[1, 1, 1] # F[1, 2] + F[1, 2] # F[2, 1] + F[1, 2] # F[3]
2524
+ + F[2, 1] # F[1, 1, 1] + F[2, 1] # F[2, 1] + F[3] # F[1, 2]
2525
+ """
2526
+ F = self.parent()
2527
+ F2 = F.tensor(F)
2528
+ result = F2.zero()
2529
+ from sage.categories.tensor import tensor
2530
+ from sage.combinat.permutation import Permutation
2531
+ for I, a in self:
2532
+ # We must add a * \Delta^\times(F_I) to result.
2533
+ from sage.combinat.permutation import descents_composition_last
2534
+ pi = descents_composition_last(I)
2535
+ n = I.size()
2536
+ for sigma in Permutations(n):
2537
+ sigma_inverse = sigma.inverse()
2538
+ # If the __mul__ of permutations wasn't such a mess,
2539
+ # the next line could be as simple as
2540
+ # tau = pi * sigma_inverse.
2541
+ tau = Permutation([pi(i) for i in sigma_inverse])
2542
+ result += a * tensor([F(sigma.descents_composition()),
2543
+ F(tau.descents_composition())])
2544
+ return result
2545
+
2546
+ kronecker_coproduct = internal_coproduct
2547
+
2548
+ def star_involution(self):
2549
+ r"""
2550
+ Return the image of the quasisymmetric function ``self`` under
2551
+ the star involution.
2552
+
2553
+ The star involution is defined as the linear map
2554
+ `QSym \to QSym` which, for every composition `I`, sends the
2555
+ monomial quasisymmetric function `M_I` to `M_{I^r}`. Here, if
2556
+ `I` is a composition, we denote by `I^r` the reversed
2557
+ composition of `I`. Denoting by `f^{\ast}` the image of an
2558
+ element `f \in QSym` under the star involution, it can be shown
2559
+ that every composition `I` satisfies
2560
+
2561
+ .. MATH::
2562
+
2563
+ (M_I)^{\ast} = M_{I^r}, \quad (F_I)^{\ast} = F_{I^r},
2564
+
2565
+ where `F_I` denotes the fundamental quasisymmetric function
2566
+ corresponding to the composition `I`. The star involution is an
2567
+ involution, an algebra automorphism and a coalgebra
2568
+ anti-automorphism of `QSym`. It also is an automorphism of the
2569
+ graded vector space `QSym`, and is the identity on the subspace
2570
+ `Sym` of `QSym`. It is adjoint to the star involution on `NCSF`
2571
+ by the standard adjunction between `NCSF` and `QSym`.
2572
+
2573
+ The star involution has been denoted by `\rho` in [LMvW13]_,
2574
+ section 3.6.
2575
+
2576
+ .. SEEALSO::
2577
+
2578
+ :meth:`star involution on QSym
2579
+ <sage.combinat.ncsf_qsym.qsym.QuasiSymmetricFunctions.Bases.ElementMethods.star_involution>`,
2580
+ :meth:`star involution on NCSF
2581
+ <sage.combinat.ncsf_qsym.ncsf.NonCommutativeSymmetricFunctions.Bases.ElementMethods.star_involution>`.
2582
+
2583
+ EXAMPLES::
2584
+
2585
+ sage: QSym = QuasiSymmetricFunctions(ZZ)
2586
+ sage: F = QSym.F()
2587
+ sage: F[3,1].star_involution()
2588
+ F[1, 3]
2589
+ sage: F[5,3].star_involution()
2590
+ F[3, 5]
2591
+ sage: (F[9,1] - F[6,2] + 2*F[6,4] - 3*F[3] + 4*F[[]]).star_involution()
2592
+ 4*F[] + F[1, 9] - F[2, 6] - 3*F[3] + 2*F[4, 6]
2593
+ sage: (F[3,3] - 2*F[2]).star_involution()
2594
+ -2*F[2] + F[3, 3]
2595
+ sage: F([4,2]).star_involution()
2596
+ F[2, 4]
2597
+ sage: dI = QSym.dI()
2598
+ sage: dI([1,2]).star_involution()
2599
+ -dI[1, 2] + dI[2, 1]
2600
+ sage: dI.zero().star_involution()
2601
+ 0
2602
+ """
2603
+ parent = self.parent()
2604
+ dct = {I.reversed(): coeff for (I, coeff) in self}
2605
+ return parent._from_dict(dct)
2606
+
2607
+ F = Fundamental
2608
+
2609
+ class Essential(CombinatorialFreeModule, BindableClass):
2610
+ r"""
2611
+ The Hopf algebra of quasi-symmetric functions in the Essential basis.
2612
+
2613
+ The Essential quasi-symmetric functions are defined by
2614
+
2615
+ .. MATH::
2616
+
2617
+ E_I = \sum_{J \geq I} M_J = \sum_{i_1 \leq \cdots \leq i_k}
2618
+ x_{i_1}^{I_1} \cdots x_{i_k}^{I_k},
2619
+
2620
+ where `I = (I_1, \ldots, I_k)`.
2621
+
2622
+ .. NOTE::
2623
+
2624
+ Our convention of `\leq` and `\geq` of compositions is
2625
+ opposite that of [Hoff2015]_.
2626
+
2627
+ EXAMPLES::
2628
+
2629
+ sage: QSym = QuasiSymmetricFunctions(QQ)
2630
+ sage: E = QSym.E()
2631
+ sage: M = QSym.M()
2632
+ sage: E(M[2,2])
2633
+ E[2, 2] - E[4]
2634
+ sage: s = SymmetricFunctions(QQ).s()
2635
+ sage: E(s[3,2])
2636
+ 5*E[1, 1, 1, 1, 1] - 2*E[1, 1, 1, 2] - 2*E[1, 1, 2, 1]
2637
+ - 2*E[1, 2, 1, 1] + E[1, 2, 2] - 2*E[2, 1, 1, 1]
2638
+ + E[2, 1, 2] + E[2, 2, 1]
2639
+ sage: (1 + E[1])^3
2640
+ E[] + 3*E[1] + 6*E[1, 1] + 6*E[1, 1, 1] - 3*E[1, 2]
2641
+ - 3*E[2] - 3*E[2, 1] + E[3]
2642
+ sage: E[1,2,1].coproduct()
2643
+ E[] # E[1, 2, 1] + E[1] # E[2, 1] + E[1, 2] # E[1] + E[1, 2, 1] # E[]
2644
+
2645
+ The following is an alias for this basis::
2646
+
2647
+ sage: QSym.Essential()
2648
+ Quasisymmetric functions over the Rational Field in the Essential basis
2649
+
2650
+ TESTS::
2651
+
2652
+ sage: E(M([]))
2653
+ E[]
2654
+ sage: E(M(0))
2655
+ 0
2656
+ sage: E(s([]))
2657
+ E[]
2658
+ sage: E(s(0))
2659
+ 0
2660
+ """
2661
+
2662
+ def __init__(self, QSym):
2663
+ """
2664
+ EXAMPLES::
2665
+
2666
+ sage: E = QuasiSymmetricFunctions(QQ).Essential()
2667
+ sage: TestSuite(E).run()
2668
+
2669
+ TESTS::
2670
+
2671
+ sage: E = QuasiSymmetricFunctions(QQ).E()
2672
+ sage: M = QuasiSymmetricFunctions(QQ).M()
2673
+ sage: all(E(M(E[c])) == E[c] for n in range(5)
2674
+ ....: for c in Compositions(n))
2675
+ True
2676
+ sage: all(M(E(M[c])) == M[c] for n in range(5)
2677
+ ....: for c in Compositions(n))
2678
+ True
2679
+ """
2680
+ CombinatorialFreeModule.__init__(self, QSym.base_ring(), Compositions(),
2681
+ prefix='E', bracket=False,
2682
+ category=QSym.Bases())
2683
+
2684
+ M = QSym.M()
2685
+ category = self.realization_of()._category
2686
+ # This changes Monomial into Essential
2687
+ M.module_morphism(self.alternating_sum_of_fatter_compositions,
2688
+ codomain=self, category=category
2689
+ ).register_as_coercion()
2690
+ # This changes Essential into Monomial
2691
+ self.module_morphism(M.sum_of_fatter_compositions,
2692
+ codomain=M, category=category
2693
+ ).register_as_coercion()
2694
+
2695
+ def antipode_on_basis(self, compo):
2696
+ r"""
2697
+ Return the result of the antipode applied to a quasi-symmetric
2698
+ Essential basis element.
2699
+
2700
+ INPUT:
2701
+
2702
+ - ``compo`` -- composition
2703
+
2704
+ OUTPUT:
2705
+
2706
+ - The result of the antipode applied to the composition ``compo``,
2707
+ expressed in the Essential basis.
2708
+
2709
+ EXAMPLES::
2710
+
2711
+ sage: E = QuasiSymmetricFunctions(QQ).E()
2712
+ sage: E.antipode_on_basis(Composition([2,1]))
2713
+ E[1, 2] - E[3]
2714
+ sage: E.antipode_on_basis(Composition([]))
2715
+ E[]
2716
+
2717
+ TESTS::
2718
+
2719
+ sage: E = QuasiSymmetricFunctions(QQ).E()
2720
+ sage: M = QuasiSymmetricFunctions(QQ).M()
2721
+ sage: all(E(M(E[c]).antipode()) == E[c].antipode()
2722
+ ....: for n in range(5) for c in Compositions(n))
2723
+ True
2724
+
2725
+ sage: all((-1)**len(I) * E[I] == M[I].star_involution().antipode()
2726
+ ....: for k in [3,4] for I in Compositions(k))
2727
+ True
2728
+ """
2729
+ return (-1)**len(compo) * self.alternating_sum_of_fatter_compositions(compo.reversed())
2730
+
2731
+ def coproduct_on_basis(self, compo):
2732
+ r"""
2733
+ Return the coproduct of a Essential basis element.
2734
+
2735
+ Combinatorial rule: deconcatenation.
2736
+
2737
+ INPUT:
2738
+
2739
+ - ``compo`` -- composition
2740
+
2741
+ OUTPUT:
2742
+
2743
+ - The coproduct applied to the Essential quasi-symmetric function
2744
+ indexed by ``compo``, expressed in the Essential basis.
2745
+
2746
+ EXAMPLES::
2747
+
2748
+ sage: E = QuasiSymmetricFunctions(QQ).Essential()
2749
+ sage: E[4,2,3].coproduct()
2750
+ E[] # E[4, 2, 3] + E[4] # E[2, 3] + E[4, 2] # E[3] + E[4, 2, 3] # E[]
2751
+ sage: E.coproduct_on_basis(Composition([]))
2752
+ E[] # E[]
2753
+ """
2754
+ return self.tensor_square().sum_of_monomials((self._indices(compo[:i]),
2755
+ self._indices(compo[i:]))
2756
+ for i in range(len(compo)+1))
2757
+
2758
+ def product_on_basis(self, I, J):
2759
+ r"""
2760
+ The product on Essential basis elements.
2761
+
2762
+ The product of the basis elements indexed by two compositions
2763
+ `I` and `J` is the sum of the basis elements indexed by
2764
+ compositions `K` in the stuffle product (also called the
2765
+ overlapping shuffle product) of `I` and `J` with a
2766
+ coefficient of `(-1)^{\ell(I) + \ell(J) - \ell(K)}`,
2767
+ where `\ell(C)` is the length of the composition `C`.
2768
+
2769
+ INPUT:
2770
+
2771
+ - ``I``, ``J`` -- compositions
2772
+
2773
+ OUTPUT:
2774
+
2775
+ - The product of the Essential quasi-symmetric functions indexed
2776
+ by ``I`` and ``J``, expressed in the Essential basis.
2777
+
2778
+ EXAMPLES::
2779
+
2780
+ sage: E = QuasiSymmetricFunctions(QQ).E()
2781
+ sage: c1 = Composition([2])
2782
+ sage: c2 = Composition([1,3])
2783
+ sage: E.product_on_basis(c1, c2)
2784
+ E[1, 2, 3] + E[1, 3, 2] - E[1, 5] + E[2, 1, 3] - E[3, 3]
2785
+ sage: E.product_on_basis(c1, Composition([]))
2786
+ E[2]
2787
+ sage: E.product_on_basis(c1, Composition([3]))
2788
+ E[2, 3] + E[3, 2] - E[5]
2789
+
2790
+ TESTS::
2791
+
2792
+ sage: E = QuasiSymmetricFunctions(QQ).E()
2793
+ sage: M = QuasiSymmetricFunctions(QQ).M()
2794
+ sage: all(E(M(E[cp])*M(E[c])) == E[cp]*E[c] # long time
2795
+ ....: for c in Compositions(3) for cp in Compositions(5))
2796
+ True
2797
+ """
2798
+ n = len(I) + len(J)
2799
+ return self.sum_of_terms((K, (-1)**(n - len(K)))
2800
+ for K in I.shuffle_product(J, overlap=True))
2801
+
2802
+ E = Essential
2803
+
2804
+ class Quasisymmetric_Schur(CombinatorialFreeModule, BindableClass):
2805
+ r"""
2806
+ The Hopf algebra of quasi-symmetric function in the Quasisymmetric
2807
+ Schur basis.
2808
+
2809
+ The basis of Quasisymmetric Schur functions is defined in [QSCHUR]_
2810
+ and in Definition 5.1.1 of [LMvW13]_.
2811
+ Don't mistake them for the completely unrelated quasi-Schur
2812
+ functions of [NCSF1]_!
2813
+
2814
+ EXAMPLES::
2815
+
2816
+ sage: QSym = QuasiSymmetricFunctions(QQ)
2817
+ sage: QS = QSym.QS()
2818
+ sage: F = QSym.F()
2819
+ sage: M = QSym.M()
2820
+ sage: F(QS[1,2])
2821
+ F[1, 2]
2822
+ sage: M(QS[1,2])
2823
+ M[1, 1, 1] + M[1, 2]
2824
+ sage: s = SymmetricFunctions(QQ).s()
2825
+ sage: QS(s[2,1,1])
2826
+ QS[1, 1, 2] + QS[1, 2, 1] + QS[2, 1, 1]
2827
+ """
2828
+
2829
+ def __init__(self, QSym):
2830
+ r"""
2831
+ EXAMPLES::
2832
+
2833
+ sage: QSym = QuasiSymmetricFunctions(QQ)
2834
+ sage: F = QSym.Fundamental()
2835
+ sage: QS = QSym.Quasisymmetric_Schur()
2836
+ sage: QS(F(QS.an_element())) == QS.an_element()
2837
+ True
2838
+ sage: F(QS(F.an_element())) == F.an_element()
2839
+ True
2840
+ sage: M = QSym.Monomial()
2841
+ sage: QS(M(QS.an_element())) == QS.an_element()
2842
+ True
2843
+ sage: M(QS(M.an_element())) == M.an_element()
2844
+ True
2845
+ sage: TestSuite(QS).run() # long time
2846
+ """
2847
+ CombinatorialFreeModule.__init__(self, QSym.base_ring(), Compositions(),
2848
+ prefix='QS', bracket=False,
2849
+ category=QSym.Bases())
2850
+
2851
+ def _realization_name(self):
2852
+ r"""
2853
+ Return a nicer name for ``self`` than what is inherited
2854
+ from :mod:`sage.categories.sets_cat`.
2855
+
2856
+ EXAMPLES::
2857
+
2858
+ sage: QSym = QuasiSymmetricFunctions(QQ)
2859
+ sage: QS = QSym.QS()
2860
+ sage: QS._realization_name()
2861
+ 'Quasisymmetric Schur'
2862
+ """
2863
+ return "Quasisymmetric Schur"
2864
+
2865
+ @cached_method
2866
+ def _from_monomial_transition_matrix(self, n):
2867
+ r"""
2868
+ A matrix representing the transition coefficients to
2869
+ the complete basis and the ordering of compositions.
2870
+
2871
+ INPUT:
2872
+
2873
+ - ``n`` -- integer
2874
+
2875
+ OUTPUT: a pair of a square matrix and the ordered list of compositions
2876
+
2877
+ EXAMPLES::
2878
+
2879
+ sage: QS = QuasiSymmetricFunctions(QQ).QS()
2880
+ sage: QS._from_monomial_transition_matrix(4)[0]
2881
+ [ 1 -1 -1 0 1 1 1 -1]
2882
+ [ 0 1 0 0 -1 -1 0 1]
2883
+ [ 0 0 1 -1 0 0 -1 1]
2884
+ [ 0 0 0 1 -1 -1 -1 1]
2885
+ [ 0 0 0 0 1 0 0 -1]
2886
+ [ 0 0 0 0 0 1 0 -1]
2887
+ [ 0 0 0 0 0 0 1 -1]
2888
+ [ 0 0 0 0 0 0 0 1]
2889
+ """
2890
+ if n == 0:
2891
+ return (matrix([[]]), [])
2892
+ CO = compositions_order(n)
2893
+ # ZZ is faster than over QQ for inverting a matrix
2894
+ from sage.rings.integer_ring import ZZ
2895
+ MS = MatrixSpace(ZZ, len(CO))
2896
+ M = MS([[number_of_SSRCT(al, be) for al in CO] for be in CO])
2897
+ return (M.inverse_of_unit(), CO)
2898
+
2899
+ @cached_method
2900
+ def _from_monomial_on_basis(self, comp):
2901
+ r"""
2902
+ Map the Monomial quasi-symmetric function indexed by
2903
+ ``comp`` to the Quasisymmetric Schur basis.
2904
+
2905
+ INPUT:
2906
+
2907
+ - ``comp`` -- a composition
2908
+
2909
+ OUTPUT: a quasi-symmetric function in the Quasisymmetric Schur basis
2910
+
2911
+ EXAMPLES::
2912
+
2913
+ sage: QSym = QuasiSymmetricFunctions(QQ)
2914
+ sage: QS = QSym.QS()
2915
+ sage: M = QSym.M()
2916
+ sage: QS._from_monomial_on_basis(Composition([1,3,1]))
2917
+ QS[1, 1, 1, 1, 1] - QS[1, 1, 2, 1] + QS[1, 3, 1] - QS[2, 2, 1]
2918
+ sage: QS._from_monomial_on_basis(Composition([2]))
2919
+ -QS[1, 1] + QS[2]
2920
+ """
2921
+ comp = Composition(comp)
2922
+ if not comp._list:
2923
+ return self.one()
2924
+ T, comps = self._from_monomial_transition_matrix(comp.size())
2925
+ i = comps.index(comp)
2926
+ return self._from_dict({c: T[i,j] for j,c in enumerate(comps)
2927
+ if T[i,j] != 0},
2928
+ remove_zeros=False)
2929
+
2930
+ @cached_method
2931
+ def _to_monomial_on_basis(self, comp_shape):
2932
+ r"""
2933
+ Expand the quasi-symmetric Schur function in the Monomial basis.
2934
+
2935
+ The expansion of the quasi-symmetric Schur function indexed
2936
+ by ``comp_shape`` has coefficients which are given by the method
2937
+ :meth:`~sage.combinat.ncsf_qsym.combinatorics.number_of_SSRCT`.
2938
+
2939
+ INPUT:
2940
+
2941
+ - ``comp_shape`` -- a composition
2942
+
2943
+ OUTPUT: a quasi-symmetric function in the Monomial basis
2944
+
2945
+ EXAMPLES::
2946
+
2947
+ sage: QSym = QuasiSymmetricFunctions(QQ)
2948
+ sage: QS = QSym.QS()
2949
+ sage: QS._to_monomial_on_basis(Composition([1,3,1]))
2950
+ 2*M[1, 1, 1, 1, 1] + 2*M[1, 1, 2, 1] + M[1, 2, 1, 1] + M[1, 3, 1] + M[2, 1, 1, 1] + M[2, 2, 1]
2951
+ """
2952
+ M = self.realization_of().Monomial()
2953
+ if not comp_shape:
2954
+ return M([])
2955
+ return M.sum_of_terms(((comp_content,
2956
+ number_of_SSRCT(comp_content, comp_shape))
2957
+ for comp_content in Compositions(sum(comp_shape))),
2958
+ distinct=True )
2959
+
2960
+ def dual(self):
2961
+ r"""
2962
+ The dual basis to the Quasisymmetric Schur basis.
2963
+
2964
+ The dual basis to the Quasisymmetric Schur basis is
2965
+ implemented as dual.
2966
+
2967
+ OUTPUT:
2968
+
2969
+ - the dual Quasisymmetric Schur basis of the
2970
+ non-commutative symmetric functions
2971
+
2972
+ EXAMPLES::
2973
+
2974
+ sage: QS = QuasiSymmetricFunctions(QQ).Quasisymmetric_Schur()
2975
+ sage: QS.dual()
2976
+ Non-Commutative Symmetric Functions over the Rational Field
2977
+ in the dual Quasisymmetric-Schur basis
2978
+ """
2979
+ return self.realization_of().dual().dualQuasisymmetric_Schur()
2980
+
2981
+ QS = Quasisymmetric_Schur
2982
+
2983
+ class Young_Quasisymmetric_Schur(CombinatorialFreeModule, BindableClass):
2984
+ r"""
2985
+ The Hopf algebra of quasi-symmetric functions in the Young
2986
+ Quasisymmetric Schur basis.
2987
+
2988
+ The basis of Young Quasisymmetric Schur functions is from
2989
+ Definition 5.2.1 of [LMvW13]_.
2990
+
2991
+ This basis is related to the Quasisymmetric Schur basis ``QS`` by
2992
+ ``QS(alpha.reversed()) == YQS(alpha).star_involution()`` .
2993
+
2994
+ EXAMPLES::
2995
+
2996
+ sage: QSym = QuasiSymmetricFunctions(QQ)
2997
+ sage: YQS = QSym.YQS()
2998
+ sage: F = QSym.F()
2999
+ sage: QS = QSym.QS()
3000
+ sage: F(YQS[1,2])
3001
+ F[1, 2]
3002
+ sage: all(QS(al.reversed())==YQS(al).star_involution() for al in Compositions(5))
3003
+ True
3004
+ sage: s = SymmetricFunctions(QQ).s()
3005
+ sage: YQS(s[2,1,1])
3006
+ YQS[1, 1, 2] + YQS[1, 2, 1] + YQS[2, 1, 1]
3007
+ """
3008
+
3009
+ def __init__(self, QSym):
3010
+ r"""
3011
+ Initialize ``self``.
3012
+
3013
+ EXAMPLES::
3014
+
3015
+ sage: QSym = QuasiSymmetricFunctions(QQ)
3016
+ sage: F = QSym.Fundamental()
3017
+ sage: YQS = QSym.Young_Quasisymmetric_Schur()
3018
+ sage: YQS(F(YQS.an_element())) == YQS.an_element()
3019
+ True
3020
+ sage: F(YQS(F.an_element())) == F.an_element()
3021
+ True
3022
+ sage: M = QSym.Monomial()
3023
+ sage: YQS(M(YQS.an_element())) == YQS.an_element()
3024
+ True
3025
+ sage: M(YQS(M.an_element())) == M.an_element()
3026
+ True
3027
+ sage: TestSuite(YQS).run() # long time
3028
+ """
3029
+ self._QS = QSym.QS()
3030
+ self._M = QSym.M()
3031
+ CombinatorialFreeModule.__init__(self, QSym.base_ring(),
3032
+ Compositions(), prefix='YQS',
3033
+ bracket=False, category=QSym.Bases())
3034
+ self.module_morphism(self._to_monomial_on_basis,
3035
+ codomain=self._M, category=QSym.Bases()).register_as_coercion()
3036
+ self._M.module_morphism(self._from_monomial_on_basis,
3037
+ codomain=self, category=QSym.Bases()).register_as_coercion()
3038
+
3039
+ def _realization_name(self):
3040
+ r"""
3041
+ Return a nicer name for ``self`` than what is inherited
3042
+ from :mod:`sage.categories.sets_cat`.
3043
+
3044
+ EXAMPLES::
3045
+
3046
+ sage: QSym = QuasiSymmetricFunctions(QQ)
3047
+ sage: QS = QSym.QS()
3048
+ sage: QS._realization_name()
3049
+ 'Quasisymmetric Schur'
3050
+ """
3051
+ return "Young Quasisymmetric Schur"
3052
+
3053
+ @cached_method
3054
+ def _to_monomial_on_basis(self, comp):
3055
+ r"""
3056
+ Expand the Young quasi-symmetric Schur function in the
3057
+ Monomial basis.
3058
+
3059
+ INPUT:
3060
+
3061
+ - ``comp`` -- a composition
3062
+
3063
+ OUTPUT: a quasi-symmetric function in the Monomial basis
3064
+
3065
+ EXAMPLES::
3066
+
3067
+ sage: QSym = QuasiSymmetricFunctions(QQ)
3068
+ sage: YQS = QSym.QS()
3069
+ sage: YQS._to_monomial_on_basis(Composition([2]))
3070
+ M[1, 1] + M[2]
3071
+ sage: YQS._to_monomial_on_basis(Composition([1,3,1]))
3072
+ 2*M[1, 1, 1, 1, 1] + 2*M[1, 1, 2, 1] + M[1, 2, 1, 1] + M[1, 3, 1] + M[2, 1, 1, 1] + M[2, 2, 1]
3073
+ """
3074
+ return self._M(self._QS.monomial(comp.reversed())).star_involution()
3075
+
3076
+ @cached_method
3077
+ def _from_monomial_on_basis(self, comp):
3078
+ r"""
3079
+ The expansion of the quasi-symmetric Schur function indexed
3080
+ by ``comp_shape`` has coefficients which are given by the method
3081
+ :meth:`~sage.combinat.ncsf_qsym.combinatorics.number_of_SSRCT`.
3082
+
3083
+ INPUT:
3084
+
3085
+ - ``comp`` -- a composition
3086
+
3087
+ OUTPUT: a quasi-symmetric function in the Young Quasisymmetric Schur basis
3088
+
3089
+ EXAMPLES::
3090
+
3091
+ sage: QSym = QuasiSymmetricFunctions(QQ)
3092
+ sage: YQS = QSym.YQS()
3093
+ sage: YQS._from_monomial_on_basis(Composition([2]))
3094
+ -YQS[1, 1] + YQS[2]
3095
+ sage: YQS._from_monomial_on_basis(Composition([1,3,1]))
3096
+ YQS[1, 1, 1, 1, 1] - YQS[1, 2, 1, 1] - YQS[1, 2, 2] + YQS[1, 3, 1]
3097
+ """
3098
+ elt = self._QS(self._M.monomial(comp.reversed()))
3099
+ return self._from_dict({al.reversed(): c for al,c in elt},
3100
+ coerce=False, remove_zeros=False)
3101
+
3102
+ YQS = Young_Quasisymmetric_Schur
3103
+
3104
+ class dualImmaculate(CombinatorialFreeModule, BindableClass):
3105
+ def __init__(self, QSym):
3106
+ r"""
3107
+ The dual immaculate basis of the quasi-symmetric functions.
3108
+
3109
+ This basis first appears in [BBSSZ2012]_.
3110
+
3111
+ EXAMPLES::
3112
+
3113
+ sage: QSym = QuasiSymmetricFunctions(QQ)
3114
+ sage: dI = QSym.dI()
3115
+ sage: dI([1,3,2])*dI([1]) # long time (6s on sage.math, 2013)
3116
+ dI[1, 1, 3, 2] + dI[2, 3, 2]
3117
+ sage: dI([1,3])*dI([1,1])
3118
+ dI[1, 1, 1, 3] + dI[1, 1, 4] + dI[1, 2, 3] - dI[1, 3, 2] - dI[1, 4, 1] - dI[1, 5] + dI[2, 3, 1] + dI[2, 4]
3119
+ sage: dI([3,1])*dI([2,1]) # long time (7s on sage.math, 2013)
3120
+ dI[1, 1, 5] - dI[1, 4, 1, 1] - dI[1, 4, 2] - 2*dI[1, 5, 1] - dI[1, 6] - dI[2, 4, 1] - dI[2, 5] - dI[3, 1, 3] + dI[3, 2, 1, 1] + dI[3, 2, 2] + dI[3, 3, 1] + dI[4, 1, 1, 1] + 2*dI[4, 2, 1] + dI[4, 3] + dI[5, 1, 1] + dI[5, 2]
3121
+ sage: F = QSym.F()
3122
+ sage: dI(F[1,3,1])
3123
+ -dI[1, 1, 1, 2] + dI[1, 1, 2, 1] - dI[1, 2, 2] + dI[1, 3, 1]
3124
+ sage: F(dI(F([2,1,3])))
3125
+ F[2, 1, 3]
3126
+ """
3127
+ CombinatorialFreeModule.__init__(self, QSym.base_ring(), Compositions(),
3128
+ prefix='dI', bracket=False,
3129
+ category=QSym.Bases())
3130
+
3131
+ def _to_Monomial_on_basis(self, J):
3132
+ r"""
3133
+ Expand the dual immaculate function labelled by a composition
3134
+ ``J`` in the quasi-symmetric monomial basis.
3135
+
3136
+ INPUT:
3137
+
3138
+ - ``J`` -- a composition
3139
+
3140
+ OUTPUT: a quasi-symmetric function in the monomial basis
3141
+
3142
+ EXAMPLES::
3143
+
3144
+ sage: dI = QuasiSymmetricFunctions(QQ).dI()
3145
+ sage: dI._to_Monomial_on_basis(Composition([1,3]))
3146
+ M[1, 1, 1, 1] + M[1, 1, 2] + M[1, 2, 1] + M[1, 3]
3147
+ sage: dI._to_Monomial_on_basis(Composition([]))
3148
+ M[]
3149
+ sage: dI._to_Monomial_on_basis(Composition([2,1,2]))
3150
+ 4*M[1, 1, 1, 1, 1] + 3*M[1, 1, 1, 2] + 2*M[1, 1, 2, 1] + M[1, 1, 3] + M[1, 2, 1, 1] + M[1, 2, 2] + M[2, 1, 1, 1] + M[2, 1, 2]
3151
+ """
3152
+ M = self.realization_of().Monomial()
3153
+ if not J._list:
3154
+ return M([])
3155
+ C = Compositions()
3156
+ C_size = Compositions(J.size())
3157
+ return M.sum_of_terms( ( (C(I), number_of_fCT(C(I), J)) for I in C_size ),
3158
+ distinct=True )
3159
+
3160
+ @cached_method
3161
+ def _matrix_monomial_to_dual_immaculate(self, n):
3162
+ r"""
3163
+ This function caches the change of basis matrix from the
3164
+ quasisymmetric monomial basis to the dual immaculate basis.
3165
+
3166
+ INPUT:
3167
+
3168
+ - ``J`` -- a composition
3169
+
3170
+ OUTPUT:
3171
+
3172
+ - A list. Each entry in the list is a row in the
3173
+ change-of-basis matrix.
3174
+
3175
+ EXAMPLES::
3176
+
3177
+ sage: dI = QuasiSymmetricFunctions(QQ).dI()
3178
+ sage: dI._matrix_monomial_to_dual_immaculate(3)
3179
+ [[1, -1, -1, 1], [0, 1, -1, 0], [0, 0, 1, -1], [0, 0, 0, 1]]
3180
+ sage: dI._matrix_monomial_to_dual_immaculate(0)
3181
+ [[1]]
3182
+ """
3183
+ N = NonCommutativeSymmetricFunctions(self.base_ring())
3184
+ I = N.I()
3185
+ S = N.S()
3186
+ mat = []
3187
+ C = Compositions()
3188
+ C_n = Compositions(n)
3189
+ for alp in C_n:
3190
+ row = []
3191
+ expansion = S(I(C(alp)))
3192
+ for bet in C_n:
3193
+ row.append(expansion.coefficient(C(bet)))
3194
+ mat.append(row)
3195
+ return mat
3196
+
3197
+ def _from_Monomial_on_basis(self, J):
3198
+ r"""
3199
+ Expand the monomial quasi-symmetric function labelled by the
3200
+ composition ``J`` in the dual immaculate basis.
3201
+
3202
+ INPUT:
3203
+
3204
+ - ``J`` -- a composition
3205
+
3206
+ OUTPUT: a quasi-symmetric function in the dual immaculate basis
3207
+
3208
+ EXAMPLES::
3209
+
3210
+ sage: dI = QuasiSymmetricFunctions(QQ).dI()
3211
+ sage: dI._from_Monomial_on_basis(Composition([]))
3212
+ dI[]
3213
+ sage: dI._from_Monomial_on_basis(Composition([2,1]))
3214
+ -dI[1, 1, 1] - dI[1, 2] + dI[2, 1]
3215
+ sage: dI._from_Monomial_on_basis(Composition([3,1,2]))
3216
+ -dI[1, 1, 1, 1, 1, 1] + dI[1, 1, 1, 1, 2] + dI[1, 1, 1, 3] - dI[1, 1, 4] - dI[1, 2, 1, 1, 1] + dI[1, 2, 3] + dI[2, 1, 1, 1, 1] - dI[2, 1, 1, 2] + dI[2, 2, 1, 1] - dI[2, 2, 2] - dI[3, 1, 1, 1] + dI[3, 1, 2]
3217
+ """
3218
+ n = J.size()
3219
+ C = Compositions()
3220
+ C_n = Compositions(n)
3221
+ mat = self._matrix_monomial_to_dual_immaculate(n)
3222
+ column = C_n.list().index(J)
3223
+ return self.sum_of_terms( ( (C(I), mat[C_n.list().index(I)][column])
3224
+ for I in C_n ),
3225
+ distinct=True )
3226
+
3227
+ dI = dualImmaculate
3228
+
3229
+ class HazewinkelLambda(CombinatorialFreeModule, BindableClass):
3230
+ r"""
3231
+ The Hazewinkel lambda basis of the quasi-symmetric functions.
3232
+
3233
+ This basis goes back to [Haz2004]_, albeit it is indexed in a
3234
+ different way here. It is a multiplicative basis in a weak
3235
+ sense of this word (the product of any two basis elements is a
3236
+ basis element, but of course not the one obtained by
3237
+ concatenating the indexing compositions).
3238
+
3239
+ In [Haz2004]_, Hazewinkel showed that the `\mathbf{k}`-algebra
3240
+ `\mathrm{QSym}` is a polynomial algebra. (The proof is correct
3241
+ but rests upon an unproven claim that the lexicographically
3242
+ largest term of the `n`-th shuffle power of a Lyndon word is
3243
+ the `n`-fold concatenation of this Lyndon word with
3244
+ itself, occurring `n!` times in that shuffle power. But this
3245
+ can be deduced from Section 2 of [Rad1979]_. See also
3246
+ Chapter 6 of [GriRei18]_, specifically Theorem 6.5.13, for a
3247
+ complete proof.) More precisely, he showed that
3248
+ `\mathrm{QSym}` is generated, as a free commutative
3249
+ `\mathbf{k}`-algebra, by the elements `\lambda^n(M_I)`, where
3250
+ `n` ranges over the positive integers, and `I` ranges over
3251
+ all compositions which are Lyndon words and whose entries
3252
+ have gcd `1`. Here, `\lambda^n` denotes the `n`-th lambda
3253
+ operation as explained in
3254
+ :meth:`~sage.combinat.ncsf_qsym.qsym.QuasiSymmetricFunctions.Monomial.lambda_of_monomial`.
3255
+
3256
+ Thus, products of these generators form a `\mathbf{k}`-module
3257
+ basis of `\mathrm{QSym}`. We index this basis by compositions
3258
+ here. More precisely, we define the Hazewinkel lambda basis
3259
+ `(\mathrm{HWL}_I)_I` (with `I` ranging over all compositions)
3260
+ as follows:
3261
+
3262
+ Let `I` be a composition. Let `I = I_1 I_2 \ldots I_k` be the
3263
+ Chen-Fox-Lyndon factorization of `I` (see
3264
+ :meth:`~sage.combinat.words.finite_word.FiniteWord_class.lyndon_factorization`).
3265
+ For every `j \in \{1, 2, \ldots , k\}`, let `g_j` be the
3266
+ gcd of the entries of the Lyndon word `I_j`, and let `J_j` be
3267
+ the result of dividing the entries of `I_j` by this gcd. Then,
3268
+ `\mathrm{HWL}_I` is defined to be
3269
+ `\prod_{j=1}^{k} \lambda^{g_j} (M_{J_j})`.
3270
+
3271
+ .. TODO::
3272
+
3273
+ The conversion from the M basis to the HWL basis is
3274
+ currently implemented in the naive way (inverting the
3275
+ base-change matrix in the other direction). This matrix
3276
+ is not triangular (not even after any permutations of
3277
+ the bases), and there could very well be a faster method
3278
+ (the one given by Hazewinkel?).
3279
+
3280
+ EXAMPLES::
3281
+
3282
+ sage: QSym = QuasiSymmetricFunctions(ZZ)
3283
+ sage: HWL = QSym.HazewinkelLambda()
3284
+ sage: M = QSym.M()
3285
+ sage: M(HWL([2]))
3286
+ M[1, 1]
3287
+ sage: M(HWL([1,1]))
3288
+ 2*M[1, 1] + M[2]
3289
+ sage: M(HWL([1,2]))
3290
+ M[1, 2]
3291
+ sage: M(HWL([2,1]))
3292
+ 3*M[1, 1, 1] + M[1, 2] + M[2, 1]
3293
+ sage: M(HWL(Composition([])))
3294
+ M[]
3295
+ sage: HWL(M([1,1]))
3296
+ HWL[2]
3297
+ sage: HWL(M(Composition([2])))
3298
+ HWL[1, 1] - 2*HWL[2]
3299
+ sage: HWL(M([1]))
3300
+ HWL[1]
3301
+
3302
+ TESTS:
3303
+
3304
+ Transforming from the M-basis into the HWL-basis and back
3305
+ returns us to where we started::
3306
+
3307
+ sage: all( M(HWL(M[I])) == M[I] for I in Compositions(3) )
3308
+ True
3309
+ sage: all( HWL(M(HWL[I])) == HWL[I] for I in Compositions(4) )
3310
+ True
3311
+
3312
+ Checking the HWL basis elements corresponding to Lyndon
3313
+ words::
3314
+
3315
+ sage: all( M(HWL[Composition(I)])
3316
+ ....: == M.lambda_of_monomial([i // gcd(I) for i in I], gcd(I))
3317
+ ....: for I in LyndonWords(e=3, k=2) )
3318
+ True
3319
+ """
3320
+
3321
+ def __init__(self, QSym):
3322
+ r"""
3323
+ TESTS::
3324
+
3325
+ sage: HWL = QuasiSymmetricFunctions(QQ).HazewinkelLambda()
3326
+ sage: TestSuite(HWL).run()
3327
+ """
3328
+ CombinatorialFreeModule.__init__(self, QSym.base_ring(), Compositions(),
3329
+ prefix='HWL', bracket=False,
3330
+ category=QSym.Bases())
3331
+
3332
+ def __init_extra__(self):
3333
+ """
3334
+ Set up caches for the transition maps to and from the monomial
3335
+ basis, and register them as coercions.
3336
+
3337
+ TESTS::
3338
+
3339
+ sage: HWL = QuasiSymmetricFunctions(QQ).HazewinkelLambda()
3340
+ sage: M = QuasiSymmetricFunctions(QQ).Monomial()
3341
+ sage: M2HWL = HWL.coerce_map_from(M); M2HWL
3342
+ Generic morphism:
3343
+ From: Quasisymmetric functions over the Rational Field in the Monomial basis
3344
+ To: Quasisymmetric functions over the Rational Field in the HazewinkelLambda basis
3345
+ sage: HWL2M = M.coerce_map_from(HWL); HWL2M
3346
+ Generic morphism:
3347
+ From: Quasisymmetric functions over the Rational Field in the HazewinkelLambda basis
3348
+ To: Quasisymmetric functions over the Rational Field in the Monomial basis
3349
+ sage: HWL2M(HWL[2])
3350
+ M[1, 1]
3351
+ sage: M2HWL(M[2])
3352
+ HWL[1, 1] - 2*HWL[2]
3353
+ """
3354
+ M = self.realization_of().M()
3355
+ category = self.realization_of()._category
3356
+ # This changes Monomial into Hazewinkel Lambda
3357
+ M.module_morphism(self._from_Monomial_on_basis,
3358
+ codomain=self, category=category
3359
+ ).register_as_coercion()
3360
+ # This changes Hazewinkel Lambda into Monomial
3361
+ self.module_morphism(self._to_Monomial_on_basis,
3362
+ codomain=M, category=category
3363
+ ).register_as_coercion()
3364
+
3365
+ # cache for the coordinates of the elements
3366
+ # of the monomial basis with respect to the HWL basis
3367
+ self._M_to_self_cache = {}
3368
+ # cache for the coordinates of the elements
3369
+ # of the HWL basis with respect to the monomial basis
3370
+ self._M_from_self_cache = {}
3371
+ # cache for transition matrices which contain the coordinates of
3372
+ # the elements of the monomial basis with respect to the HWL basis
3373
+ self._M_transition_matrices = {}
3374
+ # cache for transition matrices which contain the coordinates of
3375
+ # the elements of the HWL basis with respect to the monomial basis
3376
+ self._M_inverse_transition_matrices = {}
3377
+
3378
+ def _precompute_cache(self, n, to_self_cache, from_self_cache, transition_matrices, inverse_transition_matrices, from_self_gen_function):
3379
+ r"""
3380
+ Compute the transition matrices between ``self`` and the
3381
+ monomial basis in the homogeneous components of degree `n`.
3382
+ The results are not returned, but rather stored in the caches.
3383
+
3384
+ This assumes that the transition matrices in all degrees smaller
3385
+ than `n` have already been computed and cached!
3386
+
3387
+ INPUT:
3388
+
3389
+ - ``n`` -- nonnegative integer
3390
+ - ``to_self_cache`` -- a cache which stores the coordinates of
3391
+ the elements of the monomial basis with respect to the
3392
+ basis ``self``
3393
+ - ``from_self_cache`` -- a cache which stores the coordinates
3394
+ of the elements of ``self`` with respect to the monomial
3395
+ basis
3396
+ - ``transition_matrices`` -- a cache for transition matrices
3397
+ which contain the coordinates of the elements of the monomial
3398
+ basis with respect to ``self``
3399
+ - ``inverse_transition_matrices`` -- a cache for transition
3400
+ matrices which contain the coordinates of the elements of
3401
+ ``self`` with respect to the monomial basis
3402
+ - ``from_self_gen_function`` -- a function which takes a
3403
+ Lyndon word `I` and returns the Hazewinkel Lambda basis
3404
+ element indexed by `I` expanded with respect to the
3405
+ monomial basis (as an element of the monomial basis, not as
3406
+ a dictionary)
3407
+
3408
+ EXAMPLES:
3409
+
3410
+ The examples below demonstrate how the caches are built
3411
+ step by step using the ``_precompute_cache`` method. In order
3412
+ not to influence the outcome of other doctests, we make sure
3413
+ not to use the caches internally used by this class, but
3414
+ rather to create new caches. This allows us to compute the
3415
+ transition matrices for a slight variation of the Hazewinkel
3416
+ Lambda basis, namely the basis whose `I`-th element is given
3417
+ by the simple formula `\prod_{j=1}^{k} M_{I_j}` instead of
3418
+ `\prod_{j=1}^{k} \lambda^{g_j} (M_{J_j})`. We will see that
3419
+ this is only a `\QQ`-basis rather than a `\ZZ`-basis (a
3420
+ reason why the Ditters conjecture took so long to prove)::
3421
+
3422
+ sage: QSym = QuasiSymmetricFunctions(QQ)
3423
+ sage: HWL = QSym.HazewinkelLambda()
3424
+ sage: M = QSym.M()
3425
+ sage: toy_to_self_cache = {}
3426
+ sage: toy_from_self_cache = {}
3427
+ sage: toy_transition_matrices = {}
3428
+ sage: toy_inverse_transition_matrices = {}
3429
+ sage: l = lambda c: [ (i[0],[j for j in sorted(i[1].items())]) for i in sorted(c.items())]
3430
+ sage: l(toy_to_self_cache)
3431
+ []
3432
+ sage: def toy_gen_function(I):
3433
+ ....: return M[I]
3434
+ sage: HWL._precompute_cache(0, toy_to_self_cache,
3435
+ ....: toy_from_self_cache,
3436
+ ....: toy_transition_matrices,
3437
+ ....: toy_inverse_transition_matrices,
3438
+ ....: toy_gen_function)
3439
+ sage: l(toy_to_self_cache)
3440
+ [([], [([], 1)])]
3441
+ sage: HWL._precompute_cache(1, toy_to_self_cache,
3442
+ ....: toy_from_self_cache,
3443
+ ....: toy_transition_matrices,
3444
+ ....: toy_inverse_transition_matrices,
3445
+ ....: toy_gen_function)
3446
+ sage: l(toy_to_self_cache)
3447
+ [([], [([], 1)]), ([1], [([1], 1)])]
3448
+ sage: HWL._precompute_cache(2, toy_to_self_cache,
3449
+ ....: toy_from_self_cache,
3450
+ ....: toy_transition_matrices,
3451
+ ....: toy_inverse_transition_matrices,
3452
+ ....: toy_gen_function)
3453
+ sage: l(toy_to_self_cache)
3454
+ [([], [([], 1)]), ([1], [([1], 1)]), ([1, 1], [([1, 1], 1/2), ([2], -1/2)]), ([2], [([2], 1)])]
3455
+ sage: toy_transition_matrices[2]
3456
+ [ 1/2 -1/2]
3457
+ [ 0 1]
3458
+ sage: toy_inverse_transition_matrices[2]
3459
+ [2 1]
3460
+ [0 1]
3461
+ sage: sorted(toy_transition_matrices)
3462
+ [0, 1, 2]
3463
+
3464
+ As we see from the fractions in the transition matrices, this
3465
+ is only a basis over `\QQ`, not over `\ZZ`.
3466
+
3467
+ Let us try another variation on the definition of the basis:
3468
+ `\prod_{j=1}^{k} \lambda^{g_j} (M_{J_j})` will now be replaced
3469
+ by `\prod_{j=1}^{k} M_{J_j^{g_j}}`, where `J_g` means the
3470
+ `g`-fold concatenation of the composition `J` with itself::
3471
+
3472
+ sage: toy_to_self_cache = {}
3473
+ sage: toy_from_self_cache = {}
3474
+ sage: toy_transition_matrices = {}
3475
+ sage: toy_inverse_transition_matrices = {}
3476
+ sage: l = lambda c: [ (i[0],[j for j in sorted(i[1].items())]) for i in sorted(c.items())]
3477
+ sage: l(toy_to_self_cache)
3478
+ []
3479
+ sage: def toy_gen_function(I):
3480
+ ....: xs = [i // gcd(I) for i in I] * gcd(I)
3481
+ ....: return M[xs]
3482
+ sage: HWL._precompute_cache(0, toy_to_self_cache,
3483
+ ....: toy_from_self_cache,
3484
+ ....: toy_transition_matrices,
3485
+ ....: toy_inverse_transition_matrices,
3486
+ ....: toy_gen_function)
3487
+ sage: l(toy_to_self_cache)
3488
+ [([], [([], 1)])]
3489
+ sage: HWL._precompute_cache(1, toy_to_self_cache,
3490
+ ....: toy_from_self_cache,
3491
+ ....: toy_transition_matrices,
3492
+ ....: toy_inverse_transition_matrices,
3493
+ ....: toy_gen_function)
3494
+ sage: l(toy_to_self_cache)
3495
+ [([], [([], 1)]), ([1], [([1], 1)])]
3496
+ sage: HWL._precompute_cache(2, toy_to_self_cache,
3497
+ ....: toy_from_self_cache,
3498
+ ....: toy_transition_matrices,
3499
+ ....: toy_inverse_transition_matrices,
3500
+ ....: toy_gen_function)
3501
+ sage: l(toy_to_self_cache)
3502
+ [([], [([], 1)]), ([1], [([1], 1)]), ([1, 1], [([2], 1)]), ([2], [([1, 1], 1), ([2], -2)])]
3503
+
3504
+ This appears to form another `\ZZ`-basis of
3505
+ `\mathrm{QSym}`, but the appearance is deceiving: it
3506
+ fails to span the degree-`9` part of `\mathrm{QSym}`.
3507
+ (The corresponding computation is not tested as it takes
3508
+ a few minutes.) We have not checked if it spans
3509
+ `\mathrm{QSym}` over `\QQ`.
3510
+ """
3511
+ # Much of this code is adapted from sage/combinat/sf/dual.py
3512
+ base_ring = self.base_ring()
3513
+ zero = base_ring.zero()
3514
+
3515
+ # Handle the n == 0 case separately
3516
+ if n == 0:
3517
+ part = self._indices([])
3518
+ one = base_ring.one()
3519
+ to_self_cache[ part ] = { part: one }
3520
+ from_self_cache[ part ] = { part: one }
3521
+ transition_matrices[n] = matrix(base_ring, [[one]])
3522
+ inverse_transition_matrices[n] = matrix(base_ring, [[one]])
3523
+ return
3524
+
3525
+ compositions_n = Compositions(n).list()
3526
+ len_compositions_n = 2 ** (n-1) # since n > 0 by now.
3527
+ M = self.realization_of().M()
3528
+
3529
+ # The monomial basis will be called M from now on.
3530
+
3531
+ # This contains the data for the transition matrix from the
3532
+ # monomial basis M to the Hazewinkel lambda basis self.
3533
+ transition_matrix_n = matrix(base_ring, len_compositions_n, len_compositions_n)
3534
+
3535
+ # This first section calculates how the basis elements of the
3536
+ # Hazewinkel lambda basis self decompose in the monomial
3537
+ # basis M.
3538
+
3539
+ # For every composition I of size n, expand self[I] in terms
3540
+ # of the monomial basis M.
3541
+ i = 0
3542
+ for I in compositions_n:
3543
+ # M_coeffs will be M(self[I])._monomial_coefficients
3544
+ M_coeffs = {}
3545
+
3546
+ self_I_in_M_basis = M.prod([from_self_gen_function(self._indices(list(J)))
3547
+ for J in Word(I).lyndon_factorization()])
3548
+
3549
+ j = 0
3550
+
3551
+ for J in compositions_n:
3552
+ if J in self_I_in_M_basis._monomial_coefficients:
3553
+ sp = self_I_in_M_basis._monomial_coefficients[J]
3554
+ M_coeffs[J] = sp
3555
+ transition_matrix_n[i,j] = sp
3556
+
3557
+ j += 1
3558
+
3559
+ from_self_cache[I] = M_coeffs
3560
+ i += 1
3561
+
3562
+ # Save the transition matrix
3563
+ inverse_transition_matrices[n] = transition_matrix_n
3564
+
3565
+ # This second section calculates how the basis elements of the
3566
+ # monomial basis M expand in terms of the basis B. We do this
3567
+ # by inverting the above transition matrix.
3568
+ #
3569
+ # TODO: The way given in Hazewinkel's [Haz2004]_ paper might
3570
+ # be faster.
3571
+ inverse_transition = (~transition_matrix_n).change_ring(base_ring)
3572
+ # Note that we don't simply write
3573
+ # "inverse_transition = ~transition_matrix_n" because that
3574
+ # tends to cast the entries of the matrix into a quotient
3575
+ # field even if this is unnecessary.
3576
+ # MAYBE use .inverse_of_unit() ?
3577
+
3578
+ # TODO: This still looks fragile when the base ring is weird!
3579
+ # Possibly work over ZZ in this method?
3580
+
3581
+ for i in range(len_compositions_n):
3582
+ self_coeffs = {}
3583
+ for j in range(len_compositions_n):
3584
+ if inverse_transition[i,j] != zero:
3585
+ self_coeffs[ compositions_n[j] ] = inverse_transition[i,j]
3586
+
3587
+ to_self_cache[ compositions_n[i] ] = self_coeffs
3588
+
3589
+ transition_matrices[n] = inverse_transition
3590
+
3591
+ def _precompute_M(self, n):
3592
+ """
3593
+ Compute the transition matrices between ``self`` and the
3594
+ monomial basis in the homogeneous components of degree `n`
3595
+ (and in those of smaller degree, if not already computed).
3596
+ The result is not returned, but rather stored in the cache.
3597
+
3598
+ INPUT:
3599
+
3600
+ - ``n`` -- nonnegative integer
3601
+
3602
+ EXAMPLES:
3603
+
3604
+ The examples below demonstrate how the caches of ``self`` are
3605
+ built step by step using the ``_precompute_M`` method. This
3606
+ demonstration relies on an untouched Hazewinkel Lambda basis
3607
+ (because any computations might have filled the cache already).
3608
+ We obtain such a basis by choosing a ground ring unlikely to
3609
+ appear elsewhere::
3610
+
3611
+ sage: QSym = QuasiSymmetricFunctions(ZZ['hell', 'yeah'])
3612
+ sage: HWL = QSym.HazewinkelLambda()
3613
+ sage: M = QSym.M()
3614
+ sage: l = lambda c: [ (i[0],[j for j in sorted(i[1].items())]) for i in sorted(c.items())]
3615
+ sage: l(HWL._M_to_self_cache)
3616
+ []
3617
+ sage: HWL._precompute_M(0)
3618
+ sage: l(HWL._M_to_self_cache)
3619
+ [([], [([], 1)])]
3620
+ sage: HWL._precompute_M(1)
3621
+ sage: l(HWL._M_to_self_cache)
3622
+ [([], [([], 1)]), ([1], [([1], 1)])]
3623
+ sage: HWL._precompute_M(2)
3624
+ sage: l(HWL._M_to_self_cache)
3625
+ [([], [([], 1)]),
3626
+ ([1], [([1], 1)]),
3627
+ ([1, 1], [([2], 1)]),
3628
+ ([2], [([1, 1], 1), ([2], -2)])]
3629
+ sage: HWL._M_transition_matrices[2]
3630
+ [ 0 1]
3631
+ [ 1 -2]
3632
+ sage: HWL._M_inverse_transition_matrices[2]
3633
+ [2 1]
3634
+ [1 0]
3635
+ sage: sorted(HWL._M_transition_matrices)
3636
+ [0, 1, 2]
3637
+
3638
+ We did not have to call ``HWL._precompute_M(0)``,
3639
+ ``HWL._precompute_M(1)`` and ``HWL._precompute_M(2)``
3640
+ in this order; it would be enough to just call
3641
+ ``HWL._precompute_M(2)``::
3642
+
3643
+ sage: QSym = QuasiSymmetricFunctions(ZZ['lol', 'wut'])
3644
+ sage: HWL = QSym.HazewinkelLambda()
3645
+ sage: M = QSym.M()
3646
+ sage: l = lambda c: [ (i[0],[j for j in sorted(i[1].items())]) for i in sorted(c.items())]
3647
+ sage: l(HWL._M_to_self_cache)
3648
+ []
3649
+ sage: HWL._precompute_M(2)
3650
+ sage: l(HWL._M_to_self_cache)
3651
+ [([], [([], 1)]),
3652
+ ([1], [([1], 1)]),
3653
+ ([1, 1], [([2], 1)]),
3654
+ ([2], [([1, 1], 1), ([2], -2)])]
3655
+ sage: HWL._precompute_M(1)
3656
+ sage: l(HWL._M_to_self_cache)
3657
+ [([], [([], 1)]),
3658
+ ([1], [([1], 1)]),
3659
+ ([1, 1], [([2], 1)]),
3660
+ ([2], [([1, 1], 1), ([2], -2)])]
3661
+ """
3662
+ l = len(self._M_transition_matrices)
3663
+ M = self.realization_of().M()
3664
+ if l <= n:
3665
+ from sage.misc.cachefunc import cached_function
3666
+ from sage.arith.misc import gcd
3667
+
3668
+ @cached_function
3669
+ def monolambda(I):
3670
+ # expansion of self[I] in monomial basis,
3671
+ # where I is a composition which is a Lyndon word
3672
+ g = gcd(I)
3673
+ I_reduced = [i // g for i in I]
3674
+ return M.lambda_of_monomial(I_reduced, g)
3675
+ for i in range(l, n + 1):
3676
+ self._precompute_cache(i, self._M_to_self_cache,
3677
+ self._M_from_self_cache,
3678
+ self._M_transition_matrices,
3679
+ self._M_inverse_transition_matrices,
3680
+ monolambda)
3681
+
3682
+ def _to_Monomial_on_basis(self, J):
3683
+ r"""
3684
+ Expand the Hazewinkel Lambda basis element labelled by a
3685
+ composition ``J`` in the quasi-symmetric Monomial basis.
3686
+
3687
+ INPUT:
3688
+
3689
+ - ``J`` -- a composition
3690
+
3691
+ OUTPUT: a quasi-symmetric function in the Monomial basis
3692
+
3693
+ EXAMPLES::
3694
+
3695
+ sage: HWL = QuasiSymmetricFunctions(QQ).HazewinkelLambda()
3696
+ sage: J = Composition([1, 2, 1])
3697
+ sage: HWL._to_Monomial_on_basis(J)
3698
+ 2*M[1, 1, 2] + M[1, 2, 1] + M[1, 3] + M[2, 2]
3699
+ """
3700
+ n = sum(J)
3701
+ self._precompute_M(n)
3702
+ return self.realization_of().M()._from_dict(self._M_from_self_cache[J])
3703
+
3704
+ def _from_Monomial_on_basis(self, J):
3705
+ r"""
3706
+ Expand the Monomial quasi-symmetric function labelled by the
3707
+ composition ``J`` in the Hazewinkel Lambda basis.
3708
+
3709
+ INPUT:
3710
+
3711
+ - ``J`` -- a composition
3712
+
3713
+ OUTPUT: a quasi-symmetric function in the Hazewinkel lambda basis
3714
+
3715
+ EXAMPLES::
3716
+
3717
+ sage: HWL = QuasiSymmetricFunctions(QQ).HazewinkelLambda()
3718
+ sage: J = Composition([1, 2, 1])
3719
+ sage: HWL._from_Monomial_on_basis(J)
3720
+ -2*HWL[1, 1, 2] + HWL[1, 2, 1] - HWL[1, 3] - HWL[2, 2] + 2*HWL[3, 1] - 2*HWL[4]
3721
+ """
3722
+ n = sum(J)
3723
+ self._precompute_M(n)
3724
+ return self._from_dict(self._M_to_self_cache[J])
3725
+
3726
+ def product_on_basis(self, I, J):
3727
+ """
3728
+ The product on Hazewinkel Lambda basis elements.
3729
+
3730
+ The product of the basis elements indexed by two compositions
3731
+ `I` and `J` is the basis element obtained by concatenating the
3732
+ Lyndon factorizations of the words `I` and `J`, then reordering
3733
+ the Lyndon factors in nonincreasing order, and finally
3734
+ concatenating them in this order (giving a new composition).
3735
+
3736
+ INPUT:
3737
+
3738
+ - ``I``, ``J`` -- compositions
3739
+
3740
+ OUTPUT:
3741
+
3742
+ - The product of the Hazewinkel Lambda quasi-symmetric
3743
+ functions indexed by ``I`` and ``J``, expressed in the
3744
+ Hazewinkel Lambda basis.
3745
+
3746
+ EXAMPLES::
3747
+
3748
+ sage: HWL = QuasiSymmetricFunctions(QQ).HazewinkelLambda()
3749
+ sage: c1 = Composition([1, 2, 1])
3750
+ sage: c2 = Composition([2, 1, 3, 2])
3751
+ sage: HWL.product_on_basis(c1, c2)
3752
+ HWL[2, 1, 3, 2, 1, 2, 1]
3753
+ sage: HWL.product_on_basis(c1, Composition([]))
3754
+ HWL[1, 2, 1]
3755
+ sage: HWL.product_on_basis(Composition([]), Composition([]))
3756
+ HWL[]
3757
+
3758
+ TESTS::
3759
+
3760
+ sage: M = QuasiSymmetricFunctions(QQ).M()
3761
+ sage: all( all( M(HWL[I] * HWL[J]) == M(HWL[I]) * M(HWL[J]) # long time
3762
+ ....: for I in Compositions(3) )
3763
+ ....: for J in Compositions(3) )
3764
+ True
3765
+ """
3766
+ from sage.misc.flatten import flatten
3767
+ I_factors = [list(i) for i in Word(I).lyndon_factorization()]
3768
+ J_factors = [list(j) for j in Word(J).lyndon_factorization()]
3769
+ # This uses the convenient fact that comparison of lists in
3770
+ # Python works exactly as one wants in Lyndon word theory:
3771
+ # [a_1, a_2, ..., a_n] > [b_1, b_2, ..., b_m] if and only if
3772
+ # either some i satisfies a_i > b_i and (a_j == b_j for all
3773
+ # j < i), or we have n > m and all i <= m satisfy a_i == b_i.
3774
+ new_factors = sorted(I_factors + J_factors, reverse=True)
3775
+ return self.monomial(self._indices(flatten(new_factors)))
3776
+
3777
+ class psi(CombinatorialFreeModule, BindableClass):
3778
+ r"""
3779
+ The Hopf algebra of quasi-symmetric functions in the `\psi` basis.
3780
+
3781
+ The `\psi` basis is defined as a rescaled Hopf dual of the `\Psi`
3782
+ basis of the non-commutative symmetric functions (see Section 3.1
3783
+ of [BDHMN2017]_), where the pairing is
3784
+
3785
+ .. MATH::
3786
+
3787
+ (\psi_I, \Psi_J) = z_I \delta_{I,J},
3788
+
3789
+ where `z_I = 1^{m_1} m_1! 2^{m_2} m_2! \cdots` with `m_i` being the
3790
+ multiplicity of `i` in the composition `I`. Therefore, we call these
3791
+ the *quasi-symmetric power sums of the first kind*.
3792
+
3793
+ Using the duality, we can directly define the `\psi` basis by
3794
+
3795
+ .. MATH::
3796
+
3797
+ \psi_I = \sum_{J \succ I} z_I / \pi_{I,J} M_J,
3798
+
3799
+ where `\pi_{I,J}` is as defined in [NCSF]_.
3800
+
3801
+ The `\psi`-basis is well-defined only when the base ring is a
3802
+ `\QQ`-algebra.
3803
+
3804
+ EXAMPLES::
3805
+
3806
+ sage: QSym = QuasiSymmetricFunctions(QQ)
3807
+ sage: psi = QSym.psi(); psi
3808
+ Quasisymmetric functions over the Rational Field in the psi basis
3809
+ sage: psi.an_element()
3810
+ 2*psi[] + 2*psi[1] + 3*psi[1, 1]
3811
+ sage: p = SymmetricFunctions(QQ).p()
3812
+ sage: psi(p[2,2,1])
3813
+ psi[1, 2, 2] + psi[2, 1, 2] + psi[2, 2, 1]
3814
+ sage: all(sum(psi(list(al)) for al in Permutations(la))==psi(p(la)) for la in Partitions(6))
3815
+ True
3816
+ sage: p = SymmetricFunctions(QQ).p()
3817
+ sage: psi(p[3,2,2])
3818
+ psi[2, 2, 3] + psi[2, 3, 2] + psi[3, 2, 2]
3819
+
3820
+ Checking the equivalent definition of `\psi_n`::
3821
+
3822
+ sage: def test_psi(n):
3823
+ ....: psi = QuasiSymmetricFunctions(QQ).psi()
3824
+ ....: Psi = NonCommutativeSymmetricFunctions(QQ).Psi()
3825
+ ....: M = matrix([[psi[I].duality_pairing(Psi[J])
3826
+ ....: for I in Compositions(n)]
3827
+ ....: for J in Compositions(n)])
3828
+ ....: def z(J): return J.to_partition().centralizer_size()
3829
+ ....: return M == matrix.diagonal([z(I) for I in Compositions(n)])
3830
+ sage: all(test_psi(k) for k in range(1,5))
3831
+ True
3832
+ """
3833
+
3834
+ def __init__(self, QSym):
3835
+ r"""
3836
+ Initialize ``self``.
3837
+
3838
+ EXAMPLES::
3839
+
3840
+ sage: psi = QuasiSymmetricFunctions(QQ).psi()
3841
+ sage: TestSuite(psi).run()
3842
+
3843
+ TESTS::
3844
+
3845
+ sage: psi = QuasiSymmetricFunctions(QQ).psi()
3846
+ sage: M = QuasiSymmetricFunctions(QQ).M()
3847
+ sage: all(psi(M(psi[c])) == psi[c] for n in range(5)
3848
+ ....: for c in Compositions(n))
3849
+ True
3850
+ sage: all(M(psi(M[c])) == M[c] for n in range(5)
3851
+ ....: for c in Compositions(n))
3852
+ True
3853
+ """
3854
+ CombinatorialFreeModule.__init__(self, QSym.base_ring(), Compositions(),
3855
+ prefix='psi', bracket=False,
3856
+ category=QSym.Bases())
3857
+
3858
+ category = self.realization_of()._category
3859
+ Monomial = self.realization_of().Monomial()
3860
+ self.module_morphism(self._to_Monomial_on_basis,
3861
+ codomain=Monomial, category=category
3862
+ ).register_as_coercion()
3863
+ Monomial.module_morphism(self._from_Monomial_on_basis,
3864
+ codomain=self, category=category
3865
+ ).register_as_coercion()
3866
+
3867
+ def _from_Monomial_on_basis(self, I):
3868
+ r"""
3869
+ Expand a Monomial basis element indexed by ``I`` in the
3870
+ `\psi` basis.
3871
+
3872
+ INPUT:
3873
+
3874
+ - ``I`` -- a composition
3875
+
3876
+ OUTPUT: a quasi-symmetric function in the `\psi` basis
3877
+
3878
+ TESTS::
3879
+
3880
+ sage: psi = QuasiSymmetricFunctions(QQ).psi()
3881
+ sage: I = Composition([2, 3, 2])
3882
+ sage: psi._from_Monomial_on_basis(I)
3883
+ 1/2*psi[2, 3, 2] - 2/5*psi[2, 5] - 3/5*psi[5, 2] + 2/7*psi[7]
3884
+ """
3885
+ R = self.base_ring()
3886
+ minus_one = -R.one()
3887
+
3888
+ def z(J):
3889
+ return R(J.to_partition().centralizer_size())
3890
+ return self._from_dict({J: minus_one**(len(I)-len(J)) / z(J) * coeff_lp(I, J)
3891
+ for J in I.fatter()})
3892
+
3893
+ def _to_Monomial_on_basis(self, I):
3894
+ r"""
3895
+ Expand a `\psi` basis element indexed by ``I`` in the
3896
+ Monomial basis.
3897
+
3898
+ INPUT:
3899
+
3900
+ - ``I`` -- a composition
3901
+
3902
+ OUTPUT: a quasi-symmetric function in the Monomial basis
3903
+
3904
+ TESTS::
3905
+
3906
+ sage: psi = QuasiSymmetricFunctions(QQ).psi()
3907
+ sage: I = Composition([2, 3, 2])
3908
+ sage: psi._to_Monomial_on_basis(I)
3909
+ 2*M[2, 3, 2] + 4/5*M[2, 5] + 6/5*M[5, 2] + 12/35*M[7]
3910
+ """
3911
+ R = self.base_ring()
3912
+ z = R(I.to_partition().centralizer_size())
3913
+ Monomial = self.realization_of().Monomial()
3914
+ return Monomial._from_dict({J: z / coeff_pi(I,J) for J in I.fatter()})
3915
+
3916
+ class phi(CombinatorialFreeModule, BindableClass):
3917
+ r"""
3918
+ The Hopf algebra of quasi-symmetric functions in the `\phi` basis.
3919
+
3920
+ The `\phi` basis is defined as a rescaled Hopf dual of the `\Phi`
3921
+ basis of the non-commutative symmetric functions (see Section 3.1
3922
+ of [BDHMN2017]_), where the pairing is
3923
+
3924
+ .. MATH::
3925
+
3926
+ (\phi_I, \Phi_J) = z_I \delta_{I,J},
3927
+
3928
+ where `z_I = 1^{m_1} m_1! 2^{m_2} m_2! \cdots` with `m_i` being the
3929
+ multiplicity of `i` in the composition `I`. Therefore, we call these
3930
+ the *quasi-symmetric power sums of the second kind*.
3931
+
3932
+ Using the duality, we can directly define the `\phi` basis by
3933
+
3934
+ .. MATH::
3935
+
3936
+ \phi_I = \sum_{J \succ I} z_I / sp_{I,J} M_J,
3937
+
3938
+ where `sp_{I,J}` is as defined in [NCSF]_.
3939
+
3940
+ The `\phi`-basis is well-defined only when the base ring is a
3941
+ `\QQ`-algebra.
3942
+
3943
+ EXAMPLES::
3944
+
3945
+ sage: QSym = QuasiSymmetricFunctions(QQ)
3946
+ sage: phi = QSym.phi(); phi
3947
+ Quasisymmetric functions over the Rational Field in the phi basis
3948
+ sage: phi.an_element()
3949
+ 2*phi[] + 2*phi[1] + 3*phi[1, 1]
3950
+ sage: p = SymmetricFunctions(QQ).p()
3951
+ sage: phi(p[2,2,1])
3952
+ phi[1, 2, 2] + phi[2, 1, 2] + phi[2, 2, 1]
3953
+ sage: all(sum(phi(list(al)) for al in Permutations(la))==phi(p(la)) for la in Partitions(6))
3954
+ True
3955
+ sage: p = SymmetricFunctions(QQ).p()
3956
+ sage: phi(p[3,2,2])
3957
+ phi[2, 2, 3] + phi[2, 3, 2] + phi[3, 2, 2]
3958
+
3959
+ Checking the equivalent definition of `\phi_n`::
3960
+
3961
+ sage: def test_phi(n):
3962
+ ....: phi = QuasiSymmetricFunctions(QQ).phi()
3963
+ ....: Phi = NonCommutativeSymmetricFunctions(QQ).Phi()
3964
+ ....: M = matrix([[phi[I].duality_pairing(Phi[J])
3965
+ ....: for I in Compositions(n)]
3966
+ ....: for J in Compositions(n)])
3967
+ ....: def z(J): return J.to_partition().centralizer_size()
3968
+ ....: return M == matrix.diagonal([z(I) for I in Compositions(n)])
3969
+ sage: all(test_phi(k) for k in range(1,5))
3970
+ True
3971
+ """
3972
+
3973
+ def __init__(self, QSym):
3974
+ r"""
3975
+ Initialize ``self``.
3976
+
3977
+ EXAMPLES::
3978
+
3979
+ sage: phi = QuasiSymmetricFunctions(QQ).phi()
3980
+ sage: TestSuite(phi).run()
3981
+
3982
+ TESTS::
3983
+
3984
+ sage: phi = QuasiSymmetricFunctions(QQ).phi()
3985
+ sage: M = QuasiSymmetricFunctions(QQ).M()
3986
+ sage: all(phi(M(phi[c])) == phi[c] for n in range(5)
3987
+ ....: for c in Compositions(n))
3988
+ True
3989
+ sage: all(M(phi(M[c])) == M[c] for n in range(5)
3990
+ ....: for c in Compositions(n))
3991
+ True
3992
+ """
3993
+ CombinatorialFreeModule.__init__(self, QSym.base_ring(), Compositions(),
3994
+ prefix='phi', bracket=False,
3995
+ category=QSym.Bases())
3996
+
3997
+ category = self.realization_of()._category
3998
+ Monomial = self.realization_of().Monomial()
3999
+ self.module_morphism(self._to_Monomial_on_basis,
4000
+ codomain=Monomial, category=category
4001
+ ).register_as_coercion()
4002
+ Monomial.module_morphism(self._from_Monomial_on_basis,
4003
+ codomain=self, category=category
4004
+ ).register_as_coercion()
4005
+
4006
+ def _from_Monomial_on_basis(self, I):
4007
+ r"""
4008
+ Expand a Monomial basis element indexed by ``I`` in the
4009
+ `\phi` basis.
4010
+
4011
+ INPUT:
4012
+
4013
+ - ``I`` -- a composition
4014
+
4015
+ OUTPUT: a quasi-symmetric function in the `\psi` basis
4016
+
4017
+ TESTS::
4018
+
4019
+ sage: phi = QuasiSymmetricFunctions(QQ).phi()
4020
+ sage: I = Composition([3, 2, 2])
4021
+ sage: phi._from_Monomial_on_basis(I)
4022
+ 1/2*phi[3, 2, 2] - 1/2*phi[3, 4] - 1/2*phi[5, 2] + 1/3*phi[7]
4023
+ """
4024
+ R = self.base_ring()
4025
+ minus_one = -R.one()
4026
+
4027
+ def z(J):
4028
+ return R(J.to_partition().centralizer_size())
4029
+ return self._from_dict({J: minus_one**(len(I)-len(J)) * R.prod(J) / (coeff_ell(I, J) * z(J))
4030
+ for J in I.fatter()})
4031
+
4032
+ def _to_Monomial_on_basis(self, I):
4033
+ r"""
4034
+ Expand a `\phi` basis element indexed by ``I`` in the
4035
+ Monomial basis.
4036
+
4037
+ INPUT:
4038
+
4039
+ - ``I`` -- a composition
4040
+
4041
+ OUTPUT: a quasi-symmetric function in the Monomial basis
4042
+
4043
+ TESTS::
4044
+
4045
+ sage: phi = QuasiSymmetricFunctions(QQ).phi()
4046
+ sage: I = Composition([3, 2, 2])
4047
+ sage: phi._to_Monomial_on_basis(I)
4048
+ 2*M[3, 2, 2] + M[3, 4] + M[5, 2] + 1/3*M[7]
4049
+ """
4050
+ R = self.base_ring()
4051
+ z = R(I.to_partition().centralizer_size())
4052
+ Monomial = self.realization_of().Monomial()
4053
+ return Monomial._from_dict({J: z / coeff_sp(I,J) for J in I.fatter()})