passagemath-combinat 10.6.42__cp314-cp314t-win_amd64.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 (401) hide show
  1. passagemath_combinat/__init__.py +3 -0
  2. passagemath_combinat-10.6.42.dist-info/DELVEWHEEL +2 -0
  3. passagemath_combinat-10.6.42.dist-info/METADATA +160 -0
  4. passagemath_combinat-10.6.42.dist-info/RECORD +401 -0
  5. passagemath_combinat-10.6.42.dist-info/WHEEL +5 -0
  6. passagemath_combinat-10.6.42.dist-info/top_level.txt +3 -0
  7. passagemath_combinat.libs/libgmp-10-3a5f019e2510aeaad918cab2b57a689d.dll +0 -0
  8. passagemath_combinat.libs/libsymmetrica-3-7dcf900932804d0df5fd0919b4668720.dll +0 -0
  9. sage/algebras/affine_nil_temperley_lieb.py +263 -0
  10. sage/algebras/all.py +24 -0
  11. sage/algebras/all__sagemath_combinat.py +35 -0
  12. sage/algebras/askey_wilson.py +935 -0
  13. sage/algebras/associated_graded.py +345 -0
  14. sage/algebras/cellular_basis.py +350 -0
  15. sage/algebras/cluster_algebra.py +2766 -0
  16. sage/algebras/down_up_algebra.py +860 -0
  17. sage/algebras/free_algebra.py +1698 -0
  18. sage/algebras/free_algebra_element.py +345 -0
  19. sage/algebras/free_algebra_quotient.py +405 -0
  20. sage/algebras/free_algebra_quotient_element.py +295 -0
  21. sage/algebras/free_zinbiel_algebra.py +885 -0
  22. sage/algebras/hall_algebra.py +783 -0
  23. sage/algebras/hecke_algebras/all.py +4 -0
  24. sage/algebras/hecke_algebras/ariki_koike_algebra.py +1796 -0
  25. sage/algebras/hecke_algebras/ariki_koike_specht_modules.py +475 -0
  26. sage/algebras/hecke_algebras/cubic_hecke_algebra.py +3520 -0
  27. sage/algebras/hecke_algebras/cubic_hecke_base_ring.py +1473 -0
  28. sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py +1079 -0
  29. sage/algebras/iwahori_hecke_algebra.py +3095 -0
  30. sage/algebras/jordan_algebra.py +1773 -0
  31. sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py +113 -0
  32. sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py +156 -0
  33. sage/algebras/lie_conformal_algebras/all.py +18 -0
  34. sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py +134 -0
  35. sage/algebras/lie_conformal_algebras/examples.py +43 -0
  36. sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py +131 -0
  37. sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py +139 -0
  38. sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py +174 -0
  39. sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py +167 -0
  40. sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py +107 -0
  41. sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py +135 -0
  42. sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py +353 -0
  43. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py +236 -0
  44. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py +78 -0
  45. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py +328 -0
  46. sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py +117 -0
  47. sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py +86 -0
  48. sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py +82 -0
  49. sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py +205 -0
  50. sage/algebras/nil_coxeter_algebra.py +191 -0
  51. sage/algebras/q_commuting_polynomials.py +673 -0
  52. sage/algebras/q_system.py +608 -0
  53. sage/algebras/quantum_clifford.py +959 -0
  54. sage/algebras/quantum_groups/ace_quantum_onsager.py +693 -0
  55. sage/algebras/quantum_groups/all.py +9 -0
  56. sage/algebras/quantum_groups/fock_space.py +2219 -0
  57. sage/algebras/quantum_groups/q_numbers.py +207 -0
  58. sage/algebras/quantum_groups/quantum_group_gap.py +2695 -0
  59. sage/algebras/quantum_groups/representations.py +591 -0
  60. sage/algebras/quantum_matrix_coordinate_algebra.py +1006 -0
  61. sage/algebras/quantum_oscillator.py +623 -0
  62. sage/algebras/quaternion_algebra.py +20 -0
  63. sage/algebras/quaternion_algebra_element.py +55 -0
  64. sage/algebras/rational_cherednik_algebra.py +525 -0
  65. sage/algebras/schur_algebra.py +670 -0
  66. sage/algebras/shuffle_algebra.py +1011 -0
  67. sage/algebras/splitting_algebra.py +779 -0
  68. sage/algebras/tensor_algebra.py +709 -0
  69. sage/algebras/yangian.py +1082 -0
  70. sage/algebras/yokonuma_hecke_algebra.py +1018 -0
  71. sage/all__sagemath_combinat.py +44 -0
  72. sage/combinat/SJT.py +255 -0
  73. sage/combinat/affine_permutation.py +2405 -0
  74. sage/combinat/algebraic_combinatorics.py +55 -0
  75. sage/combinat/all.py +53 -0
  76. sage/combinat/all__sagemath_combinat.py +195 -0
  77. sage/combinat/alternating_sign_matrix.py +2063 -0
  78. sage/combinat/baxter_permutations.py +346 -0
  79. sage/combinat/bijectionist.py +3220 -0
  80. sage/combinat/binary_recurrence_sequences.py +1180 -0
  81. sage/combinat/blob_algebra.py +685 -0
  82. sage/combinat/catalog_partitions.py +27 -0
  83. sage/combinat/chas/all.py +23 -0
  84. sage/combinat/chas/fsym.py +1180 -0
  85. sage/combinat/chas/wqsym.py +2601 -0
  86. sage/combinat/cluster_complex.py +326 -0
  87. sage/combinat/colored_permutations.py +2039 -0
  88. sage/combinat/colored_permutations_representations.py +964 -0
  89. sage/combinat/composition_signed.py +142 -0
  90. sage/combinat/composition_tableau.py +855 -0
  91. sage/combinat/constellation.py +1729 -0
  92. sage/combinat/core.py +751 -0
  93. sage/combinat/counting.py +12 -0
  94. sage/combinat/crystals/affine.py +742 -0
  95. sage/combinat/crystals/affine_factorization.py +518 -0
  96. sage/combinat/crystals/affinization.py +331 -0
  97. sage/combinat/crystals/alcove_path.py +2013 -0
  98. sage/combinat/crystals/all.py +22 -0
  99. sage/combinat/crystals/bkk_crystals.py +141 -0
  100. sage/combinat/crystals/catalog.py +115 -0
  101. sage/combinat/crystals/catalog_elementary_crystals.py +18 -0
  102. sage/combinat/crystals/catalog_infinity_crystals.py +33 -0
  103. sage/combinat/crystals/catalog_kirillov_reshetikhin.py +18 -0
  104. sage/combinat/crystals/crystals.py +257 -0
  105. sage/combinat/crystals/direct_sum.py +260 -0
  106. sage/combinat/crystals/elementary_crystals.py +1251 -0
  107. sage/combinat/crystals/fast_crystals.py +441 -0
  108. sage/combinat/crystals/fully_commutative_stable_grothendieck.py +1205 -0
  109. sage/combinat/crystals/generalized_young_walls.py +1076 -0
  110. sage/combinat/crystals/highest_weight_crystals.py +436 -0
  111. sage/combinat/crystals/induced_structure.py +695 -0
  112. sage/combinat/crystals/infinity_crystals.py +730 -0
  113. sage/combinat/crystals/kac_modules.py +863 -0
  114. sage/combinat/crystals/kirillov_reshetikhin.py +4196 -0
  115. sage/combinat/crystals/kyoto_path_model.py +497 -0
  116. sage/combinat/crystals/letters.cp314t-win_amd64.pyd +0 -0
  117. sage/combinat/crystals/letters.pxd +79 -0
  118. sage/combinat/crystals/letters.pyx +3056 -0
  119. sage/combinat/crystals/littelmann_path.py +1518 -0
  120. sage/combinat/crystals/monomial_crystals.py +1262 -0
  121. sage/combinat/crystals/multisegments.py +462 -0
  122. sage/combinat/crystals/mv_polytopes.py +467 -0
  123. sage/combinat/crystals/pbw_crystal.py +511 -0
  124. sage/combinat/crystals/pbw_datum.cp314t-win_amd64.pyd +0 -0
  125. sage/combinat/crystals/pbw_datum.pxd +4 -0
  126. sage/combinat/crystals/pbw_datum.pyx +487 -0
  127. sage/combinat/crystals/polyhedral_realization.py +372 -0
  128. sage/combinat/crystals/spins.cp314t-win_amd64.pyd +0 -0
  129. sage/combinat/crystals/spins.pxd +21 -0
  130. sage/combinat/crystals/spins.pyx +756 -0
  131. sage/combinat/crystals/star_crystal.py +290 -0
  132. sage/combinat/crystals/subcrystal.py +464 -0
  133. sage/combinat/crystals/tensor_product.py +1177 -0
  134. sage/combinat/crystals/tensor_product_element.cp314t-win_amd64.pyd +0 -0
  135. sage/combinat/crystals/tensor_product_element.pxd +35 -0
  136. sage/combinat/crystals/tensor_product_element.pyx +1870 -0
  137. sage/combinat/crystals/virtual_crystal.py +420 -0
  138. sage/combinat/cyclic_sieving_phenomenon.py +204 -0
  139. sage/combinat/debruijn_sequence.cp314t-win_amd64.pyd +0 -0
  140. sage/combinat/debruijn_sequence.pyx +355 -0
  141. sage/combinat/decorated_permutation.py +270 -0
  142. sage/combinat/degree_sequences.cp314t-win_amd64.pyd +0 -0
  143. sage/combinat/degree_sequences.pyx +588 -0
  144. sage/combinat/derangements.py +527 -0
  145. sage/combinat/descent_algebra.py +1008 -0
  146. sage/combinat/diagram.py +1551 -0
  147. sage/combinat/diagram_algebras.py +5886 -0
  148. sage/combinat/dyck_word.py +4349 -0
  149. sage/combinat/e_one_star.py +1623 -0
  150. sage/combinat/enumerated_sets.py +123 -0
  151. sage/combinat/expnums.cp314t-win_amd64.pyd +0 -0
  152. sage/combinat/expnums.pyx +148 -0
  153. sage/combinat/fast_vector_partitions.cp314t-win_amd64.pyd +0 -0
  154. sage/combinat/fast_vector_partitions.pyx +346 -0
  155. sage/combinat/fqsym.py +1977 -0
  156. sage/combinat/free_dendriform_algebra.py +954 -0
  157. sage/combinat/free_prelie_algebra.py +1141 -0
  158. sage/combinat/fully_commutative_elements.py +1077 -0
  159. sage/combinat/fully_packed_loop.py +1523 -0
  160. sage/combinat/gelfand_tsetlin_patterns.py +1409 -0
  161. sage/combinat/gray_codes.py +311 -0
  162. sage/combinat/grossman_larson_algebras.py +667 -0
  163. sage/combinat/growth.py +4352 -0
  164. sage/combinat/hall_polynomial.py +188 -0
  165. sage/combinat/hillman_grassl.py +866 -0
  166. sage/combinat/integer_matrices.py +329 -0
  167. sage/combinat/integer_vectors_mod_permgroup.py +1238 -0
  168. sage/combinat/k_tableau.py +4564 -0
  169. sage/combinat/kazhdan_lusztig.py +215 -0
  170. sage/combinat/key_polynomial.py +885 -0
  171. sage/combinat/knutson_tao_puzzles.py +2286 -0
  172. sage/combinat/lr_tableau.py +311 -0
  173. sage/combinat/matrices/all.py +24 -0
  174. sage/combinat/matrices/hadamard_matrix.py +3790 -0
  175. sage/combinat/matrices/latin.py +2912 -0
  176. sage/combinat/misc.py +401 -0
  177. sage/combinat/multiset_partition_into_sets_ordered.py +3541 -0
  178. sage/combinat/ncsf_qsym/all.py +21 -0
  179. sage/combinat/ncsf_qsym/combinatorics.py +317 -0
  180. sage/combinat/ncsf_qsym/generic_basis_code.py +1427 -0
  181. sage/combinat/ncsf_qsym/ncsf.py +5637 -0
  182. sage/combinat/ncsf_qsym/qsym.py +4053 -0
  183. sage/combinat/ncsf_qsym/tutorial.py +447 -0
  184. sage/combinat/ncsym/all.py +21 -0
  185. sage/combinat/ncsym/bases.py +855 -0
  186. sage/combinat/ncsym/dual.py +593 -0
  187. sage/combinat/ncsym/ncsym.py +2076 -0
  188. sage/combinat/necklace.py +551 -0
  189. sage/combinat/non_decreasing_parking_function.py +634 -0
  190. sage/combinat/nu_dyck_word.py +1474 -0
  191. sage/combinat/output.py +861 -0
  192. sage/combinat/parallelogram_polyomino.py +4326 -0
  193. sage/combinat/parking_functions.py +1602 -0
  194. sage/combinat/partition_algebra.py +1998 -0
  195. sage/combinat/partition_kleshchev.py +1982 -0
  196. sage/combinat/partition_shifting_algebras.py +584 -0
  197. sage/combinat/partition_tuple.py +3114 -0
  198. sage/combinat/path_tableaux/all.py +13 -0
  199. sage/combinat/path_tableaux/catalog.py +29 -0
  200. sage/combinat/path_tableaux/dyck_path.py +380 -0
  201. sage/combinat/path_tableaux/frieze.py +476 -0
  202. sage/combinat/path_tableaux/path_tableau.py +728 -0
  203. sage/combinat/path_tableaux/semistandard.py +510 -0
  204. sage/combinat/perfect_matching.py +779 -0
  205. sage/combinat/plane_partition.py +3300 -0
  206. sage/combinat/q_bernoulli.cp314t-win_amd64.pyd +0 -0
  207. sage/combinat/q_bernoulli.pyx +128 -0
  208. sage/combinat/quickref.py +81 -0
  209. sage/combinat/recognizable_series.py +2051 -0
  210. sage/combinat/regular_sequence.py +4316 -0
  211. sage/combinat/regular_sequence_bounded.py +543 -0
  212. sage/combinat/restricted_growth.py +81 -0
  213. sage/combinat/ribbon.py +20 -0
  214. sage/combinat/ribbon_shaped_tableau.py +489 -0
  215. sage/combinat/ribbon_tableau.py +1180 -0
  216. sage/combinat/rigged_configurations/all.py +46 -0
  217. sage/combinat/rigged_configurations/bij_abstract_class.py +548 -0
  218. sage/combinat/rigged_configurations/bij_infinity.py +370 -0
  219. sage/combinat/rigged_configurations/bij_type_A.py +163 -0
  220. sage/combinat/rigged_configurations/bij_type_A2_dual.py +338 -0
  221. sage/combinat/rigged_configurations/bij_type_A2_even.py +218 -0
  222. sage/combinat/rigged_configurations/bij_type_A2_odd.py +199 -0
  223. sage/combinat/rigged_configurations/bij_type_B.py +900 -0
  224. sage/combinat/rigged_configurations/bij_type_C.py +267 -0
  225. sage/combinat/rigged_configurations/bij_type_D.py +771 -0
  226. sage/combinat/rigged_configurations/bij_type_D_tri.py +392 -0
  227. sage/combinat/rigged_configurations/bij_type_D_twisted.py +576 -0
  228. sage/combinat/rigged_configurations/bij_type_E67.py +402 -0
  229. sage/combinat/rigged_configurations/bijection.py +143 -0
  230. sage/combinat/rigged_configurations/kleber_tree.py +1475 -0
  231. sage/combinat/rigged_configurations/kr_tableaux.py +1898 -0
  232. sage/combinat/rigged_configurations/rc_crystal.py +461 -0
  233. sage/combinat/rigged_configurations/rc_infinity.py +540 -0
  234. sage/combinat/rigged_configurations/rigged_configuration_element.py +2403 -0
  235. sage/combinat/rigged_configurations/rigged_configurations.py +1918 -0
  236. sage/combinat/rigged_configurations/rigged_partition.cp314t-win_amd64.pyd +0 -0
  237. sage/combinat/rigged_configurations/rigged_partition.pxd +15 -0
  238. sage/combinat/rigged_configurations/rigged_partition.pyx +680 -0
  239. sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +499 -0
  240. sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py +428 -0
  241. sage/combinat/rsk.py +3438 -0
  242. sage/combinat/schubert_polynomial.py +508 -0
  243. sage/combinat/set_partition.py +3318 -0
  244. sage/combinat/set_partition_iterator.cp314t-win_amd64.pyd +0 -0
  245. sage/combinat/set_partition_iterator.pyx +136 -0
  246. sage/combinat/set_partition_ordered.py +1590 -0
  247. sage/combinat/sf/abreu_nigro.py +346 -0
  248. sage/combinat/sf/all.py +52 -0
  249. sage/combinat/sf/character.py +576 -0
  250. sage/combinat/sf/classical.py +319 -0
  251. sage/combinat/sf/dual.py +996 -0
  252. sage/combinat/sf/elementary.py +549 -0
  253. sage/combinat/sf/hall_littlewood.py +1028 -0
  254. sage/combinat/sf/hecke.py +336 -0
  255. sage/combinat/sf/homogeneous.py +464 -0
  256. sage/combinat/sf/jack.py +1428 -0
  257. sage/combinat/sf/k_dual.py +1458 -0
  258. sage/combinat/sf/kfpoly.py +447 -0
  259. sage/combinat/sf/llt.py +789 -0
  260. sage/combinat/sf/macdonald.py +2019 -0
  261. sage/combinat/sf/monomial.py +525 -0
  262. sage/combinat/sf/multiplicative.py +113 -0
  263. sage/combinat/sf/new_kschur.py +1786 -0
  264. sage/combinat/sf/ns_macdonald.py +964 -0
  265. sage/combinat/sf/orthogonal.py +246 -0
  266. sage/combinat/sf/orthotriang.py +355 -0
  267. sage/combinat/sf/powersum.py +963 -0
  268. sage/combinat/sf/schur.py +880 -0
  269. sage/combinat/sf/sf.py +1653 -0
  270. sage/combinat/sf/sfa.py +7053 -0
  271. sage/combinat/sf/symplectic.py +253 -0
  272. sage/combinat/sf/witt.py +721 -0
  273. sage/combinat/shifted_primed_tableau.py +2735 -0
  274. sage/combinat/shuffle.py +830 -0
  275. sage/combinat/sidon_sets.py +146 -0
  276. sage/combinat/similarity_class_type.py +1721 -0
  277. sage/combinat/sine_gordon.py +618 -0
  278. sage/combinat/six_vertex_model.py +784 -0
  279. sage/combinat/skew_partition.py +2053 -0
  280. sage/combinat/skew_tableau.py +2989 -0
  281. sage/combinat/sloane_functions.py +8935 -0
  282. sage/combinat/specht_module.py +1403 -0
  283. sage/combinat/species/all.py +48 -0
  284. sage/combinat/species/characteristic_species.py +321 -0
  285. sage/combinat/species/composition_species.py +273 -0
  286. sage/combinat/species/cycle_species.py +284 -0
  287. sage/combinat/species/empty_species.py +155 -0
  288. sage/combinat/species/functorial_composition_species.py +148 -0
  289. sage/combinat/species/generating_series.py +673 -0
  290. sage/combinat/species/library.py +148 -0
  291. sage/combinat/species/linear_order_species.py +169 -0
  292. sage/combinat/species/misc.py +83 -0
  293. sage/combinat/species/partition_species.py +290 -0
  294. sage/combinat/species/permutation_species.py +268 -0
  295. sage/combinat/species/product_species.py +423 -0
  296. sage/combinat/species/recursive_species.py +476 -0
  297. sage/combinat/species/set_species.py +192 -0
  298. sage/combinat/species/species.py +820 -0
  299. sage/combinat/species/structure.py +539 -0
  300. sage/combinat/species/subset_species.py +243 -0
  301. sage/combinat/species/sum_species.py +225 -0
  302. sage/combinat/subword.py +564 -0
  303. sage/combinat/subword_complex.py +2122 -0
  304. sage/combinat/subword_complex_c.cp314t-win_amd64.pyd +0 -0
  305. sage/combinat/subword_complex_c.pyx +119 -0
  306. sage/combinat/super_tableau.py +821 -0
  307. sage/combinat/superpartition.py +1154 -0
  308. sage/combinat/symmetric_group_algebra.py +3774 -0
  309. sage/combinat/symmetric_group_representations.py +1830 -0
  310. sage/combinat/t_sequences.py +877 -0
  311. sage/combinat/tableau.py +9506 -0
  312. sage/combinat/tableau_residues.py +860 -0
  313. sage/combinat/tableau_tuple.py +5353 -0
  314. sage/combinat/tiling.py +2432 -0
  315. sage/combinat/triangles_FHM.py +777 -0
  316. sage/combinat/tutorial.py +1857 -0
  317. sage/combinat/vector_partition.py +337 -0
  318. sage/combinat/words/abstract_word.py +1722 -0
  319. sage/combinat/words/all.py +59 -0
  320. sage/combinat/words/alphabet.py +268 -0
  321. sage/combinat/words/finite_word.py +7201 -0
  322. sage/combinat/words/infinite_word.py +113 -0
  323. sage/combinat/words/lyndon_word.py +652 -0
  324. sage/combinat/words/morphic.py +351 -0
  325. sage/combinat/words/morphism.py +3878 -0
  326. sage/combinat/words/paths.py +2932 -0
  327. sage/combinat/words/shuffle_product.py +278 -0
  328. sage/combinat/words/suffix_trees.py +1873 -0
  329. sage/combinat/words/word.py +769 -0
  330. sage/combinat/words/word_char.cp314t-win_amd64.pyd +0 -0
  331. sage/combinat/words/word_char.pyx +847 -0
  332. sage/combinat/words/word_datatypes.cp314t-win_amd64.pyd +0 -0
  333. sage/combinat/words/word_datatypes.pxd +4 -0
  334. sage/combinat/words/word_datatypes.pyx +1067 -0
  335. sage/combinat/words/word_generators.py +2026 -0
  336. sage/combinat/words/word_infinite_datatypes.py +1218 -0
  337. sage/combinat/words/word_options.py +99 -0
  338. sage/combinat/words/words.py +2396 -0
  339. sage/data_structures/all__sagemath_combinat.py +1 -0
  340. sage/databases/all__sagemath_combinat.py +13 -0
  341. sage/databases/findstat.py +4897 -0
  342. sage/databases/oeis.py +2058 -0
  343. sage/databases/sloane.py +393 -0
  344. sage/dynamics/all__sagemath_combinat.py +14 -0
  345. sage/dynamics/cellular_automata/all.py +7 -0
  346. sage/dynamics/cellular_automata/catalog.py +34 -0
  347. sage/dynamics/cellular_automata/elementary.py +612 -0
  348. sage/dynamics/cellular_automata/glca.py +477 -0
  349. sage/dynamics/cellular_automata/solitons.py +1463 -0
  350. sage/dynamics/finite_dynamical_system.py +1249 -0
  351. sage/dynamics/finite_dynamical_system_catalog.py +382 -0
  352. sage/games/all.py +7 -0
  353. sage/games/hexad.py +704 -0
  354. sage/games/quantumino.py +591 -0
  355. sage/games/sudoku.py +889 -0
  356. sage/games/sudoku_backtrack.cp314t-win_amd64.pyd +0 -0
  357. sage/games/sudoku_backtrack.pyx +189 -0
  358. sage/groups/all__sagemath_combinat.py +1 -0
  359. sage/groups/indexed_free_group.py +489 -0
  360. sage/libs/all__sagemath_combinat.py +6 -0
  361. sage/libs/lrcalc/__init__.py +1 -0
  362. sage/libs/lrcalc/lrcalc.py +525 -0
  363. sage/libs/symmetrica/__init__.py +7 -0
  364. sage/libs/symmetrica/all.py +101 -0
  365. sage/libs/symmetrica/kostka.pxi +168 -0
  366. sage/libs/symmetrica/part.pxi +193 -0
  367. sage/libs/symmetrica/plet.pxi +42 -0
  368. sage/libs/symmetrica/sab.pxi +196 -0
  369. sage/libs/symmetrica/sb.pxi +332 -0
  370. sage/libs/symmetrica/sc.pxi +192 -0
  371. sage/libs/symmetrica/schur.pxi +956 -0
  372. sage/libs/symmetrica/symmetrica.cp314t-win_amd64.pyd +0 -0
  373. sage/libs/symmetrica/symmetrica.pxi +1172 -0
  374. sage/libs/symmetrica/symmetrica.pyx +39 -0
  375. sage/monoids/all.py +13 -0
  376. sage/monoids/automatic_semigroup.py +1054 -0
  377. sage/monoids/free_abelian_monoid.py +315 -0
  378. sage/monoids/free_abelian_monoid_element.cp314t-win_amd64.pyd +0 -0
  379. sage/monoids/free_abelian_monoid_element.pxd +16 -0
  380. sage/monoids/free_abelian_monoid_element.pyx +397 -0
  381. sage/monoids/free_monoid.py +335 -0
  382. sage/monoids/free_monoid_element.py +431 -0
  383. sage/monoids/hecke_monoid.py +65 -0
  384. sage/monoids/string_monoid.py +817 -0
  385. sage/monoids/string_monoid_element.py +547 -0
  386. sage/monoids/string_ops.py +143 -0
  387. sage/monoids/trace_monoid.py +972 -0
  388. sage/rings/all__sagemath_combinat.py +2 -0
  389. sage/sat/all.py +4 -0
  390. sage/sat/boolean_polynomials.py +405 -0
  391. sage/sat/converters/__init__.py +6 -0
  392. sage/sat/converters/anf2cnf.py +14 -0
  393. sage/sat/converters/polybori.py +611 -0
  394. sage/sat/solvers/__init__.py +5 -0
  395. sage/sat/solvers/cryptominisat.py +287 -0
  396. sage/sat/solvers/dimacs.py +783 -0
  397. sage/sat/solvers/picosat.py +228 -0
  398. sage/sat/solvers/sat_lp.py +156 -0
  399. sage/sat/solvers/satsolver.cp314t-win_amd64.pyd +0 -0
  400. sage/sat/solvers/satsolver.pxd +3 -0
  401. sage/sat/solvers/satsolver.pyx +405 -0
@@ -0,0 +1,2735 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ # sage.doctest: needs sage.combinat sage.modules
3
+ """
4
+ Shifted primed tableaux
5
+
6
+ AUTHORS:
7
+
8
+ - Kirill Paramonov (2017-08-18): initial implementation
9
+ - Chaman Agrawal (2019-08-12): add parameter to allow primed diagonal entry
10
+ """
11
+
12
+ # ****************************************************************************
13
+ # Copyright (C) 2017 Kirill Paramonov <kbparamonov at ucdavis.edu>,
14
+ #
15
+ # This program is free software: you can redistribute it and/or modify
16
+ # it under the terms of the GNU General Public License as published by
17
+ # the Free Software Foundation, either version 2 of the License, or
18
+ # (at your option) any later version.
19
+ # https://www.gnu.org/licenses/
20
+ # ****************************************************************************
21
+
22
+ from sage.combinat.partition import Partition, Partitions, _Partitions, OrderedPartitions
23
+ from sage.combinat.partitions import ZS1_iterator
24
+ from sage.combinat.tableau import Tableaux
25
+ from sage.combinat.skew_partition import SkewPartition
26
+ from sage.combinat.integer_vector import IntegerVectors
27
+ from sage.rings.integer import Integer
28
+ from sage.rings.rational_field import QQ
29
+
30
+ from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass
31
+ from sage.misc.lazy_attribute import lazy_attribute
32
+ from sage.misc.lazy_import import lazy_import
33
+
34
+ from sage.structure.list_clone import ClonableArray
35
+ from sage.structure.parent import Parent
36
+ from sage.structure.unique_representation import UniqueRepresentation
37
+ from sage.structure.sage_object import SageObject
38
+
39
+ from sage.categories.regular_crystals import RegularCrystals
40
+ from sage.categories.regular_supercrystals import RegularSuperCrystals
41
+ from sage.categories.sets_cat import Sets
42
+ from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
43
+ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
44
+ from sage.combinat.combination import Combinations
45
+
46
+ lazy_import('sage.combinat.root_system.cartan_type', 'CartanType')
47
+
48
+
49
+ class ShiftedPrimedTableau(ClonableArray,
50
+ metaclass=InheritComparisonClasscallMetaclass):
51
+ r"""
52
+ A shifted primed tableau.
53
+
54
+ A primed tableau is a tableau of shifted shape in the alphabet
55
+ `X' = \{1' < 1 < 2' < 2 < \cdots < n' < n\}` such that
56
+
57
+ 1. the entries are weakly increasing along rows and columns;
58
+ 2. a row cannot have two repeated primed elements, and a column
59
+ cannot have two repeated non-primed elements;
60
+
61
+ Skew shape of the shifted primed tableaux is specified either
62
+ with an optional argument ``skew`` or with ``None`` entries.
63
+
64
+ Primed entries in the main diagonal can be allowed with the optional
65
+ boolean parameter ``primed_diagonal``(default: ``False``).
66
+
67
+ EXAMPLES::
68
+
69
+ sage: T = ShiftedPrimedTableaux([4,2])
70
+ sage: T([[1,"2'","3'",3],[2,"3'"]])[1]
71
+ (2, 3')
72
+ sage: t = ShiftedPrimedTableau([[1,"2p",2.5,3],[2,2.5]])
73
+ sage: t[1]
74
+ (2, 3')
75
+ sage: ShiftedPrimedTableau([["2p",2,3],["2p","3p"],[2]], skew=[2,1])
76
+ [(None, None, 2', 2, 3), (None, 2', 3'), (2,)]
77
+ sage: ShiftedPrimedTableau([[None,None,"2p"],[None,"2p"]])
78
+ [(None, None, 2'), (None, 2')]
79
+ sage: T = ShiftedPrimedTableaux([4,2], primed_diagonal=True)
80
+ sage: T([[1,"2'","3'",3],["2'","3'"]])[1] # With primed diagonal entry
81
+ (2', 3')
82
+
83
+ TESTS::
84
+
85
+ sage: t = ShiftedPrimedTableau([[1,2,2.5,3],[2,2.5]])
86
+ Traceback (most recent call last):
87
+ ...
88
+ ValueError: [[1, 2, 2.50000000000000, 3], [2, 2.50000000000000]]
89
+ is not an element of Shifted Primed Tableaux
90
+
91
+ sage: ShiftedPrimedTableau([[1,1,2.5],[1.5,2.5]])
92
+ Traceback (most recent call last):
93
+ ...
94
+ ValueError: [[1, 1, 2.50000000000000], [1.50000000000000, 2.50000000000000]]
95
+ is not an element of Shifted Primed Tableaux
96
+
97
+ sage: ShiftedPrimedTableau([[1,1,2.5],[1.5,2.5]], primed_diagonal=True)
98
+ [(1, 1, 3'), (2', 3')]
99
+ """
100
+ @staticmethod
101
+ def __classcall_private__(cls, T, skew=None, primed_diagonal=False):
102
+ r"""
103
+ Ensure that a shifted tableau is only ever constructed as an
104
+ ``element_class`` call of an appropriate parent.
105
+
106
+ EXAMPLES::
107
+
108
+ sage: data = [[1,"2'","2",3],[2,"3'"]]
109
+ sage: t = ShiftedPrimedTableau(data)
110
+ sage: T = ShiftedPrimedTableaux(shape=[4,2],weight=(1,3,2))
111
+ sage: t == T(data)
112
+ True
113
+ sage: S = ShiftedPrimedTableaux(shape=[4,2])
114
+ sage: t == S(data)
115
+ True
116
+ sage: t = ShiftedPrimedTableau([["2p",2,3],["2p"]],skew=[2,1])
117
+ sage: t.parent()
118
+ Shifted Primed Tableaux skewed by [2, 1]
119
+ sage: s = ShiftedPrimedTableau([[None, None,"2p",2,3],[None,"2p"]])
120
+ sage: s.parent()
121
+ Shifted Primed Tableaux skewed by [2, 1]
122
+
123
+ TESTS::
124
+
125
+ sage: ShiftedPrimedTableau([])
126
+ []
127
+ sage: ShiftedPrimedTableau([tuple()])
128
+ []
129
+ sage: ShiftedPrimedTableau([], primed_diagonal=True)
130
+ []
131
+ sage: ShiftedPrimedTableau([tuple()], primed_diagonal=True)
132
+ []
133
+ """
134
+ if (isinstance(T, ShiftedPrimedTableau) and T._skew == skew
135
+ and T.parent()._primed_diagonal == primed_diagonal):
136
+ return T
137
+
138
+ skew_ = Partition([row.count(None) for row in T])
139
+ if skew_:
140
+ if skew and Partition(skew) != skew_:
141
+ raise ValueError("skew shape does not agree with None entries")
142
+ skew = skew_
143
+ return ShiftedPrimedTableaux(skew=skew, primed_diagonal=primed_diagonal)(T)
144
+
145
+ def __init__(self, parent, T, skew=None, check=True, preprocessed=False):
146
+ r"""
147
+ Initialize a shifted tableau.
148
+
149
+ TESTS::
150
+
151
+ sage: s = ShiftedPrimedTableau([[1,"2'","3'",3], [2,"3'"]])
152
+ sage: t = ShiftedPrimedTableaux([4,2])([[1,"2p","3p",3], [2,"3p"]])
153
+ sage: s == t
154
+ True
155
+ sage: t.parent()
156
+ Shifted Primed Tableaux of shape [4, 2]
157
+ sage: s.parent()
158
+ Shifted Primed Tableaux
159
+ sage: r = ShiftedPrimedTableaux([4, 2])(s); r.parent()
160
+ Shifted Primed Tableaux of shape [4, 2]
161
+ sage: s is t # identical shifted tableaux are distinct objects
162
+ False
163
+
164
+ A shifted primed tableau is deeply immutable as the rows are
165
+ stored as tuples::
166
+
167
+ sage: t = ShiftedPrimedTableau([[1,"2p","3p",3],[2,"3p"]])
168
+ sage: t[0][1] = 3
169
+ Traceback (most recent call last):
170
+ ...
171
+ TypeError: 'tuple' object does not support item assignment
172
+ """
173
+ if not preprocessed:
174
+ T = self._preprocess(T, skew=skew)
175
+ self._skew = skew
176
+ ClonableArray.__init__(self, parent, T, check=check)
177
+
178
+ @staticmethod
179
+ def _preprocess(T, skew=None):
180
+ """
181
+ Preprocessing list ``T`` to initialize the tableau.
182
+
183
+ The output is a list of rows as tuples, with explicit
184
+ ``None`` to indicate the skew shape, and entries being
185
+ ``PrimedEntry`` instances.
186
+
187
+ Trailing empty rows are removed.
188
+
189
+ TESTS::
190
+
191
+ sage: ShiftedPrimedTableau._preprocess([["2'", "3p", 3.5]],
192
+ ....: skew=[1])
193
+ [(None, 2', 3', 4')]
194
+ sage: ShiftedPrimedTableau._preprocess([[None]], skew=[1])
195
+ [(None,)]
196
+ sage: ShiftedPrimedTableau._preprocess([], skew=[2,1])
197
+ [(None, None), (None,)]
198
+ sage: ShiftedPrimedTableau._preprocess([], skew=[])
199
+ []
200
+ """
201
+ if isinstance(T, ShiftedPrimedTableau):
202
+ return T
203
+ # Preprocessing list t for primes and other symbols
204
+ T = [[PrimedEntry(entry) for entry in row if entry is not None]
205
+ for row in T]
206
+ while T and not T[-1]:
207
+ T = T[:-1]
208
+ row_min = min(len(skew), len(T)) if skew else 0
209
+ T_ = [(None,)*skew[i] + tuple(T[i]) for i in range(row_min)]
210
+
211
+ if row_min < len(T):
212
+ T_ += [tuple(T[i]) for i in range(row_min, len(T))]
213
+ elif skew:
214
+ T_ += [(None,)*skew[i] for i in range(row_min, len(skew))]
215
+ return T_
216
+
217
+ def check(self):
218
+ """
219
+ Check that ``self`` is a valid primed tableau.
220
+
221
+ EXAMPLES::
222
+
223
+ sage: T = ShiftedPrimedTableaux([4,2])
224
+ sage: t = T([[1,'2p',2,2],[2,'3p']])
225
+ sage: t.check()
226
+ sage: s = ShiftedPrimedTableau([["2p",2,3],["2p"],[2]],skew=[2,1])
227
+ sage: s.check()
228
+ sage: t = T([['1p','2p',2,2],[2,'3p']])
229
+ Traceback (most recent call last):
230
+ ...
231
+ ValueError: [['1p', '2p', 2, 2], [2, '3p']] is not an element of
232
+ Shifted Primed Tableaux of shape [4, 2]
233
+
234
+ sage: T = ShiftedPrimedTableaux([4,2], primed_diagonal=True)
235
+ sage: t = T([['1p','2p',2,2],[2,'3p']]) # primed_diagonal allowed
236
+ sage: t.check()
237
+ sage: t = T([['1p','1p',2,2],[2,'3p']])
238
+ Traceback (most recent call last):
239
+ ...
240
+ ValueError: [['1p', '1p', 2, 2], [2, '3p']] is not an element of
241
+ Shifted Primed Tableaux of shape [4, 2] and maximum entry 6
242
+ """
243
+ if not self.parent()._contains_tableau(self):
244
+ raise ValueError("{} is not an element of Shifted Primed Tableaux".format(self))
245
+
246
+ def is_standard(self):
247
+ r"""
248
+ Return ``True`` if the entries of ``self`` are in bijection with
249
+ positive primed integers `1', 1, 2', \ldots, n`.
250
+
251
+ EXAMPLES::
252
+
253
+ sage: ShiftedPrimedTableau([["1'", 1, "2'"], [2, "3'"]],
254
+ ....: primed_diagonal=True).is_standard()
255
+ True
256
+ sage: ShiftedPrimedTableau([["1'", 1, 2], ["2'", "3'"]],
257
+ ....: primed_diagonal=True).is_standard()
258
+ True
259
+ sage: ShiftedPrimedTableau([["1'", 1, 1], ["2'", 2]],
260
+ ....: primed_diagonal=True).is_standard()
261
+ False
262
+ sage: ShiftedPrimedTableau([[1, "2'"], [2]]).is_standard()
263
+ False
264
+ sage: s = ShiftedPrimedTableau([[None, None,"1p","2p",2],[None,"1"]])
265
+ sage: s.is_standard()
266
+ True
267
+ """
268
+ flattened = {i for row in self for i in row if i is not None}
269
+ if len(flattened) != sum(len(row) - row.count(None) for row in self):
270
+ return False
271
+
272
+ a = PrimedEntry('1p')
273
+ while flattened:
274
+ if a not in flattened:
275
+ return False
276
+ flattened.remove(a)
277
+ a = a.increase_half()
278
+ return True
279
+
280
+ def __eq__(self, other):
281
+ """
282
+ Check whether ``self`` is equal to ``other``.
283
+
284
+ INPUT:
285
+
286
+ - ``other`` -- the element that ``self`` is compared to
287
+
288
+ OUTPUT: boolean
289
+
290
+ EXAMPLES::
291
+
292
+ sage: t = ShiftedPrimedTableau([[1,"2p"]])
293
+ sage: t == ShiftedPrimedTableaux([2])([[1,3/2]])
294
+ True
295
+ sage: s = ShiftedPrimedTableau([["2p",3]], skew=[1])
296
+ sage: s == [[None, "2p", 3]]
297
+ True
298
+ """
299
+ if isinstance(other, ShiftedPrimedTableau):
300
+ return self._skew == other._skew and list(self) == list(other)
301
+ try:
302
+ Tab = ShiftedPrimedTableau(other, primed_diagonal=self.parent()._primed_diagonal)
303
+ except (ValueError, TypeError):
304
+ return False
305
+ return self._skew == Tab._skew and list(self) == list(Tab)
306
+
307
+ def __ne__(self, other):
308
+ """
309
+ Check whether ``self`` is not equal to ``other``.
310
+
311
+ INPUT:
312
+
313
+ - ``other`` -- the element that ``self`` is compared to
314
+
315
+ OUTPUT: boolean
316
+
317
+ EXAMPLES::
318
+
319
+ sage: t = ShiftedPrimedTableau([[1,"2p"]])
320
+ sage: t != ShiftedPrimedTableaux([2])([[1,1]])
321
+ True
322
+ sage: s = ShiftedPrimedTableau([["2p",3]], skew=[1])
323
+ sage: s != [[None, "2p", 3]]
324
+ False
325
+ """
326
+ return not (self == other)
327
+
328
+ def __hash__(self):
329
+ """
330
+ Return the hash of ``self``.
331
+
332
+ EXAMPLES::
333
+
334
+ sage: t = ShiftedPrimedTableau([[1,"2p"]])
335
+ sage: hash(t) == hash(ShiftedPrimedTableaux([2])([[1,3/2]]))
336
+ True
337
+ """
338
+ return hash((self._skew, tuple(self)))
339
+
340
+ def _repr_(self):
341
+ """
342
+ Return a string representation of ``self``.
343
+
344
+ EXAMPLES::
345
+
346
+ sage: t = ShiftedPrimedTableau([[1,'2p',2,2],[2,'3p']])
347
+ sage: t
348
+ [(1, 2', 2, 2), (2, 3')]
349
+ sage: ShiftedPrimedTableau([["2p",2,3],["2p"]],skew=[2,1])
350
+ [(None, None, 2', 2, 3), (None, 2')]
351
+ """
352
+ return self.parent().options._dispatch(self, '_repr_', 'display')
353
+
354
+ def _repr_list(self):
355
+ """
356
+ Return a string representation of ``self`` as a list of tuples.
357
+
358
+ EXAMPLES::
359
+
360
+ sage: ShiftedPrimedTableau([['2p',3],[2,2]], skew=[2])._repr_list()
361
+ "[(None, None, 2', 3), (2, 2)]"
362
+ """
363
+ return repr(list(self))
364
+
365
+ def _repr_tab(self):
366
+ """
367
+ Return a nested list of strings representing the elements.
368
+
369
+ EXAMPLES::
370
+
371
+ sage: t = ShiftedPrimedTableau([[1,'2p',2,2],[2,'3p']])
372
+ sage: t._repr_tab()
373
+ [[' 1 ', " 2'", ' 2 ', ' 2 '], [' 2 ', " 3'"]]
374
+ sage: s = ShiftedPrimedTableau([["2p",2,3],["2p"]],skew=[2,1])
375
+ sage: s._repr_tab()
376
+ [[' . ', ' . ', " 2'", ' 2 ', ' 3 '], [' . ', " 2'"]]
377
+ """
378
+ max_len = len(str(self.max_entry())) + 2
379
+ repr_tab = []
380
+ for row in self:
381
+ repr_row = []
382
+ for entry in row:
383
+ if entry is None:
384
+ repr_row.append('. '.rjust(max_len))
385
+ elif entry.is_primed():
386
+ repr_row.append(repr(entry).rjust(max_len))
387
+ elif entry.is_unprimed():
388
+ repr_row.append(repr(entry).rjust(max_len-1)+" ")
389
+ repr_tab.append(repr_row)
390
+ return repr_tab
391
+
392
+ def _repr_diagram(self):
393
+ """
394
+ Return a string representation of ``self`` as an array.
395
+
396
+ EXAMPLES::
397
+
398
+ sage: t = ShiftedPrimedTableau([[1,'2p',2,2],[2,'3p']])
399
+ sage: print(t._repr_diagram())
400
+ 1 2' 2 2
401
+ 2 3'
402
+ sage: t = ShiftedPrimedTableau([[10,'11p',11,11],[11,'12']])
403
+ sage: print(t._repr_diagram())
404
+ 10 11' 11 11
405
+ 11 12
406
+ sage: s = ShiftedPrimedTableau([["2p",2,3],["2p"]],skew=[2,1])
407
+ sage: print(s._repr_diagram())
408
+ . . 2' 2 3
409
+ . 2'
410
+ """
411
+ max_len = len(str(self.max_entry()))+2
412
+ return "\n".join([" "*max_len*i + "".join(val)
413
+ for i, val in enumerate(self._repr_tab())])
414
+
415
+ _repr_compact = _repr_diagram
416
+
417
+ def _ascii_art_(self):
418
+ """
419
+ Return ASCII representation of ``self``.
420
+
421
+ EXAMPLES::
422
+
423
+ sage: ascii_art(ShiftedPrimedTableau([[1,'2p',2,2],[2,'3p']]))
424
+ +---+---+---+---+
425
+ | 1 | 2'| 2 | 2 |
426
+ +---+---+---+---+
427
+ | 2 | 3'|
428
+ +---+---+
429
+ sage: s = ShiftedPrimedTableau([["2p",2,3],["2p"]],skew=[2,1])
430
+ sage: ascii_art(s)
431
+ +---+---+---+---+---+
432
+ | . | . | 2'| 2 | 3 |
433
+ +---+---+---+---+---+
434
+ | . | 2'|
435
+ +---+---+
436
+
437
+ TESTS::
438
+
439
+ sage: ascii_art(ShiftedPrimedTableau([]))
440
+ ++
441
+ ++
442
+
443
+ sage: ascii_art(ShiftedPrimedTableau([], skew=[1]))
444
+ +---+
445
+ | . |
446
+ +---+
447
+ """
448
+ from sage.typeset.ascii_art import AsciiArt
449
+ return AsciiArt(self._ascii_art_table(unicode=False).splitlines())
450
+
451
+ def _unicode_art_(self):
452
+ """
453
+ Return a Unicode representation of ``self``.
454
+
455
+ EXAMPLES::
456
+
457
+ sage: unicode_art(ShiftedPrimedTableau([[1,'2p',2,2],[2,'3p']]))
458
+ ┌───┬───┬───┬───┐
459
+ │ 1 │ 2'│ 2 │ 2 │
460
+ └───┼───┼───┼───┘
461
+ │ 2 │ 3'│
462
+ └───┴───┘
463
+ sage: s = ShiftedPrimedTableau([["2p",2,3],["2p"]],skew=[2,1])
464
+ sage: unicode_art(s)
465
+ ┌───┬───┬───┬───┬───┐
466
+ │ . │ . │ 2'│ 2 │ 3 │
467
+ └───┼───┼───┼───┴───┘
468
+ │ . │ 2'│
469
+ └───┴───┘
470
+
471
+ TESTS::
472
+
473
+ sage: unicode_art(ShiftedPrimedTableau([]))
474
+ ┌┐
475
+ └┘
476
+ sage: unicode_art(ShiftedPrimedTableau([], skew=[1]))
477
+ ┌───┐
478
+ │ . │
479
+ └───┘
480
+ """
481
+ from sage.typeset.unicode_art import UnicodeArt
482
+ return UnicodeArt(self._ascii_art_table(unicode=True).splitlines())
483
+
484
+ def _ascii_art_table(self, unicode=False):
485
+ """
486
+ TESTS::
487
+
488
+ sage: t = ShiftedPrimedTableau([[1,'2p',2],[2,'3p']])
489
+ sage: print(t._ascii_art_table(unicode=True))
490
+ ┌───┬───┬───┐
491
+ │ 1 │ 2'│ 2 │
492
+ └───┼───┼───┤
493
+ │ 2 │ 3'│
494
+ └───┴───┘
495
+ sage: print(t._ascii_art_table())
496
+ +---+---+---+
497
+ | 1 | 2'| 2 |
498
+ +---+---+---+
499
+ | 2 | 3'|
500
+ +---+---+
501
+ sage: s = ShiftedPrimedTableau([[1,'2p',2, 23],[2,'30p']])
502
+ sage: print(s._ascii_art_table(unicode=True))
503
+ ┌────┬────┬────┬────┐
504
+ │ 1 │ 2'│ 2 │ 23 │
505
+ └────┼────┼────┼────┘
506
+ │ 2 │ 30'│
507
+ └────┴────┘
508
+ sage: print(s._ascii_art_table(unicode=False))
509
+ +----+----+----+----+
510
+ | 1 | 2'| 2 | 23 |
511
+ +----+----+----+----+
512
+ | 2 | 30'|
513
+ +----+----+
514
+ sage: s = ShiftedPrimedTableau([["2p",2,10],["2p"]],skew=[2,1])
515
+ sage: print(s._ascii_art_table(unicode=True))
516
+ ┌────┬────┬────┬────┬────┐
517
+ │ . │ . │ 2'│ 2 │ 10 │
518
+ └────┼────┼────┼────┴────┘
519
+ │ . │ 2'│
520
+ └────┴────┘
521
+ """
522
+ if unicode:
523
+ import unicodedata
524
+ v = unicodedata.lookup('BOX DRAWINGS LIGHT VERTICAL')
525
+ h = unicodedata.lookup('BOX DRAWINGS LIGHT HORIZONTAL')
526
+ dl = unicodedata.lookup('BOX DRAWINGS LIGHT DOWN AND LEFT')
527
+ dr = unicodedata.lookup('BOX DRAWINGS LIGHT DOWN AND RIGHT')
528
+ ul = unicodedata.lookup('BOX DRAWINGS LIGHT UP AND LEFT')
529
+ ur = unicodedata.lookup('BOX DRAWINGS LIGHT UP AND RIGHT')
530
+ vl = unicodedata.lookup('BOX DRAWINGS LIGHT VERTICAL AND LEFT')
531
+ uh = unicodedata.lookup('BOX DRAWINGS LIGHT UP AND HORIZONTAL')
532
+ dh = unicodedata.lookup('BOX DRAWINGS LIGHT DOWN AND HORIZONTAL')
533
+ vh = unicodedata.lookup(
534
+ 'BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL')
535
+ else:
536
+ v = '|'
537
+ h = '-'
538
+ dl = dr = ul = ur = vl = uh = dh = vh = '+'
539
+
540
+ if not self.shape():
541
+ return dr + dl + '\n' + ur + ul
542
+
543
+ # Get the widths of the columns
544
+ str_tab = self._repr_tab()
545
+ width = len(str_tab[0][0])
546
+ str_list = [dr + (h*width + dh)*(len(str_tab[0])-1) + h*width + dl]
547
+ for nrow, row in enumerate(str_tab):
548
+ l1 = " " * (width+1) * nrow
549
+ l2 = " " * (width+1) * nrow
550
+ n = len(str_tab[nrow+1]) if nrow+1 < len(str_tab) else -1
551
+ for i, e in enumerate(row):
552
+ if i == 0:
553
+ l1 += ur + h*width
554
+ elif i <= n+1:
555
+ l1 += vh + h*width
556
+ else:
557
+ l1 += uh + h*width
558
+ if unicode:
559
+ l2 += "{}{:^{width}}".format(v, e, width=width)
560
+ else:
561
+ l2 += "{}{:^{width}}".format(v, e, width=width)
562
+ if i <= n:
563
+ l1 += vl
564
+ else:
565
+ l1 += ul
566
+ l2 += v
567
+ str_list.append(l2)
568
+ str_list.append(l1)
569
+ return "\n".join(str_list)
570
+
571
+ def pp(self):
572
+ """
573
+ Pretty print ``self``.
574
+
575
+ EXAMPLES::
576
+
577
+ sage: t = ShiftedPrimedTableau([[1,'2p',2,2],[2,'3p']])
578
+ sage: t.pp()
579
+ 1 2' 2 2
580
+ 2 3'
581
+ sage: t = ShiftedPrimedTableau([[10,'11p',11,11],[11,'12']])
582
+ sage: t.pp()
583
+ 10 11' 11 11
584
+ 11 12
585
+ sage: s = ShiftedPrimedTableau([['2p',2,3],['2p']],skew=[2,1])
586
+ sage: s.pp()
587
+ . . 2' 2 3
588
+ . 2'
589
+
590
+ TESTS::
591
+
592
+ sage: ShiftedPrimedTableau([],skew=[1]).pp()
593
+ .
594
+ sage: ShiftedPrimedTableau([]).pp()
595
+ <BLANKLINE>
596
+ """
597
+ print(self._repr_diagram())
598
+
599
+ def _latex_(self):
600
+ r"""
601
+ Return LaTex code for ``self``.
602
+
603
+ EXAMPLES::
604
+
605
+ sage: T = ShiftedPrimedTableaux([4,2])
606
+ sage: latex(T([[1,"2p",2,"3p"],[2,3]]))
607
+ {\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
608
+ \raisebox{-.6ex}{$\begin{array}[b]{*{4}c}\cline{1-4}
609
+ \lr{ 1 }&\lr{ 2'}&\lr{ 2 }&\lr{ 3'}\\\cline{1-4}
610
+ &\lr{ 2 }&\lr{ 3 }\\\cline{2-3}
611
+ \end{array}$}
612
+ }
613
+ """
614
+ from sage.combinat.output import tex_from_array
615
+ L = [[None]*i + row for i, row in enumerate(self._repr_tab())]
616
+ return tex_from_array(L)
617
+
618
+ def max_entry(self):
619
+ r"""
620
+ Return the minimum unprimed letter `x > y` for all `y` in ``self``.
621
+
622
+ EXAMPLES::
623
+
624
+ sage: Tab = ShiftedPrimedTableau([(1,1,'2p','3p'),(2,2)])
625
+ sage: Tab.max_entry()
626
+ 3
627
+
628
+ TESTS::
629
+
630
+ sage: Tab = ShiftedPrimedTableau([], skew=[2,1])
631
+ sage: Tab.max_entry()
632
+ 0
633
+ sage: Tab = ShiftedPrimedTableau([["1p"]], skew=[2,1])
634
+ sage: Tab.max_entry()
635
+ 1
636
+ """
637
+ flat = [entry.unprimed() for row in self
638
+ for entry in row if entry is not None]
639
+ if len(flat) == 0:
640
+ return 0
641
+ return max(flat)
642
+
643
+ def shape(self):
644
+ r"""
645
+ Return the shape of the underlying partition of ``self``.
646
+
647
+ EXAMPLES::
648
+
649
+ sage: t = ShiftedPrimedTableau([[1,'2p',2,2],[2,'3p']])
650
+ sage: t.shape()
651
+ [4, 2]
652
+ sage: s = ShiftedPrimedTableau([["2p",2,3],["2p"]],skew=[2,1])
653
+ sage: s.shape()
654
+ [5, 2] / [2, 1]
655
+ """
656
+ if self._skew is None:
657
+ return Partition([len(row) for row in self])
658
+ return SkewPartition(([len(row) for row in self], self._skew))
659
+
660
+ def restrict(self, n):
661
+ """
662
+ Return the restriction of the shifted tableau to all
663
+ the numbers less than or equal to ``n``.
664
+
665
+ .. NOTE::
666
+
667
+ If only the outer shape of the restriction, rather than
668
+ the whole restriction, is needed, then the faster method
669
+ :meth:`restriction_outer_shape` is preferred. Similarly if
670
+ only the skew shape is needed, use :meth:`restriction_shape`.
671
+
672
+ EXAMPLES::
673
+
674
+ sage: t = ShiftedPrimedTableau([[1,'2p',2,2],[2,'3p']])
675
+ sage: t.restrict(2).pp()
676
+ 1 2' 2 2
677
+ 2
678
+
679
+ sage: t.restrict("2p").pp()
680
+ 1 2'
681
+
682
+ sage: s = ShiftedPrimedTableau([["2p",2,3],["2p"]], skew=[2,1])
683
+ sage: s.restrict(2).pp()
684
+ . . 2' 2
685
+ . 2'
686
+ sage: s.restrict(1.5).pp()
687
+ . . 2'
688
+ . 2'
689
+ """
690
+ t = self[:]
691
+ n = PrimedEntry(n)
692
+ loop = ([y for y in x if y is not None and y <= n] for x in t)
693
+ return ShiftedPrimedTableau([z for z in loop if z], skew=self._skew)
694
+
695
+ def restriction_outer_shape(self, n):
696
+ """
697
+ Return the outer shape of the restriction of the shifted
698
+ tableau ``self`` to `n`.
699
+
700
+ If `T` is a (skew) shifted tableau and `n` is a half-integer,
701
+ then the restriction of `T` to `n` is defined as the (skew)
702
+ shifted tableau obtained by removing all cells filled with
703
+ entries greater than `n` from `T`.
704
+
705
+ This method computes merely the outer shape of the restriction.
706
+ For the restriction itself, use :meth:`restrict`.
707
+
708
+ EXAMPLES::
709
+
710
+ sage: s = ShiftedPrimedTableau([["2p",2,3],["2p"]], skew=[2,1])
711
+ sage: s.pp()
712
+ . . 2' 2 3
713
+ . 2'
714
+ sage: s.restriction_outer_shape(2)
715
+ [4, 2]
716
+ sage: s.restriction_outer_shape("2p")
717
+ [3, 2]
718
+ """
719
+ n = PrimedEntry(n)
720
+ if self._skew is None:
721
+ res = [len([y for y in row if y <= n]) for row in self]
722
+ else:
723
+ res = [len([y for y in row if y is None or y <= n])
724
+ for i, row in enumerate(self)]
725
+
726
+ return Partition(res)
727
+
728
+ def restriction_shape(self, n):
729
+ """
730
+ Return the skew shape of the restriction of the skew tableau
731
+ ``self`` to ``n``.
732
+
733
+ If `T` is a shifted tableau and `n` is a half-integer, then
734
+ the restriction of `T` to `n` is defined as the
735
+ (skew) shifted tableau obtained by removing all cells
736
+ filled with entries greater than `n` from `T`.
737
+
738
+ This method computes merely the skew shape of the restriction.
739
+ For the restriction itself, use :meth:`restrict`.
740
+
741
+ EXAMPLES::
742
+
743
+ sage: s = ShiftedPrimedTableau([["2p",2,3],["2p"]], skew=[2,1])
744
+ sage: s.pp()
745
+ . . 2' 2 3
746
+ . 2'
747
+
748
+ sage: s.restriction_shape(2)
749
+ [4, 2] / [2, 1]
750
+ """
751
+ if self._skew is None:
752
+ return Partition(self.restriction_outer_shape(n))
753
+ else:
754
+ return SkewPartition([self.restriction_outer_shape(n), self._skew])
755
+
756
+ def to_chain(self):
757
+ """
758
+ Return the chain of partitions corresponding to the (skew)
759
+ shifted tableau ``self``, interlaced by one of the colours
760
+ ``1`` is the added cell is on the diagonal, ``2`` if an
761
+ ordinary entry is added and ``3`` if a primed entry is added.
762
+
763
+ EXAMPLES::
764
+
765
+ sage: s = ShiftedPrimedTableau([(1, 2, 3.5, 5, 6.5), (3, 5.5)])
766
+ sage: s.pp()
767
+ 1 2 4' 5 7'
768
+ 3 6'
769
+
770
+ sage: s.to_chain()
771
+ [[], 1, [1], 2, [2], 1, [2, 1], 3, [3, 1], 2, [4, 1], 3, [4, 2], 3, [5, 2]]
772
+
773
+
774
+ sage: s = ShiftedPrimedTableau([(1, 3.5), (2.5,), (6,)], skew=[2,1])
775
+ sage: s.pp()
776
+ . . 1 4'
777
+ . 3'
778
+ 6
779
+
780
+ sage: s.to_chain()
781
+ [[2, 1], 2, [3, 1], 0, [3, 1], 3, [3, 2], 3, [4, 2], 0, [4, 2], 1, [4, 2, 1]]
782
+
783
+ TESTS::
784
+
785
+ sage: s = ShiftedPrimedTableau([["2p",2,3],["2p"]], skew=[2,1])
786
+ sage: s.pp()
787
+ . . 2' 2 3
788
+ . 2'
789
+ sage: s.to_chain()
790
+ Traceback (most recent call last):
791
+ ...
792
+ ValueError: can compute a chain of partitions only for
793
+ skew shifted tableaux without repeated entries
794
+ """
795
+ if any(e not in [0, 1] for e in self.weight()):
796
+ raise ValueError("can compute a chain of partitions only for skew"
797
+ " shifted tableaux without repeated entries")
798
+ entries = sorted(e for row in self for e in row if e is not None)
799
+ if self._skew is None:
800
+ mu = Partition([])
801
+ m = 0
802
+ else:
803
+ mu = self._skew
804
+ m = len(self._skew)
805
+ chain = [mu]
806
+ f = 0
807
+ for e in entries:
808
+ n = e.integer()
809
+ chain.extend([0, mu]*int(n-f-1))
810
+ mu = self.restriction_outer_shape(e)
811
+ if n == e:
812
+ if any(e == row[0] for i, row in enumerate(self) if i >= m or self._skew[i] == 0):
813
+ chain.append(1)
814
+ else:
815
+ chain.append(2)
816
+ else:
817
+ chain.append(3)
818
+ chain.append(mu)
819
+ f = n
820
+ return chain
821
+
822
+ def weight(self):
823
+ r"""
824
+ Return the weight of ``self``.
825
+
826
+ The weight of a shifted primed tableau is defined to be the vector
827
+ with `i`-th component equal to the number of entries `i` and `i'`
828
+ in the tableau.
829
+
830
+ EXAMPLES::
831
+
832
+ sage: t = ShiftedPrimedTableau([['2p',2,2],[2,'3p']], skew=[1])
833
+ sage: t.weight()
834
+ (0, 4, 1)
835
+ """
836
+ flat = [entry.integer() for row in self
837
+ for entry in row if entry is not None]
838
+ if not flat:
839
+ return ()
840
+
841
+ weight = tuple([flat.count(i+1) for i in range(max(flat))])
842
+ return weight
843
+
844
+
845
+ class CrystalElementShiftedPrimedTableau(ShiftedPrimedTableau):
846
+ """
847
+ Class for elements of ``crystals.ShiftedPrimedTableau``.
848
+ """
849
+
850
+ def _to_matrix(self):
851
+ """
852
+ Return a 2-dimensional array representation of a shifted tableau.
853
+
854
+ EXAMPLES::
855
+
856
+ sage: SPT = ShiftedPrimedTableaux([4,2,1])
857
+ sage: t = SPT([[1,'2p',2,2],[2,'3p'],[3]])
858
+ sage: mat = t._to_matrix()
859
+ sage: mat
860
+ [[1, 2', 2, 2], [None, 2, 3', None], [None, None, 3, None]]
861
+ """
862
+ m = len(self[0])
863
+ return [[None]*i + list(row) + [None]*(m-i-len(row))
864
+ for i, row in enumerate(self)]
865
+
866
+ def _reading_word_with_positions(self):
867
+ """
868
+ Iterate over the reading word of ``self`` together with positions
869
+ of the corresponding letters in ``self``.
870
+
871
+ The reading word of a shifted primed tableau is constructed
872
+ as follows:
873
+
874
+ 1. List all primed entries in the tableau, column by
875
+ column, in decreasing order within each column, moving
876
+ from the rightmost column to the left, and with all
877
+ the primes removed (i.e. all entries are increased by
878
+ half a unit).
879
+
880
+ 2. Then list all unprimed entries, row by row, in
881
+ increasing order within each row, moving from the
882
+ bottommost row to the top.
883
+
884
+ EXAMPLES::
885
+
886
+ sage: SPT = ShiftedPrimedTableaux([4,2])
887
+ sage: t = SPT([[1,'2p',2,2],[2,'3p']])
888
+ sage: list(t._reading_word_with_positions())
889
+ [((1, 2), 3), ((0, 1), 2), ((1, 1), 2), ((0, 0), 1),
890
+ ((0, 2), 2), ((0, 3), 2)]
891
+ """
892
+ mat = self._to_matrix()
893
+ ndim, mdim = len(mat), len(mat[0])
894
+ for j in reversed(range(mdim)):
895
+ for i in range(ndim):
896
+ x = mat[i][j]
897
+ if x is not None and x.is_primed():
898
+ yield ((i, j), x.integer())
899
+ for i in reversed(range(ndim)):
900
+ for j in range(mdim):
901
+ x = mat[i][j]
902
+ if x is not None and x.is_unprimed():
903
+ yield ((i, j), x.integer())
904
+
905
+ def reading_word(self):
906
+ """
907
+ Return the reading word of ``self``.
908
+
909
+ The reading word of a shifted primed tableau is constructed
910
+ as follows:
911
+
912
+ 1. List all primed entries in the tableau, column by
913
+ column, in decreasing order within each column, moving
914
+ from the rightmost column to the left, and with all
915
+ the primes removed (i.e. all entries are increased by
916
+ half a unit).
917
+
918
+ 2. Then list all unprimed entries, row by row, in
919
+ increasing order within each row, moving from the
920
+ bottommost row to the top.
921
+
922
+ EXAMPLES::
923
+
924
+ sage: SPT = ShiftedPrimedTableaux([4,2])
925
+ sage: t = SPT([[1,'2p',2,2],[2,'3p']])
926
+ sage: t.reading_word()
927
+ [3, 2, 2, 1, 2, 2]
928
+ """
929
+ if self._skew is not None:
930
+ raise NotImplementedError('skew tableau must be empty')
931
+ return [tup[1] for tup in self._reading_word_with_positions()]
932
+
933
+ def f(self, ind):
934
+ r"""
935
+ Compute the action of the crystal operator `f_i` on a shifted primed
936
+ tableau using cases from the papers [HPS2017]_ and [AO2018]_.
937
+
938
+ INPUT:
939
+
940
+ - ``ind`` -- element in the index set of the crystal
941
+
942
+ OUTPUT: primed tableau or ``None``
943
+
944
+ EXAMPLES::
945
+
946
+ sage: SPT = ShiftedPrimedTableaux([5,4,2])
947
+ sage: t = SPT([[1,1,1,1,'3p'],[2,2,2,'3p'],[3,3]])
948
+ sage: t.pp()
949
+ 1 1 1 1 3'
950
+ 2 2 2 3'
951
+ 3 3
952
+ sage: s = t.f(2)
953
+ sage: s is None
954
+ True
955
+
956
+ sage: t = SPT([[1,1,1,'2p','3p'],[2,2,3,3],[3,4]])
957
+ sage: t.pp()
958
+ 1 1 1 2' 3'
959
+ 2 2 3 3
960
+ 3 4
961
+ sage: s = t.f(2)
962
+ sage: s.pp()
963
+ 1 1 1 2' 3'
964
+ 2 3' 3 3
965
+ 3 4
966
+
967
+ sage: SPT = ShiftedPrimedTableaux([2,1])
968
+ sage: t = SPT([[1,1],[2]])
969
+ sage: t.f(-1).pp()
970
+ 1 2'
971
+ 2
972
+ sage: t.f(1).pp()
973
+ 1 2'
974
+ 2
975
+ sage: t.f(2).pp()
976
+ 1 1
977
+ 3
978
+
979
+ sage: r = SPT([[1,'2p'],[2]])
980
+ sage: r.f(-1) is None
981
+ True
982
+ sage: r.f(1) is None
983
+ True
984
+ sage: r.f(2).pp()
985
+ 1 2'
986
+ 3
987
+
988
+ sage: r = SPT([[1,1],[3]])
989
+ sage: r.f(-1).pp()
990
+ 1 2'
991
+ 3
992
+ sage: r.f(1).pp()
993
+ 1 2
994
+ 3
995
+ sage: r.f(2) is None
996
+ True
997
+
998
+ sage: r = SPT([[1,2],[3]])
999
+ sage: r.f(-1).pp()
1000
+ 2 2
1001
+ 3
1002
+ sage: r.f(1).pp()
1003
+ 2 2
1004
+ 3
1005
+ sage: r.f(2) is None
1006
+ True
1007
+
1008
+ sage: t = SPT([[1,1],[2]])
1009
+ sage: t.f(-1).f(2).f(2).f(-1) == t.f(2).f(1).f(-1).f(2)
1010
+ True
1011
+ sage: t.f(-1).f(2).f(2).f(-1).pp()
1012
+ 2 3'
1013
+ 3
1014
+ sage: all(t.f(-1).f(2).f(2).f(-1).f(i) is None for i in {-1, 1, 2})
1015
+ True
1016
+
1017
+ sage: SPT = ShiftedPrimedTableaux([4])
1018
+ sage: t = SPT([[1,1,1,1]])
1019
+ sage: t.f(-1).pp()
1020
+ 1 1 1 2'
1021
+ sage: t.f(1).pp()
1022
+ 1 1 1 2
1023
+ sage: t.f(-1).f(-1) is None
1024
+ True
1025
+ sage: t.f(1).f(-1).pp()
1026
+ 1 1 2' 2
1027
+ sage: t.f(1).f(1).pp()
1028
+ 1 1 2 2
1029
+ sage: t.f(1).f(1).f(-1).pp()
1030
+ 1 2' 2 2
1031
+ sage: t.f(1).f(1).f(1).pp()
1032
+ 1 2 2 2
1033
+ sage: t.f(1).f(1).f(1).f(-1).pp()
1034
+ 2 2 2 2
1035
+ sage: t.f(1).f(1).f(1).f(1).pp()
1036
+ 2 2 2 2
1037
+ sage: t.f(1).f(1).f(1).f(1).f(-1) is None
1038
+ True
1039
+ """
1040
+ T = self._to_matrix()
1041
+
1042
+ # special logic for queer lowering operator f_{-1}
1043
+ if ind == -1:
1044
+ read_word = [num for num in self._reading_word_with_positions() if num[1] in {1, 2}]
1045
+
1046
+ # f_{-1} acts as zero if tableau contains 2'
1047
+ if any(elt == 2 and T[pos[0]][pos[1]].is_primed() for pos, elt in read_word):
1048
+ return None
1049
+
1050
+ ones = sorted([pos for pos, elt in read_word if elt == 1], key=lambda x: x[1])
1051
+
1052
+ # f_{-1} acts as zero if tableau contains no entries equal to 1
1053
+ if len(ones) == 0:
1054
+ return None
1055
+ # otherwise, f_{-1} changes last 1 in first row to 2' (if off diagonal) or 2 (if on diagonal)
1056
+ else:
1057
+ r, c = ones[-1]
1058
+ assert r == 0
1059
+ T[r][c] = PrimedEntry('2p') if r != c else PrimedEntry(2)
1060
+ T = [tuple(elmt for elmt in row if elmt is not None) for row in T]
1061
+ return type(self)(self.parent(), T, check=False, preprocessed=True)
1062
+
1063
+ read_word = [num for num in self._reading_word_with_positions()
1064
+ if num[1] == ind or num[1] == ind+1]
1065
+
1066
+ element_to_change = None
1067
+ count = 0
1068
+
1069
+ for element in read_word:
1070
+ if element[1] == ind+1:
1071
+ count += 1
1072
+ elif count == 0:
1073
+ element_to_change = element
1074
+ else:
1075
+ count -= 1
1076
+
1077
+ if element_to_change is None:
1078
+ return None
1079
+
1080
+ (r, c), elt = element_to_change
1081
+ ind_e = PrimedEntry(ind)
1082
+ ind_plus_one = ind_e.increase_one()
1083
+ ind_plus_half = ind_e.increase_half()
1084
+
1085
+ if T[r][c].is_primed():
1086
+ T = [[elmt.increase_half() if elmt is not None else elmt
1087
+ for elmt in row] for row in T]
1088
+ T = [list(z) for z in zip(*T)]
1089
+ r, c = c, r
1090
+ h, l = len(T), len(T[0])
1091
+
1092
+ if (c+1 == l or T[r][c+1] is None or T[r][c+1] >= ind_plus_one):
1093
+ (tp_r, tp_c) = (r, c)
1094
+ while True:
1095
+ if tp_r+1 == h or T[tp_r+1][tp_c] is None or T[tp_r+1][tp_c] > ind_plus_one:
1096
+ break
1097
+ if tp_r <= tp_c and T[tp_r+1][tp_r+1] == ind_plus_one:
1098
+ tp_r += 1
1099
+ tp_c = tp_r
1100
+ break
1101
+ if ind_plus_half not in T[tp_r+1]:
1102
+ break
1103
+ tp_r += 1
1104
+ tp_c = T[tp_r].index(ind_plus_half)
1105
+
1106
+ if tp_r == r:
1107
+ T[r][c] = T[r][c].increase_one()
1108
+ elif tp_r == tp_c:
1109
+ T[r][c] = T[r][c].increase_half()
1110
+ else:
1111
+ T[r][c] = T[r][c].increase_half()
1112
+ T[tp_r][tp_c] = T[tp_r][tp_c].increase_half()
1113
+
1114
+ elif T[r][c+1] == ind_plus_half:
1115
+ T[r][c+1] = T[r][c+1].increase_half()
1116
+ T[r][c] = T[r][c].increase_half()
1117
+
1118
+ if r > c:
1119
+ T = [[elmt.decrease_half() if elmt is not None else elmt
1120
+ for elmt in row] for row in T]
1121
+ T = [list(z) for z in zip(*T)]
1122
+
1123
+ T = [tuple(elmt for elmt in row if elmt is not None) for row in T]
1124
+ return type(self)(self.parent(), T, check=False, preprocessed=True)
1125
+
1126
+ def e(self, ind):
1127
+ r"""
1128
+ Compute the action of the crystal operator `e_i` on a shifted primed
1129
+ tableau using cases from the papers [HPS2017]_ and [AO2018]_.
1130
+
1131
+ INPUT:
1132
+
1133
+ - ``ind`` -- an element in the index set of the crystal
1134
+
1135
+ OUTPUT: primed tableau or ``None``
1136
+
1137
+ EXAMPLES::
1138
+
1139
+ sage: SPT = ShiftedPrimedTableaux([5,4,2])
1140
+ sage: t = SPT([[1,1,1,'2p','3p'], [2,'3p',3,3],[3,4]])
1141
+ sage: t.pp()
1142
+ 1 1 1 2' 3'
1143
+ 2 3' 3 3
1144
+ 3 4
1145
+ sage: s = t.e(2)
1146
+ sage: s.pp()
1147
+ 1 1 1 2' 3'
1148
+ 2 2 3 3
1149
+ 3 4
1150
+ sage: t == s.f(2)
1151
+ True
1152
+
1153
+ sage: SPT = ShiftedPrimedTableaux([2,1])
1154
+ sage: t = SPT([[2,'3p'],[3]])
1155
+ sage: t.e(-1).pp()
1156
+ 1 3'
1157
+ 3
1158
+ sage: t.e(1).pp()
1159
+ 1 3'
1160
+ 3
1161
+ sage: t.e(2).pp()
1162
+ 2 2
1163
+ 3
1164
+
1165
+ sage: r = SPT([[2, 2],[3]])
1166
+ sage: r.e(-1).pp()
1167
+ 1 2
1168
+ 3
1169
+ sage: r.e(1).pp()
1170
+ 1 2
1171
+ 3
1172
+ sage: r.e(2) is None
1173
+ True
1174
+
1175
+ sage: r = SPT([[1,'3p'],[3]])
1176
+ sage: r.e(-1) is None
1177
+ True
1178
+ sage: r.e(1) is None
1179
+ True
1180
+ sage: r.e(2).pp()
1181
+ 1 2'
1182
+ 3
1183
+ sage: r = SPT([[1,'2p'],[3]])
1184
+ sage: r.e(-1).pp()
1185
+ 1 1
1186
+ 3
1187
+ sage: r.e(1) is None
1188
+ True
1189
+ sage: r.e(2).pp()
1190
+ 1 2'
1191
+ 2
1192
+ sage: t = SPT([[2,'3p'],[3]])
1193
+ sage: t.e(-1).e(2).e(2).e(-1) == t.e(2).e(1).e(1).e(2)
1194
+ True
1195
+ sage: t.e(-1).e(2).e(2).e(-1).pp()
1196
+ 1 1
1197
+ 2
1198
+ sage: all(t.e(-1).e(2).e(2).e(-1).e(i) is None for i in {-1, 1, 2})
1199
+ True
1200
+
1201
+ sage: SPT = ShiftedPrimedTableaux([4])
1202
+ sage: t = SPT([[2,2,2,2]])
1203
+ sage: t.e(-1).pp()
1204
+ 1 2 2 2
1205
+ sage: t.e(1).pp()
1206
+ 1 2 2 2
1207
+ sage: t.e(-1).e(-1) is None
1208
+ True
1209
+ sage: t.e(1).e(1).pp()
1210
+ 1 1 2 2
1211
+ """
1212
+ T = self._to_matrix()
1213
+
1214
+ # special logic for queer raising operator e_{-1}
1215
+ if ind == -1:
1216
+ read_word = [num for num in self._reading_word_with_positions() if num[1] in {1, 2}]
1217
+
1218
+ two_primes = sorted(
1219
+ [pos for pos, elt in read_word if elt == 2 and T[pos[0]][pos[1]].is_primed()],
1220
+ key=lambda x: x[1]
1221
+ )
1222
+
1223
+ # e_{-1} acts as zero if tableau contains no 2' and first diagonal entry is not 2
1224
+ if len(two_primes) == 0:
1225
+ if T[0][0] != PrimedEntry(2):
1226
+ return None
1227
+ # if tableau has no 2' but first diagonal entry is 2, then e_{-1} changes this to 1
1228
+ else:
1229
+ T[0][0] = PrimedEntry(1)
1230
+ # if tableau has at least one 2', then e_{-1} changes the first 2' to 1
1231
+ else:
1232
+ r, c = two_primes[0]
1233
+ assert r == 0
1234
+ T[r][c] = PrimedEntry(1)
1235
+
1236
+ T = [tuple(elmt for elmt in row if elmt is not None) for row in T]
1237
+ return type(self)(self.parent(), T, check=False, preprocessed=True)
1238
+
1239
+ read_word = [num for num in self._reading_word_with_positions()
1240
+ if num[1] == ind or num[1] == ind+1]
1241
+
1242
+ element_to_change = None
1243
+ count = 0
1244
+
1245
+ for element in reversed(read_word):
1246
+ if element[1] == ind:
1247
+ count += 1
1248
+ elif count == 0:
1249
+ element_to_change = element
1250
+ else:
1251
+ count -= 1
1252
+
1253
+ if element_to_change is None:
1254
+ return None
1255
+ (r, c), elt = element_to_change
1256
+
1257
+ ind_e = PrimedEntry(ind)
1258
+ ind_plus_half = ind_e.increase_half()
1259
+
1260
+ if T[r][c].is_primed():
1261
+ T = [[elmt.increase_half() if elmt is not None else elmt
1262
+ for elmt in row] for row in T]
1263
+ T = [list(z) for z in zip(*T)]
1264
+ r, c = c, r
1265
+
1266
+ if (c == 0 or T[r][c-1] is None or T[r][c-1] <= ind_e):
1267
+ (tp_r, tp_c) = (r, c)
1268
+ while True:
1269
+ if tp_r == 0 or T[tp_r-1][tp_c] is None or T[tp_r-1][tp_c] < ind_e:
1270
+ break
1271
+ if ind_plus_half not in T[tp_r-1]:
1272
+ break
1273
+ tp_r -= 1
1274
+ tp_c = T[tp_r].index(ind_plus_half)
1275
+
1276
+ if tp_r == r:
1277
+ T[r][c] = T[r][c].decrease_one()
1278
+ elif tp_r == tp_c:
1279
+ T[r][c] = T[r][c].decrease_half()
1280
+ else:
1281
+ T[r][c] = T[r][c].decrease_half()
1282
+ T[tp_r][tp_c] = T[tp_r][tp_c].decrease_half()
1283
+
1284
+ elif T[r][c-1] == ind_plus_half:
1285
+ T[r][c-1] = T[r][c-1].decrease_half()
1286
+ T[r][c] = T[r][c].decrease_half()
1287
+ if r > c:
1288
+ T = [[elmt.decrease_half() if elmt is not None else elmt
1289
+ for elmt in row] for row in T]
1290
+ T = [list(z) for z in zip(*T)]
1291
+
1292
+ T = [tuple(elmt for elmt in row if elmt is not None) for row in T]
1293
+ return type(self)(self.parent(), T, check=False, preprocessed=True)
1294
+
1295
+ def is_highest_weight(self, index_set=None):
1296
+ r"""
1297
+ Return whether ``self`` is a highest weight element of the crystal.
1298
+
1299
+ An element is highest weight if it vanishes under all crystal
1300
+ operators `e_i`.
1301
+
1302
+ EXAMPLES::
1303
+
1304
+ sage: SPT = ShiftedPrimedTableaux([5,4,2])
1305
+ sage: t = SPT([(1, 1, 1, 1, 1), (2, 2, 2, "3p"), (3, 3)])
1306
+ sage: t.is_highest_weight()
1307
+ True
1308
+
1309
+ sage: SPT = ShiftedPrimedTableaux([5,4])
1310
+ sage: s = SPT([(1, 1, 1, 1, 1), (2, 2, "3p", 3)])
1311
+ sage: s.is_highest_weight(index_set=[1])
1312
+ True
1313
+ """
1314
+ read_w = self.reading_word()
1315
+ max_entry = max(read_w)
1316
+ count = {i: 0 for i in range(max_entry+1)}
1317
+ if index_set is None:
1318
+ index_set = self.parent().index_set()
1319
+ for l in reversed(read_w):
1320
+ count[l] += 1
1321
+ if l-1 in index_set and l > 1 and count[l] > count[l-1]:
1322
+ return False
1323
+ return True
1324
+
1325
+ def weight(self):
1326
+ r"""
1327
+ Return the weight of ``self``.
1328
+
1329
+ The weight of a shifted primed tableau is defined to be the vector
1330
+ with `i`-th component equal to the number of entries `i` and `i'`
1331
+ in the tableau.
1332
+
1333
+ EXAMPLES::
1334
+
1335
+ sage: t = ShiftedPrimedTableau([[1,'2p',2,2],[2,'3p']])
1336
+ sage: t.weight()
1337
+ (1, 4, 1)
1338
+ """
1339
+ flat = [entry.integer() for row in self for entry in row]
1340
+ if flat == []:
1341
+ max_ind = 0
1342
+ else:
1343
+ max_ind = max(flat)
1344
+ weight = tuple([flat.count(i+1) for i in range(max_ind)])
1345
+ return self.parent().weight_lattice_realization()(weight)
1346
+
1347
+
1348
+ class PrimedEntry(SageObject):
1349
+ r"""
1350
+ The class of entries in shifted primed tableaux.
1351
+
1352
+ An entry in a shifted primed tableau is an element in
1353
+ the alphabet `\{1' < 1 < 2' < 2 < \cdots < n' < n\}`.
1354
+ The difference between two elements `i` and `i-1` counts as a
1355
+ whole unit, whereas the difference between `i` and `i'` counts
1356
+ as half a unit.
1357
+ Internally, we represent an unprimed element `x` as `2x`
1358
+ and the primed elements as the corresponding odd integer
1359
+ that respects the total order.
1360
+
1361
+ INPUT:
1362
+
1363
+ - ``entry`` -- half integer or string of an integer
1364
+ possibly ending in ``p`` or ``'``
1365
+ - ``double`` -- the doubled value
1366
+ """
1367
+
1368
+ def __init__(self, entry=None, double=None):
1369
+ """
1370
+ Normalize the entry.
1371
+
1372
+ TESTS::
1373
+
1374
+ sage: from sage.combinat.shifted_primed_tableau import PrimedEntry
1375
+ sage: PrimedEntry(2)
1376
+ 2
1377
+ sage: PrimedEntry("2p")
1378
+ 2'
1379
+ sage: PrimedEntry("2'")
1380
+ 2'
1381
+ sage: a = PrimedEntry(2.5)
1382
+ sage: PrimedEntry(a)
1383
+ 3'
1384
+ sage: PrimedEntry(None)
1385
+ Traceback (most recent call last):
1386
+ ...
1387
+ ValueError: primed entry must not be None
1388
+ """
1389
+ # store primed numbers as odd, unprimed numbers as even integers
1390
+ if isinstance(entry, self.__class__):
1391
+ self._entry = entry._entry
1392
+ return
1393
+
1394
+ if double is not None:
1395
+ self._entry = Integer(double)
1396
+ return
1397
+
1398
+ if isinstance(entry, str):
1399
+ if (entry[-1] == "'" or entry[-1] == "p") and entry[:-1].isdigit():
1400
+ # Check if an element has "'" or "p" at the end
1401
+ self._entry = 2 * Integer(entry[:-1]) - 1
1402
+ else:
1403
+ self._entry = 2 * Integer(entry)
1404
+ return
1405
+
1406
+ if entry is None:
1407
+ raise ValueError("primed entry must not be None")
1408
+ try:
1409
+ self._entry = Integer(2*entry)
1410
+ except (TypeError, ValueError):
1411
+ raise ValueError("primed entries must be half-integers")
1412
+
1413
+ def __hash__(self):
1414
+ """
1415
+ TESTS::
1416
+
1417
+ sage: from sage.combinat.shifted_primed_tableau import PrimedEntry
1418
+ sage: a = PrimedEntry("2p")
1419
+ sage: b = PrimedEntry("2'")
1420
+ sage: a == b
1421
+ True
1422
+ """
1423
+ return hash(self._entry)
1424
+
1425
+ def __repr__(self):
1426
+ """
1427
+ Represent ``self`` as primed or unprimed integer.
1428
+
1429
+ TESTS::
1430
+
1431
+ sage: ShiftedPrimedTableau([[1,"2p"]])[0][1]
1432
+ 2'
1433
+ """
1434
+ if self.is_unprimed():
1435
+ return repr(self._entry // 2)
1436
+ else:
1437
+ return repr((self._entry+1) // 2) + "'"
1438
+
1439
+ def integer(self):
1440
+ """
1441
+ Return the corresponding integer `i` for primed entries
1442
+ of the form `i` or `i'`.
1443
+
1444
+ TESTS::
1445
+
1446
+ sage: from sage.combinat.shifted_primed_tableau import PrimedEntry
1447
+ sage: b = PrimedEntry("2p").integer()
1448
+ sage: b
1449
+ 2
1450
+ sage: b.category()
1451
+ Category of elements of Integer Ring
1452
+ """
1453
+ return (self._entry + 1) // 2
1454
+
1455
+ def __eq__(self, other):
1456
+ """
1457
+ TESTS::
1458
+
1459
+ sage: from sage.combinat.shifted_primed_tableau import PrimedEntry
1460
+ sage: a = PrimedEntry("2p")
1461
+ sage: b = PrimedEntry("2'")
1462
+ sage: a == b
1463
+ True
1464
+ """
1465
+ try:
1466
+ other = PrimedEntry(other)
1467
+ except ValueError:
1468
+ return False
1469
+ return self._entry == other._entry
1470
+
1471
+ def __ne__(self, other):
1472
+ """
1473
+ TESTS::
1474
+
1475
+ sage: from sage.combinat.shifted_primed_tableau import PrimedEntry
1476
+ sage: a = PrimedEntry("1")
1477
+ sage: b = PrimedEntry(1)
1478
+ sage: a != b
1479
+ False
1480
+ """
1481
+ try:
1482
+ other = PrimedEntry(other)
1483
+ except ValueError:
1484
+ return True
1485
+ return self._entry != other._entry
1486
+
1487
+ def __lt__(self, other):
1488
+ """
1489
+ TESTS::
1490
+
1491
+ sage: from sage.combinat.shifted_primed_tableau import PrimedEntry
1492
+ sage: a = PrimedEntry("2p")
1493
+ sage: b = PrimedEntry(2)
1494
+ sage: a < b
1495
+ True
1496
+ """
1497
+ return self._entry < PrimedEntry(other)._entry
1498
+
1499
+ def __le__(self, other):
1500
+ """
1501
+ TESTS::
1502
+
1503
+ sage: from sage.combinat.shifted_primed_tableau import PrimedEntry
1504
+ sage: a = PrimedEntry(2)
1505
+ sage: b = PrimedEntry("3p")
1506
+ sage: a <= b
1507
+ True
1508
+ """
1509
+ return self._entry <= PrimedEntry(other)._entry
1510
+
1511
+ def __gt__(self, other):
1512
+ """
1513
+ TESTS::
1514
+
1515
+ sage: from sage.combinat.shifted_primed_tableau import PrimedEntry
1516
+ sage: a = PrimedEntry("2p")
1517
+ sage: b = PrimedEntry(2)
1518
+ sage: b > a
1519
+ True
1520
+ """
1521
+ return self._entry > PrimedEntry(other)._entry
1522
+
1523
+ def __ge__(self, other):
1524
+ """
1525
+ TESTS::
1526
+
1527
+ sage: from sage.combinat.shifted_primed_tableau import PrimedEntry
1528
+ sage: a = PrimedEntry(2)
1529
+ sage: b = PrimedEntry("3p")
1530
+ sage: a >= b
1531
+ False
1532
+ """
1533
+ return self._entry >= PrimedEntry(other)._entry
1534
+
1535
+ def is_unprimed(self):
1536
+ """
1537
+ Check if ``self`` is an unprimed element.
1538
+
1539
+ TESTS::
1540
+
1541
+ sage: from sage.combinat.shifted_primed_tableau import PrimedEntry
1542
+ sage: a = PrimedEntry("2p")
1543
+ sage: a.is_unprimed()
1544
+ False
1545
+ """
1546
+ return self._entry % 2 == 0
1547
+
1548
+ def is_primed(self):
1549
+ """
1550
+ Check if ``self`` is a primed element.
1551
+
1552
+ TESTS::
1553
+
1554
+ sage: from sage.combinat.shifted_primed_tableau import PrimedEntry
1555
+ sage: a = PrimedEntry("3p")
1556
+ sage: a.is_primed()
1557
+ True
1558
+ """
1559
+ return self._entry % 2 == 1
1560
+
1561
+ def unprimed(self):
1562
+ """
1563
+ Unprime ``self`` if it is a primed element.
1564
+
1565
+ TESTS::
1566
+
1567
+ sage: from sage.combinat.shifted_primed_tableau import PrimedEntry
1568
+ sage: a = PrimedEntry("2p")
1569
+ sage: a.unprimed()
1570
+ 2
1571
+ """
1572
+ if self.is_unprimed():
1573
+ return self
1574
+ else:
1575
+ return PrimedEntry(double=self._entry + 1)
1576
+
1577
+ def primed(self):
1578
+ """
1579
+ Prime ``self`` if it is an unprimed element.
1580
+
1581
+ TESTS::
1582
+
1583
+ sage: from sage.combinat.shifted_primed_tableau import PrimedEntry
1584
+ sage: a = PrimedEntry(1)
1585
+ sage: a.primed()
1586
+ 1'
1587
+ """
1588
+ if self.is_unprimed():
1589
+ return PrimedEntry(double=self._entry - 1)
1590
+ else:
1591
+ return self
1592
+
1593
+ def increase_half(self):
1594
+ """
1595
+ Increase ``self`` by half a unit.
1596
+
1597
+ TESTS::
1598
+
1599
+ sage: from sage.combinat.shifted_primed_tableau import PrimedEntry
1600
+ sage: a = PrimedEntry(1)
1601
+ sage: a.increase_half()
1602
+ 2'
1603
+ """
1604
+ return PrimedEntry(double=self._entry + 1)
1605
+
1606
+ def decrease_half(self):
1607
+ """
1608
+ Decrease ``self`` by half a unit.
1609
+
1610
+ TESTS::
1611
+
1612
+ sage: from sage.combinat.shifted_primed_tableau import PrimedEntry
1613
+ sage: a = PrimedEntry(1)
1614
+ sage: a.decrease_half()
1615
+ 1'
1616
+ """
1617
+ return PrimedEntry(double=self._entry - 1)
1618
+
1619
+ def increase_one(self):
1620
+ """
1621
+ Increase ``self`` by one unit.
1622
+
1623
+ TESTS::
1624
+
1625
+ sage: from sage.combinat.shifted_primed_tableau import PrimedEntry
1626
+ sage: a = PrimedEntry("2p")
1627
+ sage: a.increase_one()
1628
+ 3'
1629
+ """
1630
+ return PrimedEntry(double=self._entry + 2)
1631
+
1632
+ def decrease_one(self):
1633
+ """
1634
+ Decrease ``self`` by one unit.
1635
+
1636
+ TESTS::
1637
+
1638
+ sage: from sage.combinat.shifted_primed_tableau import PrimedEntry
1639
+ sage: a = PrimedEntry("2p")
1640
+ sage: a.decrease_one()
1641
+ 1'
1642
+ """
1643
+ return PrimedEntry(double=self._entry - 2)
1644
+
1645
+
1646
+ class ShiftedPrimedTableaux(UniqueRepresentation, Parent):
1647
+ r"""
1648
+ Return the combinatorial class of shifted primed tableaux subject
1649
+ to the constraints given by the arguments.
1650
+
1651
+ A primed tableau is a tableau of shifted shape on the alphabet
1652
+ `X' = \{1' < 1 < 2' < 2 < \cdots < n' < n\}` such that
1653
+
1654
+ 1. the entries are weakly increasing along rows and columns
1655
+
1656
+ 2. a row cannot have two repeated primed entries, and a column
1657
+ cannot have two repeated non-primed entries
1658
+
1659
+ INPUT:
1660
+
1661
+ Valid optional keywords:
1662
+
1663
+ - ``shape`` -- the (outer skew) shape of tableaux
1664
+
1665
+ - ``weight`` -- the weight of tableaux
1666
+
1667
+ - ``max_entry`` -- the maximum entry of tableaux
1668
+
1669
+ - ``skew`` -- the inner skew shape of tableaux
1670
+
1671
+ - ``primed_diagonal`` -- allow primed entries in main diagonal of tableaux
1672
+
1673
+ The weight of a tableau is defined to be the vector with `i`-th
1674
+ component equal to the number of entries `i` and `i'` in the tableau.
1675
+ The sum of the coordinates in the weight vector must be equal to the
1676
+ number of entries in the partition.
1677
+
1678
+ The ``shape`` and ``skew`` must be strictly decreasing partitions.
1679
+ The ``primed_diagonal`` is a boolean (default: ``False``).
1680
+
1681
+ EXAMPLES::
1682
+
1683
+ sage: SPT = ShiftedPrimedTableaux(weight=(1,2,2), shape=[3,2]); SPT
1684
+ Shifted Primed Tableaux of weight (1, 2, 2) and shape [3, 2]
1685
+ sage: SPT.list()
1686
+ [[(1, 2, 2), (3, 3)],
1687
+ [(1, 2', 3'), (2, 3)],
1688
+ [(1, 2', 3'), (2, 3')],
1689
+ [(1, 2', 2), (3, 3)]]
1690
+ sage: SPT = ShiftedPrimedTableaux(weight=(1,2,2), shape=[3,2],
1691
+ ....: primed_diagonal=True); SPT
1692
+ Shifted Primed Tableaux of weight (1, 2, 2) and shape [3, 2]
1693
+ sage: SPT.list()
1694
+ [[(1, 2, 2), (3, 3)],
1695
+ [(1, 2, 2), (3', 3)],
1696
+ [(1, 2', 3'), (2, 3)],
1697
+ [(1, 2', 3'), (2, 3')],
1698
+ [(1, 2', 3'), (2', 3)],
1699
+ [(1, 2', 3'), (2', 3')],
1700
+ [(1, 2', 2), (3, 3)],
1701
+ [(1, 2', 2), (3', 3)],
1702
+ [(1', 2, 2), (3, 3)],
1703
+ [(1', 2, 2), (3', 3)],
1704
+ [(1', 2', 3'), (2, 3)],
1705
+ [(1', 2', 3'), (2, 3')],
1706
+ [(1', 2', 3'), (2', 3)],
1707
+ [(1', 2', 3'), (2', 3')],
1708
+ [(1', 2', 2), (3, 3)],
1709
+ [(1', 2', 2), (3', 3)]]
1710
+ sage: SPT = ShiftedPrimedTableaux(weight=(1,2)); SPT
1711
+ Shifted Primed Tableaux of weight (1, 2)
1712
+ sage: list(SPT)
1713
+ [[(1, 2, 2)], [(1, 2', 2)], [(1, 2'), (2,)]]
1714
+ sage: SPT = ShiftedPrimedTableaux(weight=(1,2), primed_diagonal=True)
1715
+ sage: list(SPT)
1716
+ [[(1, 2, 2)],
1717
+ [(1, 2', 2)],
1718
+ [(1', 2, 2)],
1719
+ [(1', 2', 2)],
1720
+ [(1, 2'), (2,)],
1721
+ [(1, 2'), (2',)],
1722
+ [(1', 2'), (2,)],
1723
+ [(1', 2'), (2',)]]
1724
+ sage: SPT = ShiftedPrimedTableaux([3,2], max_entry=2); SPT
1725
+ Shifted Primed Tableaux of shape [3, 2] and maximum entry 2
1726
+ sage: list(SPT)
1727
+ [[(1, 1, 1), (2, 2)], [(1, 1, 2'), (2, 2)]]
1728
+ sage: SPT = ShiftedPrimedTableaux([3,2], max_entry=2,
1729
+ ....: primed_diagonal=True)
1730
+ sage: list(SPT)
1731
+ [[(1, 1, 1), (2, 2)],
1732
+ [(1, 1, 1), (2', 2)],
1733
+ [(1', 1, 1), (2, 2)],
1734
+ [(1', 1, 1), (2', 2)],
1735
+ [(1, 1, 2'), (2, 2)],
1736
+ [(1, 1, 2'), (2', 2)],
1737
+ [(1', 1, 2'), (2, 2)],
1738
+ [(1', 1, 2'), (2', 2)]]
1739
+
1740
+ TESTS::
1741
+
1742
+ sage: [(1,'2p',2,2),(2,'3p')] in ShiftedPrimedTableaux()
1743
+ True
1744
+ sage: [('1p','2p',2,2),(2,'3p')] in ShiftedPrimedTableaux()
1745
+ False
1746
+ sage: [(1,1),(2,2)] in ShiftedPrimedTableaux()
1747
+ False
1748
+ sage: [] in ShiftedPrimedTableaux()
1749
+ True
1750
+ sage: [('1p','2p',2,2),(2,'3p')] in ShiftedPrimedTableaux(
1751
+ ....: primed_diagonal=True)
1752
+ True
1753
+ sage: [] in ShiftedPrimedTableaux(primed_diagonal=True)
1754
+ True
1755
+
1756
+ .. SEEALSO::
1757
+
1758
+ - :class:`ShiftedPrimedTableau`
1759
+ """
1760
+ Element = ShiftedPrimedTableau
1761
+ options = Tableaux.options
1762
+
1763
+ @staticmethod
1764
+ def __classcall_private__(cls, shape=None, weight=None, max_entry=None,
1765
+ skew=None, primed_diagonal=False):
1766
+ r"""
1767
+ Normalize and process input to return the correct parent and
1768
+ ensure a unique representation.
1769
+
1770
+ TESTS::
1771
+
1772
+ sage: ShiftedPrimedTableaux([])
1773
+ Shifted Primed Tableaux of shape []
1774
+ sage: ShiftedPrimedTableaux(3)
1775
+ Traceback (most recent call last):
1776
+ ...
1777
+ ValueError: invalid shape argument
1778
+ sage: ShiftedPrimedTableaux(weight=(2,2,2), shape=[3,2])
1779
+ Traceback (most recent call last):
1780
+ ...
1781
+ ValueError: weight and shape are incompatible
1782
+ sage: ShiftedPrimedTableaux([[1]])
1783
+ Traceback (most recent call last):
1784
+ ...
1785
+ ValueError: invalid shape argument
1786
+ sage: ShiftedPrimedTableaux(weight=(2,2,2), max_entry=2)
1787
+ Traceback (most recent call last):
1788
+ ...
1789
+ ValueError: maximum entry is incompatible with the weight
1790
+ sage: ShiftedPrimedTableaux(shape=[4,1],skew=[3,2])
1791
+ Traceback (most recent call last):
1792
+ ...
1793
+ ValueError: skew shape must be inside the given tableau shape
1794
+
1795
+ sage: SPT1 = ShiftedPrimedTableaux(weight=())
1796
+ sage: SPT2 = ShiftedPrimedTableaux(weight=(0,0,0))
1797
+ sage: SPT1 is SPT2
1798
+ True
1799
+ """
1800
+ if skew is not None:
1801
+ try:
1802
+ skew = Partition(skew)
1803
+ except ValueError:
1804
+ raise ValueError('invalid skew argument')
1805
+ if not all(skew[i] > skew[i+1] for i in range(len(skew)-1)):
1806
+ raise ValueError('skew shape must be a strict partition')
1807
+
1808
+ if weight is not None:
1809
+ weight = tuple(weight)
1810
+
1811
+ if shape is not None:
1812
+ if isinstance(shape, SkewPartition):
1813
+ skew = shape.inner()
1814
+ shape = shape.outer()
1815
+ try:
1816
+ shape = Partition(shape)
1817
+ except (ValueError, TypeError):
1818
+ raise ValueError('invalid shape argument')
1819
+
1820
+ if not all(shape[i] > shape[i+1] for i in range(len(shape)-1)):
1821
+ raise ValueError("shape {} is not a strict partition".format(shape))
1822
+
1823
+ if (skew is not None and not all(skew[i] <= shape[i]
1824
+ for i in range(len(skew)))):
1825
+ raise ValueError('skew shape must be inside the given tableau shape')
1826
+
1827
+ if weight is not None:
1828
+ while weight and weight[-1] == 0:
1829
+ weight = weight[:-1]
1830
+
1831
+ if max_entry is not None and weight is not None:
1832
+ if len(weight) > max_entry:
1833
+ raise ValueError("maximum entry is incompatible with the weight")
1834
+
1835
+ if shape is None:
1836
+ if weight is None:
1837
+ if max_entry is not None:
1838
+ raise ValueError("specify shape or weight argument")
1839
+ return ShiftedPrimedTableaux_all(skew=skew, primed_diagonal=primed_diagonal)
1840
+ else:
1841
+ return ShiftedPrimedTableaux_weight(weight, skew=skew, primed_diagonal=primed_diagonal)
1842
+ else:
1843
+ if weight is None:
1844
+ return ShiftedPrimedTableaux_shape(shape, max_entry=max_entry, skew=skew, primed_diagonal=primed_diagonal)
1845
+
1846
+ if (skew is not None and sum(shape) - sum(skew) != sum(weight)
1847
+ or skew is None and sum(shape) != sum(weight)):
1848
+ raise ValueError("weight and shape are incompatible")
1849
+
1850
+ return ShiftedPrimedTableaux_weight_shape(weight, shape, skew=skew, primed_diagonal=primed_diagonal)
1851
+
1852
+ def __init__(self, skew=None, primed_diagonal=False):
1853
+ """
1854
+ Initialization of the parent class with given skew shape.
1855
+
1856
+ TESTS::
1857
+
1858
+ sage: SPT = ShiftedPrimedTableaux(skew=[1])
1859
+ sage: TestSuite(SPT).run() # known bug
1860
+ """
1861
+ self._skew = skew
1862
+ self._primed_diagonal = primed_diagonal
1863
+
1864
+ def _element_constructor_(self, T):
1865
+ """
1866
+ Construct an object from ``T`` as an element of shifted primed
1867
+ tableaux, if possible.
1868
+
1869
+ INPUT:
1870
+
1871
+ - ``T`` -- data which can be interpreted as a primed tableau
1872
+
1873
+ OUTPUT: the corresponding primed tableau object
1874
+
1875
+ EXAMPLES::
1876
+
1877
+ sage: SPT = ShiftedPrimedTableaux()
1878
+ sage: Primed_SPT = ShiftedPrimedTableaux(primed_diagonal=True)
1879
+
1880
+ sage: tab = SPT([[1,1,"2p"]]); tab
1881
+ [(1, 1, 2')]
1882
+ sage: tab.parent() is SPT
1883
+ True
1884
+ sage: tab = Primed_SPT([["1p",1,"2p"]]); tab
1885
+ [(1', 1, 2')]
1886
+ sage: tab.parent() is Primed_SPT
1887
+ True
1888
+
1889
+ sage: tab = SPT([[1,1,2],[2,2]])
1890
+ Traceback (most recent call last):
1891
+ ...
1892
+ ValueError: [[1, 1, 2], [2, 2]] is not an element of Shifted Primed Tableaux
1893
+ sage: SPT([[1,"2p","2p"]])
1894
+ Traceback (most recent call last):
1895
+ ...
1896
+ ValueError: [[1, '2p', '2p']] is not an element of Shifted Primed Tableaux
1897
+
1898
+ sage: SPT = ShiftedPrimedTableaux(skew=[1])
1899
+ sage: SPT([["2p",2]])
1900
+ [(None, 2', 2)]
1901
+
1902
+ sage: SPT = ShiftedPrimedTableaux(weight=(2,1))
1903
+ sage: tab = SPT([[1,1,1.5]]); tab
1904
+ [(1, 1, 2')]
1905
+ sage: tab.parent() is SPT
1906
+ True
1907
+
1908
+ sage: SPT = ShiftedPrimedTableaux([3])
1909
+ sage: tab = SPT([[1,1,1.5]]); tab
1910
+ [(1, 1, 2')]
1911
+ sage: tab.parent() is SPT
1912
+ True
1913
+ sage: SPT([[1,1]])
1914
+ Traceback (most recent call last):
1915
+ ...
1916
+ ValueError: [[1, 1]] is not an element of Shifted Primed Tableaux
1917
+ of shape [3]
1918
+
1919
+ sage: SPT = ShiftedPrimedTableaux([3], weight=(2,1))
1920
+ sage: tab = SPT([[1,1,1.5]]); tab
1921
+ [(1, 1, 2')]
1922
+ sage: tab.parent() is SPT
1923
+ True
1924
+ sage: SPT([[1,1]])
1925
+ Traceback (most recent call last):
1926
+ ...
1927
+ ValueError: [[1, 1]] is not an element of Shifted Primed Tableaux
1928
+ of weight (2, 1) and shape [3]
1929
+ """
1930
+ try:
1931
+ return self.element_class(self, T, skew=self._skew)
1932
+ except ValueError:
1933
+ raise ValueError("{} is not an element of {}".format(T, self))
1934
+
1935
+ def _contains_tableau(self, T):
1936
+ """
1937
+ Check if ``self`` contains preprocessed tableau ``T``.
1938
+
1939
+ TESTS::
1940
+
1941
+ sage: Tabs = ShiftedPrimedTableaux()
1942
+ sage: tab = ShiftedPrimedTableau._preprocess(
1943
+ ....: [[1,"2p","3p","3p"]])
1944
+ sage: tab
1945
+ [(1, 2', 3', 3')]
1946
+ sage: Tabs._contains_tableau(tab)
1947
+ False
1948
+ sage: tab = ShiftedPrimedTableau._preprocess(
1949
+ ....: [["1p","2p","3p",3]])
1950
+ sage: Tabs._contains_tableau(tab)
1951
+ False
1952
+ sage: Tabs = ShiftedPrimedTableaux(primed_diagonal=True)
1953
+ sage: Tabs._contains_tableau(tab)
1954
+ True
1955
+ sage: Tabs = ShiftedPrimedTableaux(skew=[1])
1956
+ sage: tab = ShiftedPrimedTableau._preprocess(
1957
+ ....: [["2p","3p",3]], skew=[1])
1958
+ sage: tab
1959
+ [(None, 2', 3', 3)]
1960
+ sage: Tabs._contains_tableau(tab)
1961
+ True
1962
+ """
1963
+ if not all(len(T[i]) > len(T[i+1]) for i in range(len(T)-1)):
1964
+ return False
1965
+ if self._skew is not None:
1966
+ skew = self._skew + [0]*(len(T)-len(self._skew))
1967
+ else:
1968
+ skew = [0] * len(T)
1969
+ for i, row in enumerate(T):
1970
+ if i > 0:
1971
+ if not all(val > T[i-1][j+1]
1972
+ for j, val in enumerate(row)
1973
+ if j+1 >= skew[i-1] and val.is_unprimed()):
1974
+ return False
1975
+ if not all(val >= T[i-1][j+1]
1976
+ for j, val in enumerate(row)
1977
+ if j+1 >= skew[i-1] and val.is_primed()):
1978
+ return False
1979
+ if not all(row[j] <= row[j+1]
1980
+ for j in range(skew[i], len(row)-1)
1981
+ if row[j].is_unprimed()):
1982
+ return False
1983
+ if not all(row[j] < row[j+1]
1984
+ for j in range(skew[i], len(row)-1)
1985
+ if row[j].is_primed()):
1986
+ return False
1987
+ if not (self._primed_diagonal or all(row[0].is_unprimed()
1988
+ for i, row in enumerate(T)
1989
+ if skew[i] == 0)):
1990
+ return False
1991
+ return True
1992
+
1993
+
1994
+ class ShiftedPrimedTableaux_all(ShiftedPrimedTableaux):
1995
+ """
1996
+ The class of all shifted primed tableaux.
1997
+ """
1998
+
1999
+ def __init__(self, skew=None, primed_diagonal=False):
2000
+ """
2001
+ Initialize the class of all shifted tableaux.
2002
+
2003
+ TESTS::
2004
+
2005
+ sage: SPT = ShiftedPrimedTableaux()
2006
+ sage: [[1,1.5],[2]] in SPT
2007
+ True
2008
+ sage: [[1,1.5],[1.5]] in SPT
2009
+ False
2010
+ sage: [[1,1],[1]] in SPT
2011
+ False
2012
+ sage: [[1,1],[2,2]] in SPT
2013
+ False
2014
+ sage: TestSuite(SPT).run() # long time
2015
+
2016
+ sage: Primed_SPT = ShiftedPrimedTableaux(primed_diagonal=True)
2017
+ sage: [[0.5,1.5],[2]] in Primed_SPT
2018
+ True
2019
+ sage: [[0.5,1.5],[1.5]] in Primed_SPT
2020
+ True
2021
+ sage: [[0.5,1],[1]] in Primed_SPT
2022
+ False
2023
+ sage: TestSuite(Primed_SPT).run() # long time
2024
+ """
2025
+ if skew is None:
2026
+ Parent.__init__(self, category=InfiniteEnumeratedSets())
2027
+ else:
2028
+ Parent.__init__(self, category=Sets().Infinite())
2029
+ ShiftedPrimedTableaux.__init__(self, skew=skew, primed_diagonal=primed_diagonal)
2030
+
2031
+ def _repr_(self):
2032
+ """
2033
+ Return a string representation of ``self``.
2034
+
2035
+ TESTS::
2036
+
2037
+ sage: ShiftedPrimedTableaux()
2038
+ Shifted Primed Tableaux
2039
+ """
2040
+ if self._skew is None:
2041
+ return "Shifted Primed Tableaux"
2042
+ return "Shifted Primed Tableaux skewed by {}".format(self._skew)
2043
+
2044
+ def __iter__(self):
2045
+ """
2046
+ Iterate over ``self``.
2047
+
2048
+ EXAMPLES::
2049
+
2050
+ sage: # needs sage.libs.gap
2051
+ sage: Tabs = ShiftedPrimedTableaux()
2052
+ sage: Tabs[:5]
2053
+ [[], [(1,)], [(2,)], [(1, 2)], [(1, 2')]]
2054
+ sage: Tabs = ShiftedPrimedTableaux(primed_diagonal=True)
2055
+ sage: Tabs[:5]
2056
+ [[], [(1,)], [(1',)], [(2,)], [(2',)]]
2057
+ """
2058
+ if self._skew is not None:
2059
+ raise NotImplementedError('skew tableau must be empty')
2060
+ yield self.element_class(self, [])
2061
+
2062
+ max_entry = 1
2063
+ while True:
2064
+ for size in range(1, max_entry+1):
2065
+ for shape in Partitions(size, max_slope=-1):
2066
+ for weight in OrderedPartitions(size+max_entry-1,
2067
+ k=max_entry):
2068
+ weight = [weight[i]-1 for i in range(max_entry)]
2069
+ weight[-1] += 1
2070
+ for tab in ShiftedPrimedTableaux(shape=shape,
2071
+ weight=weight,
2072
+ primed_diagonal=self._primed_diagonal):
2073
+ yield self.element_class(self, tab, check=False,
2074
+ preprocessed=True)
2075
+ max_entry += 1
2076
+
2077
+
2078
+ class ShiftedPrimedTableaux_shape(ShiftedPrimedTableaux):
2079
+ r"""
2080
+ Shifted primed tableaux of a fixed shape.
2081
+
2082
+ Shifted primed tableaux admit a type `A_n` classical crystal structure
2083
+ with highest weights corresponding to a given shape.
2084
+
2085
+ The list of module generators consists of all elements of the
2086
+ crystal with nonincreasing weight entries.
2087
+
2088
+ The crystal is constructed following operations described in [HPS2017]_
2089
+ and [AO2018]_.
2090
+
2091
+ The optional ``primed_diagonal`` allows primed entries in the main diagonal
2092
+ of all the Shifted primed tableaux of a fixed shape. If the ``max_entry``
2093
+ is ``None`` then ``max_entry`` is set to the total number of entries in the
2094
+ tableau if ``primed_diagonal`` is ``True``.
2095
+
2096
+ EXAMPLES::
2097
+
2098
+ sage: ShiftedPrimedTableaux([4,3,1], max_entry=4)
2099
+ Shifted Primed Tableaux of shape [4, 3, 1] and maximum entry 4
2100
+ sage: ShiftedPrimedTableaux([4,3,1], max_entry=4).cardinality()
2101
+ 384
2102
+
2103
+ We compute some of the crystal structure::
2104
+
2105
+ sage: SPTC = crystals.ShiftedPrimedTableaux([3,2], 3)
2106
+ sage: T = SPTC.module_generators[-1]
2107
+ sage: T
2108
+ [(1, 1, 2'), (2, 3')]
2109
+ sage: T.f(2)
2110
+ [(1, 1, 3'), (2, 3')]
2111
+ sage: len(SPTC.module_generators)
2112
+ 7
2113
+ sage: SPTC[0]
2114
+ [(1, 1, 1), (2, 2)]
2115
+ sage: SPTC.cardinality()
2116
+ 24
2117
+
2118
+ We compare this implementation with the `q(n)`-crystal
2119
+ on (tensor products) of letters::
2120
+
2121
+ sage: # needs sage.graphs
2122
+ sage: tableau_crystal = crystals.ShiftedPrimedTableaux([4,1], 3)
2123
+ sage: tableau_digraph = tableau_crystal.digraph()
2124
+ sage: c = crystals.Letters(['Q', 3])
2125
+ sage: tensor_crystal = tensor([c]*5)
2126
+ sage: u = tensor_crystal(c(1), c(1), c(1), c(2), c(1))
2127
+ sage: subcrystal = tensor_crystal.subcrystal(generators=[u],
2128
+ ....: index_set=[1,2,-1])
2129
+ sage: tensor_digraph = subcrystal.digraph()
2130
+ sage: tensor_digraph.is_isomorphic(tableau_digraph, edge_labels=True)
2131
+ True
2132
+
2133
+ If we allow primed entries in the main diagonal::
2134
+
2135
+ sage: ShiftedPrimedTableaux([4,3,1], max_entry=4,
2136
+ ....: primed_diagonal=True)
2137
+ Shifted Primed Tableaux of shape [4, 3, 1] and maximum entry 4
2138
+ sage: ShiftedPrimedTableaux([4,3,1], max_entry=4,
2139
+ ....: primed_diagonal=True).cardinality()
2140
+ 3072
2141
+ sage: SPTC = ShiftedPrimedTableaux([3,2], max_entry=3,
2142
+ ....: primed_diagonal=True)
2143
+ sage: T = SPTC[-1]
2144
+ sage: T
2145
+ [(1', 2', 2), (3', 3)]
2146
+ sage: SPTC[0]
2147
+ [(1, 1, 1), (2, 2)]
2148
+ sage: SPTC.cardinality()
2149
+ 96
2150
+ """
2151
+ @staticmethod
2152
+ def __classcall_private__(cls, shape, max_entry=None, skew=None, primed_diagonal=False):
2153
+ """
2154
+ Normalize the attributes for the class.
2155
+
2156
+ TESTS::
2157
+
2158
+ sage: SPT = ShiftedPrimedTableaux(shape=[2,1])
2159
+ sage: SPT._shape.parent()
2160
+ Partitions
2161
+
2162
+ sage: SPT1 = ShiftedPrimedTableaux(shape=(2,1), max_entry=3)
2163
+ sage: SPT2 = ShiftedPrimedTableaux(shape=[2,1], max_entry=3)
2164
+ sage: SPT1 is SPT2
2165
+ True
2166
+ """
2167
+ shape = _Partitions(shape)
2168
+ return super().__classcall__(cls,
2169
+ shape=shape, max_entry=max_entry, skew=skew, primed_diagonal=primed_diagonal)
2170
+
2171
+ def __init__(self, shape, max_entry=None, skew=None, primed_diagonal=False):
2172
+ """
2173
+ Initialize the class of shifted primed tableaux of a given shape.
2174
+
2175
+ If ``max_elt`` is specified, a finite set with entries smaller
2176
+ or equal to ``max_elt``.
2177
+
2178
+ TESTS::
2179
+
2180
+ sage: SPT = ShiftedPrimedTableaux([4,2,1], max_entry=4)
2181
+ sage: TestSuite(SPT).run() # long time
2182
+ sage: SPT.cartan_type()
2183
+ ['Q', 4]
2184
+
2185
+ sage: SPT = ShiftedPrimedTableaux([4,2,1])
2186
+ sage: SPT.cartan_type()
2187
+ ['A', NN]
2188
+ sage: SPT = ShiftedPrimedTableaux([4,2,1], max_entry=4,
2189
+ ....: primed_diagonal=True)
2190
+ sage: TestSuite(SPT).run() # long time
2191
+ """
2192
+ if not primed_diagonal:
2193
+ # Determine the correct category
2194
+ if max_entry is None:
2195
+ if skew is None:
2196
+ category = RegularCrystals().Infinite()
2197
+ self._cartan_type = CartanType(['A+oo'])
2198
+ self.Element = CrystalElementShiftedPrimedTableau
2199
+ else:
2200
+ category = Sets().Infinite()
2201
+ else:
2202
+ if skew is None:
2203
+ category = RegularSuperCrystals()
2204
+ self._cartan_type = CartanType(['Q', max_entry])
2205
+ self.Element = CrystalElementShiftedPrimedTableau
2206
+ else:
2207
+ category = Sets().Finite()
2208
+ else:
2209
+ if max_entry is None:
2210
+ max_entry = sum(shape)
2211
+
2212
+ if skew is None:
2213
+ category = FiniteEnumeratedSets()
2214
+ else:
2215
+ category = Sets().Finite()
2216
+
2217
+ ShiftedPrimedTableaux.__init__(self, skew=skew, primed_diagonal=primed_diagonal)
2218
+ Parent.__init__(self, category=category)
2219
+ self._max_entry = max_entry
2220
+ if skew is None:
2221
+ self._shape = Partition(shape)
2222
+ else:
2223
+ self._shape = SkewPartition((shape, skew))
2224
+
2225
+ def _repr_(self):
2226
+ """
2227
+ Return a string representation of ``self``.
2228
+
2229
+ TESTS::
2230
+
2231
+ sage: ShiftedPrimedTableaux([3,2,1])
2232
+ Shifted Primed Tableaux of shape [3, 2, 1]
2233
+ sage: ShiftedPrimedTableaux([3,2,1], primed_diagonal=True)
2234
+ Shifted Primed Tableaux of shape [3, 2, 1] and maximum
2235
+ entry 6
2236
+ """
2237
+ base = "Shifted Primed Tableaux of shape " + self._shape._repr_()
2238
+ if self._max_entry is not None:
2239
+ base += " and maximum entry {}".format(self._max_entry)
2240
+ return base
2241
+
2242
+ def _contains_tableau(self, T):
2243
+ """
2244
+ TESTS::
2245
+
2246
+ sage: t = ShiftedPrimedTableau._preprocess([[1,'2p',2,2],[2,'3p']])
2247
+ sage: ShiftedPrimedTableaux([4,2],max_entry=4)._contains_tableau(t)
2248
+ True
2249
+ sage: s = ShiftedPrimedTableau._preprocess([[1,'2p',2],[2,'3p']])
2250
+ sage: ShiftedPrimedTableaux([4,2])._contains_tableau(s)
2251
+ False
2252
+ sage: t = ShiftedPrimedTableau._preprocess([['1p','2p',2,2],
2253
+ ....: ['2p','3p']])
2254
+ sage: ShiftedPrimedTableaux([4,2],max_entry=4,
2255
+ ....: primed_diagonal=True)._contains_tableau(t)
2256
+ True
2257
+ """
2258
+ if not super()._contains_tableau(T):
2259
+ return False
2260
+
2261
+ shape = [len(row) for row in T]
2262
+ skew = [row.count(None) for row in T]
2263
+ if sum(skew) == 0:
2264
+ shape = Partition(shape)
2265
+ else:
2266
+ shape = SkewPartition((shape, skew))
2267
+ if self._shape != shape:
2268
+ return False
2269
+
2270
+ if self._max_entry is not None:
2271
+ flat = [item.integer() for sublist in T for item in sublist]
2272
+ if flat == []:
2273
+ max_entry = 0
2274
+ else:
2275
+ max_entry = int(max(flat))
2276
+ if max_entry > self._max_entry:
2277
+ return False
2278
+
2279
+ return True
2280
+
2281
+ def __iter__(self):
2282
+ r"""
2283
+ Iterate over ``self``.
2284
+
2285
+ EXAMPLES::
2286
+
2287
+ sage: Tabs = ShiftedPrimedTableaux(shape=(3,2), max_entry=5)
2288
+ sage: Tabs[:4]
2289
+ [[(1, 1, 1), (2, 2)],
2290
+ [(1, 1, 1), (2, 3)],
2291
+ [(1, 1, 1), (2, 3')],
2292
+ [(1, 1, 2), (2, 3)]]
2293
+ sage: len(list(Tabs))
2294
+ 376
2295
+ sage: Tabs = ShiftedPrimedTableaux(shape=(3,2), primed_diagonal=True)
2296
+ sage: Tabs[:4]
2297
+ [[(1, 1, 1), (2, 2)],
2298
+ [(1, 1, 1), (2', 2)],
2299
+ [(1', 1, 1), (2, 2)],
2300
+ [(1', 1, 1), (2', 2)]]
2301
+ sage: len(list(Tabs))
2302
+ 1504
2303
+ """
2304
+ if not self._primed_diagonal:
2305
+ for T in super().__iter__():
2306
+ yield T
2307
+ return
2308
+
2309
+ from sage.combinat.permutation import Permutations
2310
+ list_weights = []
2311
+ for partition in Partitions(sum(self._shape)):
2312
+ if len(partition) <= self._max_entry:
2313
+ for c in Combinations(range(self._max_entry), len(partition)):
2314
+ for p in Permutations(partition):
2315
+ weight = [0] * self._max_entry
2316
+ for i,val in enumerate(p):
2317
+ weight[c[i]] = val
2318
+ list_weights.append(weight)
2319
+ for weight in list_weights:
2320
+ for T in ShiftedPrimedTableaux(weight=tuple(weight), shape=self._shape,
2321
+ primed_diagonal=self._primed_diagonal):
2322
+ yield self.element_class(self, T, preprocessed=True, check=False)
2323
+
2324
+ @lazy_attribute
2325
+ def module_generators(self):
2326
+ """
2327
+ Return the generators of ``self`` as a crystal.
2328
+
2329
+ TESTS::
2330
+
2331
+ sage: SPT = ShiftedPrimedTableaux(shape=[2,1])
2332
+ sage: SPT.module_generators
2333
+ ([(1, 1), (2,)], [(1, 2), (3,)], [(1, 2'), (3,)])
2334
+ """
2335
+ if self._skew is not None:
2336
+ raise NotImplementedError("only for non-skew shapes")
2337
+ list_dw = []
2338
+ if self._max_entry is None:
2339
+ max_entry = sum(self._shape)
2340
+ else:
2341
+ max_entry = self._max_entry
2342
+ for weight in (Partition(self._shape).dominated_partitions(rows=max_entry)):
2343
+ list_dw.extend([self.element_class(self, T, check=False,
2344
+ preprocessed=True)
2345
+ for T in ShiftedPrimedTableaux(weight=tuple(weight),
2346
+ shape=self._shape,
2347
+ primed_diagonal=self._primed_diagonal)])
2348
+ return tuple(list_dw)
2349
+
2350
+ def shape(self):
2351
+ """
2352
+ Return the shape of the shifted tableaux ``self``.
2353
+
2354
+ TESTS::
2355
+
2356
+ sage: ShiftedPrimedTableaux([6,4,3,1]).shape()
2357
+ [6, 4, 3, 1]
2358
+ """
2359
+ return self._shape
2360
+
2361
+
2362
+ class ShiftedPrimedTableaux_weight(ShiftedPrimedTableaux):
2363
+ """
2364
+ Shifted primed tableaux of fixed weight.
2365
+
2366
+ EXAMPLES::
2367
+
2368
+ sage: ShiftedPrimedTableaux(weight=(2,3,1))
2369
+ Shifted Primed Tableaux of weight (2, 3, 1)
2370
+ sage: ShiftedPrimedTableaux(weight=(2,3,1)).cardinality()
2371
+ 17
2372
+ sage: SPT = ShiftedPrimedTableaux(weight=(2,3,1), primed_diagonal=True)
2373
+ sage: SPT.cardinality()
2374
+ 64
2375
+ sage: T = ShiftedPrimedTableaux(weight=(3,2), primed_diagonal=True)
2376
+ sage: T[:5]
2377
+ [[(1, 1, 1, 2, 2)],
2378
+ [(1, 1, 1, 2', 2)],
2379
+ [(1', 1, 1, 2, 2)],
2380
+ [(1', 1, 1, 2', 2)],
2381
+ [(1, 1, 1, 2), (2,)]]
2382
+ sage: T.cardinality()
2383
+ 16
2384
+ """
2385
+
2386
+ def __init__(self, weight, skew=None, primed_diagonal=False):
2387
+ """
2388
+ Initialize the class of shifted primed tableaux of a given weight.
2389
+
2390
+ TESTS::
2391
+
2392
+ sage: TestSuite( ShiftedPrimedTableaux(weight=(3,2,1)) ).run()
2393
+ sage: TestSuite( ShiftedPrimedTableaux(weight=(3,2,1),
2394
+ ....: primed_diagonal=True) ).run()
2395
+ """
2396
+ ShiftedPrimedTableaux.__init__(self, skew=skew, primed_diagonal=primed_diagonal)
2397
+ if skew is None:
2398
+ Parent.__init__(self, category=FiniteEnumeratedSets())
2399
+ else:
2400
+ Parent.__init__(self, category=Sets().Finite())
2401
+ self._weight = weight
2402
+
2403
+ def _repr_(self):
2404
+ """
2405
+ Return a string representation of ``self``.
2406
+
2407
+ TESTS::
2408
+
2409
+ sage: ShiftedPrimedTableaux(weight=(3,2,1))
2410
+ Shifted Primed Tableaux of weight (3, 2, 1)
2411
+ """
2412
+ if self._skew is None:
2413
+ return "Shifted Primed Tableaux of weight {}".format(self._weight)
2414
+ return "Shifted Primed Tableaux of weight {} skewed by {}".format(self._weight, self._skew)
2415
+
2416
+ def _contains_tableau(self, T):
2417
+ """
2418
+ Check if ``self`` contains preprocessed tableau ``T``.
2419
+
2420
+ TESTS::
2421
+
2422
+ sage: t = ShiftedPrimedTableau._preprocess([[1,1.5],[2]])
2423
+ sage: ShiftedPrimedTableaux(weight=(1,2))._contains_tableau(t)
2424
+ True
2425
+ sage: t = ShiftedPrimedTableau._preprocess([[0.5,1.5],[2]])
2426
+ sage: ShiftedPrimedTableaux(weight=(1,2),
2427
+ ....: primed_diagonal=True)._contains_tableau(t)
2428
+ True
2429
+ sage: s = ShiftedPrimedTableau._preprocess([[1,1.5],[3]])
2430
+ sage: ShiftedPrimedTableaux(weight=(1,2))._contains_tableau(s)
2431
+ False
2432
+
2433
+ sage: u = ShiftedPrimedTableau._preprocess([])
2434
+ sage: ShiftedPrimedTableaux(weight=())._contains_tableau(u)
2435
+ True
2436
+ sage: ShiftedPrimedTableaux(weight=(1,2))._contains_tableau(u)
2437
+ False
2438
+ """
2439
+ if not super()._contains_tableau(T):
2440
+ return False
2441
+
2442
+ flat = [item.integer() for sublist in T for item in sublist]
2443
+ if not flat:
2444
+ return not self._weight
2445
+ max_ind = max(flat)
2446
+ weight = tuple([flat.count(i+1) for i in range(max_ind)])
2447
+ return self._weight == weight
2448
+
2449
+ def __iter__(self):
2450
+ """
2451
+ Iterate over ``self``.
2452
+
2453
+ EXAMPLES::
2454
+
2455
+ sage: Tabs = ShiftedPrimedTableaux(weight=(2,3))
2456
+ sage: Tabs[:4]
2457
+ [[(1, 1, 2, 2, 2)],
2458
+ [(1, 1, 2', 2, 2)],
2459
+ [(1, 1, 2, 2), (2,)],
2460
+ [(1, 1, 2', 2), (2,)]]
2461
+ sage: len(list(Tabs))
2462
+ 5
2463
+ sage: Tabs = ShiftedPrimedTableaux(weight=(2,3),
2464
+ ....: primed_diagonal=True)
2465
+ sage: Tabs[:4]
2466
+ [[(1, 1, 2, 2, 2)],
2467
+ [(1, 1, 2', 2, 2)],
2468
+ [(1', 1, 2, 2, 2)],
2469
+ [(1', 1, 2', 2, 2)]]
2470
+ sage: len(list(Tabs))
2471
+ 16
2472
+ """
2473
+ for shape_ in ZS1_iterator(sum(self._weight)):
2474
+ if all(shape_[i] > shape_[i+1] for i in range(len(shape_)-1)):
2475
+ for tab in ShiftedPrimedTableaux(shape=shape_, weight=self._weight,
2476
+ skew=self._skew,
2477
+ primed_diagonal=self._primed_diagonal
2478
+ ):
2479
+ yield self.element_class(self, tab, check=False, preprocessed=True)
2480
+
2481
+
2482
+ class ShiftedPrimedTableaux_weight_shape(ShiftedPrimedTableaux):
2483
+ """
2484
+ Shifted primed tableaux of the fixed weight and shape.
2485
+
2486
+ EXAMPLES::
2487
+
2488
+ sage: ShiftedPrimedTableaux([4,2,1], weight=(2,3,2))
2489
+ Shifted Primed Tableaux of weight (2, 3, 2) and shape [4, 2, 1]
2490
+ sage: ShiftedPrimedTableaux([4,2,1], weight=(2,3,2)).cardinality()
2491
+ 4
2492
+ sage: T = ShiftedPrimedTableaux([4,2,1], weight=(2,3,2),
2493
+ ....: primed_diagonal=True)
2494
+ sage: T[:6]
2495
+ [[(1, 1, 2, 2), (2, 3'), (3,)],
2496
+ [(1, 1, 2, 2), (2, 3'), (3',)],
2497
+ [(1, 1, 2, 2), (2', 3'), (3,)],
2498
+ [(1, 1, 2, 2), (2', 3'), (3',)],
2499
+ [(1, 1, 2', 3), (2, 2), (3,)],
2500
+ [(1, 1, 2', 3), (2, 2), (3',)]]
2501
+ sage: T.cardinality()
2502
+ 32
2503
+ """
2504
+
2505
+ def __init__(self, weight, shape, skew=None, primed_diagonal=False):
2506
+ """
2507
+ Initialize the class of shifted primed tableaux of the given weight
2508
+ and shape.
2509
+
2510
+ TESTS::
2511
+
2512
+ sage: TestSuite( ShiftedPrimedTableaux([4,2,1],
2513
+ ....: weight=(3,2,2)) ).run()
2514
+ sage: TestSuite( ShiftedPrimedTableaux([4,2,1],
2515
+ ....: weight=(3,2,2), primed_diagonal=True) ).run()
2516
+ """
2517
+ ShiftedPrimedTableaux.__init__(self, skew=skew, primed_diagonal=primed_diagonal)
2518
+ if skew is None:
2519
+ Parent.__init__(self, category=FiniteEnumeratedSets())
2520
+ else:
2521
+ Parent.__init__(self, category=Sets().Finite())
2522
+ self._weight = weight
2523
+ if skew is None:
2524
+ self._shape = _Partitions(shape)
2525
+ else:
2526
+ self._shape = SkewPartition((shape, skew))
2527
+
2528
+ def _repr_(self):
2529
+ """
2530
+ Return a string representation of ``self``.
2531
+
2532
+ TESTS::
2533
+
2534
+ sage: ShiftedPrimedTableaux([3,2,1], weight=(4,2))
2535
+ Shifted Primed Tableaux of weight (4, 2) and shape [3, 2, 1]
2536
+ """
2537
+ return ("Shifted Primed Tableaux of weight {} and shape {}"
2538
+ .format(self._weight, self._shape))
2539
+
2540
+ def _contains_tableau(self, T):
2541
+ """
2542
+ Check if ``self`` contains preprocessed tableau ``T``.
2543
+
2544
+ TESTS::
2545
+
2546
+ sage: t = ShiftedPrimedTableau._preprocess([[1,1.5],[2]])
2547
+ sage: ShiftedPrimedTableaux([2,1],
2548
+ ....: weight=(1,2))._contains_tableau(t)
2549
+ True
2550
+ sage: t = ShiftedPrimedTableau._preprocess([[0.5,1.5],[2]])
2551
+ sage: ShiftedPrimedTableaux([2,1],
2552
+ ....: weight=(1,2))._contains_tableau(t)
2553
+ False
2554
+ sage: t = ShiftedPrimedTableau._preprocess([[0.5,1.5],[2]])
2555
+ sage: ShiftedPrimedTableaux([2,1], weight=(1,2),
2556
+ ....: primed_diagonal=True)._contains_tableau(t)
2557
+ True
2558
+ sage: ShiftedPrimedTableaux([2,1],
2559
+ ....: weight=(2,1))._contains_tableau(t)
2560
+ False
2561
+ sage: s = ShiftedPrimedTableau._preprocess([[1,1.5,2,3],[3]])
2562
+ sage: ShiftedPrimedTableaux([3,2],
2563
+ ....: weight=(1,2,2))._contains_tableau(s)
2564
+ False
2565
+
2566
+ sage: u = ShiftedPrimedTableau._preprocess([])
2567
+ sage: ShiftedPrimedTableaux([3,2],
2568
+ ....: weight=(1,2,2))._contains_tableau(u)
2569
+ False
2570
+ sage: ShiftedPrimedTableaux([], weight=())._contains_tableau(u)
2571
+ True
2572
+ """
2573
+ if not super()._contains_tableau(T):
2574
+ return False
2575
+
2576
+ flat = [item.integer() for sublist in T for item in sublist]
2577
+ if not flat:
2578
+ # It is sufficient only to check this because the weight
2579
+ # and shape must be compatible
2580
+ return not self._weight
2581
+
2582
+ max_ind = max(flat)
2583
+ weight = tuple([flat.count(i+1) for i in range(max_ind)])
2584
+ if self._weight != weight:
2585
+ return False
2586
+
2587
+ shape = [len(row) for row in T]
2588
+ skew = [row.count(None) for row in T]
2589
+ if sum(skew) == 0:
2590
+ shape = _Partitions(shape)
2591
+ else:
2592
+ shape = SkewPartition((shape, skew))
2593
+ return self._shape == shape
2594
+
2595
+ def __iter__(self):
2596
+ """
2597
+ Iterate over ``self``.
2598
+
2599
+ EXAMPLES::
2600
+
2601
+ sage: Tabs = ShiftedPrimedTableaux([3,2], weight=(1,2,2))
2602
+ sage: Tabs[:4]
2603
+ [[(1, 2, 2), (3, 3)],
2604
+ [(1, 2', 3'), (2, 3)],
2605
+ [(1, 2', 3'), (2, 3')],
2606
+ [(1, 2', 2), (3, 3)]]
2607
+ sage: len(list(Tabs))
2608
+ 4
2609
+ sage: Tabs = ShiftedPrimedTableaux([3,2],weight=(1,2,2),
2610
+ ....: primed_diagonal=True)
2611
+ sage: Tabs[:4]
2612
+ [[(1, 2, 2), (3, 3)],
2613
+ [(1, 2, 2), (3', 3)],
2614
+ [(1, 2', 3'), (2, 3)],
2615
+ [(1, 2', 3'), (2, 3')]]
2616
+ sage: len(list(Tabs))
2617
+ 16
2618
+
2619
+ TESTS::
2620
+
2621
+ sage: Tabs = ShiftedPrimedTableaux([3,2], weight=(1,4))
2622
+ sage: list(Tabs)
2623
+ []
2624
+ """
2625
+ if self._skew is not None:
2626
+ raise NotImplementedError('skew tableau must be empty')
2627
+
2628
+ if not self._shape.dominates(sorted(self._weight, reverse=True)):
2629
+ return
2630
+ full_shape = self._shape
2631
+ sub_tab = []
2632
+ tab_list_new = [[]]
2633
+ half = ~QQ(2)
2634
+ for i, w in enumerate(self._weight):
2635
+ tab_list_old = tab_list_new
2636
+ tab_list_new = []
2637
+ for sub_tab in tab_list_old:
2638
+ sub_shape = [len(row) for row in sub_tab]
2639
+ for strip in _add_strip(sub_shape, full_shape, w):
2640
+ l = len(strip) // 2
2641
+ new_tab = []
2642
+ new_tab1 = None
2643
+ if len(sub_shape) < len(full_shape):
2644
+ new_tab = [sub_tab[r] + [i+half]*strip[r] + [i+1]*strip[-r-1]
2645
+ for r in range(l-1)]
2646
+ if strip[l] != 0:
2647
+ if self._primed_diagonal:
2648
+ new_tab1 = new_tab[:]
2649
+ new_tab1.append([i+half] + [i+1] * (strip[l]-1))
2650
+ new_tab.append([i+1] * strip[l])
2651
+ else:
2652
+ new_tab = [sub_tab[r] + [i+half]*strip[r] + [i+1]*strip[-r-1]
2653
+ for r in range(l)]
2654
+ tab_list_new.append(new_tab)
2655
+ if new_tab1:
2656
+ tab_list_new.append(new_tab1)
2657
+ for tab in tab_list_new:
2658
+ yield self.element_class(self, tab)
2659
+
2660
+
2661
+ ####################
2662
+ # Helper functions #
2663
+ ####################
2664
+
2665
+
2666
+ def _add_strip(sub_tab, full_tab, length):
2667
+ """
2668
+ Helper function used in the algorithm to generate all shifted primed
2669
+ tableaux of the fixed weight and shape.
2670
+
2671
+ TESTS::
2672
+
2673
+ sage: list(ShiftedPrimedTableaux([3,1], weight=(2,2))) # indirect doctest
2674
+ [[(1, 1, 2), (2,)], [(1, 1, 2'), (2,)]]
2675
+ sage: list(ShiftedPrimedTableaux([3,1], weight=(2,2), # indirect doctest
2676
+ ....: primed_diagonal=True))
2677
+ [[(1, 1, 2), (2,)],
2678
+ [(1, 1, 2), (2',)],
2679
+ [(1, 1, 2'), (2,)],
2680
+ [(1, 1, 2'), (2',)],
2681
+ [(1', 1, 2), (2,)],
2682
+ [(1', 1, 2), (2',)],
2683
+ [(1', 1, 2'), (2,)],
2684
+ [(1', 1, 2'), (2',)]]
2685
+ """
2686
+ if sum(sub_tab) + length > sum(full_tab):
2687
+ raise ValueError("strip does not fit")
2688
+
2689
+ if not sub_tab:
2690
+ cliff_list = []
2691
+ else:
2692
+ cliff_list = [int(sub_tab[0] != full_tab[0])]
2693
+
2694
+ for row in range(1, len(sub_tab)):
2695
+ if sub_tab[row] == full_tab[row]:
2696
+ cliff_list.append(0)
2697
+ elif sub_tab[row-1] - 1 == sub_tab[row]:
2698
+ cliff_list[-1] += 1
2699
+ else:
2700
+ cliff_list.append(1)
2701
+
2702
+ if len(sub_tab) < len(full_tab):
2703
+ cliff_list.append(0)
2704
+
2705
+ for primes_num in range(min(sum(cliff_list), length) + 1):
2706
+ for primed_list in IntegerVectors(n=primes_num, k=len(cliff_list),
2707
+ outer=cliff_list):
2708
+ row = 0
2709
+ primed_strip = []
2710
+ for i, cliff in enumerate(cliff_list):
2711
+ if cliff == 0:
2712
+ row += 1
2713
+ primed_strip.append(0)
2714
+ primed_strip.extend([int(primed_list[i] > j)
2715
+ for j in range(cliff)])
2716
+ row += cliff
2717
+ plat_list = []
2718
+
2719
+ if sub_tab and len(sub_tab) < len(full_tab):
2720
+ plat_list.append(min(sub_tab[-1] + primed_strip[-2] - 1,
2721
+ full_tab[len(sub_tab)]))
2722
+ plat_list.extend(
2723
+ min(sub_tab[row-1] + primed_strip[row-1] - 1, full_tab[row])
2724
+ - sub_tab[row] - primed_strip[row]
2725
+ for row in reversed(range(1, len(sub_tab))))
2726
+
2727
+ if sub_tab:
2728
+ plat_list.append(full_tab[0] - sub_tab[0] - primed_strip[0])
2729
+ else:
2730
+ plat_list.append(full_tab[0])
2731
+
2732
+ for non_primed_strip in IntegerVectors(n=length-primes_num,
2733
+ k=len(plat_list),
2734
+ outer=plat_list):
2735
+ yield list(primed_strip) + list(non_primed_strip)