passagemath-combinat 10.6.42__cp314-cp314-musllinux_1_2_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (400) hide show
  1. passagemath_combinat/__init__.py +3 -0
  2. passagemath_combinat-10.6.42.dist-info/METADATA +160 -0
  3. passagemath_combinat-10.6.42.dist-info/RECORD +400 -0
  4. passagemath_combinat-10.6.42.dist-info/WHEEL +5 -0
  5. passagemath_combinat-10.6.42.dist-info/top_level.txt +3 -0
  6. passagemath_combinat.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  7. passagemath_combinat.libs/libsymmetrica-81fe8739.so.3.0.0 +0 -0
  8. sage/algebras/affine_nil_temperley_lieb.py +263 -0
  9. sage/algebras/all.py +24 -0
  10. sage/algebras/all__sagemath_combinat.py +35 -0
  11. sage/algebras/askey_wilson.py +935 -0
  12. sage/algebras/associated_graded.py +345 -0
  13. sage/algebras/cellular_basis.py +350 -0
  14. sage/algebras/cluster_algebra.py +2766 -0
  15. sage/algebras/down_up_algebra.py +860 -0
  16. sage/algebras/free_algebra.py +1698 -0
  17. sage/algebras/free_algebra_element.py +345 -0
  18. sage/algebras/free_algebra_quotient.py +405 -0
  19. sage/algebras/free_algebra_quotient_element.py +295 -0
  20. sage/algebras/free_zinbiel_algebra.py +885 -0
  21. sage/algebras/hall_algebra.py +783 -0
  22. sage/algebras/hecke_algebras/all.py +4 -0
  23. sage/algebras/hecke_algebras/ariki_koike_algebra.py +1796 -0
  24. sage/algebras/hecke_algebras/ariki_koike_specht_modules.py +475 -0
  25. sage/algebras/hecke_algebras/cubic_hecke_algebra.py +3520 -0
  26. sage/algebras/hecke_algebras/cubic_hecke_base_ring.py +1473 -0
  27. sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py +1079 -0
  28. sage/algebras/iwahori_hecke_algebra.py +3095 -0
  29. sage/algebras/jordan_algebra.py +1773 -0
  30. sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py +113 -0
  31. sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py +156 -0
  32. sage/algebras/lie_conformal_algebras/all.py +18 -0
  33. sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py +134 -0
  34. sage/algebras/lie_conformal_algebras/examples.py +43 -0
  35. sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py +131 -0
  36. sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py +139 -0
  37. sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py +174 -0
  38. sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py +167 -0
  39. sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py +107 -0
  40. sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py +135 -0
  41. sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py +353 -0
  42. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py +236 -0
  43. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py +78 -0
  44. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py +328 -0
  45. sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py +117 -0
  46. sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py +86 -0
  47. sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py +82 -0
  48. sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py +205 -0
  49. sage/algebras/nil_coxeter_algebra.py +191 -0
  50. sage/algebras/q_commuting_polynomials.py +673 -0
  51. sage/algebras/q_system.py +608 -0
  52. sage/algebras/quantum_clifford.py +959 -0
  53. sage/algebras/quantum_groups/ace_quantum_onsager.py +693 -0
  54. sage/algebras/quantum_groups/all.py +9 -0
  55. sage/algebras/quantum_groups/fock_space.py +2219 -0
  56. sage/algebras/quantum_groups/q_numbers.py +207 -0
  57. sage/algebras/quantum_groups/quantum_group_gap.py +2695 -0
  58. sage/algebras/quantum_groups/representations.py +591 -0
  59. sage/algebras/quantum_matrix_coordinate_algebra.py +1006 -0
  60. sage/algebras/quantum_oscillator.py +623 -0
  61. sage/algebras/quaternion_algebra.py +20 -0
  62. sage/algebras/quaternion_algebra_element.py +55 -0
  63. sage/algebras/rational_cherednik_algebra.py +525 -0
  64. sage/algebras/schur_algebra.py +670 -0
  65. sage/algebras/shuffle_algebra.py +1011 -0
  66. sage/algebras/splitting_algebra.py +779 -0
  67. sage/algebras/tensor_algebra.py +709 -0
  68. sage/algebras/yangian.py +1082 -0
  69. sage/algebras/yokonuma_hecke_algebra.py +1018 -0
  70. sage/all__sagemath_combinat.py +35 -0
  71. sage/combinat/SJT.py +255 -0
  72. sage/combinat/affine_permutation.py +2405 -0
  73. sage/combinat/algebraic_combinatorics.py +55 -0
  74. sage/combinat/all.py +53 -0
  75. sage/combinat/all__sagemath_combinat.py +195 -0
  76. sage/combinat/alternating_sign_matrix.py +2063 -0
  77. sage/combinat/baxter_permutations.py +346 -0
  78. sage/combinat/bijectionist.py +3220 -0
  79. sage/combinat/binary_recurrence_sequences.py +1180 -0
  80. sage/combinat/blob_algebra.py +685 -0
  81. sage/combinat/catalog_partitions.py +27 -0
  82. sage/combinat/chas/all.py +23 -0
  83. sage/combinat/chas/fsym.py +1180 -0
  84. sage/combinat/chas/wqsym.py +2601 -0
  85. sage/combinat/cluster_complex.py +326 -0
  86. sage/combinat/colored_permutations.py +2039 -0
  87. sage/combinat/colored_permutations_representations.py +964 -0
  88. sage/combinat/composition_signed.py +142 -0
  89. sage/combinat/composition_tableau.py +855 -0
  90. sage/combinat/constellation.py +1729 -0
  91. sage/combinat/core.py +751 -0
  92. sage/combinat/counting.py +12 -0
  93. sage/combinat/crystals/affine.py +742 -0
  94. sage/combinat/crystals/affine_factorization.py +518 -0
  95. sage/combinat/crystals/affinization.py +331 -0
  96. sage/combinat/crystals/alcove_path.py +2013 -0
  97. sage/combinat/crystals/all.py +22 -0
  98. sage/combinat/crystals/bkk_crystals.py +141 -0
  99. sage/combinat/crystals/catalog.py +115 -0
  100. sage/combinat/crystals/catalog_elementary_crystals.py +18 -0
  101. sage/combinat/crystals/catalog_infinity_crystals.py +33 -0
  102. sage/combinat/crystals/catalog_kirillov_reshetikhin.py +18 -0
  103. sage/combinat/crystals/crystals.py +257 -0
  104. sage/combinat/crystals/direct_sum.py +260 -0
  105. sage/combinat/crystals/elementary_crystals.py +1251 -0
  106. sage/combinat/crystals/fast_crystals.py +441 -0
  107. sage/combinat/crystals/fully_commutative_stable_grothendieck.py +1205 -0
  108. sage/combinat/crystals/generalized_young_walls.py +1076 -0
  109. sage/combinat/crystals/highest_weight_crystals.py +436 -0
  110. sage/combinat/crystals/induced_structure.py +695 -0
  111. sage/combinat/crystals/infinity_crystals.py +730 -0
  112. sage/combinat/crystals/kac_modules.py +863 -0
  113. sage/combinat/crystals/kirillov_reshetikhin.py +4196 -0
  114. sage/combinat/crystals/kyoto_path_model.py +497 -0
  115. sage/combinat/crystals/letters.cpython-314-x86_64-linux-musl.so +0 -0
  116. sage/combinat/crystals/letters.pxd +79 -0
  117. sage/combinat/crystals/letters.pyx +3056 -0
  118. sage/combinat/crystals/littelmann_path.py +1518 -0
  119. sage/combinat/crystals/monomial_crystals.py +1262 -0
  120. sage/combinat/crystals/multisegments.py +462 -0
  121. sage/combinat/crystals/mv_polytopes.py +467 -0
  122. sage/combinat/crystals/pbw_crystal.py +511 -0
  123. sage/combinat/crystals/pbw_datum.cpython-314-x86_64-linux-musl.so +0 -0
  124. sage/combinat/crystals/pbw_datum.pxd +4 -0
  125. sage/combinat/crystals/pbw_datum.pyx +487 -0
  126. sage/combinat/crystals/polyhedral_realization.py +372 -0
  127. sage/combinat/crystals/spins.cpython-314-x86_64-linux-musl.so +0 -0
  128. sage/combinat/crystals/spins.pxd +21 -0
  129. sage/combinat/crystals/spins.pyx +756 -0
  130. sage/combinat/crystals/star_crystal.py +290 -0
  131. sage/combinat/crystals/subcrystal.py +464 -0
  132. sage/combinat/crystals/tensor_product.py +1177 -0
  133. sage/combinat/crystals/tensor_product_element.cpython-314-x86_64-linux-musl.so +0 -0
  134. sage/combinat/crystals/tensor_product_element.pxd +35 -0
  135. sage/combinat/crystals/tensor_product_element.pyx +1870 -0
  136. sage/combinat/crystals/virtual_crystal.py +420 -0
  137. sage/combinat/cyclic_sieving_phenomenon.py +204 -0
  138. sage/combinat/debruijn_sequence.cpython-314-x86_64-linux-musl.so +0 -0
  139. sage/combinat/debruijn_sequence.pyx +355 -0
  140. sage/combinat/decorated_permutation.py +270 -0
  141. sage/combinat/degree_sequences.cpython-314-x86_64-linux-musl.so +0 -0
  142. sage/combinat/degree_sequences.pyx +588 -0
  143. sage/combinat/derangements.py +527 -0
  144. sage/combinat/descent_algebra.py +1008 -0
  145. sage/combinat/diagram.py +1551 -0
  146. sage/combinat/diagram_algebras.py +5886 -0
  147. sage/combinat/dyck_word.py +4349 -0
  148. sage/combinat/e_one_star.py +1623 -0
  149. sage/combinat/enumerated_sets.py +123 -0
  150. sage/combinat/expnums.cpython-314-x86_64-linux-musl.so +0 -0
  151. sage/combinat/expnums.pyx +148 -0
  152. sage/combinat/fast_vector_partitions.cpython-314-x86_64-linux-musl.so +0 -0
  153. sage/combinat/fast_vector_partitions.pyx +346 -0
  154. sage/combinat/fqsym.py +1977 -0
  155. sage/combinat/free_dendriform_algebra.py +954 -0
  156. sage/combinat/free_prelie_algebra.py +1141 -0
  157. sage/combinat/fully_commutative_elements.py +1077 -0
  158. sage/combinat/fully_packed_loop.py +1523 -0
  159. sage/combinat/gelfand_tsetlin_patterns.py +1409 -0
  160. sage/combinat/gray_codes.py +311 -0
  161. sage/combinat/grossman_larson_algebras.py +667 -0
  162. sage/combinat/growth.py +4352 -0
  163. sage/combinat/hall_polynomial.py +188 -0
  164. sage/combinat/hillman_grassl.py +866 -0
  165. sage/combinat/integer_matrices.py +329 -0
  166. sage/combinat/integer_vectors_mod_permgroup.py +1238 -0
  167. sage/combinat/k_tableau.py +4564 -0
  168. sage/combinat/kazhdan_lusztig.py +215 -0
  169. sage/combinat/key_polynomial.py +885 -0
  170. sage/combinat/knutson_tao_puzzles.py +2286 -0
  171. sage/combinat/lr_tableau.py +311 -0
  172. sage/combinat/matrices/all.py +24 -0
  173. sage/combinat/matrices/hadamard_matrix.py +3790 -0
  174. sage/combinat/matrices/latin.py +2912 -0
  175. sage/combinat/misc.py +401 -0
  176. sage/combinat/multiset_partition_into_sets_ordered.py +3541 -0
  177. sage/combinat/ncsf_qsym/all.py +21 -0
  178. sage/combinat/ncsf_qsym/combinatorics.py +317 -0
  179. sage/combinat/ncsf_qsym/generic_basis_code.py +1427 -0
  180. sage/combinat/ncsf_qsym/ncsf.py +5637 -0
  181. sage/combinat/ncsf_qsym/qsym.py +4053 -0
  182. sage/combinat/ncsf_qsym/tutorial.py +447 -0
  183. sage/combinat/ncsym/all.py +21 -0
  184. sage/combinat/ncsym/bases.py +855 -0
  185. sage/combinat/ncsym/dual.py +593 -0
  186. sage/combinat/ncsym/ncsym.py +2076 -0
  187. sage/combinat/necklace.py +551 -0
  188. sage/combinat/non_decreasing_parking_function.py +634 -0
  189. sage/combinat/nu_dyck_word.py +1474 -0
  190. sage/combinat/output.py +861 -0
  191. sage/combinat/parallelogram_polyomino.py +4326 -0
  192. sage/combinat/parking_functions.py +1602 -0
  193. sage/combinat/partition_algebra.py +1998 -0
  194. sage/combinat/partition_kleshchev.py +1982 -0
  195. sage/combinat/partition_shifting_algebras.py +584 -0
  196. sage/combinat/partition_tuple.py +3114 -0
  197. sage/combinat/path_tableaux/all.py +13 -0
  198. sage/combinat/path_tableaux/catalog.py +29 -0
  199. sage/combinat/path_tableaux/dyck_path.py +380 -0
  200. sage/combinat/path_tableaux/frieze.py +476 -0
  201. sage/combinat/path_tableaux/path_tableau.py +728 -0
  202. sage/combinat/path_tableaux/semistandard.py +510 -0
  203. sage/combinat/perfect_matching.py +779 -0
  204. sage/combinat/plane_partition.py +3300 -0
  205. sage/combinat/q_bernoulli.cpython-314-x86_64-linux-musl.so +0 -0
  206. sage/combinat/q_bernoulli.pyx +128 -0
  207. sage/combinat/quickref.py +81 -0
  208. sage/combinat/recognizable_series.py +2051 -0
  209. sage/combinat/regular_sequence.py +4316 -0
  210. sage/combinat/regular_sequence_bounded.py +543 -0
  211. sage/combinat/restricted_growth.py +81 -0
  212. sage/combinat/ribbon.py +20 -0
  213. sage/combinat/ribbon_shaped_tableau.py +489 -0
  214. sage/combinat/ribbon_tableau.py +1180 -0
  215. sage/combinat/rigged_configurations/all.py +46 -0
  216. sage/combinat/rigged_configurations/bij_abstract_class.py +548 -0
  217. sage/combinat/rigged_configurations/bij_infinity.py +370 -0
  218. sage/combinat/rigged_configurations/bij_type_A.py +163 -0
  219. sage/combinat/rigged_configurations/bij_type_A2_dual.py +338 -0
  220. sage/combinat/rigged_configurations/bij_type_A2_even.py +218 -0
  221. sage/combinat/rigged_configurations/bij_type_A2_odd.py +199 -0
  222. sage/combinat/rigged_configurations/bij_type_B.py +900 -0
  223. sage/combinat/rigged_configurations/bij_type_C.py +267 -0
  224. sage/combinat/rigged_configurations/bij_type_D.py +771 -0
  225. sage/combinat/rigged_configurations/bij_type_D_tri.py +392 -0
  226. sage/combinat/rigged_configurations/bij_type_D_twisted.py +576 -0
  227. sage/combinat/rigged_configurations/bij_type_E67.py +402 -0
  228. sage/combinat/rigged_configurations/bijection.py +143 -0
  229. sage/combinat/rigged_configurations/kleber_tree.py +1475 -0
  230. sage/combinat/rigged_configurations/kr_tableaux.py +1898 -0
  231. sage/combinat/rigged_configurations/rc_crystal.py +461 -0
  232. sage/combinat/rigged_configurations/rc_infinity.py +540 -0
  233. sage/combinat/rigged_configurations/rigged_configuration_element.py +2403 -0
  234. sage/combinat/rigged_configurations/rigged_configurations.py +1918 -0
  235. sage/combinat/rigged_configurations/rigged_partition.cpython-314-x86_64-linux-musl.so +0 -0
  236. sage/combinat/rigged_configurations/rigged_partition.pxd +15 -0
  237. sage/combinat/rigged_configurations/rigged_partition.pyx +680 -0
  238. sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +499 -0
  239. sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py +428 -0
  240. sage/combinat/rsk.py +3438 -0
  241. sage/combinat/schubert_polynomial.py +508 -0
  242. sage/combinat/set_partition.py +3318 -0
  243. sage/combinat/set_partition_iterator.cpython-314-x86_64-linux-musl.so +0 -0
  244. sage/combinat/set_partition_iterator.pyx +136 -0
  245. sage/combinat/set_partition_ordered.py +1590 -0
  246. sage/combinat/sf/abreu_nigro.py +346 -0
  247. sage/combinat/sf/all.py +52 -0
  248. sage/combinat/sf/character.py +576 -0
  249. sage/combinat/sf/classical.py +319 -0
  250. sage/combinat/sf/dual.py +996 -0
  251. sage/combinat/sf/elementary.py +549 -0
  252. sage/combinat/sf/hall_littlewood.py +1028 -0
  253. sage/combinat/sf/hecke.py +336 -0
  254. sage/combinat/sf/homogeneous.py +464 -0
  255. sage/combinat/sf/jack.py +1428 -0
  256. sage/combinat/sf/k_dual.py +1458 -0
  257. sage/combinat/sf/kfpoly.py +447 -0
  258. sage/combinat/sf/llt.py +789 -0
  259. sage/combinat/sf/macdonald.py +2019 -0
  260. sage/combinat/sf/monomial.py +525 -0
  261. sage/combinat/sf/multiplicative.py +113 -0
  262. sage/combinat/sf/new_kschur.py +1786 -0
  263. sage/combinat/sf/ns_macdonald.py +964 -0
  264. sage/combinat/sf/orthogonal.py +246 -0
  265. sage/combinat/sf/orthotriang.py +355 -0
  266. sage/combinat/sf/powersum.py +963 -0
  267. sage/combinat/sf/schur.py +880 -0
  268. sage/combinat/sf/sf.py +1653 -0
  269. sage/combinat/sf/sfa.py +7053 -0
  270. sage/combinat/sf/symplectic.py +253 -0
  271. sage/combinat/sf/witt.py +721 -0
  272. sage/combinat/shifted_primed_tableau.py +2735 -0
  273. sage/combinat/shuffle.py +830 -0
  274. sage/combinat/sidon_sets.py +146 -0
  275. sage/combinat/similarity_class_type.py +1721 -0
  276. sage/combinat/sine_gordon.py +618 -0
  277. sage/combinat/six_vertex_model.py +784 -0
  278. sage/combinat/skew_partition.py +2053 -0
  279. sage/combinat/skew_tableau.py +2989 -0
  280. sage/combinat/sloane_functions.py +8935 -0
  281. sage/combinat/specht_module.py +1403 -0
  282. sage/combinat/species/all.py +48 -0
  283. sage/combinat/species/characteristic_species.py +321 -0
  284. sage/combinat/species/composition_species.py +273 -0
  285. sage/combinat/species/cycle_species.py +284 -0
  286. sage/combinat/species/empty_species.py +155 -0
  287. sage/combinat/species/functorial_composition_species.py +148 -0
  288. sage/combinat/species/generating_series.py +673 -0
  289. sage/combinat/species/library.py +148 -0
  290. sage/combinat/species/linear_order_species.py +169 -0
  291. sage/combinat/species/misc.py +83 -0
  292. sage/combinat/species/partition_species.py +290 -0
  293. sage/combinat/species/permutation_species.py +268 -0
  294. sage/combinat/species/product_species.py +423 -0
  295. sage/combinat/species/recursive_species.py +476 -0
  296. sage/combinat/species/set_species.py +192 -0
  297. sage/combinat/species/species.py +820 -0
  298. sage/combinat/species/structure.py +539 -0
  299. sage/combinat/species/subset_species.py +243 -0
  300. sage/combinat/species/sum_species.py +225 -0
  301. sage/combinat/subword.py +564 -0
  302. sage/combinat/subword_complex.py +2122 -0
  303. sage/combinat/subword_complex_c.cpython-314-x86_64-linux-musl.so +0 -0
  304. sage/combinat/subword_complex_c.pyx +119 -0
  305. sage/combinat/super_tableau.py +821 -0
  306. sage/combinat/superpartition.py +1154 -0
  307. sage/combinat/symmetric_group_algebra.py +3774 -0
  308. sage/combinat/symmetric_group_representations.py +1830 -0
  309. sage/combinat/t_sequences.py +877 -0
  310. sage/combinat/tableau.py +9506 -0
  311. sage/combinat/tableau_residues.py +860 -0
  312. sage/combinat/tableau_tuple.py +5353 -0
  313. sage/combinat/tiling.py +2432 -0
  314. sage/combinat/triangles_FHM.py +777 -0
  315. sage/combinat/tutorial.py +1857 -0
  316. sage/combinat/vector_partition.py +337 -0
  317. sage/combinat/words/abstract_word.py +1722 -0
  318. sage/combinat/words/all.py +59 -0
  319. sage/combinat/words/alphabet.py +268 -0
  320. sage/combinat/words/finite_word.py +7201 -0
  321. sage/combinat/words/infinite_word.py +113 -0
  322. sage/combinat/words/lyndon_word.py +652 -0
  323. sage/combinat/words/morphic.py +351 -0
  324. sage/combinat/words/morphism.py +3878 -0
  325. sage/combinat/words/paths.py +2932 -0
  326. sage/combinat/words/shuffle_product.py +278 -0
  327. sage/combinat/words/suffix_trees.py +1873 -0
  328. sage/combinat/words/word.py +769 -0
  329. sage/combinat/words/word_char.cpython-314-x86_64-linux-musl.so +0 -0
  330. sage/combinat/words/word_char.pyx +847 -0
  331. sage/combinat/words/word_datatypes.cpython-314-x86_64-linux-musl.so +0 -0
  332. sage/combinat/words/word_datatypes.pxd +4 -0
  333. sage/combinat/words/word_datatypes.pyx +1067 -0
  334. sage/combinat/words/word_generators.py +2026 -0
  335. sage/combinat/words/word_infinite_datatypes.py +1218 -0
  336. sage/combinat/words/word_options.py +99 -0
  337. sage/combinat/words/words.py +2396 -0
  338. sage/data_structures/all__sagemath_combinat.py +1 -0
  339. sage/databases/all__sagemath_combinat.py +13 -0
  340. sage/databases/findstat.py +4897 -0
  341. sage/databases/oeis.py +2058 -0
  342. sage/databases/sloane.py +393 -0
  343. sage/dynamics/all__sagemath_combinat.py +14 -0
  344. sage/dynamics/cellular_automata/all.py +7 -0
  345. sage/dynamics/cellular_automata/catalog.py +34 -0
  346. sage/dynamics/cellular_automata/elementary.py +612 -0
  347. sage/dynamics/cellular_automata/glca.py +477 -0
  348. sage/dynamics/cellular_automata/solitons.py +1463 -0
  349. sage/dynamics/finite_dynamical_system.py +1249 -0
  350. sage/dynamics/finite_dynamical_system_catalog.py +382 -0
  351. sage/games/all.py +7 -0
  352. sage/games/hexad.py +704 -0
  353. sage/games/quantumino.py +591 -0
  354. sage/games/sudoku.py +889 -0
  355. sage/games/sudoku_backtrack.cpython-314-x86_64-linux-musl.so +0 -0
  356. sage/games/sudoku_backtrack.pyx +189 -0
  357. sage/groups/all__sagemath_combinat.py +1 -0
  358. sage/groups/indexed_free_group.py +489 -0
  359. sage/libs/all__sagemath_combinat.py +6 -0
  360. sage/libs/lrcalc/__init__.py +1 -0
  361. sage/libs/lrcalc/lrcalc.py +525 -0
  362. sage/libs/symmetrica/__init__.py +7 -0
  363. sage/libs/symmetrica/all.py +101 -0
  364. sage/libs/symmetrica/kostka.pxi +168 -0
  365. sage/libs/symmetrica/part.pxi +193 -0
  366. sage/libs/symmetrica/plet.pxi +42 -0
  367. sage/libs/symmetrica/sab.pxi +196 -0
  368. sage/libs/symmetrica/sb.pxi +332 -0
  369. sage/libs/symmetrica/sc.pxi +192 -0
  370. sage/libs/symmetrica/schur.pxi +956 -0
  371. sage/libs/symmetrica/symmetrica.cpython-314-x86_64-linux-musl.so +0 -0
  372. sage/libs/symmetrica/symmetrica.pxi +1172 -0
  373. sage/libs/symmetrica/symmetrica.pyx +39 -0
  374. sage/monoids/all.py +13 -0
  375. sage/monoids/automatic_semigroup.py +1054 -0
  376. sage/monoids/free_abelian_monoid.py +315 -0
  377. sage/monoids/free_abelian_monoid_element.cpython-314-x86_64-linux-musl.so +0 -0
  378. sage/monoids/free_abelian_monoid_element.pxd +16 -0
  379. sage/monoids/free_abelian_monoid_element.pyx +397 -0
  380. sage/monoids/free_monoid.py +335 -0
  381. sage/monoids/free_monoid_element.py +431 -0
  382. sage/monoids/hecke_monoid.py +65 -0
  383. sage/monoids/string_monoid.py +817 -0
  384. sage/monoids/string_monoid_element.py +547 -0
  385. sage/monoids/string_ops.py +143 -0
  386. sage/monoids/trace_monoid.py +972 -0
  387. sage/rings/all__sagemath_combinat.py +2 -0
  388. sage/sat/all.py +4 -0
  389. sage/sat/boolean_polynomials.py +405 -0
  390. sage/sat/converters/__init__.py +6 -0
  391. sage/sat/converters/anf2cnf.py +14 -0
  392. sage/sat/converters/polybori.py +611 -0
  393. sage/sat/solvers/__init__.py +5 -0
  394. sage/sat/solvers/cryptominisat.py +287 -0
  395. sage/sat/solvers/dimacs.py +783 -0
  396. sage/sat/solvers/picosat.py +228 -0
  397. sage/sat/solvers/sat_lp.py +156 -0
  398. sage/sat/solvers/satsolver.cpython-314-x86_64-linux-musl.so +0 -0
  399. sage/sat/solvers/satsolver.pxd +3 -0
  400. sage/sat/solvers/satsolver.pyx +405 -0
@@ -0,0 +1,1551 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ r"""
3
+ Combinatorial diagrams
4
+
5
+ A combinatorial diagram is a collection of cells `(i,j)` indexed by pairs of
6
+ natural numbers.
7
+
8
+ For arbitrary diagrams, see :class:`Diagram`. There are also two other specific
9
+ types of diagrams implemented here. They are northwest diagrams
10
+ (:class:`NorthwestDiagram`) and Rothe diagrams (:func:`RotheDiagram`, a special
11
+ kind of northwest diagram).
12
+
13
+ AUTHORS:
14
+
15
+ - Trevor K. Karn (2022-08-01): initial version
16
+ """
17
+
18
+ # ****************************************************************************
19
+ # Copyright (C) 2022 Trevor K. Karn <karnx018 (at) umn.edu>
20
+ #
21
+ # This program is free software: you can redistribute it and/or modify
22
+ # it under the terms of the GNU General Public License as published by
23
+ # the Free Software Foundation, either version 2 of the License, or
24
+ # (at your option) any later version.
25
+ # https://www.gnu.org/licenses/
26
+ # ****************************************************************************
27
+ from itertools import product
28
+
29
+ from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
30
+ from sage.combinat.composition import Composition
31
+ from sage.combinat.partition import Partition
32
+ from sage.combinat.permutation import Permutations
33
+ from sage.combinat.skew_partition import SkewPartition
34
+ from sage.combinat.skew_tableau import SkewTableaux
35
+ from sage.combinat.tableau import Tableau
36
+ from sage.misc.cachefunc import cached_method
37
+ from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass
38
+ from sage.misc.lazy_import import lazy_import
39
+ from sage.structure.element import Matrix
40
+ from sage.structure.list_clone import ClonableArray
41
+ from sage.structure.parent import Parent
42
+ from sage.structure.unique_representation import UniqueRepresentation
43
+
44
+ lazy_import('sage.combinat.tiling', 'Polyomino')
45
+
46
+
47
+ class Diagram(ClonableArray, metaclass=InheritComparisonClasscallMetaclass):
48
+ r"""
49
+ Combinatorial diagrams with positions indexed by rows and columns.
50
+
51
+ The positions are indexed by rows and columns as in a matrix. For example,
52
+ a Ferrers diagram is a diagram obtained from a partition
53
+ `\lambda = (\lambda_0, \lambda_1, \ldots, \lambda_{\ell})`, where the
54
+ cells are in rows `i` for `0 \leq i \leq \ell` and the cells in row `i`
55
+ consist of `(i,j)` for `0 \leq j < \lambda_i`. In English notation, the
56
+ indices are read from top left to bottom right as in a matrix.
57
+
58
+ Indexing conventions are the same as
59
+ :class:`~sage.combinat.partition.Partition`. Printing the diagram of a
60
+ partition, however, will always be in English notation.
61
+
62
+ EXAMPLES:
63
+
64
+ To create an arbitrary diagram, pass a list of all cells::
65
+
66
+ sage: from sage.combinat.diagram import Diagram
67
+ sage: cells = [(0,0), (0,1), (1,0), (1,1), (4,4), (4,5), (4,6), (5,4), (7, 6)]
68
+ sage: D = Diagram(cells); D
69
+ [(0, 0), (0, 1), (1, 0), (1, 1), (4, 4), (4, 5), (4, 6), (5, 4), (7, 6)]
70
+
71
+ We can visualize the diagram by printing ``O``'s and ``.``'s. ``O``'s are
72
+ present in the cells which are present in the diagram and a ``.`` represents
73
+ the absence of a cell in the diagram::
74
+
75
+ sage: D.pp()
76
+ O O . . . . .
77
+ O O . . . . .
78
+ . . . . . . .
79
+ . . . . . . .
80
+ . . . . O O O
81
+ . . . . O . .
82
+ . . . . . . .
83
+ . . . . . . O
84
+
85
+ We can also check if certain cells are contained in a given diagram::
86
+
87
+ sage: (1, 0) in D
88
+ True
89
+ sage: (2, 2) in D
90
+ False
91
+
92
+ If you know that there are entire empty rows or columns at the end of the
93
+ diagram, you can manually pass them with keyword arguments ``n_rows=`` or
94
+ ``n_cols=``::
95
+
96
+ sage: Diagram([(0,0), (0,3), (2,2), (2,4)]).pp()
97
+ O . . O .
98
+ . . . . .
99
+ . . O . O
100
+ sage: Diagram([(0,0), (0,3), (2,2), (2,4)], n_rows=6, n_cols=6).pp()
101
+ O . . O . .
102
+ . . . . . .
103
+ . . O . O .
104
+ . . . . . .
105
+ . . . . . .
106
+ . . . . . .
107
+ """
108
+ @staticmethod
109
+ def __classcall_private__(self, cells, n_rows=None, n_cols=None, check=True):
110
+ r"""
111
+ Normalize the input so that it lives in the correct parent.
112
+
113
+ EXAMPLES::
114
+
115
+ sage: from sage.combinat.diagram import Diagram
116
+ sage: D = Diagram([(0,0), (0,3), (2,2), (2,4)])
117
+ sage: D.parent()
118
+ Combinatorial diagrams
119
+ """
120
+ return Diagrams()(cells, n_rows, n_cols, check)
121
+
122
+ def __init__(self, parent, cells, n_rows=None, n_cols=None, check=True):
123
+ r"""
124
+ Initialize ``self``.
125
+
126
+ EXAMPLES::
127
+
128
+ sage: from sage.combinat.diagram import Diagram
129
+ sage: D1 = Diagram([(0,2),(0,3),(1,1),(3,2)])
130
+ sage: D1.cells()
131
+ [(0, 2), (0, 3), (1, 1), (3, 2)]
132
+ sage: D1.nrows()
133
+ 4
134
+ sage: D1.ncols()
135
+ 4
136
+ sage: TestSuite(D1).run()
137
+
138
+ We can specify the number of rows and columns explicitly,
139
+ in case they are supposed to be empty::
140
+
141
+ sage: D2 = Diagram([(0,2),(0,3),(1,1),(3,2)], n_cols=5)
142
+ sage: D2.cells()
143
+ [(0, 2), (0, 3), (1, 1), (3, 2)]
144
+ sage: D2.ncols()
145
+ 5
146
+ sage: D2.pp()
147
+ . . O O .
148
+ . O . . .
149
+ . . . . .
150
+ . . O . .
151
+ sage: TestSuite(D2).run()
152
+ """
153
+ self._cells = frozenset(cells)
154
+
155
+ if self._cells:
156
+ # minimum possible number of rows/cols
157
+ N_rows = max(c[0] for c in self._cells)
158
+ N_cols = max(c[1] for c in self._cells)
159
+ else: # if there are no cells
160
+ N_rows = -1
161
+ N_cols = -1
162
+
163
+ if n_rows is not None:
164
+ if n_rows <= N_rows:
165
+ raise ValueError('n_rows is too small')
166
+ self._n_rows = n_rows
167
+ else:
168
+ self._n_rows = N_rows + 1
169
+ if n_cols is not None:
170
+ if n_cols <= N_cols:
171
+ raise ValueError('n_cols is too small')
172
+ self._n_cols = n_cols
173
+ else:
174
+ self._n_cols = N_cols + 1
175
+
176
+ self._n_nonempty_rows = len(set(i for i, j in self._cells))
177
+ self._n_nonempty_cols = len(set(j for i, j in self._cells))
178
+
179
+ ClonableArray.__init__(self, parent, sorted(cells), check)
180
+
181
+ def pp(self):
182
+ r"""
183
+ Return a visualization of the diagram.
184
+
185
+ Cells which are present in the
186
+ diagram are filled with a ``O``. Cells which are not present in the
187
+ diagram are filled with a ``.``.
188
+
189
+ EXAMPLES::
190
+
191
+ sage: from sage.combinat.diagram import Diagram
192
+ sage: Diagram([(0,0), (0,3), (2,2), (2,4)]).pp()
193
+ O . . O .
194
+ . . . . .
195
+ . . O . O
196
+ sage: Diagram([(0,0), (0,3), (2,2), (2,4)], n_rows=6, n_cols=6).pp()
197
+ O . . O . .
198
+ . . . . . .
199
+ . . O . O .
200
+ . . . . . .
201
+ . . . . . .
202
+ . . . . . .
203
+ sage: Diagram([]).pp()
204
+ -
205
+ """
206
+ if self._n_rows == 0 or self._n_cols == 0:
207
+ print('-')
208
+ return
209
+ print("\n".join(self._pretty_print()))
210
+
211
+ def _ascii_art_(self):
212
+ r"""
213
+ Return a visualization of the diagram.
214
+
215
+ Cells which are present in the
216
+ diagram are filled with a ``O``. Cells which are not present in the
217
+ diagram are filled with a ``.``.
218
+
219
+ EXAMPLES::
220
+
221
+ sage: from sage.combinat.diagram import Diagram
222
+ sage: ascii_art(Diagram([(0,0), (0,3), (2,2), (2,4)]))
223
+ O . . O .
224
+ . . . . .
225
+ . . O . O
226
+ sage: ascii_art(Diagram([(0,0), (0,3), (2,2), (2,4)], n_rows=6, n_cols=6))
227
+ O . . O . .
228
+ . . . . . .
229
+ . . O . O .
230
+ . . . . . .
231
+ . . . . . .
232
+ . . . . . .
233
+ sage: ascii_art(Diagram([]))
234
+ -
235
+ """
236
+ from sage.typeset.ascii_art import ascii_art
237
+ if self._n_rows == 0 or self._n_cols == 0:
238
+ return ascii_art("-")
239
+ return ascii_art("\n".join(self._pretty_print()))
240
+
241
+ def _unicode_art_(self):
242
+ r"""
243
+ Return a unicode visualization of the diagram.
244
+
245
+ Cells which are present in the
246
+ diagram are filled with a crossed box. Cells which are not present in the
247
+ diagram are filled with an empty box.
248
+
249
+ EXAMPLES::
250
+
251
+ sage: from sage.combinat.diagram import Diagram
252
+ sage: unicode_art(Diagram([(0,0), (0,3), (2,2), (2,4)]))
253
+ ┌─┬─┬─┬─┬─┐
254
+ │X│ │ │X│ │
255
+ ├─┼─┼─┼─┼─┤
256
+ │ │ │ │ │ │
257
+ ├─┼─┼─┼─┼─┤
258
+ │ │ │X│ │X│
259
+ └─┴─┴─┴─┴─┘
260
+ sage: unicode_art(Diagram([(0,0), (0,3), (2,2), (2,4)], n_rows=6, n_cols=6))
261
+ ┌─┬─┬─┬─┬─┬─┐
262
+ │X│ │ │X│ │ │
263
+ ├─┼─┼─┼─┼─┼─┤
264
+ │ │ │ │ │ │ │
265
+ ├─┼─┼─┼─┼─┼─┤
266
+ │ │ │X│ │X│ │
267
+ ├─┼─┼─┼─┼─┼─┤
268
+ │ │ │ │ │ │ │
269
+ ├─┼─┼─┼─┼─┼─┤
270
+ │ │ │ │ │ │ │
271
+ ├─┼─┼─┼─┼─┼─┤
272
+ │ │ │ │ │ │ │
273
+ └─┴─┴─┴─┴─┴─┘
274
+ sage: unicode_art(Diagram([]))
275
+
276
+ """
277
+ from sage.typeset.unicode_art import unicode_art
278
+ if self._n_rows == 0 or self._n_cols == 0:
279
+ return unicode_art("∅")
280
+
281
+ ndivs = self._n_cols - 1
282
+ cell = "│X"
283
+ empty = "│ "
284
+ it = self._pretty_print(cell, empty)
285
+ ret = "┌─" + "┬─"*ndivs + "┐"
286
+ ret += "\n" + next(it) + "│"
287
+ for row in it:
288
+ ret += "\n├─" + "┼─"*ndivs + "┤"
289
+ ret += "\n" + row + "│"
290
+ ret += "\n└─" + "┴─"*ndivs + "┘"
291
+ return unicode_art(ret)
292
+
293
+ def _pretty_print(self, cell='O ', empty='. '):
294
+ r"""
295
+ Return a visualization of the diagram.
296
+
297
+ Cells which are present in the
298
+ diagram are filled with ``cell``. Cells which are not present in the
299
+ diagram are filled with ``empty``.
300
+
301
+ EXAMPLES::
302
+
303
+ sage: from sage.combinat.diagram import Diagram
304
+ sage: "\n".join(Diagram([(0,0), (0,3), (2,2), (2,4)])._pretty_print('x ','. '))
305
+ 'x . . x . \n. . . . . \n. . x . x '
306
+ sage: "\n".join(Diagram([(0,0), (0,3), (2,2), (2,4)], n_rows=6, n_cols=6)._pretty_print('x ','. '))
307
+ 'x . . x . . \n. . . . . . \n. . x . x . \n. . . . . . \n. . . . . . \n. . . . . . '
308
+ """
309
+ for i in range(self._n_rows):
310
+ output_str = ''
311
+ for j in range(self._n_cols):
312
+ if (i, j) in self:
313
+ output_str += cell
314
+ else:
315
+ output_str += empty
316
+ yield output_str
317
+
318
+ def _latex_(self):
319
+ r"""
320
+ Return a latex representation of ``self``.
321
+
322
+ EXAMPLES::
323
+
324
+ sage: from sage.combinat.diagram import Diagram
325
+ sage: latex(Diagram([]))
326
+ {\emptyset}
327
+ sage: latex(Diagram([(0,0), (0,3), (2,2), (2,4)]))
328
+ {\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
329
+ \raisebox{-.6ex}{$\begin{array}[b]{*{5}{p{0.6ex}}}\cline{1-1}\cline{4-4}
330
+ \lr{\phantom{x}}&&&\lr{\phantom{x}}&\\\cline{1-1}\cline{4-4}
331
+ &&&&\\\cline{3-3}\cline{5-5}
332
+ &&\lr{\phantom{x}}&&\lr{\phantom{x}}\\\cline{3-3}\cline{5-5}
333
+ \end{array}$}
334
+ }
335
+ """
336
+ if self._n_rows == 0 or self._n_cols == 0:
337
+ return "{\\emptyset}"
338
+
339
+ lr = r'\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}'
340
+
341
+ array = [[("\\phantom{x}" if (i, j) in self else None)
342
+ for j in range(self._n_cols)]
343
+ for i in range(self._n_rows)]
344
+
345
+ def end_line(r):
346
+ # give the line ending to row ``r``
347
+ if r == 0:
348
+ return "".join(r'\cline{%s-%s}' % (i+1, i+1)
349
+ for i, j in enumerate(array[0]) if j is not None)
350
+ elif r == len(array):
351
+ return r"\\" + "".join(r'\cline{%s-%s}' % (i+1, i+1)
352
+ for i, j in enumerate(array[r-1]) if j is not None)
353
+ else:
354
+ out = r"\\" + "".join(r'\cline{%s-%s}' % (i+1, i+1)
355
+ for i, j in enumerate(array[r-1]) if j is not None)
356
+ out += "".join(r'\cline{%s-%s}' % (i+1, i+1)
357
+ for i, j in enumerate(array[r]) if j is not None)
358
+ return out
359
+
360
+ tex = r'\raisebox{-.6ex}{$\begin{array}[b]{*{%s}{p{0.6ex}}}' % (max(map(len, array)))
361
+ tex += end_line(0)+'\n'
362
+ for r in range(len(array)):
363
+ tex += '&'.join('' if c is None else r'\lr{%s}' % (c,) for c in array[r])
364
+ tex += end_line(r+1)+'\n'
365
+ return '{%s\n%s\n}' % (lr, tex+r'\end{array}$}')
366
+
367
+ def number_of_rows(self):
368
+ r"""
369
+ Return the total number of rows of ``self``.
370
+
371
+ EXAMPLES:
372
+
373
+ The following example has three rows which are filled, but they
374
+ are contained in rows 0 to 3 (for a total of four)::
375
+
376
+ sage: from sage.combinat.diagram import Diagram
377
+ sage: D1 = Diagram([(0,2),(0,3),(1,1),(3,2)])
378
+ sage: D1.number_of_rows()
379
+ 4
380
+ sage: D1.nrows()
381
+ 4
382
+
383
+ The total number of rows includes including those which are empty.
384
+ We can also include empty rows at the end::
385
+
386
+ sage: from sage.combinat.diagram import Diagram
387
+ sage: D = Diagram([(0,2),(0,3),(1,1),(3,2)], n_rows=6)
388
+ sage: D.number_of_rows()
389
+ 6
390
+ sage: D.pp()
391
+ . . O O
392
+ . O . .
393
+ . . . .
394
+ . . O .
395
+ . . . .
396
+ . . . .
397
+ """
398
+ return self._n_rows
399
+
400
+ nrows = number_of_rows
401
+
402
+ def number_of_cols(self):
403
+ r"""
404
+ Return the total number of rows of ``self``.
405
+
406
+ EXAMPLES:
407
+
408
+ The following example has three columns which are filled, but they
409
+ are contained in rows 0 to 3 (for a total of four)::
410
+
411
+ sage: from sage.combinat.diagram import Diagram
412
+ sage: D = Diagram([(0,2),(0,3),(1,1),(3,2)])
413
+ sage: D.number_of_cols()
414
+ 4
415
+ sage: D.ncols()
416
+ 4
417
+
418
+ We can also include empty columns at the end::
419
+
420
+ sage: from sage.combinat.diagram import Diagram
421
+ sage: D = Diagram([(0,2),(0,3),(1,1),(3,2)], n_cols=6)
422
+ sage: D.number_of_cols()
423
+ 6
424
+ sage: D.pp()
425
+ . . O O . .
426
+ . O . . . .
427
+ . . . . . .
428
+ . . O . . .
429
+ """
430
+ return self._n_cols
431
+
432
+ ncols = number_of_cols
433
+
434
+ def cells(self):
435
+ r"""
436
+ Return a ``list`` of the cells contained in the diagram ``self``.
437
+
438
+ EXAMPLES::
439
+
440
+ sage: from sage.combinat.diagram import Diagram
441
+ sage: D1 = Diagram([(0,2),(0,3),(1,1),(3,2)])
442
+ sage: D1.cells()
443
+ [(0, 2), (0, 3), (1, 1), (3, 2)]
444
+ """
445
+ return sorted(self._cells)
446
+
447
+ def number_of_cells(self):
448
+ r"""
449
+ Return the total number of cells contained in the diagram ``self``.
450
+
451
+ EXAMPLES::
452
+
453
+ sage: from sage.combinat.diagram import Diagram
454
+ sage: D1 = Diagram([(0,2),(0,3),(1,1),(3,2)])
455
+ sage: D1.number_of_cells()
456
+ 4
457
+ sage: D1.n_cells()
458
+ 4
459
+ """
460
+ return len(self._cells)
461
+
462
+ n_cells = number_of_cells
463
+
464
+ size = number_of_cells
465
+
466
+ def check(self):
467
+ r"""
468
+ Check that this is a valid diagram.
469
+
470
+ EXAMPLES::
471
+
472
+ sage: from sage.combinat.diagram import Diagram
473
+ sage: D = Diagram([(0,0), (0,3), (2,2), (2,4)])
474
+ sage: D.check()
475
+
476
+ In the next two examples, a bad diagram is passed.
477
+ The first example fails because one cell is indexed by negative
478
+ integers::
479
+
480
+ sage: D = Diagram([(0,0), (0,-3), (2,2), (2,4)])
481
+ Traceback (most recent call last):
482
+ ...
483
+ ValueError: diagrams must be indexed by nonnegative integers
484
+
485
+ The next example fails because one cell is indexed by rational
486
+ numbers::
487
+
488
+ sage: D = Diagram([(0,0), (0,3), (2/3,2), (2,4)])
489
+ Traceback (most recent call last):
490
+ ...
491
+ ValueError: diagrams must be indexed by nonnegative integers
492
+ """
493
+ from sage.sets.non_negative_integers import NonNegativeIntegers
494
+ NN = NonNegativeIntegers()
495
+ if not all(i in NN for c in self._cells for i in c):
496
+ raise ValueError("diagrams must be indexed by nonnegative integers")
497
+
498
+ def specht_module(self, base_ring=None):
499
+ r"""
500
+ Return the Specht module corresponding to ``self``.
501
+
502
+ EXAMPLES::
503
+
504
+ sage: from sage.combinat.diagram import Diagram
505
+ sage: D = Diagram([(0,0), (1,1), (2,2), (2,3)])
506
+ sage: SM = D.specht_module(QQ) # needs sage.modules
507
+ sage: s = SymmetricFunctions(QQ).s() # needs sage.modules
508
+ sage: s(SM.frobenius_image()) # needs sage.modules
509
+ s[2, 1, 1] + s[2, 2] + 2*s[3, 1] + s[4]
510
+ """
511
+ from sage.combinat.specht_module import SpechtModule
512
+ from sage.combinat.symmetric_group_algebra import SymmetricGroupAlgebra
513
+ if base_ring is None:
514
+ from sage.rings.rational_field import QQ
515
+ base_ring = QQ
516
+ R = SymmetricGroupAlgebra(base_ring, len(self))
517
+ return SpechtModule(R, self)
518
+
519
+ def specht_module_dimension(self, base_ring=None):
520
+ r"""
521
+ Return the dimension of the Specht module corresponding to ``self``.
522
+
523
+ INPUT:
524
+
525
+ - ``base_ring`` -- (default: `\QQ`) the base ring
526
+
527
+ EXAMPLES::
528
+
529
+ sage: from sage.combinat.diagram import Diagram
530
+ sage: D = Diagram([(0,0), (1,1), (2,2), (2,3)])
531
+ sage: D.specht_module_dimension() # needs sage.modules
532
+ 12
533
+ sage: D.specht_module(QQ).dimension() # needs sage.modules
534
+ 12
535
+ """
536
+ from sage.combinat.specht_module import specht_module_rank
537
+ return specht_module_rank(self, base_ring)
538
+
539
+ @cached_method
540
+ def essential_set(self):
541
+ r"""
542
+ Return the essential set of ``self`` as defined by Fulton.
543
+
544
+ Let `D` be a diagram. Then the *essential set* of `D` are the
545
+ cells `(i, j) \in D` such that `(i+1, j) \notin D` and
546
+ `(i, j+1) \notin D`; that is, the maximally southwest elements
547
+ in each connected component of `D`.
548
+
549
+ EXAMPLES::
550
+
551
+ sage: w = Permutation([2, 1, 5, 4, 3])
552
+ sage: D = w.rothe_diagram()
553
+ sage: D.essential_set()
554
+ ((0, 0), (2, 3), (3, 2))
555
+ """
556
+ ret = [c for c in self._cells if (c[0]+1, c[1]) not in self._cells
557
+ and (c[0], c[1]+1) not in self._cells]
558
+ ret.sort()
559
+ return tuple(ret)
560
+
561
+
562
+ class Diagrams(UniqueRepresentation, Parent):
563
+ r"""
564
+ The class of combinatorial diagrams.
565
+
566
+ A *combinatorial diagram* is a set of cells indexed by pairs of natural
567
+ numbers. Calling an instance of :class:`Diagrams` is one way to construct
568
+ diagrams.
569
+
570
+ EXAMPLES::
571
+
572
+ sage: from sage.combinat.diagram import Diagrams
573
+ sage: Dgms = Diagrams()
574
+ sage: D = Dgms([(0,0), (0,3), (2,2), (2,4)])
575
+ sage: D.parent()
576
+ Combinatorial diagrams
577
+ """
578
+
579
+ def __init__(self, category=None):
580
+ r"""
581
+ Initialize ``self``.
582
+
583
+ EXAMPLES::
584
+
585
+ sage: from sage.combinat.diagram import Diagrams
586
+ sage: Dgms = Diagrams(); Dgms
587
+ Combinatorial diagrams
588
+
589
+ TESTS::
590
+
591
+ sage: TestSuite(Dgms).run()
592
+ """
593
+ Parent.__init__(self, category=InfiniteEnumeratedSets().or_subcategory(category))
594
+
595
+ def __iter__(self):
596
+ r"""
597
+ Iterate over ``self``.
598
+
599
+ EXAMPLES::
600
+
601
+ sage: from sage.combinat.diagram import Diagrams
602
+ sage: I = iter(Diagrams())
603
+ sage: for i in range(10):
604
+ ....: print(next(I))
605
+ []
606
+ [(0, 0)]
607
+ [(1, 0)]
608
+ [(0, 0), (1, 0)]
609
+ [(0, 1)]
610
+ [(0, 0), (0, 1)]
611
+ [(0, 1), (1, 0)]
612
+ [(0, 0), (0, 1), (1, 0)]
613
+ [(2, 0)]
614
+ [(0, 0), (2, 0)]
615
+ sage: next(I).parent()
616
+ Combinatorial diagrams
617
+
618
+ sage: from sage.combinat.diagram import NorthwestDiagrams
619
+ sage: I = iter(NorthwestDiagrams())
620
+ sage: for i in range(20):
621
+ ....: print(next(I))
622
+ []
623
+ [(0, 0)]
624
+ [(1, 0)]
625
+ [(0, 0), (1, 0)]
626
+ [(0, 1)]
627
+ [(0, 0), (0, 1)]
628
+ [(0, 0), (0, 1), (1, 0)]
629
+ [(2, 0)]
630
+ [(0, 0), (2, 0)]
631
+ [(1, 0), (2, 0)]
632
+ [(0, 0), (1, 0), (2, 0)]
633
+ [(0, 0), (0, 1), (2, 0)]
634
+ [(0, 0), (0, 1), (1, 0), (2, 0)]
635
+ [(1, 1)]
636
+ [(0, 0), (1, 1)]
637
+ [(1, 0), (1, 1)]
638
+ [(0, 0), (1, 0), (1, 1)]
639
+ [(0, 1), (1, 1)]
640
+ [(0, 0), (0, 1), (1, 1)]
641
+ [(0, 0), (0, 1), (1, 0), (1, 1)]
642
+ """
643
+ from sage.sets.non_negative_integers import NonNegativeIntegers
644
+ from sage.categories.cartesian_product import cartesian_product
645
+ from sage.combinat.subset import subsets
646
+ # the product of positive integers automatically implements an
647
+ # an enumeration which allows us to get out of the first column
648
+ N = NonNegativeIntegers()
649
+ NxN = cartesian_product([N, N])
650
+ X = subsets(NxN)
651
+ while True:
652
+ cells = next(X)
653
+ try:
654
+ yield self.element_class(self, tuple((i, j) for i, j in cells))
655
+ except ValueError:
656
+ # if cells causes the .check method of a
657
+ # subclass to fail, just go to the next one
658
+ pass
659
+
660
+ def _repr_(self):
661
+ r"""
662
+ Return a string representation of ``self``.
663
+
664
+ EXAMPLES::
665
+
666
+ sage: from sage.combinat.diagram import Diagrams
667
+ sage: Dgms = Diagrams(); Dgms
668
+ Combinatorial diagrams
669
+ """
670
+ return 'Combinatorial diagrams'
671
+
672
+ def _element_constructor_(self, cells, n_rows=None, n_cols=None, check=True):
673
+ r"""
674
+ Construct an element of ``self``.
675
+
676
+ EXAMPLES::
677
+
678
+ sage: from sage.combinat.diagram import Diagrams
679
+ sage: Dgms = Diagrams()
680
+ sage: Dgms([(0,1),(2,2)]).pp()
681
+ . O .
682
+ . . .
683
+ . . O
684
+
685
+
686
+ sage: from sage.combinat.tiling import Polyomino # needs sage.modules
687
+ sage: p = Polyomino([(0,0),(1,0),(1,1),(1,2)]) # needs sage.modules
688
+ sage: Dgms(p).pp() # needs sage.modules
689
+ O . .
690
+ O O O
691
+
692
+ sage: from sage.combinat.composition import Composition
693
+ sage: a = Composition([4,2,0,2,4])
694
+ sage: Dgms(a).pp()
695
+ O O O O
696
+ O O . .
697
+ . . . .
698
+ O O . .
699
+ O O O O
700
+
701
+ sage: M = Matrix([[1,1,1,1],[1,1,0,0],[0,0,0,0],[1,1,0,0],[1,1,1,1]]) # needs sage.modules
702
+ sage: Dgms(M).pp() # needs sage.modules
703
+ O O O O
704
+ O O . .
705
+ . . . .
706
+ O O . .
707
+ O O O O
708
+
709
+ TESTS::
710
+
711
+ sage: TestSuite(Dgms).run()
712
+ """
713
+ if isinstance(cells, Polyomino):
714
+ return self.from_polyomino(cells)
715
+ if isinstance(cells, Composition):
716
+ return self.from_composition(cells)
717
+ if isinstance(cells, Matrix):
718
+ return self.from_zero_one_matrix(cells)
719
+
720
+ return self.element_class(self, cells, n_rows, n_cols, check)
721
+
722
+ def _an_element_(self):
723
+ r"""
724
+ Return an element of ``self``.
725
+
726
+ EXAMPLES::
727
+
728
+ sage: from sage.combinat.diagram import Diagrams
729
+ sage: Dgms = Diagrams()
730
+ sage: D = Dgms.an_element(); D
731
+ [(0, 2), (1, 1), (2, 3)]
732
+ sage: D.pp()
733
+ . . O .
734
+ . O . .
735
+ . . . O
736
+ """
737
+ return self([(0, 2), (1, 1), (2, 3)])
738
+
739
+ def from_polyomino(self, p):
740
+ r"""
741
+ Create the diagram corresponding to a 2d
742
+ :class:`~sage.combinat.tiling.Polyomino`
743
+
744
+ EXAMPLES::
745
+
746
+ sage: from sage.combinat.tiling import Polyomino # needs sage.modules
747
+ sage: p = Polyomino([(0,0),(1,0),(1,1),(1,2)]) # needs sage.modules
748
+ sage: from sage.combinat.diagram import Diagrams
749
+ sage: Diagrams()(p).pp() # needs sage.modules
750
+ O . .
751
+ O O O
752
+
753
+ We can also call this method directly::
754
+
755
+ sage: Diagrams().from_polyomino(p).pp() # needs sage.modules
756
+ O . .
757
+ O O O
758
+
759
+ This only works for a 2d :class:`~sage.combinat.tiling.Polyomino`::
760
+
761
+ sage: p = Polyomino([(0,0,0), (0,1,0), (1,1,0), (1,1,1)], color='blue') # needs sage.modules
762
+ sage: Diagrams().from_polyomino(p) # needs sage.modules
763
+ Traceback (most recent call last):
764
+ ...
765
+ ValueError: the polyomino must be 2 dimensional
766
+ """
767
+ if not p._dimension == 2:
768
+ raise ValueError("the polyomino must be 2 dimensional")
769
+ cells = list(map(tuple, p))
770
+ return self.element_class(self, cells)
771
+
772
+ def from_composition(self, alpha):
773
+ r"""
774
+ Create the diagram corresponding to a weak composition `\alpha \vDash n`.
775
+
776
+ EXAMPLES::
777
+
778
+ sage: alpha = Composition([3,0,2,1,4,4])
779
+ sage: from sage.combinat.diagram import Diagrams
780
+ sage: Diagrams()(alpha).pp()
781
+ O O O .
782
+ . . . .
783
+ O O . .
784
+ O . . .
785
+ O O O O
786
+ O O O O
787
+ sage: Diagrams().from_composition(alpha).pp()
788
+ O O O .
789
+ . . . .
790
+ O O . .
791
+ O . . .
792
+ O O O O
793
+ O O O O
794
+ """
795
+ cells = []
796
+ for i, n in enumerate(alpha):
797
+ cells.extend((i, j) for j in range(n))
798
+ return self.element_class(self, cells, check=False)
799
+
800
+ def from_zero_one_matrix(self, M, check=True):
801
+ r"""
802
+ Get a diagram from a matrix with entries in `\{0, 1\}`, where
803
+ positions of cells are indicated by the `1`'s.
804
+
805
+ EXAMPLES::
806
+
807
+ sage: M = matrix([[1,0,1,1],[0,1,1,0]]) # needs sage.modules
808
+ sage: from sage.combinat.diagram import Diagrams
809
+ sage: Diagrams()(M).pp() # needs sage.modules
810
+ O . O O
811
+ . O O .
812
+ sage: Diagrams().from_zero_one_matrix(M).pp() # needs sage.modules
813
+ O . O O
814
+ . O O .
815
+
816
+ sage: M = matrix([[1, 0, 0], [1, 0, 0], [0, 0, 0]]) # needs sage.modules
817
+ sage: Diagrams()(M).pp() # needs sage.modules
818
+ O . .
819
+ O . .
820
+ . . .
821
+ """
822
+ # check matrix is zero-one
823
+ n_rows, n_cols = M.dimensions()
824
+
825
+ if check:
826
+ zero = M.base_ring().zero()
827
+ one = M.base_ring().one()
828
+ for i in range(n_rows):
829
+ for j in range(n_cols):
830
+ if not (M[i, j] == zero or M[i, j] == one):
831
+ raise ValueError("matrix entries must be 0 or 1")
832
+ cells = [(i, j) for i in range(n_rows) for j in range(n_cols) if M[i, j]]
833
+
834
+ return self.element_class(self, cells, n_rows, n_cols, check=False)
835
+
836
+ Element = Diagram
837
+
838
+
839
+ ####################
840
+ # Northwest diagrams
841
+ ####################
842
+
843
+ class NorthwestDiagram(Diagram, metaclass=InheritComparisonClasscallMetaclass):
844
+ r"""
845
+ Diagrams with the northwest property.
846
+
847
+ A diagram is a set of cells indexed by natural numbers. Such a diagram
848
+ has the *northwest property* if the presence of cells `(i1, j1)` and
849
+ `(i2, j2)` implies the presence of the cell
850
+ `(\min(i1, i2), \min(j1, j2))`. Diagrams with the northwest property are
851
+ called *northwest diagrams*.
852
+
853
+ For general diagrams see :class:`Diagram`.
854
+
855
+ EXAMPLES::
856
+
857
+ sage: from sage.combinat.diagram import NorthwestDiagram
858
+ sage: N = NorthwestDiagram([(0,0), (0, 2), (2,0)])
859
+
860
+ To visualize them, use the ``.pp()`` method::
861
+
862
+ sage: N.pp()
863
+ O . O
864
+ . . .
865
+ O . .
866
+ """
867
+ @staticmethod
868
+ def __classcall_private__(self, cells, n_rows=None, n_cols=None, check=True):
869
+ """
870
+ Normalize input to ensure a correct parent. This method also allows
871
+ one to specify whether or not to check the northwest property for the
872
+ provided cells.
873
+
874
+ EXAMPLES::
875
+
876
+ sage: from sage.combinat.diagram import NorthwestDiagram, NorthwestDiagrams
877
+ sage: N1 = NorthwestDiagram([(0,1), (0,2)])
878
+ sage: N2 = NorthwestDiagram([(0,1), (0,3)])
879
+ sage: N1.parent() is N2.parent()
880
+ True
881
+ sage: N3 = NorthwestDiagrams()([(0,1), (0,2)])
882
+ sage: N3.parent() is NorthwestDiagrams()
883
+ True
884
+ sage: N1.parent() is NorthwestDiagrams()
885
+ True
886
+ """
887
+ return NorthwestDiagrams()(cells, n_rows, n_cols, check)
888
+
889
+ def check(self):
890
+ r"""
891
+ A diagram has the northwest property if the presence of cells
892
+ `(i1, j1)` and `(i2, j2)` implies the presence of the cell
893
+ `(min(i1, i2), min(j1, j2))`. This method checks if the northwest
894
+ property is satisfied for ``self``
895
+
896
+ EXAMPLES::
897
+
898
+ sage: from sage.combinat.diagram import NorthwestDiagram
899
+ sage: N = NorthwestDiagram([(0,0), (0,3), (3,0)])
900
+ sage: N.check()
901
+
902
+ Here is a non-example::
903
+
904
+ sage: notN = NorthwestDiagram([(0,1), (1,0)]) #.check() is implicit
905
+ Traceback (most recent call last):
906
+ ...
907
+ ValueError: diagram is not northwest
908
+
909
+ TESTS::
910
+
911
+ sage: NorthwestDiagram([(0,1/2)])
912
+ Traceback (most recent call last):
913
+ ...
914
+ ValueError: diagrams must be indexed by nonnegative integers
915
+ """
916
+ from itertools import combinations
917
+ Diagram.check(self)
918
+ if not all((min(i1, i2), min(j1, j2)) in self
919
+ for (i1, j1), (i2, j2) in combinations(self._cells, 2)):
920
+ raise ValueError("diagram is not northwest")
921
+
922
+ def peelable_tableaux(self):
923
+ r"""
924
+ Return the set of peelable tableaux whose diagram is ``self``.
925
+
926
+ For a fixed northwest diagram `D`, we say that a Young tableau `T` is
927
+ `D`-peelable if:
928
+
929
+ 1. the row indices of the cells in the first column of `D` are
930
+ the entries in an initial segment in the first column of `T` and
931
+ 2. the tableau `Q` obtained by removing those cells from `T` and playing
932
+ jeu de taquin is `(D-C)`-peelable, where `D-C` is the diagram formed
933
+ by forgetting the first column of `D`.
934
+
935
+ Reiner and Shimozono [RS1995]_ showed that the number
936
+ `\operatorname{red}(w)` of reduced words of a permutation `w` may be
937
+ computed using the peelable tableaux of the Rothe diagram `D(w)`.
938
+ Explicitly,
939
+
940
+ .. MATH::
941
+
942
+ \operatorname{red}(w) = \sum_{T} f_{\operatorname{shape} T},
943
+
944
+ where the sum runs over the `D(w)`-peelable tableaux `T` and `f_\lambda`
945
+ is the number of standard Young tableaux of shape `\lambda` (which may
946
+ be computed using the hook-length formula).
947
+
948
+ EXAMPLES:
949
+
950
+ We can compute the `D`-peelable diagrams for a northwest diagram `D`::
951
+
952
+ sage: from sage.combinat.diagram import NorthwestDiagram
953
+ sage: cells = [(0,0), (0,1), (0,2), (1,0), (2,0), (2,2), (2,4),
954
+ ....: (4,0), (4,2)]
955
+ sage: D = NorthwestDiagram(cells); D.pp()
956
+ O O O . .
957
+ O . . . .
958
+ O . O . O
959
+ . . . . .
960
+ O . O . .
961
+ sage: D.peelable_tableaux()
962
+ {[[1, 1, 1], [2, 3, 3], [3, 5], [5]],
963
+ [[1, 1, 1, 3], [2, 3], [3, 5], [5]]}
964
+
965
+ EXAMPLES:
966
+
967
+ If the diagram is only one column, there is only one peelable tableau::
968
+
969
+ sage: from sage.combinat.diagram import NorthwestDiagram
970
+ sage: NWD = NorthwestDiagram([(0,0), (2,0)])
971
+ sage: NWD.peelable_tableaux()
972
+ {[[1], [3]]}
973
+
974
+ From [RS1995]_, we know that there is only one peelable tableau for the
975
+ Rothe diagram of the permutation (in one line notation) `251643`::
976
+
977
+ sage: D = NorthwestDiagram([(1, 2), (1, 3), (3, 2), (3, 3), (4, 2)])
978
+ sage: D.pp()
979
+ . . . .
980
+ . . O O
981
+ . . . .
982
+ . . O O
983
+ . . O .
984
+
985
+ sage: D.peelable_tableaux()
986
+ {[[2, 2], [4, 4], [5]]}
987
+
988
+ Here are all the intermediate steps to compute the peelables for the
989
+ Rothe diagram of (in one-line notation) `64817235`. They are listed from
990
+ deepest in the recursion to the final step. The recursion has depth five
991
+ in this case so we will label the intermediate tableaux by `D_i` where
992
+ `i` is the step in the recursion at which they appear.
993
+
994
+ Start with the one that has a single column::
995
+
996
+ sage: D5 = NorthwestDiagram([(2,0)]); D5.pp()
997
+ .
998
+ .
999
+ O
1000
+ sage: D5.peelable_tableaux()
1001
+ {[[3]]}
1002
+
1003
+ Now we know all of the `D_5` peelables, so we can compute the `D_4`
1004
+ peelables::
1005
+
1006
+ sage: D4 = NorthwestDiagram([(0, 0), (2,0), (4, 0), (2, 2)])
1007
+ sage: D4.pp()
1008
+ O . .
1009
+ . . .
1010
+ O . O
1011
+ . . .
1012
+ O . .
1013
+
1014
+ sage: D4.peelable_tableaux()
1015
+ {[[1, 3], [3], [5]]}
1016
+
1017
+ There is only one `D_4` peelable, so we can compute the `D_3`
1018
+ peelables::
1019
+
1020
+ sage: D3 = NorthwestDiagram([(0,0), (0,1), (2, 1), (2, 3), (4,1)])
1021
+ sage: D3.pp()
1022
+ O O . .
1023
+ . . . .
1024
+ . O . O
1025
+ . . . .
1026
+ . O . .
1027
+
1028
+ sage: D3.peelable_tableaux()
1029
+ {[[1, 1], [3, 3], [5]], [[1, 1, 3], [3], [5]]}
1030
+
1031
+ Now compute the `D_2` peelables::
1032
+
1033
+ sage: cells = [(0,0), (0,1), (0,2), (1,0), (2,0), (2,2), (2,4),
1034
+ ....: (4,0), (4,2)]
1035
+ sage: D2 = NorthwestDiagram(cells); D2.pp()
1036
+ O O O . .
1037
+ O . . . .
1038
+ O . O . O
1039
+ . . . . .
1040
+ O . O . .
1041
+
1042
+ sage: D2.peelable_tableaux()
1043
+ {[[1, 1, 1], [2, 3, 3], [3, 5], [5]],
1044
+ [[1, 1, 1, 3], [2, 3], [3, 5], [5]]}
1045
+
1046
+ And the `D_1` peelables::
1047
+
1048
+ sage: cells = [(0,0), (0,1), (0,2), (0,3), (1,0), (1,1), (2,0),
1049
+ ....: (2,1), (2,3), (2,5), (4,0), (4,1), (4,3)]
1050
+ sage: D1 = NorthwestDiagram(cells); D1.pp()
1051
+ O O O O . .
1052
+ O O . . . .
1053
+ O O . O . O
1054
+ . . . . . .
1055
+ O O . O . .
1056
+
1057
+ sage: D1.peelable_tableaux()
1058
+ {[[1, 1, 1, 1], [2, 2, 3, 3], [3, 3, 5], [5, 5]],
1059
+ [[1, 1, 1, 1, 3], [2, 2, 3], [3, 3, 5], [5, 5]]}
1060
+
1061
+ Which we can use to get the `D` peelables::
1062
+
1063
+ sage: cells = [(0,0), (0,1), (0,2), (0,3), (0,4),
1064
+ ....: (1,0), (1,1), (1,2),
1065
+ ....: (2,0), (2,1), (2,2), (2,4), (2,6),
1066
+ ....: (4,1), (4,2), (4,4)]
1067
+ sage: D = NorthwestDiagram(cells); D.pp()
1068
+ O O O O O . .
1069
+ O O O . . . .
1070
+ O O O . O . O
1071
+ . . . . . . .
1072
+ . O O . O . .
1073
+ sage: D.peelable_tableaux()
1074
+ {[[1, 1, 1, 1, 1], [2, 2, 2, 3, 3], [3, 3, 3], [5, 5, 5]],
1075
+ [[1, 1, 1, 1, 1], [2, 2, 2, 3, 3], [3, 3, 3, 5], [5, 5]],
1076
+ [[1, 1, 1, 1, 1, 3], [2, 2, 2, 3], [3, 3, 3], [5, 5, 5]],
1077
+ [[1, 1, 1, 1, 1, 3], [2, 2, 2, 3], [3, 3, 3, 5], [5, 5]]}
1078
+
1079
+ ALGORITHM:
1080
+
1081
+ This implementation uses the algorithm suggested in Remark 25
1082
+ of [RS1995]_.
1083
+
1084
+ TESTS:
1085
+
1086
+ Corner case::
1087
+
1088
+ sage: from sage.combinat.diagram import NorthwestDiagram
1089
+ sage: D = NorthwestDiagram([])
1090
+ sage: D.peelable_tableaux()
1091
+ {[]}
1092
+ """
1093
+ # TODO: There is a condition on the first column (if the rows in Dhat
1094
+ # are a subset of the rows in the first column) which simplifies the
1095
+ # description without performing JDT, so we should implement that
1096
+
1097
+ # empty diagram case
1098
+ if not self:
1099
+ return set([Tableau([])])
1100
+
1101
+ # if there is a single column in the diagram then there is only
1102
+ # one posslbe peelable tableau.
1103
+ if self._n_nonempty_cols == 1:
1104
+ return set([Tableau([[i+1] for i, j in self.cells()])])
1105
+
1106
+ first_col = min(j for i, j in self._cells)
1107
+
1108
+ dhat_cells = []
1109
+ new_vals_cells = []
1110
+ for i, j in self._cells:
1111
+ if j != first_col:
1112
+ dhat_cells.append((i, j))
1113
+ else:
1114
+ new_vals_cells.append(i + 1)
1115
+
1116
+ new_vals = sorted(new_vals_cells)
1117
+
1118
+ Dhat = NorthwestDiagram(dhat_cells)
1119
+ k = self.n_cells() - Dhat.n_cells()
1120
+
1121
+ peelables = set()
1122
+
1123
+ for Q in Dhat.peelable_tableaux():
1124
+ # get the vertical strips
1125
+ mu = Q.shape()
1126
+ vertical_strip_cells = mu.vertical_border_strip_cells(k)
1127
+ for s in vertical_strip_cells:
1128
+ sQ = SkewTableaux()(Q) # sQ is skew - get it?
1129
+ # perform the jeu de taquin slides
1130
+ for c in s:
1131
+ sQ = sQ.backward_slide(c)
1132
+ # create the new tableau by filling the columns
1133
+ sQ_new = sQ.to_list()
1134
+ for n in range(k):
1135
+ sQ_new[n][0] = new_vals[n]
1136
+
1137
+ T = Tableau(sQ_new)
1138
+ if T.is_column_strict():
1139
+ peelables.add(T)
1140
+
1141
+ return peelables
1142
+
1143
+
1144
+ class NorthwestDiagrams(Diagrams):
1145
+ r"""
1146
+ Diagrams satisfying the northwest property.
1147
+
1148
+ A diagram `D` is a *northwest diagram* if for every two cells `(i_1, j_1)`
1149
+ and `(i_2, j_2)` in `D` then there exists the cell
1150
+ `(\min(i_1, i_2), \min(j_1, j_2)) \in D`.
1151
+
1152
+ EXAMPLES::
1153
+
1154
+ sage: from sage.combinat.diagram import NorthwestDiagram
1155
+ sage: N = NorthwestDiagram([(0,0), (0, 10), (5,0)]); N.pp()
1156
+ O . . . . . . . . . O
1157
+ . . . . . . . . . . .
1158
+ . . . . . . . . . . .
1159
+ . . . . . . . . . . .
1160
+ . . . . . . . . . . .
1161
+ O . . . . . . . . . .
1162
+
1163
+ Note that checking whether or not the northwest property is satisfied is
1164
+ automatically checked. The diagram found by adding the cell `(1,1)` to the
1165
+ diagram above is *not* a northwest diagram. The cell `(1,0)` should be
1166
+ present due to the presence of `(5,0)` and `(1,1)`::
1167
+
1168
+ sage: from sage.combinat.diagram import Diagram
1169
+ sage: Diagram([(0, 0), (0, 10), (5, 0), (1, 1)]).pp()
1170
+ O . . . . . . . . . O
1171
+ . O . . . . . . . . .
1172
+ . . . . . . . . . . .
1173
+ . . . . . . . . . . .
1174
+ . . . . . . . . . . .
1175
+ O . . . . . . . . . .
1176
+ sage: NorthwestDiagram([(0, 0), (0, 10), (5, 0), (1, 1)])
1177
+ Traceback (most recent call last):
1178
+ ...
1179
+ ValueError: diagram is not northwest
1180
+
1181
+ However, this behavior can be turned off if you are confident that
1182
+ you are providing a northwest diagram::
1183
+
1184
+ sage: N = NorthwestDiagram([(0, 0), (0, 10), (5, 0),
1185
+ ....: (1, 1), (0, 1), (1, 0)],
1186
+ ....: check=False)
1187
+ sage: N.pp()
1188
+ O O . . . . . . . . O
1189
+ O O . . . . . . . . .
1190
+ . . . . . . . . . . .
1191
+ . . . . . . . . . . .
1192
+ . . . . . . . . . . .
1193
+ O . . . . . . . . . .
1194
+
1195
+ Note that arbitrary diagrams which happen to be northwest diagrams
1196
+ only live in the parent of :class:`Diagrams`::
1197
+
1198
+ sage: D = Diagram([(0, 0), (0, 10), (5, 0), (1, 1), (0, 1), (1, 0)])
1199
+ sage: D.pp()
1200
+ O O . . . . . . . . O
1201
+ O O . . . . . . . . .
1202
+ . . . . . . . . . . .
1203
+ . . . . . . . . . . .
1204
+ . . . . . . . . . . .
1205
+ O . . . . . . . . . .
1206
+ sage: from sage.combinat.diagram import NorthwestDiagrams
1207
+ sage: D in NorthwestDiagrams()
1208
+ False
1209
+
1210
+ Here are some more examples::
1211
+
1212
+ sage: from sage.combinat.diagram import NorthwestDiagram, NorthwestDiagrams
1213
+ sage: D = NorthwestDiagram([(0,1), (0,2), (1,1)]); D.pp()
1214
+ . O O
1215
+ . O .
1216
+ sage: NWDgms = NorthwestDiagrams()
1217
+ sage: D = NWDgms([(1,1), (1,2), (2,1)]); D.pp()
1218
+ . . .
1219
+ . O O
1220
+ . O .
1221
+ sage: D.parent()
1222
+ Combinatorial northwest diagrams
1223
+
1224
+ Additionally, there are natural constructions of a northwest diagram
1225
+ given the data of a permutation (Rothe diagrams are the prototypical example
1226
+ of northwest diagrams), or the data of a partition of an integer, or a
1227
+ skew partition.
1228
+
1229
+ The Rothe diagram `D(\omega)` of a permutation `\omega` is specified by
1230
+ the cells
1231
+
1232
+ .. MATH::
1233
+
1234
+ D(\omega) = \{(\omega_j, i) : i<j,\, \omega_i > \omega_j \}.
1235
+
1236
+ We can construct one by calling :meth:`rothe_diagram` method on the set
1237
+ of all :class:`~sage.combinat.diagram.NorthwestDiagrams`::
1238
+
1239
+ sage: w = Permutations(4)([4,3,2,1])
1240
+ sage: NorthwestDiagrams().rothe_diagram(w).pp()
1241
+ O O O .
1242
+ O O . .
1243
+ O . . .
1244
+ . . . .
1245
+
1246
+ To turn a Ferrers diagram into a northwest diagram, we may call
1247
+ :meth:`from_partition`. This will return a Ferrer's diagram in the
1248
+ set of all northwest diagrams. For many use-cases it is probably better
1249
+ to get Ferrer's diagrams by the corresponding method on partitions, namely
1250
+ :meth:`sage.combinat.partitions.Partitions.ferrers_diagram`::
1251
+
1252
+ sage: mu = Partition([7,3,1,1])
1253
+ sage: mu.pp()
1254
+ *******
1255
+ ***
1256
+ *
1257
+ *
1258
+ sage: NorthwestDiagrams().from_partition(mu).pp()
1259
+ O O O O O O O
1260
+ O O O . . . .
1261
+ O . . . . . .
1262
+ O . . . . . .
1263
+
1264
+ It is also possible to turn a Ferrers diagram of a skew partition into a
1265
+ northwest diagram, although it is more subtle than just using the skew
1266
+ diagram itself. One must first reflect the partition about a vertical axis
1267
+ so that the skew partition looks "backwards"::
1268
+
1269
+ sage: mu, nu = Partition([5,4,3,2,1]), Partition([3,2,1])
1270
+ sage: s = mu/nu; s.pp()
1271
+ **
1272
+ **
1273
+ **
1274
+ **
1275
+ *
1276
+ sage: NorthwestDiagrams().from_skew_partition(s).pp()
1277
+ O O . . .
1278
+ . O O . .
1279
+ . . O O .
1280
+ . . . O O
1281
+ . . . . O
1282
+ """
1283
+
1284
+ def _repr_(self):
1285
+ r"""
1286
+ Return a string representation of ``self``.
1287
+
1288
+ EXAMPLES::
1289
+
1290
+ sage: from sage.combinat.diagram import NorthwestDiagrams
1291
+ sage: NWDgms = NorthwestDiagrams(); NWDgms
1292
+ Combinatorial northwest diagrams
1293
+ """
1294
+ return 'Combinatorial northwest diagrams'
1295
+
1296
+ def _an_element_(self):
1297
+ r"""
1298
+ Return an element of ``self``.
1299
+
1300
+ EXAMPLES::
1301
+
1302
+ sage: from sage.combinat.diagram import NorthwestDiagrams
1303
+ sage: NWDgms = NorthwestDiagrams()
1304
+ sage: NWD = NWDgms.an_element(); NWD
1305
+ [(0, 1), (0, 2), (1, 1), (2, 3)]
1306
+ sage: NWD.pp()
1307
+ . O O .
1308
+ . O . .
1309
+ . . . O
1310
+ sage: NWD.parent() is NWDgms
1311
+ True
1312
+ """
1313
+ return self([(0, 1), (0, 2), (1, 1), (2, 3)])
1314
+
1315
+ def rothe_diagram(self, w):
1316
+ r"""
1317
+ Return the Rothe diagram of ``w``.
1318
+
1319
+ We construct a northwest diagram from a permutation by
1320
+ constructing its Rothe diagram. Formally, if `\omega` is
1321
+ a :class:`~sage.combinat.permutation.Permutation`
1322
+ then the Rothe diagram `D(\omega)` is the diagram whose cells are
1323
+
1324
+ .. MATH::
1325
+
1326
+ D(\omega) = \{(\omega_j, i) : i<j,\, \omega_i > \omega_j \}.
1327
+
1328
+ Informally, one can construct the Rothe diagram by starting with all
1329
+ `n^2` possible cells, and then deleting the cells `(i, \omega(i))` as
1330
+ well as all cells to the right and below. (These are sometimes called
1331
+ "death rays".)
1332
+
1333
+ .. SEEALSO::
1334
+
1335
+ :func:`~sage.combinat.diagram.RotheDiagram`
1336
+
1337
+ EXAMPLES::
1338
+
1339
+ sage: from sage.combinat.diagram import NorthwestDiagrams
1340
+ sage: w = Permutations(3)([2,1,3])
1341
+ sage: NorthwestDiagrams().rothe_diagram(w).pp()
1342
+ O . .
1343
+ . . .
1344
+ . . .
1345
+ sage: NorthwestDiagrams().from_permutation(w).pp()
1346
+ O . .
1347
+ . . .
1348
+ . . .
1349
+
1350
+ sage: w = Permutations(8)([2,5,4,1,3,6,7,8])
1351
+ sage: NorthwestDiagrams().rothe_diagram(w).pp()
1352
+ O . . . . . . .
1353
+ O . O O . . . .
1354
+ O . O . . . . .
1355
+ . . . . . . . .
1356
+ . . . . . . . .
1357
+ . . . . . . . .
1358
+ . . . . . . . .
1359
+ . . . . . . . .
1360
+ """
1361
+ return RotheDiagram(w)
1362
+
1363
+ from_permutation = rothe_diagram
1364
+
1365
+ def from_partition(self, mu):
1366
+ r"""
1367
+ Return the Ferrer's diagram of ``mu`` as a northwest diagram.
1368
+
1369
+ EXAMPLES::
1370
+
1371
+ sage: mu = Partition([5,2,1]); mu.pp()
1372
+ *****
1373
+ **
1374
+ *
1375
+ sage: mu.parent()
1376
+ Partitions
1377
+ sage: from sage.combinat.diagram import NorthwestDiagrams
1378
+ sage: D = NorthwestDiagrams().from_partition(mu)
1379
+ sage: D.pp()
1380
+ O O O O O
1381
+ O O . . .
1382
+ O . . . .
1383
+ sage: D.parent()
1384
+ Combinatorial northwest diagrams
1385
+
1386
+ This will print in English notation even if the notation is set to
1387
+ French for the partition::
1388
+
1389
+ sage: Partitions.options.convention="french"
1390
+ sage: mu.pp()
1391
+ *
1392
+ **
1393
+ *****
1394
+ sage: D.pp()
1395
+ O O O O O
1396
+ O O . . .
1397
+ O . . . .
1398
+
1399
+ TESTS::
1400
+
1401
+ sage: from sage.combinat.diagram import NorthwestDiagrams
1402
+ sage: mu = [5, 2, 1]
1403
+ sage: D = NorthwestDiagrams().from_partition(mu)
1404
+ Traceback (most recent call last):
1405
+ ...
1406
+ ValueError: mu must be a Partition
1407
+ """
1408
+ if not isinstance(mu, Partition):
1409
+ raise ValueError("mu must be a Partition")
1410
+ return self.element_class(self, mu.cells(), check=False)
1411
+
1412
+ def from_skew_partition(self, s):
1413
+ r"""
1414
+ Get the northwest diagram found by reflecting a skew shape across
1415
+ a vertical plane.
1416
+
1417
+ EXAMPLES::
1418
+
1419
+ sage: mu, nu = Partition([3,2,1]), Partition([2,1])
1420
+ sage: s = mu/nu; s.pp()
1421
+ *
1422
+ *
1423
+ *
1424
+ sage: from sage.combinat.diagram import NorthwestDiagrams
1425
+ sage: D = NorthwestDiagrams().from_skew_partition(s)
1426
+ sage: D.pp()
1427
+ O . .
1428
+ . O .
1429
+ . . O
1430
+
1431
+ sage: mu, nu = Partition([3,3,2]), Partition([2,2,2])
1432
+ sage: s = mu/nu; s.pp()
1433
+ *
1434
+ *
1435
+ sage: NorthwestDiagrams().from_skew_partition(s).pp()
1436
+ O . .
1437
+ O . .
1438
+ . . .
1439
+
1440
+ TESTS::
1441
+
1442
+ sage: mu = Partition([3,2,1])
1443
+ sage: NorthwestDiagrams().from_skew_partition(mu)
1444
+ Traceback (most recent call last):
1445
+ ...
1446
+ ValueError: mu must be a SkewPartition
1447
+ """
1448
+ if not isinstance(s, SkewPartition):
1449
+ raise ValueError("mu must be a SkewPartition")
1450
+
1451
+ n_cols = s.outer()[0]
1452
+ n_rows = len(s.outer())
1453
+
1454
+ cells = [(i, n_cols - 1 - j) for i, j in s.cells()]
1455
+
1456
+ return self.element_class(self, cells, n_rows, n_cols, check=False)
1457
+
1458
+ def from_parallelogram_polyomino(self, p):
1459
+ r"""
1460
+ Create the diagram corresponding to a
1461
+ :class:`~sage.combinat.parallelogram_polyomino.ParallelogramPolyomino`.
1462
+
1463
+ EXAMPLES::
1464
+
1465
+ sage: p = ParallelogramPolyomino([[0, 0, 1, 0, 0, 0, 1, 1], # needs sage.modules
1466
+ ....: [1, 1, 0, 1, 0, 0, 0, 0]])
1467
+ sage: from sage.combinat.diagram import NorthwestDiagrams
1468
+ sage: NorthwestDiagrams().from_parallelogram_polyomino(p).pp() # needs sage.modules
1469
+ O O .
1470
+ O O O
1471
+ . O O
1472
+ . O O
1473
+ . O O
1474
+ """
1475
+ from sage.matrix.constructor import Matrix
1476
+ M = Matrix(p.get_array())
1477
+ return self.from_zero_one_matrix(M)
1478
+
1479
+ Element = NorthwestDiagram
1480
+
1481
+
1482
+ def RotheDiagram(w):
1483
+ r"""
1484
+ The Rothe diagram of a permutation ``w``.
1485
+
1486
+ EXAMPLES::
1487
+
1488
+ sage: w = Permutations(9)([1, 7, 4, 5, 9, 3, 2, 8, 6])
1489
+ sage: from sage.combinat.diagram import RotheDiagram
1490
+ sage: D = RotheDiagram(w); D.pp()
1491
+ . . . . . . . . .
1492
+ . O O O O O . . .
1493
+ . O O . . . . . .
1494
+ . O O . . . . . .
1495
+ . O O . . O . O .
1496
+ . O . . . . . . .
1497
+ . . . . . . . . .
1498
+ . . . . . O . . .
1499
+ . . . . . . . . .
1500
+
1501
+ The Rothe diagram is a northwest diagram::
1502
+
1503
+ sage: D.parent()
1504
+ Combinatorial northwest diagrams
1505
+
1506
+ Some other examples::
1507
+
1508
+ sage: RotheDiagram([2, 1, 4, 3]).pp()
1509
+ O . . .
1510
+ . . . .
1511
+ . . O .
1512
+ . . . .
1513
+
1514
+ sage: RotheDiagram([4, 1, 3, 2]).pp()
1515
+ O O O .
1516
+ . . . .
1517
+ . O . .
1518
+ . . . .
1519
+
1520
+ Currently, only elements of the set of
1521
+ :class:`sage.combinat.permutations.Permutations` are supported. In
1522
+ particular, elements of permutation groups are not supported::
1523
+
1524
+ sage: w = SymmetricGroup(9).an_element() # needs sage.groups
1525
+ sage: RotheDiagram(w) # needs sage.groups
1526
+ Traceback (most recent call last):
1527
+ ...
1528
+ ValueError: w must be a permutation
1529
+
1530
+ TESTS::
1531
+
1532
+ sage: w = Permutations(5)([1,2,3,4,5])
1533
+ sage: from sage.combinat.diagram import RotheDiagram
1534
+ sage: RotheDiagram(w).pp()
1535
+ . . . . .
1536
+ . . . . .
1537
+ . . . . .
1538
+ . . . . .
1539
+ . . . . .
1540
+ """
1541
+ P = Permutations()
1542
+ if w not in P:
1543
+ raise ValueError('w must be a permutation')
1544
+ w = P(w)
1545
+
1546
+ N = w.size()
1547
+ winv = w.inverse()
1548
+ cells = [c for c in product(range(N), range(N))
1549
+ if c[0] + 1 < winv(c[1] + 1) and c[1] + 1 < w(c[0] + 1)]
1550
+
1551
+ return NorthwestDiagram(cells, n_rows=N, n_cols=N, check=False)