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,2405 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ # sage.doctest: needs sage.combinat sage.groups
3
+ r"""
4
+ Affine permutations
5
+ """
6
+ # ****************************************************************************
7
+ # Copyright (C) 2013 Tom Denton <sdenton4@gmail.com>
8
+ #
9
+ # Distributed under the terms of the GNU General Public License (GPL)
10
+ # as published by the Free Software Foundation; either version 2 of
11
+ # the License, or (at your option) any later version.
12
+ # https://www.gnu.org/licenses/
13
+ # ****************************************************************************
14
+ from __future__ import annotations
15
+ from itertools import repeat
16
+
17
+ from sage.categories.affine_weyl_groups import AffineWeylGroups
18
+ from sage.combinat.composition import Composition
19
+ from sage.combinat.partition import Partition
20
+ from sage.combinat.root_system.cartan_type import CartanType
21
+ from sage.misc.cachefunc import cached_method
22
+ from sage.misc.constant_function import ConstantFunction
23
+ from sage.misc.lazy_import import lazy_import
24
+ from sage.misc.misc_c import prod
25
+ from sage.misc.prandom import randint
26
+ from sage.rings.integer import Integer
27
+ from sage.structure.list_clone import ClonableArray
28
+ from sage.structure.parent import Parent
29
+ from sage.structure.unique_representation import UniqueRepresentation
30
+
31
+ lazy_import('sage.combinat.root_system.weyl_group', 'WeylGroup')
32
+ lazy_import('sage.groups.perm_gps.permgroup_named', 'SymmetricGroup')
33
+
34
+
35
+ class AffinePermutation(ClonableArray):
36
+ r"""
37
+ An affine permutation, represented in the window notation, and
38
+ considered as a bijection from `\ZZ` to `\ZZ`.
39
+
40
+ EXAMPLES::
41
+
42
+ sage: A = AffinePermutationGroup(['A',7,1])
43
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
44
+ sage: p
45
+ Type A affine permutation with window [3, -1, 0, 6, 5, 4, 10, 9]
46
+ """
47
+
48
+ def __init__(self, parent, lst, check=True) -> None:
49
+ r"""
50
+ Initialize ``self``.
51
+
52
+ INPUT:
53
+
54
+ - ``parent`` -- the parent affine permutation group
55
+
56
+ - ``lst`` -- list giving the base window of the affine permutation
57
+
58
+ - ``check`` -- whether to test if the affine permutation is valid
59
+
60
+ EXAMPLES::
61
+
62
+ sage: A = AffinePermutationGroup(['A',7,1])
63
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
64
+ sage: p
65
+ Type A affine permutation with window [3, -1, 0, 6, 5, 4, 10, 9]
66
+ sage: TestSuite(p).run()
67
+
68
+ TESTS:
69
+
70
+ Check that :issue:`26436` is fixed::
71
+
72
+ sage: A = AffinePermutationGroup(['A',3,1])
73
+ sage: p = A([-3/1,2/1,3/1,8/1])
74
+ sage: q = ~p
75
+ sage: q * p
76
+ Type A affine permutation with window [1, 2, 3, 4]
77
+ """
78
+ if check:
79
+ lst = [Integer(val) for val in lst]
80
+ self.k = parent.k
81
+ self.n = self.k + 1
82
+ # This N doesn't matter for type A, but comes up in all other types.
83
+ if parent.cartan_type()[0] == 'A':
84
+ self.N = self.n
85
+ elif parent.cartan_type()[0] in ['B', 'C', 'D']:
86
+ self.N = 2 * self.k + 1
87
+ elif parent.cartan_type()[0] == 'G':
88
+ self.N = 6
89
+ else:
90
+ raise NotImplementedError('unsupported Cartan type')
91
+ ClonableArray.__init__(self, parent, lst, check)
92
+
93
+ def _repr_(self) -> str:
94
+ r"""
95
+ EXAMPLES::
96
+
97
+ sage: A = AffinePermutationGroup(['A',7,1])
98
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
99
+ sage: p
100
+ Type A affine permutation with window [3, -1, 0, 6, 5, 4, 10, 9]
101
+ """
102
+ return ("Type " + self.parent().cartan_type().letter
103
+ + " affine permutation with window " + str(list(self)))
104
+
105
+ def __rmul__(self, q) -> AffinePermutation:
106
+ r"""
107
+ Given ``self`` and `q`, returns ``self*q``.
108
+
109
+ INPUT:
110
+
111
+ - ``q`` -- an element of ``self.parent()``
112
+
113
+ EXAMPLES::
114
+
115
+ sage: A = AffinePermutationGroup(['A',7,1])
116
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
117
+ sage: q = A([0, 2, 3, 4, 5, 6, 7, 9])
118
+ sage: p.__rmul__(q)
119
+ Type A affine permutation with window [1, -1, 0, 6, 5, 4, 10, 11]
120
+ """
121
+ l = [self.value(q.value(i)) for i in range(1, len(self) + 1)]
122
+ return type(self)(self.parent(), l, check=False)
123
+
124
+ def __lmul__(self, q) -> AffinePermutation:
125
+ r"""
126
+ Given ``self`` and `q`, returns ``q*self``.
127
+
128
+ INPUT:
129
+
130
+ - ``q`` -- an element of ``self.parent()``
131
+
132
+ EXAMPLES::
133
+
134
+ sage: A = AffinePermutationGroup(['A',7,1])
135
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
136
+ sage: q = A([0,2,3,4,5,6,7,9])
137
+ sage: p.__lmul__(q)
138
+ Type A affine permutation with window [3, -1, 1, 6, 5, 4, 10, 8]
139
+ """
140
+ # if self.parent().right_to_left:
141
+ # self,q=q,self
142
+ # ... product rule
143
+ l = [q.value(self.value(i)) for i in range(1, len(self) + 1)]
144
+ return type(self)(self.parent(), l, check=False)
145
+
146
+ def __mul__(self, q) -> AffinePermutation:
147
+ r"""
148
+ Given ``self`` and `q`, returns ``self*q``.
149
+
150
+ INPUT:
151
+
152
+ - ``q`` -- an element of ``self.parent()``
153
+
154
+ EXAMPLES::
155
+
156
+ sage: p = AffinePermutationGroup(['A',7,1])([3, -1, 0, 6, 5, 4, 10, 9])
157
+ sage: s1 = AffinePermutationGroup(['A',7,1]).one().apply_simple_reflection(1)
158
+ sage: p * s1
159
+ Type A affine permutation with window [-1, 3, 0, 6, 5, 4, 10, 9]
160
+ sage: p.apply_simple_reflection(1, 'right')
161
+ Type A affine permutation with window [-1, 3, 0, 6, 5, 4, 10, 9]
162
+ """
163
+ return self.__rmul__(q)
164
+
165
+ @cached_method
166
+ def __invert__(self) -> AffinePermutation:
167
+ r"""
168
+ Return the inverse affine permutation.
169
+
170
+ EXAMPLES::
171
+
172
+ sage: p = AffinePermutationGroup(['A',7,1])([3, -1, 0, 6, 5, 4, 10, 9])
173
+ sage: p.inverse() # indirect doctest
174
+ Type A affine permutation with window [0, -1, 1, 6, 5, 4, 10, 11]
175
+ """
176
+ inv = [self.position(i) for i in range(1, len(self) + 1)]
177
+ return type(self)(self.parent(), inv, check=False)
178
+
179
+ def apply_simple_reflection(self, i, side='right') -> AffinePermutation:
180
+ r"""
181
+ Apply a simple reflection.
182
+
183
+ INPUT:
184
+
185
+ - ``i`` -- integer
186
+ - ``side`` -- (default: ``'right'``) determines whether to apply the
187
+ reflection on the ``'right'`` or ``'left'``
188
+
189
+ EXAMPLES::
190
+
191
+ sage: p = AffinePermutationGroup(['A',7,1])([3, -1, 0, 6, 5, 4, 10, 9])
192
+ sage: p.apply_simple_reflection(3)
193
+ Type A affine permutation with window [3, -1, 6, 0, 5, 4, 10, 9]
194
+ sage: p.apply_simple_reflection(11)
195
+ Type A affine permutation with window [3, -1, 6, 0, 5, 4, 10, 9]
196
+ sage: p.apply_simple_reflection(3, 'left')
197
+ Type A affine permutation with window [4, -1, 0, 6, 5, 3, 10, 9]
198
+ sage: p.apply_simple_reflection(11, 'left')
199
+ Type A affine permutation with window [4, -1, 0, 6, 5, 3, 10, 9]
200
+ """
201
+ if side == 'right':
202
+ return self.apply_simple_reflection_right(i)
203
+ return self.apply_simple_reflection_left(i)
204
+
205
+ def __call__(self, i):
206
+ r"""
207
+ Return the image of the integer ``i`` under this permutation.
208
+
209
+ EXAMPLES::
210
+
211
+ sage: A = AffinePermutationGroup(['A',7,1])
212
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
213
+ sage: p.value(1) #indirect doctest
214
+ 3
215
+ sage: p.value(9)
216
+ 11
217
+ """
218
+ return self.value(i)
219
+
220
+ def is_i_grassmannian(self, i=0, side='right') -> bool:
221
+ r"""
222
+ Test whether ``self`` is `i`-grassmannian, i.e., either is the
223
+ identity or has ``i`` as the sole descent.
224
+
225
+ INPUT:
226
+
227
+ - ``i`` -- an element of the index set
228
+ - ``side`` -- determines the side on which to check the descents
229
+
230
+ EXAMPLES::
231
+
232
+ sage: A = AffinePermutationGroup(['A',7,1])
233
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
234
+ sage: p.is_i_grassmannian()
235
+ False
236
+ sage: q = A.from_word([3,2,1,0])
237
+ sage: q.is_i_grassmannian()
238
+ True
239
+ sage: q = A.from_word([2,3,4,5])
240
+ sage: q.is_i_grassmannian(5)
241
+ True
242
+ sage: q.is_i_grassmannian(2, side='left')
243
+ True
244
+ """
245
+ return self == self.parent().one() or self.descents(side) == [i]
246
+
247
+ def index_set(self) -> tuple[int, ...]:
248
+ r"""
249
+ Index set of the affine permutation group.
250
+
251
+ EXAMPLES::
252
+
253
+ sage: A = AffinePermutationGroup(['A',7,1])
254
+ sage: A.index_set()
255
+ (0, 1, 2, 3, 4, 5, 6, 7)
256
+ """
257
+ return tuple(range(self.k + 1))
258
+
259
+ def lower_covers(self, side='right') -> list[AffinePermutation]:
260
+ r"""
261
+ Return lower covers of ``self``.
262
+
263
+ The set of affine permutations of one less length related by
264
+ multiplication by a simple transposition on the indicated side.
265
+ These are the elements that ``self`` covers in weak order.
266
+
267
+ EXAMPLES::
268
+
269
+ sage: A = AffinePermutationGroup(['A',7,1])
270
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
271
+ sage: p.lower_covers()
272
+ [Type A affine permutation with window [-1, 3, 0, 6, 5, 4, 10, 9],
273
+ Type A affine permutation with window [3, -1, 0, 5, 6, 4, 10, 9],
274
+ Type A affine permutation with window [3, -1, 0, 6, 4, 5, 10, 9],
275
+ Type A affine permutation with window [3, -1, 0, 6, 5, 4, 9, 10]]
276
+ """
277
+ S = self.descents(side)
278
+ return [self.apply_simple_reflection(i, side) for i in S]
279
+
280
+ def is_one(self) -> bool:
281
+ r"""
282
+ Test whether the affine permutation is the identity.
283
+
284
+ EXAMPLES::
285
+
286
+ sage: A = AffinePermutationGroup(['A',7,1])
287
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
288
+ sage: p.is_one()
289
+ False
290
+ sage: q = A.one()
291
+ sage: q.is_one()
292
+ True
293
+ """
294
+ return self == self.parent().one()
295
+
296
+ def reduced_word(self) -> list[int]:
297
+ r"""
298
+ Return a reduced word for the affine permutation.
299
+
300
+ EXAMPLES::
301
+
302
+ sage: A = AffinePermutationGroup(['A',7,1])
303
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
304
+ sage: p.reduced_word()
305
+ [0, 7, 4, 1, 0, 7, 5, 4, 2, 1]
306
+ """
307
+ # This is about 25% faster than the default algorithm.
308
+ x = self
309
+ i = 0
310
+ word = []
311
+ while not x.is_one():
312
+ if x.has_descent(i):
313
+ x = x.apply_simple_reflection_right(i)
314
+ word.append(i)
315
+ i = (i+1) % (self.k+1)
316
+ word.reverse()
317
+ return word
318
+
319
+ def signature(self) -> int:
320
+ r"""
321
+ Signature of the affine permutation, `(-1)^l`, where `l` is the
322
+ length of the permutation.
323
+
324
+ EXAMPLES::
325
+
326
+ sage: A = AffinePermutationGroup(['A',7,1])
327
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
328
+ sage: p.signature()
329
+ 1
330
+ """
331
+ return (-1)**self.length()
332
+
333
+ @cached_method
334
+ def to_weyl_group_element(self):
335
+ r"""
336
+ The affine Weyl group element corresponding to the affine permutation.
337
+
338
+ EXAMPLES::
339
+
340
+ sage: A = AffinePermutationGroup(['A',7,1])
341
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
342
+ sage: p.to_weyl_group_element()
343
+ [ 0 -1 0 1 0 0 1 0]
344
+ [ 1 -1 0 1 0 0 1 -1]
345
+ [ 1 -1 0 1 0 0 0 0]
346
+ [ 0 0 0 1 0 0 0 0]
347
+ [ 0 0 0 1 0 -1 1 0]
348
+ [ 0 0 0 1 -1 0 1 0]
349
+ [ 0 0 0 0 0 0 1 0]
350
+ [ 0 -1 1 0 0 0 1 0]
351
+ """
352
+ W = self.parent().weyl_group()
353
+ return W.from_reduced_word(self.reduced_word())
354
+
355
+ def grassmannian_quotient(self, i=0, side='right') -> tuple:
356
+ r"""
357
+ Return the Grassmannian quotient.
358
+
359
+ Factors ``self`` into a unique product of a Grassmannian and a
360
+ finite-type element. Returns a tuple containing the Grassmannian
361
+ and finite elements, in order according to ``side``.
362
+
363
+ INPUT:
364
+
365
+ - ``i`` -- (default: 0) an element of the index set; the descent
366
+ checked for
367
+
368
+ EXAMPLES::
369
+
370
+ sage: A = AffinePermutationGroup(['A',7,1])
371
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
372
+ sage: gq=p.grassmannian_quotient()
373
+ sage: gq
374
+ (Type A affine permutation with window [-1, 0, 3, 4, 5, 6, 9, 10],
375
+ Type A affine permutation with window [3, 1, 2, 6, 5, 4, 8, 7])
376
+ sage: gq[0].is_i_grassmannian()
377
+ True
378
+ sage: 0 not in gq[1].reduced_word()
379
+ True
380
+ sage: prod(gq)==p
381
+ True
382
+
383
+ sage: gqLeft=p.grassmannian_quotient(side='left')
384
+ sage: 0 not in gqLeft[0].reduced_word()
385
+ True
386
+ sage: gqLeft[1].is_i_grassmannian(side='left')
387
+ True
388
+ sage: prod(gqLeft)==p
389
+ True
390
+ """
391
+ fin = self.parent().one()
392
+ gr = self
393
+ D = gr.descents(side=side)
394
+ while not (D == [i] or D == []):
395
+ m = D[0]
396
+ if m == i:
397
+ m = D[1]
398
+ if side == 'right':
399
+ fin = fin.apply_simple_reflection(m, side='left')
400
+ gr = gr.apply_simple_reflection(m, side='right')
401
+ else:
402
+ fin = fin.apply_simple_reflection(m, side='right')
403
+ gr = gr.apply_simple_reflection(m, side='left')
404
+ D = gr.descents(side=side)
405
+ if side == 'right':
406
+ return (gr, fin)
407
+ else:
408
+ return (fin, gr)
409
+
410
+
411
+ class AffinePermutationTypeA(AffinePermutation):
412
+ # ----------------------
413
+ # Type-specific methods.
414
+ # (Methods existing in all types, but with type-specific definition.)
415
+ # ----------------------
416
+ def check(self) -> None:
417
+ r"""
418
+ Check that ``self`` is an affine permutation.
419
+
420
+ EXAMPLES::
421
+
422
+ sage: A = AffinePermutationGroup(['A',7,1])
423
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
424
+ sage: p
425
+ Type A affine permutation with window [3, -1, 0, 6, 5, 4, 10, 9]
426
+ sage: q = A([1,2,3]) # indirect doctest
427
+ Traceback (most recent call last):
428
+ ...
429
+ ValueError: length of list must be k+1=8
430
+ sage: q = A([1,2,3,4,5,6,7,0]) # indirect doctest
431
+ Traceback (most recent call last):
432
+ ...
433
+ ValueError: window does not sum to 36
434
+ sage: q = A([1,1,3,4,5,6,7,9]) # indirect doctest
435
+ Traceback (most recent call last):
436
+ ...
437
+ ValueError: entries must have distinct residues
438
+ """
439
+ if not self:
440
+ return
441
+ k = self.parent().k
442
+ # Type A
443
+ if len(self) != k + 1:
444
+ raise ValueError(f"length of list must be k+1={k + 1}")
445
+ sigma = (k + 2).binomial(2)
446
+ if sigma != sum(self):
447
+ raise ValueError(f"window does not sum to {sigma}")
448
+ l = sorted(i % (k + 1) for i in self)
449
+ if any(i != j for i, j in enumerate(l)):
450
+ raise ValueError("entries must have distinct residues")
451
+
452
+ def value(self, i, base_window=False):
453
+ r"""
454
+ Return the image of the integer ``i`` under this permutation.
455
+
456
+ INPUT:
457
+
458
+ - ``base_window`` -- boolean; indicating whether ``i`` is in the
459
+ base window; if ``True``, will run a bit faster, but the method
460
+ will screw up if ``i`` is not actually in the index set
461
+
462
+ EXAMPLES::
463
+
464
+ sage: A = AffinePermutationGroup(['A',7,1])
465
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
466
+ sage: p.value(1)
467
+ 3
468
+ sage: p.value(9)
469
+ 11
470
+ """
471
+ if base_window:
472
+ self[i-1]
473
+ window = (i-1) // (self.k+1)
474
+ return self[(i-1) % (self.k+1)] + window*(self.k+1)
475
+
476
+ def position(self, i):
477
+ r"""
478
+ Find the position ``j`` such the ``self.value(j) == i``.
479
+
480
+ EXAMPLES::
481
+
482
+ sage: A = AffinePermutationGroup(['A',7,1])
483
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
484
+ sage: p.position(3)
485
+ 1
486
+ sage: p.position(11)
487
+ 9
488
+ """
489
+ for r in range(self.k+1):
490
+ if self[r] % (self.k+1) == i % (self.k+1):
491
+ # i sits in position i, but some number of windows away.
492
+ diff = (i-self[r]) // (self.k+1)
493
+ return r + diff*(self.k+1) + 1
494
+ return False
495
+
496
+ def apply_simple_reflection_right(self, i) -> AffinePermutationTypeA:
497
+ r"""
498
+ Apply the simple reflection to positions `i`, `i+1`.
499
+
500
+ INPUT:
501
+
502
+ - ``i`` -- integer
503
+
504
+ EXAMPLES::
505
+
506
+ sage: p = AffinePermutationGroup(['A',7,1])([3, -1, 0, 6, 5, 4, 10, 9])
507
+ sage: p.apply_simple_reflection_right(3)
508
+ Type A affine permutation with window [3, -1, 6, 0, 5, 4, 10, 9]
509
+ sage: p.apply_simple_reflection_right(11)
510
+ Type A affine permutation with window [3, -1, 6, 0, 5, 4, 10, 9]
511
+ """
512
+ j = i % (self.k+1)
513
+ # Cloning is currently kinda broken, in that caches don't clear which
514
+ # leads to strangeness with the cloned object.
515
+ # The clone approach is quite a bit (2x) faster, though, so this should
516
+ # switch once the caching situation is fixed.
517
+ # with self.clone(check=False) as l:
518
+ l = self[:]
519
+ if j == 0:
520
+ a = l[0]
521
+ l[0] = l[-1] - (self.k+1)
522
+ l[-1] = a + (self.k+1)
523
+ else:
524
+ a = l[j-1]
525
+ l[j-1] = l[j]
526
+ l[j] = a
527
+ return type(self)(self.parent(), l, check=False)
528
+
529
+ def apply_simple_reflection_left(self, i) -> AffinePermutationTypeA:
530
+ r"""
531
+ Apply the simple reflection to the values `i`, `i+1`.
532
+
533
+ EXAMPLES::
534
+
535
+ sage: p = AffinePermutationGroup(['A',7,1])([3, -1, 0, 6, 5, 4, 10, 9])
536
+ sage: p.apply_simple_reflection_left(3)
537
+ Type A affine permutation with window [4, -1, 0, 6, 5, 3, 10, 9]
538
+ sage: p.apply_simple_reflection_left(11)
539
+ Type A affine permutation with window [4, -1, 0, 6, 5, 3, 10, 9]
540
+ """
541
+ # Here are a couple other methods we tried out, but turned out
542
+ # to be slower than the current implementation.
543
+ # 1) This one was very bad:
544
+ # return self.inverse().apply_simple_reflection_right(i).inverse()
545
+ # 2) Also bad, though not quite so bad:
546
+ # return (self.parent().simple_reflection(i))*self
547
+ i = i % (self.k + 1)
548
+ # Cloning is currently kinda broken, in that caches don't clear which
549
+ # leads to strangeness with the cloned object.
550
+ # The clone approach is quite a bit faster, though,
551
+ # so this should switch once the caching situation is fixed.
552
+ # with self.clone(check=False) as l:
553
+ l = []
554
+ if i != self.k:
555
+ for m in range(self.k + 1):
556
+ res = self[m] % (self.k + 1)
557
+ if res == i:
558
+ l.append(self[m] + 1)
559
+ elif res == i + 1:
560
+ l.append(self[m] - 1)
561
+ else:
562
+ l.append(self[m])
563
+ if i == self.k:
564
+ for m in range(self.k + 1):
565
+ res = self[m] % (self.k + 1)
566
+ if res == i:
567
+ l.append(self[m] + 1)
568
+ elif res == 0:
569
+ l.append(self[m] - 1)
570
+ else:
571
+ l.append(self[m])
572
+ return type(self)(self.parent(), l, check=False)
573
+
574
+ def has_right_descent(self, i) -> bool:
575
+ r"""
576
+ Determine whether there is a descent at ``i``.
577
+
578
+ INPUT:
579
+
580
+ - ``i`` -- integer
581
+
582
+ EXAMPLES::
583
+
584
+ sage: p = AffinePermutationGroup(['A',7,1])([3, -1, 0, 6, 5, 4, 10, 9])
585
+ sage: p.has_right_descent(1)
586
+ True
587
+ sage: p.has_right_descent(9)
588
+ True
589
+ sage: p.has_right_descent(0)
590
+ False
591
+ """
592
+ return self.value(i) > self.value(i + 1)
593
+
594
+ def has_left_descent(self, i) -> bool:
595
+ r"""
596
+ Determine whether there is a descent at ``i``.
597
+
598
+ INPUT:
599
+
600
+ - ``i`` -- integer
601
+
602
+ EXAMPLES::
603
+
604
+ sage: p = AffinePermutationGroup(['A',7,1])([3, -1, 0, 6, 5, 4, 10, 9])
605
+ sage: p.has_left_descent(1)
606
+ True
607
+ sage: p.has_left_descent(9)
608
+ True
609
+ sage: p.has_left_descent(0)
610
+ True
611
+ """
612
+ # This is much faster than the default method of taking the inverse and
613
+ # then finding right descents...
614
+ return self.position(i) > self.position(i + 1)
615
+
616
+ def to_type_a(self) -> AffinePermutationTypeA:
617
+ r"""
618
+ Return an embedding of ``self`` into the affine permutation group of
619
+ type `A`. (For type `A`, just returns ``self``.)
620
+
621
+ EXAMPLES::
622
+
623
+ sage: p = AffinePermutationGroup(['A',7,1])([3, -1, 0, 6, 5, 4, 10, 9])
624
+ sage: p.to_type_a() is p
625
+ True
626
+ """
627
+ return self
628
+
629
+ # ----------------------
630
+ # Type-A-specific methods.
631
+ # Only available in Type A.
632
+ # ----------------------
633
+
634
+ def flip_automorphism(self) -> AffinePermutationTypeA:
635
+ r"""
636
+ The Dynkin diagram automorphism which fixes `s_0` and reverses all
637
+ other indices.
638
+
639
+ EXAMPLES::
640
+
641
+ sage: A = AffinePermutationGroup(['A',7,1])
642
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
643
+ sage: p.flip_automorphism()
644
+ Type A affine permutation with window [0, -1, 5, 4, 3, 9, 10, 6]
645
+ """
646
+ # Note: There should be a more combinatorial (ie, faster) way to do this.
647
+ w = [(self.k+1-i) % (self.k+1) for i in self.reduced_word()]
648
+ return self.parent().from_word(w)
649
+
650
+ def promotion(self) -> AffinePermutationTypeA:
651
+ r"""
652
+ The Dynkin diagram automorphism which sends `s_i` to `s_{i+1}`.
653
+
654
+ EXAMPLES::
655
+
656
+ sage: A = AffinePermutationGroup(['A',7,1])
657
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
658
+ sage: p.promotion()
659
+ Type A affine permutation with window [2, 4, 0, 1, 7, 6, 5, 11]
660
+ """
661
+ l = [self[-1] - self.k]
662
+ l.extend(self[i] + 1 for i in range(self.k))
663
+ return type(self)(self.parent(), l)
664
+
665
+ def maximal_cyclic_factor(self, typ='decreasing',
666
+ side='right', verbose=False) -> list:
667
+ r"""
668
+ For an affine permutation `x`, find the unique maximal subset `A`
669
+ of the index set such that `x = yd_A` is a reduced product.
670
+
671
+ INPUT:
672
+
673
+ - ``typ`` -- ``'increasing'`` or ``'decreasing'``
674
+ (default: ``'decreasing'``); chooses whether to find increasing
675
+ or decreasing sets
676
+
677
+ - ``side`` -- ``'right'`` or ``'left'`` (default: ``'right'``); chooses
678
+ whether to find maximal sets starting from the left or the right
679
+
680
+ - ``verbose`` -- boolean; if ``True``, outputs information about how
681
+ the cyclically increasing element was found
682
+
683
+ EXAMPLES::
684
+
685
+ sage: p = AffinePermutationGroup(['A',7,1])([3, -1, 0, 6, 5, 4, 10, 9])
686
+ sage: p.maximal_cyclic_factor()
687
+ [7, 5, 4, 2, 1]
688
+ sage: p.maximal_cyclic_factor(side='left')
689
+ [1, 0, 7, 5, 4]
690
+ sage: p.maximal_cyclic_factor('increasing','right')
691
+ [4, 5, 7, 0, 1]
692
+ sage: p.maximal_cyclic_factor('increasing','left')
693
+ [0, 1, 2, 4, 5]
694
+ """
695
+ k = self.k
696
+ if side[0] == 'r':
697
+ descents = self.descents(side='right')
698
+ side = 'right'
699
+ else:
700
+ descents = self.descents(side='left')
701
+ side = 'left'
702
+ # for now, assume side is 'right')
703
+ best_T: list[int] = []
704
+ for i in descents:
705
+ y = self.clone().apply_simple_reflection(i, side)
706
+ T = [i]
707
+ j = i
708
+ for _ in range(1, self.k):
709
+ if (typ[0], side[0]) == ('d', 'r'):
710
+ j = (j+1) % (k+1)
711
+ if (typ[0], side[0]) == ('i', 'r'):
712
+ j = (j-1) % (k+1)
713
+ if (typ[0], side[0]) == ('d', 'l'):
714
+ j = (j-1) % (k+1)
715
+ if (typ[0], side[0]) == ('i', 'l'):
716
+ j = (j+1) % (k+1)
717
+ if y.has_descent(j, side):
718
+ y = y.apply_simple_reflection(j, side)
719
+ T.append(j % (k+1))
720
+ if verbose:
721
+ print(i, T)
722
+ if len(T) > len(best_T):
723
+ best_T = T
724
+ # if (typ[0],side[0])==('i','r'): best_T.reverse()
725
+ # if (typ[0],side[0])==('d','l'): best_T.reverse()
726
+ # if typ[0]=='d': best_T.reverse()
727
+ if side[0] == 'r':
728
+ best_T.reverse()
729
+ return best_T
730
+
731
+ def maximal_cyclic_decomposition(self, typ='decreasing', side='right', verbose=False):
732
+ r"""
733
+ Find the unique maximal decomposition of ``self`` into cyclically
734
+ decreasing/increasing elements.
735
+
736
+ INPUT:
737
+
738
+ - ``typ`` -- ``'increasing'`` or ``'decreasing'``
739
+ (default: ``'decreasing'``); chooses whether to find increasing
740
+ or decreasing sets
741
+
742
+ - ``side`` -- ``'right'`` or ``'left'`` (default: ``'right'``) chooses
743
+ whether to find maximal sets starting from the left or the right
744
+
745
+ - ``verbose`` -- boolean (default: ``False``); print extra information
746
+ while finding the decomposition
747
+
748
+ EXAMPLES::
749
+
750
+ sage: p = AffinePermutationGroup(['A',7,1])([3, -1, 0, 6, 5, 4, 10, 9])
751
+ sage: p.maximal_cyclic_decomposition()
752
+ [[0, 7], [4, 1, 0], [7, 5, 4, 2, 1]]
753
+ sage: p.maximal_cyclic_decomposition(side='left')
754
+ [[1, 0, 7, 5, 4], [1, 0, 5], [2, 1]]
755
+ sage: p.maximal_cyclic_decomposition(typ='increasing', side='right')
756
+ [[1], [5, 0, 1, 2], [4, 5, 7, 0, 1]]
757
+ sage: p.maximal_cyclic_decomposition(typ='increasing', side='left')
758
+ [[0, 1, 2, 4, 5], [4, 7, 0, 1], [7]]
759
+
760
+ TESTS::
761
+
762
+ sage: A = AffinePermutationGroup(['A',7,1])
763
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
764
+ sage: S = p.maximal_cyclic_decomposition()
765
+ sage: p == prod(A.from_word(l) for l in S)
766
+ True
767
+ sage: S = p.maximal_cyclic_decomposition(typ='increasing', side='left')
768
+ sage: p == prod(A.from_word(l) for l in S)
769
+ True
770
+ sage: S = p.maximal_cyclic_decomposition(typ='increasing', side='right')
771
+ sage: p == prod(A.from_word(l) for l in S)
772
+ True
773
+ sage: S = p.maximal_cyclic_decomposition(typ='decreasing', side='right')
774
+ sage: p == prod(A.from_word(l) for l in S)
775
+ True
776
+ """
777
+ y = self.clone()
778
+ listy = []
779
+ if verbose:
780
+ print('length of x:', self.length())
781
+ while not y.is_one():
782
+ S = y.maximal_cyclic_factor(typ, side, verbose)
783
+ listy.append(S[:])
784
+ if side[0] == 'r':
785
+ S.reverse()
786
+ for i in S:
787
+ if side[0] == 'r':
788
+ y = y.apply_simple_reflection_right(i)
789
+ else:
790
+ y = y.apply_simple_reflection_left(i)
791
+ if verbose:
792
+ print(S, y.length())
793
+ if side[0] == 'r':
794
+ listy.reverse()
795
+ return listy
796
+
797
+ def to_lehmer_code(self, typ='decreasing', side='right') -> Composition:
798
+ r"""
799
+ Return the affine Lehmer code.
800
+
801
+ There are four such codes; the options ``typ`` and ``side`` determine
802
+ which code is generated. The codes generated are the shape of the
803
+ maximal cyclic decompositions of ``self`` according to the given
804
+ ``typ`` and ``side`` options.
805
+
806
+ INPUT:
807
+
808
+ - ``typ`` -- ``'increasing'`` or ``'decreasing'``
809
+ (default: ``'decreasing'``); chooses whether to find increasing
810
+ or decreasing sets
811
+
812
+ - ``side`` -- ``'right'`` or ``'left'`` (default: ``'right'``) chooses
813
+ whether to find maximal sets starting from the left or the right
814
+
815
+ EXAMPLES::
816
+
817
+ sage: import itertools
818
+ sage: A = AffinePermutationGroup(['A',7,1])
819
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
820
+ sage: orders = ('increasing','decreasing')
821
+ sage: sides = ('left','right')
822
+ sage: for o,s in itertools.product(orders, sides):
823
+ ....: p.to_lehmer_code(o,s)
824
+ [2, 3, 2, 0, 1, 2, 0, 0]
825
+ [2, 2, 0, 0, 2, 1, 0, 3]
826
+ [3, 1, 0, 0, 2, 1, 0, 3]
827
+ [0, 3, 3, 0, 1, 2, 0, 1]
828
+ sage: for a in itertools.product(orders, sides):
829
+ ....: A.from_lehmer_code(p.to_lehmer_code(a[0],a[1]), a[0],a[1])==p
830
+ True
831
+ True
832
+ True
833
+ True
834
+ """
835
+ code = [0 for i in range(self.k+1)]
836
+ if typ[0] == 'i' and side[0] == 'r':
837
+ # Find number of positions to the right of position i with smaller
838
+ # value than the number in position i.
839
+ for i in range(self.k+1):
840
+ a = self(i)
841
+ for j in range(i+1, i+self.k+1):
842
+ b = self(j)
843
+ if b < a:
844
+ code[i] += (a-b) // (self.k+1) + 1
845
+ elif typ[0] == 'd' and side[0] == 'r':
846
+ # Find number of positions to the left of position i with larger
847
+ # value than the number in position i. Then cyclically shift
848
+ # the resulting vector.
849
+ for i in range(self.k+1):
850
+ a = self(i)
851
+ for j in range(i-self.k, i):
852
+ b = self(j)
853
+ # A small rotation is necessary for the reduced word from
854
+ # the Lehmer code to match the element.
855
+ if a < b:
856
+ code[i-1] += ((b-a)//(self.k+1)+1)
857
+ elif typ[0] == 'i' and side[0] == 'l':
858
+ # Find number of positions to the right of i smaller than i, then
859
+ # cyclically shift the resulting vector.
860
+ for i in range(self.k+1):
861
+ pos = self.position(i)
862
+ for j in range(pos+1, pos+self.k+1):
863
+ b = self(j)
864
+ # A small rotation is necessary for the reduced word from
865
+ # the lehmer code to match the element.
866
+ if b < i:
867
+ code[i-1] += (i-b) // (self.k+1) + 1
868
+ elif typ[0] == 'd' and side[0] == 'l':
869
+ # Find number of positions to the left of i larger than i.
870
+ for i in range(self.k+1):
871
+ pos = self.position(i)
872
+ for j in range(pos-self.k, pos):
873
+ b = self(j)
874
+ if b > i:
875
+ code[i] += (b-i) // (self.k+1) + 1
876
+ return Composition(code)
877
+
878
+ def is_fully_commutative(self) -> bool:
879
+ r"""
880
+ Determine whether ``self`` is fully commutative.
881
+
882
+ This means that it has no reduced word with a braid.
883
+
884
+ This uses a specific algorithm.
885
+
886
+ EXAMPLES::
887
+
888
+ sage: A = AffinePermutationGroup(['A',7,1])
889
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
890
+ sage: p.is_fully_commutative()
891
+ False
892
+ sage: q = A([-3, -2, 0, 7, 9, 2, 11, 12])
893
+ sage: q.is_fully_commutative()
894
+ True
895
+ """
896
+ if self == self.parent().one():
897
+ return True
898
+ c = self.to_lehmer_code()
899
+ found = False
900
+ m = -1
901
+ for i in range(self.n):
902
+ if c[i] > 0:
903
+ if not found:
904
+ found = True
905
+ firstnonzero = i
906
+ if m != -1 and c[i] - (i - m) >= c[m]:
907
+ return False
908
+ m = i
909
+ assert found
910
+ # now check m (the last nonzero) against first nonzero.
911
+ d = self.n - (m - firstnonzero)
912
+ return not c[firstnonzero] - d >= c[m]
913
+
914
+ def to_bounded_partition(self, typ='decreasing', side='right') -> Partition:
915
+ r"""
916
+ Return the `k`-bounded partition associated to the dominant element
917
+ obtained by sorting the Lehmer code.
918
+
919
+ INPUT:
920
+
921
+ - ``typ`` -- ``'increasing'`` or ``'decreasing'`` (default: ``'decreasing'``);
922
+ chooses whether to find increasing or decreasing sets
923
+
924
+ - ``side`` -- ``'right'`` or ``'left'`` (default: ``'right'``); chooses
925
+ whether to find maximal sets starting from the left or the right
926
+
927
+ EXAMPLES::
928
+
929
+ sage: A = AffinePermutationGroup(['A',2,1])
930
+ sage: p = A.from_lehmer_code([4,1,0])
931
+ sage: p.to_bounded_partition()
932
+ [2, 1, 1, 1]
933
+ """
934
+ c = sorted(self.to_lehmer_code(typ, side))
935
+ c.reverse()
936
+ return Partition(c).conjugate()
937
+
938
+ def to_core(self, typ='decreasing', side='right'):
939
+ r"""
940
+ Return the core associated to the dominant element obtained by sorting
941
+ the Lehmer code.
942
+
943
+ INPUT:
944
+
945
+ - ``typ`` -- ``'increasing'`` or ``'decreasing'`` (default: ``'decreasing'``.)
946
+
947
+ - ``side`` -- ``'right'`` or ``'left'`` (default: ``'right'``.) Chooses whether to
948
+ find maximal sets starting from the left or the right
949
+
950
+ EXAMPLES::
951
+
952
+ sage: A = AffinePermutationGroup(['A',2,1])
953
+ sage: p = A.from_lehmer_code([4,1,0])
954
+ sage: p.to_bounded_partition()
955
+ [2, 1, 1, 1]
956
+ sage: p.to_core()
957
+ [4, 2, 1, 1]
958
+ """
959
+ return self.to_bounded_partition(typ, side).to_core(self.k)
960
+
961
+ def to_dominant(self, typ='decreasing',
962
+ side='right') -> AffinePermutationTypeA:
963
+ r"""
964
+ Find the Lehmer code and then sort it. Return the affine permutation
965
+ with the given sorted Lehmer code.
966
+
967
+ This element is 0-dominant.
968
+
969
+ INPUT:
970
+
971
+ - ``typ`` -- ``'increasing'`` or ``'decreasing'``
972
+ (default: ``'decreasing'``) chooses whether to find increasing
973
+ or decreasing sets
974
+
975
+ - ``side`` -- ``'right'`` or ``'left'`` (default: ``'right'``) chooses
976
+ whether to find maximal sets starting from the left or the right
977
+
978
+ EXAMPLES::
979
+
980
+ sage: A = AffinePermutationGroup(['A',7,1])
981
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
982
+ sage: p.to_dominant()
983
+ Type A affine permutation with window [-2, -1, 1, 3, 4, 8, 10, 13]
984
+ sage: p.to_dominant(typ='increasing', side='left')
985
+ Type A affine permutation with window [3, 4, -1, 5, 0, 9, 6, 10]
986
+ """
987
+ if self.is_i_grassmannian(side=side):
988
+ return self
989
+ c = sorted(self.to_lehmer_code(typ, side))
990
+ c.reverse()
991
+ return self.parent().from_lehmer_code(c, typ, side)
992
+
993
+ def tableau_of_word(self, w, typ='decreasing', side='right', alpha=None):
994
+ r"""
995
+ Finds a tableau on the Lehmer code of ``self`` corresponding
996
+ to the given reduced word.
997
+
998
+ For a full description of this algorithm, see [Den2012]_.
999
+
1000
+ INPUT:
1001
+
1002
+ - ``w`` -- a reduced word for ``self``
1003
+ - ``typ`` -- ``'increasing'`` or ``'decreasing'``; the type of
1004
+ Lehmer code used
1005
+ - ``side`` -- ``'right'`` or ``'left'``
1006
+ - ``alpha`` -- a content vector; ``w`` should be of type ``alpha``;
1007
+ specifying ``alpha`` produces semistandard tableaux
1008
+
1009
+ EXAMPLES::
1010
+
1011
+ sage: A = AffinePermutationGroup(['A',7,1])
1012
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
1013
+ sage: p.tableau_of_word(p.reduced_word())
1014
+ [[], [1, 6, 9], [2, 7, 10], [], [3], [4, 8], [], [5]]
1015
+ sage: A = AffinePermutationGroup(['A',7,1])
1016
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
1017
+ sage: w = p.reduced_word(); w
1018
+ [0, 7, 4, 1, 0, 7, 5, 4, 2, 1]
1019
+ sage: alpha = [5,3,2]
1020
+ sage: p.tableau_of_word(p.reduced_word(), alpha=alpha)
1021
+ [[], [1, 2, 3], [1, 2, 3], [], [1], [1, 2], [], [1]]
1022
+ sage: p.tableau_of_word(p.reduced_word(), side='left')
1023
+ [[1, 4, 9], [6], [], [], [3, 7], [8], [], [2, 5, 10]]
1024
+ sage: p.tableau_of_word(p.reduced_word(), typ='increasing', side='right')
1025
+ [[9, 10], [1, 2], [], [], [3, 4], [8], [], [5, 6, 7]]
1026
+ sage: p.tableau_of_word(p.reduced_word(), typ='increasing', side='left')
1027
+ [[1, 2], [4, 5, 6], [9, 10], [], [3], [7, 8], [], []]
1028
+ """
1029
+ g = self.parent().simple_reflections()
1030
+ # Check w is reduced....:should probably throw an exception otherwise.
1031
+ x0 = prod(g[i] for i in w)
1032
+ if x0.length() != len(w):
1033
+ raise ValueError("word was not reduced")
1034
+ if alpha is None:
1035
+ alpha = Composition([1 for i in w])
1036
+ else:
1037
+ if sum(alpha) != len(w):
1038
+ raise ValueError("size of alpha must match length of w")
1039
+ alpha = Composition(alpha)
1040
+ # TODO: We should probably check that w is of type alpha! probably a different function.
1041
+ # Now we actually build the recording tableau.
1042
+ tab: list[list[int]] = [[] for _ in repeat(None, self.k + 1)]
1043
+ label = 1
1044
+ al_index = 0
1045
+ j = 0
1046
+ x = self.parent().one()
1047
+ cx = x.to_lehmer_code(typ, side)
1048
+ n = len(w)-1
1049
+ for i in range(len(w)):
1050
+ if side[0] == 'r':
1051
+ # y=g[w[n-i]]*x
1052
+ y = x.apply_simple_reflection_left(w[n-i])
1053
+ else:
1054
+ y = x.apply_simple_reflection_right(w[i])
1055
+ cy = y.to_lehmer_code(typ, side)
1056
+ for r in range(self.k+1):
1057
+ if cy[r] > cx[r]:
1058
+ tab[r].append(label)
1059
+ j += 1
1060
+ if j == alpha[al_index]:
1061
+ al_index += 1
1062
+ j = 0
1063
+ label += 1
1064
+ break
1065
+ x = y
1066
+ cx = cy
1067
+ return tab
1068
+
1069
+ # -----------------------------------------------------------------------------
1070
+
1071
+
1072
+ class AffinePermutationTypeC(AffinePermutation):
1073
+ # ----------------------
1074
+ # Type-specific methods.
1075
+ # (Methods existing in all types, but with type-specific definition.)
1076
+ # ----------------------
1077
+ def check(self) -> None:
1078
+ r"""
1079
+ Check that ``self`` is an affine permutation.
1080
+
1081
+ EXAMPLES::
1082
+
1083
+ sage: C = AffinePermutationGroup(['C',4,1])
1084
+ sage: x = C([-1,5,3,7])
1085
+ sage: x
1086
+ Type C affine permutation with window [-1, 5, 3, 7]
1087
+ """
1088
+ if not self:
1089
+ return
1090
+ k = self.parent().k
1091
+ if len(self) != k:
1092
+ raise ValueError("length of list must be k=" + str(k))
1093
+ reslist = []
1094
+ for i in self:
1095
+ r = i % self.N
1096
+ if r == 0:
1097
+ raise ValueError("entries may not have residue 0 mod 2k+1")
1098
+ if r in reslist or self.N - r in reslist:
1099
+ raise ValueError("entries must have distinct residues")
1100
+ reslist.append(r)
1101
+
1102
+ def value(self, i):
1103
+ r"""
1104
+ Return the image of the integer ``i`` under this permutation.
1105
+
1106
+ EXAMPLES::
1107
+
1108
+ sage: C = AffinePermutationGroup(['C',4,1])
1109
+ sage: x = C.one()
1110
+ sage: all(x.value(i) == i for i in range(-10,10))
1111
+ True
1112
+ """
1113
+ N = 2*self.k + 1
1114
+ window = i // N
1115
+ index = i % N
1116
+ if index == 0:
1117
+ return i
1118
+ if index <= self.k:
1119
+ return self[index-1]+window*N
1120
+ if index > self.k:
1121
+ return -(self[N-index-1]-N)+window*N
1122
+
1123
+ def position(self, i):
1124
+ r"""
1125
+ Find the position `j` such the ``self.value(j)=i``.
1126
+
1127
+ EXAMPLES::
1128
+
1129
+ sage: C = AffinePermutationGroup(['C',4,1])
1130
+ sage: x = C.one()
1131
+ sage: all(x.position(i) == i for i in range(-10,10))
1132
+ True
1133
+ """
1134
+ N = 2*self.k + 1
1135
+ index = i % N
1136
+ if index == 0:
1137
+ return i
1138
+ for r in range(len(self)):
1139
+ if self[r] % N == index:
1140
+ # i sits in position i, but some number of windows away.
1141
+ diff = (i-self[r]) // N
1142
+ return r + diff*N + 1
1143
+ if self[r] % N == N - index:
1144
+ # then we sit some number of windows from position -r.
1145
+ diff = (i+self[r]) // N
1146
+ return -r + diff*N - 1
1147
+ return False
1148
+
1149
+ def apply_simple_reflection_right(self, i) -> AffinePermutationTypeC:
1150
+ r"""
1151
+ Apply the simple reflection indexed by ``i`` on positions.
1152
+
1153
+ EXAMPLES::
1154
+
1155
+ sage: C = AffinePermutationGroup(['C',4,1])
1156
+ sage: x = C([-1,5,3,7])
1157
+ sage: for i in C.index_set(): x.apply_simple_reflection_right(i)
1158
+ Type C affine permutation with window [1, 5, 3, 7]
1159
+ Type C affine permutation with window [5, -1, 3, 7]
1160
+ Type C affine permutation with window [-1, 3, 5, 7]
1161
+ Type C affine permutation with window [-1, 5, 7, 3]
1162
+ Type C affine permutation with window [-1, 5, 3, 2]
1163
+ """
1164
+ if i not in self.parent().index_set():
1165
+ raise ValueError('index not in index set')
1166
+ j = i
1167
+ l = self[:]
1168
+ if j != 0 and j != self.k:
1169
+ a = l[j-1]
1170
+ l[j-1] = l[j]
1171
+ l[j] = a
1172
+ elif j == 0:
1173
+ l[0] = -l[0]
1174
+ elif j == self.k:
1175
+ l[self.k-1] = self(self.k+1)
1176
+ # return l
1177
+ return type(self)(self.parent(), l, check=False)
1178
+
1179
+ def apply_simple_reflection_left(self, i) -> AffinePermutationTypeC:
1180
+ r"""
1181
+ Apply the simple reflection indexed by ``i`` on values.
1182
+
1183
+ EXAMPLES::
1184
+
1185
+ sage: C = AffinePermutationGroup(['C',4,1])
1186
+ sage: x = C([-1,5,3,7])
1187
+ sage: for i in C.index_set(): x.apply_simple_reflection_left(i)
1188
+ Type C affine permutation with window [1, 5, 3, 7]
1189
+ Type C affine permutation with window [-2, 5, 3, 8]
1190
+ Type C affine permutation with window [-1, 5, 2, 6]
1191
+ Type C affine permutation with window [-1, 6, 4, 7]
1192
+ Type C affine permutation with window [-1, 4, 3, 7]
1193
+ """
1194
+ if i not in self.parent().index_set():
1195
+ raise ValueError('index not in index set')
1196
+ j = self.N - i
1197
+ l = []
1198
+ if i != self.k and i != 0:
1199
+ for m in range(self.k):
1200
+ res = self[m] % self.N
1201
+ if res == i:
1202
+ l.append(self[m] + 1)
1203
+ elif res == i + 1:
1204
+ l.append(self[m] - 1)
1205
+ elif res == j:
1206
+ l.append(self[m] - 1)
1207
+ elif res == j - 1:
1208
+ l.append(self[m] + 1)
1209
+ else:
1210
+ l.append(self[m])
1211
+ elif i == 0:
1212
+ for m in range(self.k):
1213
+ res = self[m] % self.N
1214
+ if res == 1:
1215
+ l.append(self[m] - 2)
1216
+ elif res == self.N - 1:
1217
+ l.append(self[m] + 2)
1218
+ else:
1219
+ l.append(self[m])
1220
+ elif i == self.k:
1221
+ for m in range(self.k):
1222
+ res = self[m] % self.N
1223
+ if res == i:
1224
+ l.append(self[m] + 1)
1225
+ elif res == j:
1226
+ l.append(self[m] - 1)
1227
+ else:
1228
+ l.append(self[m])
1229
+ return type(self)(self.parent(), l, check=False)
1230
+
1231
+ def has_right_descent(self, i) -> bool:
1232
+ r"""
1233
+ Determine whether there is a descent at index ``i``.
1234
+
1235
+ INPUT:
1236
+
1237
+ - ``i`` -- integer
1238
+
1239
+ EXAMPLES::
1240
+
1241
+ sage: C = AffinePermutationGroup(['C',4,1])
1242
+ sage: x = C([-1,5,3,7])
1243
+ sage: for i in C.index_set(): x.has_right_descent(i)
1244
+ True
1245
+ False
1246
+ True
1247
+ False
1248
+ True
1249
+ """
1250
+ return self.value(i) > self.value(i+1)
1251
+
1252
+ def has_left_descent(self, i) -> bool:
1253
+ r"""
1254
+ Determine whether there is a descent at ``i``.
1255
+
1256
+ INPUT:
1257
+
1258
+ - ``i`` -- integer
1259
+
1260
+ EXAMPLES::
1261
+
1262
+ sage: C = AffinePermutationGroup(['C',4,1])
1263
+ sage: x = C([-1,5,3,7])
1264
+ sage: for i in C.index_set(): x.has_left_descent(i)
1265
+ True
1266
+ False
1267
+ True
1268
+ False
1269
+ True
1270
+ """
1271
+ # This is much faster than the default method of taking the inverse and
1272
+ # then finding right descents...
1273
+ return self.position(i) > self.position(i + 1)
1274
+
1275
+ def to_type_a(self) -> AffinePermutationTypeA:
1276
+ r"""
1277
+ Return an embedding of ``self`` into the affine permutation group of
1278
+ type `A`.
1279
+
1280
+ EXAMPLES::
1281
+
1282
+ sage: C = AffinePermutationGroup(['C',4,1])
1283
+ sage: x = C([-1,5,3,7])
1284
+ sage: x.to_type_a()
1285
+ Type A affine permutation with window [-1, 5, 3, 7, 2, 6, 4, 10, 9]
1286
+ """
1287
+ A = AffinePermutationGroup(['A', self.N - 1, 1])
1288
+ return A([self.value(i) for i in range(1, self.N + 1)])
1289
+
1290
+
1291
+ class AffinePermutationTypeB(AffinePermutationTypeC):
1292
+ # ----------------------
1293
+ # Type-specific methods.
1294
+ # (Methods existing in all types, but with type-specific definition.)
1295
+ # ----------------------
1296
+ def check(self) -> None:
1297
+ r"""
1298
+ Check that ``self`` is an affine permutation.
1299
+
1300
+ EXAMPLES::
1301
+
1302
+ sage: B = AffinePermutationGroup(['B',4,1])
1303
+ sage: x = B([-5,1,6,-2])
1304
+ sage: x
1305
+ Type B affine permutation with window [-5, 1, 6, -2]
1306
+ """
1307
+ if not self:
1308
+ return
1309
+ k = self.parent().k
1310
+ # Check window length.
1311
+ if len(self) != k:
1312
+ raise ValueError("length of list must be k=" + str(k))
1313
+ # Check for repeated residues.
1314
+ reslist = []
1315
+ for i in self:
1316
+ r = i % self.N
1317
+ if r == 0:
1318
+ raise ValueError("entries may not have residue 0 mod 2k+1")
1319
+ if r in reslist or self.N - r in reslist:
1320
+ raise ValueError("entries must have distinct residues")
1321
+ reslist.append(r)
1322
+ # Check that we have an even number of 'small' elements right
1323
+ # of the zeroth entry.
1324
+ s = sum(-i // self.N + 1 for j in range(1, self.N + 1)
1325
+ if (i := self.value(j)) < 0)
1326
+ if s % 2:
1327
+ raise ValueError("type B affine permutations have an even number of "
1328
+ "entries less than 0 to the right of the 0th position")
1329
+
1330
+ def apply_simple_reflection_right(self, i) -> AffinePermutationTypeB:
1331
+ r"""
1332
+ Apply the simple reflection indexed by ``i`` on positions.
1333
+
1334
+ EXAMPLES::
1335
+
1336
+ sage: B = AffinePermutationGroup(['B',4,1])
1337
+ sage: p = B([-5,1,6,-2])
1338
+ sage: p.apply_simple_reflection_right(1)
1339
+ Type B affine permutation with window [1, -5, 6, -2]
1340
+ sage: p.apply_simple_reflection_right(0)
1341
+ Type B affine permutation with window [-1, 5, 6, -2]
1342
+ sage: p.apply_simple_reflection_right(4)
1343
+ Type B affine permutation with window [-5, 1, 6, 11]
1344
+ """
1345
+ if i not in self.parent().index_set():
1346
+ raise ValueError('index not in index set')
1347
+ j = i
1348
+ l = self[:]
1349
+ if j != 0 and j != self.k:
1350
+ # just swap l[j], l[j-1]
1351
+ (l[j-1], l[j]) = (l[j], l[j-1])
1352
+ elif j == 0:
1353
+ l[0] = -self(2)
1354
+ l[1] = -self(1)
1355
+ elif j == self.k:
1356
+ l[self.k-1] = self(self.k+1)
1357
+ return type(self)(self.parent(), l, check=False)
1358
+
1359
+ def apply_simple_reflection_left(self, i) -> AffinePermutationTypeB:
1360
+ r"""
1361
+ Apply the simple reflection indexed by ``i`` on values.
1362
+
1363
+ EXAMPLES::
1364
+
1365
+ sage: B = AffinePermutationGroup(['B',4,1])
1366
+ sage: p = B([-5,1,6,-2])
1367
+ sage: p.apply_simple_reflection_left(0)
1368
+ Type B affine permutation with window [-5, -2, 6, 1]
1369
+ sage: p.apply_simple_reflection_left(2)
1370
+ Type B affine permutation with window [-5, 1, 7, -3]
1371
+ sage: p.apply_simple_reflection_left(4)
1372
+ Type B affine permutation with window [-4, 1, 6, -2]
1373
+ """
1374
+ if i not in self.parent().index_set():
1375
+ raise ValueError('index not in index set')
1376
+ j = self.N - i
1377
+ l = []
1378
+ if i != self.k and i != 0:
1379
+ for m in range(self.k):
1380
+ res = self[m] % self.N
1381
+ if res == i:
1382
+ l.append(self[m]+1)
1383
+ elif res == i + 1:
1384
+ l.append(self[m]-1)
1385
+ elif res == j:
1386
+ l.append(self[m]-1)
1387
+ elif res == j - 1:
1388
+ l.append(self[m]+1)
1389
+ else:
1390
+ l.append(self[m])
1391
+ elif i == 0:
1392
+ for m in range(self.k):
1393
+ res = self[m] % self.N
1394
+ if res == 1:
1395
+ l.append(self[m]-3)
1396
+ elif res == self.N - 2:
1397
+ l.append(self[m]+3)
1398
+ elif res == 2:
1399
+ l.append(self[m]-3)
1400
+ elif res == self.N - 1:
1401
+ l.append(self[m]+3)
1402
+ else:
1403
+ l.append(self[m])
1404
+ elif i == self.k:
1405
+ for m in range(self.k):
1406
+ res = self[m] % self.N
1407
+ if res == i:
1408
+ l.append(self[m] + 1)
1409
+ elif res == j:
1410
+ l.append(self[m] - 1)
1411
+ else:
1412
+ l.append(self[m])
1413
+ return type(self)(self.parent(), l, check=False)
1414
+
1415
+ def has_right_descent(self, i) -> bool:
1416
+ r"""
1417
+ Determine whether there is a descent at index ``i``.
1418
+
1419
+ INPUT:
1420
+
1421
+ - ``i`` -- integer
1422
+
1423
+ EXAMPLES::
1424
+
1425
+ sage: B = AffinePermutationGroup(['B',4,1])
1426
+ sage: p = B([-5,1,6,-2])
1427
+ sage: [p.has_right_descent(i) for i in B.index_set()]
1428
+ [True, False, False, True, False]
1429
+ """
1430
+ if i == 0:
1431
+ return self.value(-2) > self.value(1)
1432
+ return self.value(i) > self.value(i+1)
1433
+
1434
+ def has_left_descent(self, i) -> bool:
1435
+ r"""
1436
+ Determine whether there is a descent at ``i``.
1437
+
1438
+ INPUT:
1439
+
1440
+ - ``i`` -- integer
1441
+
1442
+ EXAMPLES::
1443
+
1444
+ sage: B = AffinePermutationGroup(['B',4,1])
1445
+ sage: p = B([-5,1,6,-2])
1446
+ sage: [p.has_left_descent(i) for i in B.index_set()]
1447
+ [True, True, False, False, True]
1448
+ """
1449
+ if i == 0:
1450
+ return self.position(-2) > self.position(1)
1451
+ return self.position(i) > self.position(i + 1)
1452
+
1453
+
1454
+ class AffinePermutationTypeD(AffinePermutationTypeC):
1455
+ # ----------------------
1456
+ # Type-specific methods.
1457
+ # (Methods existing in all types, but with type-specific definition.)
1458
+ # ----------------------
1459
+ def check(self) -> None:
1460
+ r"""
1461
+ Check that ``self`` is an affine permutation.
1462
+
1463
+ EXAMPLES::
1464
+
1465
+ sage: D = AffinePermutationGroup(['D',4,1])
1466
+ sage: p = D([1,-6,5,-2])
1467
+ sage: p
1468
+ Type D affine permutation with window [1, -6, 5, -2]
1469
+ """
1470
+ if not self:
1471
+ return
1472
+ k = self.parent().k
1473
+ # Check window length.
1474
+ if len(self) != k:
1475
+ raise ValueError("length of list must be k=" + str(k))
1476
+ # Check for repeated residues.
1477
+ reslist = []
1478
+ for i in self:
1479
+ r = i % self.N
1480
+ if r == 0:
1481
+ raise ValueError("entries may not have residue 0 mod 2k+1")
1482
+ if r in reslist or self.N - r in reslist:
1483
+ raise ValueError("entries must have distinct residues")
1484
+ reslist.append(r)
1485
+ # Check that we have an even number of 'big' elements left of
1486
+ # the kth entry.
1487
+ s = sum(i // self.N + 1 - (i % self.N <= self.k)
1488
+ for j in range(-self.k, self.k + 1)
1489
+ if (i := self.value(j)) > self.k)
1490
+ if s % 2:
1491
+ raise ValueError("type D affine permutations have an even number of entries"
1492
+ " greater than x.k weakly to the left of the x.k position")
1493
+ # Check that we have an even number of 'small' elements right of the zeroth entry.
1494
+ s = sum(-i // self.N + 1 for j in range(1, self.N + 1)
1495
+ if (i := self.value(j)) < 0)
1496
+ if s % 2:
1497
+ raise ValueError("type D affine permutations have an even number of entries"
1498
+ " less than 0 to the right of the 0th position")
1499
+
1500
+ def apply_simple_reflection_right(self, i) -> AffinePermutationTypeD:
1501
+ r"""
1502
+ Apply the simple reflection indexed by ``i`` on positions.
1503
+
1504
+ EXAMPLES::
1505
+
1506
+ sage: D = AffinePermutationGroup(['D',4,1])
1507
+ sage: p = D([1,-6,5,-2])
1508
+ sage: p.apply_simple_reflection_right(0)
1509
+ Type D affine permutation with window [6, -1, 5, -2]
1510
+ sage: p.apply_simple_reflection_right(1)
1511
+ Type D affine permutation with window [-6, 1, 5, -2]
1512
+ sage: p.apply_simple_reflection_right(4)
1513
+ Type D affine permutation with window [1, -6, 11, 4]
1514
+ """
1515
+ if i not in self.parent().index_set():
1516
+ raise ValueError('index not in index set')
1517
+ j = i
1518
+ l = self[:]
1519
+ if j != 0 and j != self.k:
1520
+ a = l[j-1]
1521
+ l[j-1] = l[j]
1522
+ l[j] = a
1523
+ elif j == 0:
1524
+ c = l[0]
1525
+ l[0] = -l[1]
1526
+ l[1] = -c
1527
+ elif j == self.k:
1528
+ l[self.k-2] = self(self.k+1)
1529
+ l[self.k-1] = self(self.k+2)
1530
+ return type(self)(self.parent(), l, check=False)
1531
+
1532
+ def apply_simple_reflection_left(self, i) -> AffinePermutationTypeD:
1533
+ r"""
1534
+ Apply simple reflection indexed by ``i`` on values.
1535
+
1536
+ EXAMPLES::
1537
+
1538
+ sage: D = AffinePermutationGroup(['D',4,1])
1539
+ sage: p = D([1,-6,5,-2])
1540
+ sage: p.apply_simple_reflection_left(0)
1541
+ Type D affine permutation with window [-2, -6, 5, 1]
1542
+ sage: p.apply_simple_reflection_left(1)
1543
+ Type D affine permutation with window [2, -6, 5, -1]
1544
+ sage: p.apply_simple_reflection_left(4)
1545
+ Type D affine permutation with window [1, -4, 3, -2]
1546
+ """
1547
+ if i not in self.parent().index_set():
1548
+ raise ValueError('index not in index set')
1549
+ j = self.N - i
1550
+ l = []
1551
+ if i and i != self.k:
1552
+ for m in range(self.k):
1553
+ res = self[m] % self.N
1554
+ if res == i:
1555
+ l.append(self[m]+1)
1556
+ elif res == i+1:
1557
+ l.append(self[m]-1)
1558
+ elif res == j:
1559
+ l.append(self[m]-1)
1560
+ elif res == j-1:
1561
+ l.append(self[m]+1)
1562
+ else:
1563
+ l.append(self[m])
1564
+ elif i == 0:
1565
+ for m in range(self.k):
1566
+ res = self[m] % self.N
1567
+ if res == 1:
1568
+ l.append(self[m]-3)
1569
+ elif res == self.N-2:
1570
+ l.append(self[m]+3)
1571
+ elif res == 2:
1572
+ l.append(self[m]-3)
1573
+ elif res == self.N-1:
1574
+ l.append(self[m]+3)
1575
+ else:
1576
+ l.append(self[m])
1577
+ elif i == self.k:
1578
+ for m in range(self.k):
1579
+ res = self[m] % self.N
1580
+ if res == self.k:
1581
+ l.append(self[m]+2)
1582
+ elif res == self.k+2:
1583
+ l.append(self[m]-2)
1584
+ elif res == self.k-1:
1585
+ l.append(self[m]+2)
1586
+ elif res == self.k+1:
1587
+ l.append(self[m]-2)
1588
+ else:
1589
+ l.append(self[m])
1590
+ return type(self)(self.parent(), l, check=False)
1591
+
1592
+ def has_right_descent(self, i) -> bool:
1593
+ r"""
1594
+ Determine whether there is a descent at index ``i``.
1595
+
1596
+ INPUT:
1597
+
1598
+ - ``i`` -- integer
1599
+
1600
+ EXAMPLES::
1601
+
1602
+ sage: D = AffinePermutationGroup(['D',4,1])
1603
+ sage: p = D([1,-6,5,-2])
1604
+ sage: [p.has_right_descent(i) for i in D.index_set()]
1605
+ [True, True, False, True, False]
1606
+ """
1607
+ if i == 0:
1608
+ return self.value(-2) > self.value(1)
1609
+ if i == self.k:
1610
+ return self.value(i) > self.value(i+2)
1611
+ return self.value(i) > self.value(i+1)
1612
+
1613
+ def has_left_descent(self, i) -> bool:
1614
+ r"""
1615
+ Determine whether there is a descent at ``i``.
1616
+
1617
+ INPUT:
1618
+
1619
+ - ``i`` -- integer
1620
+
1621
+ EXAMPLES::
1622
+
1623
+ sage: D = AffinePermutationGroup(['D',4,1])
1624
+ sage: p = D([1,-6,5,-2])
1625
+ sage: [p.has_left_descent(i) for i in D.index_set()]
1626
+ [True, True, False, True, True]
1627
+ """
1628
+ if i == 0:
1629
+ return self.position(-2) > self.position(1)
1630
+ if i == self.k:
1631
+ return self.position(i) > self.position(i+2)
1632
+ return self.position(i) > self.position(i+1)
1633
+
1634
+
1635
+ class AffinePermutationTypeG(AffinePermutation):
1636
+ # ----------------------
1637
+ # Type-specific methods.
1638
+ # (Methods existing in all types, but with type-specific definition.)
1639
+ # ----------------------
1640
+ def check(self) -> None:
1641
+ r"""
1642
+ Check that ``self`` is an affine permutation.
1643
+
1644
+ EXAMPLES::
1645
+
1646
+ sage: G = AffinePermutationGroup(['G',2,1])
1647
+ sage: p = G([2, 10, -5, 12, -3, 5])
1648
+ sage: p
1649
+ Type G affine permutation with window [2, 10, -5, 12, -3, 5]
1650
+ """
1651
+ if not self:
1652
+ return
1653
+ if not len(self) == 6:
1654
+ raise ValueError("length of list must be 6")
1655
+ # Check that we have an even number of 'big' elements left of the 7th entry.
1656
+ s = sum(i//6 - (i % 6 == 0) for i in self if i > 6)
1657
+ if s % 2:
1658
+ raise ValueError("type G affine permutations have an even number of"
1659
+ " entries greater than 6 to the left of the 7th position")
1660
+ # Check that we have an even number of 'small' elements right of the zeroth entry.
1661
+ s = sum(-i//6 + 1 for i in self if i <= 0)
1662
+ if s % 2:
1663
+ raise ValueError("type G affine permutations have an even number of"
1664
+ " entries less than 0 to the right of the 0th position")
1665
+
1666
+ def value(self, i, base_window=False):
1667
+ r"""
1668
+ Return the image of the integer ``i`` under this permutation.
1669
+
1670
+ INPUT:
1671
+
1672
+ - ``base_window`` -- boolean indicating whether ``i`` is between 1 and
1673
+ `k+1`; if ``True``, will run a bit faster, but the method will screw
1674
+ up if ``i`` is not actually in the index set
1675
+
1676
+ EXAMPLES::
1677
+
1678
+ sage: G = AffinePermutationGroup(['G',2,1])
1679
+ sage: p = G([2, 10, -5, 12, -3, 5])
1680
+ sage: [p.value(i) for i in [1..12]]
1681
+ [2, 10, -5, 12, -3, 5, 8, 16, 1, 18, 3, 11]
1682
+ """
1683
+ N = 6
1684
+ if base_window:
1685
+ self[i-1]
1686
+ window = (i-1) // N
1687
+ return self[(i-1) % N] + window*(N)
1688
+
1689
+ def position(self, i):
1690
+ r"""
1691
+ Find the position ``j`` such the ``self.value(j) == i``.
1692
+
1693
+ EXAMPLES::
1694
+
1695
+ sage: G = AffinePermutationGroup(['G',2,1])
1696
+ sage: p = G([2, 10, -5, 12, -3, 5])
1697
+ sage: [p.position(i) for i in p]
1698
+ [1, 2, 3, 4, 5, 6]
1699
+ """
1700
+ N = 6
1701
+ for r in range(N):
1702
+ if self[r] % N == i % N:
1703
+ # i sits in position i, but some number of windows away.
1704
+ diff = (i-self[r]) // N
1705
+ return r + diff*N + 1
1706
+ return False
1707
+
1708
+ def apply_simple_reflection_right(self, i) -> AffinePermutationTypeG:
1709
+ r"""
1710
+ Apply the simple reflection indexed by ``i`` on positions.
1711
+
1712
+ EXAMPLES::
1713
+
1714
+ sage: G = AffinePermutationGroup(['G',2,1])
1715
+ sage: p = G([2, 10, -5, 12, -3, 5])
1716
+ sage: p.apply_simple_reflection_right(0)
1717
+ Type G affine permutation with window [-9, -1, -5, 12, 8, 16]
1718
+ sage: p.apply_simple_reflection_right(1)
1719
+ Type G affine permutation with window [10, 2, 12, -5, 5, -3]
1720
+ sage: p.apply_simple_reflection_right(2)
1721
+ Type G affine permutation with window [2, -5, 10, -3, 12, 5]
1722
+ """
1723
+ if i not in self.parent().index_set():
1724
+ raise ValueError('index not in index set')
1725
+ j = i
1726
+ l = self[:]
1727
+ if j == 1:
1728
+ l[0] = self(2)
1729
+ l[1] = self(1)
1730
+ l[2] = self(4)
1731
+ l[3] = self(3)
1732
+ l[4] = self(6)
1733
+ l[5] = self(5)
1734
+ elif j == 2:
1735
+ l[1] = self(3)
1736
+ l[2] = self(2)
1737
+ l[3] = self(5)
1738
+ l[4] = self(4)
1739
+ elif j == 0:
1740
+ l[0] = self(-1)
1741
+ l[1] = self(0)
1742
+ l[4] = self(7)
1743
+ l[5] = self(8)
1744
+ return type(self)(self.parent(), l, check=False)
1745
+
1746
+ def apply_simple_reflection_left(self, i) -> AffinePermutationTypeG:
1747
+ r"""
1748
+ Apply simple reflection indexed by `i` on values.
1749
+
1750
+ EXAMPLES::
1751
+
1752
+ sage: G = AffinePermutationGroup(['G',2,1])
1753
+ sage: p = G([2, 10, -5, 12, -3, 5])
1754
+ sage: p.apply_simple_reflection_left(0)
1755
+ Type G affine permutation with window [0, 10, -7, 14, -3, 7]
1756
+ sage: p.apply_simple_reflection_left(1)
1757
+ Type G affine permutation with window [1, 9, -4, 11, -2, 6]
1758
+ sage: p.apply_simple_reflection_left(2)
1759
+ Type G affine permutation with window [3, 11, -5, 12, -4, 4]
1760
+ """
1761
+ if i not in self.parent().index_set():
1762
+ raise ValueError('index not in index set')
1763
+ l = []
1764
+ if i == 1:
1765
+ for m in range(6):
1766
+ res = self[m] % 6
1767
+ if res == 1 or res == 3 or res == 5:
1768
+ l.append(self[m]+1)
1769
+ elif res == 2 or res == 4 or res == 0:
1770
+ l.append(self[m]-1)
1771
+ else:
1772
+ l.append(self[m])
1773
+ elif i == 2:
1774
+ for m in range(6):
1775
+ res = self[m] % 6
1776
+ if res == 2 or res == 4:
1777
+ l.append(self[m]+1)
1778
+ elif res == 3 or res == 5:
1779
+ l.append(self[m]-1)
1780
+ else:
1781
+ l.append(self[m])
1782
+ elif i == 0:
1783
+ for m in range(6):
1784
+ res = self[m] % 6
1785
+ if res == 1 or res == 2:
1786
+ l.append(self[m]-2)
1787
+ elif res == 5 or res == 0:
1788
+ l.append(self[m]+2)
1789
+ else:
1790
+ l.append(self[m])
1791
+ return type(self)(self.parent(), l, check=False)
1792
+
1793
+ def has_right_descent(self, i) -> bool:
1794
+ r"""
1795
+ Determine whether there is a descent at index `i`.
1796
+
1797
+ INPUT:
1798
+
1799
+ - ``i`` -- integer
1800
+
1801
+ EXAMPLES::
1802
+
1803
+ sage: G = AffinePermutationGroup(['G',2,1])
1804
+ sage: p = G([2, 10, -5, 12, -3, 5])
1805
+ sage: [p.has_right_descent(i) for i in G.index_set()]
1806
+ [False, False, True]
1807
+ """
1808
+ if i not in self.parent().index_set():
1809
+ raise ValueError('index not in index set')
1810
+ if i == 0:
1811
+ return self.value(0) > self.value(2)
1812
+ return self.value(i) > self.value(i+1)
1813
+
1814
+ def has_left_descent(self, i) -> bool:
1815
+ r"""
1816
+ Determine whether there is a descent at ``i``.
1817
+
1818
+ INPUT:
1819
+
1820
+ - ``i`` -- integer
1821
+
1822
+ EXAMPLES::
1823
+
1824
+ sage: G = AffinePermutationGroup(['G',2,1])
1825
+ sage: p = G([2, 10, -5, 12, -3, 5])
1826
+ sage: [p.has_left_descent(i) for i in G.index_set()]
1827
+ [False, True, False]
1828
+ """
1829
+ if i not in self.parent().index_set():
1830
+ raise ValueError('index not in index set')
1831
+ if i == 0:
1832
+ return self.position(0) > self.position(2)
1833
+ return self.position(i) > self.position(i+1)
1834
+
1835
+ def to_type_a(self) -> AffinePermutationTypeA:
1836
+ r"""
1837
+ Return an embedding of ``self`` into the affine permutation group of
1838
+ type A.
1839
+
1840
+ EXAMPLES::
1841
+
1842
+ sage: G = AffinePermutationGroup(['G',2,1])
1843
+ sage: p = G([2, 10, -5, 12, -3, 5])
1844
+ sage: p.to_type_a()
1845
+ Type A affine permutation with window [2, 10, -5, 12, -3, 5]
1846
+ """
1847
+ A = AffinePermutationGroup(['A', 5, 1])
1848
+ return A([self.value(i) for i in range(1, 7)])
1849
+
1850
+
1851
+ # -----------------------------------------------------------------------
1852
+ # Class of all affine permutations.
1853
+ # -----------------------------------------------------------------------
1854
+
1855
+ def AffinePermutationGroup(cartan_type):
1856
+ r"""
1857
+ Wrapper function for specific affine permutation groups.
1858
+
1859
+ These are combinatorial implementations of the affine Weyl groups of
1860
+ types `A`, `B`, `C`, `D`, and `G` as permutations of the set of all integers.
1861
+ the basic algorithms are derived from [BB2005]_ and [Eri1995]_.
1862
+
1863
+ EXAMPLES::
1864
+
1865
+ sage: ct = CartanType(['A',7,1])
1866
+ sage: A = AffinePermutationGroup(ct)
1867
+ sage: A
1868
+ The group of affine permutations of type ['A', 7, 1]
1869
+
1870
+ We define an element of ``A``::
1871
+
1872
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
1873
+ sage: p
1874
+ Type A affine permutation with window [3, -1, 0, 6, 5, 4, 10, 9]
1875
+
1876
+ We find the value `p(1)`, considering `p` as a bijection on the integers.
1877
+ This is the same as calling the
1878
+ :meth:`~sage.combinat.affine_permutation.AffinePermutation.value` method::
1879
+
1880
+ sage: p.value(1)
1881
+ 3
1882
+ sage: p(1) == p.value(1)
1883
+ True
1884
+
1885
+ We can also find the position of the integer 3 in `p` considered as a
1886
+ sequence, equivalent to finding `p^{-1}(3)`::
1887
+
1888
+ sage: p.position(3)
1889
+ 1
1890
+ sage: (p^-1)(3)
1891
+ 1
1892
+
1893
+ Since the affine permutation group is a group, we demonstrate its
1894
+ group properties::
1895
+
1896
+ sage: A.one()
1897
+ Type A affine permutation with window [1, 2, 3, 4, 5, 6, 7, 8]
1898
+
1899
+ sage: q = A([0, 2, 3, 4, 5, 6, 7, 9])
1900
+ sage: p * q
1901
+ Type A affine permutation with window [1, -1, 0, 6, 5, 4, 10, 11]
1902
+ sage: q * p
1903
+ Type A affine permutation with window [3, -1, 1, 6, 5, 4, 10, 8]
1904
+
1905
+ sage: p^-1
1906
+ Type A affine permutation with window [0, -1, 1, 6, 5, 4, 10, 11]
1907
+ sage: p^-1 * p == A.one()
1908
+ True
1909
+ sage: p * p^-1 == A.one()
1910
+ True
1911
+
1912
+ If we decide we prefer the Weyl Group implementation of the affine Weyl
1913
+ group, we can easily get it::
1914
+
1915
+ sage: p.to_weyl_group_element()
1916
+ [ 0 -1 0 1 0 0 1 0]
1917
+ [ 1 -1 0 1 0 0 1 -1]
1918
+ [ 1 -1 0 1 0 0 0 0]
1919
+ [ 0 0 0 1 0 0 0 0]
1920
+ [ 0 0 0 1 0 -1 1 0]
1921
+ [ 0 0 0 1 -1 0 1 0]
1922
+ [ 0 0 0 0 0 0 1 0]
1923
+ [ 0 -1 1 0 0 0 1 0]
1924
+
1925
+ We can find a reduced word and do all of the other things one expects in
1926
+ a Coxeter group::
1927
+
1928
+ sage: p.has_right_descent(1)
1929
+ True
1930
+ sage: p.apply_simple_reflection(1)
1931
+ Type A affine permutation with window [-1, 3, 0, 6, 5, 4, 10, 9]
1932
+ sage: p.apply_simple_reflection(0)
1933
+ Type A affine permutation with window [1, -1, 0, 6, 5, 4, 10, 11]
1934
+ sage: p.reduced_word()
1935
+ [0, 7, 4, 1, 0, 7, 5, 4, 2, 1]
1936
+ sage: p.length()
1937
+ 10
1938
+
1939
+ The following methods are particular to type `A`.
1940
+ We can check if the element is fully commutative::
1941
+
1942
+ sage: p.is_fully_commutative()
1943
+ False
1944
+ sage: q.is_fully_commutative()
1945
+ True
1946
+
1947
+ We can also compute the affine Lehmer code of the permutation,
1948
+ a weak composition with `k + 1` entries::
1949
+
1950
+ sage: p.to_lehmer_code()
1951
+ [0, 3, 3, 0, 1, 2, 0, 1]
1952
+
1953
+ Once we have the Lehmer code, we can obtain a `k`-bounded partition by
1954
+ sorting the Lehmer code, and then reading the row lengths.
1955
+ There is a unique 0-Grassmanian (dominant) affine permutation associated
1956
+ to this `k`-bounded partition, and a `k`-core as well. ::
1957
+
1958
+ sage: p.to_bounded_partition()
1959
+ [5, 3, 2]
1960
+ sage: p.to_dominant()
1961
+ Type A affine permutation with window [-2, -1, 1, 3, 4, 8, 10, 13]
1962
+ sage: p.to_core()
1963
+ [5, 3, 2]
1964
+
1965
+ Finally, we can take a reduced word for `p` and insert it to find a
1966
+ standard composition tableau associated uniquely to that word::
1967
+
1968
+ sage: p.tableau_of_word(p.reduced_word())
1969
+ [[], [1, 6, 9], [2, 7, 10], [], [3], [4, 8], [], [5]]
1970
+
1971
+ We can also form affine permutation groups in types `B`, `C`, `D`,
1972
+ and `G`::
1973
+
1974
+ sage: B = AffinePermutationGroup(['B',4,1])
1975
+ sage: B.an_element()
1976
+ Type B affine permutation with window [-1, 3, 4, 11]
1977
+
1978
+ sage: C = AffinePermutationGroup(['C',4,1])
1979
+ sage: C.an_element()
1980
+ Type C affine permutation with window [2, 3, 4, 10]
1981
+
1982
+ sage: D = AffinePermutationGroup(['D',4,1])
1983
+ sage: D.an_element()
1984
+ Type D affine permutation with window [-1, 3, 11, 5]
1985
+
1986
+ sage: G = AffinePermutationGroup(['G',2,1])
1987
+ sage: G.an_element()
1988
+ Type G affine permutation with window [0, 4, -1, 8, 3, 7]
1989
+ """
1990
+ ct = CartanType(cartan_type)
1991
+ if ct.letter == 'A':
1992
+ return AffinePermutationGroupTypeA(ct)
1993
+ if ct.letter == 'B':
1994
+ return AffinePermutationGroupTypeB(ct)
1995
+ if ct.letter == 'C':
1996
+ return AffinePermutationGroupTypeC(ct)
1997
+ if ct.letter == 'D':
1998
+ return AffinePermutationGroupTypeD(ct)
1999
+ if ct.letter == 'G':
2000
+ return AffinePermutationGroupTypeG(ct)
2001
+ raise NotImplementedError('Cartan type provided is not implemented as an affine permutation group')
2002
+
2003
+
2004
+ class AffinePermutationGroupGeneric(UniqueRepresentation, Parent):
2005
+ """
2006
+ The generic affine permutation group class, in which we define all type-free
2007
+ methods for the specific affine permutation groups.
2008
+
2009
+ TESTS::
2010
+
2011
+ sage: AffinePermutationGroup(['A',7,1])([3, -1, 0, 6, 5, 4, 10, 9])
2012
+ Type A affine permutation with window [3, -1, 0, 6, 5, 4, 10, 9]
2013
+ """
2014
+ # ----------------------
2015
+ # Type-free methods.
2016
+ # ----------------------
2017
+
2018
+ def __init__(self, cartan_type) -> None:
2019
+ r"""
2020
+ TESTS::
2021
+
2022
+ sage: AffinePermutationGroup(['A',7,1])
2023
+ The group of affine permutations of type ['A', 7, 1]
2024
+ """
2025
+ Parent.__init__(self, category=AffineWeylGroups())
2026
+ ct = CartanType(cartan_type)
2027
+ self.k = Integer(ct.n)
2028
+ self.n = ct.rank()
2029
+ # This N doesn't matter for type A, but comes up in all other types.
2030
+ if ct.letter == 'A':
2031
+ self.N = self.k + 1
2032
+ elif ct.letter == 'B' or ct.letter == 'C' or ct.letter == 'D':
2033
+ self.N = 2 * self.k + 1
2034
+ elif ct.letter == 'G':
2035
+ self.N = 6
2036
+ self._cartan_type = ct
2037
+
2038
+ def _repr_(self) -> str:
2039
+ r"""
2040
+ TESTS::
2041
+
2042
+ sage: AffinePermutationGroup(['A',7,1])
2043
+ The group of affine permutations of type ['A', 7, 1]
2044
+ """
2045
+ return "The group of affine permutations of type " + str(self.cartan_type())
2046
+
2047
+ def _test_enumeration(self, n=4, **options):
2048
+ r"""
2049
+ Test that ``self`` has same number of elements of length ``n`` as the
2050
+ Weyl Group implementation.
2051
+
2052
+ Combined with ``self._test_coxeter_relations`` this shows isomorphism
2053
+ up to length ``n``.
2054
+
2055
+ TESTS::
2056
+
2057
+ sage: A = AffinePermutationGroup(['A',7,1])
2058
+ sage: A._test_enumeration(3)
2059
+ """
2060
+ tester = self._tester(**options)
2061
+ n1 = len(list(self.elements_of_length(n)))
2062
+ W = self.weyl_group()
2063
+ I = W.weak_order_ideal(ConstantFunction(True), side='right')
2064
+ n2 = len(list(I.elements_of_depth_iterator(n)))
2065
+ tester.assertEqual(n1, n2, "number of (ranked) elements of affine"
2066
+ " permutation group disagrees with Weyl group")
2067
+
2068
+ def weyl_group(self):
2069
+ r"""
2070
+ Return the Weyl Group of the same type as ``self``.
2071
+
2072
+ EXAMPLES::
2073
+
2074
+ sage: A = AffinePermutationGroup(['A',7,1])
2075
+ sage: A.weyl_group()
2076
+ Weyl Group of type ['A', 7, 1] (as a matrix group acting on the root space)
2077
+ """
2078
+ return WeylGroup(self._cartan_type)
2079
+
2080
+ def classical(self):
2081
+ r"""
2082
+ Return the finite permutation group.
2083
+
2084
+ EXAMPLES::
2085
+
2086
+ sage: A = AffinePermutationGroup(['A',7,1])
2087
+ sage: A.classical()
2088
+ Symmetric group of order 8! as a permutation group
2089
+ """
2090
+ if self._cartan_type.letter == 'A':
2091
+ return SymmetricGroup(self.k+1)
2092
+ return WeylGroup(self._cartan_type.classical())
2093
+
2094
+ def cartan_type(self):
2095
+ r"""
2096
+ Return the Cartan type of ``self``.
2097
+
2098
+ EXAMPLES::
2099
+
2100
+ sage: AffinePermutationGroup(['A',7,1]).cartan_type()
2101
+ ['A', 7, 1]
2102
+ """
2103
+ return self._cartan_type
2104
+
2105
+ def cartan_matrix(self):
2106
+ r"""
2107
+ Return the Cartan matrix of ``self``.
2108
+
2109
+ EXAMPLES::
2110
+
2111
+ sage: AffinePermutationGroup(['A',7,1]).cartan_matrix()
2112
+ [ 2 -1 0 0 0 0 0 -1]
2113
+ [-1 2 -1 0 0 0 0 0]
2114
+ [ 0 -1 2 -1 0 0 0 0]
2115
+ [ 0 0 -1 2 -1 0 0 0]
2116
+ [ 0 0 0 -1 2 -1 0 0]
2117
+ [ 0 0 0 0 -1 2 -1 0]
2118
+ [ 0 0 0 0 0 -1 2 -1]
2119
+ [-1 0 0 0 0 0 -1 2]
2120
+ """
2121
+ return self.cartan_type().cartan_matrix()
2122
+
2123
+ def is_crystallographic(self) -> bool:
2124
+ r"""
2125
+ Tell whether the affine permutation group is crystallographic.
2126
+
2127
+ EXAMPLES::
2128
+
2129
+ sage: AffinePermutationGroup(['A',7,1]).is_crystallographic()
2130
+ True
2131
+ """
2132
+ return self.cartan_type().is_crystallographic()
2133
+
2134
+ def index_set(self):
2135
+ r"""
2136
+ EXAMPLES::
2137
+
2138
+ sage: AffinePermutationGroup(['A',7,1]).index_set()
2139
+ (0, 1, 2, 3, 4, 5, 6, 7)
2140
+ """
2141
+ return self.cartan_type().index_set()
2142
+
2143
+ _index_set = index_set
2144
+
2145
+ def reflection_index_set(self):
2146
+ r"""
2147
+ EXAMPLES::
2148
+
2149
+ sage: AffinePermutationGroup(['A',7,1]).reflection_index_set()
2150
+ (0, 1, 2, 3, 4, 5, 6, 7)
2151
+ """
2152
+ return self.cartan_type().index_set()
2153
+
2154
+ def rank(self):
2155
+ r"""
2156
+ Rank of the affine permutation group, equal to `k+1`.
2157
+
2158
+ EXAMPLES::
2159
+
2160
+ sage: AffinePermutationGroup(['A',7,1]).rank()
2161
+ 8
2162
+ """
2163
+ return self.k + 1
2164
+
2165
+ def random_element(self, n=None) -> AffinePermutation:
2166
+ r"""
2167
+ Return a random affine permutation of length ``n``.
2168
+
2169
+ If ``n`` is not specified, then ``n`` is chosen as a random
2170
+ nonnegative integer in `[0, 1000]`.
2171
+
2172
+ Starts at the identity, then chooses an upper cover at random.
2173
+ Not very uniform: actually constructs a uniformly random reduced word
2174
+ of length `n`. Thus we most likely get elements with lots of reduced
2175
+ words!
2176
+
2177
+ For the actual code, see
2178
+ :meth:`sage.categories.coxeter_group.random_element_of_length`.
2179
+
2180
+ EXAMPLES::
2181
+
2182
+ sage: A = AffinePermutationGroup(['A',7,1])
2183
+ sage: A.random_element() # random
2184
+ Type A affine permutation with window [-12, 16, 19, -1, -2, 10, -3, 9]
2185
+ sage: p = A.random_element(10)
2186
+ sage: p.length() == 10
2187
+ True
2188
+ """
2189
+ if n is None:
2190
+ n = randint(0, 1000)
2191
+ return self.random_element_of_length(n)
2192
+
2193
+ def from_word(self, w) -> AffinePermutation:
2194
+ r"""
2195
+ Build an affine permutation from a given word.
2196
+ Note: Already in category as ``from_reduced_word``, but this is less
2197
+ typing!
2198
+
2199
+ EXAMPLES::
2200
+
2201
+ sage: A = AffinePermutationGroup(['A',7,1])
2202
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
2203
+ sage: A.from_word([0, 7, 4, 1, 0, 7, 5, 4, 2, 1])
2204
+ Type A affine permutation with window [3, -1, 0, 6, 5, 4, 10, 9]
2205
+ """
2206
+ return self.from_reduced_word(w)
2207
+
2208
+ @cached_method
2209
+ def _an_element_(self) -> AffinePermutation:
2210
+ r"""
2211
+ Return a Coxeter element.
2212
+
2213
+ EXAMPLES::
2214
+
2215
+ sage: A = AffinePermutationGroup(['A',7,1])
2216
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
2217
+ sage: A.from_word([0, 7, 4, 1, 0, 7, 5, 4, 2, 1])
2218
+ Type A affine permutation with window [3, -1, 0, 6, 5, 4, 10, 9]
2219
+ """
2220
+ return self.from_reduced_word(self.index_set())
2221
+
2222
+
2223
+ class AffinePermutationGroupTypeA(AffinePermutationGroupGeneric):
2224
+ # ------------------------
2225
+ # Type-specific methods.
2226
+ # (Methods in all types, but with specific definition.)
2227
+ # ------------------------
2228
+
2229
+ @cached_method
2230
+ def one(self) -> AffinePermutation:
2231
+ r"""
2232
+ Return the identity element.
2233
+
2234
+ EXAMPLES::
2235
+
2236
+ sage: AffinePermutationGroup(['A',7,1]).one()
2237
+ Type A affine permutation with window [1, 2, 3, 4, 5, 6, 7, 8]
2238
+
2239
+ TESTS::
2240
+
2241
+ sage: A = AffinePermutationGroup(['A',5,1])
2242
+ sage: A == loads(dumps(A))
2243
+ True
2244
+ sage: TestSuite(A).run()
2245
+ """
2246
+ return self(range(1, self.k + 2))
2247
+
2248
+ # ------------------------
2249
+ # Type-unique methods.
2250
+ # (Methods which do not exist in all types.)
2251
+ # ------------------------
2252
+ def from_lehmer_code(self, C, typ='decreasing',
2253
+ side='right') -> AffinePermutation:
2254
+ r"""
2255
+ Return the affine permutation with the supplied Lehmer code (a weak
2256
+ composition with `k+1` parts, at least one of which is 0).
2257
+
2258
+ INPUT:
2259
+
2260
+ - ``typ`` -- ``'increasing'`` or ``'decreasing'``
2261
+ (default: ``'decreasing'``); type of product
2262
+ - ``side`` -- ``'right'`` or ``'left'`` (default: ``'right'``);
2263
+ whether the decomposition is from the right or left
2264
+
2265
+ EXAMPLES::
2266
+
2267
+ sage: import itertools
2268
+ sage: A = AffinePermutationGroup(['A',7,1])
2269
+ sage: p = A([3, -1, 0, 6, 5, 4, 10, 9])
2270
+ sage: p.to_lehmer_code()
2271
+ [0, 3, 3, 0, 1, 2, 0, 1]
2272
+ sage: A.from_lehmer_code(p.to_lehmer_code()) == p
2273
+ True
2274
+ sage: orders = ('increasing','decreasing')
2275
+ sage: sides = ('left','right')
2276
+ sage: all(A.from_lehmer_code(p.to_lehmer_code(o,s),o,s) == p
2277
+ ....: for o,s in itertools.product(orders,sides))
2278
+ True
2279
+ """
2280
+ if len(C) - 1 != self.k:
2281
+ raise ValueError("composition must have {} entries".format(self.k+1))
2282
+ if 0 not in C:
2283
+ raise ValueError("composition must contain a zero entry")
2284
+ k = self.k
2285
+ # Find a zero entry in C.
2286
+ for r in range(self.k+1):
2287
+ if C[r] == 0:
2288
+ break
2289
+ D = list(C)
2290
+ # The s0 and t0 are +-1, dependent on typ and side.
2291
+ if (typ[0], side[0]) == ('d', 'r'):
2292
+ t0, s0 = (-1, 1)
2293
+ elif (typ[0], side[0]) == ('i', 'r'):
2294
+ t0, s0 = (1, 1)
2295
+ elif (typ[0], side[0]) == ('d', 'l'):
2296
+ t0, s0 = (-1, -1)
2297
+ elif (typ[0], side[0]) == ('i', 'l'):
2298
+ t0, s0 = (1, -1)
2299
+ else:
2300
+ raise RuntimeError
2301
+ row = 0
2302
+ # Method is to build a reduced word from the composition.
2303
+ # We create a list of cyclically in/decreasing words appearing in
2304
+ # the decomposition corresponding to the composition C,
2305
+ # and then build the element.
2306
+ listy = []
2307
+ while sum(D) > 0:
2308
+ l = ['x'] * (self.k + 1)
2309
+ ll = []
2310
+ # read off a row of C.
2311
+ for j in range(self.k+1):
2312
+ pos = (r + s0*t0*j) % (k+1)
2313
+ residue = (r + s0*t0*(row + j)) % (k+1)
2314
+ if D[pos] != 0:
2315
+ ll.append(residue)
2316
+ l[pos] = [residue]
2317
+ D[pos] -= 1
2318
+ if side[0] == 'l':
2319
+ ll.reverse()
2320
+ listy.append(ll)
2321
+ row += 1
2322
+ if side[0] == 'r':
2323
+ listy.reverse()
2324
+ x = self.one()
2325
+ for ll in listy:
2326
+ for i in ll:
2327
+ x = x.apply_simple_reflection_right(i)
2328
+ return x
2329
+
2330
+ Element = AffinePermutationTypeA
2331
+
2332
+
2333
+ class AffinePermutationGroupTypeC(AffinePermutationGroupGeneric):
2334
+ # ------------------------
2335
+ # Type-specific methods.
2336
+ # (Methods in all types, but with specific definition.)
2337
+ # ------------------------
2338
+
2339
+ @cached_method
2340
+ def one(self) -> AffinePermutation:
2341
+ r"""
2342
+ Return the identity element.
2343
+
2344
+ EXAMPLES::
2345
+
2346
+ sage: ct = CartanType(['C',4,1])
2347
+ sage: C = AffinePermutationGroup(ct)
2348
+ sage: C.one()
2349
+ Type C affine permutation with window [1, 2, 3, 4]
2350
+ sage: C.one()*C.one()==C.one()
2351
+ True
2352
+
2353
+ TESTS::
2354
+
2355
+ sage: C = AffinePermutationGroup(['C',4,1])
2356
+ sage: C == loads(dumps(C))
2357
+ True
2358
+ sage: TestSuite(C).run()
2359
+ """
2360
+ return self(range(1, self.k + 1))
2361
+
2362
+ Element = AffinePermutationTypeC
2363
+
2364
+
2365
+ class AffinePermutationGroupTypeB(AffinePermutationGroupTypeC):
2366
+ # ------------------------
2367
+ # Type-specific methods.
2368
+ # (Methods in all types, but with specific definition.)
2369
+ # ------------------------
2370
+ Element = AffinePermutationTypeB
2371
+
2372
+
2373
+ class AffinePermutationGroupTypeD(AffinePermutationGroupTypeC):
2374
+ # ------------------------
2375
+ # Type-specific methods.
2376
+ # (Methods in all types, but with specific definition.)
2377
+ # ------------------------
2378
+ Element = AffinePermutationTypeD
2379
+
2380
+
2381
+ class AffinePermutationGroupTypeG(AffinePermutationGroupGeneric):
2382
+ # ------------------------
2383
+ # Type-specific methods.
2384
+ # (Methods in all types, but with specific definition.)
2385
+ # ------------------------
2386
+ @cached_method
2387
+ def one(self) -> AffinePermutation:
2388
+ r"""
2389
+ Return the identity element.
2390
+
2391
+ EXAMPLES::
2392
+
2393
+ sage: AffinePermutationGroup(['G',2,1]).one()
2394
+ Type G affine permutation with window [1, 2, 3, 4, 5, 6]
2395
+
2396
+ TESTS::
2397
+
2398
+ sage: G = AffinePermutationGroup(['G',2,1])
2399
+ sage: G == loads(dumps(G))
2400
+ True
2401
+ sage: TestSuite(G).run()
2402
+ """
2403
+ return self([1, 2, 3, 4, 5, 6])
2404
+
2405
+ Element = AffinePermutationTypeG