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,1077 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ # sage.doctest: needs sage.combinat sage.graphs sage.modules
3
+ r"""
4
+ Fully commutative elements of Coxeter groups
5
+
6
+ An element `w` in a Coxeter system (W,S) is fully commutative (FC) if
7
+ every two reduced words of w can be related by a sequence of only
8
+ commutation relations, i.e., relations of the form `st=ts` where `s,t` are
9
+ commuting generators in `S`. See [Ste1996]_.
10
+
11
+ Authors:
12
+
13
+ - Chase Meadors, Tianyuan Xu (2020): Initial version
14
+
15
+ Acknowledgements
16
+ ----------------
17
+
18
+ A draft of this code was written during an REU project at University of
19
+ Colorado Boulder. We thank Rachel Castro, Joel Courtney, Thomas Magnuson and
20
+ Natalie Schoenhals for their contribution to the project and the code.
21
+ """
22
+ # ****************************************************************************
23
+ # Copyright (C) 2020 Chase Meadors <Chase.Meadors at colorado.edu>,
24
+ # Tianyuan Xu <Tianyuan.Xu at colorado.edu>
25
+ #
26
+ # This program is free software: you can redistribute it and/or modify
27
+ # it under the terms of the GNU General Public License as published by
28
+ # the Free Software Foundation, either version 2 of the License, or
29
+ # (at your option) any later version.
30
+ # https://www.gnu.org/licenses/
31
+ # ****************************************************************************
32
+ from collections import deque
33
+
34
+ from sage.categories.coxeter_groups import CoxeterGroups
35
+ from sage.categories.enumerated_sets import EnumeratedSets
36
+ from sage.misc.lazy_import import lazy_import
37
+ from sage.structure.list_clone import NormalizedClonableList
38
+ from sage.structure.parent import Parent
39
+ from sage.structure.unique_representation import UniqueRepresentation
40
+
41
+ lazy_import('sage.combinat.posets.posets', 'Poset')
42
+ lazy_import('sage.combinat.root_system.coxeter_group', 'CoxeterGroup')
43
+ lazy_import('sage.combinat.root_system.coxeter_matrix', 'CoxeterMatrix')
44
+
45
+
46
+ class FullyCommutativeElement(NormalizedClonableList):
47
+ r"""
48
+ A fully commutative (FC) element in a Coxeter system.
49
+
50
+ An element `w` in a Coxeter system (W,S) is fully commutative (FC) if every
51
+ two reduced word of w can be related by a sequence of only commutation
52
+ relations, i.e., relations of the form `st=ts` where `s,t` are commuting
53
+ generators in `S`.
54
+
55
+ Every FC element has a canonical reduced word called its Cartier--Foata
56
+ form. See [Gre2006]_. We will normalize each FC element to this form.
57
+ """
58
+
59
+ def group_element(self):
60
+ r"""
61
+ Get the actual element of the Coxeter group associated with
62
+ ``self.parent()`` corresponding to ``self``.
63
+
64
+ EXAMPLES::
65
+
66
+ sage: W = CoxeterGroup(['A', 3])
67
+ sage: FC = W.fully_commutative_elements()
68
+ sage: x = FC([1, 2])
69
+ sage: x.group_element()
70
+ [ 0 -1 1]
71
+ [ 1 -1 1]
72
+ [ 0 0 1]
73
+ sage: x.group_element() in W
74
+ True
75
+ """
76
+ return self.parent().coxeter_group().from_reduced_word(self)
77
+
78
+ ###########################################################################
79
+ # Characterization and representation of FC elements #
80
+ ###########################################################################
81
+
82
+ # Methods required as a subclass of NormalizedClonableList:
83
+ def check(self):
84
+ r"""
85
+ Called automatically when an element is created.
86
+
87
+ EXAMPLES::
88
+
89
+ sage: CoxeterGroup(['A', 3]).fully_commutative_elements()([1, 2]) # indirect doctest
90
+ [1, 2]
91
+ sage: CoxeterGroup(['A', 3]).fully_commutative_elements()([1, 2, 1]) # indirect doctest
92
+ Traceback (most recent call last):
93
+ ...
94
+ ValueError: the input is not a reduced word of a fully commutative element
95
+ """
96
+ if not self.is_fully_commutative():
97
+ raise ValueError('the input is not a reduced word of a fully commutative element')
98
+
99
+ def normalize(self):
100
+ r"""
101
+ Mutate ``self`` into Cartier-Foata normal form.
102
+
103
+ EXAMPLES:
104
+
105
+ The following reduced words express the same FC elements in `B_5`::
106
+
107
+ sage: FC = CoxeterGroup(['B', 5]).fully_commutative_elements()
108
+ sage: FC([1, 4, 3, 5, 2, 4, 3]) # indirect doctest
109
+ [1, 4, 3, 5, 2, 4, 3]
110
+ sage: FC([4, 1, 3, 5, 2, 4, 3]) # indirect doctest
111
+ [1, 4, 3, 5, 2, 4, 3]
112
+ sage: FC([4, 3, 1, 5, 4, 2, 3]) # indirect doctest
113
+ [1, 4, 3, 5, 2, 4, 3]
114
+
115
+ .. NOTE::
116
+
117
+ The Cartier--Foata form of a reduced word of an FC element `w` can
118
+ be found recursively by repeatedly moving left descents of
119
+ elements to the left and ordering the left descents from small to
120
+ large. In the above example, the left descents of the element are
121
+ 4 and 1, therefore the Cartier--Foata form of the element is the
122
+ concatenation of [1,4] with the Cartier--Foata form of the
123
+ remaining part of the word. See [Gre2006]_.
124
+
125
+ .. SEEALSO:: :func:`descents`
126
+ """
127
+ self._require_mutable()
128
+
129
+ out_word = []
130
+
131
+ while self:
132
+ fronts = self.descents()
133
+ out_word.extend(sorted(fronts))
134
+ for s in fronts:
135
+ self.remove(s)
136
+
137
+ self._set_list(out_word)
138
+
139
+ # Full commutativity test
140
+ def is_fully_commutative(self):
141
+ r"""
142
+ Check if ``self`` is the reduced word of an FC element.
143
+
144
+ To check if ``self`` is FC, we use the well-known characterization that
145
+ an element `w` in a Coxeter system `(W,S)` is FC if and only if for
146
+ every pair of generators `s,t \in S` for which `m(s,t)>2`, no reduced
147
+ word of `w` contains the 'braid' word `sts...` of length `m(s,t)` as a
148
+ contiguous subword. See [Ste1996]_.
149
+
150
+ :func:`check` is an alias of this method, and is called automatically
151
+ when an element is created.
152
+
153
+ EXAMPLES::
154
+
155
+ sage: FC = CoxeterGroup(['A', 3]).fully_commutative_elements()
156
+ sage: x = FC([1, 2]); x.is_fully_commutative()
157
+ True
158
+ sage: x = FC.element_class(FC, [1, 2, 1], check=False); x.is_fully_commutative()
159
+ False
160
+ """
161
+ word = list(self)
162
+ from sage.combinat.root_system.braid_orbit import is_fully_commutative as is_fully_comm
163
+
164
+ group = self.parent().coxeter_group()
165
+ braid_rels = group.braid_relations()
166
+ I = group.index_set()
167
+
168
+ from sage.rings.integer_ring import ZZ
169
+ be_careful = any(i not in ZZ for i in I)
170
+
171
+ if be_careful:
172
+ Iinv = {i: j for j, i in enumerate(I)}
173
+ word = [Iinv[i] for i in word]
174
+ braid_rels = [[[Iinv[i] for i in l],
175
+ [Iinv[i] for i in r]] for l, r in braid_rels]
176
+
177
+ return is_fully_comm(word, braid_rels)
178
+
179
+ # Representing FC elements: Heaps
180
+ def heap(self, **kargs):
181
+ r"""
182
+ Create the heap poset of ``self``.
183
+
184
+ The heap of an FC element `w` is a labeled poset that can be defined
185
+ from any reduced word of `w`. Different reduced words yield isomorphic
186
+ labeled posets, so the heap is well defined.
187
+
188
+ Heaps are very useful for visualizing and studying FC elements; see, for
189
+ example, [Ste1996]_ and [GX2020]_.
190
+
191
+ INPUT:
192
+
193
+ - ``self`` -- list; a reduced word `w=s_0... s_{k-1}` of an FC element
194
+
195
+ - ``one_index`` -- boolean (default: ``False``); setting the value to True
196
+ will change the underlying set of the poset to `\{1, 2, \dots, n\}`
197
+
198
+ - ``display_labeling`` -- boolean (default: ``False``); setting the value to
199
+ ``True`` will display the label `s_i` for each element `i` of the poset
200
+
201
+ OUTPUT:
202
+
203
+ A labeled poset where the underlying set is `\{0,1,...,k-1\}`
204
+ and where each element `i` carries `s_i` as its label. The partial order
205
+ `\prec` on the poset is defined by declaring `i\prec j` if `i<j` and
206
+ `m(s_i,s_j)\neq 2`.
207
+
208
+ EXAMPLES::
209
+
210
+ sage: FC = CoxeterGroup(['A', 5]).fully_commutative_elements()
211
+ sage: FC([1, 4, 3, 5, 2, 4]).heap().cover_relations()
212
+ [[1, 2], [1, 3], [2, 5], [2, 4], [3, 5], [0, 4]]
213
+ sage: FC([1, 4, 3, 5, 4, 2]).heap(one_index=True).cover_relations()
214
+ [[2, 3], [2, 4], [3, 6], [3, 5], [4, 6], [1, 5]]
215
+ """
216
+ m = self.parent().coxeter_group().coxeter_matrix()
217
+
218
+ one_index = kargs.get('one_index', False)
219
+ display_labeling = kargs.get('display_labeling', False)
220
+ # elements of the poset:
221
+ elements = list(range(1, len(self) + 1)
222
+ ) if one_index else list(range(len(self)))
223
+
224
+ # get the label of each poset element:
225
+ def letter(index):
226
+ return self[index - 1] if one_index else self[index]
227
+
228
+ # specify the partial order:
229
+ relations = [(i, j) for i in elements for j in elements
230
+ if i < j and m[letter(i), letter(j)] != 2]
231
+ p = Poset((elements, relations))
232
+
233
+ if not display_labeling:
234
+ return p
235
+ else:
236
+ return p.relabel(lambda i: (i, letter(i)))
237
+
238
+ # Hasse diagrams of heaps help visualize FC elements:
239
+ def plot_heap(self):
240
+ r"""
241
+ Display the Hasse diagram of the heap of ``self``.
242
+
243
+ The Hasse diagram is rendered in the lattice `S \times \NN`, with
244
+ every element `i` in the poset drawn as a point labelled by its label
245
+ `s_i`. Every point is placed in the column for its label at a certain
246
+ level. The levels start at 0 and the level k of an element `i` is the
247
+ maximal number `k` such that the heap contains a chain `i_0\prec
248
+ i_1\prec ... \prec i_k` where `i_k=i`. See [Ste1996]_ and [GX2020]_.
249
+
250
+ OUTPUT: GraphicsObject
251
+
252
+ EXAMPLES::
253
+
254
+ sage: FC = CoxeterGroup(['B', 5]).fully_commutative_elements()
255
+ sage: FC([3,2,4,3,1]).plot_heap() # needs sage.plot
256
+ Graphics object consisting of 15 graphics primitives
257
+
258
+ .. PLOT::
259
+ :width: 400 px
260
+
261
+ FC = CoxeterGroup(['B', 5]).fully_commutative_elements()
262
+ g = FC([3,2,4,3,1]).plot_heap()
263
+ sphinx_plot(g)
264
+ """
265
+ import sage.plot.all as plot
266
+
267
+ m = self.parent().coxeter_group().coxeter_matrix()
268
+ letters = self.parent().coxeter_group().index_set()
269
+ graphics = []
270
+
271
+ h = self.heap()
272
+ levels = h.level_sets()
273
+ letters_at_level = [set(self[i] for i in level) for level in levels]
274
+
275
+ for (level_zero_index, members) in enumerate(levels):
276
+ level = level_zero_index + 1
277
+ for i in members:
278
+ x = self[i]
279
+
280
+ # Draw the node
281
+ graphics.append(plot.circle(
282
+ (x, level), 0.1, fill=True, facecolor='white', edgecolor='blue', zorder=1))
283
+ graphics.append(
284
+ plot.text(str(x), (x, level), color='blue', zorder=2))
285
+
286
+ neighbors = {z for z in letters if m[x, z] >= 3}
287
+ for other in neighbors:
288
+ highest_level = max(
289
+ (j + 1 for j in range(level_zero_index) if other in letters_at_level[j]), default=None)
290
+ if highest_level:
291
+ graphics.append(
292
+ plot.line([(other, highest_level), (x, level)], color='black', zorder=0))
293
+
294
+ g = sum(graphics)
295
+ g.axes(False)
296
+ return g
297
+
298
+ # An application of heaps:
299
+ def n_value(self):
300
+ r"""
301
+ Calculate the n-value of ``self``.
302
+
303
+ The *n-value* of a fully commutative element is the *width* (length of
304
+ any longest antichain) of its heap. The n-value is important as it
305
+ coincides with Lusztig's a-value for FC elements in all Weyl and affine
306
+ Weyl groups as well as so-called star-reducible groups; see [GX2020]_.
307
+
308
+ EXAMPLES::
309
+
310
+ sage: FC = CoxeterGroup(['A', 5]).fully_commutative_elements()
311
+ sage: FC([1,3]).n_value()
312
+ 2
313
+ sage: FC([1,2,3]).n_value()
314
+ 1
315
+ sage: FC([1,3,2]).n_value()
316
+ 2
317
+ sage: FC([1,3,2,5]).n_value()
318
+ 3
319
+ """
320
+ return self.heap().width()
321
+
322
+ ###########################################################################
323
+ # Descents and coset decompositions of FC elements #
324
+ ###########################################################################
325
+
326
+ # Descents
327
+
328
+ # The following three functions deal with descents of FC elements.
329
+ # Descents of FC elements are easier to find than those of general
330
+ # elements, but they are also extremely useful: repeated searching of
331
+ # descents is essential to finding Cartier Foata forms and coset
332
+ # decompositions of FC elements; see :func:`cartier_foata_form` and
333
+ # :func:`coset_decomposition`.
334
+
335
+ def find_descent(self, s, side='left'):
336
+ r"""
337
+ Check if ``s`` is a descent of ``self`` and find its position if so.
338
+
339
+ A generator `s` is called a left or right descent of an element `w` if
340
+ `l(sw)` or `l(ws)` is smaller than `l(w)`, respectively. If `w` is FC,
341
+ then `s` is a left descent of `w` if and only if `s` appears to in the
342
+ word and every generator to the left of the leftmost `s` in the word
343
+ commutes with `s`. A similar characterization exists for right descents
344
+ of FC elements.
345
+
346
+ INPUT:
347
+
348
+ - ``s`` -- integer representing a generator of the Coxeter system
349
+
350
+ - ``side`` -- string (default: ``'left'``); if the argument is set to
351
+ 'right', the function checks if ``s`` is a right descent of ``self``
352
+ and finds the index of the rightmost occurrence of ``s`` if so
353
+
354
+ OUTPUT:
355
+
356
+ Determine if the generator ``s`` is a left descent of ``self``; return
357
+ the index of the leftmost occurrence of ``s`` in ``self`` if so and
358
+ return ``None`` if not.
359
+
360
+ EXAMPLES::
361
+
362
+ sage: FC = CoxeterGroup(['B', 5]).fully_commutative_elements()
363
+ sage: w = FC([1, 4, 3, 5, 2, 4, 3])
364
+ sage: w.find_descent(1)
365
+ 0
366
+ sage: w.find_descent(1, side='right')
367
+ <BLANKLINE>
368
+ sage: w.find_descent(4)
369
+ 1
370
+ sage: w.find_descent(4, side='right')
371
+ <BLANKLINE>
372
+ sage: w.find_descent(3)
373
+ <BLANKLINE>
374
+ """
375
+ m = self.parent().coxeter_group().coxeter_matrix()
376
+ view = list(self) if side == 'left' else self[::-1]
377
+ for i, t in enumerate(view):
378
+ if t == s and not any(m[x, t] > 2 for x in view[:i]):
379
+ return i
380
+ return None
381
+
382
+ def has_descent(self, s, side='left') -> bool:
383
+ r"""
384
+ Determine if ``s`` is a descent on the appropriate side of ``self``.
385
+
386
+ INPUT:
387
+
388
+ - ``side`` -- string (default: ``'left'``); if set to 'right', determine
389
+ if ``self`` has ``s`` as a right descent
390
+
391
+ OUTPUT: boolean
392
+
393
+ EXAMPLES::
394
+
395
+ sage: FC = CoxeterGroup(['B', 5]).fully_commutative_elements()
396
+ sage: w = FC([1, 4, 3, 5, 2, 4, 3])
397
+ sage: w.has_descent(1)
398
+ True
399
+ sage: w.has_descent(1, side='right')
400
+ False
401
+ sage: w.has_descent(4)
402
+ True
403
+ sage: w.has_descent(4, side='right')
404
+ False
405
+
406
+ .. SEEALSO:: :func:`find_descent`
407
+ """
408
+ return self.find_descent(s, side=side) is not None
409
+
410
+ def descents(self, side='left'):
411
+ r"""
412
+ Obtain the set of descents on the appropriate side of ``self``.
413
+
414
+ INPUT:
415
+
416
+ - ``side`` -- string (default: ``'left'``); if set to 'right', find the
417
+ right descents
418
+
419
+ A generator `s` is called a left or right descent of an element `w` if
420
+ `l(sw)` or `l(ws)` is smaller than `l(w)`, respectively. If `w` is FC,
421
+ then `s` is a left descent of `w` if and only if `s` appears to in the
422
+ word and every generator to the left of the leftmost `s` in the word
423
+ commutes with `s`. A similar characterization exists for right descents
424
+ of FC elements.
425
+
426
+ EXAMPLES::
427
+
428
+ sage: FC = CoxeterGroup(['B', 5]).fully_commutative_elements()
429
+ sage: w = FC([1, 4, 3, 5, 2, 4, 3])
430
+ sage: sorted(w.descents())
431
+ [1, 4]
432
+ sage: w.descents(side='right')
433
+ {3}
434
+ sage: FC = CoxeterGroup(['A', 5]).fully_commutative_elements()
435
+ sage: sorted(FC([1, 4, 3, 5, 2, 4, 3]).descents())
436
+ [1, 4]
437
+
438
+ .. SEEALSO:: :func:`find_descent`
439
+ """
440
+ view = list(self) if side == 'left' else self[::-1]
441
+ m = self.parent().coxeter_group().coxeter_matrix()
442
+ out = set()
443
+ for (i, t) in enumerate(view):
444
+ if not any(m[x, t] > 2 for x in view[:i]):
445
+ out.add(t)
446
+ return out
447
+
448
+ # Coset decompositions
449
+ def coset_decomposition(self, J, side='left'):
450
+ r"""
451
+ Return the coset decomposition of ``self`` with respect to the parabolic
452
+ subgroup generated by ``J``.
453
+
454
+ INPUT:
455
+
456
+ - ``J`` -- subset of the generating set `S` of the Coxeter system
457
+
458
+ - ``side`` -- string (default: ``'left'``); if the value is set to
459
+ 'right', then the function returns the tuple `(w'^J, w'_J)` from the
460
+ coset decomposition `w = w'^J \cdot w'_J` of `w` with respect to `J`
461
+
462
+ OUTPUT:
463
+
464
+ The tuple of elements `(w_J, w^J)` such that `w=w_J \cdot w^J`, `w_J` is
465
+ generated by the elements in `J`, and `w^J` has no left descent from
466
+ `J`. This tuple is unique and satisfies the equation `\ell(w) =
467
+ \ell(w_J) + \ell(w^J)`, where `\ell` denotes Coxeter length, by general
468
+ theory; see Proposition 2.4.4 of [BB2005]_.
469
+
470
+ EXAMPLES::
471
+
472
+ sage: FC = CoxeterGroup(['B', 6]).fully_commutative_elements()
473
+ sage: w = FC([1, 6, 2, 5, 4, 6, 5])
474
+ sage: w.coset_decomposition({1})
475
+ ([1], [6, 2, 5, 4, 6, 5])
476
+ sage: w.coset_decomposition({1}, side = 'right')
477
+ ([1, 6, 2, 5, 4, 6, 5], [])
478
+ sage: w.coset_decomposition({5, 6})
479
+ ([6, 5, 6], [1, 2, 4, 5])
480
+ sage: w.coset_decomposition({5, 6}, side='right')
481
+ ([1, 6, 2, 5, 4], [6, 5])
482
+
483
+ .. NOTE::
484
+
485
+ The factor `w_J` of the coset decomposition `w = w_J \cdot
486
+ w^J` can be obtained by greedily "pulling left descents of `w` that
487
+ are in `J` to the left"; see the proof of [BB2005]_. This greedy
488
+ algorithm works for all elements in Coxeter group, but it becomes
489
+ especially simple for FC elements because descents are easier to
490
+ find for FC elements.
491
+ """
492
+ string = [] # to record w_J
493
+ remaining = self.clone() # to record w^J
494
+
495
+ if side == 'right':
496
+ remaining._set_list(remaining[::-1])
497
+
498
+ while True:
499
+ x = next((x for x in J if remaining.has_descent(x, side='left')), None)
500
+ if x is not None:
501
+ string.append(x)
502
+ remaining.remove(x)
503
+ else:
504
+ break
505
+
506
+ if side == 'right':
507
+ remaining._set_list(remaining[::-1])
508
+ string = string[::-1]
509
+
510
+ string = self.parent().element_class(self.parent(), string, check=False)
511
+ remaining.set_immutable()
512
+
513
+ return (string, remaining) if side == 'left' else (remaining, string)
514
+
515
+ ###########################################################################
516
+ # Application of coset decompositions, I: New FC elements from old #
517
+ ###########################################################################
518
+
519
+ # The following function uses coset decompositions and will help us
520
+ # generate all FC elements in a Coxeter group by induction on length.
521
+ def _still_reduced_fc_after_prepending(self, s):
522
+ r"""
523
+ Determine if ``self`` prepended with ``s`` is still a reduced word of an
524
+ FC element in the Coxeter system.
525
+
526
+ INPUT:
527
+
528
+ - ``s`` -- integer representing a generator of the Coxeter system
529
+ - ``self`` -- a reduced word of an FC element
530
+
531
+ EXAMPLES:
532
+
533
+ Consider the FC element `w = 12` in the group `B_3`::
534
+
535
+ sage: FCB3 = CoxeterGroup(['B', 3]).fully_commutative_elements()
536
+ sage: w = FCB3([1,2])
537
+
538
+ When `s=1`, `sw` is 112, which is not reduced::
539
+
540
+ sage: w._still_reduced_fc_after_prepending(1)
541
+ False
542
+
543
+
544
+ When `s=2`, `sw` is 212, which is reduced but not FC::
545
+
546
+ sage: w._still_reduced_fc_after_prepending(2)
547
+ False
548
+
549
+ When `s=31, `sw` is 312, which is reduced and FC::
550
+
551
+ sage: w._still_reduced_fc_after_prepending(3)
552
+ True
553
+
554
+ More examples::
555
+
556
+ sage: u = FCB3([3,1,2])
557
+ sage: u._still_reduced_fc_after_prepending(1)
558
+ False
559
+ sage: u._still_reduced_fc_after_prepending(2)
560
+ True
561
+ sage: u._still_reduced_fc_after_prepending(3)
562
+ False
563
+
564
+ sage: FCA5 = CoxeterGroup(['A', 5]).fully_commutative_elements()
565
+ sage: w = FCA5([2,4,1,3,2,5])
566
+ sage: w._still_reduced_fc_after_prepending(5)
567
+ False
568
+
569
+ .. NOTE::
570
+
571
+ If `w` is a reduced word of an element, then the concatenation
572
+ `sw` is still a reduced word if and only if `s` is not a left
573
+ descent of `w` by general Coxeter group theory. So now assume `w`
574
+ is a reduced word of an FC element and `s` is not a left descent
575
+ `w`. In this case, Lemma 4.1 of [Ste1996]_ implies that `sw` is
576
+ not a reduced word of an FC element if and only if some letter in
577
+ `w` does not commute with `s` and the following conditions hold
578
+ simultaneously for the leftmost such letter `t`:
579
+
580
+ (1) `t` is left descent of the word `u_1` obtained by removing
581
+ all letters to the left of the aforementioned `t` from `w`;
582
+ (this condition is automatically true by definition of `u_1`)
583
+
584
+ (2) `s` is left descent of the word `u_2` obtained by
585
+ removing the leftmost `t` from `u_1`;
586
+
587
+ (3) `t` is left descent of the word `u_3` obtained by
588
+ removing the leftmost `s` from `u_2`;
589
+
590
+ ...
591
+
592
+ (m-1) the appropriate element in `\{s, t\}` is a left descent
593
+ of the word `u_{m-1}` obtained by removing the leftmost letter
594
+ required to be a descent in Condition (m-2) from `u_{m-2}`.
595
+
596
+ In the last example above, we have `s=5`, `t=4`, Condition (1)
597
+ holds, but Condition (2) fails, therefore `5w` is still a
598
+ reduced word of an FC element.
599
+
600
+ Note that the conditions (1)--(m-1) are equivalent to the
601
+ condition that the parabolic factor `u_J` from the coset
602
+ decomposition `u_1 = u_J \cdot u^J` of `u_1` with respect to
603
+ `J := \{s, t\}` is the element `tst...` of length `m(s,t)-1`.
604
+
605
+ REFERENCES:
606
+
607
+ See Lemma 4.1 of [Ste1996]_.
608
+ """
609
+ m = self.parent().coxeter_group().coxeter_matrix()
610
+ if self.has_descent(s):
611
+ return False
612
+
613
+ # Find the first letter in that doesn't commute with s.
614
+ try:
615
+ j, t = next((i, x) for i, x in enumerate(self) if m[s, x] >= 3)
616
+ except StopIteration:
617
+ return True
618
+
619
+ u = self.clone()
620
+ u._set_list(self[j:])
621
+ x, _ = u.coset_decomposition({s, t})
622
+ return len(x) != m[s, t] - 1
623
+
624
+ ###########################################################################
625
+ # Application of coset decompositions, II: Star operations #
626
+ ###########################################################################
627
+
628
+ # Generalized star operations
629
+ def star_operation(self, J, direction, side='left'):
630
+ r"""
631
+ Apply a star operation on ``self`` relative to two noncommuting
632
+ generators.
633
+
634
+ Star operations were first defined on elements of Coxeter groups by
635
+ Kazhdan and Lusztig in [KL1979]_ with respect to pair of generators
636
+ `s,t` such that `m(s,t)=3`. Later, Lusztig generalized the definition in
637
+ [Lus1985]_, via coset decompositions, to allow star operations with
638
+ respect to any pair of generators `s,t` such that `m(s,t)\ge 3`. Given
639
+ such a pair, we can potentially perform four types of star operations
640
+ corresponding to all combinations of a 'direction' and a 'side': upper
641
+ left, lower left, upper right and lower right; see [Gre2006]_.
642
+
643
+ Let `w` be an element in `W` and let `J` be any pair `\{s, t\}` of
644
+ noncommuting generators in `S`. Consider the coset decomposition `w =
645
+ w_J \cdot {}^J w` of `w` relative to `J`. Then an upper left star
646
+ operation is defined on `w` if and only if `1 \le l(w_J) \le m(s,t)-2`;
647
+ when this is the case, the operation returns `x\cdot w_J\cdot w^J` where
648
+ `x` is the letter `J` different from the leftmost letter of `w_J`. A
649
+ lower left star operation is defined on `w` if and only if `2 \le l(w_J)
650
+ \le m(s,t)-1`; when this is the case, the operation removes the leftmost
651
+ letter of `w_J` from `w`. Similar facts hold for right star operations.
652
+ See [Gre2006]_.
653
+
654
+ The facts of the previous paragraph hold in general, even if `w` is not
655
+ FC. Note that if `f` is a star operation of any kind, then for every
656
+ element `w \in W`, the elements `w` and `f(w)` are either both FC or
657
+ both not FC.
658
+
659
+ INPUT:
660
+
661
+ - ``J`` -- set of two integers representing two noncommuting
662
+ generators of the Coxeter system
663
+
664
+ - ``direction`` -- string, ``'upper'`` or ``'lower'``; the function
665
+ performs an upper or lower star operation according to ``direction``
666
+
667
+ - ``side`` -- string (default: ``'left'``); if this is set to 'right',
668
+ the function performs a right star operation
669
+
670
+ OUTPUT:
671
+
672
+ The Cartier--Foata form of the result of the star operation if the
673
+ operation is defined on ``self``, ``None`` otherwise.
674
+
675
+ EXAMPLES:
676
+
677
+ We will compute all star operations on the following FC element in type
678
+ `B_6` relative to `J = \{5, 6\}`::
679
+
680
+ sage: FC = CoxeterGroup(['B', 6]).fully_commutative_elements()
681
+ sage: w = FC([1, 6, 2, 5, 4, 6, 5])
682
+
683
+ Whether and how a left star operations can be applied depend on the
684
+ coset decomposition `w = w_J \cdot w^J`::
685
+
686
+ sage: w.coset_decomposition({5, 6})
687
+ ([6, 5, 6], [1, 2, 4, 5])
688
+
689
+ Only the lower star operation is defined on the left on `w`::
690
+
691
+ sage: w.star_operation({5,6}, 'upper')
692
+ <BLANKLINE>
693
+ sage: w.star_operation({5,6}, 'lower')
694
+ [1, 5, 2, 4, 6, 5]
695
+
696
+ Whether and how a right star operations can be applied depend on the
697
+ coset decomposition `w = w^J \cdot w_J`::
698
+
699
+ sage: w.coset_decomposition({5, 6}, side='right')
700
+ ([1, 6, 2, 5, 4], [6, 5])
701
+
702
+ Both types of right star operations on defined for this example::
703
+
704
+ sage: w.star_operation({5, 6}, 'upper', side='right')
705
+ [1, 6, 2, 5, 4, 6, 5, 6]
706
+
707
+ sage: w.star_operation({5, 6}, 'lower', side='right')
708
+ [1, 6, 2, 5, 4, 6]
709
+ """
710
+ assert len(J) == 2, 'J needs to contain a pair of generators.'
711
+ s, t = J
712
+ mst = self.parent().coxeter_group().coxeter_matrix()[s, t]
713
+
714
+ # Perform the coset decomposition on the specified side:
715
+ if side == 'left':
716
+ (string, remaining) = self.coset_decomposition(J, side=side)
717
+ elif side == 'right':
718
+ (remaining, string) = self.coset_decomposition(J, side=side)
719
+
720
+ cur_string = list(string)
721
+
722
+ # From the coset decomposition, perform the upper or lower operation:
723
+ if direction == 'lower' and 2 <= len(string) <= mst - 1:
724
+ # the lower star operation
725
+ new_string = cur_string[1:] if side == 'left' else cur_string[:-1]
726
+ elif direction == 'upper' and 1 <= len(string) <= mst - 2:
727
+ # the upper star operation
728
+ ending_letter = cur_string[0] if side == 'left' else cur_string[-1]
729
+ other = next(x for x in J if x != ending_letter)
730
+ new_string = [other] + cur_string if side == 'left' else cur_string + [other]
731
+ else:
732
+ return None
733
+
734
+ # concatenate w_J and w^J in the appropriate order
735
+ combined_data = new_string + list(remaining) if side == 'left' else list(remaining) + new_string
736
+
737
+ # return the result of the star operation in its canonical form
738
+ return self.parent().element_class(self.parent(), combined_data, check=False)
739
+
740
+
741
+ class FullyCommutativeElements(UniqueRepresentation, Parent):
742
+ r"""
743
+ Class for the set of fully commutative (FC) elements of a Coxeter system.
744
+
745
+ Coxeter systems with finitely many FC elements, or *FC-finite* Coxeter
746
+ systems, are classified by Stembridge in [Ste1996]_. They fall into seven
747
+ families, namely the groups of types `A_n, B_n, D_n, E_n, F_n, H_n` and
748
+ `I_2(m)`.
749
+
750
+ INPUT:
751
+
752
+ - ``data`` -- CoxeterMatrix, CartanType, or the usual datum that can is
753
+ taken in the constructors for these classes (see
754
+ :func:`sage.combinat.root_system.coxeter_group.CoxeterGroup`)
755
+
756
+ OUTPUT:
757
+
758
+ The class of fully commutative elements in the Coxeter group constructed
759
+ from ``data``. This will belong to the category of enumerated sets. If the
760
+ Coxeter data corresponds to a Cartan type, the category is further refined
761
+ to either finite enumerated sets or infinite enumerated sets depending on
762
+ whether the Coxeter group is FC-finite; the refinement is not carried out
763
+ if ``data`` is a Coxeter matrix not corresponding to a Cartan type.
764
+
765
+ .. TODO::
766
+
767
+ It would be ideal to implement the aforementioned refinement to finite
768
+ and infinite enumerated sets for all possible ``data``, regardless of
769
+ whether it corresponds to a Cartan type. Doing so requires determining
770
+ if an arbitrary Coxeter matrix corresponds to a Cartan type. It may be
771
+ best to address this issue in ``sage.combinat.root_system``. On the other
772
+ hand, the refinement in the general case may be unnecessary in light of
773
+ the fact that Stembridge's classification of FC-finite groups contains
774
+ a very small number of easily-recognizable families.
775
+
776
+ EXAMPLES:
777
+
778
+ Create the enumerate set of fully commutative elements in `B_3`::
779
+
780
+ sage: FC = CoxeterGroup(['B', 3]).fully_commutative_elements(); FC
781
+ Fully commutative elements of Finite Coxeter group over Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095? with Coxeter matrix:
782
+ [1 3 2]
783
+ [3 1 4]
784
+ [2 4 1]
785
+
786
+ Construct elements::
787
+
788
+ sage: FC([])
789
+ []
790
+ sage: FC([1,2])
791
+ [1, 2]
792
+ sage: FC([2,3,2])
793
+ [2, 3, 2]
794
+ sage: FC([3,2,3])
795
+ [3, 2, 3]
796
+
797
+ Elements are normalized to Cartier--Foata normal form upon construction::
798
+
799
+ sage: FC([3,1])
800
+ [1, 3]
801
+ sage: FC([2,3,1])
802
+ [2, 1, 3]
803
+ sage: FC([1,3]) == FC([3,1])
804
+ True
805
+
806
+ Attempting to create an element from an input that is not the reduced word
807
+ of a fully commutative element throws a :exc:`ValueError`::
808
+
809
+ sage: FC([1,2,1])
810
+ Traceback (most recent call last):
811
+ ...
812
+ ValueError: the input is not a reduced word of a fully commutative element
813
+ sage: FC([2,3,2,3])
814
+ Traceback (most recent call last):
815
+ ...
816
+ ValueError: the input is not a reduced word of a fully commutative element
817
+
818
+ Enumerate the FC elements in `A_3`::
819
+
820
+ sage: FCA3 = CoxeterGroup(['A', 3]).fully_commutative_elements()
821
+ sage: FCA3.category()
822
+ Category of finite enumerated sets
823
+ sage: FCA3.list()
824
+ [[],
825
+ [1],
826
+ [2],
827
+ [3],
828
+ [2, 1],
829
+ [1, 3],
830
+ [1, 2],
831
+ [3, 2],
832
+ [2, 3],
833
+ [3, 2, 1],
834
+ [2, 1, 3],
835
+ [1, 3, 2],
836
+ [1, 2, 3],
837
+ [2, 1, 3, 2]]
838
+
839
+ Count the FC elements in `B_8`::
840
+
841
+ sage: FCB8 = CoxeterGroup(['B', 8]).fully_commutative_elements()
842
+ sage: len(FCB8) # long time (7 seconds)
843
+ 14299
844
+
845
+ Iterate through the FC elements of length up to 2 in the non-FC-finite group
846
+ affine `A_2`::
847
+
848
+ sage: FCAffineA2 = CoxeterGroup(['A', 2, 1]).fully_commutative_elements()
849
+ sage: FCAffineA2.category()
850
+ Category of infinite enumerated sets
851
+ sage: list(FCAffineA2.iterate_to_length(2))
852
+ [[], [0], [1], [2], [1, 0], [2, 0], [0, 1], [2, 1], [0, 2], [1, 2]]
853
+
854
+ The cardinality of the set is determined from the classification of
855
+ FC-finite Coxeter groups::
856
+
857
+ sage: CoxeterGroup('A2').fully_commutative_elements().category()
858
+ Category of finite enumerated sets
859
+ sage: CoxeterGroup('B7').fully_commutative_elements().category()
860
+ Category of finite enumerated sets
861
+ sage: CoxeterGroup('A3~').fully_commutative_elements().category()
862
+ Category of infinite enumerated sets
863
+ sage: CoxeterGroup('F4~').fully_commutative_elements().category()
864
+ Category of finite enumerated sets
865
+ sage: CoxeterGroup('E8~').fully_commutative_elements().category()
866
+ Category of finite enumerated sets
867
+ sage: CoxeterGroup('F4~xE8~').fully_commutative_elements().category()
868
+ Category of finite enumerated sets
869
+ sage: CoxeterGroup('B4~xE8~').fully_commutative_elements().category()
870
+ Category of infinite enumerated sets
871
+ """
872
+ @staticmethod
873
+ def __classcall_private__(cls, data):
874
+ r"""
875
+ EXAMPLES::
876
+
877
+ sage: from sage.combinat.fully_commutative_elements import FullyCommutativeElements
878
+ sage: x1 = FullyCommutativeElements(CoxeterGroup(['B', 3])); x1
879
+ Fully commutative elements of Finite Coxeter group over Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095? with Coxeter matrix:
880
+ [1 3 2]
881
+ [3 1 4]
882
+ [2 4 1]
883
+ sage: x2 = FullyCommutativeElements(['B', 3]); x2
884
+ Fully commutative elements of Finite Coxeter group over Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095? with Coxeter matrix:
885
+ [1 3 2]
886
+ [3 1 4]
887
+ [2 4 1]
888
+ sage: x3 = FullyCommutativeElements(CoxeterMatrix([[1, 3, 2], [3, 1, 4], [2, 4, 1]])); x3
889
+ Fully commutative elements of Finite Coxeter group over Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095? with Coxeter matrix:
890
+ [1 3 2]
891
+ [3 1 4]
892
+ [2 4 1]
893
+ sage: x1 is x2 is x3
894
+ True
895
+ sage: FullyCommutativeElements(CartanType(['B', 3]).relabel({1: 3, 2: 2, 3: 1}))
896
+ Fully commutative elements of Finite Coxeter group over Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095? with Coxeter matrix:
897
+ [1 4 2]
898
+ [4 1 3]
899
+ [2 3 1]
900
+ sage: m = CoxeterMatrix([(1, 5, 2, 2, 2), (5, 1, 3, 2, 2), (2, 3, 1, 3, 2), (2, 2, 3, 1, 3), (2, 2, 2, 3, 1)]); FullyCommutativeElements(m)
901
+ Fully commutative elements of Coxeter group over Universal Cyclotomic Field with Coxeter matrix:
902
+ [1 5 2 2 2]
903
+ [5 1 3 2 2]
904
+ [2 3 1 3 2]
905
+ [2 2 3 1 3]
906
+ [2 2 2 3 1]
907
+ """
908
+ if data in CoxeterGroups():
909
+ group = data
910
+ else:
911
+ group = CoxeterGroup(data)
912
+ return super().__classcall__(cls, group)
913
+
914
+ def __init__(self, coxeter_group):
915
+ r"""
916
+ EXAMPLES::
917
+
918
+ sage: from sage.combinat.fully_commutative_elements import FullyCommutativeElements
919
+ sage: FC = FullyCommutativeElements(CoxeterGroup(['H', 4]))
920
+ sage: TestSuite(FC).run()
921
+ """
922
+ self._coxeter_group = coxeter_group
923
+
924
+ # Start with the category of enumerated sets and refine it to finite or
925
+ # infinite enumerated sets for Coxeter groups of Cartan types.
926
+ category = EnumeratedSets()
927
+
928
+ coxeter_type = self._coxeter_group.coxeter_type()
929
+
930
+ if not isinstance(coxeter_type, CoxeterMatrix):
931
+ # This case handles all finite or affine Coxeter types (or products thereof)
932
+ ctypes = [coxeter_type] if coxeter_type.is_irreducible() else coxeter_type.component_types()
933
+
934
+ is_finite = True
935
+ # this type will be FC-finite if and only if each component type is:
936
+ for ctype in ctypes:
937
+ family, rank = ctype.type(), ctype.rank()
938
+ # Finite Coxeter groups are certainly FC-finite.
939
+ # Of the affine Coxeter groups only the groups affine `F_4` and
940
+ # affine `E_8` are FC-finite; they have rank 5 and rank 9 and
941
+ # correspond to the groups `F_5` and `E_9` in [Ste1996]_.
942
+ if not (ctype.is_finite() or (family == 'F' and rank == 5) or (family == 'E' and rank == 9)):
943
+ is_finite = False
944
+ break
945
+
946
+ if is_finite:
947
+ category = category.Finite()
948
+ else:
949
+ category = category.Infinite()
950
+ else:
951
+ # coxeter_type is a plain CoxeterMatrix, i.e. it is an indefinite
952
+ # type, and we do not specify any refinement. (Note that this
953
+ # includes groups of the form E_n (n>9), F_n (n>5) and H_n (n>4)
954
+ # from [Ste1996]_ which are known to be FC-finite).
955
+ pass
956
+
957
+ Parent.__init__(self, category=category)
958
+
959
+ def _repr_(self):
960
+ r"""
961
+ EXAMPLES::
962
+
963
+ sage: CoxeterGroup(['H', 4]).fully_commutative_elements()
964
+ Fully commutative elements of Finite Coxeter group over Number Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790? with Coxeter matrix:
965
+ [1 3 2 2]
966
+ [3 1 3 2]
967
+ [2 3 1 5]
968
+ [2 2 5 1]
969
+ """
970
+ return 'Fully commutative elements of {}'.format(str(self.coxeter_group()))
971
+
972
+ def _element_constructor_(self, lst):
973
+ r"""
974
+ TESTS::
975
+
976
+ sage: FC = CoxeterGroup(['A', 3]).fully_commutative_elements()
977
+ sage: FC([1, 2]) # indirect doctest
978
+ [1, 2]
979
+ """
980
+ return self.element_class(self, lst)
981
+
982
+ Element = FullyCommutativeElement
983
+
984
+ def coxeter_group(self):
985
+ r"""
986
+ Obtain the Coxeter group associated with ``self``.
987
+
988
+ EXAMPLES::
989
+
990
+ sage: FCA3 = CoxeterGroup(['A', 3]).fully_commutative_elements()
991
+ sage: FCA3.coxeter_group()
992
+ Finite Coxeter group over Integer Ring with Coxeter matrix:
993
+ [1 3 2]
994
+ [3 1 3]
995
+ [2 3 1]
996
+ """
997
+ return self._coxeter_group
998
+
999
+ def __iter__(self):
1000
+ r"""
1001
+ Enumerate the elements of this set by length, starting with the empty
1002
+ word and, if the group is FC-finite, ending with the longest fully
1003
+ commutative element.
1004
+
1005
+ TESTS::
1006
+
1007
+ sage: FC = CoxeterGroup(['A', 10]).fully_commutative_elements()
1008
+ sage: next(iter(FC)) # indirect doctest
1009
+ []
1010
+ """
1011
+ empty_word = self.element_class(self, [], check=False)
1012
+ letters = self.coxeter_group().index_set()
1013
+
1014
+ # To make the iterator deterministic, use a dictionary rather than a
1015
+ # set, for the keys are then ordered by default by Python 3.7+:
1016
+ recent_words = {empty_word: True}
1017
+ yield empty_word
1018
+ while recent_words:
1019
+ new_words = {}
1020
+ for w in recent_words:
1021
+ for s in letters:
1022
+ if w._still_reduced_fc_after_prepending(s):
1023
+ sw = self.element_class(
1024
+ self, [s] + list(w), check=False)
1025
+ # "Add" sw to the "set"
1026
+ new_words[sw] = True
1027
+ for w in new_words:
1028
+ yield w
1029
+ recent_words = new_words
1030
+
1031
+ def iterate_to_length(self, length):
1032
+ r"""
1033
+ Iterate through the elements of this class up to a maximum length.
1034
+
1035
+ INPUT:
1036
+
1037
+ - ``length`` -- integer; maximum length of element to generate
1038
+
1039
+ OUTPUT: generator for elements of ``self`` of length up to ``length``
1040
+
1041
+ EXAMPLES:
1042
+
1043
+ The following example produces all FC elements of length up to 2 in the
1044
+ group `A_3`::
1045
+
1046
+ sage: FCA3 = CoxeterGroup(['A', 3]).fully_commutative_elements()
1047
+ sage: list(FCA3.iterate_to_length(2))
1048
+ [[], [1], [2], [3], [2, 1], [1, 3], [1, 2], [3, 2], [2, 3]]
1049
+
1050
+ The lists for length 4 and 5 are the same since 4 is the maximum length
1051
+ of an FC element in `A_3`::
1052
+
1053
+ sage: list(FCA3.iterate_to_length(4))
1054
+ [[], [1], [2], [3], [2, 1], [1, 3], [1, 2], [3, 2], [2, 3],
1055
+ [3, 2, 1], [2, 1, 3], [1, 3, 2], [1, 2, 3], [2, 1, 3, 2]]
1056
+ sage: list(FCA3.iterate_to_length(5))
1057
+ [[], [1], [2], [3], [2, 1], [1, 3], [1, 2], [3, 2], [2, 3],
1058
+ [3, 2, 1], [2, 1, 3], [1, 3, 2], [1, 2, 3], [2, 1, 3, 2]]
1059
+ sage: list(FCA3.iterate_to_length(4)) == list(FCA3)
1060
+ True
1061
+
1062
+ The following example produces all FC elements of length up to 4 in the
1063
+ affine Weyl group `\tilde A_2`::
1064
+
1065
+ sage: FCAffineA2 = CoxeterGroup(['A', 2, 1]).fully_commutative_elements()
1066
+ sage: FCAffineA2.category()
1067
+ Category of infinite enumerated sets
1068
+ sage: list(FCAffineA2.iterate_to_length(4))
1069
+ [[], [0], [1], [2], [1, 0], [2, 0], [0, 1], [2, 1], [0, 2],
1070
+ [1, 2], [2, 1, 0], [1, 2, 0], [2, 0, 1], [0, 2, 1], [1, 0, 2],
1071
+ [0, 1, 2], [0, 2, 1, 0], [0, 1, 2, 0], [1, 2, 0, 1],
1072
+ [1, 0, 2, 1], [2, 1, 0, 2], [2, 0, 1, 2]]
1073
+ """
1074
+ for w in self:
1075
+ if len(w) > length:
1076
+ break
1077
+ yield w