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,2063 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ # sage.doctest: needs sage.combinat sage.modules
3
+ r"""
4
+ Alternating sign matrices
5
+
6
+ AUTHORS:
7
+
8
+ - Mike Hansen (2007): Initial version
9
+ - Pierre Cange, Luis Serrano (2012): Added monotone triangles
10
+ - Travis Scrimshaw (2013-28-03): Added element class for ASM's and made
11
+ :class:`MonotoneTriangles` inherit from :class:`GelfandTsetlinPatterns`
12
+ - Jessica Striker (2013): Added additional methods
13
+ - Vincent Delecroix (2017): cleaning
14
+ """
15
+ # ****************************************************************************
16
+ # Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,
17
+ # 2012 Pierre Cagne <pierre.cagne@ens.fr>,
18
+ # Luis Serrano <luisgui.serrano@gmail.com>
19
+ # 2013 Travis Scrimshaw <tscrim@ucdavis.edu>
20
+ # 2013 Jessica Striker <jessicapalencia@gmail.com>
21
+ # 2017 Vincent Delecroix <20100.delecroix@gmail.com>
22
+ #
23
+ # Distributed under the terms of the GNU General Public License (GPL)
24
+ #
25
+ # This code is distributed in the hope that it will be useful, but
26
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
27
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28
+ # General Public License for more details.
29
+ #
30
+ # The full text of the GPL is available at:
31
+ #
32
+ # https://www.gnu.org/licenses/
33
+ # ****************************************************************************
34
+
35
+ import copy
36
+ from sage.misc.classcall_metaclass import ClasscallMetaclass
37
+ from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass
38
+ from sage.misc.flatten import flatten
39
+ from sage.misc.misc_c import prod
40
+ from sage.structure.unique_representation import UniqueRepresentation
41
+ from sage.structure.parent import Parent
42
+ from sage.structure.element import Element
43
+ from sage.structure.richcmp import richcmp
44
+ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
45
+ from sage.matrix.matrix_space import MatrixSpace
46
+ from sage.matrix.constructor import matrix
47
+ from sage.modules.free_module_element import zero_vector
48
+ from sage.misc.cachefunc import cached_method
49
+ from sage.misc.lazy_import import lazy_import
50
+ from sage.rings.integer_ring import ZZ
51
+ from sage.arith.misc import factorial
52
+ from sage.rings.integer import Integer
53
+ from sage.combinat.gelfand_tsetlin_patterns import GelfandTsetlinPatternsTopRow
54
+ from sage.combinat.combinatorial_map import combinatorial_map
55
+ from sage.combinat.non_decreasing_parking_function import NonDecreasingParkingFunction
56
+ from sage.combinat.permutation import Permutation
57
+ from sage.combinat.six_vertex_model import SquareIceModel
58
+
59
+ lazy_import('sage.combinat.posets.lattices', 'LatticePoset')
60
+
61
+
62
+ def _inplace_height_function_gyration(hf):
63
+ k = hf.nrows() - 1
64
+ for i in range(1,k):
65
+ for j in range(1,k):
66
+ if (i+j) % 2 == 0 \
67
+ and hf[i-1,j] == hf[i+1,j] == hf[i,j+1] == hf[i,j-1]:
68
+ if hf[i,j] < hf[i+1,j]:
69
+ hf[i,j] += 2
70
+ else:
71
+ hf[i,j] -= 2
72
+ for i in range(1,k):
73
+ for j in range(1,k):
74
+ if (i+j) % 2 == 1 \
75
+ and hf[i-1,j] == hf[i+1,j] == hf[i,j+1] == hf[i,j-1]:
76
+ if hf[i,j] < hf[i+1,j]:
77
+ hf[i,j] += 2
78
+ else:
79
+ hf[i,j] -= 2
80
+
81
+
82
+ class AlternatingSignMatrix(Element,
83
+ metaclass=InheritComparisonClasscallMetaclass):
84
+ r"""
85
+ An alternating sign matrix.
86
+
87
+ An alternating sign matrix is a square matrix of `0`'s, `1`'s and `-1`'s
88
+ such that the sum of each row and column is `1` and the nonzero
89
+ entries in each row and column alternate in sign.
90
+
91
+ These were introduced in [MRR1983]_.
92
+ """
93
+ @staticmethod
94
+ def __classcall_private__(cls, asm, check=True):
95
+ """
96
+ Create an ASM.
97
+
98
+ EXAMPLES::
99
+
100
+ sage: AlternatingSignMatrix([[1, 0, 0],[0, 1, 0],[0, 0, 1]])
101
+ [1 0 0]
102
+ [0 1 0]
103
+ [0 0 1]
104
+
105
+ sage: AlternatingSignMatrix([[0, 1, 0],[1, -1, 1],[0, 1, 0]])
106
+ [ 0 1 0]
107
+ [ 1 -1 1]
108
+ [ 0 1 0]
109
+
110
+ TESTS:
111
+
112
+ Check that :issue:`22032` is fixed::
113
+
114
+ sage: AlternatingSignMatrix([])
115
+ []
116
+
117
+ Check dimension 1::
118
+
119
+ sage: AlternatingSignMatrix([1])
120
+ [1]
121
+
122
+ sage: AlternatingSignMatrix([-1])
123
+ Traceback (most recent call last):
124
+ ...
125
+ ValueError: invalid alternating sign matrix
126
+ """
127
+ asm = matrix(ZZ, asm)
128
+ if not asm.is_square():
129
+ raise ValueError("the alternating sign matrices must be square")
130
+ return AlternatingSignMatrices(asm.nrows())(asm, check=check)
131
+
132
+ def __init__(self, parent, asm):
133
+ """
134
+ Initialize ``self``.
135
+
136
+ EXAMPLES::
137
+
138
+ sage: A = AlternatingSignMatrices(3)
139
+ sage: elt = A([[1, 0, 0],[0, 1, 0],[0, 0, 1]])
140
+ sage: TestSuite(elt).run()
141
+ """
142
+ self._matrix = asm
143
+ Element.__init__(self, parent)
144
+
145
+ def __hash__(self):
146
+ r"""
147
+ TESTS::
148
+
149
+ sage: A = AlternatingSignMatrices(3)
150
+ sage: elt = A([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
151
+ sage: hash(elt)
152
+ 1
153
+ """
154
+ return hash(self._matrix)
155
+
156
+ def _repr_(self):
157
+ """
158
+ Return a string representation of ``self``.
159
+
160
+ EXAMPLES::
161
+
162
+ sage: A = AlternatingSignMatrices(3)
163
+ sage: A([[1, 0, 0],[0, 1, 0],[0, 0, 1]])
164
+ [1 0 0]
165
+ [0 1 0]
166
+ [0 0 1]
167
+ """
168
+ return repr(self._matrix)
169
+
170
+ def _unicode_art_(self):
171
+ """
172
+ Unicode art representation of ``self``.
173
+
174
+ TESTS::
175
+
176
+ sage: A = AlternatingSignMatrices(3)
177
+ sage: M = A([[1, 0, 0],[0, 1, 0],[0, 0, 1]])
178
+ sage: M._unicode_art_()
179
+ ⎛1 0 0⎞
180
+ ⎜0 1 0⎟
181
+ ⎝0 0 1⎠
182
+ """
183
+ return self._matrix._unicode_art_()
184
+
185
+ def _richcmp_(self, other, op):
186
+ """
187
+ Do the comparison.
188
+
189
+ EXAMPLES::
190
+
191
+ sage: A = AlternatingSignMatrices(3)
192
+ sage: M = A([[1, 0, 0],[0, 1, 0],[0, 0, 1]])
193
+ sage: M == A([[1, 0, 0],[0, 1, 0],[0, 0, 1]])
194
+ True
195
+ sage: M == A([[1, 0, 0],[0, 0, 1],[0, 1, 0]])
196
+ False
197
+ sage: A = AlternatingSignMatrices(3)
198
+ sage: M = A([[1, 0, 0],[0, 1, 0],[0, 0, 1]])
199
+ sage: M != A([[1, 0, 0],[0, 1, 0],[0, 0, 1]])
200
+ False
201
+ sage: M != A([[1, 0, 0],[0, 0, 1],[0, 1, 0]])
202
+ True
203
+
204
+ sage: A = AlternatingSignMatrices(3)
205
+ sage: M = A([[1, 0, 0],[0, 1, 0],[0, 0, 1]])
206
+ sage: M <= A([[1, 0, 0],[0, 1, 0],[0, 0, 1]])
207
+ True
208
+ sage: M <= A([[1, 0, 0],[0, 0, 1],[0, 1, 0]])
209
+ False
210
+ """
211
+ return richcmp(self._matrix, other._matrix, op)
212
+
213
+ def _latex_(self):
214
+ r"""
215
+ Return a `\LaTeX` representation of ``self``.
216
+
217
+ EXAMPLES::
218
+
219
+ sage: A = AlternatingSignMatrices(3)
220
+ sage: latex(A([[1, 0, 0],[0, 1, 0],[0, 0, 1]]))
221
+ \left(\begin{array}{rrr}
222
+ 1 & 0 & 0 \\
223
+ 0 & 1 & 0 \\
224
+ 0 & 0 & 1
225
+ \end{array}\right)
226
+ """
227
+ return self._matrix._latex_()
228
+
229
+ def to_matrix(self):
230
+ """
231
+ Return ``self`` as a regular matrix.
232
+
233
+ EXAMPLES::
234
+
235
+ sage: A = AlternatingSignMatrices(3)
236
+ sage: asm = A([[1, 0, 0],[0, 1, 0],[0, 0, 1]])
237
+ sage: m = asm.to_matrix(); m
238
+ [1 0 0]
239
+ [0 1 0]
240
+ [0 0 1]
241
+ sage: m.parent()
242
+ Full MatrixSpace of 3 by 3 dense matrices over Integer Ring
243
+ """
244
+ return copy.copy(self._matrix)
245
+
246
+ @combinatorial_map(name='to monotone triangle')
247
+ def to_monotone_triangle(self):
248
+ r"""
249
+ Return a monotone triangle from ``self``.
250
+
251
+ EXAMPLES::
252
+
253
+ sage: A = AlternatingSignMatrices(3)
254
+ sage: A([[1, 0, 0],[0, 1, 0],[0, 0, 1]]).to_monotone_triangle()
255
+ [[3, 2, 1], [2, 1], [1]]
256
+ sage: asm = A([[0, 1, 0],[1, -1, 1],[0, 1, 0]])
257
+ sage: asm.to_monotone_triangle()
258
+ [[3, 2, 1], [3, 1], [2]]
259
+ sage: asm = A([[0, 0, 1],[1, 0, 0],[0, 1, 0]])
260
+ sage: asm.to_monotone_triangle()
261
+ [[3, 2, 1], [3, 1], [3]]
262
+ sage: A.from_monotone_triangle(asm.to_monotone_triangle()) == asm
263
+ True
264
+ """
265
+ n = self._matrix.nrows()
266
+ triangle = [0] * n
267
+ add_row = zero_vector(ZZ, n)
268
+ for j, row in enumerate(self._matrix):
269
+ add_row = row + add_row
270
+ triangle[n - 1 - j] = [i + 1 for i in range(n - 1, -1, -1)
271
+ if add_row[i] == 1]
272
+ return MonotoneTriangles(n)(triangle)
273
+
274
+ @combinatorial_map(name='rotate counterclockwise')
275
+ def rotate_ccw(self):
276
+ r"""
277
+ Return the counterclockwise quarter turn rotation of ``self``.
278
+
279
+ EXAMPLES::
280
+
281
+ sage: A = AlternatingSignMatrices(3)
282
+ sage: A([[1, 0, 0],[0, 1, 0],[0, 0, 1]]).rotate_ccw()
283
+ [0 0 1]
284
+ [0 1 0]
285
+ [1 0 0]
286
+ sage: asm = A([[0, 0, 1],[1, 0, 0],[0, 1, 0]])
287
+ sage: asm.rotate_ccw()
288
+ [1 0 0]
289
+ [0 0 1]
290
+ [0 1 0]
291
+ """
292
+ li = list(self._matrix.transpose())
293
+ li.reverse()
294
+ return AlternatingSignMatrix(li)
295
+
296
+ def inversion_number(self):
297
+ r"""
298
+ Return the inversion number of ``self``.
299
+
300
+ If we denote the entries of the alternating sign matrix as `a_{i,j}`,
301
+ the inversion number is defined as `\sum_{i>k}\sum_{j<l}a_{i,j}a_{k,l}`.
302
+ When restricted to permutation matrices, this gives the usual inversion
303
+ number of the permutation.
304
+
305
+ This definition is equivalent to the one given in [MRR1983]_.
306
+
307
+ EXAMPLES::
308
+
309
+ sage: A = AlternatingSignMatrices(3)
310
+ sage: A([[1, 0, 0],[0, 1, 0],[0, 0, 1]]).inversion_number()
311
+ 0
312
+ sage: asm = A([[0, 0, 1],[1, 0, 0],[0, 1, 0]])
313
+ sage: asm.inversion_number()
314
+ 2
315
+ sage: asm = A([[0, 1, 0],[1, -1, 1],[0, 1, 0]])
316
+ sage: asm.inversion_number()
317
+ 2
318
+ sage: P = Permutations(5)
319
+ sage: all(p.number_of_inversions()==AlternatingSignMatrix(p.to_matrix()).inversion_number() for p in P)
320
+ True
321
+ """
322
+ inversion_num = 0
323
+ asm_matrix = self.to_matrix()
324
+ nonzero_cells = asm_matrix.nonzero_positions()
325
+ for (i, j) in nonzero_cells:
326
+ for (k, l) in nonzero_cells:
327
+ if i > k and j < l:
328
+ inversion_num += asm_matrix[i][j] * asm_matrix[k][l]
329
+ return inversion_num
330
+
331
+ @combinatorial_map(name='rotate clockwise')
332
+ def rotate_cw(self):
333
+ r"""
334
+ Return the clockwise quarter turn rotation of ``self``.
335
+
336
+ EXAMPLES::
337
+
338
+ sage: A = AlternatingSignMatrices(3)
339
+ sage: A([[1, 0, 0],[0, 1, 0],[0, 0, 1]]).rotate_cw()
340
+ [0 0 1]
341
+ [0 1 0]
342
+ [1 0 0]
343
+ sage: asm = A([[0, 0, 1],[1, 0, 0],[0, 1, 0]])
344
+ sage: asm.rotate_cw()
345
+ [0 1 0]
346
+ [1 0 0]
347
+ [0 0 1]
348
+ """
349
+ li = list(self._matrix.transpose())
350
+ li.reverse()
351
+ return AlternatingSignMatrix(matrix(li).transpose().antitranspose())
352
+
353
+ @combinatorial_map(name='transpose')
354
+ def transpose(self):
355
+ r"""
356
+ Return ``self`` transposed.
357
+
358
+ EXAMPLES::
359
+
360
+ sage: A = AlternatingSignMatrices(3)
361
+ sage: A([[1, 0, 0],[0, 1, 0],[0, 0, 1]]).transpose()
362
+ [1 0 0]
363
+ [0 1 0]
364
+ [0 0 1]
365
+ sage: asm = A([[0, 0, 1],[1, 0, 0],[0, 1, 0]])
366
+ sage: asm.transpose()
367
+ [0 1 0]
368
+ [0 0 1]
369
+ [1 0 0]
370
+ """
371
+ return AlternatingSignMatrix(self._matrix.transpose())
372
+
373
+ def corner_sum_matrix(self):
374
+ r"""
375
+ Return the corner sum matrix of ``self``.
376
+
377
+ EXAMPLES::
378
+
379
+ sage: A = AlternatingSignMatrices(3)
380
+ sage: A([[1, 0, 0],[0, 1, 0],[0, 0, 1]]).corner_sum_matrix()
381
+ [0 0 0 0]
382
+ [0 1 1 1]
383
+ [0 1 2 2]
384
+ [0 1 2 3]
385
+ sage: asm = A([[0, 1, 0],[1, -1, 1],[0, 1, 0]])
386
+ sage: asm.corner_sum_matrix()
387
+ [0 0 0 0]
388
+ [0 0 1 1]
389
+ [0 1 1 2]
390
+ [0 1 2 3]
391
+ sage: asm = A([[0, 0, 1],[1, 0, 0],[0, 1, 0]])
392
+ sage: asm.corner_sum_matrix()
393
+ [0 0 0 0]
394
+ [0 0 0 1]
395
+ [0 1 1 2]
396
+ [0 1 2 3]
397
+
398
+ TESTS:
399
+
400
+ Some non-symmetric tests::
401
+
402
+ sage: A = AlternatingSignMatrices(3)
403
+ sage: asm = A([[0, 1, 0], [0, 0, 1], [1, 0, 0]])
404
+ sage: asm.corner_sum_matrix()
405
+ [0 0 0 0]
406
+ [0 0 1 1]
407
+ [0 0 1 2]
408
+ [0 1 2 3]
409
+ sage: B = AlternatingSignMatrices(4)
410
+ sage: asm = B([[0, 0, 1, 0], [1, 0, 0, 0], [0, 1, -1, 1], [0, 0, 1, 0]])
411
+ sage: asm.corner_sum_matrix()
412
+ [0 0 0 0 0]
413
+ [0 0 0 1 1]
414
+ [0 1 1 2 2]
415
+ [0 1 2 2 3]
416
+ [0 1 2 3 4]
417
+ """
418
+ asm = self._matrix
419
+ n = asm.nrows()
420
+ ans = matrix(ZZ, n + 1)
421
+ col_sum = [ZZ.zero()] * n
422
+ for i in range(n):
423
+ for j in range(n):
424
+ col_sum[j] += asm[i, j]
425
+ ans[i + 1, j + 1] = ans[i + 1, j] + col_sum[j]
426
+ return ans
427
+
428
+ def height_function(self):
429
+ r"""
430
+ Return the height function from ``self``.
431
+
432
+ A height function
433
+ corresponding to an `n \times n` ASM is an `(n+1) \times (n+1)` matrix
434
+ such that the first row is `0, 1, \ldots, n`, the last row is
435
+ `n, n-1, \ldots, 1, 0`, and the difference between adjacent entries
436
+ is 1.
437
+
438
+ EXAMPLES::
439
+
440
+ sage: A = AlternatingSignMatrices(3)
441
+ sage: A([[1, 0, 0],[0, 1, 0],[0, 0, 1]]).height_function()
442
+ [0 1 2 3]
443
+ [1 0 1 2]
444
+ [2 1 0 1]
445
+ [3 2 1 0]
446
+ sage: asm = A([[0, 1, 0],[1, -1, 1],[0, 1, 0]])
447
+ sage: asm.height_function()
448
+ [0 1 2 3]
449
+ [1 2 1 2]
450
+ [2 1 2 1]
451
+ [3 2 1 0]
452
+ sage: asm = A([[0, 0, 1],[1, 0, 0],[0, 1, 0]])
453
+ sage: asm.height_function()
454
+ [0 1 2 3]
455
+ [1 2 1 2]
456
+ [2 3 2 1]
457
+ [3 2 1 0]
458
+
459
+ sage: A = AlternatingSignMatrices(4)
460
+ sage: all(A.from_height_function(a.height_function()) == a for a in A)
461
+ True
462
+ """
463
+ asm = self._matrix
464
+ n = asm.nrows()
465
+ ans = matrix(ZZ, n + 1)
466
+ for i in range(1, n + 1):
467
+ ans[0, i] = ans[i, 0] = i
468
+ col_sum = [ZZ.zero()] * n
469
+ for i in range(n):
470
+ for j in range(n):
471
+ col_sum[j] += asm[i, j]
472
+ ans[j+1, i+1] = ans[j, i+1] + 1 - 2 * col_sum[j]
473
+ return ans
474
+
475
+ def to_six_vertex_model(self):
476
+ r"""
477
+ Return the six vertex model configuration from ``self``.
478
+
479
+ This method calls :meth:`sage.combinat.six_vertex_model.from_alternating_sign_matrix`.
480
+
481
+ EXAMPLES::
482
+
483
+ sage: asm = AlternatingSignMatrix([[0,1,0],[1,-1,1],[0,1,0]])
484
+ sage: asm.to_six_vertex_model()
485
+ ^ ^ ^
486
+ | | |
487
+ --> # -> # <- # <--
488
+ ^ | ^
489
+ | V |
490
+ --> # <- # -> # <--
491
+ | ^ |
492
+ V | V
493
+ --> # -> # <- # <--
494
+ | | |
495
+ V V V
496
+
497
+ TESTS::
498
+
499
+ sage: ASM = AlternatingSignMatrices(5)
500
+ sage: all((x.to_six_vertex_model()).to_alternating_sign_matrix() == x
501
+ ....: for x in ASM)
502
+ True
503
+ """
504
+ asm = self.to_matrix()
505
+ n = asm.nrows()
506
+ M = SquareIceModel(n)
507
+ return M.from_alternating_sign_matrix(self)
508
+
509
+ def to_fully_packed_loop(self):
510
+ r"""
511
+ Return the fully packed loop configuration from ``self``.
512
+
513
+ .. SEEALSO::
514
+
515
+ :class:`FullyPackedLoop`
516
+
517
+ EXAMPLES::
518
+
519
+ sage: asm = AlternatingSignMatrix([[1,0,0],[0,1,0],[0,0,1]])
520
+ sage: fpl = asm.to_fully_packed_loop()
521
+ sage: fpl
522
+ │ │
523
+ │ │
524
+ + + ── +
525
+ │ │
526
+ │ │
527
+ ── + + + ──
528
+ │ │
529
+ │ │
530
+ + ── + +
531
+ │ │
532
+ │ │
533
+ """
534
+ from sage.combinat.fully_packed_loop import FullyPackedLoop
535
+ return FullyPackedLoop(self)
536
+
537
+ def link_pattern(self):
538
+ """
539
+ Return the link pattern corresponding to the fully packed loop
540
+ corresponding to ``self``.
541
+
542
+ EXAMPLES:
543
+
544
+ We can extract the underlying link pattern (a non-crossing
545
+ partition) from a fully packed loop::
546
+
547
+ sage: A = AlternatingSignMatrix([[0, 1, 0], [1, -1, 1], [0, 1, 0]])
548
+ sage: A.link_pattern()
549
+ [(1, 2), (3, 6), (4, 5)]
550
+
551
+ sage: B = AlternatingSignMatrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
552
+ sage: B.link_pattern()
553
+ [(1, 6), (2, 5), (3, 4)]
554
+ """
555
+ return self.to_fully_packed_loop().link_pattern()
556
+
557
+ @combinatorial_map(name='gyration')
558
+ def gyration(self):
559
+ r"""
560
+ Return the alternating sign matrix obtained by applying gyration
561
+ to the height function in bijection with ``self``.
562
+
563
+ Gyration acts on height functions as follows. Go through the entries of
564
+ the matrix, first those for which the sum of the row and column indices
565
+ is even, then for those for which it is odd, and increment or decrement
566
+ the squares by 2 wherever possible such that the resulting matrix is
567
+ still a height function. Gyration was first defined in [Wie2000]_ as
568
+ an action on fully-packed loops.
569
+
570
+ EXAMPLES::
571
+
572
+ sage: A = AlternatingSignMatrices(3)
573
+ sage: A([[1, 0, 0],[0, 1, 0],[0, 0, 1]]).gyration()
574
+ [0 0 1]
575
+ [0 1 0]
576
+ [1 0 0]
577
+ sage: asm = A([[0, 1, 0],[1, -1, 1],[0, 1, 0]])
578
+ sage: asm.gyration()
579
+ [1 0 0]
580
+ [0 1 0]
581
+ [0 0 1]
582
+ sage: asm = A([[0, 0, 1],[1, 0, 0],[0, 1, 0]])
583
+ sage: asm.gyration()
584
+ [0 1 0]
585
+ [0 0 1]
586
+ [1 0 0]
587
+ sage: A = AlternatingSignMatrices(3)
588
+ sage: A([[1, 0, 0],[0, 1, 0],[0, 0, 1]]).gyration().gyration()
589
+ [ 0 1 0]
590
+ [ 1 -1 1]
591
+ [ 0 1 0]
592
+ sage: A([[1, 0, 0],[0, 1, 0],[0, 0, 1]]).gyration().gyration().gyration()
593
+ [1 0 0]
594
+ [0 1 0]
595
+ [0 0 1]
596
+
597
+ sage: A = AlternatingSignMatrices(4)
598
+ sage: M = A([[0,0,1,0],[1,0,0,0],[0,1,-1,1],[0,0,1,0]])
599
+ sage: for i in range(5):
600
+ ....: M = M.gyration()
601
+ sage: M
602
+ [1 0 0 0]
603
+ [0 0 0 1]
604
+ [0 1 0 0]
605
+ [0 0 1 0]
606
+
607
+ sage: a0 = a = AlternatingSignMatrices(5).random_element()
608
+ sage: for i in range(20):
609
+ ....: a = a.gyration()
610
+ sage: a == a0
611
+ True
612
+ """
613
+ hf = self.height_function()
614
+ _inplace_height_function_gyration(hf)
615
+ return self.parent().from_height_function(hf)
616
+
617
+ def gyration_orbit(self):
618
+ r"""
619
+ Return the gyration orbit of ``self`` (including ``self``).
620
+
621
+ EXAMPLES::
622
+
623
+ sage: AlternatingSignMatrix([[0,1,0],[1,-1,1],[0,1,0]]).gyration_orbit()
624
+ [
625
+ [ 0 1 0] [1 0 0] [0 0 1]
626
+ [ 1 -1 1] [0 1 0] [0 1 0]
627
+ [ 0 1 0], [0 0 1], [1 0 0]
628
+ ]
629
+
630
+ sage: AlternatingSignMatrix([[0,1,0,0],[1,-1,1,0],[0,1,-1,1],[0,0,1,0]]).gyration_orbit()
631
+ [
632
+ [ 0 1 0 0] [1 0 0 0] [ 0 0 1 0] [0 0 0 1]
633
+ [ 1 -1 1 0] [0 1 0 0] [ 0 1 -1 1] [0 0 1 0]
634
+ [ 0 1 -1 1] [0 0 1 0] [ 1 -1 1 0] [0 1 0 0]
635
+ [ 0 0 1 0], [0 0 0 1], [ 0 1 0 0], [1 0 0 0]
636
+ ]
637
+
638
+ sage: len(AlternatingSignMatrix([[0,1,0,0,0,0],[0,0,1,0,0,0],[1,-1,0,0,0,1],
639
+ ....: [0,1,0,0,0,0],[0,0,0,1,0,0],[0,0,0,0,1,0]]).gyration_orbit())
640
+ 12
641
+ """
642
+ hf = self.height_function()
643
+
644
+ cyc = [hf.__copy__()]
645
+ cyc[-1].set_immutable()
646
+
647
+ _inplace_height_function_gyration(hf)
648
+
649
+ while hf != cyc[0]:
650
+ cyc.append(hf.__copy__())
651
+ cyc[-1].set_immutable()
652
+ _inplace_height_function_gyration(hf)
653
+
654
+ P = self.parent()
655
+ return [P.from_height_function(hfun) for hfun in cyc]
656
+
657
+ def ASM_compatible(self, B):
658
+ r"""
659
+ Return ``True`` if ``self`` and ``B`` are compatible alternating sign
660
+ matrices in the sense of [EKLP1992]_. (If ``self`` is of size `n`, ``B``
661
+ must be of size `n+1`.)
662
+
663
+ In [EKLP1992]_, there is a notion of a pair of ASM's with sizes differing
664
+ by 1 being compatible, in the sense that they can be combined to encode
665
+ a tiling of the Aztec Diamond.
666
+
667
+ EXAMPLES::
668
+
669
+ sage: A = AlternatingSignMatrix(matrix([[0,0,1,0],[0,1,-1,1],[1,0,0,0],[0,0,1,0]]))
670
+ sage: B = AlternatingSignMatrix(matrix([[0,0,1,0,0],[0,0,0,1,0],[1,0,0,-1,1],[0,1,0,0,0],[0,0,0,1,0]]))
671
+ sage: A.ASM_compatible(B)
672
+ True
673
+ sage: A = AlternatingSignMatrix(matrix([[0,1,0],[1,-1,1],[0,1,0]]))
674
+ sage: B = AlternatingSignMatrix(matrix([[0,0,1,0],[0,0,0,1],[1,0,0,0],[0,1,0,0]]))
675
+ sage: A.ASM_compatible(B)
676
+ False
677
+ """
678
+ if B.parent()._n - self.parent()._n != 1:
679
+ raise ValueError("mismatched sizes")
680
+
681
+ AA = self.corner_sum_matrix()
682
+ BB = B.corner_sum_matrix()
683
+ for i in range(len(AA[0])):
684
+ for j in range(len(AA[0])):
685
+ if not (AA[i,j] >= BB[i,j] and AA[i,j] >= BB[i+1,j+1]-1
686
+ and AA[i,j] <= BB[i+1,j] and AA[i,j] <= BB[i,j+1]):
687
+ return False
688
+ return True
689
+
690
+ def ASM_compatible_bigger(self):
691
+ r"""
692
+ Return all ASM's compatible with ``self`` that are of size one greater
693
+ than ``self``.
694
+
695
+ Given an `n \times n` alternating sign matrix `A`, there are as many
696
+ ASM's of size `n+1` compatible with `A` as 2 raised to the power of
697
+ the number of 1s in `A` [EKLP1992]_.
698
+
699
+ EXAMPLES::
700
+
701
+ sage: A = AlternatingSignMatrix([[1,0],[0,1]])
702
+ sage: A.ASM_compatible_bigger()
703
+ [
704
+ [ 0 1 0] [1 0 0] [0 1 0] [1 0 0]
705
+ [ 1 -1 1] [0 0 1] [1 0 0] [0 1 0]
706
+ [ 0 1 0], [0 1 0], [0 0 1], [0 0 1]
707
+ ]
708
+ sage: B = AlternatingSignMatrix([[0,1],[1,0]])
709
+ sage: B.ASM_compatible_bigger()
710
+ [
711
+ [0 0 1] [0 0 1] [0 1 0] [ 0 1 0]
712
+ [0 1 0] [1 0 0] [0 0 1] [ 1 -1 1]
713
+ [1 0 0], [0 1 0], [1 0 0], [ 0 1 0]
714
+ ]
715
+
716
+ sage: B = AlternatingSignMatrix([[0,1,0],[1,-1,1],[0,1,0]])
717
+ sage: len(B.ASM_compatible_bigger()) == 2**4
718
+ True
719
+ """
720
+ n = self.parent()._n + 1
721
+ M = AlternatingSignMatrices(n)
722
+ sign = []
723
+ B = matrix(ZZ, n+1)
724
+ A = 2 * self.height_function()
725
+ for i in range(n):
726
+ for j in range(n):
727
+ A.add_to_entry(i, j, ZZ.one())
728
+ for a in range(n+1):
729
+ B[a,0] = B[0,a] = 2*a
730
+ B[a,n] = B[n,a] = 2*(n-a)
731
+
732
+ for i in range(1,n):
733
+ for j in range(1,n):
734
+ if A[i-1,j-1] == A[i,j] == A[i-1,j]-2 == A[i,j-1]-2:
735
+ B[i,j] = -A[i,j]
736
+ sign.append([i,j])
737
+ else:
738
+ s = {A[i-1,j-1]-1,A[i-1,j-1]+3} & {A[i-1,j]-3,A[i-1,j]+1} & {A[i,j-1]-3,A[i,j-1]+1} & {A[i,j]-1,A[i,j]+3}
739
+ assert len(s) == 1
740
+ B[i,j] = s.pop()
741
+
742
+ output = [B]
743
+ for b in range(len(sign)):
744
+ N = len(output)
745
+ for c in range(N):
746
+ d = copy.copy(output[c])
747
+ output[c][sign[b][0],sign[b][1]] = -output[c][sign[b][0], sign[b][1]] + 3
748
+ d[sign[b][0],sign[b][1]] = -d[sign[b][0], sign[b][1]]-1
749
+ output.append(d)
750
+
751
+ for k in range(len(output)):
752
+ output[k] = M.from_height_function(output[k]/2)
753
+ return output
754
+
755
+ def ASM_compatible_smaller(self):
756
+ r"""
757
+ Return the list of all ASMs compatible with ``self`` that are of size
758
+ one smaller than ``self``.
759
+
760
+ Given an alternating sign matrix `A` of size `n`, there are as many
761
+ ASM's of size `n-1` compatible with it as 2 raised to the power of
762
+ the number of `-1`'s in `A` [EKLP1992]_.
763
+
764
+ EXAMPLES::
765
+
766
+ sage: A = AlternatingSignMatrix(matrix([[0,0,1,0],[0,1,-1,1],[1,0,0,0],[0,0,1,0]]))
767
+ sage: A.ASM_compatible_smaller()
768
+ [
769
+ [0 0 1] [ 0 1 0]
770
+ [1 0 0] [ 1 -1 1]
771
+ [0 1 0], [ 0 1 0]
772
+ ]
773
+ sage: B = AlternatingSignMatrix(matrix([[1,0,0],[0,0,1],[0,1,0]]))
774
+ sage: B.ASM_compatible_smaller()
775
+ [
776
+ [1 0]
777
+ [0 1]
778
+ ]
779
+ """
780
+ n = self.parent()._n
781
+ M = AlternatingSignMatrices(n-1)
782
+ A = matrix(ZZ, n)
783
+ B = 2*self.height_function()[:n,:n]
784
+ sign = []
785
+ for a in range(n):
786
+ A[a,0] = 2*a + 1
787
+ A[0,a] = 2*a + 1
788
+ A[n-1,a] = 2*(n-a) - 1
789
+ A[a,n-1] = 2*(n-a) - 1
790
+
791
+ for i in range(n-1):
792
+ for j in range(n-1):
793
+ if B[i+1,j+1] == B[i,j] == B[i,j+1]+2 == B[i+1,j]+2:
794
+ A[i,j] = -B[i,j]
795
+ sign.append([i,j])
796
+ else:
797
+ A[i,j] = list({B[i,j]+1,B[i,j]-3} & {B[i,j+1]+3,B[i,j+1]-1} & {B[i+1,j]+3,B[i+1,j]-1} & {B[i+1,j+1]+1,B[i+1,j+1]-3})[0]
798
+
799
+ output = [A]
800
+ for b in range(len(sign)):
801
+ N = len(output)
802
+ for c in range(N):
803
+ d = copy.copy(output[c])
804
+ output[c][sign[b][0],sign[b][1]] = -output[c][sign[b][0], sign[b][1]]+1
805
+ d[sign[b][0],sign[b][1]] = -d[sign[b][0], sign[b][1]]-3
806
+ output.append(d)
807
+ for k in range(len(output)):
808
+ output[k] = M.from_height_function((output[k]-matrix.ones(n,n))/2)
809
+ return output
810
+
811
+ @combinatorial_map(name='to Dyck word')
812
+ def to_dyck_word(self, algorithm):
813
+ r"""
814
+ Return a Dyck word determined by the specified algorithm.
815
+
816
+ The algorithm 'last_diagonal' uses the last diagonal of the monotone
817
+ triangle corresponding to ``self``. The algorithm 'link_pattern' returns
818
+ the Dyck word in bijection with the link pattern of the fully packed
819
+ loop.
820
+
821
+ Note that these two algorithms in general yield different Dyck words for a
822
+ given alternating sign matrix.
823
+
824
+ INPUT:
825
+
826
+ - ``algorithm`` -- either ``'last_diagonal'`` or ``'link_pattern'``
827
+
828
+ EXAMPLES::
829
+
830
+ sage: A = AlternatingSignMatrices(3)
831
+ sage: A([[0,1,0],[1,0,0],[0,0,1]]).to_dyck_word(algorithm = 'last_diagonal')
832
+ [1, 1, 0, 0, 1, 0]
833
+ sage: d = A([[0,1,0],[1,-1,1],[0,1,0]]).to_dyck_word(algorithm = 'last_diagonal'); d
834
+ [1, 1, 0, 1, 0, 0]
835
+ sage: parent(d)
836
+ Complete Dyck words
837
+ sage: A = AlternatingSignMatrices(3)
838
+ sage: asm = A([[0,1,0],[1,0,0],[0,0,1]])
839
+ sage: asm.to_dyck_word(algorithm = 'link_pattern')
840
+ [1, 0, 1, 0, 1, 0]
841
+ sage: asm = A([[0,1,0],[1,-1,1],[0,1,0]])
842
+ sage: asm.to_dyck_word(algorithm = 'link_pattern')
843
+ [1, 0, 1, 1, 0, 0]
844
+ sage: A = AlternatingSignMatrices(4)
845
+ sage: asm = A([[0,0,1,0],[1,0,0,0],[0,1,-1,1],[0,0,1,0]])
846
+ sage: asm.to_dyck_word(algorithm = 'link_pattern')
847
+ [1, 1, 1, 0, 1, 0, 0, 0]
848
+ sage: asm.to_dyck_word()
849
+ Traceback (most recent call last):
850
+ ...
851
+ TypeError: ...to_dyck_word() ...argument...
852
+ sage: asm.to_dyck_word(algorithm = 'notamethod')
853
+ Traceback (most recent call last):
854
+ ...
855
+ ValueError: unknown algorithm 'notamethod'
856
+ """
857
+ if algorithm == 'last_diagonal':
858
+ MT = self.to_monotone_triangle()
859
+ nplus = self._matrix.nrows() + 1
860
+ parkfn = [nplus - row[0] for row in list(MT) if row]
861
+ return NonDecreasingParkingFunction(parkfn).to_dyck_word().reverse()
862
+
863
+ elif algorithm == 'link_pattern':
864
+ from sage.combinat.perfect_matching import PerfectMatching
865
+ from sage.combinat.dyck_word import DyckWords
866
+ p = PerfectMatching(self.link_pattern()).to_noncrossing_set_partition()
867
+ asm = self.to_matrix()
868
+ n = asm.nrows()
869
+ d = DyckWords(n)
870
+ return d.from_noncrossing_partition(p)
871
+
872
+ raise ValueError("unknown algorithm '%s'" % algorithm)
873
+
874
+ def number_negative_ones(self):
875
+ """
876
+ Return the number of entries in ``self`` equal to -1.
877
+
878
+ EXAMPLES::
879
+
880
+ sage: A = AlternatingSignMatrices(3)
881
+ sage: asm = A([[0,1,0],[1,0,0],[0,0,1]])
882
+ sage: asm.number_negative_ones()
883
+ 0
884
+ sage: asm = A([[0,1,0],[1,-1,1],[0,1,0]])
885
+ sage: asm.number_negative_ones()
886
+ 1
887
+ """
888
+ a = self._matrix
889
+ return ZZ((len(a.nonzero_positions()) - a.nrows()) // 2)
890
+
891
+ def is_permutation(self):
892
+ """
893
+ Return ``True`` if ``self`` is a permutation matrix
894
+ and ``False`` otherwise.
895
+
896
+ EXAMPLES::
897
+
898
+ sage: A = AlternatingSignMatrices(3)
899
+ sage: asm = A([[0,1,0],[1,0,0],[0,0,1]])
900
+ sage: asm.is_permutation()
901
+ True
902
+ sage: asm = A([[0,1,0],[1,-1,1],[0,1,0]])
903
+ sage: asm.is_permutation()
904
+ False
905
+ """
906
+ return self.number_negative_ones() == 0
907
+
908
+ def to_permutation(self):
909
+ """
910
+ Return the corresponding permutation if ``self`` is a permutation
911
+ matrix.
912
+
913
+ EXAMPLES::
914
+
915
+ sage: A = AlternatingSignMatrices(3)
916
+ sage: asm = A([[0,1,0],[1,0,0],[0,0,1]])
917
+ sage: p = asm.to_permutation(); p
918
+ [2, 1, 3]
919
+ sage: parent(p)
920
+ Standard permutations
921
+ sage: asm = A([[0,1,0],[1,-1,1],[0,1,0]])
922
+ sage: asm.to_permutation()
923
+ Traceback (most recent call last):
924
+ ...
925
+ ValueError: not a permutation matrix
926
+ """
927
+ if not self.is_permutation():
928
+ raise ValueError('not a permutation matrix')
929
+ asm_matrix = self.to_matrix()
930
+ return Permutation([j + 1 for (i, j) in asm_matrix.nonzero_positions()])
931
+
932
+ @combinatorial_map(name='to semistandard tableau')
933
+ def to_semistandard_tableau(self):
934
+ """
935
+ Return the semistandard tableau corresponding the monotone triangle
936
+ corresponding to ``self``.
937
+
938
+ EXAMPLES::
939
+
940
+ sage: A = AlternatingSignMatrices(3)
941
+ sage: A([[0,0,1],[1,0,0],[0,1,0]]).to_semistandard_tableau()
942
+ [[1, 1, 3], [2, 3], [3]]
943
+ sage: t = A([[0,1,0],[1,-1,1],[0,1,0]]).to_semistandard_tableau(); t
944
+ [[1, 1, 2], [2, 3], [3]]
945
+ sage: parent(t)
946
+ Semistandard tableaux
947
+ """
948
+ from sage.combinat.tableau import SemistandardTableau
949
+ mt = self.to_monotone_triangle()
950
+ ssyt = [[0]*(len(mt) - j) for j in range(len(mt))]
951
+ for i in range(len(mt)):
952
+ for j in range(len(mt[i])):
953
+ ssyt[i][j] = mt[j][-(i+1)]
954
+ return SemistandardTableau(ssyt)
955
+
956
+ def left_key(self):
957
+ r"""
958
+ Return the left key of the alternating sign matrix ``self``.
959
+
960
+ The left key of an alternating sign matrix was defined by Lascoux
961
+ in [Lasc]_ and is obtained by successively removing all the
962
+ `-1`'s until what remains is a permutation matrix. This notion
963
+ corresponds to the notion of left key for semistandard tableaux. So
964
+ our algorithm proceeds as follows: we map ``self`` to its
965
+ corresponding monotone triangle, view that monotone triangle as a
966
+ semistandard tableau, take its left key, and then map back through
967
+ monotone triangles to the permutation matrix which is the left key.
968
+
969
+ See also [Ava2007]_.
970
+
971
+ EXAMPLES::
972
+
973
+ sage: A = AlternatingSignMatrices(3)
974
+ sage: A([[0,0,1],[1,0,0],[0,1,0]]).left_key()
975
+ [0 0 1]
976
+ [1 0 0]
977
+ [0 1 0]
978
+ sage: t = A([[0,1,0],[1,-1,1],[0,1,0]]).left_key(); t
979
+ [1 0 0]
980
+ [0 0 1]
981
+ [0 1 0]
982
+ sage: parent(t)
983
+ Alternating sign matrices of size 3
984
+ """
985
+ lkey = self.to_semistandard_tableau().left_key_tableau()
986
+ mt = [[0]*(len(lkey) - j) for j in range(len(lkey))]
987
+ for i in range(len(lkey)):
988
+ for j in range(len(lkey[i])):
989
+ mt[i][j] = lkey[len(lkey[i])-j-1][i]
990
+ A = AlternatingSignMatrices(len(lkey))
991
+ return A.from_monotone_triangle(mt)
992
+
993
+ @combinatorial_map(name='to left key permutation')
994
+ def left_key_as_permutation(self):
995
+ """
996
+ Return the permutation of the left key of ``self``.
997
+
998
+ .. SEEALSO::
999
+
1000
+ - :meth:`left_key()`
1001
+
1002
+ EXAMPLES::
1003
+
1004
+ sage: A = AlternatingSignMatrices(3)
1005
+ sage: A([[0,0,1],[1,0,0],[0,1,0]]).left_key_as_permutation()
1006
+ [3, 1, 2]
1007
+ sage: t = A([[0,1,0],[1,-1,1],[0,1,0]]).left_key_as_permutation(); t
1008
+ [1, 3, 2]
1009
+ sage: parent(t)
1010
+ Standard permutations
1011
+ """
1012
+ return self.left_key().to_permutation()
1013
+
1014
+
1015
+ class AlternatingSignMatrices(UniqueRepresentation, Parent):
1016
+ r"""
1017
+ Class of all `n \times n` alternating sign matrices.
1018
+
1019
+ An alternating sign matrix of size `n` is an `n \times n` matrix of `0`'s,
1020
+ `1`'s and `-1`'s such that the sum of each row and column is `1` and the
1021
+ nonzero entries in each row and column alternate in sign.
1022
+
1023
+ Alternating sign matrices of size `n` are in bijection with
1024
+ :class:`monotone triangles <MonotoneTriangles>` with `n` rows.
1025
+
1026
+ INPUT:
1027
+
1028
+ - ``n`` -- integer; the size of the matrices
1029
+
1030
+ EXAMPLES:
1031
+
1032
+ This will create an instance to manipulate the alternating sign
1033
+ matrices of size 3::
1034
+
1035
+ sage: A = AlternatingSignMatrices(3)
1036
+ sage: A
1037
+ Alternating sign matrices of size 3
1038
+ sage: A.cardinality()
1039
+ 7
1040
+
1041
+ Notably, this implementation allows to make a lattice of it::
1042
+
1043
+ sage: # needs sage.graphs
1044
+ sage: L = A.lattice(); L
1045
+ Finite lattice containing 7 elements
1046
+ sage: L.category()
1047
+ Category of facade finite enumerated lattice posets
1048
+ """
1049
+
1050
+ def __init__(self, n):
1051
+ r"""
1052
+ Initialize ``self``.
1053
+
1054
+ TESTS::
1055
+
1056
+ sage: A = AlternatingSignMatrices(4)
1057
+ sage: TestSuite(A).run()
1058
+ """
1059
+ self._n = n
1060
+ self._matrix_space = MatrixSpace(ZZ, n)
1061
+ Parent.__init__(self, category=FiniteEnumeratedSets())
1062
+
1063
+ def _repr_(self):
1064
+ r"""
1065
+ Return a string representation of ``self``.
1066
+
1067
+ TESTS::
1068
+
1069
+ sage: A = AlternatingSignMatrices(4); A
1070
+ Alternating sign matrices of size 4
1071
+ """
1072
+ return "Alternating sign matrices of size %s" % self._n
1073
+
1074
+ def _repr_option(self, key):
1075
+ """
1076
+ Metadata about the :meth:`_repr_` output.
1077
+
1078
+ See :meth:`sage.structure.parent._repr_option` for details.
1079
+
1080
+ EXAMPLES::
1081
+
1082
+ sage: A = AlternatingSignMatrices(3)
1083
+ sage: A._repr_option('element_ascii_art')
1084
+ True
1085
+ """
1086
+ return self._matrix_space._repr_option(key)
1087
+
1088
+ def __contains__(self, asm):
1089
+ """
1090
+ Check if ``asm`` is in ``self``.
1091
+
1092
+ TESTS::
1093
+
1094
+ sage: A = AlternatingSignMatrices(3)
1095
+ sage: [[0,1,0],[1,0,0],[0,0,1]] in A
1096
+ True
1097
+ sage: [[0,1,0],[1,-1,1],[0,1,0]] in A
1098
+ True
1099
+ sage: [[0, 1],[1,0]] in A
1100
+ False
1101
+ sage: [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]] in A
1102
+ False
1103
+ sage: [[-1, 1, 1],[1,-1,1],[1,1,-1]] in A
1104
+ False
1105
+
1106
+ sage: M = MatrixSpace(ZZ, 3)
1107
+ sage: for p in [[-1,1,1,1,0,0,1,0,0],
1108
+ ....: [0,1,0,0,1,0,1,-1,1],
1109
+ ....: [0,1,0,0,2,0,1,-2,1],
1110
+ ....: [0,2,0,1,-2,1,0,1,0]]:
1111
+ ....: m = M(p)
1112
+ ....: assert not m in A
1113
+ ....: m = m.transpose()
1114
+ ....: assert not m in A
1115
+ ....: m = m.antitranspose()
1116
+ ....: assert not m in A
1117
+ ....: m = m.transpose()
1118
+ ....: assert not m in A
1119
+
1120
+ Exhaustive verifications for `2 \times 2` and `3 \times 3` matrices::
1121
+
1122
+ sage: from itertools import product
1123
+
1124
+ sage: M = MatrixSpace(ZZ, 2)
1125
+ sage: A = AlternatingSignMatrices(2)
1126
+ sage: mats = [M(p) for p in product([-1,0,1], repeat=4)]
1127
+ sage: sum(1 for m in mats if m in A)
1128
+ 2
1129
+
1130
+ sage: M = MatrixSpace(ZZ, 3)
1131
+ sage: A = AlternatingSignMatrices(3)
1132
+ sage: mats = [M(p) for p in product([-1,0,1], repeat=9)]
1133
+ sage: sum(1 for m in mats if m in A)
1134
+ 7
1135
+ """
1136
+ if isinstance(asm, AlternatingSignMatrix):
1137
+ return asm._matrix.nrows() == self._n
1138
+ try:
1139
+ asm = self._matrix_space(asm)
1140
+ except (TypeError, ValueError):
1141
+ return False
1142
+
1143
+ if not asm.is_square():
1144
+ return False
1145
+
1146
+ n = asm.nrows()
1147
+ for i in range(n):
1148
+ # check that partial sums of the i-th row
1149
+ # and i-th column are either 0 or 1
1150
+ rs = cs = ZZ.zero()
1151
+ for j in range(n):
1152
+ rs += asm[i,j]
1153
+ if not (rs.is_zero() or rs.is_one()):
1154
+ return False
1155
+
1156
+ cs += asm[j,i]
1157
+ if not (cs.is_zero() or cs.is_one()):
1158
+ return False
1159
+
1160
+ # check that the total sums of the i-th
1161
+ # row and i-th column is 1
1162
+ if not (rs.is_one() and cs.is_one()):
1163
+ return False
1164
+
1165
+ return True
1166
+
1167
+ def _element_constructor_(self, asm, check=True):
1168
+ """
1169
+ Construct an element of ``self``.
1170
+
1171
+ EXAMPLES::
1172
+
1173
+ sage: A = AlternatingSignMatrices(3)
1174
+ sage: elt = A([[1, 0, 0],[0, 1, 0],[0, 0, 1]]); elt
1175
+ [1 0 0]
1176
+ [0 1 0]
1177
+ [0 0 1]
1178
+ sage: elt.parent() is A
1179
+ True
1180
+ sage: A([[3, 2, 1], [2, 1], [1]])
1181
+ [1 0 0]
1182
+ [0 1 0]
1183
+ [0 0 1]
1184
+
1185
+ Check that checking is disabled with ``check=False``::
1186
+
1187
+ sage: A = AlternatingSignMatrices(3)
1188
+ sage: A([[1,2,3],[4,5,6],[7,8,9]])
1189
+ Traceback (most recent call last):
1190
+ ...
1191
+ ValueError: invalid alternating sign matrix
1192
+ sage: A([[1,2,3],[4,5,6],[7,8,9]], check=False)
1193
+ [1 2 3]
1194
+ [4 5 6]
1195
+ [7 8 9]
1196
+ """
1197
+ if isinstance(asm, AlternatingSignMatrix):
1198
+ if asm.parent() is self:
1199
+ return asm
1200
+ raise ValueError("cannot convert between alternating sign matrices of different sizes")
1201
+ try:
1202
+ m = self._matrix_space(asm)
1203
+ except (TypeError, ValueError):
1204
+ try:
1205
+ return self.from_monotone_triangle(asm, check=check)
1206
+ except (TypeError, ValueError):
1207
+ raise ValueError('invalid alternating sign matrix')
1208
+
1209
+ m.set_immutable()
1210
+ if check and m not in self:
1211
+ raise ValueError('invalid alternating sign matrix')
1212
+ return self.element_class(self, m)
1213
+
1214
+ Element = AlternatingSignMatrix
1215
+
1216
+ def _an_element_(self):
1217
+ """
1218
+ Return an element of ``self``.
1219
+
1220
+ EXAMPLES::
1221
+
1222
+ sage: A = AlternatingSignMatrices(3)
1223
+ sage: A._an_element_()
1224
+ [1 0 0]
1225
+ [0 1 0]
1226
+ [0 0 1]
1227
+ """
1228
+ return self.element_class(self, self._matrix_space.identity_matrix())
1229
+
1230
+ def random_element(self):
1231
+ r"""
1232
+ Return a uniformly random alternating sign matrix.
1233
+
1234
+ EXAMPLES::
1235
+
1236
+ sage: AlternatingSignMatrices(7).random_element() # random
1237
+ [ 0 0 0 0 1 0 0]
1238
+ [ 0 0 1 0 -1 0 1]
1239
+ [ 0 0 0 0 1 0 0]
1240
+ [ 0 1 -1 0 0 1 0]
1241
+ [ 1 -1 1 0 0 0 0]
1242
+ [ 0 0 0 1 0 0 0]
1243
+ [ 0 1 0 0 0 0 0]
1244
+ sage: a = AlternatingSignMatrices(5).random_element()
1245
+ sage: bool(a.number_negative_ones()) or a.is_permutation()
1246
+ True
1247
+
1248
+ This is done using a modified version of Propp and Wilson's "coupling
1249
+ from the past" algorithm. It creates a uniformly random Gelfand-Tsetlin
1250
+ triangle with top row `[n, n-1, \ldots 2, 1]`, and then converts it to
1251
+ an alternating sign matrix.
1252
+ """
1253
+ from sage.combinat.gelfand_tsetlin_patterns import GelfandTsetlinPatterns
1254
+ n = self._n
1255
+ toprow = [n - i for i in range(n)]
1256
+ gt = GelfandTsetlinPatterns(top_row=toprow, strict=True)
1257
+ randomgt = gt.random_element()
1258
+ A = AlternatingSignMatrices(n)
1259
+ return A.from_monotone_triangle(randomgt)
1260
+
1261
+ def from_monotone_triangle(self, triangle, check=True):
1262
+ r"""
1263
+ Return an alternating sign matrix from a monotone triangle.
1264
+
1265
+ EXAMPLES::
1266
+
1267
+ sage: A = AlternatingSignMatrices(3)
1268
+ sage: A.from_monotone_triangle([[3, 2, 1], [2, 1], [1]])
1269
+ [1 0 0]
1270
+ [0 1 0]
1271
+ [0 0 1]
1272
+ sage: A.from_monotone_triangle([[3, 2, 1], [3, 2], [3]])
1273
+ [0 0 1]
1274
+ [0 1 0]
1275
+ [1 0 0]
1276
+
1277
+
1278
+ sage: A.from_monotone_triangle([[3, 2, 1], [2, 2], [1]])
1279
+ Traceback (most recent call last):
1280
+ ...
1281
+ ValueError: not a valid triangle
1282
+ """
1283
+ n = len(triangle)
1284
+ if n != self._n:
1285
+ raise ValueError("incorrect size")
1286
+
1287
+ asm = self._matrix_space()
1288
+ for i in range(n - 1):
1289
+ for k in triangle[n - i - 1]:
1290
+ asm[i, k - 1] += 1
1291
+ asm[i + 1, k - 1] -= 1
1292
+ for i in range(n):
1293
+ asm[n - 1, i] += 1
1294
+
1295
+ asm.set_immutable()
1296
+ if check and asm not in self:
1297
+ raise ValueError('not a valid triangle')
1298
+ return self.element_class(self, asm)
1299
+
1300
+ def from_corner_sum(self, corner):
1301
+ r"""
1302
+ Return an alternating sign matrix from a corner sum matrix.
1303
+
1304
+ EXAMPLES::
1305
+
1306
+ sage: A = AlternatingSignMatrices(3)
1307
+ sage: A.from_corner_sum(matrix([[0,0,0,0],[0,1,1,1],[0,1,2,2],[0,1,2,3]]))
1308
+ [1 0 0]
1309
+ [0 1 0]
1310
+ [0 0 1]
1311
+ sage: A.from_corner_sum(matrix([[0,0,0,0],[0,0,1,1],[0,1,1,2],[0,1,2,3]]))
1312
+ [ 0 1 0]
1313
+ [ 1 -1 1]
1314
+ [ 0 1 0]
1315
+
1316
+ TESTS::
1317
+
1318
+ sage: A = AlternatingSignMatrices(4)
1319
+ sage: all(A.from_corner_sum(a.corner_sum_matrix()) == a for a in A)
1320
+ True
1321
+ """
1322
+ n = self._n
1323
+ corner = MatrixSpace(ZZ, n+1)(corner)
1324
+ asm = corner[1:,1:] + corner[:n,:n] - corner[:n,1:] - corner[1:,:n]
1325
+ return self.element_class(self, asm)
1326
+
1327
+ def from_height_function(self, height):
1328
+ r"""
1329
+ Return an alternating sign matrix from a height function.
1330
+
1331
+ EXAMPLES::
1332
+
1333
+ sage: A = AlternatingSignMatrices(3)
1334
+ sage: A.from_height_function(matrix([[0,1,2,3],[1,2,1,2],[2,3,2,1],[3,2,1,0]]))
1335
+ [0 0 1]
1336
+ [1 0 0]
1337
+ [0 1 0]
1338
+ sage: A.from_height_function(matrix([[0,1,2,3],[1,2,1,2],[2,1,2,1],[3,2,1,0]]))
1339
+ [ 0 1 0]
1340
+ [ 1 -1 1]
1341
+ [ 0 1 0]
1342
+ """
1343
+ n = self._n
1344
+ height = MatrixSpace(ZZ, n + 1)(height)
1345
+ return self.from_corner_sum([[(i + j - height[i, j]) // 2
1346
+ for i in range(n + 1)]
1347
+ for j in range(n + 1)])
1348
+
1349
+ def from_contre_tableau(self, comps):
1350
+ r"""
1351
+ Return an alternating sign matrix from a contre-tableau.
1352
+
1353
+ EXAMPLES::
1354
+
1355
+ sage: ASM = AlternatingSignMatrices(3)
1356
+ sage: ASM.from_contre_tableau([[1, 2, 3], [1, 2], [1]])
1357
+ [0 0 1]
1358
+ [0 1 0]
1359
+ [1 0 0]
1360
+ sage: ASM.from_contre_tableau([[1, 2, 3], [2, 3], [3]])
1361
+ [1 0 0]
1362
+ [0 1 0]
1363
+ [0 0 1]
1364
+ """
1365
+ n = len(comps)
1366
+ M = [[0 for _ in range(n)] for _ in range(n)]
1367
+
1368
+ previous_set = set()
1369
+ for col in range(n-1, -1, -1):
1370
+ s = set(comps[col])
1371
+ for x in s.difference(previous_set):
1372
+ M[x-1][col] = 1
1373
+ for x in previous_set.difference(s):
1374
+ M[x-1][col] = -1
1375
+
1376
+ previous_set = s
1377
+
1378
+ return AlternatingSignMatrix(M)
1379
+
1380
+ def size(self):
1381
+ r"""
1382
+ Return the size of the matrices in ``self``.
1383
+
1384
+ TESTS::
1385
+
1386
+ sage: A = AlternatingSignMatrices(4)
1387
+ sage: A.size()
1388
+ 4
1389
+ """
1390
+ return self._n
1391
+
1392
+ def cardinality(self):
1393
+ r"""
1394
+ Return the cardinality of ``self``.
1395
+
1396
+ The number of `n \times n` alternating sign matrices is equal to
1397
+
1398
+ .. MATH::
1399
+
1400
+ \prod_{k=0}^{n-1} \frac{(3k+1)!}{(n+k)!} = \frac{1! 4! 7! 10!
1401
+ \cdots (3n-2)!}{n! (n+1)! (n+2)! (n+3)! \cdots (2n-1)!}
1402
+
1403
+ EXAMPLES::
1404
+
1405
+ sage: [AlternatingSignMatrices(n).cardinality() for n in range(11)]
1406
+ [1, 1, 2, 7, 42, 429, 7436, 218348, 10850216, 911835460, 129534272700]
1407
+ """
1408
+ return Integer(prod(factorial(3 * k + 1) / factorial(self._n + k)
1409
+ for k in range(self._n)))
1410
+
1411
+ def matrix_space(self):
1412
+ """
1413
+ Return the underlying matrix space.
1414
+
1415
+ EXAMPLES::
1416
+
1417
+ sage: A = AlternatingSignMatrices(3)
1418
+ sage: A.matrix_space()
1419
+ Full MatrixSpace of 3 by 3 dense matrices over Integer Ring
1420
+ """
1421
+ return self._matrix_space
1422
+
1423
+ def __iter__(self):
1424
+ r"""
1425
+ Iterator on the alternating sign matrices of size `n`.
1426
+
1427
+ TESTS::
1428
+
1429
+ sage: AlternatingSignMatrices(3).list()
1430
+ [
1431
+ [1 0 0] [0 1 0] [1 0 0] [ 0 1 0] [0 0 1] [0 1 0] [0 0 1]
1432
+ [0 1 0] [1 0 0] [0 0 1] [ 1 -1 1] [1 0 0] [0 0 1] [0 1 0]
1433
+ [0 0 1], [0 0 1], [0 1 0], [ 0 1 0], [0 1 0], [1 0 0], [1 0 0]
1434
+ ]
1435
+ sage: sum(1 for a in AlternatingSignMatrices(4))
1436
+ 42
1437
+ """
1438
+ for t in MonotoneTriangles(self._n):
1439
+ yield self.from_monotone_triangle(t, check=False)
1440
+
1441
+ def first(self):
1442
+ r"""
1443
+ Return the first alternating sign matrix.
1444
+
1445
+ EXAMPLES::
1446
+
1447
+ sage: AlternatingSignMatrices(5).first()
1448
+ [1 0 0 0 0]
1449
+ [0 1 0 0 0]
1450
+ [0 0 1 0 0]
1451
+ [0 0 0 1 0]
1452
+ [0 0 0 0 1]
1453
+ """
1454
+ return self.element_class(self, self._matrix_space.one())
1455
+
1456
+ def last(self):
1457
+ r"""
1458
+ Return the last alternating sign matrix.
1459
+
1460
+ EXAMPLES::
1461
+
1462
+ sage: AlternatingSignMatrices(5).last()
1463
+ [0 0 0 0 1]
1464
+ [0 0 0 1 0]
1465
+ [0 0 1 0 0]
1466
+ [0 1 0 0 0]
1467
+ [1 0 0 0 0]
1468
+ """
1469
+ m = self._matrix_space.zero().__copy__()
1470
+ for i in range(self._n):
1471
+ m[i, self._n - i - 1] = 1
1472
+ m.set_immutable()
1473
+ return self.element_class(self, m)
1474
+
1475
+ def _lattice_initializer(self):
1476
+ r"""
1477
+ Return a 2-tuple to use in argument of ``LatticePoset``.
1478
+
1479
+ For more details about the cover relations, see
1480
+ ``MonotoneTriangles``. Notice that the returned matrices are
1481
+ made immutable to ensure their hashability required by
1482
+ ``LatticePoset``.
1483
+
1484
+ EXAMPLES:
1485
+
1486
+ Proof of the lattice property for alternating sign matrices of
1487
+ size 3::
1488
+
1489
+ sage: # needs sage.graphs
1490
+ sage: A = AlternatingSignMatrices(3)
1491
+ sage: P = Poset(A._lattice_initializer())
1492
+ sage: P.is_lattice()
1493
+ True
1494
+ """
1495
+ mts, rels = MonotoneTriangles(self._n)._lattice_initializer()
1496
+ bij = {t: self.from_monotone_triangle(t) for t in mts}
1497
+ return (bij.values(), [(bij[a], bij[b]) for (a, b) in rels])
1498
+
1499
+ def cover_relations(self):
1500
+ r"""
1501
+ Iterate on the cover relations between the alternating sign
1502
+ matrices.
1503
+
1504
+ EXAMPLES::
1505
+
1506
+ sage: A = AlternatingSignMatrices(3)
1507
+ sage: for (a,b) in A.cover_relations():
1508
+ ....: eval('a, b')
1509
+ (
1510
+ [1 0 0] [0 1 0]
1511
+ [0 1 0] [1 0 0]
1512
+ [0 0 1], [0 0 1]
1513
+ )
1514
+ (
1515
+ [1 0 0] [1 0 0]
1516
+ [0 1 0] [0 0 1]
1517
+ [0 0 1], [0 1 0]
1518
+ )
1519
+ (
1520
+ [0 1 0] [ 0 1 0]
1521
+ [1 0 0] [ 1 -1 1]
1522
+ [0 0 1], [ 0 1 0]
1523
+ )
1524
+ (
1525
+ [1 0 0] [ 0 1 0]
1526
+ [0 0 1] [ 1 -1 1]
1527
+ [0 1 0], [ 0 1 0]
1528
+ )
1529
+ (
1530
+ [ 0 1 0] [0 0 1]
1531
+ [ 1 -1 1] [1 0 0]
1532
+ [ 0 1 0], [0 1 0]
1533
+ )
1534
+ (
1535
+ [ 0 1 0] [0 1 0]
1536
+ [ 1 -1 1] [0 0 1]
1537
+ [ 0 1 0], [1 0 0]
1538
+ )
1539
+ (
1540
+ [0 0 1] [0 0 1]
1541
+ [1 0 0] [0 1 0]
1542
+ [0 1 0], [1 0 0]
1543
+ )
1544
+ (
1545
+ [0 1 0] [0 0 1]
1546
+ [0 0 1] [0 1 0]
1547
+ [1 0 0], [1 0 0]
1548
+ )
1549
+ """
1550
+ return iter(self._lattice_initializer()[1])
1551
+
1552
+ def lattice(self):
1553
+ r"""
1554
+ Return the lattice of the alternating sign matrices of size
1555
+ `n`, created by ``LatticePoset``.
1556
+
1557
+ EXAMPLES::
1558
+
1559
+ sage: A = AlternatingSignMatrices(3)
1560
+ sage: L = A.lattice(); L # needs sage.graphs
1561
+ Finite lattice containing 7 elements
1562
+ """
1563
+ return LatticePoset(self._lattice_initializer(), cover_relations=True,
1564
+ check=False)
1565
+
1566
+ @cached_method
1567
+ def gyration_orbits(self):
1568
+ r"""
1569
+ Return the list of gyration orbits of ``self``.
1570
+
1571
+ EXAMPLES::
1572
+
1573
+ sage: AlternatingSignMatrices(3).gyration_orbits()
1574
+ ((
1575
+ [1 0 0] [0 0 1] [ 0 1 0]
1576
+ [0 1 0] [0 1 0] [ 1 -1 1]
1577
+ [0 0 1], [1 0 0], [ 0 1 0]
1578
+ ),
1579
+ (
1580
+ [0 1 0] [1 0 0]
1581
+ [1 0 0] [0 0 1]
1582
+ [0 0 1], [0 1 0]
1583
+ ),
1584
+ (
1585
+ [0 0 1] [0 1 0]
1586
+ [1 0 0] [0 0 1]
1587
+ [0 1 0], [1 0 0]
1588
+ ))
1589
+ """
1590
+ ASMs = list(self)
1591
+ perm = Permutation([ASMs.index(asm.gyration())+1 for asm in ASMs])
1592
+ return tuple([tuple([ASMs[i-1] for i in cyc])
1593
+ for cyc in perm.cycle_tuples()])
1594
+
1595
+ def gyration_orbit_sizes(self):
1596
+ r"""
1597
+ Return the sizes of gyration orbits of ``self``.
1598
+
1599
+ EXAMPLES::
1600
+
1601
+ sage: AlternatingSignMatrices(3).gyration_orbit_sizes()
1602
+ [3, 2, 2]
1603
+ sage: AlternatingSignMatrices(4).gyration_orbit_sizes()
1604
+ [4, 8, 2, 8, 8, 8, 2, 2]
1605
+
1606
+ sage: A = AlternatingSignMatrices(5)
1607
+ sage: li = [5,10,10,10,10,10,2,5,10,10,10,10,10,10,10,10,10,10,10,10,
1608
+ ....: 4,10,10,10,10,10,10,4,5,10,10,10,10,10,10,10,2,4,5,10,10,10,10,10,10,
1609
+ ....: 4,5,10,10,2,2]
1610
+ sage: A.gyration_orbit_sizes() == li
1611
+ True
1612
+ """
1613
+ return [len(orbit) for orbit in self.gyration_orbits()]
1614
+
1615
+
1616
+ class MonotoneTriangles(GelfandTsetlinPatternsTopRow):
1617
+ r"""
1618
+ Monotone triangles with `n` rows.
1619
+
1620
+ A monotone triangle is a number triangle `(a_{i,j})_{1 \leq i \leq
1621
+ n , 1 \leq j \leq i}` on `\{1, \dots, n\}` such that:
1622
+
1623
+ - `a_{i,j} < a_{i,j+1}`
1624
+
1625
+ - `a_{i+1,j} < a_{i,j} \leq a_{i+1,j+1}`
1626
+
1627
+ This notably requires that the bottom column is ``[1,...,n]``.
1628
+
1629
+ Alternatively a monotone triangle is a strict Gelfand-Tsetlin pattern with
1630
+ top row `(n, \ldots, 2, 1)`.
1631
+
1632
+ INPUT:
1633
+
1634
+ - ``n`` -- the number of rows in the monotone triangles
1635
+
1636
+ EXAMPLES:
1637
+
1638
+ This represents the monotone triangles with base ``[3,2,1]``::
1639
+
1640
+ sage: M = MonotoneTriangles(3)
1641
+ sage: M
1642
+ Monotone triangles with 3 rows
1643
+ sage: M.cardinality()
1644
+ 7
1645
+
1646
+ The monotone triangles are a lattice::
1647
+
1648
+ sage: M.lattice() # needs sage.graphs
1649
+ Finite lattice containing 7 elements
1650
+
1651
+ Monotone triangles can be converted to alternating sign matrices
1652
+ and back::
1653
+
1654
+ sage: M = MonotoneTriangles(5)
1655
+ sage: A = AlternatingSignMatrices(5)
1656
+ sage: all(A.from_monotone_triangle(m).to_monotone_triangle() == m for m in M)
1657
+ True
1658
+ """
1659
+
1660
+ def __init__(self, n):
1661
+ r"""
1662
+ Initialize ``self``.
1663
+
1664
+ TESTS::
1665
+
1666
+ sage: M = MonotoneTriangles(4)
1667
+ sage: TestSuite(M).run()
1668
+ sage: M2 = MonotoneTriangles(int(4))
1669
+ sage: M is M2
1670
+ True
1671
+ """
1672
+ GelfandTsetlinPatternsTopRow.__init__(self, tuple(reversed(range(1, n+1))), True)
1673
+
1674
+ def _repr_(self):
1675
+ r"""
1676
+ String representation.
1677
+
1678
+ TESTS::
1679
+
1680
+ sage: M = MonotoneTriangles(4)
1681
+ sage: M
1682
+ Monotone triangles with 4 rows
1683
+ """
1684
+ return "Monotone triangles with %s rows" % self._n
1685
+
1686
+ def cardinality(self):
1687
+ r"""
1688
+ Cardinality of ``self``.
1689
+
1690
+ The number of monotone triangles with `n` rows is equal to
1691
+
1692
+ .. MATH::
1693
+
1694
+ \prod_{k=0}^{n-1} \frac{(3k+1)!}{(n+k)!} = \frac{1! 4! 7! 10!
1695
+ \cdots (3n-2)!}{n! (n+1)! (n+2)! (n+3)! \cdots (2n-1)!}
1696
+
1697
+ EXAMPLES::
1698
+
1699
+ sage: M = MonotoneTriangles(4)
1700
+ sage: M.cardinality()
1701
+ 42
1702
+ """
1703
+ return Integer(prod(factorial(3 * k + 1) / factorial(self._n + k)
1704
+ for k in range(self._n)))
1705
+
1706
+ def _lattice_initializer(self):
1707
+ r"""
1708
+ Return a 2-tuple to use in argument of ``LatticePoset``.
1709
+
1710
+ This couple is composed by the set of the monotone triangles
1711
+ with `n` rows and the cover relations. Specializing this
1712
+ function allows to generate the monotone triangles just once,
1713
+ and so to speed up the computation in comparison of
1714
+ ``(list(self), self.cover_relations())``. Notice that the
1715
+ function also switch the representation of monotone triangles
1716
+ from list of list to tuple of tuple in order to make them
1717
+ hashable (required to make a poset with them).
1718
+
1719
+ EXAMPLES::
1720
+
1721
+ sage: # needs sage.graphs
1722
+ sage: M = MonotoneTriangles(3)
1723
+ sage: P = Poset(M._lattice_initializer())
1724
+ sage: P.is_lattice()
1725
+ True
1726
+ """
1727
+ # get a list of the elements and switch to a tuple representation
1728
+ set_ = [tuple(tuple(t) for t in x) for x in list(self)]
1729
+ return (set_, [(a, b) for a in set_ for b in set_ if _is_a_cover(a, b)])
1730
+
1731
+ def cover_relations(self):
1732
+ r"""
1733
+ Iterate on the cover relations in the set of monotone triangles
1734
+ with `n` rows.
1735
+
1736
+ EXAMPLES::
1737
+
1738
+ sage: M = MonotoneTriangles(3)
1739
+ sage: for (a,b) in M.cover_relations():
1740
+ ....: eval('a, b')
1741
+ ([[3, 2, 1], [2, 1], [1]], [[3, 2, 1], [2, 1], [2]])
1742
+ ([[3, 2, 1], [2, 1], [1]], [[3, 2, 1], [3, 1], [1]])
1743
+ ([[3, 2, 1], [2, 1], [2]], [[3, 2, 1], [3, 1], [2]])
1744
+ ([[3, 2, 1], [3, 1], [1]], [[3, 2, 1], [3, 1], [2]])
1745
+ ([[3, 2, 1], [3, 1], [2]], [[3, 2, 1], [3, 1], [3]])
1746
+ ([[3, 2, 1], [3, 1], [2]], [[3, 2, 1], [3, 2], [2]])
1747
+ ([[3, 2, 1], [3, 1], [3]], [[3, 2, 1], [3, 2], [3]])
1748
+ ([[3, 2, 1], [3, 2], [2]], [[3, 2, 1], [3, 2], [3]])
1749
+ """
1750
+ set_ = list(self)
1751
+ return ((a, b) for a in set_ for b in set_ if _is_a_cover(a, b))
1752
+
1753
+ def lattice(self):
1754
+ r"""
1755
+ Return the lattice of the monotone triangles with `n` rows.
1756
+
1757
+ EXAMPLES::
1758
+
1759
+ sage: M = MonotoneTriangles(3)
1760
+ sage: P = M.lattice(); P # needs sage.graphs
1761
+ Finite lattice containing 7 elements
1762
+ """
1763
+ return LatticePoset(self._lattice_initializer(), cover_relations=True,
1764
+ check=False)
1765
+
1766
+
1767
+ def _is_a_cover(mt0, mt1):
1768
+ r"""
1769
+ Define the cover relations.
1770
+
1771
+ Return ``True`` if and only if the second argument is a cover of
1772
+ the first one.
1773
+
1774
+ EXAMPLES::
1775
+
1776
+ sage: import sage.combinat.alternating_sign_matrix as asm
1777
+ sage: asm._is_a_cover([[1,2,3],[1,2],[1]], [[1,2,3],[1,3],[1]])
1778
+ True
1779
+ sage: asm._is_a_cover([[1,2,3],[1,3],[2]], [[1,2,3],[1,2],[1]])
1780
+ False
1781
+ """
1782
+ diffs = 0
1783
+ for (a, b) in zip(flatten(mt0), flatten(mt1)):
1784
+ if a != b:
1785
+ if a + 1 == b:
1786
+ diffs += 1
1787
+ else:
1788
+ return False
1789
+ if diffs > 1:
1790
+ return False
1791
+ return diffs == 1
1792
+
1793
+
1794
+ from sage.misc.persist import register_unpickle_override
1795
+ register_unpickle_override('sage.combinat.alternating_sign_matrix', 'AlternatingSignMatrices_n', AlternatingSignMatrices)
1796
+ register_unpickle_override('sage.combinat.alternating_sign_matrix', 'MonotoneTriangles_n', MonotoneTriangles)
1797
+
1798
+
1799
+ class ContreTableaux(Parent, metaclass=ClasscallMetaclass):
1800
+ """
1801
+ Factory class for the combinatorial class of contre tableaux of size `n`.
1802
+
1803
+ EXAMPLES::
1804
+
1805
+ sage: ct4 = ContreTableaux(4); ct4
1806
+ Contre tableaux of size 4
1807
+ sage: ct4.cardinality()
1808
+ 42
1809
+ """
1810
+ @staticmethod
1811
+ def __classcall_private__(cls, n, **kwds):
1812
+ r"""
1813
+ Factory pattern.
1814
+
1815
+ Check properties on arguments, then call the appropriate class.
1816
+
1817
+ EXAMPLES::
1818
+
1819
+ sage: C = ContreTableaux(4)
1820
+ sage: type(C)
1821
+ <class 'sage.combinat.alternating_sign_matrix.ContreTableaux_n'>
1822
+ """
1823
+ assert isinstance(n, (int, Integer))
1824
+ return ContreTableaux_n(n, **kwds)
1825
+
1826
+
1827
+ class ContreTableaux_n(ContreTableaux):
1828
+ def __init__(self, n):
1829
+ """
1830
+ TESTS::
1831
+
1832
+ sage: ct2 = ContreTableaux(2); ct2
1833
+ Contre tableaux of size 2
1834
+ sage: ct2 == loads(dumps(ct2))
1835
+ True
1836
+ """
1837
+ self.n = n
1838
+
1839
+ def __repr__(self):
1840
+ """
1841
+ TESTS::
1842
+
1843
+ sage: repr(ContreTableaux(2))
1844
+ 'Contre tableaux of size 2'
1845
+ """
1846
+ return "Contre tableaux of size %s" % self.n
1847
+
1848
+ def __eq__(self, other):
1849
+ """
1850
+ TESTS::
1851
+
1852
+ sage: C = ContreTableaux(4)
1853
+ sage: C == loads(dumps(C))
1854
+ True
1855
+ """
1856
+ return self.n == other.n
1857
+
1858
+ def cardinality(self):
1859
+ """
1860
+ EXAMPLES::
1861
+
1862
+ sage: [ContreTableaux(n).cardinality() for n in range(11)]
1863
+ [1, 1, 2, 7, 42, 429, 7436, 218348, 10850216, 911835460, 129534272700]
1864
+ """
1865
+ return Integer(prod(factorial(3 * k + 1) / factorial(self.n + k)
1866
+ for k in range(self.n)))
1867
+
1868
+ def _iterator_rec(self, i):
1869
+ """
1870
+ EXAMPLES::
1871
+
1872
+ sage: c = ContreTableaux(2)
1873
+ sage: list(c._iterator_rec(0))
1874
+ [[]]
1875
+ sage: list(c._iterator_rec(1))
1876
+ [[[1, 2]]]
1877
+ sage: list(c._iterator_rec(2))
1878
+ [[[1, 2], [1]], [[1, 2], [2]]]
1879
+ """
1880
+ if i == 0:
1881
+ yield []
1882
+ elif i == 1:
1883
+ yield [list(range(1, self.n + 1))]
1884
+ else:
1885
+ for columns in self._iterator_rec(i-1):
1886
+ previous_column = columns[-1]
1887
+ for column in _next_column_iterator(previous_column, len(previous_column)-1):
1888
+ yield columns + [column]
1889
+
1890
+ def __iter__(self):
1891
+ """
1892
+ EXAMPLES::
1893
+
1894
+ sage: list(ContreTableaux(0))
1895
+ [[]]
1896
+ sage: list(ContreTableaux(1))
1897
+ [[[1]]]
1898
+ sage: list(ContreTableaux(2))
1899
+ [[[1, 2], [1]], [[1, 2], [2]]]
1900
+ sage: list(ContreTableaux(3))
1901
+ [[[1, 2, 3], [1, 2], [1]],
1902
+ [[1, 2, 3], [1, 2], [2]],
1903
+ [[1, 2, 3], [1, 3], [1]],
1904
+ [[1, 2, 3], [1, 3], [2]],
1905
+ [[1, 2, 3], [1, 3], [3]],
1906
+ [[1, 2, 3], [2, 3], [2]],
1907
+ [[1, 2, 3], [2, 3], [3]]]
1908
+ """
1909
+ yield from self._iterator_rec(self.n)
1910
+
1911
+
1912
+ def _next_column_iterator(previous_column, height, i=None):
1913
+ r"""
1914
+ Return a generator for all columns of height ``height``
1915
+ properly filled from row 1 to ``i``.
1916
+
1917
+ "Properly filled" means strictly increasing and having
1918
+ the property that the `k`-th entry is `\geq` to the `k`-th
1919
+ entry of ``previous_column`` for each `k`.
1920
+
1921
+ EXAMPLES::
1922
+
1923
+ sage: import sage.combinat.alternating_sign_matrix as asm
1924
+ sage: list(asm._next_column_iterator([1], 0))
1925
+ [[]]
1926
+ sage: list(asm._next_column_iterator([1,5],1))
1927
+ [[1], [2], [3], [4], [5]]
1928
+ sage: list(asm._next_column_iterator([1,4,5],2))
1929
+ [[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5], [4, 5]]
1930
+ """
1931
+ if i is None:
1932
+ i = height
1933
+ if i == 0:
1934
+ yield [-1] * height
1935
+ else:
1936
+ for column in _next_column_iterator(previous_column, height, i-1):
1937
+ min_value = previous_column[i-1]
1938
+ if i > 1:
1939
+ min_value = max(min_value, column[i-2]+1)
1940
+ for value in range(min_value, previous_column[i]+1):
1941
+ c = column[:]
1942
+ c[i-1] = value
1943
+ yield c
1944
+
1945
+
1946
+ def _previous_column_iterator(column, height, max_value):
1947
+ """
1948
+ EXAMPLES::
1949
+
1950
+ sage: import sage.combinat.alternating_sign_matrix as asm
1951
+ sage: list(asm._previous_column_iterator([2,3], 3, 4))
1952
+ [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]
1953
+ """
1954
+ new_column = [1] + column + [max_value] * (height - len(column))
1955
+ return _next_column_iterator(new_column, height)
1956
+
1957
+
1958
+ class TruncatedStaircases(Parent, metaclass=ClasscallMetaclass):
1959
+ """
1960
+ Factory class for the combinatorial class of truncated staircases
1961
+ of size ``n`` with last column ``last_column``.
1962
+
1963
+ EXAMPLES::
1964
+
1965
+ sage: t4 = TruncatedStaircases(4, [2,3]); t4
1966
+ Truncated staircases of size 4 with last column [2, 3]
1967
+ sage: t4.cardinality()
1968
+ 4
1969
+ """
1970
+ @staticmethod
1971
+ def __classcall_private__(cls, n, last_column, **kwds):
1972
+ r"""
1973
+ Factory pattern.
1974
+
1975
+ Check properties on arguments, then call the appropriate class.
1976
+
1977
+ TESTS::
1978
+
1979
+ sage: T = TruncatedStaircases(4, [2,3])
1980
+ sage: type(T)
1981
+ <class 'sage.combinat.alternating_sign_matrix.TruncatedStaircases_nlastcolumn'>
1982
+ """
1983
+ assert isinstance(n, (int, Integer))
1984
+ return TruncatedStaircases_nlastcolumn(n, last_column, **kwds)
1985
+
1986
+
1987
+ class TruncatedStaircases_nlastcolumn(TruncatedStaircases):
1988
+ def __init__(self, n, last_column):
1989
+ """
1990
+ TESTS::
1991
+
1992
+ sage: t4 = TruncatedStaircases(4, [2,3]); t4
1993
+ Truncated staircases of size 4 with last column [2, 3]
1994
+ sage: t4 == loads(dumps(t4))
1995
+ True
1996
+ """
1997
+ self.n = n
1998
+ self.last_column = last_column
1999
+
2000
+ def __repr__(self):
2001
+ """
2002
+ TESTS::
2003
+
2004
+ sage: repr(TruncatedStaircases(4, [2,3]))
2005
+ 'Truncated staircases of size 4 with last column [2, 3]'
2006
+ """
2007
+ return "Truncated staircases of size %s with last column %s" % (self.n, self.last_column)
2008
+
2009
+ def _iterator_rec(self, i):
2010
+ """
2011
+ EXAMPLES::
2012
+
2013
+ sage: t = TruncatedStaircases(3, [2,3])
2014
+ sage: list(t._iterator_rec(1))
2015
+ []
2016
+ sage: list(t._iterator_rec(2))
2017
+ [[[2, 3]]]
2018
+ sage: list(t._iterator_rec(3))
2019
+ [[[1, 2, 3], [2, 3]]]
2020
+ """
2021
+ if i < len(self.last_column):
2022
+ return
2023
+ elif i == len(self.last_column):
2024
+ yield [self.last_column]
2025
+ else:
2026
+ for columns in self._iterator_rec(i-1):
2027
+ previous_column = columns[0]
2028
+ for column in _previous_column_iterator(previous_column, len(previous_column)+1, self.n):
2029
+ yield [column] + columns
2030
+
2031
+ def __iter__(self):
2032
+ """
2033
+ EXAMPLES::
2034
+
2035
+ sage: list(TruncatedStaircases(4, [2,3]))
2036
+ [[[4, 3, 2, 1], [3, 2, 1], [3, 2]], [[4, 3, 2, 1], [4, 2, 1], [3, 2]], [[4, 3, 2, 1], [4, 3, 1], [3, 2]], [[4, 3, 2, 1], [4, 3, 2], [3, 2]]]
2037
+ """
2038
+ for z in self._iterator_rec(self.n):
2039
+ yield [list(reversed(x)) for x in z]
2040
+
2041
+ def __eq__(self, other):
2042
+ r"""
2043
+ TESTS::
2044
+
2045
+ sage: T = TruncatedStaircases(4, [2,3])
2046
+ sage: T == loads(dumps(T))
2047
+ True
2048
+ """
2049
+ return (self.n == other.n and
2050
+ self.last_column == other.last_column)
2051
+
2052
+ def cardinality(self):
2053
+ r"""
2054
+ EXAMPLES::
2055
+
2056
+ sage: T = TruncatedStaircases(4, [2,3])
2057
+ sage: T.cardinality()
2058
+ 4
2059
+ """
2060
+ c = 0
2061
+ for _ in self:
2062
+ c += 1
2063
+ return c