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,2286 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ r"""
3
+ Knutson-Tao puzzles
4
+
5
+ This module implements a generic algorithm to solve Knutson-Tao puzzles. An
6
+ instance of this class will be callable: the arguments are the labels of
7
+ north-east and north-west sides of the puzzle boundary; the output is the list
8
+ of the fillings of the puzzle with the specified pieces.
9
+
10
+ Acknowledgements
11
+ ----------------
12
+
13
+ This code was written during Sage Days 45 at ICERM with Franco Saliola, Anne
14
+ Schilling, and Avinash Dalal in discussions with Allen Knutson. The code was
15
+ tested afterwards by Liz Beazley and Ed Richmond.
16
+
17
+ .. TODO::
18
+
19
+ Functionality to add:
20
+
21
+ - plotter will not plot edge labels higher than 2; e.g. in BK puzzles, the labels are
22
+ 1,..., n and so in 3-step examples, none of the edge labels with 3 appear
23
+
24
+ - we should also have a 3-step puzzle pieces constructor, taken from p22 of
25
+ :arxiv:`math/0610538`
26
+
27
+ - implement the bijection from puzzles to tableaux; see for example
28
+ R. Vakil, A geometric Littlewood-Richardson rule, :arxiv:`math/0302294`
29
+ or K. Purbhoo, Puzzles, Tableaux and Mosaics, :arxiv:`0705.1184`.
30
+ """
31
+ # ****************************************************************************
32
+ # Copyright (C) 2013 Franco Saliola <saliola@gmail.com>,
33
+ # 2013 Allen Knutson,
34
+ # 2013 Avinash Dalal,
35
+ # 2013 Anne Schilling,
36
+ # 2013 Elizabeth Beazley,
37
+ # 2013 Ed Richmond
38
+ #
39
+ # Distributed under the terms of the GNU General Public License (GPL)
40
+ # https://www.gnu.org/licenses/
41
+ # ****************************************************************************
42
+ from __future__ import annotations
43
+
44
+ from sage.misc.lazy_import import lazy_import
45
+ lazy_import("sage.plot.graphics", "Graphics")
46
+ lazy_import("sage.plot.polygon", "polygon")
47
+ lazy_import("sage.plot.line", "line")
48
+ lazy_import("sage.plot.text", "text")
49
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
50
+ from sage.rings.finite_rings.integer_mod_ring import Integers
51
+ lazy_import("sage.plot.plot", "graphics_array")
52
+ from sage.misc.cachefunc import cached_method
53
+ from sage.structure.unique_representation import UniqueRepresentation
54
+
55
+
56
+ class PuzzlePiece:
57
+ r"""
58
+ Abstract class for puzzle pieces.
59
+
60
+ This abstract class contains information on how to test equality of
61
+ puzzle pieces, and sets color and plotting options.
62
+ """
63
+
64
+ def __eq__(self, other) -> bool:
65
+ r"""
66
+ TESTS::
67
+
68
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece
69
+ sage: delta = DeltaPiece('a','b','c')
70
+ sage: delta1 = DeltaPiece('a','b','c')
71
+ sage: delta == delta1
72
+ True
73
+ sage: delta1 = DeltaPiece('A','b','c')
74
+ sage: delta == delta1
75
+ False
76
+ """
77
+ if isinstance(other, PuzzlePiece):
78
+ return self.border() == other.border()
79
+ else:
80
+ return False
81
+
82
+ def __hash__(self):
83
+ r"""
84
+ TESTS::
85
+
86
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece
87
+ sage: delta = DeltaPiece('a','b','c')
88
+ sage: hash(delta) == hash(delta)
89
+ True
90
+ """
91
+ return hash((type(self), self.border()))
92
+
93
+ def border(self) -> tuple:
94
+ r"""
95
+ Return the border of ``self``.
96
+
97
+ EXAMPLES::
98
+
99
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece
100
+ sage: delta = DeltaPiece('a','b','c')
101
+ sage: sorted(delta.border())
102
+ ['a', 'b', 'c']
103
+ """
104
+ return tuple(self.edge_label(edge) for edge in self.edges())
105
+
106
+ def color(self) -> str:
107
+ r"""
108
+ Return the color of ``self``.
109
+
110
+ EXAMPLES::
111
+
112
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece
113
+ sage: delta = DeltaPiece('a','b','c')
114
+ sage: delta.color()
115
+ 'white'
116
+ sage: delta = DeltaPiece('0','0','0')
117
+ sage: delta.color()
118
+ 'red'
119
+ sage: delta = DeltaPiece('1','1','1')
120
+ sage: delta.color()
121
+ 'blue'
122
+ sage: delta = DeltaPiece('2','2','2')
123
+ sage: delta.color()
124
+ 'green'
125
+ sage: delta = DeltaPiece('2','K','2')
126
+ sage: delta.color()
127
+ 'orange'
128
+ sage: delta = DeltaPiece('2','T1/2','2')
129
+ sage: delta.color()
130
+ 'yellow'
131
+ """
132
+ colors = {('0', '0', '0'): 'red',
133
+ ('1', '1', '1'): 'blue',
134
+ ('2', '2', '2'): 'green'}
135
+ border = self.border()
136
+ if border in colors:
137
+ color = colors[border]
138
+ elif 'K' in border:
139
+ color = 'orange'
140
+ elif '10' in border:
141
+ color = 'white'
142
+ elif any(label.startswith('T') for label in border):
143
+ color = 'yellow'
144
+ else:
145
+ color = 'white'
146
+ return color
147
+
148
+ def _plot_label(self, label, coords, fontcolor=(0.3, 0.3, 0.3),
149
+ fontsize=15, rotation=0):
150
+ r"""
151
+ TESTS::
152
+
153
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece
154
+ sage: delta = DeltaPiece('2','K','2')
155
+ sage: delta._plot_label('1',(1,1)) # not tested
156
+ """
157
+ if label in ('0', '1', '2'):
158
+ return text(label, coords, color=fontcolor, fontsize=fontsize, rotation=rotation)
159
+ else:
160
+ return Graphics()
161
+
162
+ def _plot_piece(self, coords, border_color=(0.5, 0.5, 0.5),
163
+ border_thickness=1, style='fill'):
164
+ r"""
165
+ TESTS::
166
+
167
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece
168
+ sage: delta = DeltaPiece('2','K','2')
169
+ sage: delta._plot_piece([(1,1),(1,2),(2,2)]) # not tested
170
+ """
171
+ if style == 'fill':
172
+ P = polygon(coords, color=self.color())
173
+ P += polygon(coords, fill=False, color=border_color, thickness=border_thickness)
174
+ return P
175
+ elif style == 'edges':
176
+ if isinstance(self, DeltaPiece):
177
+ edges = ('north_west', 'south', 'north_east')
178
+ elif isinstance(self, NablaPiece):
179
+ edges = ('south_west', 'north', 'south_east')
180
+ else:
181
+ edges = self.edges()
182
+ P = Graphics()
183
+ for (i, edge) in enumerate(edges):
184
+ P += line([coords[i], coords[(i + 1) % 3]],
185
+ color=self.edge_color(edge),
186
+ thickness=border_thickness)
187
+ return P
188
+ else:
189
+ return NotImplemented
190
+
191
+ def edge_color(self, edge) -> str:
192
+ r"""
193
+ Color of the specified edge of ``self`` (to be used when plotting the
194
+ piece).
195
+
196
+ EXAMPLES::
197
+
198
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece
199
+ sage: delta = DeltaPiece('1','0','10')
200
+ sage: delta.edge_color('south')
201
+ 'blue'
202
+ sage: delta.edge_color('north_west')
203
+ 'red'
204
+ sage: delta.edge_color('north_east')
205
+ 'white'
206
+ """
207
+ edge_label = self.edge_label(edge)
208
+ colors = {'1': 'blue', '0': 'red'}
209
+ if edge_label in colors:
210
+ color = colors[edge_label]
211
+ elif 'K' in edge_label:
212
+ color = 'orange'
213
+ elif edge_label.startswith('T'):
214
+ color = 'yellow'
215
+ else:
216
+ color = 'white'
217
+ return color
218
+
219
+ def edge_label(self, edge) -> str:
220
+ r"""
221
+ Return the edge label of ``edge``.
222
+
223
+ EXAMPLES::
224
+
225
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece
226
+ sage: delta = DeltaPiece('2','K','2')
227
+ sage: delta.edge_label('south')
228
+ '2'
229
+ sage: delta.edge_label('north_east')
230
+ '2'
231
+ sage: delta.edge_label('north_west')
232
+ 'K'
233
+ """
234
+ return self._edge_labels[edge]
235
+
236
+ __getitem__ = edge_label
237
+
238
+
239
+ class NablaPiece(PuzzlePiece):
240
+ r"""
241
+ Nabla Piece takes as input three labels, inputted as strings. They label
242
+ the North, Southeast and Southwest edges, respectively.
243
+
244
+ EXAMPLES::
245
+
246
+ sage: from sage.combinat.knutson_tao_puzzles import NablaPiece
247
+ sage: NablaPiece('a','b','c')
248
+ c\a/b
249
+ """
250
+
251
+ def __init__(self, north, south_east, south_west):
252
+ r"""
253
+ INPUT:
254
+
255
+ - ``north``, ``south_east``, ``south_west`` -- strings, which label the edges
256
+
257
+ EXAMPLES::
258
+
259
+ sage: from sage.combinat.knutson_tao_puzzles import NablaPiece
260
+ sage: NablaPiece('1','2','3')
261
+ 3\1/2
262
+ """
263
+ self._edge_labels = dict(north=north, south_east=south_east, south_west=south_west)
264
+
265
+ def __eq__(self, other) -> bool:
266
+ r"""
267
+ TESTS::
268
+
269
+ sage: from sage.combinat.knutson_tao_puzzles import NablaPiece
270
+ sage: n = NablaPiece('a','b','c')
271
+ sage: n1 = NablaPiece('a','b','c')
272
+ sage: n == n1
273
+ True
274
+ sage: n1 = NablaPiece('A','b','c')
275
+ sage: n == n1
276
+ False
277
+ """
278
+ if isinstance(other, NablaPiece):
279
+ return (self.border() == other.border() and
280
+ self._edge_labels == other._edge_labels)
281
+ else:
282
+ return False
283
+
284
+ def __hash__(self):
285
+ r"""
286
+ TESTS::
287
+
288
+ sage: from sage.combinat.knutson_tao_puzzles import NablaPiece
289
+ sage: n = NablaPiece('a','b','c')
290
+ sage: hash(n) == hash(n)
291
+ True
292
+ """
293
+ return hash((NablaPiece, self.border()))
294
+
295
+ def __repr__(self) -> str:
296
+ r"""
297
+ Print the labels of the Nabla piece.
298
+
299
+ EXAMPLES::
300
+
301
+ sage: from sage.combinat.knutson_tao_puzzles import NablaPiece
302
+ sage: NablaPiece('1','2','3')
303
+ 3\1/2
304
+ """
305
+ return r"%s\%s/%s" % (self['south_west'],
306
+ self['north'],
307
+ self['south_east'])
308
+
309
+ def clockwise_rotation(self) -> NablaPiece:
310
+ r"""
311
+ Rotate the Nabla piece by 120 degree clockwise.
312
+
313
+ OUTPUT: Nabla piece
314
+
315
+ EXAMPLES::
316
+
317
+ sage: from sage.combinat.knutson_tao_puzzles import NablaPiece
318
+ sage: nabla = NablaPiece('1','2','3')
319
+ sage: nabla.clockwise_rotation()
320
+ 2\3/1
321
+ """
322
+ return NablaPiece(north=self['south_west'],
323
+ south_east=self['north'],
324
+ south_west=self['south_east'])
325
+
326
+ def half_turn_rotation(self) -> DeltaPiece:
327
+ r"""
328
+ Rotate the Nabla piece by 180 degree.
329
+
330
+ OUTPUT: Delta piece
331
+
332
+ EXAMPLES::
333
+
334
+ sage: from sage.combinat.knutson_tao_puzzles import NablaPiece
335
+ sage: nabla = NablaPiece('1','2','3')
336
+ sage: nabla.half_turn_rotation()
337
+ 2/1\3
338
+ """
339
+ return DeltaPiece(south=self['north'],
340
+ north_west=self['south_east'],
341
+ north_east=self['south_west'])
342
+
343
+ def edges(self) -> tuple:
344
+ r"""
345
+ Return the tuple of edge names.
346
+
347
+ EXAMPLES::
348
+
349
+ sage: from sage.combinat.knutson_tao_puzzles import NablaPiece
350
+ sage: nabla = NablaPiece('1','2','3')
351
+ sage: nabla.edges()
352
+ ('north', 'south_east', 'south_west')
353
+ """
354
+ return ('north', 'south_east', 'south_west')
355
+
356
+
357
+ class DeltaPiece(PuzzlePiece):
358
+ r"""
359
+ Delta Piece takes as input three labels, inputted as strings. They label
360
+ the South, Northwest and Northeast edges, respectively.
361
+
362
+ EXAMPLES::
363
+
364
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece
365
+ sage: DeltaPiece('a','b','c')
366
+ b/a\c
367
+ """
368
+
369
+ def __init__(self, south, north_west, north_east):
370
+ r"""
371
+ INPUT:
372
+
373
+ - ``south``, ``north_west``, ``north_east`` -- strings, which label the edges
374
+
375
+ EXAMPLES::
376
+
377
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece
378
+ sage: DeltaPiece('1','2','3')
379
+ 2/1\3
380
+ """
381
+ self._edge_labels = dict(south=south, north_west=north_west, north_east=north_east)
382
+
383
+ def __eq__(self, other) -> bool:
384
+ r"""
385
+ TESTS::
386
+
387
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece
388
+ sage: delta = DeltaPiece('a','b','c')
389
+ sage: delta1 = DeltaPiece('a','b','c')
390
+ sage: delta == delta1
391
+ True
392
+ sage: delta1 = DeltaPiece('A','b','c')
393
+ sage: delta == delta1
394
+ False
395
+ """
396
+ if isinstance(other, DeltaPiece):
397
+ return (self.border() == other.border() and
398
+ self._edge_labels == other._edge_labels)
399
+ else:
400
+ return False
401
+
402
+ def __hash__(self):
403
+ r"""
404
+ TESTS::
405
+
406
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece
407
+ sage: delta = DeltaPiece('a','b','c')
408
+ sage: hash(delta) == hash(delta)
409
+ True
410
+ """
411
+ return hash((DeltaPiece, self.border()))
412
+
413
+ def __repr__(self) -> str:
414
+ r"""
415
+ Print the labels of the Delta piece.
416
+
417
+ EXAMPLES::
418
+
419
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece
420
+ sage: DeltaPiece('1','2','3')
421
+ 2/1\3
422
+ """
423
+ return r"%s/%s\%s" % (self['north_west'],
424
+ self['south'],
425
+ self['north_east'])
426
+
427
+ def clockwise_rotation(self) -> DeltaPiece:
428
+ r"""
429
+ Rotate the Delta piece by 120 degree clockwise.
430
+
431
+ OUTPUT: Delta piece
432
+
433
+ EXAMPLES::
434
+
435
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece
436
+ sage: delta = DeltaPiece('1','2','3')
437
+ sage: delta.clockwise_rotation()
438
+ 1/3\2
439
+ """
440
+ return DeltaPiece(south=self['north_east'],
441
+ north_west=self['south'],
442
+ north_east=self['north_west'])
443
+
444
+ def half_turn_rotation(self) -> NablaPiece:
445
+ r"""
446
+ Rotate the Delta piece by 180 degree.
447
+
448
+ OUTPUT: Nabla piece
449
+
450
+ EXAMPLES::
451
+
452
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece
453
+ sage: delta = DeltaPiece('1','2','3')
454
+ sage: delta.half_turn_rotation()
455
+ 3\1/2
456
+ """
457
+ return NablaPiece(north=self['south'],
458
+ south_east=self['north_west'],
459
+ south_west=self['north_east'])
460
+
461
+ def edges(self) -> tuple:
462
+ r"""
463
+ Return the tuple of edge names.
464
+
465
+ EXAMPLES::
466
+
467
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece
468
+ sage: delta = DeltaPiece('1','2','3')
469
+ sage: delta.edges()
470
+ ('south', 'north_west', 'north_east')
471
+ """
472
+ return ('south', 'north_west', 'north_east')
473
+
474
+
475
+ class RhombusPiece(PuzzlePiece):
476
+ r"""
477
+ Class of rhombi pieces.
478
+
479
+ To construct a rhombus piece we input a delta and a nabla piece.
480
+ The delta and nabla pieces are joined along the south and north edge,
481
+ respectively.
482
+
483
+ EXAMPLES::
484
+
485
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece, NablaPiece, RhombusPiece
486
+ sage: delta = DeltaPiece('1','2','3')
487
+ sage: nabla = NablaPiece('4','5','6')
488
+ sage: RhombusPiece(delta,nabla)
489
+ 2/\3 6\/5
490
+ """
491
+
492
+ def __init__(self, north_piece, south_piece):
493
+ r"""
494
+ EXAMPLES::
495
+
496
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece, NablaPiece, RhombusPiece
497
+ sage: delta = DeltaPiece('1','2','3')
498
+ sage: nabla = NablaPiece('4','5','6')
499
+ sage: RhombusPiece(delta,nabla)
500
+ 2/\3 6\/5
501
+ """
502
+ self._north_piece = north_piece
503
+ self._south_piece = south_piece
504
+ self._edge_labels = dict(north_west=north_piece['north_west'],
505
+ north_east=north_piece['north_east'],
506
+ south_east=south_piece['south_east'],
507
+ south_west=south_piece['south_west'])
508
+
509
+ def __eq__(self, other) -> bool:
510
+ r"""
511
+ TESTS::
512
+
513
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece, NablaPiece, RhombusPiece
514
+ sage: delta = DeltaPiece('1','2','3')
515
+ sage: nabla = NablaPiece('4','5','6')
516
+ sage: r = RhombusPiece(delta,nabla)
517
+ sage: r == r
518
+ True
519
+ sage: delta1 = DeltaPiece('A','b','c')
520
+ sage: r == RhombusPiece(delta1,nabla)
521
+ False
522
+ """
523
+ if isinstance(other, RhombusPiece):
524
+ return (self.border() == other.border() and
525
+ self._north_piece == other._north_piece and
526
+ self._south_piece == other._south_piece and
527
+ self._edge_labels == other._edge_labels)
528
+ else:
529
+ return False
530
+
531
+ def __hash__(self):
532
+ r"""
533
+ TESTS::
534
+
535
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece, NablaPiece, RhombusPiece
536
+ sage: delta = DeltaPiece('1','2','3')
537
+ sage: nabla = NablaPiece('4','5','6')
538
+ sage: r = RhombusPiece(delta,nabla)
539
+ sage: hash(r) == hash(r)
540
+ True
541
+ """
542
+ return hash((RhombusPiece, self.border()))
543
+
544
+ def __iter__(self):
545
+ r"""
546
+ Return the list of the north and south piece.
547
+
548
+ EXAMPLES::
549
+
550
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece, NablaPiece, RhombusPiece
551
+ sage: delta = DeltaPiece('1','2','3')
552
+ sage: nabla = NablaPiece('4','5','6')
553
+ sage: r = RhombusPiece(delta,nabla)
554
+ sage: list(r)
555
+ [2/1\3, 6\4/5]
556
+ """
557
+ yield self._north_piece
558
+ yield self._south_piece
559
+
560
+ def north_piece(self) -> DeltaPiece:
561
+ r"""
562
+ Return the north piece.
563
+
564
+ EXAMPLES::
565
+
566
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece, NablaPiece, RhombusPiece
567
+ sage: delta = DeltaPiece('1','2','3')
568
+ sage: nabla = NablaPiece('4','5','6')
569
+ sage: r = RhombusPiece(delta,nabla)
570
+ sage: r.north_piece()
571
+ 2/1\3
572
+ """
573
+ return self._north_piece
574
+
575
+ def south_piece(self) -> NablaPiece:
576
+ r"""
577
+ Return the south piece.
578
+
579
+ EXAMPLES::
580
+
581
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece, NablaPiece, RhombusPiece
582
+ sage: delta = DeltaPiece('1','2','3')
583
+ sage: nabla = NablaPiece('4','5','6')
584
+ sage: r = RhombusPiece(delta,nabla)
585
+ sage: r.south_piece()
586
+ 6\4/5
587
+ """
588
+ return self._south_piece
589
+
590
+ def __repr__(self) -> str:
591
+ r"""
592
+ EXAMPLES::
593
+
594
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece, NablaPiece, RhombusPiece
595
+ sage: delta = DeltaPiece('1','2','3')
596
+ sage: nabla = NablaPiece('4','5','6')
597
+ sage: RhombusPiece(delta,nabla)
598
+ 2/\3 6\/5
599
+ """
600
+ return r"%s/\%s %s\/%s" % (self['north_west'], self['north_east'],
601
+ self['south_west'], self['south_east'])
602
+
603
+ def edges(self) -> tuple:
604
+ r"""
605
+ Return the tuple of edge names.
606
+
607
+ EXAMPLES::
608
+
609
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece, NablaPiece, RhombusPiece
610
+ sage: delta = DeltaPiece('1','2','3')
611
+ sage: nabla = NablaPiece('4','5','6')
612
+ sage: RhombusPiece(delta,nabla).edges()
613
+ ('north_west', 'north_east', 'south_east', 'south_west')
614
+ """
615
+ return ('north_west', 'north_east', 'south_east', 'south_west')
616
+
617
+
618
+ class PuzzlePieces:
619
+ r"""
620
+ Construct a valid set of puzzle pieces.
621
+
622
+ This class constructs the set of valid puzzle pieces. It can take a list of
623
+ forbidden border labels as input. These labels are forbidden from appearing
624
+ on the south edge of a puzzle filling. The user can add valid nabla or
625
+ delta pieces and specify which rotations of these pieces are legal. For
626
+ example, ``rotations=0`` does not add any additional pieces (only the piece
627
+ itself), ``rotations=60`` adds six pieces (the pieces and its rotations by
628
+ 60, 120, 180, 240, 300), etc..
629
+
630
+ EXAMPLES::
631
+
632
+ sage: from sage.combinat.knutson_tao_puzzles import PuzzlePieces, NablaPiece
633
+ sage: forbidden_border_labels = ['10']
634
+ sage: pieces = PuzzlePieces(forbidden_border_labels)
635
+ sage: pieces.add_piece(NablaPiece('0','0','0'), rotations=60)
636
+ sage: pieces.add_piece(NablaPiece('1','1','1'), rotations=60)
637
+ sage: pieces.add_piece(NablaPiece('1','0','10'), rotations=60)
638
+ sage: pieces
639
+ Nablas : [0\0/0, 0\10/1, 10\1/0, 1\0/10, 1\1/1]
640
+ Deltas : [0/0\0, 0/1\10, 1/10\0, 1/1\1, 10/0\1]
641
+
642
+ The user can obtain the list of valid rhombi pieces as follows::
643
+
644
+ sage: sorted([p for p in pieces.rhombus_pieces()], key=str)
645
+ [0/\0 0\/0, 0/\0 1\/10, 0/\10 10\/0, 0/\10 1\/1, 1/\0 0\/1,
646
+ 1/\1 10\/0, 1/\1 1\/1, 10/\1 0\/0, 10/\1 1\/10]
647
+ """
648
+
649
+ def __init__(self, forbidden_border_labels=None):
650
+ r"""
651
+ INPUT:
652
+
653
+ - ``forbidden_border_labels`` -- list of forbidden border labels given as strings
654
+
655
+ TESTS::
656
+
657
+ sage: from sage.combinat.knutson_tao_puzzles import PuzzlePieces
658
+ sage: forbidden_border_labels = ['10']
659
+ sage: pieces = PuzzlePieces(forbidden_border_labels)
660
+ sage: pieces
661
+ Nablas : []
662
+ Deltas : []
663
+
664
+ sage: PuzzlePieces('10')
665
+ Traceback (most recent call last):
666
+ ...
667
+ TypeError: Input must be a list
668
+ """
669
+ self._nabla_pieces = set()
670
+ self._delta_pieces = set()
671
+ if forbidden_border_labels is None:
672
+ forbidden_border_labels = []
673
+ if not isinstance(forbidden_border_labels, list):
674
+ raise TypeError("Input must be a list")
675
+ self._forbidden_border_labels = forbidden_border_labels
676
+
677
+ def __eq__(self, other) -> bool:
678
+ r"""
679
+ TESTS::
680
+
681
+ sage: from sage.combinat.knutson_tao_puzzles import H_grassmannian_pieces
682
+ sage: x = H_grassmannian_pieces()
683
+ sage: y = H_grassmannian_pieces()
684
+ sage: x == y
685
+ True
686
+ """
687
+ if isinstance(other, type(self)):
688
+ return self.__dict__ == other.__dict__
689
+ else:
690
+ return False
691
+
692
+ def __hash__(self):
693
+ r"""
694
+ TESTS::
695
+
696
+ sage: from sage.combinat.knutson_tao_puzzles import H_grassmannian_pieces
697
+ sage: x = H_grassmannian_pieces()
698
+ sage: hash(x) == hash(x)
699
+ True
700
+ """
701
+ return hash((type(self), repr(self)))
702
+
703
+ def add_piece(self, piece, rotations=120):
704
+ r"""
705
+ Add ``piece`` to the list of pieces.
706
+
707
+ INPUT:
708
+
709
+ - ``piece`` -- a nabla piece or a delta piece
710
+ - ``rotations`` -- (default: 120) 0, 60, 120, 180
711
+
712
+ The user can add valid nabla or delta pieces and specify
713
+ which rotations of these pieces are legal. For example, ``rotations=0``
714
+ does not add any additional pieces (only the piece itself), ``rotations=60`` adds
715
+ six pieces (namely three delta and three nabla pieces), while
716
+ ``rotations=120`` adds only delta or nabla (depending on which piece ``self`` is).
717
+ ``rotations=180`` adds the piece and its 180 degree rotation, i.e. one delta and one
718
+ nabla piece.
719
+
720
+ EXAMPLES::
721
+
722
+ sage: from sage.combinat.knutson_tao_puzzles import PuzzlePieces, DeltaPiece
723
+ sage: delta = DeltaPiece('a','b','c')
724
+ sage: pieces = PuzzlePieces()
725
+ sage: pieces
726
+ Nablas : []
727
+ Deltas : []
728
+ sage: pieces.add_piece(delta)
729
+ sage: pieces
730
+ Nablas : []
731
+ Deltas : [a/c\b, b/a\c, c/b\a]
732
+
733
+ sage: pieces = PuzzlePieces()
734
+ sage: pieces.add_piece(delta,rotations=0)
735
+ sage: pieces
736
+ Nablas : []
737
+ Deltas : [b/a\c]
738
+
739
+ sage: pieces = PuzzlePieces()
740
+ sage: pieces.add_piece(delta,rotations=60)
741
+ sage: pieces
742
+ Nablas : [a\b/c, b\c/a, c\a/b]
743
+ Deltas : [a/c\b, b/a\c, c/b\a]
744
+ """
745
+ if isinstance(piece, NablaPiece):
746
+ pieces_list = self._nabla_pieces
747
+ else:
748
+ pieces_list = self._delta_pieces
749
+ pieces_list.add(piece)
750
+ if rotations == 120:
751
+ pieces_list.add(piece.clockwise_rotation())
752
+ pieces_list.add(piece.clockwise_rotation().clockwise_rotation())
753
+ elif rotations == 180:
754
+ self.add_piece(piece.half_turn_rotation(), rotations=0)
755
+ elif rotations == 60:
756
+ self.add_piece(piece, rotations=120)
757
+ self.add_piece(piece.half_turn_rotation(), rotations=120)
758
+
759
+ def add_forbidden_label(self, label):
760
+ r"""
761
+ Add forbidden border labels.
762
+
763
+ INPUT:
764
+
765
+ - ``label`` -- string specifying a new forbidden label
766
+
767
+ EXAMPLES::
768
+
769
+ sage: from sage.combinat.knutson_tao_puzzles import PuzzlePieces
770
+ sage: pieces = PuzzlePieces()
771
+ sage: pieces.add_forbidden_label('1')
772
+ sage: pieces._forbidden_border_labels
773
+ ['1']
774
+ sage: pieces.add_forbidden_label('2')
775
+ sage: pieces._forbidden_border_labels
776
+ ['1', '2']
777
+ """
778
+ self._forbidden_border_labels.append(label)
779
+
780
+ def add_T_piece(self, label1, label2):
781
+ r"""
782
+ Add a nabla and delta piece with ``label1`` and ``label2``.
783
+
784
+ This method adds a nabla piece with edges ``label2``\ T``label1``|``label2`` / ``label1``.
785
+ and a delta piece with edges ``label1``/ T``label1``|``label2`` \ ``label2``.
786
+ It also adds T``label1``|``label2`` to the forbidden list.
787
+
788
+ EXAMPLES::
789
+
790
+ sage: from sage.combinat.knutson_tao_puzzles import PuzzlePieces
791
+ sage: pieces = PuzzlePieces()
792
+ sage: pieces.add_T_piece('1','3')
793
+ sage: pieces
794
+ Nablas : [3\T1|3/1]
795
+ Deltas : [1/T1|3\3]
796
+ sage: pieces._forbidden_border_labels
797
+ ['T1|3']
798
+ """
799
+ self.add_forbidden_label('T%s|%s' % (label1, label2))
800
+ self.add_piece(NablaPiece('T%s|%s' % (label1, label2), label1, label2), rotations=180)
801
+
802
+ def __repr__(self) -> str:
803
+ r"""
804
+ TESTS::
805
+
806
+ sage: from sage.combinat.knutson_tao_puzzles import PuzzlePieces, DeltaPiece
807
+ sage: pieces = PuzzlePieces()
808
+ sage: delta = DeltaPiece('a','b','c')
809
+ sage: pieces.add_piece(delta,rotations=60)
810
+ sage: pieces
811
+ Nablas : [a\b/c, b\c/a, c\a/b]
812
+ Deltas : [a/c\b, b/a\c, c/b\a]
813
+ """
814
+ s = "Nablas : %s\n" % sorted(self._nabla_pieces, key=str)
815
+ s += "Deltas : %s" % sorted(self._delta_pieces, key=str)
816
+ return s
817
+
818
+ def delta_pieces(self):
819
+ r"""
820
+ Return the delta pieces as a set.
821
+
822
+ EXAMPLES::
823
+
824
+ sage: from sage.combinat.knutson_tao_puzzles import PuzzlePieces, DeltaPiece
825
+ sage: pieces = PuzzlePieces()
826
+ sage: delta = DeltaPiece('a','b','c')
827
+ sage: pieces.add_piece(delta,rotations=60)
828
+ sage: sorted([p for p in pieces.delta_pieces()], key=str)
829
+ [a/c\b, b/a\c, c/b\a]
830
+ """
831
+ return self._delta_pieces
832
+
833
+ def nabla_pieces(self):
834
+ r"""
835
+ Return the nabla pieces as a set.
836
+
837
+ EXAMPLES::
838
+
839
+ sage: from sage.combinat.knutson_tao_puzzles import PuzzlePieces, DeltaPiece
840
+ sage: pieces = PuzzlePieces()
841
+ sage: delta = DeltaPiece('a','b','c')
842
+ sage: pieces.add_piece(delta,rotations=60)
843
+ sage: sorted([p for p in pieces.nabla_pieces()], key=str)
844
+ [a\b/c, b\c/a, c\a/b]
845
+ """
846
+ return self._nabla_pieces
847
+
848
+ def rhombus_pieces(self) -> set:
849
+ r"""
850
+ Return a set of all allowable rhombus pieces.
851
+
852
+ Allowable rhombus pieces are those where the south edge of the delta
853
+ piece equals the north edge of the nabla piece.
854
+
855
+ EXAMPLES::
856
+
857
+ sage: from sage.combinat.knutson_tao_puzzles import PuzzlePieces, DeltaPiece
858
+ sage: pieces = PuzzlePieces()
859
+ sage: delta = DeltaPiece('a','b','c')
860
+ sage: pieces.add_piece(delta,rotations=60)
861
+ sage: sorted([p for p in pieces.rhombus_pieces()], key=str)
862
+ [a/\b b\/a, b/\c c\/b, c/\a a\/c]
863
+ """
864
+ rhombi = set()
865
+ for nabla in self._nabla_pieces:
866
+ for delta in self._delta_pieces:
867
+ if delta['south'] == nabla['north']:
868
+ rhombi.add(RhombusPiece(delta, nabla))
869
+ return rhombi
870
+
871
+ def boundary_deltas(self) -> tuple:
872
+ r"""
873
+ Return deltas with south edges not in the forbidden list.
874
+
875
+ EXAMPLES::
876
+
877
+ sage: from sage.combinat.knutson_tao_puzzles import PuzzlePieces, DeltaPiece
878
+ sage: pieces = PuzzlePieces(['a'])
879
+ sage: delta = DeltaPiece('a','b','c')
880
+ sage: pieces.add_piece(delta,rotations=60)
881
+ sage: sorted([p for p in pieces.boundary_deltas()], key=str)
882
+ [a/c\b, c/b\a]
883
+ """
884
+ return tuple(delta for delta in self.delta_pieces()
885
+ if delta['south'] not in self._forbidden_border_labels)
886
+
887
+
888
+ def H_grassmannian_pieces():
889
+ r"""
890
+ Define the puzzle pieces used in computing the cohomology of the Grassmannian.
891
+
892
+ REFERENCES:
893
+
894
+ .. [KTW] Allen Knutson, Terence Tao, Christopher Woodward,
895
+ The honeycomb model of GL(n) tensor products II: Puzzles determine facets of the Littlewood-Richardson cone,
896
+ :arxiv:`math/0107011`
897
+
898
+ EXAMPLES::
899
+
900
+ sage: from sage.combinat.knutson_tao_puzzles import H_grassmannian_pieces
901
+ sage: H_grassmannian_pieces()
902
+ Nablas : [0\0/0, 0\10/1, 10\1/0, 1\0/10, 1\1/1]
903
+ Deltas : [0/0\0, 0/1\10, 1/10\0, 1/1\1, 10/0\1]
904
+ """
905
+ forbidden_border_labels = ['10']
906
+ pieces = PuzzlePieces(forbidden_border_labels)
907
+ pieces.add_piece(NablaPiece('0', '0', '0'), rotations=60)
908
+ pieces.add_piece(NablaPiece('1', '1', '1'), rotations=60)
909
+ pieces.add_piece(NablaPiece('1', '0', '10'), rotations=60)
910
+ return pieces
911
+
912
+
913
+ def HT_grassmannian_pieces():
914
+ r"""
915
+ Define the puzzle pieces used in computing the torus-equivariant cohomology of the Grassmannian.
916
+
917
+ REFERENCES:
918
+
919
+ .. [KT2003] Allen Knutson, Terence Tao, Puzzles and (equivariant) cohomology of Grassmannians,
920
+ Duke Math. J. 119 (2003) 221
921
+
922
+ EXAMPLES::
923
+
924
+ sage: from sage.combinat.knutson_tao_puzzles import HT_grassmannian_pieces
925
+ sage: HT_grassmannian_pieces()
926
+ Nablas : [0\0/0, 0\10/1, 10\1/0, 1\0/10, 1\1/1, 1\T0|1/0]
927
+ Deltas : [0/0\0, 0/1\10, 0/T0|1\1, 1/10\0, 1/1\1, 10/0\1]
928
+ """
929
+ pieces = H_grassmannian_pieces()
930
+ pieces.add_T_piece('0', '1')
931
+ return pieces
932
+
933
+
934
+ def K_grassmannian_pieces():
935
+ r"""
936
+ Define the puzzle pieces used in computing the K-theory of the Grassmannian.
937
+
938
+ REFERENCES:
939
+
940
+ .. [Buch00] \A. Buch, A Littlewood-Richardson rule for the K-theory of Grassmannians, :arxiv:`math.AG/0004137`
941
+
942
+ EXAMPLES::
943
+
944
+ sage: from sage.combinat.knutson_tao_puzzles import K_grassmannian_pieces
945
+ sage: K_grassmannian_pieces()
946
+ Nablas : [0\0/0, 0\10/1, 0\K/1, 10\1/0, 1\0/10, 1\0/K, 1\1/1, K\1/0]
947
+ Deltas : [0/0\0, 0/1\10, 1/10\0, 1/1\1, 10/0\1, K/K\K]
948
+ """
949
+ pieces = H_grassmannian_pieces()
950
+ pieces.add_forbidden_label('K')
951
+ pieces.add_piece(NablaPiece('0', 'K', '1'), rotations=120)
952
+ pieces.add_piece(DeltaPiece('K', 'K', 'K'), rotations=0)
953
+ return pieces
954
+
955
+
956
+ def H_two_step_pieces():
957
+ r"""
958
+ Define the puzzle pieces used in two step flags.
959
+
960
+ This rule is currently only conjecturally true. See [BuchKreschTamvakis03]_.
961
+
962
+ REFERENCES:
963
+
964
+ .. [BuchKreschTamvakis03] \A. Buch, A. Kresch, H. Tamvakis, Gromov-Witten invariants on Grassmannian, :arxiv:`math/0306388`
965
+
966
+ EXAMPLES::
967
+
968
+ sage: from sage.combinat.knutson_tao_puzzles import H_two_step_pieces
969
+ sage: H_two_step_pieces()
970
+ Nablas : [(21)0\21/0, 0\(21)0/21, 0\0/0, 0\10/1, 0\20/2, 10\1/0, 10\2(10)/2, 1\0/10, 1\1/1, 1\21/2,
971
+ 2(10)\2/10, 20\2/0, 21\0/(21)0, 21\2/1, 2\0/20, 2\1/21, 2\10/2(10), 2\2/2]
972
+ Deltas : [(21)0/0\21, 0/0\0, 0/1\10, 0/21\(21)0, 0/2\20, 1/10\0, 1/1\1, 1/2\21, 10/0\1, 10/2\2(10),
973
+ 2(10)/10\2, 2/2(10)\10, 2/20\0, 2/21\1, 2/2\2, 20/0\2, 21/(21)0\0, 21/1\2]
974
+ """
975
+ forbidden_border_labels = ['10', '20', '21', '(21)0', '2(10)']
976
+ pieces = PuzzlePieces(forbidden_border_labels)
977
+ for i in ('0', '1', '2'):
978
+ pieces.add_piece(DeltaPiece(i, i, i), rotations=60)
979
+ for i, j in (('1', '0'), ('2', '0'), ('2', '1')):
980
+ pieces.add_piece(DeltaPiece(i + j, i, j), rotations=60)
981
+ pieces.add_piece(DeltaPiece('(21)0', '21', '0'), rotations=60)
982
+ pieces.add_piece(DeltaPiece('2(10)', '2', '10'), rotations=60)
983
+ return pieces
984
+
985
+
986
+ def HT_two_step_pieces():
987
+ r"""
988
+ Define the puzzle pieces used in computing the equivariant two step puzzle pieces.
989
+
990
+ For the puzzle pieces, see Figure 26 on page 22 of [CoskunVakil06]_.
991
+
992
+ REFERENCES:
993
+
994
+ .. [CoskunVakil06] \I. Coskun, R. Vakil, Geometric positivity in the cohomology of homogeneous spaces
995
+ and generalized Schubert calculus, :arxiv:`math/0610538`
996
+
997
+ EXAMPLES::
998
+
999
+ sage: from sage.combinat.knutson_tao_puzzles import HT_two_step_pieces
1000
+ sage: HT_two_step_pieces()
1001
+ Nablas : [(21)0\21/0, 0\(21)0/21, 0\0/0, 0\10/1, 0\20/2, 10\1/0, 10\2(10)/2,
1002
+ 1\0/10, 1\1/1, 1\21/2, 1\T0|1/0, 2(10)\2/10, 20\2/0, 21\0/(21)0, 21\2/1, 21\T0|21/0,
1003
+ 21\T10|21/10, 2\0/20, 2\1/21, 2\10/2(10), 2\2/2, 2\T0|2/0, 2\T10|2/10, 2\T1|2/1]
1004
+ Deltas : [(21)0/0\21, 0/0\0, 0/1\10, 0/21\(21)0, 0/2\20, 0/T0|1\1, 0/T0|21\21, 0/T0|2\2,
1005
+ 1/10\0, 1/1\1, 1/2\21, 1/T1|2\2, 10/0\1, 10/2\2(10), 10/T10|21\21, 10/T10|2\2, 2(10)/10\2,
1006
+ 2/2(10)\10, 2/20\0, 2/21\1, 2/2\2, 20/0\2, 21/(21)0\0, 21/1\2]
1007
+ """
1008
+ pieces = H_two_step_pieces()
1009
+ for label1, label2 in (('0', '1'), ('0', '2'), ('1', '2'),
1010
+ ('10', '2'), ('0', '21'), ('10', '21')):
1011
+ pieces.add_T_piece(label1, label2)
1012
+ return pieces
1013
+
1014
+
1015
+ def BK_pieces(max_letter):
1016
+ r"""
1017
+ The puzzle pieces used in computing the Belkale-Kumar coefficients for any
1018
+ partial flag variety in type `A`.
1019
+
1020
+ There are two types of puzzle pieces:
1021
+
1022
+ - a triangle, with each edge labeled with the same letter;
1023
+ - a rhombus, with edges labeled `i`, `j`, `i`, `j` in clockwise order with
1024
+ `i > j`.
1025
+
1026
+ Each of these is rotated by 60 degrees, but not reflected.
1027
+
1028
+ We model the rhombus pieces as two triangles: a delta piece north-west
1029
+ label `i`, north-east label `j` and south label `i(j)`; and a nabla piece
1030
+ with south-east label `i`, south-west label `j` and north label `i(j)`.
1031
+
1032
+ INPUT:
1033
+
1034
+ - ``max_letter`` -- positive integer specifying the number of steps in the
1035
+ partial flag variety, equivalently, the number of elements in the
1036
+ alphabet for the edge labels. The smallest label is `1`.
1037
+
1038
+ REFERENCES:
1039
+
1040
+ .. [KnutsonPurbhoo10] \A. Knutson, K. Purbhoo, Product and puzzle formulae
1041
+ for `GL_n` Belkale-Kumar coefficients, :arxiv:`1008.4979`
1042
+
1043
+ EXAMPLES::
1044
+
1045
+ sage: from sage.combinat.knutson_tao_puzzles import BK_pieces
1046
+ sage: BK_pieces(3)
1047
+ Nablas : [1\1/1, 1\2(1)/2, 1\3(1)/3, 2(1)\2/1, 2\1/2(1), 2\2/2, 2\3(2)/3, 3(1)\3/1, 3(2)\3/2, 3\1/3(1), 3\2/3(2), 3\3/3]
1048
+ Deltas : [1/1\1, 1/2\2(1), 1/3\3(1), 2(1)/1\2, 2/2(1)\1, 2/2\2, 2/3\3(2), 3(1)/1\3, 3(2)/2\3, 3/3(1)\1, 3/3(2)\2, 3/3\3]
1049
+ """
1050
+ forbidden_border_labels = ['%s(%s)' % (i, j)
1051
+ for i in range(1, max_letter + 1)
1052
+ for j in range(1, i)]
1053
+ pieces = PuzzlePieces(forbidden_border_labels)
1054
+ for i in range(1, max_letter + 1):
1055
+ piece = DeltaPiece('%s' % i, '%s' % i, '%s' % i)
1056
+ pieces.add_piece(piece, rotations=60)
1057
+ for j in range(1, i):
1058
+ piece = DeltaPiece(north_west='%s' % i, north_east='%s' % j,
1059
+ south='%s(%s)' % (i, j))
1060
+ pieces.add_piece(piece, rotations=60)
1061
+ return pieces
1062
+
1063
+
1064
+ class PuzzleFilling:
1065
+ r"""
1066
+ Create partial puzzles and provides methods to build puzzles from them.
1067
+ """
1068
+
1069
+ def __init__(self, north_west_labels, north_east_labels):
1070
+ r"""
1071
+ TESTS::
1072
+
1073
+ sage: from sage.combinat.knutson_tao_puzzles import PuzzleFilling
1074
+ sage: P = PuzzleFilling('0101','0101')
1075
+ sage: P
1076
+ {}
1077
+ """
1078
+ self._nw_labels = tuple(north_west_labels)
1079
+ self._ne_labels = tuple(north_east_labels)
1080
+ self._squares = {}
1081
+ self._n = len(self._nw_labels)
1082
+ self._kink_coordinates = (1, self._n)
1083
+
1084
+ def __getitem__(self, key):
1085
+ r"""
1086
+ TESTS::
1087
+
1088
+ sage: from sage.combinat.knutson_tao_puzzles import KnutsonTaoPuzzleSolver
1089
+ sage: ps = KnutsonTaoPuzzleSolver("H")
1090
+ sage: puzzle = ps('0101','1001')[0]
1091
+ sage: puzzle
1092
+ {(1, 1): 0/1\10,
1093
+ (1, 2): 1/\1 10\/0,
1094
+ (1, 3): 0/\10 1\/1,
1095
+ (1, 4): 1/\1 10\/0,
1096
+ (2, 2): 0/0\0,
1097
+ (2, 3): 1/\0 0\/1,
1098
+ (2, 4): 0/\0 0\/0,
1099
+ (3, 3): 1/1\1,
1100
+ (3, 4): 0/\0 1\/10,
1101
+ (4, 4): 10/0\1}
1102
+ sage: puzzle[(1,2)] # indirect doctest
1103
+ 1/\1 10\/0
1104
+ """
1105
+ return self._squares[key]
1106
+
1107
+ def kink_coordinates(self) -> tuple:
1108
+ r"""
1109
+ Provide the coordinates of the kinks.
1110
+
1111
+ The kink coordinates are the coordinates up to which the puzzle has already
1112
+ been built. The kink starts in the north corner and then moves down the diagonals
1113
+ as the puzzles is built.
1114
+
1115
+ EXAMPLES::
1116
+
1117
+ sage: from sage.combinat.knutson_tao_puzzles import PuzzleFilling
1118
+ sage: P = PuzzleFilling('0101','0101')
1119
+ sage: P
1120
+ {}
1121
+ sage: P.kink_coordinates()
1122
+ (1, 4)
1123
+ """
1124
+ return self._kink_coordinates
1125
+
1126
+ def is_in_south_edge(self) -> bool:
1127
+ r"""
1128
+ Check whether kink coordinates of partial puzzle is in south corner.
1129
+
1130
+ EXAMPLES::
1131
+
1132
+ sage: from sage.combinat.knutson_tao_puzzles import PuzzleFilling
1133
+ sage: P = PuzzleFilling('0101','0101')
1134
+ sage: P.is_in_south_edge()
1135
+ False
1136
+ """
1137
+ i, j = self.kink_coordinates()
1138
+ return i == j
1139
+
1140
+ def north_west_label_of_kink(self):
1141
+ r"""
1142
+ Return north-west label of kink.
1143
+
1144
+ EXAMPLES::
1145
+
1146
+ sage: from sage.combinat.knutson_tao_puzzles import PuzzleFilling
1147
+ sage: P = PuzzleFilling('0101','0101')
1148
+ sage: P.north_west_label_of_kink()
1149
+ '1'
1150
+ """
1151
+ (i, j) = self.kink_coordinates()
1152
+ if i == 1:
1153
+ return self._nw_labels[j - 1]
1154
+ else:
1155
+ return self._squares[i - 1, j]['south_east']
1156
+
1157
+ def north_east_label_of_kink(self):
1158
+ r"""
1159
+ Return north east label of kink.
1160
+
1161
+ EXAMPLES::
1162
+
1163
+ sage: from sage.combinat.knutson_tao_puzzles import PuzzleFilling
1164
+ sage: P = PuzzleFilling('0101','0101')
1165
+ sage: P.north_east_label_of_kink()
1166
+ '0'
1167
+ """
1168
+ (i, j) = self.kink_coordinates()
1169
+ if j == self._n:
1170
+ return self._ne_labels[i - 1]
1171
+ else:
1172
+ return self._squares[i, j + 1]['south_west']
1173
+
1174
+ def is_completed(self):
1175
+ r"""
1176
+ Whether partial puzzle is complete (completely filled) or not.
1177
+
1178
+ EXAMPLES::
1179
+
1180
+ sage: from sage.combinat.knutson_tao_puzzles import PuzzleFilling
1181
+ sage: P = PuzzleFilling('0101','0101')
1182
+ sage: P.is_completed()
1183
+ False
1184
+
1185
+ sage: from sage.combinat.knutson_tao_puzzles import KnutsonTaoPuzzleSolver
1186
+ sage: ps = KnutsonTaoPuzzleSolver("H")
1187
+ sage: puzzle = ps('0101','1001')[0]
1188
+ sage: puzzle.is_completed()
1189
+ True
1190
+ """
1191
+ i, _ = self.kink_coordinates()
1192
+ return i == self._n + 1
1193
+
1194
+ def south_labels(self):
1195
+ r"""
1196
+ Return south labels for completed puzzle.
1197
+
1198
+ EXAMPLES::
1199
+
1200
+ sage: from sage.combinat.knutson_tao_puzzles import KnutsonTaoPuzzleSolver
1201
+ sage: ps = KnutsonTaoPuzzleSolver("H")
1202
+ sage: ps('0101','1001')[0].south_labels()
1203
+ ('1', '0', '1', '0')
1204
+ """
1205
+ # TODO: return ''.join(self[i, i]['south'] for i in range(1, self._n + 1))
1206
+ return tuple([self[i, i]['south'] for i in range(1, self._n + 1)])
1207
+
1208
+ def add_piece(self, piece):
1209
+ r"""
1210
+ Add ``piece`` to partial puzzle.
1211
+
1212
+ EXAMPLES::
1213
+
1214
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece, PuzzleFilling
1215
+ sage: piece = DeltaPiece('0','1','0')
1216
+ sage: P = PuzzleFilling('0101','0101'); P
1217
+ {}
1218
+ sage: P.add_piece(piece); P
1219
+ {(1, 4): 1/0\0}
1220
+ """
1221
+ i, j = self.kink_coordinates()
1222
+ self._squares[i, j] = piece
1223
+ if isinstance(piece, DeltaPiece):
1224
+ i += 1
1225
+ j = self._n
1226
+ else:
1227
+ j -= 1
1228
+ self._kink_coordinates = (i, j)
1229
+
1230
+ def add_pieces(self, pieces):
1231
+ r"""
1232
+ Add ``piece`` to partial puzzle.
1233
+
1234
+ INPUT:
1235
+
1236
+ - ``pieces`` -- tuple of pieces
1237
+
1238
+ EXAMPLES::
1239
+
1240
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece, PuzzleFilling
1241
+ sage: P = PuzzleFilling('0101','0101'); P
1242
+ {}
1243
+ sage: piece = DeltaPiece('0','1','0')
1244
+ sage: pieces = [piece,piece]
1245
+ sage: P.add_pieces(pieces)
1246
+ sage: P
1247
+ {(1, 4): 1/0\0, (2, 4): 1/0\0}
1248
+ """
1249
+ i, j = self.kink_coordinates()
1250
+ for piece in pieces:
1251
+ self._squares[i, j] = piece
1252
+ if isinstance(piece, DeltaPiece):
1253
+ i += 1
1254
+ j = self._n
1255
+ else:
1256
+ j -= 1
1257
+ self._kink_coordinates = (i, j)
1258
+
1259
+ def copy(self):
1260
+ r"""
1261
+ Return copy of ``self``.
1262
+
1263
+ EXAMPLES::
1264
+
1265
+
1266
+ sage: from sage.combinat.knutson_tao_puzzles import DeltaPiece, PuzzleFilling
1267
+ sage: piece = DeltaPiece('0','1','0')
1268
+ sage: P = PuzzleFilling('0101','0101'); P
1269
+ {}
1270
+ sage: PP = P.copy()
1271
+ sage: P.add_piece(piece); P
1272
+ {(1, 4): 1/0\0}
1273
+ sage: PP
1274
+ {}
1275
+ """
1276
+ PP = PuzzleFilling(self._nw_labels, self._ne_labels)
1277
+ PP._squares = self._squares.copy()
1278
+ PP._kink_coordinates = self._kink_coordinates
1279
+ PP._n = self._n
1280
+ return PP
1281
+
1282
+ def contribution(self):
1283
+ r"""
1284
+ Return equivariant contributions from ``self`` in polynomial ring.
1285
+
1286
+ EXAMPLES::
1287
+
1288
+ sage: from sage.combinat.knutson_tao_puzzles import KnutsonTaoPuzzleSolver
1289
+ sage: ps = KnutsonTaoPuzzleSolver("HT")
1290
+ sage: puzzles = ps('0101','1001')
1291
+ sage: sorted([p.contribution() for p in puzzles], key=str)
1292
+ [1, y1 - y3]
1293
+ """
1294
+ R = PolynomialRing(Integers(), 'y', self._n + 1)
1295
+ y = R.gens()
1296
+ z = R.one()
1297
+ for i in range(1, self._n + 1):
1298
+ for j in range(i + 1, self._n + 1):
1299
+ if self[i, j].north_piece()['south'].startswith('T'):
1300
+ z *= y[i] - y[j]
1301
+ if self[i, j].north_piece()['south'].startswith('K'):
1302
+ z *= -1
1303
+ return z
1304
+
1305
+ def __repr__(self):
1306
+ r"""
1307
+ TESTS::
1308
+
1309
+ sage: from sage.combinat.knutson_tao_puzzles import H_grassmannian_pieces, PuzzleFilling
1310
+ sage: P = PuzzleFilling('0101','0101'); P
1311
+ {}
1312
+ sage: P.__repr__()
1313
+ '{}'
1314
+ """
1315
+ from pprint import pformat
1316
+ return pformat(self._squares)
1317
+
1318
+ def __iter__(self):
1319
+ r"""
1320
+ Iterator.
1321
+
1322
+ TESTS::
1323
+
1324
+ sage: from sage.combinat.knutson_tao_puzzles import KnutsonTaoPuzzleSolver
1325
+ sage: ps = KnutsonTaoPuzzleSolver("H")
1326
+ sage: puzzle = ps('0101','1001')[0]
1327
+ sage: puzzle
1328
+ {(1, 1): 0/1\10,
1329
+ (1, 2): 1/\1 10\/0,
1330
+ (1, 3): 0/\10 1\/1,
1331
+ (1, 4): 1/\1 10\/0,
1332
+ (2, 2): 0/0\0,
1333
+ (2, 3): 1/\0 0\/1,
1334
+ (2, 4): 0/\0 0\/0,
1335
+ (3, 3): 1/1\1,
1336
+ (3, 4): 0/\0 1\/10,
1337
+ (4, 4): 10/0\1}
1338
+ sage: [p for p in puzzle]
1339
+ [1/\1 10\/0,
1340
+ 0/\10 1\/1,
1341
+ 0/\0 0\/0,
1342
+ 1/\1 10\/0,
1343
+ 1/\0 0\/1,
1344
+ 0/\0 1\/10,
1345
+ 0/1\10,
1346
+ 0/0\0,
1347
+ 1/1\1,
1348
+ 10/0\1]
1349
+ """
1350
+ for d in range(self._n):
1351
+ for k in range(d + 1):
1352
+ yield self[k + 1, self._n - d + k]
1353
+
1354
+ def plot(self, labels=True, style='fill'):
1355
+ r"""
1356
+ Plot completed puzzle.
1357
+
1358
+ EXAMPLES::
1359
+
1360
+ sage: from sage.combinat.knutson_tao_puzzles import KnutsonTaoPuzzleSolver
1361
+ sage: ps = KnutsonTaoPuzzleSolver("H")
1362
+ sage: puzzle = ps('0101','1001')[0]
1363
+ sage: puzzle.plot() #not tested
1364
+ sage: puzzle.plot(style='fill') #not tested
1365
+ sage: puzzle.plot(style='edges') #not tested
1366
+ """
1367
+ P = Graphics()
1368
+ coords = [(k, -d) for d in range(self._n) for k in range(-d, d + 1, 2)]
1369
+ for ((k, d), piece) in zip(coords, self):
1370
+ if isinstance(piece, RhombusPiece):
1371
+ for (i, triangle) in enumerate(piece):
1372
+ P += triangle._plot_piece([(k, d - 2 * i), (k - 1, d - 1), (k + 1, d - 1)], style=style)
1373
+ if labels:
1374
+ P += piece._plot_label(piece['north_west'], (k - 0.5, d - 0.5), rotation=60)
1375
+ P += piece._plot_label(piece['north_east'], (k + 0.5, d - 0.5), rotation=-60)
1376
+ P += piece._plot_label(piece.north_piece()['south'], (k, d - 1))
1377
+ else:
1378
+ P += piece._plot_piece([(k, d), (k - 1, d - 1), (k + 1, d - 1)], style=style)
1379
+ if labels:
1380
+ P += piece._plot_label(piece['north_west'], (k - 0.5, d - 0.5), rotation=60)
1381
+ P += piece._plot_label(piece['north_east'], (k + 0.5, d - 0.5), rotation=-60)
1382
+ P += piece._plot_label(piece['south'], (k, d - 1))
1383
+ P.set_aspect_ratio(1.73)
1384
+ P.axes(False)
1385
+ return P
1386
+
1387
+ def _latex_(self):
1388
+ r"""
1389
+ Return latex version of ``self``.
1390
+
1391
+ Note that you might need to add tikz to the preamble::
1392
+
1393
+ sage: latex.extra_preamble(r'''\usepackage{tikz}''')
1394
+ sage: from sage.combinat.knutson_tao_puzzles import *
1395
+
1396
+ sage: ps = KnutsonTaoPuzzleSolver(H_grassmannian_pieces())
1397
+ sage: solns = ps('0101', '0101')
1398
+ sage: view(solns[0], viewer='pdf') # not tested
1399
+
1400
+ sage: ps = KnutsonTaoPuzzleSolver(HT_two_step_pieces())
1401
+ sage: solns = ps(list('10212'), list('12012'))
1402
+ sage: view(solns[0], viewer='pdf') # not tested
1403
+
1404
+ sage: ps = KnutsonTaoPuzzleSolver(K_grassmannian_pieces())
1405
+ sage: solns = ps('0101', '0101')
1406
+ sage: view(solns[0], viewer='pdf') # not tested
1407
+ """
1408
+ from collections import defaultdict
1409
+ label_colors = defaultdict(lambda: None)
1410
+ label_colors.update({'0': 'red', '1': 'blue', '2': 'green'})
1411
+ edge_colors = defaultdict(lambda: None)
1412
+ edge_colors.update({'0': 'red', '1': 'blue',
1413
+ '2': 'green', 'K': 'orange'})
1414
+
1415
+ s = r"""\begin{tikzpicture}[yscale=1.73]"""
1416
+ coords = [(k, -d) for d in range(self._n) for k in range(-d, d + 1, 2)]
1417
+
1418
+ def tikztriangle_fill(color, k, d, i, *args):
1419
+ s = r"""\path[color=%s, fill=%s!10]""" % (color, color)
1420
+ s += r"""(%s, %s) -- (%s, %s)""" % (k, d - 2 * i, k - 1, d - 1)
1421
+ s += r"""-- (%s, %s)""" % (k + 1, d - 1)
1422
+ s += r"""-- (%s, %s)""" % (k, d - 2 * i)
1423
+ s += ";\n"
1424
+ return s
1425
+
1426
+ def tikztriangle_edges(color, k, d, i, label1, label2, label3):
1427
+ s = ""
1428
+ if i == 1:
1429
+ return s
1430
+ tikzcmd = r"""\draw[color=%s, fill=none] (%s, %s) -- (%s, %s);""" + "\n"
1431
+ if edge_colors[label1]:
1432
+ s += tikzcmd % (edge_colors[label1], k - 1, d - 1, k + 1, d - 1)
1433
+ if edge_colors[label2]:
1434
+ s += tikzcmd % (edge_colors[label2], k, d - 2 * i, k - 1, d - 1)
1435
+ if edge_colors[label3]:
1436
+ s += tikzcmd % (edge_colors[label3], k + 1, d - 1, k, d - 2 * i)
1437
+ return s
1438
+
1439
+ def tikzlabels(color, k, d, i, label1, label2, label3):
1440
+ s = r"""\path[] (%s, %s)""" % (k, d - 2 * i)
1441
+ s += r"""-- (%s, %s) """ % (k - 1, d - 1)
1442
+ if label_colors[label2]:
1443
+ s += r"""node[midway, color=%s] {$%s$} """ % (label_colors[label2], label2)
1444
+ s += r"""-- (%s, %s) """ % (k + 1, d - 1)
1445
+ if label_colors[label1]:
1446
+ s += r"""node[midway, color=%s] {$%s$} """ % (label_colors[label1], label1)
1447
+ s += r"""-- (%s, %s) """ % (k, d - 2 * i)
1448
+ if label_colors[label3]:
1449
+ s += r"""node[midway, color=%s] {$%s$} """ % (label_colors[label3], label3)
1450
+ s += ";\n"
1451
+ return s
1452
+
1453
+ for ((k, d), piece) in zip(coords, self):
1454
+ for tikzcmd in (tikztriangle_fill, tikztriangle_edges, tikzlabels):
1455
+ if isinstance(piece, RhombusPiece):
1456
+ for (i, triangle) in enumerate([piece.north_piece(), piece.south_piece()]):
1457
+ if i == 0:
1458
+ s += tikzcmd(triangle.color(), k, d, i, *triangle.border())
1459
+ else:
1460
+ s += tikzcmd(triangle.color(), k, d, i, "", "", "")
1461
+ else:
1462
+ color = piece.color()
1463
+ s += tikzcmd(color, k, d, 0, *piece.border())
1464
+
1465
+ s += r"""\end{tikzpicture}"""
1466
+
1467
+ return s
1468
+
1469
+
1470
+ class KnutsonTaoPuzzleSolver(UniqueRepresentation):
1471
+ r"""
1472
+ Return puzzle solver function used to create all puzzles with given boundary conditions.
1473
+
1474
+ This class implements a generic algorithm to solve Knutson-Tao puzzles.
1475
+ An instance of this class will be callable: the arguments are the
1476
+ labels of north-east and north-west sides of the puzzle boundary; the
1477
+ output is the list of the fillings of the puzzle with the specified
1478
+ pieces.
1479
+
1480
+ INPUT:
1481
+
1482
+ - ``puzzle_pieces`` -- takes either a collection of puzzle pieces or
1483
+ a string indicating a pre-programmed collection of puzzle pieces:
1484
+
1485
+ - ``H`` -- cohomology of the Grassmannian
1486
+ - ``HT`` -- equivariant cohomology of the Grassmannian
1487
+ - ``K`` -- K-theory
1488
+ - ``H2step`` -- cohomology of the *2-step* Grassmannian
1489
+ - ``HT2step`` -- equivariant cohomology of the *2-step* Grassmannian
1490
+ - ``BK`` -- Belkale-Kumar puzzle pieces
1491
+
1492
+ - ``max_letter`` -- ``None`` or a positive integer(default: ``None``); this
1493
+ is only required for Belkale-Kumar puzzles
1494
+
1495
+ EXAMPLES:
1496
+
1497
+ Each puzzle piece is an edge-labelled triangle oriented in such a way
1498
+ that it has a south edge (called a *delta* piece) or a north edge
1499
+ (called a *nabla* piece). For example, the puzzle pieces corresponding
1500
+ to the cohomology of the Grassmannian are the following::
1501
+
1502
+ sage: from sage.combinat.knutson_tao_puzzles import H_grassmannian_pieces
1503
+ sage: H_grassmannian_pieces()
1504
+ Nablas : [0\0/0, 0\10/1, 10\1/0, 1\0/10, 1\1/1]
1505
+ Deltas : [0/0\0, 0/1\10, 1/10\0, 1/1\1, 10/0\1]
1506
+
1507
+ In the string representation, the nabla pieces are depicted as
1508
+ ``c\a/b``, where `a` is the label of the north edge, `b` is the label
1509
+ of the south-east edge, `c` is the label of the south-west edge.
1510
+ A similar string representation exists for the delta pieces.
1511
+
1512
+ To create a puzzle solver, one specifies a collection of puzzle pieces::
1513
+
1514
+ sage: KnutsonTaoPuzzleSolver(H_grassmannian_pieces())
1515
+ Knutson-Tao puzzle solver with pieces:
1516
+ Nablas : [0\0/0, 0\10/1, 10\1/0, 1\0/10, 1\1/1]
1517
+ Deltas : [0/0\0, 0/1\10, 1/10\0, 1/1\1, 10/0\1]
1518
+
1519
+ The following shorthand to create the above puzzle solver is also supported::
1520
+
1521
+ sage: KnutsonTaoPuzzleSolver('H')
1522
+ Knutson-Tao puzzle solver with pieces:
1523
+ Nablas : [0\0/0, 0\10/1, 10\1/0, 1\0/10, 1\1/1]
1524
+ Deltas : [0/0\0, 0/1\10, 1/10\0, 1/1\1, 10/0\1]
1525
+
1526
+ The solver will compute all fillings of the puzzle with the given
1527
+ puzzle pieces. The user specifies the labels of north-east and
1528
+ north-west sides of the puzzle boundary and the output is a list of the
1529
+ fillings of the puzzle with the specified pieces. For example, there is
1530
+ one solution to the puzzle whose north-west and north-east edges are
1531
+ both labeled '0'::
1532
+
1533
+ sage: ps = KnutsonTaoPuzzleSolver('H')
1534
+ sage: ps('0', '0')
1535
+ [{(1, 1): 0/0\0}]
1536
+
1537
+ There are two solutions to the puzzle whose north-west and north-east
1538
+ edges are both labeled '0101'::
1539
+
1540
+ sage: ps = KnutsonTaoPuzzleSolver('H')
1541
+ sage: solns = ps('0101', '0101')
1542
+ sage: len(solns)
1543
+ 2
1544
+ sage: solns.sort(key=str)
1545
+ sage: solns
1546
+ [{(1, 1): 0/0\0,
1547
+ (1, 2): 1/\0 0\/1,
1548
+ (1, 3): 0/\0 0\/0,
1549
+ (1, 4): 1/\0 0\/1,
1550
+ (2, 2): 1/1\1,
1551
+ (2, 3): 0/\10 1\/1,
1552
+ (2, 4): 1/\1 10\/0,
1553
+ (3, 3): 1/1\1,
1554
+ (3, 4): 0/\0 1\/10,
1555
+ (4, 4): 10/0\1}, {(1, 1): 0/1\10,
1556
+ (1, 2): 1/\1 10\/0,
1557
+ (1, 3): 0/\0 1\/10,
1558
+ (1, 4): 1/\0 0\/1,
1559
+ (2, 2): 0/0\0,
1560
+ (2, 3): 10/\1 0\/0,
1561
+ (2, 4): 1/\1 1\/1,
1562
+ (3, 3): 0/0\0,
1563
+ (3, 4): 1/\0 0\/1,
1564
+ (4, 4): 1/1\1}]
1565
+
1566
+ The pieces in a puzzle filling are indexed by pairs of nonnegative
1567
+ integers `(i, j)` with `1 \leq i \leq j \leq n`, where `n` is the
1568
+ length of the word labelling the triangle edge. The pieces indexed by
1569
+ `(i, i)` are the triangles along the south edge of the puzzle. ::
1570
+
1571
+ sage: f = solns[0]
1572
+ sage: [f[i, i] for i in range(1,5)]
1573
+ [0/0\0, 1/1\1, 1/1\1, 10/0\1]
1574
+
1575
+ The pieces indexed by `(i, j)` for `j > i` are a pair consisting of
1576
+ a delta piece and nabla piece glued together along the south edge and
1577
+ north edge, respectively (these pairs are called *rhombi*). ::
1578
+
1579
+ sage: f = solns[0]
1580
+ sage: f[1, 2]
1581
+ 1/\0 0\/1
1582
+
1583
+ There are various methods and options to display puzzle solutions.
1584
+ A single puzzle can be displayed using the plot method of the puzzle::
1585
+
1586
+ sage: ps = KnutsonTaoPuzzleSolver("H")
1587
+ sage: puzzle = ps('0101','1001')[0]
1588
+ sage: puzzle.plot() #not tested
1589
+ sage: puzzle.plot(style='fill') #not tested
1590
+ sage: puzzle.plot(style='edges') #not tested
1591
+
1592
+ To plot several puzzle solutions, use the plot method of the puzzle
1593
+ solver::
1594
+
1595
+ sage: ps = KnutsonTaoPuzzleSolver('K')
1596
+ sage: solns = ps('0101', '0101')
1597
+ sage: ps.plot(solns) # not tested
1598
+
1599
+ The code can also generate a PDF of a puzzle (using LaTeX and *tikz*)::
1600
+
1601
+ sage: latex.extra_preamble(r'''\usepackage{tikz}''')
1602
+ sage: ps = KnutsonTaoPuzzleSolver('H')
1603
+ sage: solns = ps('0101', '0101')
1604
+ sage: view(solns[0], viewer='pdf') # not tested
1605
+
1606
+
1607
+ Below are examples of using each of the currently supported puzzles.
1608
+
1609
+ Cohomology of the Grassmannian::
1610
+
1611
+ sage: ps = KnutsonTaoPuzzleSolver("H")
1612
+ sage: solns = ps('0101', '0101')
1613
+ sage: sorted(solns, key=str)
1614
+ [{(1, 1): 0/0\0,
1615
+ (1, 2): 1/\0 0\/1,
1616
+ (1, 3): 0/\0 0\/0,
1617
+ (1, 4): 1/\0 0\/1,
1618
+ (2, 2): 1/1\1,
1619
+ (2, 3): 0/\10 1\/1,
1620
+ (2, 4): 1/\1 10\/0,
1621
+ (3, 3): 1/1\1,
1622
+ (3, 4): 0/\0 1\/10,
1623
+ (4, 4): 10/0\1}, {(1, 1): 0/1\10,
1624
+ (1, 2): 1/\1 10\/0,
1625
+ (1, 3): 0/\0 1\/10,
1626
+ (1, 4): 1/\0 0\/1,
1627
+ (2, 2): 0/0\0,
1628
+ (2, 3): 10/\1 0\/0,
1629
+ (2, 4): 1/\1 1\/1,
1630
+ (3, 3): 0/0\0,
1631
+ (3, 4): 1/\0 0\/1,
1632
+ (4, 4): 1/1\1}]
1633
+
1634
+ Equivariant puzzles::
1635
+
1636
+ sage: ps = KnutsonTaoPuzzleSolver("HT")
1637
+ sage: solns = ps('0101', '0101')
1638
+ sage: sorted(solns, key=str)
1639
+ [{(1, 1): 0/0\0,
1640
+ (1, 2): 1/\0 0\/1,
1641
+ (1, 3): 0/\0 0\/0,
1642
+ (1, 4): 1/\0 0\/1,
1643
+ (2, 2): 1/1\1,
1644
+ (2, 3): 0/\1 1\/0,
1645
+ (2, 4): 1/\1 1\/1,
1646
+ (3, 3): 0/0\0,
1647
+ (3, 4): 1/\0 0\/1,
1648
+ (4, 4): 1/1\1}, {(1, 1): 0/0\0,
1649
+ (1, 2): 1/\0 0\/1,
1650
+ (1, 3): 0/\0 0\/0,
1651
+ (1, 4): 1/\0 0\/1,
1652
+ (2, 2): 1/1\1,
1653
+ (2, 3): 0/\10 1\/1,
1654
+ (2, 4): 1/\1 10\/0,
1655
+ (3, 3): 1/1\1,
1656
+ (3, 4): 0/\0 1\/10,
1657
+ (4, 4): 10/0\1}, {(1, 1): 0/1\10,
1658
+ (1, 2): 1/\1 10\/0,
1659
+ (1, 3): 0/\0 1\/10,
1660
+ (1, 4): 1/\0 0\/1,
1661
+ (2, 2): 0/0\0,
1662
+ (2, 3): 10/\1 0\/0,
1663
+ (2, 4): 1/\1 1\/1,
1664
+ (3, 3): 0/0\0,
1665
+ (3, 4): 1/\0 0\/1,
1666
+ (4, 4): 1/1\1}]
1667
+
1668
+ K-Theory puzzles::
1669
+
1670
+ sage: ps = KnutsonTaoPuzzleSolver("K")
1671
+ sage: solns = ps('0101', '0101')
1672
+ sage: sorted(solns, key=str)
1673
+ [{(1, 1): 0/0\0,
1674
+ (1, 2): 1/\0 0\/1,
1675
+ (1, 3): 0/\0 0\/0,
1676
+ (1, 4): 1/\0 0\/1,
1677
+ (2, 2): 1/1\1,
1678
+ (2, 3): 0/\10 1\/1,
1679
+ (2, 4): 1/\1 10\/0,
1680
+ (3, 3): 1/1\1,
1681
+ (3, 4): 0/\0 1\/10,
1682
+ (4, 4): 10/0\1}, {(1, 1): 0/1\10,
1683
+ (1, 2): 1/\1 10\/0,
1684
+ (1, 3): 0/\0 1\/10,
1685
+ (1, 4): 1/\0 0\/1,
1686
+ (2, 2): 0/0\0,
1687
+ (2, 3): 10/\1 0\/0,
1688
+ (2, 4): 1/\1 1\/1,
1689
+ (3, 3): 0/0\0,
1690
+ (3, 4): 1/\0 0\/1,
1691
+ (4, 4): 1/1\1}, {(1, 1): 0/1\10,
1692
+ (1, 2): 1/\1 10\/0,
1693
+ (1, 3): 0/\0 1\/K,
1694
+ (1, 4): 1/\0 0\/1,
1695
+ (2, 2): 0/0\0,
1696
+ (2, 3): K/\K 0\/1,
1697
+ (2, 4): 1/\1 K\/0,
1698
+ (3, 3): 1/1\1,
1699
+ (3, 4): 0/\0 1\/10,
1700
+ (4, 4): 10/0\1}]
1701
+
1702
+ Two-step puzzles::
1703
+
1704
+ sage: ps = KnutsonTaoPuzzleSolver("H2step")
1705
+ sage: solns = ps('01201', '01021')
1706
+ sage: sorted(solns, key=str)
1707
+ [{(1, 1): 0/0\0,
1708
+ (1, 2): 1/\0 0\/1,
1709
+ (1, 3): 2/\0 0\/2,
1710
+ (1, 4): 0/\0 0\/0,
1711
+ (1, 5): 1/\0 0\/1,
1712
+ (2, 2): 1/2\21,
1713
+ (2, 3): 2/\2 21\/1,
1714
+ (2, 4): 0/\10 2\/21,
1715
+ (2, 5): 1/\1 10\/0,
1716
+ (3, 3): 1/1\1,
1717
+ (3, 4): 21/\2 1\/1,
1718
+ (3, 5): 0/\0 2\/20,
1719
+ (4, 4): 1/1\1,
1720
+ (4, 5): 20/\2 1\/10,
1721
+ (5, 5): 10/0\1}, {(1, 1): 0/1\10,
1722
+ (1, 2): 1/\1 10\/0,
1723
+ (1, 3): 2/\1 1\/2,
1724
+ (1, 4): 0/\0 1\/10,
1725
+ (1, 5): 1/\0 0\/1,
1726
+ (2, 2): 0/2\20,
1727
+ (2, 3): 2/\2 20\/0,
1728
+ (2, 4): 10/\1 2\/20,
1729
+ (2, 5): 1/\1 1\/1,
1730
+ (3, 3): 0/0\0,
1731
+ (3, 4): 20/\2 0\/0,
1732
+ (3, 5): 1/\0 2\/2(10),
1733
+ (4, 4): 0/0\0,
1734
+ (4, 5): 2(10)/\2 0\/1,
1735
+ (5, 5): 1/1\1}, {(1, 1): 0/2\20,
1736
+ (1, 2): 1/\21 20\/0,
1737
+ (1, 3): 2/\2 21\/1,
1738
+ (1, 4): 0/\0 2\/20,
1739
+ (1, 5): 1/\0 0\/1,
1740
+ (2, 2): 0/0\0,
1741
+ (2, 3): 1/\0 0\/1,
1742
+ (2, 4): 20/\2 0\/0,
1743
+ (2, 5): 1/\1 2\/21,
1744
+ (3, 3): 1/1\1,
1745
+ (3, 4): 0/\0 1\/10,
1746
+ (3, 5): 21/\0 0\/21,
1747
+ (4, 4): 10/0\1,
1748
+ (4, 5): 21/\2 1\/1,
1749
+ (5, 5): 1/1\1}]
1750
+
1751
+ Two-step equivariant puzzles::
1752
+
1753
+ sage: ps = KnutsonTaoPuzzleSolver("HT2step")
1754
+ sage: solns = ps('10212', '12012')
1755
+ sage: sorted(solns, key=str)
1756
+ [{(1, 1): 1/1\1,
1757
+ (1, 2): 0/\(21)0 1\/2,
1758
+ (1, 3): 2/\1 (21)0\/0,
1759
+ (1, 4): 1/\1 1\/1,
1760
+ (1, 5): 2/\1 1\/2,
1761
+ (2, 2): 2/2\2,
1762
+ (2, 3): 0/\2 2\/0,
1763
+ (2, 4): 1/\2 2\/1,
1764
+ (2, 5): 2/\2 2\/2,
1765
+ (3, 3): 0/0\0,
1766
+ (3, 4): 1/\0 0\/1,
1767
+ (3, 5): 2/\0 0\/2,
1768
+ (4, 4): 1/1\1,
1769
+ (4, 5): 2/\1 1\/2,
1770
+ (5, 5): 2/2\2}, {(1, 1): 1/1\1,
1771
+ (1, 2): 0/\(21)0 1\/2,
1772
+ (1, 3): 2/\1 (21)0\/0,
1773
+ (1, 4): 1/\1 1\/1,
1774
+ (1, 5): 2/\1 1\/2,
1775
+ (2, 2): 2/2\2,
1776
+ (2, 3): 0/\2 2\/0,
1777
+ (2, 4): 1/\21 2\/2,
1778
+ (2, 5): 2/\2 21\/1,
1779
+ (3, 3): 0/0\0,
1780
+ (3, 4): 2/\0 0\/2,
1781
+ (3, 5): 1/\0 0\/1,
1782
+ (4, 4): 2/2\2,
1783
+ (4, 5): 1/\1 2\/21,
1784
+ (5, 5): 21/1\2}, {(1, 1): 1/1\1,
1785
+ (1, 2): 0/\(21)0 1\/2,
1786
+ (1, 3): 2/\1 (21)0\/0,
1787
+ (1, 4): 1/\1 1\/1,
1788
+ (1, 5): 2/\1 1\/2,
1789
+ (2, 2): 2/2\2,
1790
+ (2, 3): 0/\20 2\/2,
1791
+ (2, 4): 1/\21 20\/0,
1792
+ (2, 5): 2/\2 21\/1,
1793
+ (3, 3): 2/2\2,
1794
+ (3, 4): 0/\0 2\/20,
1795
+ (3, 5): 1/\0 0\/1,
1796
+ (4, 4): 20/0\2,
1797
+ (4, 5): 1/\1 2\/21,
1798
+ (5, 5): 21/1\2}, {(1, 1): 1/1\1,
1799
+ (1, 2): 0/\1 1\/0,
1800
+ (1, 3): 2/\1 1\/2,
1801
+ (1, 4): 1/\1 1\/1,
1802
+ (1, 5): 2/\1 1\/2,
1803
+ (2, 2): 0/2\20,
1804
+ (2, 3): 2/\2 20\/0,
1805
+ (2, 4): 1/\2 2\/1,
1806
+ (2, 5): 2/\2 2\/2,
1807
+ (3, 3): 0/0\0,
1808
+ (3, 4): 1/\0 0\/1,
1809
+ (3, 5): 2/\0 0\/2,
1810
+ (4, 4): 1/1\1,
1811
+ (4, 5): 2/\1 1\/2,
1812
+ (5, 5): 2/2\2}, {(1, 1): 1/1\1,
1813
+ (1, 2): 0/\1 1\/0,
1814
+ (1, 3): 2/\1 1\/2,
1815
+ (1, 4): 1/\1 1\/1,
1816
+ (1, 5): 2/\1 1\/2,
1817
+ (2, 2): 0/2\20,
1818
+ (2, 3): 2/\2 20\/0,
1819
+ (2, 4): 1/\21 2\/2,
1820
+ (2, 5): 2/\2 21\/1,
1821
+ (3, 3): 0/0\0,
1822
+ (3, 4): 2/\0 0\/2,
1823
+ (3, 5): 1/\0 0\/1,
1824
+ (4, 4): 2/2\2,
1825
+ (4, 5): 1/\1 2\/21,
1826
+ (5, 5): 21/1\2}, {(1, 1): 1/1\1,
1827
+ (1, 2): 0/\10 1\/1,
1828
+ (1, 3): 2/\10 10\/2,
1829
+ (1, 4): 1/\1 10\/0,
1830
+ (1, 5): 2/\1 1\/2,
1831
+ (2, 2): 1/2\21,
1832
+ (2, 3): 2/\2 21\/1,
1833
+ (2, 4): 0/\2 2\/0,
1834
+ (2, 5): 2/\2 2\/2,
1835
+ (3, 3): 1/1\1,
1836
+ (3, 4): 0/\0 1\/10,
1837
+ (3, 5): 2/\0 0\/2,
1838
+ (4, 4): 10/0\1,
1839
+ (4, 5): 2/\1 1\/2,
1840
+ (5, 5): 2/2\2}, {(1, 1): 1/1\1,
1841
+ (1, 2): 0/\10 1\/1,
1842
+ (1, 3): 2/\10 10\/2,
1843
+ (1, 4): 1/\1 10\/0,
1844
+ (1, 5): 2/\1 1\/2,
1845
+ (2, 2): 1/2\21,
1846
+ (2, 3): 2/\2 21\/1,
1847
+ (2, 4): 0/\20 2\/2,
1848
+ (2, 5): 2/\2 20\/0,
1849
+ (3, 3): 1/1\1,
1850
+ (3, 4): 2/\1 1\/2,
1851
+ (3, 5): 0/\0 1\/10,
1852
+ (4, 4): 2/2\2,
1853
+ (4, 5): 10/\1 2\/20,
1854
+ (5, 5): 20/0\2}, {(1, 1): 1/2\21,
1855
+ (1, 2): 0/\20 21\/1,
1856
+ (1, 3): 2/\2 20\/0,
1857
+ (1, 4): 1/\1 2\/21,
1858
+ (1, 5): 2/\1 1\/2,
1859
+ (2, 2): 1/1\1,
1860
+ (2, 3): 0/\1 1\/0,
1861
+ (2, 4): 21/\2 1\/1,
1862
+ (2, 5): 2/\2 2\/2,
1863
+ (3, 3): 0/0\0,
1864
+ (3, 4): 1/\0 0\/1,
1865
+ (3, 5): 2/\0 0\/2,
1866
+ (4, 4): 1/1\1,
1867
+ (4, 5): 2/\1 1\/2,
1868
+ (5, 5): 2/2\2}, {(1, 1): 1/2\21,
1869
+ (1, 2): 0/\20 21\/1,
1870
+ (1, 3): 2/\2 20\/0,
1871
+ (1, 4): 1/\1 2\/21,
1872
+ (1, 5): 2/\1 1\/2,
1873
+ (2, 2): 1/1\1,
1874
+ (2, 3): 0/\10 1\/1,
1875
+ (2, 4): 21/\2 10\/0,
1876
+ (2, 5): 2/\2 2\/2,
1877
+ (3, 3): 1/1\1,
1878
+ (3, 4): 0/\0 1\/10,
1879
+ (3, 5): 2/\0 0\/2,
1880
+ (4, 4): 10/0\1,
1881
+ (4, 5): 2/\1 1\/2,
1882
+ (5, 5): 2/2\2}, {(1, 1): 1/2\21,
1883
+ (1, 2): 0/\21 21\/0,
1884
+ (1, 3): 2/\2 21\/1,
1885
+ (1, 4): 1/\1 2\/21,
1886
+ (1, 5): 2/\1 1\/2,
1887
+ (2, 2): 0/1\10,
1888
+ (2, 3): 1/\1 10\/0,
1889
+ (2, 4): 21/\2 1\/1,
1890
+ (2, 5): 2/\2 2\/2,
1891
+ (3, 3): 0/0\0,
1892
+ (3, 4): 1/\0 0\/1,
1893
+ (3, 5): 2/\0 0\/2,
1894
+ (4, 4): 1/1\1,
1895
+ (4, 5): 2/\1 1\/2,
1896
+ (5, 5): 2/2\2}]
1897
+
1898
+
1899
+ Belkale-Kumar puzzles (the following example is Figure 2 of [KnutsonPurbhoo10]_)::
1900
+
1901
+ sage: ps = KnutsonTaoPuzzleSolver('BK', 3)
1902
+ sage: solns = ps('12132', '23112')
1903
+ sage: len(solns)
1904
+ 1
1905
+ sage: solns[0].south_labels()
1906
+ ('3', '2', '1', '2', '1')
1907
+ sage: solns
1908
+ [{(1, 1): 1/3\3(1),
1909
+ (1, 2): 2/\3(2) 3(1)\/1,
1910
+ (1, 3): 1/\3(1) 3(2)\/2,
1911
+ (1, 4): 3/\3 3(1)\/1,
1912
+ (1, 5): 2/\2 3\/3(2),
1913
+ (2, 2): 1/2\2(1),
1914
+ (2, 3): 2/\2 2(1)\/1,
1915
+ (2, 4): 1/\2(1) 2\/2,
1916
+ (2, 5): 3(2)/\3 2(1)\/1,
1917
+ (3, 3): 1/1\1,
1918
+ (3, 4): 2/\1 1\/2,
1919
+ (3, 5): 1/\1 1\/1,
1920
+ (4, 4): 2/2\2,
1921
+ (4, 5): 1/\1 2\/2(1),
1922
+ (5, 5): 2(1)/1\2}]
1923
+ """
1924
+
1925
+ def __init__(self, puzzle_pieces):
1926
+ r"""
1927
+ Knutson-Tao puzzle solver.
1928
+
1929
+ TESTS:
1930
+
1931
+ Check that UniqueRepresentation works::
1932
+
1933
+ sage: from sage.combinat.knutson_tao_puzzles import KnutsonTaoPuzzleSolver, H_grassmannian_pieces
1934
+ sage: ps = KnutsonTaoPuzzleSolver(H_grassmannian_pieces())
1935
+ sage: qs = KnutsonTaoPuzzleSolver("H")
1936
+ sage: ps
1937
+ Knutson-Tao puzzle solver with pieces:
1938
+ Nablas : [0\0/0, 0\10/1, 10\1/0, 1\0/10, 1\1/1]
1939
+ Deltas : [0/0\0, 0/1\10, 1/10\0, 1/1\1, 10/0\1]
1940
+ sage: qs
1941
+ Knutson-Tao puzzle solver with pieces:
1942
+ Nablas : [0\0/0, 0\10/1, 10\1/0, 1\0/10, 1\1/1]
1943
+ Deltas : [0/0\0, 0/1\10, 1/10\0, 1/1\1, 10/0\1]
1944
+ sage: ps == qs
1945
+ True
1946
+ """
1947
+ self._puzzle_pieces = puzzle_pieces
1948
+ self._rhombus_pieces = tuple(puzzle_pieces.rhombus_pieces())
1949
+ self._bottom_deltas = tuple(puzzle_pieces.boundary_deltas())
1950
+
1951
+ @staticmethod
1952
+ def __classcall_private__(cls, puzzle_pieces, max_letter=None):
1953
+ r"""
1954
+ TESTS::
1955
+
1956
+ sage: from sage.combinat.knutson_tao_puzzles import *
1957
+ sage: KnutsonTaoPuzzleSolver(H_grassmannian_pieces()) == KnutsonTaoPuzzleSolver("H") # indirect doctest
1958
+ True
1959
+ sage: KnutsonTaoPuzzleSolver(HT_grassmannian_pieces()) == KnutsonTaoPuzzleSolver("HT")
1960
+ True
1961
+ sage: KnutsonTaoPuzzleSolver(K_grassmannian_pieces()) == KnutsonTaoPuzzleSolver("K")
1962
+ True
1963
+ sage: KnutsonTaoPuzzleSolver(H_two_step_pieces()) == KnutsonTaoPuzzleSolver("H2step")
1964
+ True
1965
+ sage: KnutsonTaoPuzzleSolver(HT_two_step_pieces()) == KnutsonTaoPuzzleSolver("HT2step")
1966
+ True
1967
+ sage: KnutsonTaoPuzzleSolver(BK_pieces(3)) == KnutsonTaoPuzzleSolver("BK",3)
1968
+ True
1969
+ """
1970
+ if isinstance(puzzle_pieces, str):
1971
+ if puzzle_pieces == "H":
1972
+ puzzle_pieces = H_grassmannian_pieces()
1973
+ elif puzzle_pieces == "HT":
1974
+ puzzle_pieces = HT_grassmannian_pieces()
1975
+ elif puzzle_pieces == "K":
1976
+ puzzle_pieces = K_grassmannian_pieces()
1977
+ elif puzzle_pieces == "H2step":
1978
+ puzzle_pieces = H_two_step_pieces()
1979
+ elif puzzle_pieces == "HT2step":
1980
+ puzzle_pieces = HT_two_step_pieces()
1981
+ elif puzzle_pieces == "BK":
1982
+ if max_letter is not None:
1983
+ puzzle_pieces = BK_pieces(max_letter)
1984
+ else:
1985
+ raise ValueError("max_letter needs to be specified")
1986
+ return super().__classcall__(cls, puzzle_pieces)
1987
+
1988
+ def __call__(self, lamda, mu, algorithm='strips'):
1989
+ r"""
1990
+ TESTS::
1991
+
1992
+ sage: from sage.combinat.knutson_tao_puzzles import KnutsonTaoPuzzleSolver
1993
+ sage: ps = KnutsonTaoPuzzleSolver("H")
1994
+ sage: ps('0101','1001')
1995
+ [{(1, 1): 0/1\10,
1996
+ (1, 2): 1/\1 10\/0,
1997
+ (1, 3): 0/\10 1\/1,
1998
+ (1, 4): 1/\1 10\/0,
1999
+ (2, 2): 0/0\0,
2000
+ (2, 3): 1/\0 0\/1,
2001
+ (2, 4): 0/\0 0\/0,
2002
+ (3, 3): 1/1\1,
2003
+ (3, 4): 0/\0 1\/10,
2004
+ (4, 4): 10/0\1}]
2005
+ sage: ps('0101','1001',algorithm='pieces')
2006
+ [{(1, 1): 0/1\10,
2007
+ (1, 2): 1/\1 10\/0,
2008
+ (1, 3): 0/\10 1\/1,
2009
+ (1, 4): 1/\1 10\/0,
2010
+ (2, 2): 0/0\0,
2011
+ (2, 3): 1/\0 0\/1,
2012
+ (2, 4): 0/\0 0\/0,
2013
+ (3, 3): 1/1\1,
2014
+ (3, 4): 0/\0 1\/10,
2015
+ (4, 4): 10/0\1}]
2016
+ """
2017
+ lamda, mu = tuple(lamda), tuple(mu)
2018
+ if algorithm == 'pieces':
2019
+ return list(self._fill_puzzle_by_pieces(lamda, mu))
2020
+ elif algorithm == 'strips':
2021
+ return list(self._fill_puzzle_by_strips(lamda, mu))
2022
+
2023
+ solutions = __call__
2024
+
2025
+ def __repr__(self) -> str:
2026
+ r"""
2027
+ EXAMPLES::
2028
+
2029
+ sage: from sage.combinat.knutson_tao_puzzles import KnutsonTaoPuzzleSolver
2030
+ sage: KnutsonTaoPuzzleSolver('H')
2031
+ Knutson-Tao puzzle solver with pieces:
2032
+ Nablas : [0\0/0, 0\10/1, 10\1/0, 1\0/10, 1\1/1]
2033
+ Deltas : [0/0\0, 0/1\10, 1/10\0, 1/1\1, 10/0\1]
2034
+ """
2035
+ return "Knutson-Tao puzzle solver with pieces:\n%s" % self._puzzle_pieces
2036
+
2037
+ def puzzle_pieces(self):
2038
+ r"""
2039
+ The puzzle pieces used for filling in the puzzles.
2040
+
2041
+ EXAMPLES::
2042
+
2043
+ sage: from sage.combinat.knutson_tao_puzzles import KnutsonTaoPuzzleSolver
2044
+ sage: ps = KnutsonTaoPuzzleSolver('H')
2045
+ sage: ps.puzzle_pieces()
2046
+ Nablas : [0\0/0, 0\10/1, 10\1/0, 1\0/10, 1\1/1]
2047
+ Deltas : [0/0\0, 0/1\10, 1/10\0, 1/1\1, 10/0\1]
2048
+ """
2049
+ return self._puzzle_pieces
2050
+
2051
+ def _fill_piece(self, nw_label, ne_label, pieces) -> list[PuzzlePiece]:
2052
+ r"""
2053
+ Fillings of a piece.
2054
+
2055
+ INPUT:
2056
+
2057
+ - ``nw_label``, ``nw_label`` -- label
2058
+ - ``pieces`` -- puzzle pieces used for the filling
2059
+
2060
+ OUTPUT: list of the fillings
2061
+
2062
+ EXAMPLES::
2063
+
2064
+ sage: from sage.combinat.knutson_tao_puzzles import KnutsonTaoPuzzleSolver
2065
+ sage: ps = KnutsonTaoPuzzleSolver('H')
2066
+ sage: ps._fill_piece('0', '0', ps._bottom_deltas)
2067
+ [0/0\0]
2068
+ """
2069
+ return [piece for piece in pieces
2070
+ if (piece['north_west'] == nw_label and
2071
+ piece['north_east'] == ne_label)]
2072
+
2073
+ @cached_method
2074
+ def _fill_strip(self, nw_labels, ne_label, pieces, final_pieces=None):
2075
+ r"""
2076
+ Fillings of a strip of height 1.
2077
+
2078
+ INPUT:
2079
+
2080
+ - ``nw_labels`` -- tuple of labels
2081
+ - ``nw_label`` -- label
2082
+ - ``pieces`` -- puzzle pieces used for the filling
2083
+ - ``final_pieces`` -- pieces used for the last piece to be filled in
2084
+
2085
+ OUTPUT: list of lists of the fillings
2086
+
2087
+ EXAMPLES::
2088
+
2089
+ sage: from sage.combinat.knutson_tao_puzzles import KnutsonTaoPuzzleSolver
2090
+ sage: ps = KnutsonTaoPuzzleSolver('H')
2091
+ sage: ps._fill_strip(('0',), '0', ps._rhombus_pieces, ps._bottom_deltas)
2092
+ [[0/0\0]]
2093
+ sage: ps._fill_strip(('0','0'), '0', ps._rhombus_pieces, ps._bottom_deltas)
2094
+ [[0/\0 0\/0, 0/0\0]]
2095
+ sage: sorted(ps._fill_strip(('0',), '0', ps._rhombus_pieces), key=str)
2096
+ [[0/\0 0\/0], [0/\0 1\/10]]
2097
+ sage: sorted(ps._fill_strip(('0','1'), '0', ps._rhombus_pieces), key=str)
2098
+ [[1/\0 0\/1, 0/\0 0\/0], [1/\0 0\/1, 0/\0 1\/10]]
2099
+
2100
+ TESTS::
2101
+
2102
+ sage: from sage.combinat.knutson_tao_puzzles import KnutsonTaoPuzzleSolver
2103
+ sage: ps = KnutsonTaoPuzzleSolver('H')
2104
+ sage: ps._fill_strip(('0',), 'goo', ps._rhombus_pieces)
2105
+ []
2106
+ """
2107
+ if final_pieces is None:
2108
+ final_pieces = pieces
2109
+
2110
+ output = []
2111
+ if len(nw_labels) == 1:
2112
+ X = self._fill_piece(nw_labels[0], ne_label, final_pieces)
2113
+ if X:
2114
+ output = [[x] for x in X]
2115
+ else:
2116
+ partial_fillings = self._fill_strip(nw_labels[1:], ne_label, pieces)
2117
+ for partial_filling in partial_fillings:
2118
+ ne_label = partial_filling[-1]['south_west']
2119
+ for piece in self._fill_piece(nw_labels[0], ne_label, final_pieces):
2120
+ output.append(partial_filling + [piece])
2121
+ return output
2122
+
2123
+ def _fill_puzzle_by_pieces(self, lamda, mu):
2124
+ r"""
2125
+ Fill puzzle pieces for given outer labels ``lambda`` and ``mu``.
2126
+
2127
+ EXAMPLES::
2128
+
2129
+ sage: from sage.combinat.knutson_tao_puzzles import KnutsonTaoPuzzleSolver
2130
+ sage: ps = KnutsonTaoPuzzleSolver('H')
2131
+ sage: list(ps._fill_puzzle_by_pieces('0', '0'))
2132
+ [{(1, 1): 0/0\0}]
2133
+ """
2134
+ queue = [PuzzleFilling(lamda, mu)]
2135
+ while queue:
2136
+ PP = queue.pop()
2137
+ ne_label = PP.north_east_label_of_kink()
2138
+ nw_label = PP.north_west_label_of_kink()
2139
+ if PP.is_in_south_edge():
2140
+ pieces = self._bottom_deltas
2141
+ else:
2142
+ pieces = self._rhombus_pieces
2143
+ for piece in self._fill_piece(nw_label, ne_label, pieces):
2144
+ PPcopy = PP.copy()
2145
+ PPcopy.add_piece(piece)
2146
+ if PPcopy.is_completed():
2147
+ yield PPcopy
2148
+ else:
2149
+ queue.append(PPcopy)
2150
+
2151
+ def _fill_puzzle_by_strips(self, lamda, mu):
2152
+ r"""
2153
+ Fill puzzle pieces by strips for given outer labels ``lambda`` and ``mu``.
2154
+
2155
+ EXAMPLES::
2156
+
2157
+ sage: from sage.combinat.knutson_tao_puzzles import KnutsonTaoPuzzleSolver
2158
+ sage: ps = KnutsonTaoPuzzleSolver('H')
2159
+ sage: list(ps._fill_puzzle_by_strips('0', '0'))
2160
+ [{(1, 1): 0/0\0}]
2161
+ sage: list(ps._fill_puzzle_by_strips('01', '01'))
2162
+ [{(1, 1): 0/0\0, (1, 2): 1/\0 0\/1, (2, 2): 1/1\1}]
2163
+ """
2164
+ queue = [PuzzleFilling(lamda, mu)]
2165
+ while queue:
2166
+ PP = queue.pop()
2167
+ i, _ = PP.kink_coordinates()
2168
+
2169
+ # grab nw labels
2170
+ if i == 1:
2171
+ nw_labels = PP._nw_labels
2172
+ else:
2173
+ nw_labels = tuple(PP._squares[i - 1, k]['south_east']
2174
+ for k in range(i, len(lamda) + 1))
2175
+
2176
+ # grab ne labels
2177
+ ne_label = PP._ne_labels[i - 1]
2178
+
2179
+ deltas = self._bottom_deltas
2180
+ rhombi = self._rhombus_pieces
2181
+ for row in self._fill_strip(nw_labels, ne_label, rhombi, deltas):
2182
+ PPcopy = PP.copy()
2183
+ PPcopy.add_pieces(row)
2184
+ if PPcopy.is_completed():
2185
+ yield PPcopy
2186
+ else:
2187
+ queue.append(PPcopy)
2188
+
2189
+ def plot(self, puzzles):
2190
+ r"""
2191
+ Return plot of puzzles.
2192
+
2193
+ INPUT:
2194
+
2195
+ - ``puzzles`` -- list of puzzles
2196
+
2197
+ EXAMPLES::
2198
+
2199
+ sage: from sage.combinat.knutson_tao_puzzles import KnutsonTaoPuzzleSolver
2200
+ sage: ps = KnutsonTaoPuzzleSolver('K')
2201
+ sage: solns = ps('0101', '0101')
2202
+ sage: ps.plot(solns) # not tested
2203
+ """
2204
+ g = [p.plot() for p in puzzles]
2205
+ m = len([gg.axes(False) for gg in g])
2206
+ return graphics_array(g, (m + 3) / 4, 4)
2207
+
2208
+ def structure_constants(self, lamda, mu, nu=None):
2209
+ r"""
2210
+ Compute cohomology structure coefficients from puzzles.
2211
+
2212
+ INPUT:
2213
+
2214
+ - ``pieces`` -- puzzle pieces to be used
2215
+ - ``lambda``, ``mu`` -- edge labels of puzzle for northwest and north east side
2216
+ - ``nu`` -- (default: ``None``) if ``nu`` is not specified a dictionary is returned with
2217
+ the structure coefficients corresponding to all south labels; if ``nu`` is given, only
2218
+ the coefficients with the specified label is returned
2219
+
2220
+ OUTPUT: dictionary
2221
+
2222
+ EXAMPLES:
2223
+
2224
+ Note: In order to standardize the output of the following examples,
2225
+ we output a sorted list of items from the dictionary instead of the
2226
+ dictionary itself.
2227
+
2228
+ Grassmannian cohomology::
2229
+
2230
+ sage: ps = KnutsonTaoPuzzleSolver('H')
2231
+ sage: cp = ps.structure_constants('0101', '0101')
2232
+ sage: sorted(cp.items(), key=str)
2233
+ [(('0', '1', '1', '0'), 1), (('1', '0', '0', '1'), 1)]
2234
+ sage: ps.structure_constants('001001', '001010', '010100')
2235
+ 1
2236
+
2237
+ Equivariant cohomology::
2238
+
2239
+ sage: ps = KnutsonTaoPuzzleSolver('HT')
2240
+ sage: cp = ps.structure_constants('0101', '0101')
2241
+ sage: sorted(cp.items(), key=str)
2242
+ [(('0', '1', '0', '1'), y2 - y3),
2243
+ (('0', '1', '1', '0'), 1),
2244
+ (('1', '0', '0', '1'), 1)]
2245
+
2246
+ K-theory::
2247
+
2248
+ sage: ps = KnutsonTaoPuzzleSolver('K')
2249
+ sage: cp = ps.structure_constants('0101', '0101')
2250
+ sage: sorted(cp.items(), key=str)
2251
+ [(('0', '1', '1', '0'), 1), (('1', '0', '0', '1'), 1), (('1', '0', '1', '0'), -1)]
2252
+
2253
+ Two-step::
2254
+
2255
+ sage: ps = KnutsonTaoPuzzleSolver('H2step')
2256
+ sage: cp = ps.structure_constants('01122', '01122')
2257
+ sage: sorted(cp.items(), key=str)
2258
+ [(('0', '1', '1', '2', '2'), 1)]
2259
+ sage: cp = ps.structure_constants('01201', '01021')
2260
+ sage: sorted(cp.items(), key=str)
2261
+ [(('0', '2', '1', '1', '0'), 1),
2262
+ (('1', '2', '0', '0', '1'), 1),
2263
+ (('2', '0', '1', '0', '1'), 1)]
2264
+
2265
+ Two-step equivariant::
2266
+
2267
+ sage: ps = KnutsonTaoPuzzleSolver('HT2step')
2268
+ sage: cp = ps.structure_constants('10212', '12012')
2269
+ sage: sorted(cp.items(), key=str)
2270
+ [(('1', '2', '0', '1', '2'), y1*y2 - y2*y3 - y1*y4 + y3*y4),
2271
+ (('1', '2', '0', '2', '1'), y1 - y3),
2272
+ (('1', '2', '1', '0', '2'), y2 - y4),
2273
+ (('1', '2', '1', '2', '0'), 1),
2274
+ (('1', '2', '2', '0', '1'), 1),
2275
+ (('2', '1', '0', '1', '2'), y1 - y3),
2276
+ (('2', '1', '1', '0', '2'), 1)]
2277
+ """
2278
+ from collections import defaultdict
2279
+ R = PolynomialRing(Integers(), 'y', len(lamda) + 1)
2280
+ z = defaultdict(R.zero)
2281
+ for p in self(lamda, mu):
2282
+ z[p.south_labels()] += p.contribution()
2283
+ if nu is None:
2284
+ return dict(z)
2285
+ else:
2286
+ return z[tuple(nu)]