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,2053 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ r"""
3
+ Skew partitions
4
+
5
+ A skew partition ``skp`` of size `n` is a pair of
6
+ partitions `[p_1, p_2]` where `p_1` is a
7
+ partition of the integer `n_1`, `p_2` is a
8
+ partition of the integer `n_2`, `p_2` is an inner
9
+ partition of `p_1`, and `n = n_1 - n_2`. We say
10
+ that `p_1` and `p_2` are respectively the *inner*
11
+ and *outer* partitions of ``skp``.
12
+
13
+ A skew partition can be depicted by a diagram made of rows of
14
+ cells, in the same way as a partition. Only the cells of the outer
15
+ partition `p_1` which are not in the inner partition
16
+ `p_2` appear in the picture. For example, this is the
17
+ diagram of the skew partition [[5,4,3,1],[3,3,1]].
18
+
19
+ ::
20
+
21
+ sage: print(SkewPartition([[5,4,3,1],[3,3,1]]).diagram())
22
+ **
23
+ *
24
+ **
25
+ *
26
+
27
+ A skew partition can be *connected*, which can easily be described
28
+ in graphic terms: for each pair of consecutive rows, there are at
29
+ least two cells (one in each row) which have a common edge. This is
30
+ the diagram of the connected skew partition ``[[5,4,3,1],[3,1]]``::
31
+
32
+ sage: print(SkewPartition([[5,4,3,1],[3,1]]).diagram())
33
+ **
34
+ ***
35
+ ***
36
+ *
37
+ sage: SkewPartition([[5,4,3,1],[3,1]]).is_connected()
38
+ True
39
+
40
+ The first example of a skew partition is not a connected one.
41
+
42
+ Applying a reflection with respect to the main diagonal yields the
43
+ diagram of the *conjugate skew partition*, here
44
+ ``[[4,3,3,2,1],[3,3,2]]``::
45
+
46
+ sage: SkewPartition([[5,4,3,1],[3,3,1]]).conjugate()
47
+ [4, 3, 3, 2, 1] / [3, 2, 2]
48
+ sage: print(SkewPartition([[5,4,3,1],[3,3,1]]).conjugate().diagram())
49
+ *
50
+ *
51
+ *
52
+ **
53
+ *
54
+
55
+ The *outer corners* of a skew partition are the corners of its
56
+ outer partition. The *inner corners* are the internal corners of
57
+ the outer partition when the inner partition is taken off. Shown
58
+ below are the coordinates of the inner and outer corners.
59
+
60
+ ::
61
+
62
+ sage: SkewPartition([[5,4,3,1],[3,3,1]]).outer_corners()
63
+ [(0, 4), (1, 3), (2, 2), (3, 0)]
64
+ sage: SkewPartition([[5,4,3,1],[3,3,1]]).inner_corners()
65
+ [(0, 3), (2, 1), (3, 0)]
66
+
67
+ EXAMPLES:
68
+
69
+ There are 9 skew partitions of size 3, with no empty row nor empty
70
+ column::
71
+
72
+ sage: SkewPartitions(3).cardinality()
73
+ 9
74
+ sage: SkewPartitions(3).list()
75
+ [[3] / [],
76
+ [2, 1] / [],
77
+ [3, 1] / [1],
78
+ [2, 2] / [1],
79
+ [3, 2] / [2],
80
+ [1, 1, 1] / [],
81
+ [2, 2, 1] / [1, 1],
82
+ [2, 1, 1] / [1],
83
+ [3, 2, 1] / [2, 1]]
84
+
85
+ There are 4 connected skew partitions of size 3::
86
+
87
+ sage: SkewPartitions(3, overlap=1).cardinality()
88
+ 4
89
+ sage: SkewPartitions(3, overlap=1).list()
90
+ [[3] / [], [2, 1] / [], [2, 2] / [1], [1, 1, 1] / []]
91
+
92
+ This is the conjugate of the skew partition ``[[4,3,1], [2]]``
93
+
94
+ ::
95
+
96
+ sage: SkewPartition([[4,3,1], [2]]).conjugate()
97
+ [3, 2, 2, 1] / [1, 1]
98
+
99
+ Geometrically, we just applied a reflection with respect to the main
100
+ diagonal on the diagram of the partition. Of course, this operation
101
+ is an involution::
102
+
103
+ sage: SkewPartition([[4,3,1],[2]]).conjugate().conjugate()
104
+ [4, 3, 1] / [2]
105
+
106
+ The :meth:`jacobi_trudi()` method computes the Jacobi-Trudi matrix. See
107
+ [Mac1995]_ for a definition and discussion.
108
+
109
+ ::
110
+
111
+ sage: SkewPartition([[4,3,1],[2]]).jacobi_trudi() # needs sage.modules
112
+ [h[2] h[] 0]
113
+ [h[5] h[3] h[]]
114
+ [h[6] h[4] h[1]]
115
+
116
+ This example shows how to compute the corners of a skew partition.
117
+
118
+ ::
119
+
120
+ sage: SkewPartition([[4,3,1],[2]]).inner_corners()
121
+ [(0, 2), (1, 0)]
122
+ sage: SkewPartition([[4,3,1],[2]]).outer_corners()
123
+ [(0, 3), (1, 2), (2, 0)]
124
+
125
+ AUTHORS:
126
+
127
+ - Mike Hansen: Initial version
128
+ - Travis Scrimshaw (2013-02-11): Factored out ``CombinatorialClass``
129
+ - Trevor K. Karn (2022-08-03): Add ``outside_corners``
130
+ """
131
+ #*****************************************************************************
132
+ # Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,
133
+ #
134
+ # Distributed under the terms of the GNU General Public License (GPL)
135
+ #
136
+ # This code is distributed in the hope that it will be useful,
137
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
138
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
139
+ # General Public License for more details.
140
+ #
141
+ # The full text of the GPL is available at:
142
+ #
143
+ # http://www.gnu.org/licenses/
144
+ #*****************************************************************************
145
+
146
+ from sage.structure.global_options import GlobalOptions
147
+ from sage.structure.parent import Parent
148
+ from sage.structure.unique_representation import UniqueRepresentation
149
+ from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
150
+ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
151
+
152
+ from sage.rings.integer_ring import ZZ
153
+ from sage.rings.rational_field import QQ
154
+ from sage.sets.set import Set
155
+ from sage.misc.lazy_import import lazy_import
156
+
157
+ from sage.combinat.combinat import CombinatorialElement
158
+ from sage.combinat.partition import Partitions, _Partitions
159
+ from sage.combinat.tableau import Tableaux
160
+ from sage.combinat.composition import Compositions
161
+
162
+ lazy_import('sage.graphs.digraph', 'DiGraph')
163
+ lazy_import('sage.matrix.matrix_space', 'MatrixSpace')
164
+
165
+
166
+ class SkewPartition(CombinatorialElement):
167
+ r"""
168
+ A skew partition.
169
+
170
+ A skew partition of shape `\lambda / \mu` is the Young diagram from the
171
+ partition `\lambda` and removing the partition `\mu` from the upper-left
172
+ corner in English convention.
173
+ """
174
+ @staticmethod
175
+ def __classcall_private__(cls, skp):
176
+ """
177
+ Return the skew partition object corresponding to ``skp``.
178
+
179
+ EXAMPLES::
180
+
181
+ sage: skp = SkewPartition([[3,2,1],[2,1]]); skp
182
+ [3, 2, 1] / [2, 1]
183
+ sage: skp.inner()
184
+ [2, 1]
185
+ sage: skp.outer()
186
+ [3, 2, 1]
187
+ """
188
+ skp = [_Partitions(p) for p in skp]
189
+ if skp not in SkewPartitions():
190
+ raise ValueError("invalid skew partition: %s" % skp)
191
+ return SkewPartitions()(skp)
192
+
193
+ def __init__(self, parent, skp):
194
+ """
195
+ TESTS::
196
+
197
+ sage: skp = SkewPartition([[3,2,1],[2,1]])
198
+ sage: TestSuite(skp).run()
199
+ """
200
+ CombinatorialElement.__init__(self, parent,
201
+ [_Partitions(skp[0]), _Partitions(skp[1])])
202
+
203
+ def _repr_(self):
204
+ """
205
+ Return a string representation of ``self``.
206
+
207
+ For more on the display options, see
208
+ :obj:`SkewPartitions.options`.
209
+
210
+ EXAMPLES::
211
+
212
+ sage: SkewPartition([[3,2,1],[2,1]])
213
+ [3, 2, 1] / [2, 1]
214
+ """
215
+ return self.parent().options._dispatch(self, '_repr_', 'display')
216
+
217
+ def _repr_quotient(self):
218
+ """
219
+ Return a string representation of ``self``.
220
+
221
+ EXAMPLES::
222
+
223
+ sage: print(SkewPartition([[3,2,1],[2,1]])._repr_quotient())
224
+ [3, 2, 1] / [2, 1]
225
+ """
226
+ return "%s / %s" % (self[0], self[1])
227
+
228
+ def _repr_lists(self):
229
+ """
230
+ Return a string representation of ``self`` as a pair of lists.
231
+
232
+ EXAMPLES::
233
+
234
+ sage: print(SkewPartition([[3,2,1],[2,1]])._repr_lists())
235
+ [[3, 2, 1], [2, 1]]
236
+ """
237
+ return repr([list(r) for r in self])
238
+
239
+ def _latex_(self):
240
+ r"""
241
+ Return a `\LaTeX` representation of ``self``.
242
+
243
+ For more on the latex options, see
244
+ :obj:`SkewPartitions.options`.
245
+
246
+ EXAMPLES::
247
+
248
+ sage: s = SkewPartition([[5,4,3],[3,1,1]])
249
+ sage: latex(s)
250
+ {\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
251
+ \raisebox{-.6ex}{$\begin{array}[b]{*{5}c}\cline{4-5}
252
+ &&&\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{2-5}
253
+ &\lr{\phantom{x}}&\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{2-4}
254
+ &\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{2-3}
255
+ \end{array}$}
256
+ }
257
+ """
258
+ return self.parent().options._dispatch(self, '_latex_', 'latex')
259
+
260
+ def _latex_diagram(self):
261
+ r"""
262
+ Return a `\LaTeX` representation as a young diagram.
263
+
264
+ EXAMPLES::
265
+
266
+ sage: print(SkewPartition([[5,4,3],[3,1,1]])._latex_diagram())
267
+ {\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
268
+ \raisebox{-.6ex}{$\begin{array}[b]{*{5}c}\cline{4-5}
269
+ &&&\lr{\ast}&\lr{\ast}\\\cline{2-5}
270
+ &\lr{\ast}&\lr{\ast}&\lr{\ast}\\\cline{2-4}
271
+ &\lr{\ast}&\lr{\ast}\\\cline{2-3}
272
+ \end{array}$}
273
+ }
274
+
275
+ TESTS:
276
+
277
+ Check that :issue:`34760` is fixed::
278
+
279
+ sage: print(SkewPartition([[],[]])._latex_diagram())
280
+ {\emptyset}
281
+ """
282
+ if not any(self._list):
283
+ return "{\\emptyset}"
284
+
285
+ char = self.parent().options.latex_diagram_str
286
+
287
+ from sage.combinat.output import tex_from_array
288
+ arr = [[char]*row_size for row_size in self[0]]
289
+ for i, skew_size in enumerate(self[1]): # This is always smaller by containment
290
+ for j in range(skew_size):
291
+ arr[i][j] = None
292
+ return tex_from_array(arr)
293
+
294
+ def _latex_young_diagram(self):
295
+ r"""
296
+ Return a `\LaTeX` representation of ``self`` as a young diagram.
297
+
298
+ EXAMPLES::
299
+
300
+ sage: print(SkewPartition([[5,4,3],[3,1,1]])._latex_young_diagram())
301
+ {\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
302
+ \raisebox{-.6ex}{$\begin{array}[b]{*{5}c}\cline{4-5}
303
+ &&&\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{2-5}
304
+ &\lr{\phantom{x}}&\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{2-4}
305
+ &\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{2-3}
306
+ \end{array}$}
307
+ }
308
+
309
+ TESTS:
310
+
311
+ Check that :issue:`34760` is fixed::
312
+
313
+ sage: print(SkewPartition([[],[]])._latex_young_diagram())
314
+ {\emptyset}
315
+ """
316
+ if not any(self._list):
317
+ return "{\\emptyset}"
318
+
319
+ from sage.combinat.output import tex_from_array
320
+ arr = [["\\phantom{x}"]*row_size for row_size in self[0]]
321
+ for i, skew_size in enumerate(self[1]): # This is always smaller by containment
322
+ for j in range(skew_size):
323
+ arr[i][j] = None
324
+ return tex_from_array(arr)
325
+
326
+ def _latex_marked(self):
327
+ r"""
328
+ Return a `\LaTeX` representation as a marked partition.
329
+
330
+ EXAMPLES::
331
+
332
+ sage: print(SkewPartition([[5,4,3],[3,1,1]])._latex_marked())
333
+ {\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
334
+ \raisebox{-.6ex}{$\begin{array}[b]{*{5}c}\cline{1-5}
335
+ \lr{X}&\lr{X}&\lr{X}&\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{1-5}
336
+ \lr{X}&\lr{\phantom{x}}&\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{1-4}
337
+ \lr{X}&\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{1-3}
338
+ \end{array}$}
339
+ }
340
+
341
+ TESTS:
342
+
343
+ Check that :issue:`34760` is fixed::
344
+
345
+ sage: print(SkewPartition([[],[]])._latex_marked())
346
+ {\emptyset}
347
+ """
348
+ if not any(self._list):
349
+ return "{\\emptyset}"
350
+
351
+ from sage.combinat.output import tex_from_array
352
+ char = self.parent().options.latex_marking_str
353
+ arr = [["\\phantom{x}"]*row_size for row_size in self[0]]
354
+ for i, skew_size in enumerate(self[1]): # This is always smaller by containment
355
+ for j in range(skew_size):
356
+ arr[i][j] = char
357
+ return tex_from_array(arr)
358
+
359
+ def __setstate__(self, state):
360
+ r"""
361
+ In order to maintain backwards compatibility and be able to unpickle
362
+ a old pickle from ``SkewPartition_class`` we have to override the
363
+ default ``__setstate__``.
364
+
365
+ EXAMPLES::
366
+
367
+ sage: loads(b'x\x9c\x85P\xcbN\xc2@\x14\r\x08>\x06\xf1\xfd~\xbb+.\x9a\xa8\xdf\xe0\xc2McJ\xba4\x93i\xb9v&\xb4\x03w\x1e!,Ht!\xfe\xb6Sh1\xb0qw\xce}\x9c{\xee\xf9\xac\'\x9a\xa5\xe0\'\x83<\x16\x92\x19_\xf7aD\x87L\x19a\xc4@\x92\xae\xa3o\x15\xa3I\xc6\xb4&X\xeb|a}\x82k^\xd4\xa4\x9ci\x8e\x8d\xc0\xa1Lh\x83\xcdw\\\xf7\xe6\x92\xda(\x9b\x18\xab\xc0\xef\x8d%\xcbER\xae/3\xdc\xf0\xa2\x87\xc5\x05MY\x96\xd1\x910\x9c&\xcc@:Pc\x1f2\xc8A\x9a\xf9<n\xae\xf8\xfd\xb3\xba\x10!\xb8\x95P\x1a[\x91\x19!)%)\x18f\x8c"HV\x8dY)\xd0\x02U0T\xa0\xdd\r6[\xb7RA\xcf&@\xb0U\x1e\x9b[\x11\xa0}!?\x84\x14\x06(H\x9b\x83r\x8d\x1e\xd5`4y-\x1b/\x8bz\xb7(\xe3vg\xf2\x83\xed\x10w\xa2\xf6\xf2#\xbb\xd3\x10\xf7\xa6\xb8\x1f\x04\x81\t\xf1\xc0Ez\xc8[\xff?7K\x88\xe0Q!{\x1c\xe2\xc9\x04O=\xde\x08\xb8\x0b\xfe\xac\x0c^\t\x99\x16N\x9diP$g}\xa0\x15\xc1\xf3\xa8\xf6\xfc\x1d\xe2\x05w\xe0\xc9\x81\xcb\x02<:p\x05v\x1a\xf3\xc2\xc65w\xa27\x95\xe8\xadWM\xdcU\xe0\xbe\x18\x05\x1b\xfb\xbf\x8e\x7f\xcc\xbb')
368
+ [3, 2, 1] / [1, 1]
369
+ sage: loads(dumps( SkewPartition([[3,2,1], [1,1]]) ))
370
+ [3, 2, 1] / [1, 1]
371
+ """
372
+ if isinstance(state, dict): # for old pickles from SkewPartition_class
373
+ self._set_parent(SkewPartitions())
374
+ self.__dict__ = state
375
+ else:
376
+ self._set_parent(state[0])
377
+ self.__dict__ = state[1]
378
+
379
+ def ferrers_diagram(self):
380
+ """
381
+ Return the Ferrers diagram of ``self``.
382
+
383
+ EXAMPLES::
384
+
385
+ sage: print(SkewPartition([[5,4,3,1],[3,3,1]]).ferrers_diagram())
386
+ **
387
+ *
388
+ **
389
+ *
390
+ sage: print(SkewPartition([[5,4,3,1],[3,1]]).diagram())
391
+ **
392
+ ***
393
+ ***
394
+ *
395
+ sage: SkewPartitions.options(diagram_str='#', convention='French')
396
+ sage: print(SkewPartition([[5,4,3,1],[3,1]]).diagram())
397
+ #
398
+ ###
399
+ ###
400
+ ##
401
+ sage: SkewPartitions.options._reset()
402
+ """
403
+ char, convention = self.parent().options('diagram_str', 'convention')
404
+
405
+ if convention == "English":
406
+ L = range(len(self[0]))
407
+ else:
408
+ L = reversed(range(len(self[0])))
409
+ s = ""
410
+ for i in L:
411
+ if len(self[1]) > i:
412
+ s += " "*self[1][i]
413
+ s += char*(self[0][i]-self[1][i])
414
+ else:
415
+ s += char*self[0][i]
416
+ s += "\n"
417
+ return s[:-1]
418
+
419
+ diagram = ferrers_diagram
420
+ _repr_diagram = ferrers_diagram
421
+
422
+ def pp(self):
423
+ """
424
+ Pretty-print ``self``.
425
+
426
+ EXAMPLES::
427
+
428
+ sage: SkewPartition([[5,4,3,1],[3,3,1]]).pp()
429
+ **
430
+ *
431
+ **
432
+ *
433
+ """
434
+ print(self.ferrers_diagram())
435
+
436
+ def _ascii_art_(self):
437
+ """
438
+ TESTS::
439
+
440
+ sage: ascii_art(SkewPartitions(3).list())
441
+ [ * * * * ]
442
+ [ ** ** * * * * * * ]
443
+ [ ***, * , * , **, ** , *, * , * , * ]
444
+ sage: SkewPartitions.options(diagram_str='#', convention='French')
445
+ sage: ascii_art(SkewPartitions(3).list())
446
+ [ # # # # ]
447
+ [ # # ## ## # # # # ]
448
+ [ ###, ##, ##, #, #, #, #, #, # ]
449
+ sage: SkewPartitions.options._reset()
450
+ """
451
+ from sage.typeset.ascii_art import AsciiArt
452
+ return AsciiArt(self.diagram().splitlines())
453
+
454
+ def _unicode_art_(self):
455
+ """
456
+ .. WARNING::
457
+
458
+ not working in presence of empty lines
459
+
460
+ TESTS::
461
+
462
+ sage: unicode_art(SkewPartitions(3).list())
463
+ ⎡ ┌┐ ┌┐ ┌┐ ┌┐ ⎤
464
+ ⎢ ┌┬┐ ┌┬┐ ┌┐ ┌┐ ├┤ ├┤ ┌┼┘ ┌┼┘ ⎥
465
+ ⎢ ┌┬┬┐ ├┼┘ ┌┼┴┘ ┌┼┤ ┌┬┼┘ ├┤ ┌┼┘ ├┤ ┌┼┘ ⎥
466
+ ⎣ └┴┴┘, └┘ , └┘ , └┴┘, └┴┘ , └┘, └┘ , └┘ , └┘ ⎦
467
+ sage: SkewPartitions.options.convention = "French"
468
+ sage: unicode_art(SkewPartitions(3).list())
469
+ ⎡ ┌┐ ┌┐ ┌┐ ┌┐ ⎤
470
+ ⎢ ┌┐ ┌┐ ┌┬┐ ┌┬┐ ├┤ └┼┐ ├┤ └┼┐ ⎥
471
+ ⎢ ┌┬┬┐ ├┼┐ └┼┬┐ └┼┤ └┴┼┐ ├┤ ├┤ └┼┐ └┼┐ ⎥
472
+ ⎣ └┴┴┘, └┴┘, └┴┘, └┘, └┘, └┘, └┘, └┘, └┘ ⎦
473
+ sage: SkewPartitions.options._reset()
474
+
475
+ sage: unicode_art(SkewPartition([[3,1],[2]]))
476
+ ┌┐
477
+ ┌┬┴┘
478
+ └┘
479
+
480
+ TESTS::
481
+
482
+ sage: unicode_art(SkewPartition([[],[]]))
483
+
484
+ """
485
+ from sage.typeset.unicode_art import UnicodeArt
486
+ out, inn = self
487
+ inn = inn + [0] * (len(out) - len(inn))
488
+ if not any(self._list):
489
+ return UnicodeArt('∅')
490
+ if self.parent().options.convention == "French":
491
+ s, t, b, l, r, tr, tl, br, bl, x, h = list(' ┴┬├┤┘└┐┌┼─')
492
+ else:
493
+ s, t, b, l, r, tr, tl, br, bl, x, h = list(' ┬┴├┤┐┌┘└┼─')
494
+
495
+ # working with English conventions
496
+ txt = [s * inn[0] + tl + t * (out[0] - inn[0] - 1) + tr]
497
+ for i in range(len(out) - 1):
498
+ o0 = out[i]
499
+ o1 = out[i + 1]
500
+ i0 = inn[i]
501
+ i1 = inn[i + 1]
502
+
503
+ if i0 == i1:
504
+ start = ' ' * i1 + l
505
+ d0 = 1
506
+ else:
507
+ start = ' ' * i1 + tl
508
+ d0 = 0
509
+
510
+ if o0 == o1:
511
+ end = r
512
+ d1 = 1
513
+ else:
514
+ end = br
515
+ d1 = 0
516
+
517
+ if i0 <= o1:
518
+ middle = t * (i0 - i1 - 1 + d0)
519
+ middle += x * (o1 - i0 + 1 - d0 - d1)
520
+ middle += b * (o0 - o1 - 1 + d1)
521
+ else:
522
+ middle = t * (i0 - i1 - 1)
523
+ middle += h * (i0 - o1 - 1)
524
+ middle += b * (o0 - o1 - 1)
525
+
526
+ txt += [start + middle + end]
527
+ txt += [s * inn[-1] + bl + b * (out[-1] - inn[-1] - 1) + br]
528
+
529
+ if self.parent().options.convention == "French":
530
+ txt = list(reversed(txt))
531
+ return UnicodeArt(txt, baseline=0)
532
+
533
+ def inner(self):
534
+ """
535
+ Return the inner partition of ``self``.
536
+
537
+ EXAMPLES::
538
+
539
+ sage: SkewPartition([[3,2,1],[1,1]]).inner()
540
+ [1, 1]
541
+ """
542
+ return self[1]
543
+
544
+ def outer(self):
545
+ """
546
+ Return the outer partition of ``self``.
547
+
548
+ EXAMPLES::
549
+
550
+ sage: SkewPartition([[3,2,1],[1,1]]).outer()
551
+ [3, 2, 1]
552
+ """
553
+ return self[0]
554
+
555
+ def column_lengths(self):
556
+ """
557
+ Return the column lengths of ``self``.
558
+
559
+ EXAMPLES::
560
+
561
+ sage: SkewPartition([[3,2,1],[1,1]]).column_lengths()
562
+ [1, 2, 1]
563
+ sage: SkewPartition([[5,2,2,2],[2,1]]).column_lengths()
564
+ [2, 3, 1, 1, 1]
565
+ """
566
+ return self.conjugate().row_lengths()
567
+
568
+ def row_lengths(self):
569
+ """
570
+ Return the row lengths of ``self``.
571
+
572
+ EXAMPLES::
573
+
574
+ sage: SkewPartition([[3,2,1],[1,1]]).row_lengths()
575
+ [2, 1, 1]
576
+ """
577
+ skp = self
578
+ o = skp[0]
579
+ i = skp[1]+[0]*(len(skp[0])-len(skp[1]))
580
+ return [x[0]-x[1] for x in zip(o,i)]
581
+
582
+ def size(self):
583
+ """
584
+ Return the size of ``self``.
585
+
586
+ EXAMPLES::
587
+
588
+ sage: SkewPartition([[3,2,1],[1,1]]).size()
589
+ 4
590
+ """
591
+ return sum(self.row_lengths())
592
+
593
+ def is_connected(self):
594
+ """
595
+ Return ``True`` if ``self`` is a connected skew partition.
596
+
597
+ A skew partition is said to be *connected* if for each pair of
598
+ consecutive rows, there are at least two cells (one in each row)
599
+ which have a common edge.
600
+
601
+ EXAMPLES::
602
+
603
+ sage: SkewPartition([[5,4,3,1],[3,3,1]]).is_connected()
604
+ False
605
+ sage: SkewPartition([[5,4,3,1],[3,1]]).is_connected()
606
+ True
607
+ """
608
+ return self.is_overlap(1)
609
+
610
+ def overlap(self):
611
+ """
612
+ Return the overlap of ``self``.
613
+
614
+ The overlap of two consecutive rows in a skew partition is the
615
+ number of pairs of cells (one in each row) that share a common
616
+ edge. This number can be positive, zero, or negative.
617
+
618
+ The overlap of a skew partition is the minimum of the overlap of
619
+ the consecutive rows, or infinity in the case of at most one row.
620
+ If the overlap is positive, then the skew partition is called
621
+ *connected*.
622
+
623
+ EXAMPLES::
624
+
625
+ sage: SkewPartition([[],[]]).overlap()
626
+ +Infinity
627
+ sage: SkewPartition([[1],[]]).overlap()
628
+ +Infinity
629
+ sage: SkewPartition([[10],[]]).overlap()
630
+ +Infinity
631
+ sage: SkewPartition([[10],[2]]).overlap()
632
+ +Infinity
633
+ sage: SkewPartition([[10,1],[2]]).overlap()
634
+ -1
635
+ sage: SkewPartition([[10,10],[1]]).overlap()
636
+ 9
637
+ """
638
+ p,q = self
639
+ if len(p) <= 1:
640
+ from sage.rings.infinity import PlusInfinity
641
+ return PlusInfinity()
642
+ if len(q) == 0:
643
+ return min(p)
644
+ q = [q[0]] + list(q)
645
+ return min(row_lengths_aux([p,q]))
646
+
647
+ def is_overlap(self, n):
648
+ r"""
649
+ Return ``True`` if the overlap of ``self`` is at most ``n``.
650
+
651
+ .. SEEALSO::
652
+
653
+ :meth:`overlap`
654
+
655
+ EXAMPLES::
656
+
657
+ sage: SkewPartition([[5,4,3,1],[3,1]]).is_overlap(1)
658
+ True
659
+ """
660
+ return n <= self.overlap()
661
+
662
+ def is_ribbon(self):
663
+ r"""
664
+ Return ``True`` if and only if ``self`` is a ribbon.
665
+
666
+ This means that if it has exactly one cell in each of `q`
667
+ consecutive diagonals for some nonnegative integer `q`.
668
+
669
+ EXAMPLES::
670
+
671
+ sage: P = SkewPartition([[4,4,3,3],[3,2,2]])
672
+ sage: P.pp()
673
+ *
674
+ **
675
+ *
676
+ ***
677
+ sage: P.is_ribbon()
678
+ True
679
+
680
+ sage: P = SkewPartition([[4,3,3],[1,1]])
681
+ sage: P.pp()
682
+ ***
683
+ **
684
+ ***
685
+ sage: P.is_ribbon()
686
+ False
687
+
688
+ sage: P = SkewPartition([[4,4,3,2],[3,2,2]])
689
+ sage: P.pp()
690
+ *
691
+ **
692
+ *
693
+ **
694
+ sage: P.is_ribbon()
695
+ False
696
+
697
+ sage: P = SkewPartition([[4,4,3,3],[4,2,2,1]])
698
+ sage: P.pp()
699
+ <BLANKLINE>
700
+ **
701
+ *
702
+ **
703
+ sage: P.is_ribbon()
704
+ True
705
+
706
+ sage: P = SkewPartition([[4,4,3,3],[4,2,2]])
707
+ sage: P.pp()
708
+ <BLANKLINE>
709
+ **
710
+ *
711
+ ***
712
+ sage: P.is_ribbon()
713
+ True
714
+
715
+ sage: SkewPartition([[2,2,1],[2,2,1]]).is_ribbon()
716
+ True
717
+ """
718
+ lam = self[0]
719
+ mu = self[1]
720
+ l_out = len(lam)
721
+ l_in = len(mu)
722
+ mu += [0]*(l_out-l_in)
723
+
724
+ if l_out == 0:
725
+ return True
726
+ else:
727
+ # Find the least u for which lam[u]>mu[u], if it exists
728
+ # If it does not exist then u will equal l_out
729
+ u = 0
730
+ u_test = True
731
+ while u_test:
732
+ if u >= l_out or lam[u] > mu[u]:
733
+ u_test = False
734
+ else:
735
+ u += 1
736
+
737
+ # Find the least v strictly greater than u for which
738
+ # lam[v] != mu[v-1]+1
739
+ v = u + 1
740
+ v_test = True
741
+ while v_test:
742
+ if v >= l_out or lam[v] != mu[v-1] + 1:
743
+ v_test = False
744
+ else:
745
+ v += 1
746
+
747
+ # Check if lam[i]==mu[i] for all i >= v
748
+ for i in range(v, l_out):
749
+ if lam[i] != mu[i]:
750
+ return False
751
+
752
+ return True
753
+
754
+ def conjugate(self):
755
+ """
756
+ Return the conjugate of the skew partition skp.
757
+
758
+ EXAMPLES::
759
+
760
+ sage: SkewPartition([[3,2,1],[2]]).conjugate()
761
+ [3, 2, 1] / [1, 1]
762
+ """
763
+ return SkewPartition([x.conjugate() for x in self])
764
+
765
+ def outer_corners(self):
766
+ """
767
+ Return a list of the outer corners of ``self``.
768
+
769
+ These are corners that are contained inside of the shape.
770
+ For the corners which are outside of the shape,
771
+ use :meth:`outside_corners`.
772
+
773
+ .. WARNING::
774
+
775
+ In the case that ``self`` is an honest (rather than skew) partition,
776
+ these are the :meth:`~sage.combinat.partition.Partition.corners`
777
+ of the outer partition. In the language of [Sag2001]_ these would
778
+ be the "inner corners" of the outer partition.
779
+
780
+ .. SEEALSO::
781
+
782
+ - :meth:`sage.combinat.skew_partition.SkewPartition.outside_corners`
783
+ - :meth:`sage.combinat.partition.Partition.outside_corners`
784
+
785
+ EXAMPLES::
786
+
787
+ sage: SkewPartition([[4, 3, 1], [2]]).outer_corners()
788
+ [(0, 3), (1, 2), (2, 0)]
789
+ """
790
+ return self.outer().corners()
791
+
792
+ def inner_corners(self):
793
+ """
794
+ Return a list of the inner corners of ``self``.
795
+
796
+ EXAMPLES::
797
+
798
+ sage: SkewPartition([[4, 3, 1], [2]]).inner_corners()
799
+ [(0, 2), (1, 0)]
800
+ sage: SkewPartition([[4, 3, 1], []]).inner_corners()
801
+ [(0, 0)]
802
+ """
803
+ inner = self.inner()
804
+ outer = self.outer()
805
+ if inner == []:
806
+ if outer == []:
807
+ return []
808
+ else:
809
+ return [(0,0)]
810
+ icorners = [(0, inner[0])]
811
+ nn = len(inner)
812
+ for i in range(1,nn):
813
+ if inner[i] != inner[i-1]:
814
+ icorners += [ (i, inner[i]) ]
815
+
816
+ icorners += [(nn, 0)]
817
+ return icorners
818
+
819
+ def cell_poset(self, orientation='SE'):
820
+ """
821
+ Return the Young diagram of ``self`` as a poset. The optional
822
+ keyword variable ``orientation`` determines the order relation
823
+ of the poset.
824
+
825
+ The poset always uses the set of cells of the Young diagram
826
+ of ``self`` as its ground set. The order relation of the poset
827
+ depends on the ``orientation`` variable (which defaults to
828
+ ``'SE'``). Concretely, ``orientation`` has to be specified to
829
+ one of the strings ``'NW'``, ``'NE'``, ``'SW'``, and ``'SE'``,
830
+ standing for "northwest", "northeast", "southwest" and
831
+ "southeast", respectively. If ``orientation`` is ``'SE'``, then
832
+ the order relation of the poset is such that a cell `u` is
833
+ greater or equal to a cell `v` in the poset if and only if `u`
834
+ lies weakly southeast of `v` (this means that `u` can be
835
+ reached from `v` by a sequence of south and east steps; the
836
+ sequence is allowed to consist of south steps only, or of east
837
+ steps only, or even be empty). Similarly the order relation is
838
+ defined for the other three orientations. The Young diagram is
839
+ supposed to be drawn in English notation.
840
+
841
+ The elements of the poset are the cells of the Young diagram
842
+ of ``self``, written as tuples of zero-based coordinates (so
843
+ that `(3, 7)` stands for the `8`-th cell of the `4`-th row,
844
+ etc.).
845
+
846
+ EXAMPLES::
847
+
848
+ sage: # needs sage.graphs
849
+ sage: p = SkewPartition([[3,3,1], [2,1]])
850
+ sage: Q = p.cell_poset(); Q
851
+ Finite poset containing 4 elements
852
+ sage: sorted(Q)
853
+ [(0, 2), (1, 1), (1, 2), (2, 0)]
854
+ sage: sorted(Q.maximal_elements())
855
+ [(1, 2), (2, 0)]
856
+ sage: sorted(Q.minimal_elements())
857
+ [(0, 2), (1, 1), (2, 0)]
858
+ sage: sorted(Q.upper_covers((1, 1)))
859
+ [(1, 2)]
860
+ sage: sorted(Q.upper_covers((0, 2)))
861
+ [(1, 2)]
862
+
863
+ sage: # needs sage.graphs
864
+ sage: P = p.cell_poset(orientation="NW"); P
865
+ Finite poset containing 4 elements
866
+ sage: sorted(P)
867
+ [(0, 2), (1, 1), (1, 2), (2, 0)]
868
+ sage: sorted(P.minimal_elements())
869
+ [(1, 2), (2, 0)]
870
+ sage: sorted(P.maximal_elements())
871
+ [(0, 2), (1, 1), (2, 0)]
872
+ sage: sorted(P.upper_covers((1, 2)))
873
+ [(0, 2), (1, 1)]
874
+
875
+ sage: # needs sage.graphs
876
+ sage: R = p.cell_poset(orientation="NE"); R
877
+ Finite poset containing 4 elements
878
+ sage: sorted(R)
879
+ [(0, 2), (1, 1), (1, 2), (2, 0)]
880
+ sage: R.maximal_elements()
881
+ [(0, 2)]
882
+ sage: R.minimal_elements()
883
+ [(2, 0)]
884
+ sage: R.upper_covers((2, 0))
885
+ [(1, 1)]
886
+ sage: sorted([len(R.upper_covers(v)) for v in R])
887
+ [0, 1, 1, 1]
888
+
889
+ TESTS:
890
+
891
+ We check that the posets are really what they should be for size
892
+ up to `6`::
893
+
894
+ sage: def check_NW(n):
895
+ ....: for p in SkewPartitions(n):
896
+ ....: P = p.cell_poset(orientation="NW")
897
+ ....: for c in p.cells():
898
+ ....: for d in p.cells():
899
+ ....: if P.le(c, d) != (c[0] >= d[0]
900
+ ....: and c[1] >= d[1]):
901
+ ....: return False
902
+ ....: return True
903
+ sage: all( check_NW(n) for n in range(7) ) # needs sage.graphs
904
+ True
905
+
906
+ sage: def check_NE(n):
907
+ ....: for p in SkewPartitions(n):
908
+ ....: P = p.cell_poset(orientation="NE")
909
+ ....: for c in p.cells():
910
+ ....: for d in p.cells():
911
+ ....: if P.le(c, d) != (c[0] >= d[0]
912
+ ....: and c[1] <= d[1]):
913
+ ....: return False
914
+ ....: return True
915
+ sage: all( check_NE(n) for n in range(7) ) # needs sage.graphs
916
+ True
917
+
918
+ sage: def test_duality(n, ori1, ori2):
919
+ ....: for p in SkewPartitions(n):
920
+ ....: P = p.cell_poset(orientation=ori1)
921
+ ....: Q = p.cell_poset(orientation=ori2)
922
+ ....: for c in p.cells():
923
+ ....: for d in p.cells():
924
+ ....: if P.lt(c, d) != Q.lt(d, c):
925
+ ....: return False
926
+ ....: return True
927
+ sage: all( test_duality(n, "NW", "SE") for n in range(7) ) # needs sage.graphs
928
+ True
929
+ sage: all( test_duality(n, "NE", "SW") for n in range(7) ) # needs sage.graphs
930
+ True
931
+ sage: all( test_duality(n, "NE", "SE") for n in range(4) ) # needs sage.graphs
932
+ False
933
+ """
934
+ from sage.combinat.posets.posets import Poset
935
+ # Getting the cover relations seems hard, so let's just compute
936
+ # the comparison function.
937
+ if orientation == "NW":
938
+ def poset_le(u, v):
939
+ return u[0] >= v[0] and u[1] >= v[1]
940
+ elif orientation == "NE":
941
+ def poset_le(u, v):
942
+ return u[0] >= v[0] and u[1] <= v[1]
943
+ elif orientation == "SE":
944
+ def poset_le(u, v):
945
+ return u[0] <= v[0] and u[1] <= v[1]
946
+ elif orientation == "SW":
947
+ def poset_le(u, v):
948
+ return u[0] <= v[0] and u[1] >= v[1]
949
+ return Poset((self.cells(), poset_le))
950
+
951
+ def frobenius_rank(self):
952
+ r"""
953
+ Return the Frobenius rank of the skew partition ``self``.
954
+
955
+ The Frobenius rank of a skew partition `\lambda / \mu` can be
956
+ defined in various ways. The quickest one is probably the
957
+ following: Writing `\lambda` as
958
+ `(\lambda_1, \lambda_2, \cdots , \lambda_N)`, and writing `\mu`
959
+ as `(\mu_1, \mu_2, \cdots , \mu_N)`, we define the Frobenius
960
+ rank of `\lambda / \mu` to be the number of all
961
+ `1 \leq i \leq N` such that
962
+
963
+ .. MATH::
964
+
965
+ \lambda_i - i
966
+ \not\in \{ \mu_1 - 1, \mu_2 - 2, \cdots , \mu_N - N \}.
967
+
968
+ In other words, the Frobenius rank of `\lambda / \mu` is the
969
+ number of rows in the Jacobi-Trudi matrix of `\lambda / \mu`
970
+ which don't contain `h_0`. Further definitions have been
971
+ considered in [Sta2002]_ (where Frobenius rank is just being
972
+ called rank).
973
+
974
+ If `\mu` is the empty shape, then the Frobenius rank of
975
+ `\lambda / \mu` is just the usual Frobenius rank of the
976
+ partition `\lambda` (see
977
+ :meth:`~sage.combinat.partition.Partition.frobenius_rank()`).
978
+
979
+ EXAMPLES::
980
+
981
+ sage: SkewPartition([[8,8,7,4], [4,1,1]]).frobenius_rank()
982
+ 4
983
+ sage: SkewPartition([[2,1], [1]]).frobenius_rank()
984
+ 2
985
+ sage: SkewPartition([[2,1,1], [1]]).frobenius_rank()
986
+ 2
987
+ sage: SkewPartition([[2,1,1], [1,1]]).frobenius_rank()
988
+ 2
989
+ sage: SkewPartition([[5,4,3,2], [2,1,1]]).frobenius_rank()
990
+ 3
991
+ sage: SkewPartition([[4,2,1], [3,1,1]]).frobenius_rank()
992
+ 2
993
+ sage: SkewPartition([[4,2,1], [3,2,1]]).frobenius_rank()
994
+ 1
995
+
996
+ If the inner shape is empty, then the Frobenius rank of the skew
997
+ partition is just the standard Frobenius rank of the partition::
998
+
999
+ sage: all( SkewPartition([lam, Partition([])]).frobenius_rank()
1000
+ ....: == lam.frobenius_rank() for i in range(6)
1001
+ ....: for lam in Partitions(i) )
1002
+ True
1003
+
1004
+ If the inner and outer shapes are equal, then the Frobenius rank
1005
+ is zero::
1006
+
1007
+ sage: all( SkewPartition([lam, lam]).frobenius_rank() == 0
1008
+ ....: for i in range(6) for lam in Partitions(i) )
1009
+ True
1010
+ """
1011
+ N = len(self[0])
1012
+ mu_betas = [x - j for j, x in enumerate(self[1])]
1013
+ mu_betas.extend(- j for j in range(len(self[1]), N))
1014
+ return sum(1 for i, x in enumerate(self[0])
1015
+ if (x - i) not in mu_betas)
1016
+
1017
+ def cells(self):
1018
+ """
1019
+ Return the coordinates of the cells of ``self``. Coordinates are
1020
+ given as ``(row-index, column-index)`` and are 0 based.
1021
+
1022
+ EXAMPLES::
1023
+
1024
+ sage: SkewPartition([[4, 3, 1], [2]]).cells()
1025
+ [(0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (2, 0)]
1026
+ sage: SkewPartition([[4, 3, 1], []]).cells()
1027
+ [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (2, 0)]
1028
+ sage: SkewPartition([[2], []]).cells()
1029
+ [(0, 0), (0, 1)]
1030
+ """
1031
+ outer = self.outer()
1032
+ inner = self.inner()[:]
1033
+ inner += [0] * (len(outer) - len(inner))
1034
+ return [(i, j) for i, outi in enumerate(outer)
1035
+ for j in range(inner[i], outi)]
1036
+
1037
+ def to_list(self):
1038
+ """
1039
+ Return ``self`` as a list of lists.
1040
+
1041
+ EXAMPLES::
1042
+
1043
+ sage: s = SkewPartition([[4,3,1],[2]])
1044
+ sage: s.to_list()
1045
+ [[4, 3, 1], [2]]
1046
+ sage: type(s.to_list())
1047
+ <class 'list'>
1048
+ """
1049
+ return [list(r) for r in list(self)]
1050
+
1051
+ def to_dag(self, format='string'):
1052
+ """
1053
+ Return a directed acyclic graph corresponding to the skew
1054
+ partition ``self``.
1055
+
1056
+ The directed acyclic graph corresponding to a skew partition
1057
+ `p` is the digraph whose vertices are the cells of `p`, and
1058
+ whose edges go from each cell to its lower and right
1059
+ neighbors (in English notation).
1060
+
1061
+ INPUT:
1062
+
1063
+ - ``format`` -- either ``'string'`` or ``'tuple'`` (default:
1064
+ ``'string'``); determines whether the vertices of the
1065
+ resulting dag will be strings or 2-tuples of coordinates
1066
+
1067
+ EXAMPLES::
1068
+
1069
+ sage: # needs sage.graphs
1070
+ sage: dag = SkewPartition([[3, 3, 1], [1, 1]]).to_dag()
1071
+ sage: dag.edges(sort=True)
1072
+ [('0,1', '0,2', None),
1073
+ ('0,1', '1,1', None),
1074
+ ('0,2', '1,2', None),
1075
+ ('1,1', '1,2', None)]
1076
+ sage: dag.vertices(sort=True)
1077
+ ['0,1', '0,2', '1,1', '1,2', '2,0']
1078
+ sage: dag = SkewPartition([[3, 2, 1], [1, 1]]).to_dag(format='tuple')
1079
+ sage: dag.edges(sort=True)
1080
+ [((0, 1), (0, 2), None), ((0, 1), (1, 1), None)]
1081
+ sage: dag.vertices(sort=True)
1082
+ [(0, 1), (0, 2), (1, 1), (2, 0)]
1083
+ """
1084
+ outer = list(self.outer())
1085
+ inner = list(self.inner())
1086
+ inner += [0] * (len(outer) - len(inner))
1087
+
1088
+ G = DiGraph()
1089
+ for i, outer_i in enumerate(outer):
1090
+ for j in range(inner[i], outer_i):
1091
+ if format == "string":
1092
+ string = "%d,%d" % (i, j)
1093
+ else:
1094
+ string = (i, j)
1095
+ G.add_vertex(string)
1096
+ #Check to see if there is a node to the right
1097
+ if j != outer_i - 1:
1098
+ if format == "string":
1099
+ newstring = "%d,%d" % (i, j + 1)
1100
+ else:
1101
+ newstring = (i, j + 1)
1102
+ G.add_edge(string, newstring)
1103
+
1104
+ #Check to see if there is anything below
1105
+ if i != len(outer) - 1:
1106
+ if outer[i+1] > j:
1107
+ if format == "string":
1108
+ newstring = "%d,%d" % (i + 1, j)
1109
+ else:
1110
+ newstring = (i + 1, j)
1111
+ G.add_edge(string, newstring)
1112
+ return G
1113
+
1114
+ def quotient(self, k):
1115
+ """
1116
+ The quotient map extended to skew partitions.
1117
+
1118
+ EXAMPLES::
1119
+
1120
+ sage: SkewPartition([[3, 3, 2, 1], [2, 1]]).quotient(2)
1121
+ [[3] / [], [] / []]
1122
+ """
1123
+ ## k-th element is the skew partition built using the k-th partition of the
1124
+ ## k-quotient of the outer and the inner partition.
1125
+ ## This bijection is only defined if the inner and the outer partition
1126
+ ## have the same core
1127
+ if self.inner().core(k) == self.outer().core(k):
1128
+ rqinner = self.inner().quotient(k)
1129
+ rqouter = self.outer().quotient(k)
1130
+ return [ SkewPartitions()([rqouter[i],rqinner[i]]) for i in range(k) ]
1131
+ else:
1132
+ raise ValueError("quotient map is only defined for skew partitions with inner and outer partitions having the same core")
1133
+
1134
+ def rows_intersection_set(self):
1135
+ r"""
1136
+ Return the set of cells in the rows of the outer shape of
1137
+ ``self`` which rows intersect the skew diagram of ``self``.
1138
+
1139
+ EXAMPLES::
1140
+
1141
+ sage: skp = SkewPartition([[3,2,1],[2,1]])
1142
+ sage: cells = Set([ (0,0), (0, 1), (0,2), (1, 0), (1, 1), (2, 0)])
1143
+ sage: skp.rows_intersection_set() == cells
1144
+ True
1145
+ """
1146
+ outer = self.outer()
1147
+ inner = self.inner()
1148
+ inner += [0] * (len(outer) - len(inner))
1149
+
1150
+ res = [(i, j) for i, outi in enumerate(outer)
1151
+ for j in range(outi)
1152
+ if outi != inner[i]]
1153
+ return Set(res)
1154
+
1155
+ def columns_intersection_set(self):
1156
+ """
1157
+ Return the set of cells in the columns of the outer shape of
1158
+ ``self`` which columns intersect the skew diagram of ``self``.
1159
+
1160
+ EXAMPLES::
1161
+
1162
+ sage: skp = SkewPartition([[3,2,1],[2,1]])
1163
+ sage: cells = Set([ (0,0), (0, 1), (0,2), (1, 0), (1, 1), (2, 0)])
1164
+ sage: skp.columns_intersection_set() == cells
1165
+ True
1166
+ """
1167
+ res = [ (x[1], x[0]) for x in self.conjugate().rows_intersection_set()]
1168
+ return Set(res)
1169
+
1170
+ def pieri_macdonald_coeffs(self):
1171
+ """
1172
+ Computation of the coefficients which appear in the Pieri formula
1173
+ for Macdonald polynomials given in his book ( Chapter 6.6 formula
1174
+ 6.24(ii) )
1175
+
1176
+ EXAMPLES::
1177
+
1178
+ sage: SkewPartition([[3,2,1],[2,1]]).pieri_macdonald_coeffs()
1179
+ 1
1180
+ sage: SkewPartition([[3,2,1],[2,2]]).pieri_macdonald_coeffs()
1181
+ (q^2*t^3 - q^2*t - t^2 + 1)/(q^2*t^3 - q*t^2 - q*t + 1)
1182
+ sage: SkewPartition([[3,2,1],[2,2,1]]).pieri_macdonald_coeffs()
1183
+ (q^6*t^8 - q^6*t^6 - q^4*t^7 - q^5*t^5 + q^4*t^5 - q^3*t^6 + q^5*t^3 + 2*q^3*t^4 + q*t^5 - q^3*t^2 + q^2*t^3 - q*t^3 - q^2*t - t^2 + 1)/(q^6*t^8 - q^5*t^7 - q^5*t^6 - q^4*t^6 + q^3*t^5 + 2*q^3*t^4 + q^3*t^3 - q^2*t^2 - q*t^2 - q*t + 1)
1184
+ sage: SkewPartition([[3,3,2,2],[3,2,2,1]]).pieri_macdonald_coeffs()
1185
+ (q^5*t^6 - q^5*t^5 + q^4*t^6 - q^4*t^5 - q^4*t^3 + q^4*t^2 - q^3*t^3 - q^2*t^4 + q^3*t^2 + q^2*t^3 - q*t^4 + q*t^3 + q*t - q + t - 1)/(q^5*t^6 - q^4*t^5 - q^3*t^4 - q^3*t^3 + q^2*t^3 + q^2*t^2 + q*t - 1)
1186
+ """
1187
+
1188
+ set_prod = self.rows_intersection_set() - self.columns_intersection_set()
1189
+ res = 1
1190
+ for s in set_prod:
1191
+ res *= self.inner().arms_legs_coeff(s[0],s[1])
1192
+ res /= self.outer().arms_legs_coeff(s[0],s[1])
1193
+ return res
1194
+
1195
+ def k_conjugate(self, k):
1196
+ """
1197
+ Return the `k`-conjugate of the skew partition.
1198
+
1199
+ EXAMPLES::
1200
+
1201
+ sage: SkewPartition([[3,2,1],[2,1]]).k_conjugate(3)
1202
+ [2, 1, 1, 1, 1] / [2, 1]
1203
+ sage: SkewPartition([[3,2,1],[2,1]]).k_conjugate(4)
1204
+ [2, 2, 1, 1] / [2, 1]
1205
+ sage: SkewPartition([[3,2,1],[2,1]]).k_conjugate(5)
1206
+ [3, 2, 1] / [2, 1]
1207
+ """
1208
+ return SkewPartition([ self.outer().k_conjugate(k), self.inner().k_conjugate(k) ])
1209
+
1210
+ def jacobi_trudi(self):
1211
+ """
1212
+ Return the Jacobi-Trudi matrix of ``self``.
1213
+
1214
+ EXAMPLES::
1215
+
1216
+ sage: SkewPartition([[3,2,1],[2,1]]).jacobi_trudi() # needs sage.modules
1217
+ [h[1] 0 0]
1218
+ [h[3] h[1] 0]
1219
+ [h[5] h[3] h[1]]
1220
+ sage: SkewPartition([[4,3,2],[2,1]]).jacobi_trudi() # needs sage.modules
1221
+ [h[2] h[] 0]
1222
+ [h[4] h[2] h[]]
1223
+ [h[6] h[4] h[2]]
1224
+ """
1225
+ p = self.outer()
1226
+ q = self.inner()
1227
+ from sage.combinat.sf.sf import SymmetricFunctions
1228
+ nn = len(p)
1229
+ if nn == 0:
1230
+ return MatrixSpace(SymmetricFunctions(QQ).homogeneous(), 0)(0)
1231
+ h = SymmetricFunctions(QQ).homogeneous()
1232
+ H = MatrixSpace(h, nn)
1233
+
1234
+ q = q + [0] * (nn - len(q))
1235
+ m = []
1236
+ for i in range(1,nn+1):
1237
+ row = []
1238
+ for j in range(1,nn+1):
1239
+ v = p[j-1]-q[i-1]-j+i
1240
+ if v < 0:
1241
+ row.append(h.zero())
1242
+ elif v == 0:
1243
+ row.append(h([]))
1244
+ else:
1245
+ row.append(h([v]))
1246
+ m.append(row)
1247
+ return H(m)
1248
+
1249
+ def outside_corners(self):
1250
+ r"""
1251
+ Return the outside corners of ``self``.
1252
+
1253
+ The outside corners are corners which are outside of the shape. This
1254
+ should not be confused with :meth:`outer_corners` which consists of
1255
+ corners inside the shape. It returns a result analogous to the
1256
+ ``.outside_corners()`` method on (non-skew) ``Partitions``.
1257
+
1258
+ .. SEEALSO::
1259
+
1260
+ - :meth:`sage.combinat.skew_partition.SkewPartition.outer_corners`
1261
+ - :meth:`sage.combinat.partition.Partition.outside_corners`
1262
+
1263
+ EXAMPLES::
1264
+
1265
+ sage: mu = SkewPartition([[3,2,1],[2,1]])
1266
+ sage: mu.pp()
1267
+ *
1268
+ *
1269
+ *
1270
+ sage: mu.outside_corners()
1271
+ [(0, 3), (1, 2), (2, 1), (3, 0)]
1272
+ """
1273
+ return self.outer().outside_corners()
1274
+
1275
+ def specht_module(self, base_ring=None):
1276
+ r"""
1277
+ Return the Specht module corresponding to ``self``.
1278
+
1279
+ EXAMPLES::
1280
+
1281
+ sage: mu = SkewPartition([[3,2,1], [2]])
1282
+ sage: SM = mu.specht_module(QQ) # needs sage.modules
1283
+ sage: s = SymmetricFunctions(QQ).s() # needs sage.modules
1284
+ sage: s(SM.frobenius_image()) # needs sage.libs.flint sage.modules
1285
+ s[2, 1, 1] + s[2, 2] + s[3, 1]
1286
+
1287
+ We verify that the Frobenius image is the corresponding
1288
+ skew Schur function::
1289
+
1290
+ sage: s[3,2,1].skew_by(s[2]) # needs lrcalc_python sage.modules
1291
+ s[2, 1, 1] + s[2, 2] + s[3, 1]
1292
+
1293
+ ::
1294
+
1295
+ sage: mu = SkewPartition([[4,2,1], [2,1]])
1296
+ sage: SM = mu.specht_module(QQ) # needs sage.modules
1297
+ sage: s(SM.frobenius_image()) # needs sage.libs.flint sage.modules
1298
+ s[2, 1, 1] + s[2, 2] + 2*s[3, 1] + s[4]
1299
+ sage: s(mu) # needs lrcalc_python sage.modules
1300
+ s[2, 1, 1] + s[2, 2] + 2*s[3, 1] + s[4]
1301
+ """
1302
+ from sage.combinat.specht_module import SpechtModule
1303
+ from sage.combinat.symmetric_group_algebra import SymmetricGroupAlgebra
1304
+ if base_ring is None:
1305
+ from sage.rings.rational_field import QQ
1306
+ base_ring = QQ
1307
+ R = SymmetricGroupAlgebra(base_ring, self.size())
1308
+ return SpechtModule(R, self.cells())
1309
+
1310
+ def specht_module_dimension(self, base_ring=None):
1311
+ r"""
1312
+ Return the dimension of the Specht module corresponding to ``self``.
1313
+
1314
+ This is equal to the number of standard (skew) tableaux of
1315
+ shape ``self``.
1316
+
1317
+ EXAMPLES::
1318
+
1319
+ sage: mu = SkewPartition([[3,2,1], [2]])
1320
+ sage: mu.specht_module_dimension() # needs sage.modules
1321
+ 8
1322
+ sage: mu.specht_module_dimension(GF(2)) # needs sage.modules sage.rings.finite_rings
1323
+ 8
1324
+ """
1325
+ from sage.categories.fields import Fields
1326
+ if base_ring is None or (base_ring in Fields() and base_ring.characteristic() == 0):
1327
+ from sage.combinat.skew_tableau import StandardSkewTableaux
1328
+ return StandardSkewTableaux(self).cardinality()
1329
+ from sage.combinat.specht_module import specht_module_rank
1330
+ return specht_module_rank(self, base_ring)
1331
+
1332
+
1333
+ def row_lengths_aux(skp):
1334
+ """
1335
+ EXAMPLES::
1336
+
1337
+ sage: from sage.combinat.skew_partition import row_lengths_aux
1338
+ sage: row_lengths_aux([[5,4,3,1],[3,3,1]])
1339
+ [2, 1, 2]
1340
+ sage: row_lengths_aux([[5,4,3,1],[3,1]])
1341
+ [2, 3]
1342
+ """
1343
+ if skp[0] == []:
1344
+ return []
1345
+ else:
1346
+ return [x[0] - x[1] for x in zip(skp[0], skp[1])]
1347
+
1348
+
1349
+ class SkewPartitions(UniqueRepresentation, Parent):
1350
+ """
1351
+ Skew partitions.
1352
+
1353
+ .. WARNING::
1354
+
1355
+ The iterator of this class only yields skew partitions which
1356
+ are reduced, in the sense that there are no empty rows
1357
+ before the last nonempty row, and there are no empty columns
1358
+ before the last nonempty column.
1359
+
1360
+ EXAMPLES::
1361
+
1362
+ sage: SkewPartitions(4)
1363
+ Skew partitions of 4
1364
+ sage: SkewPartitions(4).cardinality()
1365
+ 28
1366
+ sage: SkewPartitions(row_lengths=[2,1,2])
1367
+ Skew partitions with row lengths [2, 1, 2]
1368
+ sage: SkewPartitions(4, overlap=2)
1369
+ Skew partitions of 4 with a minimum overlap of 2
1370
+ sage: SkewPartitions(4, overlap=2).list()
1371
+ [[4] / [], [2, 2] / []]
1372
+ """
1373
+ @staticmethod
1374
+ def __classcall_private__(self, n=None, row_lengths=None, overlap=0):
1375
+ """
1376
+ Return the correct parent based upon the input.
1377
+
1378
+ EXAMPLES::
1379
+
1380
+ sage: SP1 = SkewPartitions(row_lengths=(2,1,2))
1381
+ sage: SP2 = SkewPartitions(row_lengths=[2,1,2])
1382
+ sage: SP1 is SP2
1383
+ True
1384
+ """
1385
+ if n is not None:
1386
+ if row_lengths is not None:
1387
+ raise ValueError("you can only specify one of n or row_lengths")
1388
+ return SkewPartitions_n(n, overlap)
1389
+ elif row_lengths is not None:
1390
+ return SkewPartitions_rowlengths(row_lengths, overlap)
1391
+ else:
1392
+ return SkewPartitions_all()
1393
+
1394
+ def __init__(self, is_infinite=False):
1395
+ """
1396
+ TESTS::
1397
+
1398
+ sage: S = SkewPartitions()
1399
+ sage: TestSuite(S).run()
1400
+ """
1401
+ if is_infinite:
1402
+ Parent.__init__(self, category=InfiniteEnumeratedSets())
1403
+ else:
1404
+ Parent.__init__(self, category=FiniteEnumeratedSets())
1405
+
1406
+ # add options to class
1407
+ class options(GlobalOptions):
1408
+ """
1409
+ Set and display the options for elements of the skew partition
1410
+ classes. If no parameters are set, then the function returns a copy of
1411
+ the options dictionary.
1412
+
1413
+ The ``options`` to skew partitions can be accessed as the method
1414
+ :obj:`SkewPartitions.options` of :class:`SkewPartitions` and
1415
+ related parent classes.
1416
+
1417
+ @OPTIONS@
1418
+
1419
+ EXAMPLES::
1420
+
1421
+ sage: SP = SkewPartition([[4,2,2,1], [3, 1, 1]])
1422
+ sage: SP
1423
+ [4, 2, 2, 1] / [3, 1, 1]
1424
+ sage: SkewPartitions.options.display="lists"
1425
+ sage: SP
1426
+ [[4, 2, 2, 1], [3, 1, 1]]
1427
+
1428
+ Changing the ``convention`` for skew partitions also changes the
1429
+ ``convention`` option for partitions and tableaux and vice versa::
1430
+
1431
+ sage: SkewPartitions.options(display='diagram', convention='French')
1432
+ sage: SP
1433
+ *
1434
+ *
1435
+ *
1436
+ *
1437
+ sage: T = Tableau([[1,2,3],[4,5]])
1438
+ sage: T.pp()
1439
+ 4 5
1440
+ 1 2 3
1441
+ sage: P = Partition([4, 2, 2, 1])
1442
+ sage: P.pp()
1443
+ *
1444
+ **
1445
+ **
1446
+ ****
1447
+ sage: Tableaux.options.convention="english"
1448
+ sage: SP
1449
+ *
1450
+ *
1451
+ *
1452
+ *
1453
+ sage: T.pp()
1454
+ 1 2 3
1455
+ 4 5
1456
+ sage: SkewPartitions.options._reset()
1457
+ """
1458
+ NAME = 'SkewPartitions'
1459
+ module = 'sage.combinat.skew_partition'
1460
+ display = dict(default='quotient',
1461
+ description='Specifies how skew partitions should be printed',
1462
+ values=dict(lists='displayed as a pair of lists',
1463
+ quotient='displayed as a quotient of partitions',
1464
+ diagram='as a skew Ferrers diagram'),
1465
+ alias=dict(array='diagram', ferrers_diagram='diagram',
1466
+ young_diagram='diagram', pair='lists'),
1467
+ case_sensitive=False)
1468
+ latex = dict(default='young_diagram',
1469
+ description='Specifies how skew partitions should be latexed',
1470
+ values=dict(diagram='latex as a skew Ferrers diagram',
1471
+ young_diagram='latex as a skew Young diagram',
1472
+ marked='latex as a partition where the skew shape is marked'),
1473
+ alias=dict(array='diagram', ferrers_diagram='diagram'),
1474
+ case_sensitive=False)
1475
+ diagram_str = dict(link_to=(Partitions.options,'diagram_str'))
1476
+ latex_diagram_str = dict(link_to=(Partitions.options,'latex_diagram_str'))
1477
+ latex_marking_str = dict(default='X',
1478
+ description='The character used to marked the deleted cells when latexing marked partitions',
1479
+ checker=lambda char: isinstance(char, str))
1480
+ convention = dict(link_to=(Tableaux.options,'convention'))
1481
+ notation = dict(alt_name='convention')
1482
+
1483
+ Element = SkewPartition
1484
+
1485
+ def _element_constructor_(self, skp):
1486
+ """
1487
+ Construct an element of ``self``.
1488
+
1489
+ EXAMPLES::
1490
+
1491
+ sage: S = SkewPartitions()
1492
+ sage: S([[3,1], [1]])
1493
+ [3, 1] / [1]
1494
+ """
1495
+ return self.element_class(self, skp)
1496
+
1497
+ def __contains__(self, x):
1498
+ """
1499
+ TESTS::
1500
+
1501
+ sage: [[], []] in SkewPartitions()
1502
+ True
1503
+ sage: [[], [1]] in SkewPartitions()
1504
+ False
1505
+ sage: [[], [-1]] in SkewPartitions()
1506
+ False
1507
+ sage: [[], [0]] in SkewPartitions()
1508
+ True
1509
+ sage: [[3,2,1],[]] in SkewPartitions()
1510
+ True
1511
+ sage: [[3,2,1],[1]] in SkewPartitions()
1512
+ True
1513
+ sage: [[3,2,1],[2]] in SkewPartitions()
1514
+ True
1515
+ sage: [[3,2,1],[3]] in SkewPartitions()
1516
+ True
1517
+ sage: [[3,2,1],[4]] in SkewPartitions()
1518
+ False
1519
+ sage: [[3,2,1],[1,1]] in SkewPartitions()
1520
+ True
1521
+ sage: [[3,2,1],[1,2]] in SkewPartitions()
1522
+ False
1523
+ sage: [[3,2,1],[2,1]] in SkewPartitions()
1524
+ True
1525
+ sage: [[3,2,1],[2,2]] in SkewPartitions()
1526
+ True
1527
+ sage: [[3,2,1],[3,2]] in SkewPartitions()
1528
+ True
1529
+ sage: [[3,2,1],[1,1,1]] in SkewPartitions()
1530
+ True
1531
+ sage: [[7, 4, 3, 2], [8, 2, 1]] in SkewPartitions()
1532
+ False
1533
+ sage: [[7, 4, 3, 2], [5, 2, 1]] in SkewPartitions()
1534
+ True
1535
+ sage: [[4,2,1],[1,1,1,1]] in SkewPartitions()
1536
+ False
1537
+ sage: [[1,1,1,0],[1,1,0,0]] in SkewPartitions()
1538
+ True
1539
+ """
1540
+ if isinstance(x, SkewPartition):
1541
+ return True
1542
+
1543
+ try:
1544
+ if len(x) != 2:
1545
+ return False
1546
+ except TypeError:
1547
+ return False
1548
+
1549
+ p = _Partitions
1550
+ if x[0] not in p:
1551
+ return False
1552
+ if x[1] not in p:
1553
+ return False
1554
+
1555
+ if not p(x[0]).contains(p(x[1])):
1556
+ return False
1557
+
1558
+ return True
1559
+
1560
+ def from_row_and_column_length(self, rowL, colL):
1561
+ """
1562
+ Construct a partition from its row lengths and column lengths.
1563
+
1564
+ INPUT:
1565
+
1566
+ - ``rowL`` -- a composition or a list of positive integers
1567
+
1568
+ - ``colL`` -- a composition or a list of positive integers
1569
+
1570
+ OUTPUT:
1571
+
1572
+ - If it exists the unique skew-partitions with row lengths ``rowL``
1573
+ and column lengths ``colL``.
1574
+ - Raise a :exc:`ValueError` if ``rowL`` and ``colL`` are not compatible.
1575
+
1576
+ EXAMPLES::
1577
+
1578
+ sage: S = SkewPartitions()
1579
+ sage: print(S.from_row_and_column_length([3,1,2,2],[2,3,1,1,1]).diagram())
1580
+ ***
1581
+ *
1582
+ **
1583
+ **
1584
+ sage: S.from_row_and_column_length([],[])
1585
+ [] / []
1586
+ sage: S.from_row_and_column_length([1],[1])
1587
+ [1] / []
1588
+ sage: S.from_row_and_column_length([2,1],[2,1])
1589
+ [2, 1] / []
1590
+ sage: S.from_row_and_column_length([1,2],[1,2])
1591
+ [2, 2] / [1]
1592
+ sage: S.from_row_and_column_length([1,2],[1,3])
1593
+ Traceback (most recent call last):
1594
+ ...
1595
+ ValueError: sum mismatch: [1, 2] and [1, 3]
1596
+ sage: S.from_row_and_column_length([3,2,1,2],[2,3,1,1,1])
1597
+ Traceback (most recent call last):
1598
+ ...
1599
+ ValueError: incompatible row and column length : [3, 2, 1, 2] and [2, 3, 1, 1, 1]
1600
+
1601
+ .. WARNING::
1602
+
1603
+ If some rows and columns have length zero, there is no way to retrieve
1604
+ unambiguously the skew partition. We therefore raise
1605
+ a :exc:`ValueError`.
1606
+ For examples here are two skew partitions with the same row and column
1607
+ lengths::
1608
+
1609
+ sage: skp1 = SkewPartition([[2,2],[2,2]])
1610
+ sage: skp2 = SkewPartition([[2,1],[2,1]])
1611
+ sage: skp1.row_lengths(), skp1.column_lengths()
1612
+ ([0, 0], [0, 0])
1613
+ sage: skp2.row_lengths(), skp2.column_lengths()
1614
+ ([0, 0], [0, 0])
1615
+ sage: SkewPartitions().from_row_and_column_length([0,0], [0,0])
1616
+ Traceback (most recent call last):
1617
+ ...
1618
+ ValueError: row and column length must be positive
1619
+
1620
+ TESTS::
1621
+
1622
+ sage: all(SkewPartitions().from_row_and_column_length(p.row_lengths(), p.column_lengths()) == p
1623
+ ....: for i in range(7) for p in SkewPartitions(i))
1624
+ True
1625
+ """
1626
+ if sum(rowL) != sum(colL):
1627
+ raise ValueError(f"sum mismatch: {rowL} and {colL}")
1628
+ if not all(i > 0 for i in rowL) or not all(i > 0 for i in colL):
1629
+ raise ValueError("row and column length must be positive")
1630
+ if not rowL:
1631
+ return self.element_class(self, [[], []])
1632
+ colL_new = colL[:]
1633
+ resIn = []
1634
+ resOut = []
1635
+ inPOld = len(colL)
1636
+ for row in rowL:
1637
+ inP = len(colL_new) - row
1638
+ if inP < 0 or inP > inPOld:
1639
+ raise ValueError("incompatible row and column length : %s and %s" % (rowL, colL))
1640
+ inPOld = inP
1641
+ resIn.append(inP)
1642
+ resOut.append(len(colL_new))
1643
+ for iCol in range(inP, len(colL_new)):
1644
+ colL_new[iCol] -= 1
1645
+ if colL_new[iCol] < 0:
1646
+ raise ValueError("incompatible row and column length : %s and %s" % (rowL, colL))
1647
+ while colL_new and colL_new[-1] == 0:
1648
+ colL_new.pop()
1649
+ return self.element_class(self, [resOut, [x for x in resIn if x]])
1650
+
1651
+
1652
+ class SkewPartitions_all(SkewPartitions):
1653
+ """
1654
+ Class of all skew partitions.
1655
+ """
1656
+
1657
+ def __init__(self):
1658
+ """
1659
+ Initialize ``self``.
1660
+
1661
+ EXAMPLES::
1662
+
1663
+ sage: S = SkewPartitions()
1664
+ sage: TestSuite(S).run()
1665
+ """
1666
+ SkewPartitions.__init__(self, True)
1667
+
1668
+ def _repr_(self):
1669
+ """
1670
+ TESTS::
1671
+
1672
+ sage: SkewPartitions()
1673
+ Skew partitions
1674
+ """
1675
+ return "Skew partitions"
1676
+
1677
+ def __iter__(self):
1678
+ """
1679
+ Iterate over ``self``.
1680
+
1681
+ EXAMPLES::
1682
+
1683
+ sage: SP = SkewPartitions()
1684
+ sage: it = SP.__iter__()
1685
+ sage: [next(it) for x in range(10)]
1686
+ [[] / [],
1687
+ [1] / [],
1688
+ [2] / [],
1689
+ [1, 1] / [],
1690
+ [2, 1] / [1],
1691
+ [3] / [],
1692
+ [2, 1] / [],
1693
+ [3, 1] / [1],
1694
+ [2, 2] / [1],
1695
+ [3, 2] / [2]]
1696
+ """
1697
+ n = 0
1698
+ while True:
1699
+ for p in SkewPartitions_n(n):
1700
+ yield self.element_class(self, p)
1701
+ n += 1
1702
+
1703
+
1704
+ class SkewPartitions_n(SkewPartitions):
1705
+ """
1706
+ The set of skew partitions of ``n`` with overlap at least
1707
+ ``overlap`` and no empty row.
1708
+
1709
+ INPUT:
1710
+
1711
+ - ``n`` -- nonnegative integer
1712
+
1713
+ - ``overlap`` -- integer (default: `0`)
1714
+
1715
+ Caveat: this set is stable under conjugation only for ``overlap`` equal
1716
+ to 0 or 1. What exactly happens for negative overlaps is not yet
1717
+ well specified and subject to change (we may want to
1718
+ introduce vertical overlap constraints as well).
1719
+
1720
+ .. TODO::
1721
+
1722
+ As is, this set is essentially the composition of
1723
+ ``Compositions(n)`` (which give the row lengths) and
1724
+ ``SkewPartition(n, row_lengths=...)``, and one would want to
1725
+ "inherit" list and cardinality from this composition.
1726
+ """
1727
+ @staticmethod
1728
+ def __classcall_private__(cls, n, overlap=0):
1729
+ """
1730
+ Normalize input so we have a unique representation.
1731
+
1732
+ EXAMPLES::
1733
+
1734
+ sage: S = SkewPartitions(3, overlap=1)
1735
+ sage: S2 = SkewPartitions(int(3), overlap='connected')
1736
+ sage: S is S2
1737
+ True
1738
+ """
1739
+ if overlap == 'connected':
1740
+ overlap = 1
1741
+ return super().__classcall__(cls, n, overlap)
1742
+
1743
+ def __init__(self, n, overlap):
1744
+ """
1745
+ Return the set of the skew partitions of ``n`` with overlap
1746
+ at least ``overlap``, and no empty row.
1747
+
1748
+ The iteration order is not specified yet.
1749
+
1750
+ Caveat: this set is stable under conjugation only for overlap=
1751
+ 0 or 1. What exactly happens for negative overlaps is not yet
1752
+ well specified, and subject to change (we may want to
1753
+ introduce vertical overlap constraints as well). ``overlap`` would
1754
+ also better be named ``min_overlap``.
1755
+
1756
+ Todo: as is, this set is essentially the composition of
1757
+ ``Compositions(n)`` (which give the row lengths) and
1758
+ ``SkewPartition(n, row_lengths=...)``, and one would want to
1759
+ "inherit" list and cardinality from this composition.
1760
+
1761
+ INPUT:
1762
+
1763
+ - ``n`` -- nonnegative integer
1764
+ - ``overlap`` -- integer
1765
+
1766
+ TESTS::
1767
+
1768
+ sage: S = SkewPartitions(3)
1769
+ sage: TestSuite(S).run()
1770
+ sage: S = SkewPartitions(3, overlap=1)
1771
+ sage: TestSuite(S).run()
1772
+ """
1773
+ self.n = n
1774
+ self.overlap = overlap
1775
+ SkewPartitions.__init__(self, False)
1776
+
1777
+ def __contains__(self, x):
1778
+ """
1779
+ TESTS::
1780
+
1781
+ sage: [[],[]] in SkewPartitions(0)
1782
+ True
1783
+ sage: [[3,2,1], []] in SkewPartitions(6)
1784
+ True
1785
+ sage: [[3,2,1], []] in SkewPartitions(7)
1786
+ False
1787
+ sage: [[3,2,1], []] in SkewPartitions(5)
1788
+ False
1789
+ sage: [[7, 4, 3, 2], [8, 2, 1]] in SkewPartitions(8)
1790
+ False
1791
+ sage: [[7, 4, 3, 2], [5, 2, 1]] in SkewPartitions(8)
1792
+ False
1793
+ sage: [[7, 4, 3, 2], [5, 2, 1]] in SkewPartitions(5)
1794
+ False
1795
+ sage: [[7, 4, 3, 2], [5, 2, 1]] in SkewPartitions(5, overlap=-1)
1796
+ False
1797
+ sage: [[7, 4, 3, 2], [5, 2, 1]] in SkewPartitions(8, overlap=-1)
1798
+ True
1799
+ sage: [[7, 4, 3, 2], [5, 2, 1]] in SkewPartitions(8, overlap=0)
1800
+ False
1801
+ sage: [[7, 4, 3, 2], [5, 2, 1]] in SkewPartitions(8, overlap='connected')
1802
+ False
1803
+ sage: [[7, 4, 3, 2], [5, 2, 1]] in SkewPartitions(8, overlap=-2)
1804
+ True
1805
+ """
1806
+ return x in SkewPartitions() \
1807
+ and sum(x[0])-sum(x[1]) == self.n \
1808
+ and self.overlap <= SkewPartition(x).overlap()
1809
+
1810
+ def _repr_(self):
1811
+ """
1812
+ TESTS::
1813
+
1814
+ sage: SkewPartitions(3)
1815
+ Skew partitions of 3
1816
+ sage: SkewPartitions(3, overlap=1)
1817
+ Skew partitions of 3 with a minimum overlap of 1
1818
+ """
1819
+ string = "Skew partitions of %s" % self.n
1820
+ if self.overlap:
1821
+ string += " with a minimum overlap of %s" % self.overlap
1822
+ return string
1823
+
1824
+ def _count_slide(self, co, overlap=0):
1825
+ """
1826
+ Return the number of skew partitions related to the composition
1827
+ ``co`` by 'sliding'. The composition ``co`` is the list of row
1828
+ lengths of the skew partition.
1829
+
1830
+ EXAMPLES::
1831
+
1832
+ sage: s = SkewPartitions(3)
1833
+ sage: s._count_slide([2,1])
1834
+ 2
1835
+ sage: [ sp for sp in s if sp.row_lengths() == [2,1] ]
1836
+ [[2, 1] / [], [3, 1] / [1]]
1837
+ sage: s = SkewPartitions(3, overlap=1)
1838
+ sage: s._count_slide([2,1], overlap=1)
1839
+ 1
1840
+ sage: [ sp for sp in s if sp.row_lengths() == [2,1] ]
1841
+ [[2, 1] / []]
1842
+ """
1843
+ result = 1
1844
+ shift = 1 - overlap
1845
+ for i in range(len(co) - 1):
1846
+ result *= min(co[i], co[i + 1]) + shift
1847
+ return result
1848
+
1849
+ def cardinality(self):
1850
+ """
1851
+ Return the number of skew partitions of the integer `n`
1852
+ (with given overlap, if specified; and with no empty rows before
1853
+ the last row).
1854
+
1855
+ EXAMPLES::
1856
+
1857
+ sage: SkewPartitions(0).cardinality()
1858
+ 1
1859
+ sage: SkewPartitions(4).cardinality()
1860
+ 28
1861
+ sage: SkewPartitions(5).cardinality()
1862
+ 87
1863
+ sage: SkewPartitions(4, overlap=1).cardinality()
1864
+ 9
1865
+ sage: SkewPartitions(5, overlap=1).cardinality()
1866
+ 20
1867
+ sage: s = SkewPartitions(5, overlap=-1)
1868
+ sage: s.cardinality() == len(s.list())
1869
+ True
1870
+ """
1871
+ if self.n == 0:
1872
+ return ZZ.one()
1873
+
1874
+ if self.overlap > 0:
1875
+ gg = Compositions(self.n, min_part=max(1, self.overlap))
1876
+ else:
1877
+ gg = Compositions(self.n)
1878
+
1879
+ sum_a = 0
1880
+ for co in gg:
1881
+ sum_a += self._count_slide(co, overlap=self.overlap)
1882
+
1883
+ return ZZ(sum_a)
1884
+
1885
+ def __iter__(self):
1886
+ """
1887
+ Iterate through the skew partitions of `n`
1888
+ (with given overlap, if specified; and with no empty rows before
1889
+ the last row).
1890
+
1891
+ EXAMPLES::
1892
+
1893
+ sage: SkewPartitions(3).list()
1894
+ [[3] / [],
1895
+ [2, 1] / [],
1896
+ [3, 1] / [1],
1897
+ [2, 2] / [1],
1898
+ [3, 2] / [2],
1899
+ [1, 1, 1] / [],
1900
+ [2, 2, 1] / [1, 1],
1901
+ [2, 1, 1] / [1],
1902
+ [3, 2, 1] / [2, 1]]
1903
+
1904
+ sage: SkewPartitions(3, overlap=0).list()
1905
+ [[3] / [],
1906
+ [2, 1] / [],
1907
+ [3, 1] / [1],
1908
+ [2, 2] / [1],
1909
+ [3, 2] / [2],
1910
+ [1, 1, 1] / [],
1911
+ [2, 2, 1] / [1, 1],
1912
+ [2, 1, 1] / [1],
1913
+ [3, 2, 1] / [2, 1]]
1914
+ sage: SkewPartitions(3, overlap=1).list()
1915
+ [[3] / [],
1916
+ [2, 1] / [],
1917
+ [2, 2] / [1],
1918
+ [1, 1, 1] / []]
1919
+ sage: SkewPartitions(3, overlap=2).list()
1920
+ [[3] / []]
1921
+ sage: SkewPartitions(3, overlap=3).list()
1922
+ [[3] / []]
1923
+ sage: SkewPartitions(3, overlap=4).list()
1924
+ []
1925
+ """
1926
+ for co in Compositions(self.n, min_part=max(1, self.overlap)):
1927
+ for sp in SkewPartitions(row_lengths=co, overlap=self.overlap):
1928
+ yield self.element_class(self, sp)
1929
+
1930
+ ######################################
1931
+ # Skew Partitions (from row lengths) #
1932
+ ######################################
1933
+
1934
+
1935
+ class SkewPartitions_rowlengths(SkewPartitions):
1936
+ """
1937
+ All skew partitions with given row lengths.
1938
+ """
1939
+ @staticmethod
1940
+ def __classcall_private__(cls, co, overlap=0):
1941
+ """
1942
+ Normalize input to ensure a unique representation.
1943
+
1944
+ EXAMPLES::
1945
+
1946
+ sage: S = SkewPartitions(row_lengths=[2,1], overlap=1)
1947
+ sage: S2 = SkewPartitions(row_lengths=(2,1), overlap='connected')
1948
+ sage: S is S2
1949
+ True
1950
+ """
1951
+ co = Compositions()(co)
1952
+ if overlap == 'connected':
1953
+ overlap = 1
1954
+ return super().__classcall__(cls, co, overlap)
1955
+
1956
+ def __init__(self, co, overlap):
1957
+ """
1958
+ TESTS::
1959
+
1960
+ sage: S = SkewPartitions(row_lengths=[2,1])
1961
+ sage: TestSuite(S).run()
1962
+ """
1963
+ self.co = co
1964
+ self.overlap = overlap
1965
+ SkewPartitions.__init__(self, False)
1966
+
1967
+ def __contains__(self, x):
1968
+ """
1969
+ EXAMPLES::
1970
+
1971
+ sage: [[4,3,1],[2]] in SkewPartitions(row_lengths=[2,3,1])
1972
+ True
1973
+ sage: [[4,3,1],[2]] in SkewPartitions(row_lengths=[2,1,3])
1974
+ False
1975
+ sage: [[5,4,3,1],[3,3,1]] in SkewPartitions(row_lengths=[2,1,1,2])
1976
+ False
1977
+ sage: [[5,4,3,1],[3,3,1]] in SkewPartitions(row_lengths=[2,1,2,1])
1978
+ True
1979
+ """
1980
+ if x in SkewPartitions():
1981
+ o = x[0]
1982
+ i = x[1]+[0]*(len(x[0])-len(x[1]))
1983
+ return [u[0]-u[1] for u in zip(o,i)] == self.co
1984
+ return False
1985
+
1986
+ def _repr_(self):
1987
+ """
1988
+ TESTS::
1989
+
1990
+ sage: SkewPartitions(row_lengths=[2,1])
1991
+ Skew partitions with row lengths [2, 1]
1992
+ """
1993
+ return "Skew partitions with row lengths %s" % self.co
1994
+
1995
+ def _from_row_lengths_aux(self, sskp, ck_1, ck, overlap=0):
1996
+ """
1997
+ EXAMPLES::
1998
+
1999
+ sage: s = SkewPartitions(row_lengths=[2,1])
2000
+ sage: list(s._from_row_lengths_aux([[1], []], 1, 1, overlap=0))
2001
+ [[1, 1] / [], [2, 1] / [1]]
2002
+ sage: list(s._from_row_lengths_aux([[1, 1], []], 1, 1, overlap=0))
2003
+ [[1, 1, 1] / [], [2, 2, 1] / [1, 1]]
2004
+ sage: list(s._from_row_lengths_aux([[2, 1], [1]], 1, 1, overlap=0))
2005
+ [[2, 1, 1] / [1], [3, 2, 1] / [2, 1]]
2006
+ sage: list(s._from_row_lengths_aux([[1], []], 1, 2, overlap=0))
2007
+ [[2, 2] / [1], [3, 2] / [2]]
2008
+ sage: list(s._from_row_lengths_aux([[2], []], 2, 1, overlap=0))
2009
+ [[2, 1] / [], [3, 1] / [1]]
2010
+ """
2011
+ nn = min(ck_1, ck)
2012
+ mm = max(0, ck-ck_1)
2013
+ # nn should be >= 0. In the case of the positive overlap,
2014
+ # the min_part condition insures ck>=overlap for all k
2015
+
2016
+ nn -= overlap
2017
+ for i in range(nn+1):
2018
+ skp1, skp2 = sskp
2019
+ skp2 += [0]*(len(skp1)-len(skp2))
2020
+ skp1 = [x + i + mm for x in skp1]
2021
+ skp1 += [ck]
2022
+ skp2 = [x + i + mm for x in skp2]
2023
+ skp2 = [x for x in skp2 if x != 0]
2024
+ yield SkewPartition([skp1, skp2])
2025
+
2026
+ def __iter__(self):
2027
+ """
2028
+ Iterate through all the skew partitions that have row lengths
2029
+ given by the composition ``self.co``.
2030
+
2031
+ EXAMPLES::
2032
+
2033
+ sage: SkewPartitions(row_lengths=[2,2]).list()
2034
+ [[2, 2] / [], [3, 2] / [1], [4, 2] / [2]]
2035
+ sage: SkewPartitions(row_lengths=[2,2], overlap=1).list()
2036
+ [[2, 2] / [], [3, 2] / [1]]
2037
+ """
2038
+ if self.co == []:
2039
+ yield self.element_class(self, [[],[]])
2040
+ return
2041
+
2042
+ nn = len(self.co)
2043
+ if nn == 1:
2044
+ yield self.element_class(self, [[self.co[0]],[]])
2045
+ return
2046
+
2047
+ for sskp in SkewPartitions(row_lengths=self.co[:-1], overlap=self.overlap):
2048
+ for sp in self._from_row_lengths_aux(sskp, self.co[-2], self.co[-1], self.overlap):
2049
+ yield self.element_class(self, sp)
2050
+
2051
+
2052
+ from sage.misc.persist import register_unpickle_override
2053
+ register_unpickle_override('sage.combinat.skew_partition', 'SkewPartition_class', SkewPartition)