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,2013 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ # sage.doctest: needs sage.combinat sage.graphs sage.modules
3
+ r"""
4
+ Alcove paths
5
+
6
+ AUTHORS:
7
+
8
+ - Brant Jones (2008): initial version
9
+ - Arthur Lubovsky (2013-03-07): rewritten to implement affine type
10
+ - Travis Scrimshaw (2016-06-23): implemented `\mathcal{B}(\infty)`
11
+
12
+ Special thanks to: Nicolas Borie, Anne Schilling, Travis Scrimshaw, and
13
+ Nicolas Thiéry.
14
+ """
15
+ # ****************************************************************************
16
+ # Copyright (C) 2008 Brant Jones <brant at math.ucdavis.edu>
17
+ # Copyright (C) 2013 Arthur Lubovsky <alubovsky at albany.edu>
18
+ #
19
+ # This program is free software: you can redistribute it and/or modify
20
+ # it under the terms of the GNU General Public License as published by
21
+ # the Free Software Foundation, either version 2 of the License, or
22
+ # (at your option) any later version.
23
+ # https://www.gnu.org/licenses/
24
+ # ****************************************************************************
25
+
26
+ from sage.structure.parent import Parent
27
+ from sage.structure.element import Element
28
+ from sage.structure.element_wrapper import ElementWrapper
29
+ from sage.structure.unique_representation import UniqueRepresentation
30
+ from sage.structure.richcmp import richcmp
31
+ from sage.categories.classical_crystals import ClassicalCrystals
32
+ from sage.categories.loop_crystals import LoopCrystals
33
+ from sage.combinat.root_system.cartan_type import CartanType
34
+ from sage.combinat.root_system.root_system import RootSystem
35
+ from sage.rings.integer import Integer
36
+ from sage.misc.misc_c import prod
37
+ from sage.categories.sets_cat import Sets
38
+ from sage.misc.cachefunc import cached_method, cached_in_parent_method
39
+ from sage.misc.lazy_import import lazy_import
40
+ from sage.categories.highest_weight_crystals import HighestWeightCrystals
41
+ from copy import copy
42
+ from sage.misc.latex import latex
43
+
44
+ lazy_import('sage.graphs.digraph', 'DiGraph')
45
+ lazy_import('sage.combinat.root_system.weyl_group', 'WeylGroup')
46
+ lazy_import('sage.modules.free_module_element', 'vector')
47
+
48
+
49
+ class CrystalOfAlcovePaths(UniqueRepresentation, Parent):
50
+ r"""
51
+ Crystal of alcove paths generated from a "straight-line" path to the
52
+ negative of a given dominant weight.
53
+
54
+ INPUT:
55
+
56
+ - ``cartan_type`` -- Cartan type of a finite or affine untwisted root
57
+ system
58
+
59
+ - ``weight`` -- dominant weight as a list of (integral) coefficients of
60
+ the fundamental weights
61
+
62
+ - ``highest_weight_crystal`` -- (default: ``True``) if ``True``
63
+ returns the highest weight crystal. If ``False`` returns an
64
+ object which is close to being isomorphic to the tensor product
65
+ of Kirillov-Reshetikhin crystals of column shape in the
66
+ following sense: We get all the vertices, but only some of the
67
+ edges. We'll call the included edges pseudo-Demazure. They are
68
+ all nonzero edges and the 0-edges not at the end of a 0-string
69
+ of edges, i.e. not those with `f_{0}(b) = b'` with
70
+ `\varphi_0(b) =1`. (Whereas Demazure 0-edges are those that
71
+ are not at the beginning of a zero string.) In this case the
72
+ weight `[c_1, c_2, \ldots, c_k]` represents
73
+ `\sum_{i=1}^k c_i \omega_i`.
74
+
75
+ .. NOTE::
76
+
77
+ If ``highest_weight_crystal`` = ``False``, since we do not
78
+ get the full crystal, ``TestSuite`` will fail on the
79
+ Stembridge axioms.
80
+
81
+ .. SEEALSO::
82
+
83
+ - :class:`Crystals`
84
+
85
+ EXAMPLES:
86
+
87
+ The following example appears in Figure 2 of [LP2008]_::
88
+
89
+ sage: C = crystals.AlcovePaths(['G',2],[0,1])
90
+ sage: G = C.digraph()
91
+ sage: GG = DiGraph({
92
+ ....: () : {(0) : 2 },
93
+ ....: (0) : {(0,8) : 1 },
94
+ ....: (0,1) : {(0,1,7) : 2 },
95
+ ....: (0,1,2) : {(0,1,2,9) : 1 },
96
+ ....: (0,1,2,3) : {(0,1,2,3,4) : 2 },
97
+ ....: (0,1,2,6) : {(0,1,2,3) : 1 },
98
+ ....: (0,1,2,9) : {(0,1,2,6) : 1 },
99
+ ....: (0,1,7) : {(0,1,2) : 2 },
100
+ ....: (0,1,7,9) : {(0,1,2,9) : 2 },
101
+ ....: (0,5) : {(0,1) : 1, (0,5,7) : 2 },
102
+ ....: (0,5,7) : {(0,5,7,9) : 1 },
103
+ ....: (0,5,7,9) : {(0,1,7,9) : 1 },
104
+ ....: (0,8) : {(0,5) : 1 },
105
+ ....: })
106
+ sage: G.is_isomorphic(GG)
107
+ True
108
+ sage: for (u,v,i) in G.edges(sort=True):
109
+ ....: print((u.integer_sequence() , v.integer_sequence(), i))
110
+ ([], [0], 2)
111
+ ([0], [0, 8], 1)
112
+ ([0, 1], [0, 1, 7], 2)
113
+ ([0, 1, 2], [0, 1, 2, 9], 1)
114
+ ([0, 1, 2, 3], [0, 1, 2, 3, 4], 2)
115
+ ([0, 1, 2, 6], [0, 1, 2, 3], 1)
116
+ ([0, 1, 2, 9], [0, 1, 2, 6], 1)
117
+ ([0, 1, 7], [0, 1, 2], 2)
118
+ ([0, 1, 7, 9], [0, 1, 2, 9], 2)
119
+ ([0, 5], [0, 1], 1)
120
+ ([0, 5], [0, 5, 7], 2)
121
+ ([0, 5, 7], [0, 5, 7, 9], 1)
122
+ ([0, 5, 7, 9], [0, 1, 7, 9], 1)
123
+ ([0, 8], [0, 5], 1)
124
+
125
+ Alcove path crystals are a discrete version of Littelmann paths.
126
+ We verify that the alcove path crystal is isomorphic to the LS
127
+ path crystal::
128
+
129
+ sage: C1 = crystals.AlcovePaths(['C',3],[2,1,0])
130
+ sage: g1 = C1.digraph() #long time
131
+ sage: C2 = crystals.LSPaths(['C',3],[2,1,0])
132
+ sage: g2 = C2.digraph() #long time
133
+ sage: g1.is_isomorphic(g2, edge_labels=True) #long time
134
+ True
135
+
136
+ The preferred initialization method is via explicit weights rather than a Cartan type
137
+ and the coefficients of the fundamental weights::
138
+
139
+ sage: R = RootSystem(['C',3])
140
+ sage: P = R.weight_lattice()
141
+ sage: La = P.fundamental_weights()
142
+ sage: C = crystals.AlcovePaths(2*La[1]+La[2]); C
143
+ Highest weight crystal of alcove paths of type ['C', 3] and weight 2*Lambda[1] + Lambda[2]
144
+ sage: C1==C
145
+ True
146
+
147
+ We now explain the data structure::
148
+
149
+ sage: C = crystals.AlcovePaths(['A',2],[2,0]) ; C
150
+ Highest weight crystal of alcove paths of type ['A', 2] and weight 2*Lambda[1]
151
+ sage: C._R.lambda_chain()
152
+ [(alpha[1], 0), (alpha[1] + alpha[2], 0), (alpha[1], 1), (alpha[1] + alpha[2], 1)]
153
+
154
+ The previous list gives the initial "straight line" path from the
155
+ fundamental alcove `A_o` to its translation `A_o - \lambda` where
156
+ `\lambda = 2\omega_1` in this example. The initial path for weight
157
+ `\lambda` is called the `\lambda`-chain. This path is constructed from
158
+ the ordered pairs `(\beta, k)`, by crossing the hyperplane orthogonal to
159
+ `\beta` at height `-k`. We can view a plot of this path as follows::
160
+
161
+ sage: x=C( () )
162
+ sage: x.plot() # not tested - outputs a pdf
163
+
164
+ An element of the crystal is given by a subset of the `\lambda`-chain.
165
+ This subset indicates the hyperplanes where the initial path should be
166
+ folded. The highest weight element is given by the empty subset. ::
167
+
168
+ sage: x
169
+ ()
170
+ sage: x.f(1).f(2)
171
+ ((alpha[1], 1), (alpha[1] + alpha[2], 1))
172
+ sage: x.f(1).f(2).integer_sequence()
173
+ [2, 3]
174
+ sage: C([2,3])
175
+ ((alpha[1], 1), (alpha[1] + alpha[2], 1))
176
+ sage: C([2,3]).is_admissible() #check if a valid vertex
177
+ True
178
+ sage: C([1,3]).is_admissible() #check if a valid vertex
179
+ False
180
+
181
+ Alcove path crystals now works in affine type (:issue:`14143`)::
182
+
183
+ sage: C = crystals.AlcovePaths(['A',2,1],[1,0,0]) ; C
184
+ Highest weight crystal of alcove paths of type ['A', 2, 1] and weight Lambda[0]
185
+ sage: x=C( () )
186
+ sage: x.f(0)
187
+ ((alpha[0], 0),)
188
+ sage: C.R
189
+ Root system of type ['A', 2, 1]
190
+ sage: C.weight
191
+ Lambda[0]
192
+
193
+ Test that the tensor products of Kirillov-Reshetikhin crystals
194
+ minus non-pseudo-Demazure arrows is in bijection with alcove path
195
+ construction::
196
+
197
+ sage: K = crystals.KirillovReshetikhin(['B',3,1],2,1)
198
+ sage: T = crystals.TensorProduct(K,K)
199
+ sage: g = T.digraph() #long time
200
+ sage: for e in g.edges(sort=False): #long time
201
+ ....: if e[0].phi(0) == 1 and e[2] == 0:
202
+ ....: g.delete_edge(e)
203
+
204
+ sage: C = crystals.AlcovePaths(['B',3,1],[0,2,0], highest_weight_crystal=False)
205
+ sage: g2 = C.digraph() #long time
206
+ sage: g.is_isomorphic(g2, edge_labels = True) #long time
207
+ True
208
+
209
+ .. NOTE::
210
+
211
+ In type `C_n^{(1)}`, the Kirillov-Reshetikhin crystal is not connected
212
+ when restricted to pseudo-Demazure arrows, hence the previous example will
213
+ fail for type `C_n^{(1)}` crystals.
214
+
215
+ ::
216
+
217
+ sage: R = RootSystem(['B',3])
218
+ sage: P = R.weight_lattice()
219
+ sage: La = P.fundamental_weights()
220
+ sage: D = crystals.AlcovePaths(2*La[2], highest_weight_crystal=False)
221
+ sage: C == D
222
+ True
223
+
224
+ .. WARNING:: Weights from finite root systems index non-highest weight crystals.
225
+ """
226
+
227
+ @staticmethod
228
+ def __classcall_private__(cls, starting_weight, cartan_type=None,
229
+ highest_weight_crystal=None):
230
+ """
231
+ Classcall to mend the input.
232
+
233
+ Internally, the
234
+ :class:`~sage.combinat.crystals.alcove_path.CrystalOfAlcovePaths`
235
+ code works with a ``starting_weight`` that is in the weight space
236
+ associated to the crystal. The user can, however, also input a
237
+ ``cartan_type`` and the coefficients of the fundamental weights as
238
+ ``starting_weight``. This code transforms the input into the right
239
+ format (also necessary for :class:`UniqueRepresentation`).
240
+
241
+ TESTS::
242
+
243
+ sage: C = crystals.AlcovePaths(['A',2,1], [1,0,0])
244
+ sage: C2 = crystals.AlcovePaths(CartanType(['A',2,1]), (1,0,0))
245
+ sage: C is C2
246
+ True
247
+ sage: R = RootSystem(['B',2,1])
248
+ sage: La = R.weight_space().basis()
249
+ sage: B1 = crystals.AlcovePaths(['B',2,1],[0,0,1])
250
+ sage: B2 = crystals.AlcovePaths(La[2])
251
+ sage: B1 is B2
252
+ True
253
+ """
254
+ if isinstance(cartan_type, bool): # new style signature, optional arguments leak over
255
+ highest_weight_crystal = cartan_type
256
+ elif isinstance(cartan_type, (list, tuple)): # old style signature
257
+ # switch positional arguments
258
+ cartan_type, starting_weight = CartanType(starting_weight), cartan_type
259
+
260
+ if highest_weight_crystal is False:
261
+ if not cartan_type.is_affine():
262
+ raise ValueError("non-highest weight crystals only valid for affine types")
263
+ cartan_type = cartan_type.classical()
264
+
265
+ if cartan_type.is_affine():
266
+ extended = True
267
+ else:
268
+ extended = False
269
+
270
+ R = RootSystem(cartan_type)
271
+ P = R.weight_space(extended=extended)
272
+ Lambda = P.basis()
273
+ offset = R.index_set()[Integer(0)]
274
+ starting_weight = P.sum(starting_weight[j - offset] * Lambda[j]
275
+ for j in R.index_set())
276
+
277
+ # set defaults
278
+ if highest_weight_crystal is None:
279
+ highest_weight_crystal = True
280
+
281
+ if not starting_weight.is_dominant():
282
+ raise ValueError("{0} is not a dominant weight".format(starting_weight))
283
+
284
+ return super().__classcall__(cls, starting_weight,
285
+ highest_weight_crystal)
286
+
287
+ def __init__(self, starting_weight, highest_weight_crystal):
288
+ r"""
289
+ Initialize ``self``.
290
+
291
+ TESTS::
292
+
293
+ sage: C = crystals.AlcovePaths(['G',2],[0,1])
294
+ sage: TestSuite(C).run()
295
+
296
+ sage: C = crystals.AlcovePaths(['A',2,1],[1,0,0])
297
+ sage: TestSuite(C).run() #long time
298
+
299
+ sage: C = crystals.AlcovePaths(['A',2,1],[1,0],False)
300
+ sage: TestSuite(C).run(skip='_test_stembridge_local_axioms') #long time
301
+
302
+ Check that :issue:`20292` is fixed::
303
+
304
+ sage: A = crystals.AlcovePaths(['A',2], [1,0])
305
+ sage: A.category()
306
+ Category of classical crystals
307
+ """
308
+ ##########################################################################
309
+ # NOTE:
310
+ # If cartan_type.is_affine() == True and highest weight crystal == False,
311
+ # since we only use the positive roots of the *finite* root system
312
+ # to get the crystal we set self._finite_cartan_type is true
313
+ #
314
+ # We want the indexing set to include 0 so use the affine type notation
315
+ # for the Cartan type.
316
+ ##########################################################################
317
+ cartan_type = starting_weight.parent().cartan_type()
318
+
319
+ self.weight = starting_weight
320
+ self.R = RootSystem(cartan_type)
321
+ self._highest_weight_crystal = highest_weight_crystal
322
+ self._cartan_type = cartan_type
323
+
324
+ if cartan_type.is_finite() and highest_weight_crystal:
325
+ Parent.__init__(self, category=ClassicalCrystals())
326
+ self._R = RootsWithHeight(starting_weight)
327
+ self._finite_cartan_type = True
328
+ elif cartan_type.is_finite() and not highest_weight_crystal:
329
+ Parent.__init__(self, category=LoopCrystals().Finite())
330
+ self._R = RootsWithHeight(starting_weight)
331
+ self._finite_cartan_type = True
332
+ self._cartan_type = cartan_type.affine()
333
+ else:
334
+ assert highest_weight_crystal
335
+ Parent.__init__(self, category=HighestWeightCrystals())
336
+ self._R = RootsWithHeight(starting_weight)
337
+ self._finite_cartan_type = False
338
+
339
+ self.module_generators = (self.element_class(self, ()),)
340
+
341
+ def _repr_(self) -> str:
342
+ """
343
+ Return a string representation of ``self``.
344
+
345
+ EXAMPLES::
346
+
347
+ sage: C = crystals.AlcovePaths(['A',2,1], [1,0,0])
348
+ sage: C
349
+ Highest weight crystal of alcove paths of type ['A', 2, 1] and weight Lambda[0]
350
+ sage: C = crystals.AlcovePaths(['A',2,1], [1,0], False)
351
+ sage: C
352
+ Crystal of alcove paths of type ['A', 2, 1] and weight Lambda[1]
353
+ """
354
+ if self._highest_weight_crystal:
355
+ return "Highest weight crystal of alcove paths of type %s and weight %s" % (self._cartan_type, self.weight)
356
+ return "Crystal of alcove paths of type %s and weight %s" % (self._cartan_type, self.weight)
357
+
358
+ def _element_constructor_(self, data):
359
+ """
360
+ Construct an element of ``self`` from ``data``.
361
+
362
+ EXAMPLES::
363
+
364
+ sage: C = crystals.AlcovePaths(['A',2],[3,2])
365
+ sage: C([8,9])
366
+ ((alpha[1], 2), (alpha[1] + alpha[2], 4))
367
+ """
368
+ if isinstance(data, tuple):
369
+ return self.element_class(self, data)
370
+ elif isinstance(data, list):
371
+ lambda_chain = self._R.lambda_chain()
372
+ # data starts indexing at 0
373
+ return self.element_class(self, tuple(sorted([lambda_chain[i] for i in data])))
374
+
375
+ def vertices(self):
376
+ r"""
377
+ Return a list of all the vertices of the crystal.
378
+
379
+ The vertices are represented as lists of integers recording the folding
380
+ positions.
381
+
382
+ One can compute all vertices of the crystal by finding all the
383
+ admissible subsets of the `\lambda`-chain (see method
384
+ is_admissible, for definition). We use the breadth first
385
+ search algorithm.
386
+
387
+ .. WARNING::
388
+
389
+ This method is (currently) only useful for the case when
390
+ ``highest_weight_crystal = False``, where you cannot always
391
+ reach all vertices of the crystal using crystal operators,
392
+ starting from the highest weight vertex. This method is
393
+ typically slower than generating the crystal graph using
394
+ crystal operators.
395
+
396
+ EXAMPLES::
397
+
398
+ sage: C = crystals.AlcovePaths(['C', 2], [1, 0])
399
+ sage: C.vertices()
400
+ [[], [0], [0, 1], [0, 1, 2]]
401
+ sage: C = crystals.AlcovePaths(['C', 2, 1], [2, 1], False)
402
+ sage: len(C.vertices())
403
+ 80
404
+
405
+ The number of elements reachable using the crystal operators from the
406
+ module generator::
407
+
408
+ sage: len(list(C))
409
+ 55
410
+ """
411
+ lambda_chain = self._R.lambda_chain()
412
+ len_lambda_chain = len(lambda_chain)
413
+ W = WeylGroup(self._R._cartan_type, prefix='s')
414
+ s = W.simple_reflections()
415
+ highest_weight_crystal = self._highest_weight_crystal
416
+
417
+ if highest_weight_crystal:
418
+ successors = 'bruhat_upper_covers'
419
+ else:
420
+ successors = 'quantum_bruhat_successors'
421
+
422
+ # lst contains ordered pairs (w,l) l= list of positions that get
423
+ # you to the word, it needs to be refreshed
424
+
425
+ # initialization
426
+ lst = []
427
+ for i in range(len_lambda_chain):
428
+ associated_reflection = lambda_chain[i].root.associated_reflection()
429
+ if len(associated_reflection) == 1:
430
+ lst.append((prod([s[j] for j in associated_reflection]), [i]))
431
+
432
+ l = copy(lst)
433
+
434
+ while True:
435
+ lst2 = []
436
+ for x in lst:
437
+ suc = getattr(x[0], successors)()
438
+ for j in range(x[1][-1] + 1, len_lambda_chain):
439
+ temp = x[0] * prod(
440
+ [s[k] for k in lambda_chain[j].root.associated_reflection()])
441
+ if temp in suc:
442
+ lst2.append((temp, x[1] + [j]))
443
+ l.append((temp, x[1] + [j]))
444
+ if not lst2:
445
+ break
446
+ else:
447
+ lst = lst2
448
+
449
+ return [[]] + [i[1] for i in l]
450
+
451
+
452
+ class CrystalOfAlcovePathsElement(ElementWrapper):
453
+ """
454
+ Crystal of alcove paths element.
455
+
456
+ INPUT:
457
+
458
+ - ``data`` -- list of folding positions in the lambda chain (indexing
459
+ starts at 0) or a tuple of :class:`RootsWithHeight` giving folding
460
+ positions in the lambda chain.
461
+
462
+ EXAMPLES::
463
+
464
+ sage: C = crystals.AlcovePaths(['A',2],[3,2])
465
+ sage: x = C ( () )
466
+ sage: x.f(1).f(2)
467
+ ((alpha[1], 2), (alpha[1] + alpha[2], 4))
468
+ sage: x.f(1).f(2).integer_sequence()
469
+ [8, 9]
470
+ sage: C([8,9])
471
+ ((alpha[1], 2), (alpha[1] + alpha[2], 4))
472
+ """
473
+
474
+ def __iter__(self):
475
+ r"""
476
+ Initialize ``self``.
477
+
478
+ EXAMPLES::
479
+
480
+ sage: C = crystals.AlcovePaths(['A',2],[1,0])
481
+ sage: lst = list(C)
482
+ sage: for i in lst[2]: i
483
+ (alpha[1], 0)
484
+ (alpha[1] + alpha[2], 0)
485
+ """
486
+ return iter(self.value)
487
+
488
+ def is_admissible(self):
489
+ r"""
490
+ Diagnostic test to check if ``self`` is a valid element of the crystal.
491
+
492
+ If ``self.value`` is given by
493
+
494
+ .. MATH::
495
+
496
+ (\beta_1, i_1), (\beta_2, i_2), \ldots, (\beta_k, i_k),
497
+
498
+ for highest weight crystals this checks if the sequence
499
+
500
+ .. MATH::
501
+
502
+ 1 \rightarrow s_{\beta_1} \rightarrow
503
+ s_{\beta_1}s_{\beta_2} \rightarrow \cdots \rightarrow
504
+ s_{\beta_1}s_{\beta_2} \ldots s_{\beta_k}
505
+
506
+ is a path in the Bruhat graph. If ``highest_weight_crystal=False``,
507
+ then the method checks if the above sequence is a path in the quantum
508
+ Bruhat graph.
509
+
510
+ EXAMPLES::
511
+
512
+ sage: C = crystals.AlcovePaths(['A',2],[1,1]); C
513
+ Highest weight crystal of alcove paths of type ['A', 2] and weight Lambda[1] + Lambda[2]
514
+ sage: roots = sorted(C._R._root_lattice.positive_roots()); roots
515
+ [alpha[1], alpha[1] + alpha[2], alpha[2]]
516
+ sage: r1 = C._R(roots[0],0); r1
517
+ (alpha[1], 0)
518
+ sage: r2 = C._R(roots[2],0); r2
519
+ (alpha[2], 0)
520
+ sage: r3 = C._R(roots[1],1); r3
521
+ (alpha[1] + alpha[2], 1)
522
+ sage: x = C( ( r1,r2) )
523
+ sage: x.is_admissible()
524
+ True
525
+ sage: x = C( (r3,) ); x
526
+ ((alpha[1] + alpha[2], 1),)
527
+ sage: x.is_admissible()
528
+ False
529
+ sage: C = crystals.AlcovePaths(['C',2,1],[2,1],False)
530
+ sage: C([7,8]).is_admissible()
531
+ True
532
+ sage: C = crystals.AlcovePaths(['A',2],[3,2])
533
+ sage: C([2,3]).is_admissible()
534
+ True
535
+
536
+ .. TODO:: Better doctest
537
+ """
538
+ W = WeylGroup(self.parent()._R._cartan_type, prefix='s')
539
+ s = W.simple_reflections()
540
+ highest_weight_crystal = self.parent()._highest_weight_crystal
541
+
542
+ if highest_weight_crystal:
543
+ successors = 'bruhat_upper_covers'
544
+ else:
545
+ successors = 'quantum_bruhat_successors'
546
+
547
+ # start at the identity
548
+ w = W.one()
549
+ for i in self:
550
+ t = prod([s[j] for j in i.root.associated_reflection()])
551
+ successor = w * t
552
+ if successor not in getattr(w, successors)():
553
+ return False
554
+ w = successor
555
+ return True
556
+
557
+ def _latex_(self):
558
+ r"""
559
+ Return a `\LaTeX` representation of ``self``.
560
+
561
+ EXAMPLES::
562
+
563
+ sage: C = crystals.AlcovePaths(['A',2],[1,1])
564
+ sage: C([1,2])._latex_()
565
+ [(\alpha_{1} + \alpha_{2}, 0), (\alpha_{1}, 0)]
566
+ """
567
+ return [(latex(i.root), i.height) for i in self.value]
568
+
569
+ @cached_in_parent_method
570
+ def integer_sequence(self):
571
+ r"""
572
+ Return a list of integers corresponding to positions in
573
+ the `\lambda`-chain where it is folded.
574
+
575
+ .. TODO::
576
+
577
+ Incorporate this method into the ``_repr_`` for finite Cartan type.
578
+
579
+ .. NOTE::
580
+
581
+ Only works for finite Cartan types and indexing starts at 0.
582
+
583
+ EXAMPLES::
584
+
585
+ sage: C = crystals.AlcovePaths(['A',2],[3,2])
586
+ sage: x = C( () )
587
+ sage: x.f(1).f(2).integer_sequence()
588
+ [8, 9]
589
+ """
590
+ lambda_chain = self.parent()._R.lambda_chain()
591
+ return [lambda_chain.index(j) for j in self.value]
592
+
593
+ def phi(self, i):
594
+ r"""
595
+ Return the distance to the end of the `i`-string.
596
+
597
+ This method overrides the generic implementation in the category of
598
+ crystals since this computation is more efficient.
599
+
600
+ EXAMPLES::
601
+
602
+ sage: C = crystals.AlcovePaths(['A',2],[1,1])
603
+ sage: [c.phi(1) for c in C]
604
+ [1, 0, 0, 1, 0, 2, 1, 0]
605
+ sage: [c.phi(2) for c in C]
606
+ [1, 2, 1, 0, 0, 0, 0, 1]
607
+ """
608
+ highest_weight_crystal = self.parent()._highest_weight_crystal
609
+ positions, gi = self._gi(i)
610
+
611
+ m = max(gi)
612
+
613
+ if not highest_weight_crystal and i == 0:
614
+ raise NotImplementedError
615
+ # I think the M below should still work in this case
616
+
617
+ return Integer(m) / 2 - Integer(1) / 2
618
+
619
+ def epsilon(self, i):
620
+ r"""
621
+ Return the distance to the start of the `i`-string.
622
+
623
+ EXAMPLES::
624
+
625
+ sage: C = crystals.AlcovePaths(['A',2],[1,1])
626
+ sage: [c.epsilon(1) for c in C]
627
+ [0, 1, 0, 0, 1, 0, 1, 2]
628
+ sage: [c.epsilon(2) for c in C]
629
+ [0, 0, 1, 2, 1, 1, 0, 0]
630
+ """
631
+ # crude but functional
632
+ j = 0
633
+ temp = self
634
+ temp = temp.e(i)
635
+ while temp is not None:
636
+ j += 1
637
+ temp = temp.e(i)
638
+
639
+ return j
640
+
641
+ def weight(self):
642
+ """
643
+ Return the weight of ``self``.
644
+
645
+ EXAMPLES::
646
+
647
+ sage: C = crystals.AlcovePaths(['A',2],[2,0])
648
+ sage: for i in C: i.weight()
649
+ (2, 0, 0)
650
+ (1, 1, 0)
651
+ (0, 2, 0)
652
+ (0, -1, 0)
653
+ (-1, 0, 0)
654
+ (-2, -2, 0)
655
+ sage: B = crystals.AlcovePaths(['A',2,1],[1,0,0])
656
+ sage: p = B.module_generators[0].f_string([0,1,2])
657
+ sage: p.weight()
658
+ Lambda[0] - delta
659
+
660
+ TESTS:
661
+
662
+ Check that crystal morphisms work (:issue:`19481`)::
663
+
664
+ sage: C1 = crystals.AlcovePaths(['A',2],[1,0])
665
+ sage: C2 = crystals.AlcovePaths(['A',2],[2,0])
666
+ sage: phi = C1.crystal_morphism(C2.module_generators, scaling_factors={1:2, 2:2})
667
+ sage: [phi(x) for x in C1]
668
+ [(), ((alpha[1], 0),), ((alpha[1], 0), (alpha[1] + alpha[2], 0))]
669
+
670
+ Check that all weights are of level 0 in the KR crystal setting
671
+ (:issue:`20292`)::
672
+
673
+ sage: A = crystals.AlcovePaths(['A',2,1], [1,0], highest_weight_crystal=False)
674
+ sage: all(x.weight().level() == 0 for x in A)
675
+ True
676
+ """
677
+ root_space = self.parent().R.root_space()
678
+ weight = -self.parent().weight
679
+ for i in self.value[::-1]:
680
+ root = root_space(i.root)
681
+ weight = -i.height * root + weight.reflection(root)
682
+
683
+ WLR = self.parent().weight_lattice_realization()
684
+ if self.cartan_type().is_affine() and self.parent()._highest_weight_crystal:
685
+ # We assume that WLR is the (extended) weight lattice
686
+ wt = WLR._from_dict({i: Integer(c) for i, c in -weight},
687
+ remove_zeros=False)
688
+ return wt
689
+ La = WLR.fundamental_weights()
690
+ wt = WLR.sum(Integer(c) * La[i] for i, c in -weight)
691
+ if self.cartan_type().is_affine():
692
+ assert not self.parent()._highest_weight_crystal
693
+ wt -= La[0] * wt.level()
694
+ return wt
695
+
696
+ def plot(self):
697
+ r"""
698
+ Return a plot ``self``.
699
+
700
+ .. NOTE::
701
+
702
+ Currently only implemented for types `A_2`, `B_2`, and `C_2`.
703
+
704
+ EXAMPLES::
705
+
706
+ sage: C = crystals.AlcovePaths(['A',2],[2,0])
707
+ sage: x = C( () ).f(1).f(2)
708
+ sage: x.plot() # Not tested - creates a pdf
709
+ """
710
+ ct = self.parent()._R._cartan_type.dual()
711
+ word = self.parent()._R.word()
712
+ integer_sequence = self.integer_sequence()
713
+ foldings = [False for i in word]
714
+ for i in integer_sequence:
715
+ foldings[i] = True
716
+ affine_ambient_space = RootSystem(ct.affine()).ambient_space()
717
+ return affine_ambient_space.plot() + affine_ambient_space.plot_alcove_walk(word, foldings=foldings, labels=False)
718
+
719
+ def _richcmp_(self, other, op):
720
+ r"""
721
+ Comparison of ``self.value`` and ``other.value``.
722
+
723
+ For inequalities, ``self.value`` is compared to
724
+ ``other.value`` in dictionary order.
725
+
726
+ EXAMPLES::
727
+
728
+ sage: C = crystals.AlcovePaths(['B',2],[1,0])
729
+ sage: lst = list(C)
730
+ sage: lst[2] == lst[2]
731
+ True
732
+ sage: lst[2] == lst[1]
733
+ False
734
+ sage: lst[2] != lst[2]
735
+ False
736
+ sage: lst[2] != lst[1]
737
+ True
738
+
739
+ sage: C = crystals.AlcovePaths(['A',2],[2,0])
740
+ sage: x = C(())
741
+ sage: x < x.f(1)
742
+ True
743
+ sage: a = x.f(1) ; b = x.f(1).f(1).f(2)
744
+ sage: a < b
745
+ False
746
+
747
+ sage: C = crystals.AlcovePaths(['A',2],[2,0])
748
+ sage: x = C( () )
749
+ sage: x > x.f(1)
750
+ False
751
+ sage: a = x.f(1) ; b = x.f(1).f(1).f(2)
752
+ sage: a > b
753
+ True
754
+ """
755
+ return richcmp(self.value, other.value, op)
756
+
757
+ def __hash__(self):
758
+ """
759
+ Return the hash of ``self``.
760
+
761
+ EXAMPLES::
762
+
763
+ sage: C = crystals.AlcovePaths(['B',2],[1,0])
764
+ sage: lst = list(C)
765
+ sage: hash(lst[2]) == hash(lst[2])
766
+ True
767
+ """
768
+ return hash(self.value)
769
+
770
+ def _folding_data(self, i):
771
+ r"""
772
+ Compute information needed to build the graph `g_{\alpha_i}`.
773
+ Results of this method are sent to _gi for further processing.
774
+
775
+ INPUT:
776
+
777
+ - ``i`` -- element of the index_set of the underlying root_system
778
+
779
+ OUTPUT:
780
+
781
+ A dictionary where the keys are of type RootsWithHeight which record
782
+ positions where `\pm \alpha_i` shows up in the folded `\lambda` chain.
783
+ The values are `1` if `\alpha_i` is in the corresponding position in
784
+ the folded `\lambda`-chain, `-1` if `-\alpha_i` is in the corresponding
785
+ position in the folded `\lambda`-chain.
786
+
787
+ .. NOTE::
788
+
789
+ *infinity* is a special key that records the "sign at infinity".
790
+
791
+ ::
792
+
793
+ sage: C = crystals.AlcovePaths(['A',2],[1,1])
794
+ sage: x = C( () ).f(1)
795
+ sage: fd = x._folding_data(2); fd # # random output
796
+ {(alpha[2], 0): 1, (alpha[1] + alpha[2], 1): 1, 'infinity': 1}
797
+ sage: fd['infinity']
798
+ 1
799
+ sage: sorted(fd.values())
800
+ [1, 1, 1]
801
+ """
802
+ Parent = self.parent()
803
+
804
+ # self.value contains the admissible sequence as a tuple of Element
805
+
806
+ finite_cartan_type = Parent._finite_cartan_type # bool
807
+ J = list(self.value)
808
+
809
+ # NOTE: R is a RootsWithHeight object and NOT a RootSystem object
810
+ R = Parent._R
811
+ weight = Parent.weight
812
+
813
+ signs = {}
814
+
815
+ # 0 arrows in the case of finite Cartan type
816
+ # always allow 0 arrows
817
+ if finite_cartan_type and i == 0:
818
+ Beta = R._root_lattice.highest_root()
819
+ elif i in self.index_set():
820
+ Beta = R._root_lattice.simple_root(i)
821
+
822
+ max_height_Beta = weight.scalar(Beta.associated_coroot())
823
+
824
+ if not J:
825
+ for k in range(max_height_Beta):
826
+ x = R(Beta, k)
827
+ signs[x] = self._sign(Beta)
828
+ signs['infinity'] = self._sign(Beta)
829
+
830
+ else:
831
+ # NOTE: we assume J is sorted by order on Element of RootsWithHeight
832
+
833
+ for k in range(max_height_Beta):
834
+ x = R(Beta, k)
835
+ if x <= J[0]:
836
+ signs[x] = self._sign(Beta)
837
+
838
+ for j in range(len(J)):
839
+ Beta = Beta.reflection(J[j].root)
840
+ sign_Beta = self._sign(Beta)
841
+ max_height_Beta = weight.scalar(
842
+ (sign_Beta * Beta).associated_coroot())
843
+
844
+ # some optimization so we don't initialize too many objects
845
+ # range(c1,c2) can be replaced by range(max_height_Beta) but it
846
+ # checks unnecessary extra things
847
+
848
+ c1 = J[j]._cmp_v[0] * max_height_Beta
849
+ if j == len(J) - 1:
850
+ c2 = max_height_Beta
851
+ else:
852
+ c2 = min(max_height_Beta, J[j+1]._cmp_v[0]*max_height_Beta + 1)
853
+
854
+ for k in range(int(c1), int(c2)):
855
+
856
+ x = R(sign_Beta * Beta, k)
857
+
858
+ if (
859
+ (j < len(J) - 1 and J[j] < x <= J[j + 1]) or
860
+ (j == len(J) - 1 and J[j] < x)
861
+ ):
862
+ signs[x] = sign_Beta
863
+
864
+ signs['infinity'] = sign_Beta
865
+ # tail sign tells something about last step in g_alpha
866
+
867
+ if finite_cartan_type and i == 0:
868
+ signs = {x: -signs[x] for x in signs}
869
+
870
+ return signs
871
+
872
+ def e(self, i):
873
+ r"""
874
+ Return the `i`-th crystal raising operator on ``self``.
875
+
876
+ INPUT:
877
+
878
+ - ``i`` -- element of the index set of the underlying root system
879
+
880
+ EXAMPLES::
881
+
882
+ sage: C = crystals.AlcovePaths(['A',2],[2,0]); C
883
+ Highest weight crystal of alcove paths of type ['A', 2] and weight 2*Lambda[1]
884
+ sage: x = C( () )
885
+ sage: x.e(1)
886
+ sage: x.f(1) == x.f(1).f(2).e(2)
887
+ True
888
+ """
889
+ Parent = self.parent()
890
+ finite_cartan_type = Parent._finite_cartan_type
891
+
892
+ J = list(self.value)
893
+ positions, gi = self._gi(i)
894
+
895
+ m = max(gi)
896
+ m_index = len(gi)-1-list(reversed(gi)).index(m) # last max in gi
897
+
898
+ if finite_cartan_type and i == 0:
899
+ M = Integer(m)/2 + Integer(1)/2
900
+ else:
901
+ M = Integer(m)/2 - Integer(1)/2
902
+
903
+ KR_test = finite_cartan_type and i == 0 and m_index < len(gi) - 1
904
+ KR_test = KR_test and M >= 1
905
+
906
+ ###################################################################
907
+ # NOTE:
908
+ # In the KR_case we want to insure that positions[m_index] is in J
909
+ # If m_index > 0 then it's always true
910
+ # If m_index == 0 then M >=1 guarantees this
911
+ ###################################################################
912
+
913
+ if ((not finite_cartan_type or i != 0) and m_index < len(gi) - 1) or KR_test:
914
+ # first condition above means that alpha_i is a simple root
915
+
916
+ J.remove(positions[m_index])
917
+ if m_index + 1 < len(positions):
918
+ # if m_index+1 != 'infinity'
919
+ # i.e. positions[m_index+1] makes sense
920
+ J.append(positions[m_index + 1])
921
+ return_value = Parent(tuple(sorted(J)))
922
+
923
+ # we attach to each admissible sequence a list
924
+ # which encodes a path (via root operators) from the () generator
925
+ # to the admissible sequence
926
+ # this is useful for investing the crystal
927
+
928
+ try:
929
+ return_value.i_string = self.i_string + [['e', i]]
930
+ except AttributeError:
931
+ return_value.i_string = [['e', i]]
932
+
933
+ return return_value
934
+ else:
935
+ return None
936
+
937
+ @cached_method
938
+ def _gi(self, i):
939
+ r"""
940
+ Compute information needed to build the graph `g_{\alpha_i}`.
941
+ This graph is used to apply the `i`-th crystal operator.
942
+
943
+ INPUT:
944
+
945
+ - ``i`` -- element of the index_set of the underlying root_system
946
+
947
+ OUTPUT:
948
+
949
+ A tuple ``(positions, gi)``:
950
+
951
+ - ``positions`` -- is a list of RootsWithHeight. These appear sorted in
952
+ their natural order, and record where `\pm \alpha_i` shows up in
953
+ the folded `\lambda`-chain.
954
+
955
+ - ``gi`` -- is a list of integers recording the height
956
+ (up to affine transformation) of `\pm \alpha_i`
957
+ in the folded `\lambda`-chain whose location is recorded by
958
+ ``positions``.
959
+
960
+ .. NOTE::
961
+
962
+ - ``positions`` has length one less than ``gi`` since it does not
963
+ contain the position 'infinity'.
964
+
965
+ - To get the real `g_{\alpha_i}` one has to divide by 2 and add 1/2
966
+ or divide by 2 and subtract 1/2 depending on if
967
+ ``self._finite_cartan_type==True and i == 0``
968
+ or not. This is done in crystal operator methods.
969
+
970
+ EXAMPLES::
971
+
972
+ sage: C=crystals.AlcovePaths(['A',2],[1,1])
973
+ sage: x=C( () ).f(1)
974
+ sage: x._gi(2)
975
+ ([(alpha[2], 0), (alpha[1] + alpha[2], 1)], [1, 3, 5])
976
+ """
977
+ signs = self._folding_data(i)
978
+ positions = sorted(x for x in signs if x != 'infinity')
979
+
980
+ if not positions:
981
+ return (positions, [signs['infinity']])
982
+
983
+ gi = [signs[positions[0]]]
984
+ for j in range(1, len(positions)):
985
+ gi.append(
986
+ gi[j-1] +
987
+ signs[positions[j-1]] * self._eps(positions[j-1]) +
988
+ signs[positions[j]])
989
+ gi.append(gi[-1] +
990
+ signs[positions[-1]] * self._eps(positions[-1]) +
991
+ signs['infinity'])
992
+
993
+ return (positions, gi)
994
+
995
+ def f(self, i):
996
+ r"""
997
+ Return the `i`-th crystal lowering operator on ``self``.
998
+
999
+ INPUT:
1000
+
1001
+ - ``i`` -- element of the index_set of the underlying root_system
1002
+
1003
+ EXAMPLES::
1004
+
1005
+ sage: C=crystals.AlcovePaths(['B',2],[1,1])
1006
+ sage: x=C( () )
1007
+ sage: x.f(1)
1008
+ ((alpha[1], 0),)
1009
+ sage: x.f(1).f(2)
1010
+ ((alpha[1], 0), (alpha[1] + alpha[2], 2))
1011
+ """
1012
+ Parent = self.parent()
1013
+ finite_cartan_type = Parent._finite_cartan_type
1014
+
1015
+ # get a copy in a form of a list of self.value
1016
+ J = list(self.value)
1017
+ positions, gi = self._gi(i)
1018
+
1019
+ m = max(gi)
1020
+ m_index = gi.index(m)
1021
+
1022
+ if finite_cartan_type and i == 0:
1023
+
1024
+ # python doesn't handle fractions natively
1025
+ M = Integer(m)/2 + Integer(1)/2
1026
+ else:
1027
+ M = Integer(m)/2 - Integer(1)/2
1028
+
1029
+ # boolean determining when to move a folding in KR case
1030
+ KR_test = finite_cartan_type and i == 0
1031
+ KR_test = KR_test and M > 1
1032
+
1033
+ # In the KR case, we return a value other than None when
1034
+ # `\alpha_i` is in position m_index - 1
1035
+ # (The following relies on a technical condition (C2) )
1036
+ # note insert reference
1037
+ #
1038
+ # if m_index - 1 == 0 then M > 1 and (C2) forces
1039
+ # `\alhpa_i` in positions[m_index - 1]
1040
+ #
1041
+ # otherwise if m_index - 1 > 0 then (C2) is enough
1042
+
1043
+ if ((not finite_cartan_type or i != 0) and M > 0) or KR_test:
1044
+ # first condition above means that alpha_i is a simple root
1045
+
1046
+ J.append(positions[m_index - 1])
1047
+ if m_index < len(positions):
1048
+ # if m_index != 'infinity'
1049
+ # thus positions[m_index] makes sense
1050
+ J.remove(positions[m_index])
1051
+ return_value = Parent(tuple(sorted(J)))
1052
+
1053
+ # we attach to each admissible sequence a list
1054
+ # which encodes a path (via root operators) from the generator ()
1055
+
1056
+ try:
1057
+ return_value.i_string = self.i_string + [['f', i]]
1058
+ except AttributeError:
1059
+ return_value.i_string = [['f', i]]
1060
+
1061
+ return return_value
1062
+ else:
1063
+ return None
1064
+
1065
+ @staticmethod
1066
+ def _sign(root):
1067
+ r"""
1068
+ Return `1` if root is a positive root, and `-1` if root is a negative
1069
+ root.
1070
+
1071
+ EXAMPLES::
1072
+
1073
+ sage: from sage.combinat.crystals.alcove_path import CrystalOfAlcovePathsElement
1074
+ sage: rl = RootSystem(['A',2]).root_lattice()
1075
+ sage: x = rl.from_vector(vector([0,1]))
1076
+ sage: CrystalOfAlcovePathsElement._sign(x)
1077
+ 1
1078
+ """
1079
+ if root.is_positive_root():
1080
+ return 1
1081
+ else:
1082
+ return -1
1083
+
1084
+ def _eps(self, root):
1085
+ r"""
1086
+ Return `-1` if root is in ``self.value``, otherwise return `1`.
1087
+
1088
+ EXAMPLES::
1089
+
1090
+ sage: C = crystals.AlcovePaths(['C',2],[3,2])
1091
+ sage: x = C( () ).f(1).f(2); x
1092
+ ((alpha[1], 2), (2*alpha[1] + alpha[2], 4))
1093
+ sage: x._eps(x.value[0])
1094
+ -1
1095
+ sage: R = C._R
1096
+ sage: y = R ( x.value[0].root, 1 ); y
1097
+ (alpha[1], 1)
1098
+ sage: x._eps(y)
1099
+ 1
1100
+ """
1101
+ if root in self.value:
1102
+ return -1
1103
+ else:
1104
+ return 1
1105
+
1106
+ def path(self):
1107
+ """
1108
+ Return the path in the (quantum) Bruhat graph corresponding
1109
+ to ``self``.
1110
+
1111
+ EXAMPLES::
1112
+
1113
+ sage: C = crystals.AlcovePaths(['B', 3], [3,1,2])
1114
+ sage: b = C.highest_weight_vector().f_string([1,3,2,1,3,1])
1115
+ sage: b.path()
1116
+ [1, s1, s3*s1, s2*s3*s1, s3*s2*s3*s1]
1117
+ sage: b = C.highest_weight_vector().f_string([2,3,3,2])
1118
+ sage: b.path()
1119
+ [1, s2, s3*s2, s2*s3*s2]
1120
+ sage: b = C.highest_weight_vector().f_string([2,3,3,2,1])
1121
+ sage: b.path()
1122
+ [1, s2, s3*s2, s2*s3*s2, s1*s2*s3*s2]
1123
+ """
1124
+ W = WeylGroup(self.parent()._R._cartan_type, prefix='s')
1125
+ s = W.simple_reflections()
1126
+
1127
+ # start at the identity
1128
+ w = W.one()
1129
+ ret = [w]
1130
+ for i in self:
1131
+ ret.append(ret[-1] * prod(s[j] for j in i.root.associated_reflection()))
1132
+ return ret
1133
+
1134
+
1135
+ CrystalOfAlcovePaths.Element = CrystalOfAlcovePathsElement
1136
+
1137
+
1138
+ class InfinityCrystalOfAlcovePaths(UniqueRepresentation, Parent):
1139
+ r"""
1140
+ `\mathcal{B}(\infty)` crystal of alcove paths.
1141
+ """
1142
+ @staticmethod
1143
+ def __classcall_private__(cls, cartan_type):
1144
+ """
1145
+ Normalize input to ensure a unique representation.
1146
+
1147
+ TESTS::
1148
+
1149
+ sage: A1 = crystals.infinity.AlcovePaths(['A',2])
1150
+ sage: A2 = crystals.infinity.AlcovePaths(CartanType(['A',2]))
1151
+ sage: A3 = crystals.infinity.AlcovePaths('A2')
1152
+ sage: A1 is A2 and A2 is A3
1153
+ True
1154
+ """
1155
+ cartan_type = CartanType(cartan_type)
1156
+ return super().__classcall__(cls, cartan_type)
1157
+
1158
+ def __init__(self, cartan_type):
1159
+ """
1160
+ Initialize ``self``.
1161
+
1162
+ TESTS::
1163
+
1164
+ sage: A = crystals.infinity.AlcovePaths(['C',3])
1165
+ sage: TestSuite(A).run(max_runs=20)
1166
+
1167
+ sage: A = crystals.infinity.AlcovePaths(['A',2,1])
1168
+ sage: TestSuite(A).run() # long time
1169
+ """
1170
+ self._cartan_type = cartan_type
1171
+ Parent.__init__(self, category=HighestWeightCrystals().Infinite())
1172
+
1173
+ self.module_generators = (self.element_class(self, (), 0),)
1174
+
1175
+ def _repr_(self) -> str:
1176
+ """
1177
+ Return a string representation of ``self``.
1178
+
1179
+ EXAMPLES::
1180
+
1181
+ sage: crystals.infinity.AlcovePaths(['E',6])
1182
+ Infinity crystal of alcove paths of type ['E', 6]
1183
+ """
1184
+ return "Infinity crystal of alcove paths of type {}".format(self._cartan_type)
1185
+
1186
+ class Element(ElementWrapper):
1187
+ def __init__(self, parent, elt, shift):
1188
+ """
1189
+ Initialize ``self``.
1190
+
1191
+ EXAMPLES::
1192
+
1193
+ sage: A = crystals.infinity.AlcovePaths(['F',4])
1194
+ sage: mg = A.highest_weight_vector()
1195
+ sage: x = mg.f_string([2,3,1,4,4,2,3,1])
1196
+ sage: TestSuite(x).run()
1197
+ """
1198
+ ElementWrapper.__init__(self, parent, elt)
1199
+ self._shift = shift
1200
+
1201
+ def e(self, i):
1202
+ """
1203
+ Return the action of `e_i` on ``self``.
1204
+
1205
+ INPUT:
1206
+
1207
+ - ``i`` -- an element of the index set
1208
+
1209
+ EXAMPLES::
1210
+
1211
+ sage: A = crystals.infinity.AlcovePaths(['D',5,1])
1212
+ sage: mg = A.highest_weight_vector()
1213
+ sage: x = mg.f_string([1,3,4,2,5,4,5,5])
1214
+ sage: x.f(4).e(5) == x.e(5).f(4)
1215
+ True
1216
+ """
1217
+ y = self.projection().e(i)
1218
+ if y is None:
1219
+ return None
1220
+ if not y.value:
1221
+ return self.parent().module_generators[0]
1222
+
1223
+ n = self.parent()._cartan_type.rank()
1224
+ s = lambda rt: int(sum(rt.associated_coroot().coefficients()))
1225
+ shift = self._shift
1226
+ while y.is_admissible():
1227
+ # The only element with a shift of 0 is the highest weight element.
1228
+ # So we do not need to check for the shift being 0.
1229
+ prev = y
1230
+ shift -= 1
1231
+ A = CrystalOfAlcovePaths(self.parent()._cartan_type, [shift]*n)
1232
+ try:
1233
+ y = A(tuple([A._R(rt.root, rt.height - s(rt.root)) for rt in y.value]))
1234
+ except ValueError: # Invalid height (and not admissible)
1235
+ break
1236
+ shift += 1
1237
+ return type(self)(self.parent(),
1238
+ tuple([(rt.root, rt.height - shift*s(rt.root))
1239
+ for rt in prev.value]),
1240
+ shift)
1241
+
1242
+ def f(self, i):
1243
+ """
1244
+ Return the action of `f_i` on ``self``.
1245
+
1246
+ INPUT:
1247
+
1248
+ - ``i`` -- an element of the index set
1249
+
1250
+ EXAMPLES::
1251
+
1252
+ sage: A = crystals.infinity.AlcovePaths(['E',7,1])
1253
+ sage: mg = A.highest_weight_vector()
1254
+ sage: mg.f_string([1,3,5,6,4,2,0,2,1,0,2,4,7,4,2])
1255
+ ((alpha[2], -3), (alpha[5], -1), (alpha[1], -1),
1256
+ (alpha[0] + alpha[1], -2),
1257
+ (alpha[2] + alpha[4] + alpha[5], -2),
1258
+ (alpha[5] + alpha[6], -1), (alpha[1] + alpha[3], -1),
1259
+ (alpha[5] + alpha[6] + alpha[7], -1),
1260
+ (alpha[0] + alpha[1] + alpha[3], -1),
1261
+ (alpha[1] + alpha[3] + alpha[4] + alpha[5], -1))
1262
+ """
1263
+ s = lambda rt: int(sum(rt.associated_coroot().coefficients()))
1264
+ y = self.projection().f(i)
1265
+ if y is not None:
1266
+ return type(self)(self.parent(),
1267
+ tuple([(rt.root, rt.height - self._shift*s(rt.root))
1268
+ for rt in y.value]),
1269
+ self._shift)
1270
+
1271
+ shift = self._shift + 1
1272
+ n = self.parent()._cartan_type.rank()
1273
+ A = CrystalOfAlcovePaths(self.parent()._cartan_type, [shift]*n)
1274
+ y = A(tuple([A._R(rt, h + shift*s(rt)) for rt, h in self.value])).f(i)
1275
+ return type(self)(self.parent(),
1276
+ tuple([(rt.root, rt.height - shift*s(rt.root))
1277
+ for rt in y.value]),
1278
+ shift)
1279
+
1280
+ def epsilon(self, i):
1281
+ r"""
1282
+ Return `\varepsilon_i` of ``self``.
1283
+
1284
+ INPUT:
1285
+
1286
+ - ``i`` -- an element of the index set
1287
+
1288
+ EXAMPLES::
1289
+
1290
+ sage: A = crystals.infinity.AlcovePaths(['A',7,2])
1291
+ sage: mg = A.highest_weight_vector()
1292
+ sage: x = mg.f_string([1,0,2,3,4,4,4,2,3,3,3])
1293
+ sage: [x.epsilon(i) for i in A.index_set()]
1294
+ [0, 0, 0, 3, 0]
1295
+ sage: x = mg.f_string([2,2,1,1,0,1,0,2,3,3,3,4])
1296
+ sage: [x.epsilon(i) for i in A.index_set()]
1297
+ [1, 2, 0, 1, 1]
1298
+ """
1299
+ return self.projection().epsilon(i)
1300
+
1301
+ def phi(self, i):
1302
+ r"""
1303
+ Return `\varphi_i` of ``self``.
1304
+
1305
+ Let `A \in \mathcal{B}(\infty)` Define `\varphi_i(A) :=
1306
+ \varepsilon_i(A) + \langle h_i, \mathrm{wt}(A) \rangle`,
1307
+ where `h_i` is the `i`-th simple coroot and `\mathrm{wt}(A)`
1308
+ is the :meth:`weight` of `A`.
1309
+
1310
+ INPUT:
1311
+
1312
+ - ``i`` -- an element of the index set
1313
+
1314
+ EXAMPLES::
1315
+
1316
+ sage: A = crystals.infinity.AlcovePaths(['A',8,2])
1317
+ sage: mg = A.highest_weight_vector()
1318
+ sage: x = mg.f_string([1,0,2,3,4,4,4,2,3,3,3])
1319
+ sage: [x.phi(i) for i in A.index_set()]
1320
+ [1, 1, 1, 3, -2]
1321
+ sage: x = mg.f_string([2,2,1,1,0,1,0,2,3,3,3,4])
1322
+ sage: [x.phi(i) for i in A.index_set()]
1323
+ [4, -1, 0, 0, 2]
1324
+ """
1325
+ P = self.parent().weight_lattice_realization()
1326
+ h = P.simple_coroots()
1327
+ return self.epsilon(i) + P(self.weight()).scalar(h[i])
1328
+
1329
+ def weight(self):
1330
+ """
1331
+ Return the weight of ``self``.
1332
+
1333
+ EXAMPLES::
1334
+
1335
+ sage: A = crystals.infinity.AlcovePaths(['E',6])
1336
+ sage: mg = A.highest_weight_vector()
1337
+ sage: fstr = [1,3,4,2,1,2,3,6,5,3,2,6,2]
1338
+ sage: x = mg.f_string(fstr)
1339
+ sage: al = A.weight_lattice_realization().simple_roots()
1340
+ sage: x.weight() == -sum(al[i]*fstr.count(i) for i in A.index_set())
1341
+ True
1342
+ """
1343
+ P = self.parent().weight_lattice_realization()
1344
+ y = self.projection()
1345
+ return y.weight() - self._shift * P.rho()
1346
+
1347
+ def projection(self, k=None):
1348
+ r"""
1349
+ Return the projection ``self`` onto `B(k \rho)`.
1350
+
1351
+ INPUT:
1352
+
1353
+ - ``k`` -- (optional) if not given, defaults to the smallest
1354
+ value such that ``self`` is not ``None`` under the projection
1355
+
1356
+ EXAMPLES::
1357
+
1358
+ sage: A = crystals.infinity.AlcovePaths(['G',2])
1359
+ sage: mg = A.highest_weight_vector()
1360
+ sage: x = mg.f_string([2,1,1,2,2,2,1,1]); x
1361
+ ((alpha[2], -3), (alpha[1] + alpha[2], -3),
1362
+ (3*alpha[1] + 2*alpha[2], -1), (2*alpha[1] + alpha[2], -1))
1363
+ sage: x.projection()
1364
+ ((alpha[2], 0), (alpha[1] + alpha[2], 9),
1365
+ (3*alpha[1] + 2*alpha[2], 8), (2*alpha[1] + alpha[2], 14))
1366
+ sage: x.projection().parent()
1367
+ Highest weight crystal of alcove paths of type ['G', 2]
1368
+ and weight 3*Lambda[1] + 3*Lambda[2]
1369
+
1370
+ sage: mg.projection().parent()
1371
+ Highest weight crystal of alcove paths of type ['G', 2]
1372
+ and weight 0
1373
+ sage: mg.f(1).projection().parent()
1374
+ Highest weight crystal of alcove paths of type ['G', 2]
1375
+ and weight Lambda[1] + Lambda[2]
1376
+ sage: mg.f(1).f(2).projection().parent()
1377
+ Highest weight crystal of alcove paths of type ['G', 2]
1378
+ and weight Lambda[1] + Lambda[2]
1379
+ sage: b = mg.f_string([1,2,2,1,2])
1380
+ sage: b.projection().parent()
1381
+ Highest weight crystal of alcove paths of type ['G', 2]
1382
+ and weight 2*Lambda[1] + 2*Lambda[2]
1383
+ sage: b.projection(3).parent()
1384
+ Highest weight crystal of alcove paths of type ['G', 2]
1385
+ and weight 3*Lambda[1] + 3*Lambda[2]
1386
+ sage: b.projection(1)
1387
+ """
1388
+ if k is None:
1389
+ k = self._shift
1390
+ elif k < self._shift:
1391
+ return None
1392
+ s = lambda rt: int(sum(rt.associated_coroot().coefficients()))
1393
+ n = self.parent()._cartan_type.rank()
1394
+ A = CrystalOfAlcovePaths(self.parent()._cartan_type, [k] * n)
1395
+ return A(tuple([A._R(rt, h + k*s(rt)) for rt, h in self.value]))
1396
+
1397
+
1398
+ class RootsWithHeight(UniqueRepresentation, Parent):
1399
+ r"""
1400
+ Data structure of the ordered pairs `(\beta,k)`,
1401
+ where `\beta` is a positive root and `k` is a nonnegative integer. A total
1402
+ order is implemented on this set, and depends on the weight.
1403
+
1404
+ INPUT:
1405
+
1406
+ - ``cartan_type`` -- Cartan type of a finite or affine untwisted root
1407
+ system
1408
+
1409
+ - ``weight`` -- dominant weight as a list of (integral) coefficients of
1410
+ the fundamental weights
1411
+
1412
+ EXAMPLES::
1413
+
1414
+ sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
1415
+ sage: R = RootsWithHeight(['A',2],[1,1]); R
1416
+ Roots with height of Cartan type ['A', 2] and dominant weight Lambda[1] + Lambda[2]
1417
+
1418
+ sage: r1 = R._root_lattice.from_vector(vector([1,0])); r1
1419
+ alpha[1]
1420
+ sage: r2 = R._root_lattice.from_vector(vector([1,1])); r2
1421
+ alpha[1] + alpha[2]
1422
+
1423
+ sage: x = R(r1,0); x
1424
+ (alpha[1], 0)
1425
+ sage: y = R(r2,1); y
1426
+ (alpha[1] + alpha[2], 1)
1427
+ sage: x < y
1428
+ True
1429
+ """
1430
+
1431
+ @staticmethod
1432
+ def __classcall_private__(cls, starting_weight, cartan_type=None):
1433
+ """
1434
+ Classcall to mend the input.
1435
+
1436
+ Internally, the RootsWithHeight code works with a ``starting_weight`` that
1437
+ is in the ``weight_space`` associated to the crystal. The user can, however,
1438
+ also input a ``cartan_type`` and the coefficients of the fundamental weights
1439
+ as ``starting_weight``. This code transforms the input into the right
1440
+ format (also necessary for UniqueRepresentation).
1441
+
1442
+ TESTS::
1443
+
1444
+ sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
1445
+ sage: R = RootsWithHeight(['A',2],[3,2])
1446
+ sage: S = RootsWithHeight(CartanType(['A',2]), (3,2))
1447
+ sage: R is S
1448
+ True
1449
+
1450
+ sage: R = RootSystem(['B',2,1])
1451
+ sage: La = R.weight_space().basis()
1452
+ sage: C = RootsWithHeight(['B',2,1],[0,0,1])
1453
+ sage: B = RootsWithHeight(La[2])
1454
+ sage: B is C
1455
+ True
1456
+ """
1457
+ if cartan_type is not None:
1458
+ cartan_type, starting_weight = CartanType(starting_weight), cartan_type
1459
+
1460
+ R = RootSystem(cartan_type)
1461
+ P = R.weight_space()
1462
+ Lambda = P.basis()
1463
+ offset = R.index_set()[Integer(0)]
1464
+ starting_weight = P.sum(starting_weight[j-offset]*Lambda[j] for j in R.index_set())
1465
+
1466
+ return super().__classcall__(cls, starting_weight)
1467
+
1468
+ def __init__(self, weight):
1469
+ r"""
1470
+ Initialize ``self``.
1471
+
1472
+ EXAMPLES::
1473
+
1474
+ sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
1475
+ sage: R = RootsWithHeight(['A',2],[3,2])
1476
+ sage: TestSuite(R).run()
1477
+ """
1478
+ Parent.__init__(self, category=Sets())
1479
+
1480
+ cartan_type = weight.parent().cartan_type()
1481
+ self._cartan_type = cartan_type
1482
+ self._root_system = RootSystem(cartan_type)
1483
+ self._root_lattice = self._root_system.root_lattice()
1484
+ self._weight_lattice = self._root_system.weight_lattice()
1485
+ self.weight = weight
1486
+
1487
+ def _repr_(self):
1488
+ """
1489
+ Return a string representation of ``self``.
1490
+
1491
+ EXAMPLES::
1492
+
1493
+ sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
1494
+ sage: RootsWithHeight(['A',2],[3,2])
1495
+ Roots with height of Cartan type ['A', 2] and dominant weight 3*Lambda[1] + 2*Lambda[2]
1496
+ """
1497
+ return "Roots with height of Cartan type %s and dominant weight %s" % (
1498
+ self._root_system.cartan_type(), self.weight)
1499
+
1500
+ def _max_height(self, root):
1501
+ r"""
1502
+ If root is `\beta`, return `k = \langle \lambda, \beta^{\vee} \rangle`.
1503
+
1504
+ Only ordered pairs of the form `(\beta, l)` for `0 \leq l < k` are
1505
+ allowed.
1506
+
1507
+ EXAMPLES::
1508
+
1509
+ sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
1510
+ sage: C = RootsWithHeight(['A',3],[3,2,0])
1511
+ sage: x = C._root_lattice.from_vector(vector([1,1])); x
1512
+ alpha[1] + alpha[2]
1513
+ sage: C._max_height(x)
1514
+ 5
1515
+ """
1516
+ return self.weight.scalar(root.associated_coroot())
1517
+
1518
+ @cached_method
1519
+ def word(self):
1520
+ r"""
1521
+ Give the initial alcove path (`\lambda`-chain) in terms of simple
1522
+ roots. Used for plotting the path.
1523
+
1524
+ .. NOTE::
1525
+
1526
+ Currently only implemented for finite Cartan types.
1527
+
1528
+ EXAMPLES::
1529
+
1530
+ sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
1531
+ sage: R = RootsWithHeight(['A',2],[3,2])
1532
+ sage: R.word()
1533
+ [2, 1, 2, 0, 1, 2, 1, 0, 1, 2]
1534
+ """
1535
+ cartan_type = self._root_system.cartan_type()
1536
+ if not cartan_type.is_finite():
1537
+ raise NotImplementedError
1538
+ lambda_chain = [x.root for x in self.lambda_chain()]
1539
+
1540
+ coroot_lattice = RootSystem(cartan_type).coroot_lattice()
1541
+ cohighest_root = coroot_lattice.highest_root()
1542
+
1543
+ word = []
1544
+ for i in range(len(lambda_chain)):
1545
+ beta = lambda_chain[i]
1546
+ for j in reversed(range(i)):
1547
+ beta = beta.reflection(lambda_chain[j])
1548
+ # beta is now a simple root or the highest root
1549
+
1550
+ coroot = beta.associated_coroot()
1551
+ support = coroot.support() # the path is in dual affine space
1552
+ if len(support) == 1: # beta is a simple root
1553
+ word.append(support[0])
1554
+ elif coroot == -cohighest_root:
1555
+ word.append(0)
1556
+ else:
1557
+ assert False, 'should never get here'
1558
+
1559
+ return word
1560
+
1561
+ @cached_method
1562
+ def lambda_chain(self):
1563
+ r"""
1564
+ Return the unfolded `\lambda`-chain.
1565
+
1566
+ .. NOTE:: Only works in root systems of finite type.
1567
+
1568
+ EXAMPLES::
1569
+
1570
+ sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
1571
+ sage: R = RootsWithHeight(['A',2],[1,1]); R
1572
+ Roots with height of Cartan type ['A', 2] and dominant weight Lambda[1] + Lambda[2]
1573
+ sage: R.lambda_chain()
1574
+ [(alpha[2], 0), (alpha[1] + alpha[2], 0), (alpha[1], 0), (alpha[1] + alpha[2], 1)]
1575
+ """
1576
+ if not self._root_lattice.cartan_type().is_finite():
1577
+ raise ValueError("Cartan type {0} is not finite".format(self._root_lattice.cartan_type()))
1578
+
1579
+ l = (self(i, j) for i in self._root_lattice.positive_roots()
1580
+ for j in range(self._max_height(i)))
1581
+
1582
+ return sorted(l)
1583
+
1584
+ def _element_constructor_(self, root, height):
1585
+ r"""
1586
+ Construct a :class:`RootsWithHeightElement` with ``self`` as the parent.
1587
+
1588
+ EXAMPLES::
1589
+
1590
+ sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
1591
+ sage: rl = RootSystem(['A',2]).root_lattice()
1592
+ sage: x = rl.from_vector(vector([1,1])); x
1593
+ alpha[1] + alpha[2]
1594
+ sage: R = RootsWithHeight(['A',2],[1,1]); R
1595
+ Roots with height of Cartan type ['A', 2] and dominant weight Lambda[1] + Lambda[2]
1596
+ sage: y = R(x,1); y
1597
+ (alpha[1] + alpha[2], 1)
1598
+ """
1599
+ root = self._root_lattice.from_vector(vector(root))
1600
+ return self.element_class(self, root, height)
1601
+
1602
+ def _an_element_(self):
1603
+ r"""
1604
+
1605
+ EXAMPLES::
1606
+
1607
+ sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
1608
+ sage: R = RootsWithHeight(['A',2],[3,2])
1609
+ sage: R._an_element_()
1610
+ (alpha[1], 0)
1611
+ """
1612
+ return self(self._root_lattice.from_vector(vector([1])), 0)
1613
+
1614
+
1615
+ class RootsWithHeightElement(Element):
1616
+ r"""
1617
+ Element of :class:`RootsWithHeight`.
1618
+
1619
+ INPUT:
1620
+
1621
+ - ``root`` -- a positive root `\beta` in our root system
1622
+ - ``height`` -- integer such that
1623
+ `0 \leq l \leq \langle \lambda, \beta^{\vee} \rangle`
1624
+
1625
+ EXAMPLES::
1626
+
1627
+ sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
1628
+ sage: rl = RootSystem(['A',2]).root_lattice()
1629
+ sage: x = rl.from_vector(vector([1,1])); x
1630
+ alpha[1] + alpha[2]
1631
+ sage: R = RootsWithHeight(['A',2],[1,1]); R
1632
+ Roots with height of Cartan type ['A', 2] and dominant weight Lambda[1] + Lambda[2]
1633
+ sage: y = R(x, 1); y
1634
+ (alpha[1] + alpha[2], 1)
1635
+ """
1636
+
1637
+ def __init__(self, parent, root, height):
1638
+ r"""
1639
+ Initialize ``self``.
1640
+
1641
+ EXAMPLES::
1642
+
1643
+ sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
1644
+ sage: rl = RootSystem(['A',2]).root_lattice()
1645
+ sage: x = rl.from_vector(vector([1,1]))
1646
+ sage: R = RootsWithHeight(['A',2],[3,2])
1647
+ sage: y = R(x, 1); y
1648
+ (alpha[1] + alpha[2], 1)
1649
+ sage: TestSuite(x).run()
1650
+ """
1651
+ Element.__init__(self, parent)
1652
+ max_height = parent._max_height(root)
1653
+
1654
+ # make sure the height is in the right range, this also catches negative
1655
+ # roots
1656
+
1657
+ if not 0 <= height < max_height:
1658
+ raise ValueError("%d out of allowed range [%d,%d)" % (height, 0, max_height))
1659
+
1660
+ v = [height / max_height]
1661
+ v.extend(x / max_height
1662
+ for x in root.associated_coroot().to_vector())
1663
+ # v.insert(0, height/max_height)
1664
+
1665
+ # the map from (root, height) --> _cmp_v is injective
1666
+
1667
+ self._cmp_v = tuple(v)
1668
+ self.root = root
1669
+ self.height = height
1670
+
1671
+ def _repr_(self):
1672
+ r"""
1673
+ Return a string representation of ``self``.
1674
+
1675
+ EXAMPLES::
1676
+
1677
+ sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
1678
+ sage: R = RootsWithHeight(['A',2],[3,2])
1679
+ sage: rl = RootSystem(['A',2]).root_lattice()
1680
+ sage: vec = rl.from_vector(vector([1,1])); vec
1681
+ alpha[1] + alpha[2]
1682
+ sage: R(vec,1)
1683
+ (alpha[1] + alpha[2], 1)
1684
+ """
1685
+ return "(%s, %s)" % (self.root, self.height)
1686
+
1687
+ def __hash__(self):
1688
+ r"""
1689
+
1690
+ EXAMPLES::
1691
+
1692
+ sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
1693
+ sage: R = RootsWithHeight(['A',2],[3,2])
1694
+ sage: rl = RootSystem(['A',2]).root_lattice()
1695
+ sage: root = rl.from_vector(vector([1,1]))
1696
+ sage: vec = R(root,0)
1697
+ sage: hash(vec) == hash(vec)
1698
+ True
1699
+ """
1700
+ return hash(self._cmp_v)
1701
+
1702
+ def __eq__(self, other):
1703
+ r"""
1704
+
1705
+ EXAMPLES::
1706
+
1707
+ sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
1708
+ sage: R = RootsWithHeight(['A',2],[3,2])
1709
+ sage: rl = RootSystem(['A',2]).root_lattice()
1710
+ sage: v1 = rl.from_vector(vector([1,1]))
1711
+ sage: v2 = rl.from_vector(vector([1]))
1712
+ sage: x1 = R(v1,1) ; x2 = R(v1,0) ; x3 = R(v2,1)
1713
+ sage: x1.__eq__(x1)
1714
+ True
1715
+ sage: x1.__eq__(x2)
1716
+ False
1717
+ sage: x1.__eq__(x3)
1718
+ False
1719
+ """
1720
+ try:
1721
+ return self._cmp_v == other._cmp_v
1722
+ except (NameError, AttributeError):
1723
+ return False
1724
+
1725
+ def _richcmp_(self, other, op):
1726
+ r"""
1727
+ Define a total order on :class:`RootsWithHeightElement`. This defines
1728
+ the initial `\lambda`-chain.
1729
+
1730
+ EXAMPLES::
1731
+
1732
+ sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
1733
+ sage: R = RootsWithHeight(['A',2],[3,2])
1734
+ sage: rl = RootSystem(['A',2]).root_lattice()
1735
+ sage: v1 = rl.from_vector(vector([1,1]))
1736
+ sage: v2 = rl.from_vector(vector([1]))
1737
+ sage: x1 = R(v1,1) ; x2 = R(v1,0) ; x3 = R(v2,1)
1738
+ sage: x1 < x2
1739
+ False
1740
+ sage: x1 < x3
1741
+ True
1742
+ """
1743
+ # I suspect that if you redefine this method to produce a
1744
+ # different (valid) `\lambda`-chain the rest of the
1745
+ # code should still work.
1746
+ # todo: check if self and other have the same parent ?
1747
+ # assert self.parent() is other.parent(), "elements have different parents"
1748
+ return richcmp(self._cmp_v, other._cmp_v, op)
1749
+
1750
+
1751
+ RootsWithHeight.Element = RootsWithHeightElement
1752
+
1753
+ #####################################################################
1754
+ # Test code, by comparing with existing crystal implementations.
1755
+ #####################################################################
1756
+
1757
+
1758
+ def _test_some_specific_examples(clss=CrystalOfAlcovePaths):
1759
+ r"""
1760
+ Test against some specific (finite type) examples.
1761
+
1762
+ EXAMPLES::
1763
+
1764
+ sage: from sage.combinat.crystals.alcove_path import _test_some_specific_examples
1765
+ sage: _test_some_specific_examples(crystals.AlcovePaths)
1766
+ G2 example passed.
1767
+ C3 example passed.
1768
+ B3 example 1 passed.
1769
+ B3 example 2 passed.
1770
+ True
1771
+ """
1772
+ # This appears in Lenart.
1773
+ C = clss(['G', 2], [0, 1])
1774
+ G = C.digraph()
1775
+
1776
+ GT = DiGraph({
1777
+ (): {(0): 2},
1778
+ (0): {(0, 8): 1},
1779
+ (0, 1): {(0, 1, 7): 2},
1780
+ (0, 1, 2): {(0, 1, 2, 9): 1},
1781
+ (0, 1, 2, 3): {(0, 1, 2, 3, 4): 2},
1782
+ (0, 1, 2, 6): {(0, 1, 2, 3): 1},
1783
+ (0, 1, 2, 9): {(0, 1, 2, 6): 1},
1784
+ (0, 1, 7): {(0, 1, 2): 2},
1785
+ (0, 1, 7, 9): {(0, 1, 2, 9): 2},
1786
+ (0, 5): {(0, 1): 1, (0, 5, 7): 2},
1787
+ (0, 5, 7): {(0, 5, 7, 9): 1},
1788
+ (0, 5, 7, 9): {(0, 1, 7, 9): 1},
1789
+ (0, 8): {(0, 5): 1}
1790
+ })
1791
+
1792
+ if not G.is_isomorphic(GT):
1793
+ return False
1794
+ else:
1795
+ print("G2 example passed.")
1796
+
1797
+ # Some examples from Hong--Kang:
1798
+
1799
+ # type C, ex. 8.3.5, pg. 189
1800
+ C = clss(['C', 3], [0, 0, 1])
1801
+ G = C.digraph()
1802
+ GT = DiGraph({
1803
+ (): {(0): 3},
1804
+ (0): {(0, 6): 2},
1805
+ (0, 1): {(0, 1, 3): 3, (0, 1, 7): 1},
1806
+ (0, 1, 2): {(0, 1, 2, 3): 3},
1807
+ (0, 1, 2, 3): {(0, 1, 2, 3, 8): 2},
1808
+ (0, 1, 2, 3, 4): {(0, 1, 2, 3, 4, 5): 3},
1809
+ (0, 1, 2, 3, 8): {(0, 1, 2, 3, 4): 2},
1810
+ (0, 1, 3): {(0, 1, 3, 7): 1},
1811
+ (0, 1, 3, 7): {(0, 1, 2, 3): 1, (0, 1, 3, 7, 8): 2},
1812
+ (0, 1, 3, 7, 8): {(0, 1, 2, 3, 8): 1},
1813
+ (0, 1, 7): {(0, 1, 2): 1, (0, 1, 3, 7): 3},
1814
+ (0, 6): {(0, 1): 2, (0, 6, 7): 1},
1815
+ (0, 6, 7): {(0, 1, 7): 2}
1816
+ })
1817
+
1818
+ if not G.is_isomorphic(GT):
1819
+ return False
1820
+ else:
1821
+ print("C3 example passed.")
1822
+
1823
+ # type B, fig. 8.1 pg. 172
1824
+ C = clss(['B', 3], [2, 0, 0])
1825
+ G = C.digraph()
1826
+
1827
+ GT = DiGraph({
1828
+ (): {(6): 1},
1829
+ (0): {(0, 7): 2},
1830
+ (0, 1): {(0, 1, 11): 3},
1831
+ (0, 1, 2): {(0, 1, 2, 9): 2},
1832
+ (0, 1, 2, 3): {(0, 1, 2, 3, 10): 1},
1833
+ (0, 1, 2, 3, 10): {(0, 1, 2, 3, 4): 1},
1834
+ (0, 1, 2, 9): {(0, 1, 2, 3): 2, (0, 1, 2, 9, 10): 1},
1835
+ (0, 1, 2, 9, 10): {(0, 1, 2, 3, 10): 2},
1836
+ (0, 1, 5): {(0, 1, 2): 3, (0, 1, 5, 9): 2},
1837
+ (0, 1, 5, 9): {(0, 1, 2, 9): 3, (0, 1, 5, 9, 10): 1},
1838
+ (0, 1, 5, 9, 10): {(0, 1, 2, 9, 10): 3},
1839
+ (0, 1, 8): {(0, 1, 5): 3},
1840
+ (0, 1, 8, 9): {(0, 1, 5, 9): 3, (0, 1, 8, 9, 10): 1},
1841
+ (0, 1, 8, 9, 10): {(0, 1, 5, 9, 10): 3},
1842
+ (0, 1, 11): {(0, 1, 8): 3},
1843
+ (0, 7): {(0, 1): 2, (0, 7, 11): 3},
1844
+ (0, 7, 8): {(0, 7, 8, 9): 2},
1845
+ (0, 7, 8, 9): {(0, 1, 8, 9): 2},
1846
+ (0, 7, 8, 9, 10): {(0, 1, 8, 9, 10): 2},
1847
+ (0, 7, 11): {(0, 1, 11): 2, (0, 7, 8): 3},
1848
+ (6): {(0): 1, (6, 7): 2},
1849
+ (6, 7): {(0, 7): 1, (6, 7, 11): 3},
1850
+ (6, 7, 8): {(0, 7, 8): 1, (6, 7, 8, 9): 2},
1851
+ (6, 7, 8, 9): {(6, 7, 8, 9, 10): 1},
1852
+ (6, 7, 8, 9, 10): {(0, 7, 8, 9, 10): 1},
1853
+ (6, 7, 11): {(0, 7, 11): 1, (6, 7, 8): 3}
1854
+ })
1855
+
1856
+ if not G.is_isomorphic(GT):
1857
+ return False
1858
+ else:
1859
+ print("B3 example 1 passed.")
1860
+
1861
+ C = clss(['B', 3], [0, 1, 0])
1862
+ G = C.digraph()
1863
+
1864
+ GT = DiGraph({
1865
+ (): {(0): 2},
1866
+ (0): {(0, 1): 1, (0, 7): 3},
1867
+ (0, 1): {(0, 1, 7): 3},
1868
+ (0, 1, 2): {(0, 1, 2, 8): 2},
1869
+ (0, 1, 2, 3): {(0, 1, 2, 3, 5): 1, (0, 1, 2, 3, 9): 3},
1870
+ (0, 1, 2, 3, 4): {(0, 1, 2, 3, 4, 5): 1},
1871
+ (0, 1, 2, 3, 4, 5): {(0, 1, 2, 3, 4, 5, 6): 2},
1872
+ (0, 1, 2, 3, 5): {(0, 1, 2, 3, 5, 9): 3},
1873
+ (0, 1, 2, 3, 5, 9): {(0, 1, 2, 3, 4, 5): 3},
1874
+ (0, 1, 2, 3, 9): {(0, 1, 2, 3, 4): 3, (0, 1, 2, 3, 5, 9): 1},
1875
+ (0, 1, 2, 5): {(0, 1, 2, 3, 5): 2},
1876
+ (0, 1, 2, 8): {(0, 1, 2, 3): 2},
1877
+ (0, 1, 2, 8, 9): {(0, 1, 2, 3, 9): 2},
1878
+ (0, 1, 7): {(0, 1, 2): 3, (0, 1, 7, 8): 2},
1879
+ (0, 1, 7, 8): {(0, 1, 7, 8, 9): 3},
1880
+ (0, 1, 7, 8, 9): {(0, 1, 2, 8, 9): 3},
1881
+ (0, 2): {(0, 1, 2): 1, (0, 2, 5): 2},
1882
+ (0, 2, 5): {(0, 2, 5, 8): 1},
1883
+ (0, 2, 5, 8): {(0, 1, 2, 5): 1},
1884
+ (0, 7): {(0, 1, 7): 1, (0, 2): 3}
1885
+ })
1886
+
1887
+ if not G.is_isomorphic(GT):
1888
+ return False
1889
+ else:
1890
+ print("B3 example 2 passed.")
1891
+
1892
+ # type B, fig. 8.3 pg. 174
1893
+
1894
+ return True
1895
+
1896
+
1897
+ def compare_graphs(g1, g2, node1, node2):
1898
+ r"""
1899
+ Compare two edge-labeled :class:`graphs <DiGraph>` obtained from
1900
+ ``Crystal.digraph()``, starting from the root nodes of each graph.
1901
+
1902
+ - ``g1`` -- :class:`graphs <DiGraph>`, first digraph
1903
+ - ``g2`` -- :class:`graphs <DiGraph>`, second digraph
1904
+ - ``node1`` -- element of ``g1``
1905
+ - ``node2`` -- element of ``g2``
1906
+
1907
+ Traverse ``g1`` starting at ``node1`` and compare this graph with
1908
+ the one obtained by traversing ``g2`` starting with ``node2``.
1909
+ If the graphs match (including labels) then return ``True``.
1910
+ Return ``False`` otherwise.
1911
+
1912
+ EXAMPLES::
1913
+
1914
+ sage: from sage.combinat.crystals.alcove_path import compare_graphs
1915
+ sage: G1 = crystals.Tableaux(['A',3], shape=[1,1]).digraph()
1916
+ sage: C = crystals.AlcovePaths(['A',3],[0,1,0])
1917
+ sage: G2 = C.digraph()
1918
+ sage: compare_graphs(G1, G2, C( () ), G2.vertices(sort=True)[0])
1919
+ True
1920
+ """
1921
+ for out_edge in g1.outgoing_edges(node1):
1922
+ matched = False
1923
+ for o2 in g2.outgoing_edges(node2):
1924
+ if o2[2] == out_edge[2]:
1925
+ if matched:
1926
+ print("ERROR: Two edges with the same label for ", out_edge, " exist.")
1927
+ return False
1928
+ matched = True
1929
+ result = compare_graphs(g1, g2, out_edge[1], o2[1])
1930
+ if not result:
1931
+ return False
1932
+ if not matched:
1933
+ print("ERROR: No matching edge for ", out_edge, ".")
1934
+ return False
1935
+ return True
1936
+
1937
+
1938
+ def _test_against_tableaux(R, N, k, clss=CrystalOfAlcovePaths):
1939
+ r"""
1940
+ Test :class:`~sage.combinat.crystals.alcove_path.CrystalOfAlcovePaths`
1941
+ against all of the tableaux crystals of type `R` in rank `N` with
1942
+ highest weight given by a partition of `k`.
1943
+
1944
+ EXAMPLES::
1945
+
1946
+ sage: from sage.combinat.crystals.alcove_path import _test_against_tableaux
1947
+ sage: _test_against_tableaux(['A',3], 3, 2)
1948
+ ** Shape [2]
1949
+ T has 10 nodes.
1950
+ C weight [2, 0, 0]
1951
+ C has 10 nodes.
1952
+ Compare graphs: True
1953
+ ** Shape [1, 1]
1954
+ T has 6 nodes.
1955
+ C weight [0, 1, 0]
1956
+ C has 6 nodes.
1957
+ Compare graphs: True
1958
+ """
1959
+ from sage.combinat.partition import Partitions
1960
+ from sage.combinat.crystals.tensor_product import CrystalOfTableaux
1961
+ shapes = Partitions(k).list()
1962
+ for shape in shapes:
1963
+ print("** Shape ", shape)
1964
+ T = CrystalOfTableaux(R, shape=shape)
1965
+ ct = len(T.list())
1966
+ print(" T has ", ct, " nodes.")
1967
+ # T.digraph().show(edge_labels=True)
1968
+ H = T.digraph()
1969
+ weight = T.module_generators[0].weight()
1970
+ w = [weight.scalar(RootSystem(R).ambient_space().simple_coroot(i))
1971
+ for i in range(1, N + 1)]
1972
+ print(" C weight ", w)
1973
+
1974
+ C = clss(R, w)
1975
+
1976
+ cc = len(C.list())
1977
+ # C.digraph().show(edge_labels=True)
1978
+ G = C.digraph()
1979
+ print(" C has ", cc, " nodes.")
1980
+ if cc != ct:
1981
+ print("FAIL: number of nodes differ.", cc, ct)
1982
+ return
1983
+ print(" Compare graphs: ", compare_graphs(G, H, C(()), H.vertices(sort=True)[0]))
1984
+
1985
+
1986
+ def _test_with_lspaths_crystal(cartan_type, weight, depth=10):
1987
+ r"""
1988
+ Test if the digraphs generated are isomorphic to the ones generated by
1989
+ LS-path model.
1990
+
1991
+ INPUT:
1992
+
1993
+ - ``cartan_type`` -- Cartan type of a finite or affine untwisted root
1994
+ system
1995
+ - ``weight`` -- dominant weight as a list of (integral) coefficients of the
1996
+ fundamental weights
1997
+ - ``depth`` -- starting at the module generator how deep do you want to
1998
+ generate the crystal, useful for affine types
1999
+
2000
+ EXAMPLES::
2001
+
2002
+ sage: from sage.combinat.crystals.alcove_path import _test_with_lspaths_crystal
2003
+ sage: _test_with_lspaths_crystal(['A',3,1],[1,0,0,0],10) #long time
2004
+ True
2005
+ sage: _test_with_lspaths_crystal(['G',2,1],[1,0,0,0,0],10) #long time
2006
+ True
2007
+ """
2008
+ from sage.combinat.crystals.littelmann_path import CrystalOfLSPaths
2009
+ G1 = CrystalOfAlcovePaths(cartan_type, weight).digraph(depth=depth)
2010
+ C = CrystalOfLSPaths(cartan_type, weight)
2011
+ G2 = C.digraph(subset=C.subcrystal(max_depth=depth, direction='lower'))
2012
+
2013
+ return G1.is_isomorphic(G2, edge_labels=True)