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,1474 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ # sage.doctest: needs sage.combinat sage.modules
3
+ r"""
4
+ `\nu`-Dyck words
5
+
6
+ A class of the `\nu`-Dyck word, see [PRV2017]_ for details.
7
+
8
+ This file is based off the class
9
+ :func:`DyckWords<sage.combinat.dyck_word.DyckWord>` written by Mike Hansen, Dan
10
+ Drake, Florent Hivert, Christian Stump, Mike Zabrocki, Jean--Baptiste Priez
11
+ and Travis Scrimshaw.
12
+
13
+ AUTHORS:
14
+
15
+ - Aram Dermenjian (2020-09-26)
16
+ """
17
+ # ****************************************************************************
18
+ # Copyright (C) 2020 Aram Dermenjian <aram.dermenjian@gmail.com>,
19
+ #
20
+ # Distributed under the terms of the GNU General Public License (GPL)
21
+ #
22
+ # This code is distributed in the hope that it will be useful,
23
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
24
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25
+ # General Public License for more details.
26
+ #
27
+ # The full text of the GPL is available at:
28
+ #
29
+ # https://www.gnu.org/licenses/
30
+ # ****************************************************************************
31
+ from __future__ import annotations
32
+ from sage.structure.element import Element
33
+ from sage.rings.integer import Integer
34
+ from sage.combinat.combinat import CombinatorialElement
35
+ from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet
36
+ from sage.structure.global_options import GlobalOptions
37
+ from sage.structure.parent import Parent
38
+ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
39
+ from sage.misc.latex import latex
40
+
41
+ from sage.combinat.words.paths import WordPaths_north_east
42
+ from sage.combinat.words.paths import FiniteWordPath_north_east
43
+
44
+ ndw_open_symbol = 1
45
+ ndw_close_symbol = 0
46
+
47
+
48
+ def update_ndw_symbols(os, cs):
49
+ r"""
50
+ A way to alter the open and close symbols from sage.
51
+
52
+ INPUT:
53
+
54
+ - ``os`` -- the open symbol
55
+ - ``cs`` -- the close symbol
56
+
57
+ EXAMPLES::
58
+
59
+ sage: from sage.combinat.nu_dyck_word import update_ndw_symbols
60
+ sage: update_ndw_symbols(0,1)
61
+ sage: dw = NuDyckWord('0101001','0110010'); dw
62
+ [0, 1, 0, 1, 0, 0, 1]
63
+
64
+ sage: dw = NuDyckWord('1010110','1001101'); dw
65
+ Traceback (most recent call last):
66
+ ...
67
+ ValueError: invalid nu-Dyck word
68
+ sage: update_ndw_symbols(1,0)
69
+ """
70
+ global ndw_open_symbol
71
+ global ndw_close_symbol
72
+ ndw_open_symbol = os
73
+ ndw_close_symbol = cs
74
+
75
+
76
+ def replace_dyck_char(x):
77
+ r"""
78
+ A map sending an opening character (``'1'``, ``'N'``, and ``'('``) to
79
+ ``ndw_open_symbol``, a closing character (``'0'``, ``'E'``, and ``')'``) to
80
+ ``ndw_close_symbol``, and raising an error on any input other than one of
81
+ the opening or closing characters.
82
+
83
+ This is the inverse map of :func:`replace_dyck_symbol`.
84
+
85
+ INPUT:
86
+
87
+ - ``x`` -- string; a ``'1'``, ``'0'``, ``'N'``, ``'E'``, ``'('`` or ``')'``
88
+
89
+ OUTPUT:
90
+
91
+ - If ``x`` is an opening character, replace ``x`` with the
92
+ constant ``ndw_open_symbol``.
93
+
94
+ - If ``x`` is a closing character, replace ``x`` with the
95
+ constant ``ndw_close_symbol``.
96
+
97
+ - Raise a :exc:`ValueError` if ``x`` is neither an opening nor a
98
+ closing character.
99
+
100
+ .. SEEALSO:: :func:`replace_dyck_symbol`
101
+
102
+ EXAMPLES::
103
+
104
+ sage: from sage.combinat.nu_dyck_word import replace_dyck_char
105
+ sage: replace_dyck_char('(')
106
+ 1
107
+ sage: replace_dyck_char(')')
108
+ 0
109
+ sage: replace_dyck_char(1)
110
+ Traceback (most recent call last):
111
+ ...
112
+ ValueError
113
+ """
114
+ if x == '(' or x == 'N' or x == str(ndw_open_symbol):
115
+ return ndw_open_symbol
116
+ if x == ')' or x == 'E' or x == str(ndw_close_symbol):
117
+ return ndw_close_symbol
118
+ raise ValueError
119
+
120
+
121
+ def replace_dyck_symbol(x, open_char='N', close_char='E') -> str:
122
+ r"""
123
+ A map sending ``ndw_open_symbol`` to ``open_char`` and ``ndw_close_symbol``
124
+ to ``close_char``, and raising an error on any input other than
125
+ ``ndw_open_symbol`` and ``ndw_close_symbol``. The values of the constants
126
+ ``ndw_open_symbol`` and ``ndw_close_symbol`` are subject to change.
127
+
128
+ This is the inverse map of :func:`replace_dyck_char`.
129
+
130
+ INPUT:
131
+
132
+ - ``x`` -- either ``ndw_open_symbol`` or ``ndw_close_symbol``
133
+
134
+ - ``open_char`` -- string (optional) default ``'N'``
135
+
136
+ - ``close_char`` -- string (optional) default ``'E'``
137
+
138
+ OUTPUT: if ``x`` is ``ndw_open_symbol``, replace ``x`` with ``open_char``
139
+
140
+ - If ``x`` is ``ndw_close_symbol``, replace ``x`` with ``close_char``.
141
+
142
+ - If ``x`` is neither ``ndw_open_symbol`` nor ``ndw_close_symbol``, a
143
+ :exc:`ValueError` is raised.
144
+
145
+ .. SEEALSO:: :func:`replace_dyck_char`
146
+
147
+ EXAMPLES::
148
+
149
+ sage: from sage.combinat.nu_dyck_word import replace_dyck_symbol
150
+ sage: replace_dyck_symbol(1)
151
+ 'N'
152
+ sage: replace_dyck_symbol(0)
153
+ 'E'
154
+ sage: replace_dyck_symbol(3)
155
+ Traceback (most recent call last):
156
+ ...
157
+ ValueError
158
+ """
159
+ if x == ndw_open_symbol:
160
+ return open_char
161
+ if x == ndw_close_symbol:
162
+ return close_char
163
+ raise ValueError
164
+
165
+
166
+ class NuDyckWord(CombinatorialElement):
167
+ r"""
168
+ A `\nu`-Dyck word.
169
+
170
+ Given a lattice path `\nu` in the `\ZZ^2` grid starting at the origin
171
+ `(0,0)` consisting of North `N = (0,1)` and East `E = (1,0)` steps, a
172
+ `\nu`-Dyck path is a lattice path in the `\ZZ^2` grid starting at the
173
+ origin `(0,0)` and ending at the same coordinate as `\nu` such that it is
174
+ weakly above `\nu`. A `\nu`-Dyck word is the representation of a
175
+ `\nu`-Dyck path where a North step is represented by a 1 and an East step
176
+ is represented by a 0.
177
+
178
+ INPUT:
179
+
180
+ - ``k1`` -- a path for the `\nu`-Dyck word
181
+
182
+ - ``k2`` -- a path for `\nu`
183
+
184
+ EXAMPLES::
185
+
186
+ sage: dw = NuDyckWord([1,0,1,0],[1,0,0,1]); dw
187
+ [1, 0, 1, 0]
188
+ sage: print(dw)
189
+ NENE
190
+ sage: dw.height()
191
+ 2
192
+
193
+ sage: dw = NuDyckWord('1010',[1,0,0,1]); dw
194
+ [1, 0, 1, 0]
195
+
196
+ sage: dw = NuDyckWord('NENE',[1,0,0,1]); dw
197
+ [1, 0, 1, 0]
198
+
199
+ sage: NuDyckWord([1,0,1,0],[1,0,0,1]).pretty_print()
200
+ __
201
+ _|x
202
+ | . .
203
+
204
+ sage: from sage.combinat.nu_dyck_word import update_ndw_symbols
205
+ sage: update_ndw_symbols(0,1)
206
+ sage: dw = NuDyckWord('0101001','0110010'); dw
207
+ [0, 1, 0, 1, 0, 0, 1]
208
+ sage: dw.pp()
209
+ __
210
+ |x
211
+ _| .
212
+ _|x .
213
+ | . . .
214
+ sage: update_ndw_symbols(1,0)
215
+ """
216
+ @staticmethod
217
+ def __classcall_private__(cls, dw=None, nu=None, **kwargs):
218
+ """
219
+ Return an element with the appropriate parent.
220
+
221
+ EXAMPLES::
222
+
223
+ sage: NuDyckWord('110100','101010')
224
+ [1, 1, 0, 1, 0, 0]
225
+ sage: NuDyckWord('010','010')
226
+ [0, 1, 0]
227
+ """
228
+ # if dw is none, then we might have a normal Dyck word
229
+ if dw is None:
230
+ from sage.combinat.dyck_word import DyckWord
231
+ return DyckWord(dw, kwargs)
232
+
233
+ if isinstance(dw, NuDyckWord):
234
+ return dw
235
+
236
+ if nu is None:
237
+ raise ValueError("nu required")
238
+
239
+ dw = to_word_path(dw)
240
+ nu = to_word_path(nu)
241
+
242
+ if path_weakly_above_other(dw, nu):
243
+ return NuDyckWords(nu)(dw)
244
+
245
+ raise ValueError("invalid nu-Dyck word")
246
+
247
+ def __init__(self, parent, dw, latex_options=None):
248
+ """
249
+ Initialize a nu-Dyck word.
250
+
251
+ EXAMPLES::
252
+
253
+ sage: NuDyckWord('010', '010')
254
+ [0, 1, 0]
255
+ sage: NuDyckWord('110100','101010')
256
+ [1, 1, 0, 1, 0, 0]
257
+ """
258
+ Element.__init__(self, parent)
259
+ self._path = to_word_path(dw)
260
+ self._list = list(self._path)
261
+
262
+ if parent is None:
263
+ raise ValueError("need parent object")
264
+
265
+ self._nu = parent._nu
266
+
267
+ if latex_options is None:
268
+ latex_options = {}
269
+ self._latex_options = dict(latex_options)
270
+
271
+ def __eq__(self, other):
272
+ """
273
+ Return if two paths are equal.
274
+
275
+ EXAMPLES::
276
+
277
+ sage: u = NuDyckWord('010','010')
278
+ sage: w = NuDyckWord('110100','101010')
279
+ sage: w == w
280
+ True
281
+ sage: u == w
282
+ False
283
+ sage: u == 4
284
+ False
285
+ """
286
+ if not isinstance(other, NuDyckWord):
287
+ return False
288
+ return self._path == other._path and self._nu == other._nu
289
+
290
+ def __neq__(self, other):
291
+ """
292
+ Return if two paths are not equal.
293
+
294
+ EXAMPLES::
295
+
296
+ sage: u = NuDyckWord('010','010')
297
+ sage: w = NuDyckWord('110100','101010')
298
+ sage: w != w
299
+ False
300
+ sage: u != w
301
+ True
302
+ sage: u != 4
303
+ True
304
+ """
305
+ return not self.__eq__(other)
306
+
307
+ def __le__(self, other):
308
+ """
309
+ Return if one path is included in another.
310
+
311
+ EXAMPLES::
312
+
313
+ sage: ND1 = NuDyckWord('101', '011')
314
+ sage: ND2 = NuDyckWord('110', '011')
315
+ sage: ND3 = NuDyckWord('011', '011')
316
+ sage: ND1 <= ND1
317
+ True
318
+ sage: ND1 <= ND2
319
+ True
320
+ sage: ND2 <= ND1
321
+ False
322
+ sage: ND3 <= ND2
323
+ True
324
+ sage: ND3 <= ND1
325
+ True
326
+ """
327
+ if self._nu == other._nu:
328
+ return path_weakly_above_other(other._path, self._path)
329
+ return False
330
+
331
+ def __lt__(self, other):
332
+ """
333
+ Return if one path is strictly included in another.
334
+
335
+ EXAMPLES::
336
+
337
+ sage: ND1 = NuDyckWord('101', '011')
338
+ sage: ND2 = NuDyckWord('110', '011')
339
+ sage: ND3 = NuDyckWord('011', '011')
340
+ sage: ND1 < ND1
341
+ False
342
+ sage: ND1 < ND2
343
+ True
344
+ sage: ND2 < ND1
345
+ False
346
+ sage: ND3 < ND2
347
+ True
348
+ sage: ND3 < ND1
349
+ True
350
+ """
351
+ return self.__le__(other) and not self.__eq__(other)
352
+
353
+ def __ge__(self, other):
354
+ """
355
+ Return if one path is included in another.
356
+
357
+ EXAMPLES::
358
+
359
+ sage: ND1 = NuDyckWord('101', '011')
360
+ sage: ND2 = NuDyckWord('110', '011')
361
+ sage: ND3 = NuDyckWord('011', '011')
362
+ sage: ND1 >= ND1
363
+ True
364
+ sage: ND1 >= ND2
365
+ False
366
+ sage: ND2 >= ND1
367
+ True
368
+ sage: ND1 >= ND3
369
+ True
370
+ sage: ND2 >= ND3
371
+ True
372
+ """
373
+ if self._nu == other._nu:
374
+ return path_weakly_above_other(self._path, other._path)
375
+ return False
376
+
377
+ def __gt__(self, other):
378
+ """
379
+ Return if one path is strictly included in another.
380
+
381
+ EXAMPLES::
382
+
383
+ sage: ND1 = NuDyckWord('101', '011')
384
+ sage: ND2 = NuDyckWord('110', '011')
385
+ sage: ND3 = NuDyckWord('011', '011')
386
+ sage: ND1 > ND1
387
+ False
388
+ sage: ND1 > ND2
389
+ False
390
+ sage: ND2 > ND1
391
+ True
392
+ sage: ND1 > ND3
393
+ True
394
+ sage: ND2 > ND3
395
+ True
396
+ """
397
+ return self.__ge__(other) and not self.__eq__(other)
398
+
399
+ def _cache_key(self) -> tuple:
400
+ """
401
+ Return a cache key for ``self``.
402
+
403
+ EXAMPLES::
404
+
405
+ sage: u = NuDyckWord('010','010')
406
+ sage: u._cache_key()
407
+ (0, 1, 0, 0, 1, 0)
408
+ """
409
+ return tuple(self._path) + tuple(self._nu)
410
+
411
+ def __hash__(self) -> int:
412
+ """
413
+ Return a hash for ``self``.
414
+
415
+ EXAMPLES::
416
+
417
+ sage: u = NuDyckWord('010','010')
418
+ sage: hash(u) # random
419
+ -4577085166836515071
420
+ """
421
+ return hash(''.join(str(i) for i in self._list))
422
+
423
+ def set_latex_options(self, D):
424
+ r"""
425
+ Set the latex options for use in the ``_latex_`` function.
426
+
427
+ The default values are set in the ``__init__`` function.
428
+
429
+ - ``color`` -- (default: black) the line color
430
+
431
+ - ``line width`` -- (default: `2 \times` ``tikz_scale``) value
432
+ representing the line width
433
+
434
+ - ``nu_options`` -- (default: ``'rounded corners=1, color=red, line
435
+ width=1'``) string to indicate what the tikz options should be for
436
+ path of `\nu`
437
+
438
+ - ``points_color`` -- (default: ``'black'``) str to indicate color
439
+ points should be drawn with
440
+
441
+ - ``show_grid`` -- boolean (default: ``True``); value to indicate if
442
+ grid should be shown
443
+
444
+ - ``show_nu`` -- boolean (default: ``True``); value to indicate if `\nu`
445
+ should be shown
446
+
447
+ - ``show_points`` -- boolean (default: ``False``); value to indicate
448
+ if points should be shown on path
449
+
450
+ - ``tikz_scale`` -- (default: 1) scale for use with the tikz package
451
+
452
+ INPUT:
453
+
454
+ - ``D`` -- dictionary with a list of latex parameters to change
455
+
456
+ EXAMPLES::
457
+
458
+ sage: NDW = NuDyckWord('010','010')
459
+ sage: NDW.set_latex_options({"tikz_scale":2})
460
+ sage: NDW.set_latex_options({"color":"blue", "show_points":True})
461
+
462
+ .. TODO::
463
+
464
+ This should probably be merged into NuDyckWord.options.
465
+ """
466
+ for opt in D:
467
+ self._latex_options[opt] = D[opt]
468
+
469
+ def latex_options(self) -> dict:
470
+ r"""
471
+ Return the latex options for use in the ``_latex_`` function as a
472
+ dictionary.
473
+
474
+ The default values are set using the options.
475
+
476
+ - ``color`` -- (default: black) the line color
477
+
478
+ - ``line width`` -- (default: 2*``tikz_scale``) value representing the
479
+ line width
480
+
481
+ - ``nu_options`` -- (default: ``'rounded corners=1, color=red, line
482
+ width=1'``) string to indicate what the tikz options should be for
483
+ path of `\nu`
484
+
485
+ - ``points_color`` -- (default: ``'black'``) str to indicate color
486
+ points should be drawn with
487
+
488
+ - ``show_grid`` -- boolean (default: ``True``); value to indicate if
489
+ grid should be shown
490
+
491
+ - ``show_nu`` -- boolean (default: ``True``); value to indicate if `\nu`
492
+ should be shown
493
+
494
+ - ``show_points`` -- boolean (default: ``False``); value to indicate
495
+ if points should be shown on path
496
+
497
+ - ``tikz_scale`` -- (default: 1) scale for use with the tikz package
498
+
499
+ EXAMPLES::
500
+
501
+ sage: NDW = NuDyckWord('010','010')
502
+ sage: NDW.latex_options()
503
+ {'color': black,
504
+ 'line width': 2,
505
+ 'nu_options': rounded corners=1, color=red, line width=1,
506
+ 'points_color': black,
507
+ 'show_grid': True,
508
+ 'show_nu': True,
509
+ 'show_points': False,
510
+ 'tikz_scale': 1}
511
+
512
+ .. TODO::
513
+
514
+ This should probably be merged into NuDyckWord.options.
515
+ """
516
+ d = self._latex_options.copy()
517
+ opts = self.parent().options
518
+ if "tikz_scale" not in d:
519
+ d["tikz_scale"] = opts.latex_tikz_scale
520
+ if "line width" not in d:
521
+ d["line width"] = opts.latex_line_width_scalar * d["tikz_scale"]
522
+ if "color" not in d:
523
+ d["color"] = opts.latex_color
524
+ if "show_points" not in d:
525
+ d["show_points"] = opts.latex_show_points
526
+ if "points_color" not in d:
527
+ d["points_color"] = opts.latex_points_color
528
+ if "show_grid" not in d:
529
+ d["show_grid"] = opts.latex_show_grid
530
+ if "show_nu" not in d:
531
+ d["show_nu"] = opts.latex_show_nu
532
+ if "nu_options" not in d:
533
+ d["nu_options"] = opts.latex_nu_options
534
+ return d
535
+
536
+ def _repr_(self) -> str:
537
+ r"""
538
+ Return a string representation of ``self`` depending on
539
+ :meth:`NuDyckWords.options`.
540
+
541
+ TESTS::
542
+
543
+ sage: NuDyckWord('01010','00011')
544
+ [0, 1, 0, 1, 0]
545
+ sage: NuDyckWord('10010','00011')
546
+ [1, 0, 0, 1, 0]
547
+ sage: NuDyckWords.options.display="lattice"
548
+ sage: NuDyckWord('10010','00011')
549
+ __
550
+ ___|x
551
+ |x x x
552
+
553
+ sage: NuDyckWords.options._reset()
554
+ """
555
+ return self.parent().options._dispatch(self, '_repr_', 'display')
556
+
557
+ def _repr_list(self) -> str:
558
+ r"""
559
+ Return a string representation of ``self`` as a list.
560
+
561
+ TESTS::
562
+
563
+ sage: NuDyckWord([1,1,0],[1,0,1]) # indirect doctest
564
+ [1, 1, 0]
565
+ sage: NuDyckWord('NNEE','NENE')
566
+ [1, 1, 0, 0]
567
+ """
568
+ return str(list(self._path))
569
+
570
+ def _repr_lattice(self, style=None, labelling=None):
571
+ r"""
572
+ See :meth:`pretty_print()`.
573
+
574
+ TESTS::
575
+
576
+ sage: n = NuDyckWord('00011001000100','00011001000100')
577
+ sage: print(n._repr_lattice(style='N-E', labelling=[1,2,3,4]))
578
+ ____
579
+ _____| . . 4
580
+ ___| . . . . . 3
581
+ | . . . . . . . 2
582
+ ______| . . . . . . . 1
583
+
584
+
585
+ sage: print(NuDyckWord('100101','010011')._repr_lattice())
586
+ _|
587
+ ___|x
588
+ |x . .
589
+
590
+ sage: print(NuDyckWord('110010','001011')._repr_lattice())
591
+ __
592
+ ___|x
593
+ |x x x
594
+ |x x .
595
+ """
596
+ if style is None:
597
+ style = self.parent().options.diagram_style
598
+ if style == "grid":
599
+ style = "N-E"
600
+
601
+ if style == "N-E":
602
+ path_length = self._path.length()
603
+ height = self._path.height()
604
+ width = self._path.width()
605
+ if path_length == 0:
606
+ return ".\n"
607
+
608
+ # Handle right-hand side labels
609
+ if labelling is None:
610
+ labels = [" "] * height
611
+ else:
612
+ if len(labelling) != height:
613
+ raise ValueError(f"the given labelling has the wrong length: {height} needed")
614
+ labels = [str(label) for label in labelling]
615
+ max_length = max(len(label) for label in labels)
616
+ labels = [lbl.rjust(max_length + 1) for lbl in labels]
617
+
618
+ rev_path = list(self._path.reversal())
619
+ rev_nu_path = list(self._nu.reversal())
620
+ ts = ""
621
+
622
+ # Grab first line
623
+ cur_pos = rev_path.index(ndw_open_symbol)
624
+ cur_nu_pos = rev_nu_path.index(ndw_open_symbol)
625
+ if cur_pos > 0:
626
+ ts += " " * (width - cur_pos)
627
+ ts += " _" + "__" * (cur_pos - 1)
628
+ ts += "_\n"
629
+
630
+ # Middle Lines
631
+ for i in range(height - 1):
632
+ old_pos = cur_pos
633
+ old_nu_pos = cur_nu_pos
634
+ cur_pos = rev_path.index(ndw_open_symbol, cur_pos + 1)
635
+ cur_nu_pos = rev_nu_path.index(ndw_open_symbol, cur_nu_pos + 1)
636
+
637
+ ts += " " * (width - cur_pos + i + 1)
638
+ if cur_pos != old_pos + 1:
639
+ ts += " _" + "__" * (cur_pos - old_pos - 2)
640
+ ts += "|"
641
+ if old_pos >= 0:
642
+ ts += "x " * (old_pos - old_nu_pos)
643
+ ts += " ." * (old_nu_pos - i)
644
+ ts += labels[height - i - 1]
645
+ ts += "\n"
646
+
647
+ # Final line
648
+ ts += "__" * (path_length - cur_pos - 1)
649
+ ts += "|"
650
+ ts += "x " * (cur_pos - cur_nu_pos)
651
+ ts += " ." * (cur_nu_pos - i - 1)
652
+ ts += labels[0]
653
+ ts += "\n"
654
+ return ts
655
+ raise ValueError(f"the given style (={style}) is not valid")
656
+
657
+ def _ascii_art_(self):
658
+ r"""
659
+ Return an ASCII art representation of ``self``.
660
+
661
+ TESTS::
662
+
663
+ sage: ascii_art(NuDyckWord('00011001000100','00011001000100'))
664
+ ____
665
+ _____| . .
666
+ ___| . . . . .
667
+ | . . . . . . .
668
+ ______| . . . . . . .
669
+ """
670
+ from sage.typeset.ascii_art import AsciiArt
671
+ rep = self.parent().options.ascii_art
672
+ if rep == "pretty_output":
673
+ ret = self._repr_lattice()
674
+ return AsciiArt(ret.splitlines(), baseline=0)
675
+
676
+ def __str__(self) -> str:
677
+ r"""
678
+ Return a string consisting of N and E steps corresponding to
679
+ the `\nu`-Dyck word.
680
+
681
+ EXAMPLES::
682
+
683
+ sage: str(NuDyckWord('100101','010011'))
684
+ 'NEENEN'
685
+ sage: str(NuDyckWord('101010','100110'))
686
+ 'NENENE'
687
+ """
688
+ return "".join(replace_dyck_symbol(let) for let in self._path)
689
+
690
+ def pretty_print(self, style=None, labelling=None):
691
+ r"""
692
+ Display a NuDyckWord as a lattice path in the `\ZZ^2` grid.
693
+
694
+ If the ``style`` is "N-E", then a cell below the diagonal is
695
+ indicated by a period, whereas a cell below the path but above
696
+ the diagonal is indicated by an x. If a list of labels is
697
+ included, they are displayed along the vertical edges of the
698
+ Dyck path.
699
+
700
+ INPUT:
701
+
702
+ - ``style`` -- (default: ``None``) can either be:
703
+
704
+ - ``None`` to use the option default
705
+ - "N-E" to show ``self`` as a path of north and east steps, or
706
+
707
+ - ``labelling`` -- (if style is "N-E") a list of labels assigned to
708
+ the up steps in ``self``
709
+
710
+ - ``underpath`` -- (if style is "N-E", default: ``True``) if ``True``,
711
+ an ``x`` to show the boxes between `\nu` and the `\nu`-Dyck Path
712
+
713
+ EXAMPLES::
714
+
715
+ sage: for ND in NuDyckWords('101010'): ND.pretty_print()
716
+ __
717
+ _| .
718
+ _| . .
719
+ | . . .
720
+ __
721
+ ___| .
722
+ |x . .
723
+ | . . .
724
+ ____
725
+ |x .
726
+ _| . .
727
+ | . . .
728
+ ____
729
+ _|x .
730
+ |x . .
731
+ | . . .
732
+ ______
733
+ |x x .
734
+ |x . .
735
+ | . . .
736
+
737
+ ::
738
+
739
+ sage: nu = [1,0,1,0,1,0,1,0,1,0,1,0]
740
+ sage: ND = NuDyckWord([1,1,1,0,1,0,0,1,1,0,0,0],nu)
741
+ sage: ND.pretty_print()
742
+ ______
743
+ |x x .
744
+ ___|x . .
745
+ _|x x . . .
746
+ |x x . . . .
747
+ |x . . . . .
748
+ | . . . . . .
749
+
750
+ ::
751
+
752
+ sage: NuDyckWord([1,1,0,0,1,0],[1,0,1,0,1,0]).pretty_print(
753
+ ....: labelling=[1,3,2])
754
+ __
755
+ ___| . 2
756
+ |x . . 3
757
+ | . . . 1
758
+
759
+ ::
760
+
761
+ sage: NuDyckWord('1101110011010010001101111000110000',
762
+ ....: '1010101010101010101010101010101010').pretty_print(
763
+ ....: labelling=list(range(1,18)))
764
+ ________
765
+ |x x x . 17
766
+ _____|x x . . 16
767
+ |x x x x . . . 15
768
+ |x x x . . . . 14
769
+ |x x . . . . . 13
770
+ _|x . . . . . . 12
771
+ |x . . . . . . . 11
772
+ _____| . . . . . . . . 10
773
+ ___|x x . . . . . . . . . 9
774
+ _|x x x . . . . . . . . . . 8
775
+ |x x x . . . . . . . . . . . 7
776
+ ___|x x . . . . . . . . . . . . 6
777
+ |x x x . . . . . . . . . . . . . 5
778
+ |x x . . . . . . . . . . . . . . 4
779
+ _|x . . . . . . . . . . . . . . . 3
780
+ |x . . . . . . . . . . . . . . . . 2
781
+ | . . . . . . . . . . . . . . . . . 1
782
+
783
+
784
+ ::
785
+
786
+ sage: NuDyckWord().pretty_print()
787
+ .
788
+ """
789
+ print(self._repr_lattice(style, labelling))
790
+
791
+ pp = pretty_print
792
+
793
+ def _latex_(self):
794
+ r"""
795
+ A latex representation of ``self`` using the tikzpicture package.
796
+
797
+ EXAMPLES::
798
+
799
+ sage: NDW = NuDyckWord('010','010')
800
+ sage: NDW.set_latex_options({"show_points":True})
801
+ sage: latex(NDW)
802
+ \vcenter{\hbox{$\begin{tikzpicture}[scale=1]
803
+ \draw[dotted] (0, 0) grid (2, 1);
804
+ \draw[line width=2,color=black,fill=black](0, 0) circle (0.21);
805
+ \draw[line width=2,color=black,fill=black](1, 0) circle (0.21);
806
+ \draw[line width=2,color=black,fill=black](1, 1) circle (0.21);
807
+ \draw[line width=2,color=black,fill=black](2, 1) circle (0.21);
808
+ \draw[rounded corners=1, color=red, line width=1] (0, 0) -- (1, 0) -- (1, 1) -- (2, 1);
809
+ \draw[rounded corners=1, color=black, line width=2] (0, 0) -- (1, 0) -- (1, 1) -- (2, 1);
810
+ \end{tikzpicture}$}}
811
+ sage: NuDyckWord('01','01')._latex_()
812
+ '\\vcenter{\\hbox{$\\begin{tikzpicture}[scale=1]\n \\draw[dotted] (0, 0) grid (1, 1);\n \\draw[rounded corners=1, color=red, line width=1] (0, 0) -- (1, 0) -- (1, 1);\n \\draw[rounded corners=1, color=black, line width=2] (0, 0) -- (1, 0) -- (1, 1);\n\\end{tikzpicture}$}}'
813
+ sage: NuDyckWord('101100','101010')._latex_()
814
+ '\\vcenter{\\hbox{$\\begin{tikzpicture}[scale=1]\n \\draw[dotted] (0, 0) grid (3, 3);\n \\draw[rounded corners=1, color=red, line width=1] (0, 0) -- (0, 1) -- (1, 1) -- (1, 2) -- (2, 2) -- (2, 3) -- (3, 3);\n \\draw[rounded corners=1, color=black, line width=2] (0, 0) -- (0, 1) -- (1, 1) -- (1, 2) -- (1, 3) -- (2, 3) -- (3, 3);\n\\end{tikzpicture}$}}'
815
+ """
816
+ latex.add_package_to_preamble_if_available("tikz")
817
+ latex_options = self.latex_options()
818
+
819
+ # Start setting up tikz
820
+ res = "\\vcenter{\\hbox{$\\begin{tikzpicture}"
821
+ res += "[scale=" + str(latex_options['tikz_scale']) + "]"
822
+ res += "\n"
823
+
824
+ # Setup background grid
825
+ if latex_options['show_grid']:
826
+ grid = [((0, 0), (self.width(), self.height()))]
827
+ for v1, v2 in grid:
828
+ res += f" \\draw[dotted] {v1} grid {v2};"
829
+ res += "\n"
830
+
831
+ # Add points if wanted
832
+ if latex_options['show_points']:
833
+ pt_color = latex_options['points_color']
834
+ radius = 0.15 + .03 * latex_options['line width']
835
+ for v in self.points():
836
+ res += " \\draw[line width=2,"
837
+ res += f"color={pt_color},fill={pt_color}]"
838
+ res += f"{v} circle ({radius});"
839
+ res += "\n"
840
+
841
+ # Add nu if wanted
842
+ if latex_options['show_nu']:
843
+ res += " \\draw[%s]" % (str(latex_options['nu_options']))
844
+ for k, p in enumerate(self._nu.points()):
845
+ if k == 0:
846
+ res += " %s" % (str(p))
847
+ else:
848
+ res += " -- %s" % (str(p))
849
+ res += ";\n"
850
+
851
+ # setup Path
852
+ res += " \\draw[rounded corners=1, color={}, line width={}]".format(
853
+ latex_options['color'],
854
+ str(latex_options['line width'])
855
+ )
856
+ for k, p in enumerate(self._path.points()):
857
+ if k == 0:
858
+ res += " %s" % (str(p))
859
+ else:
860
+ res += " -- %s" % (str(p))
861
+ res += ";\n"
862
+ res += "\\end{tikzpicture}$}}"
863
+ return res
864
+
865
+ def plot(self, **kwds):
866
+ r"""
867
+ Plot a `\nu`-Dyck word as a continuous path.
868
+
869
+ EXAMPLES::
870
+
871
+ sage: NDW = NuDyckWord('010','010')
872
+ sage: NDW.plot() # needs sage.plot
873
+ Graphics object consisting of 1 graphics primitive
874
+ """
875
+ from sage.plot.plot import list_plot
876
+ return list_plot(list(self.points()), plotjoined=True, **kwds)
877
+
878
+ def path(self):
879
+ r"""
880
+ Return the underlying path object.
881
+
882
+ EXAMPLES::
883
+
884
+ sage: NDW = NuDyckWord('10011001000','00100101001')
885
+ sage: NDW.path()
886
+ Path: 10011001000
887
+ """
888
+ return self._path
889
+
890
+ def height(self):
891
+ r"""
892
+ Return the height of ``self``.
893
+
894
+ The height is the number of ``north`` steps.
895
+
896
+ EXAMPLES::
897
+
898
+ sage: NuDyckWord('1101110011010010001101111000110000',
899
+ ....: '1010101010101010101010101010101010').height()
900
+ 17
901
+ """
902
+ return self._path.height()
903
+
904
+ def width(self):
905
+ r"""
906
+ Return the width of ``self``.
907
+
908
+ The width is the number of ``east`` steps.
909
+
910
+ EXAMPLES::
911
+
912
+ sage: NuDyckWord('110111001101001000110111100011000',
913
+ ....: '101010101010101010101010101010101').width()
914
+ 16
915
+ """
916
+ return self._path.width()
917
+
918
+ def length(self):
919
+ r"""
920
+ Return the length of ``self``.
921
+
922
+ The length is the total number of steps.
923
+
924
+ EXAMPLES::
925
+
926
+ sage: NDW = NuDyckWord('10011001000','00100101001')
927
+ sage: NDW.length()
928
+ 11
929
+ """
930
+ return self._path.length()
931
+
932
+ def points(self):
933
+ r"""
934
+ Return an iterator for the points on the `\nu`-Dyck path.
935
+
936
+ EXAMPLES::
937
+
938
+ sage: list(NuDyckWord('110111001101001000110111100011000',
939
+ ....: '101010101010101010101010101010101')._path.points())
940
+ [(0, 0),
941
+ (0, 1),
942
+ (0, 2),
943
+ (1, 2),
944
+ (1, 3),
945
+ (1, 4),
946
+ (1, 5),
947
+ (2, 5),
948
+ (3, 5),
949
+ (3, 6),
950
+ (3, 7),
951
+ (4, 7),
952
+ (4, 8),
953
+ (5, 8),
954
+ (6, 8),
955
+ (6, 9),
956
+ (7, 9),
957
+ (8, 9),
958
+ (9, 9),
959
+ (9, 10),
960
+ (9, 11),
961
+ (10, 11),
962
+ (10, 12),
963
+ (10, 13),
964
+ (10, 14),
965
+ (10, 15),
966
+ (11, 15),
967
+ (12, 15),
968
+ (13, 15),
969
+ (13, 16),
970
+ (13, 17),
971
+ (14, 17),
972
+ (15, 17),
973
+ (16, 17)]
974
+ """
975
+ return self._path.points()
976
+
977
+ def heights(self):
978
+ r"""
979
+ Return the heights of each point on ``self``.
980
+
981
+ We view the Dyck word as a Dyck path from `(0,0)` to
982
+ `(x,y)` in the first quadrant by letting ``1``'s represent
983
+ steps in the direction `(0,1)` and ``0``'s represent steps in
984
+ the direction `(1,0)`.
985
+
986
+ The heights is the sequence of the `y`-coordinates of all
987
+ `x+y` lattice points along the path.
988
+
989
+ EXAMPLES::
990
+
991
+ sage: NuDyckWord('010','010').heights()
992
+ [0, 0, 1, 1]
993
+ sage: NuDyckWord('110100','101010').heights()
994
+ [0, 1, 2, 2, 3, 3, 3]
995
+ """
996
+ return self._path.height_vector()
997
+
998
+ def widths(self):
999
+ r"""
1000
+ Return the widths of each point on ``self``.
1001
+
1002
+ We view the Dyck word as a Dyck path from `(0,0)` to
1003
+ `(x,y)` in the first quadrant by letting ``1``'s represent
1004
+ steps in the direction `(0,1)` and ``0``'s represent steps in
1005
+ the direction `(1,0)`.
1006
+
1007
+ The widths is the sequence of the `x`-coordinates of all
1008
+ `x+y` lattice points along the path.
1009
+
1010
+ EXAMPLES::
1011
+
1012
+ sage: NuDyckWord('010','010').widths()
1013
+ [0, 1, 1, 2]
1014
+ sage: NuDyckWord('110100','101010').widths()
1015
+ [0, 0, 0, 1, 1, 2, 3]
1016
+ """
1017
+ return self._path.width_vector()
1018
+
1019
+ def horizontal_distance(self):
1020
+ r"""
1021
+ Return a list of how far each point is from `\nu`.
1022
+
1023
+ EXAMPLES::
1024
+
1025
+ sage: NDW = NuDyckWord('10010100','00000111')
1026
+ sage: NDW.horizontal_distance()
1027
+ [5, 5, 4, 3, 3, 2, 2, 1, 0]
1028
+ sage: NDW = NuDyckWord('10010100','00001011')
1029
+ sage: NDW.horizontal_distance()
1030
+ [4, 5, 4, 3, 3, 2, 2, 1, 0]
1031
+ sage: NDW = NuDyckWord('10011001000','00100101001')
1032
+ sage: NDW.horizontal_distance()
1033
+ [2, 4, 3, 2, 3, 5, 4, 3, 3, 2, 1, 0]
1034
+ """
1035
+ # Grab furthest east point at each height of nu
1036
+ nu_points = list(self._nu.points())
1037
+ nu_easts = [max(i for i, j in nu_points if j == k)
1038
+ for k in range(self._nu.height() + 1)]
1039
+
1040
+ points = list(self._path.points())
1041
+ return [nu_easts[j] - i for i, j in points]
1042
+
1043
+ def can_mutate(self, i) -> bool | int:
1044
+ """
1045
+ Return True/False based off if mutable at height `i`.
1046
+
1047
+ Can only mutate if an east step is followed by a north step at height
1048
+ `i`.
1049
+
1050
+ OUTPUT: whether we can mutate at height of `i`
1051
+
1052
+ EXAMPLES::
1053
+
1054
+ sage: NDW = NuDyckWord('10010100','00000111')
1055
+ sage: NDW.can_mutate(1)
1056
+ False
1057
+ sage: NDW.can_mutate(3)
1058
+ 5
1059
+
1060
+ TESTS::
1061
+
1062
+ sage: NDW = NuDyckWord('10010100','00000111')
1063
+ sage: NDW.can_mutate(33)
1064
+ Traceback (most recent call last):
1065
+ ...
1066
+ ValueError: cannot mutate above or below path
1067
+ """
1068
+ if i > self.height() or i <= 0:
1069
+ raise ValueError('cannot mutate above or below path')
1070
+
1071
+ # Find the ith north step
1072
+ level = 0
1073
+ ndw = self._list
1074
+ for j, k in enumerate(ndw):
1075
+ if k == ndw_open_symbol:
1076
+ level += 1
1077
+ if level == i:
1078
+ break
1079
+ if j > 0 and ndw[j - 1] == ndw_close_symbol:
1080
+ return j
1081
+ return False
1082
+
1083
+ def mutate(self, i) -> None | NuDyckWord:
1084
+ r"""
1085
+ Return a new `\nu`-Dyck Word if possible.
1086
+
1087
+ If at height `i` we have an east step E meeting a north step N then we
1088
+ calculate all horizontal distances from this point until we find
1089
+ the first point that has the same horizontal distance to `\nu`. We let
1090
+
1091
+ - d is everything up until EN (not including EN)
1092
+
1093
+ - f be everything between N and the point with the same horizontal
1094
+ distance (including N)
1095
+
1096
+ - g is everything after f
1097
+
1098
+ .. SEEALSO:: :meth:`can_mutate`
1099
+
1100
+ EXAMPLES::
1101
+
1102
+ sage: NDW = NuDyckWord('10010100','00000111')
1103
+ sage: NDW.mutate(1)
1104
+ sage: NDW.mutate(3)
1105
+ [1, 0, 0, 1, 1, 0, 0, 0]
1106
+ """
1107
+ mutation_index = self.can_mutate(i)
1108
+ if not mutation_index:
1109
+ return None
1110
+
1111
+ horiz = self.horizontal_distance()
1112
+ # Find horiz in between East and North Step
1113
+ horiz_num = horiz[mutation_index]
1114
+ other_index = len(horiz)
1115
+ for i in range(mutation_index + 1, len(horiz)):
1116
+ if horiz[i] == horiz_num:
1117
+ other_index = i
1118
+ break
1119
+ ndw = self._list
1120
+ d = ndw[0:mutation_index - 1]
1121
+ e = ndw[mutation_index:other_index]
1122
+ f = ndw[other_index:]
1123
+ return NuDyckWord(d + e + [ndw_close_symbol] + f, self._nu)
1124
+
1125
+
1126
+ class NuDyckWords(Parent):
1127
+ r"""
1128
+ `\nu`-Dyck words.
1129
+
1130
+ Given a lattice path `\nu` in the `\ZZ^2` grid starting at the origin
1131
+ `(0,0)` consisting of North `N = (0,1)` and East `E = (1,0)` steps, a
1132
+ `\nu`-Dyck path is a lattice path in the`\ZZ^2` grid starting at the
1133
+ origin `(0,0)` and ending at the same coordinate as `\nu` such that it is
1134
+ weakly above `\nu`. A `\nu`-Dyck word is the representation of a
1135
+ `\nu`-Dyck path where a North step is represented by a 1 and an East step
1136
+ is represented by a 0.
1137
+
1138
+ INPUT:
1139
+
1140
+ - ``nu`` -- the base lattice path
1141
+
1142
+ EXAMPLES::
1143
+
1144
+ sage: NDW = NuDyckWords('1010'); NDW
1145
+ [1, 0, 1, 0] Dyck words
1146
+ sage: [1,0,1,0] in NDW
1147
+ True
1148
+ sage: [1,1,0,0] in NDW
1149
+ True
1150
+ sage: [1,0,0,1] in NDW
1151
+ False
1152
+ sage: [0,1,0,1] in NDW
1153
+ False
1154
+ sage: NDW.cardinality()
1155
+ 2
1156
+ """
1157
+
1158
+ Element = NuDyckWord
1159
+
1160
+ def __init__(self, nu=()) -> None:
1161
+ """
1162
+ Initialize ``self``.
1163
+
1164
+ EXAMPLES::
1165
+
1166
+ sage: TestSuite(NuDyckWords(nu=[1,0,1])).run()
1167
+ """
1168
+ Parent.__init__(self, category=FiniteEnumeratedSets())
1169
+
1170
+ self._nu = to_word_path(nu)
1171
+ if self._nu is None:
1172
+ raise ValueError("invalid nu supplied")
1173
+
1174
+ # add options to class
1175
+ class options(GlobalOptions):
1176
+ r"""
1177
+ Set and display the options for `\nu`-Dyck words. If no parameters
1178
+ are set, then the function returns a copy of the options dictionary.
1179
+
1180
+ The ``options`` to `\nu`-Dyck words can be accessed as the method
1181
+ :meth:`NuDyckWords.options` of :class:`NuDyckWords` and
1182
+ related parent classes.
1183
+
1184
+ @OPTIONS
1185
+
1186
+ EXAMPLES::
1187
+
1188
+ sage: ND = NuDyckWords('101')
1189
+ sage: ND
1190
+ [1, 0, 1] Dyck words
1191
+ sage: ND.options
1192
+ Current options for NuDyckWords
1193
+ - ascii_art: pretty_output
1194
+ - diagram_style: grid
1195
+ - display: list
1196
+ - latex_color: black
1197
+ - latex_line_width_scalar: 2
1198
+ - latex_nu_options: rounded corners=1, color=red, line width=1
1199
+ - latex_points_color: black
1200
+ - latex_show_grid: True
1201
+ - latex_show_nu: True
1202
+ - latex_show_points: False
1203
+ - latex_tikz_scale: 1
1204
+ """
1205
+ NAME = 'NuDyckWords'
1206
+ module = 'sage.combinat.nu_dyck_path'
1207
+ display = {'default': "list",
1208
+ 'description': 'Specifies how nu Dyck words should be printed',
1209
+ 'values': {'list': 'displayed as a list',
1210
+ 'lattice': 'displayed on the lattice defined by ``diagram_style``'},
1211
+ 'case_sensitive': False}
1212
+ ascii_art = {'default': "pretty_output",
1213
+ 'description': 'Specifies how the ascii art of nu Dyck words should be printed',
1214
+ 'values': {'pretty_output': "Using pretty printing"},
1215
+ 'alias': {'pretty_print': "pretty_output"},
1216
+ 'case_sensitive': False}
1217
+ diagram_style = {'default': "grid",
1218
+ 'values': {
1219
+ 'grid': 'printing as paths on a grid using N and E steps'},
1220
+ 'alias': {'N-E': 'grid'},
1221
+ 'case_sensitive': False}
1222
+ latex_tikz_scale = {'default': 1,
1223
+ 'description': 'The default value for the tikz scale when latexed',
1224
+ 'checker': lambda x: True} # More trouble than it's worth to check
1225
+ latex_line_width_scalar = {'default': 2,
1226
+ 'description': 'The default value for the line width as a '
1227
+ 'multiple of the tikz scale when latexed',
1228
+ 'checker': lambda x: True} # More trouble than it's worth to check
1229
+ latex_color = {'default': "black",
1230
+ 'description': 'The default value for the color when latexed',
1231
+ 'checker': lambda x: isinstance(x, str)}
1232
+ latex_show_points = {'default': False,
1233
+ 'description': 'The default value for showing points',
1234
+ 'checker': lambda x: isinstance(x, bool)}
1235
+ latex_points_color = {'default': 'black',
1236
+ 'description': 'The default value for path color.',
1237
+ 'checker': lambda x: isinstance(x, str)}
1238
+ latex_show_grid = {'default': True,
1239
+ 'description': 'The default value for showing grid',
1240
+ 'checker': lambda x: isinstance(x, bool)}
1241
+ latex_show_nu = {'default': True,
1242
+ 'description': 'The default value for showing nu',
1243
+ 'checker': lambda x: isinstance(x, bool)}
1244
+ latex_nu_options = {'default': 'rounded corners=1, color=red, line width=1',
1245
+ 'description': 'The default value for options for nu path',
1246
+ 'checker': lambda x: isinstance(x, str)}
1247
+
1248
+ def _element_constructor_(self, word):
1249
+ """
1250
+ Construct an element of ``self``.
1251
+
1252
+ EXAMPLES::
1253
+
1254
+ sage: NDW = NuDyckWords('101')
1255
+ sage: elt = NDW('110'); elt
1256
+ [1, 1, 0]
1257
+ sage: elt.parent() is NDW
1258
+ True
1259
+ """
1260
+ if isinstance(word, NuDyckWord) and word.parent() is self:
1261
+ return word
1262
+ return self.element_class(self, to_word_path(word))
1263
+
1264
+ def __contains__(self, x) -> bool:
1265
+ r"""
1266
+ Check for containment.
1267
+
1268
+ TESTS::
1269
+
1270
+ sage: NDW = NuDyckWords([1,0,1,1])
1271
+ sage: [1,1,0,1] in NDW
1272
+ True
1273
+ sage: [1,0,1,1] in NDW
1274
+ True
1275
+ sage: [0] in NDW
1276
+ False
1277
+ sage: [1, 0] in NDW
1278
+ False
1279
+ """
1280
+ return path_weakly_above_other(to_word_path(x), self._nu)
1281
+
1282
+ def __eq__(self, other):
1283
+ """
1284
+ Return equality.
1285
+
1286
+ TESTS::
1287
+
1288
+ sage: A = NuDyckWords([1,0,1,1])
1289
+ sage: B = NuDyckWords([1,0,1,1])
1290
+ sage: C = NuDyckWords([1,0,1,1,1])
1291
+ sage: A == B
1292
+ True
1293
+ sage: A == C
1294
+ False
1295
+ """
1296
+ if not isinstance(other, NuDyckWords):
1297
+ return False
1298
+ return self._nu == other._nu
1299
+
1300
+ def __neq__(self, other):
1301
+ """
1302
+ Return inequality.
1303
+
1304
+ TESTS::
1305
+
1306
+ sage: A = NuDyckWords([1,0,1,1])
1307
+ sage: B = NuDyckWords([1,0,1,1])
1308
+ sage: C = NuDyckWords([1,0,1,1,1])
1309
+ sage: A != B
1310
+ False
1311
+ sage: A != C
1312
+ True
1313
+ """
1314
+ return not self.__eq__(other)
1315
+
1316
+ def _repr_(self) -> str:
1317
+ r"""
1318
+ TESTS::
1319
+
1320
+ sage: NuDyckWords([1,0,1,1])
1321
+ [1, 0, 1, 1] Dyck words
1322
+ """
1323
+ return f"{list(self._nu)} Dyck words"
1324
+
1325
+ def _cache_key(self) -> str:
1326
+ """
1327
+ Return a cache key
1328
+
1329
+ TESTS::
1330
+
1331
+ sage: NuDyckWords([1,0,1,1])._cache_key()
1332
+ '1011'
1333
+ """
1334
+ return str(self._nu)
1335
+
1336
+ def _an_element_(self):
1337
+ r"""
1338
+ Return an element.
1339
+
1340
+ TESTS::
1341
+
1342
+ sage: NuDyckWords('101').an_element()
1343
+ [1, 0, 1]
1344
+ """
1345
+ return self.element_class(self, self._nu)
1346
+
1347
+ def __iter__(self, N=[], D=[], i=None, X=None):
1348
+ """
1349
+ Iterate over ``self``.
1350
+
1351
+ The iterator interchanges a 0,1 pair whenever the 0 comes before a 1
1352
+
1353
+ EXAMPLES::
1354
+
1355
+ sage: it = NuDyckWords('101010').__iter__()
1356
+ sage: [i for i in it]
1357
+ [[1, 0, 1, 0, 1, 0],
1358
+ [1, 1, 0, 0, 1, 0],
1359
+ [1, 0, 1, 1, 0, 0],
1360
+ [1, 1, 0, 1, 0, 0],
1361
+ [1, 1, 1, 0, 0, 0]]
1362
+ """
1363
+ # Define successor function for recursion
1364
+ def transpose_close_open(N):
1365
+ for k, v in enumerate(N._list):
1366
+ if k > 0 and v == ndw_open_symbol:
1367
+ w = N._list[k - 1]
1368
+ if w == ndw_close_symbol:
1369
+ new = N._list[:k - 1] + [v, w] + N._list[k + 1:]
1370
+ yield self.element_class(self, new)
1371
+
1372
+ RES = RecursivelyEnumeratedSet([self.element_class(self, self._nu)],
1373
+ transpose_close_open)
1374
+ return RES.breadth_first_search_iterator()
1375
+
1376
+ def cardinality(self):
1377
+ r"""
1378
+ Return the number of `\nu`-Dyck words.
1379
+
1380
+ EXAMPLES::
1381
+
1382
+ sage: NDW = NuDyckWords('101010'); NDW.cardinality()
1383
+ 5
1384
+ sage: NDW = NuDyckWords('1010010'); NDW.cardinality()
1385
+ 7
1386
+ sage: NDW = NuDyckWords('100100100'); NDW.cardinality()
1387
+ 12
1388
+ """
1389
+ return Integer(len([1 for _ in self.__iter__()]))
1390
+
1391
+
1392
+ def to_word_path(word):
1393
+ r"""
1394
+ Convert input into a word path over an appropriate alphabet.
1395
+
1396
+ Helper function.
1397
+
1398
+ INPUT:
1399
+
1400
+ - ``word`` -- word to convert to wordpath
1401
+
1402
+ OUTPUT: a ``FiniteWordPath_north_east`` object
1403
+
1404
+ EXAMPLES::
1405
+
1406
+ sage: from sage.combinat.nu_dyck_word import to_word_path
1407
+ sage: wp = to_word_path('NEENENEN'); wp
1408
+ Path: 10010101
1409
+ sage: from sage.combinat.words.paths import FiniteWordPath_north_east
1410
+ sage: isinstance(wp,FiniteWordPath_north_east)
1411
+ True
1412
+ sage: to_word_path('1001')
1413
+ Path: 1001
1414
+ sage: to_word_path([0,1,0,0,1,0])
1415
+ Path: 010010
1416
+ """
1417
+ # If we already have the object, don't worry
1418
+ if isinstance(word, FiniteWordPath_north_east):
1419
+ return word
1420
+
1421
+ # If we have a Nu Dyck Path, return the path it contains
1422
+ if isinstance(word, NuDyckWord):
1423
+ return word.path()
1424
+
1425
+ # if we have a string, convert to list
1426
+ if isinstance(word, str):
1427
+ word = map(replace_dyck_char, word)
1428
+
1429
+ # By default "north" is first symbol, "east" is second symbol
1430
+ P = WordPaths_north_east([ndw_open_symbol, ndw_close_symbol])
1431
+
1432
+ return P(word)
1433
+
1434
+
1435
+ def path_weakly_above_other(path, other) -> bool:
1436
+ r"""
1437
+ Test if ``path`` is weakly above ``other``.
1438
+
1439
+ A path `P` is wealy above another path `Q` if `P` and `Q` are the same
1440
+ length and if any prefix of length `n` of `Q` contains more North steps
1441
+ than the prefix of length `n` of `P`.
1442
+
1443
+ INPUT:
1444
+
1445
+ - ``path`` -- the path to verify is weakly above the other path
1446
+
1447
+ - ``other`` -- the other path to verify is weakly below the path
1448
+
1449
+ OUTPUT: boolean
1450
+
1451
+ EXAMPLES::
1452
+
1453
+ sage: from sage.combinat.nu_dyck_word import path_weakly_above_other
1454
+ sage: path_weakly_above_other('1001','0110')
1455
+ False
1456
+ sage: path_weakly_above_other('1001','0101')
1457
+ True
1458
+ sage: path_weakly_above_other('1111','0101')
1459
+ False
1460
+ sage: path_weakly_above_other('111100','0101')
1461
+ False
1462
+ """
1463
+ # Ensure we have word paths:
1464
+ path = to_word_path(path)
1465
+ other = to_word_path(other)
1466
+
1467
+ # Must be same length and must have same height
1468
+ if path.length() != other.length() or path.height() != other.height():
1469
+ return False
1470
+
1471
+ # path is above other if height is always >= height of other
1472
+ p_height = path.height_vector()
1473
+ o_height = other.height_vector()
1474
+ return all(p_h >= o_h for p_h, o_h in zip(p_height, o_height))