passagemath-categories 10.6.32__cp314-cp314t-musllinux_1_2_aarch64.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 (719) hide show
  1. passagemath_categories-10.6.32.dist-info/METADATA +156 -0
  2. passagemath_categories-10.6.32.dist-info/RECORD +719 -0
  3. passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
  4. passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
  5. passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
  6. passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
  7. passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
  8. sage/all__sagemath_categories.py +28 -0
  9. sage/arith/all.py +38 -0
  10. sage/arith/constants.pxd +27 -0
  11. sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
  12. sage/arith/functions.pxd +4 -0
  13. sage/arith/functions.pyx +221 -0
  14. sage/arith/misc.py +6552 -0
  15. sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
  16. sage/arith/multi_modular.pxd +39 -0
  17. sage/arith/multi_modular.pyx +994 -0
  18. sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
  19. sage/arith/rational_reconstruction.pxd +4 -0
  20. sage/arith/rational_reconstruction.pyx +115 -0
  21. sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
  22. sage/arith/srange.pyx +571 -0
  23. sage/calculus/all__sagemath_categories.py +2 -0
  24. sage/calculus/functional.py +481 -0
  25. sage/calculus/functions.py +151 -0
  26. sage/categories/additive_groups.py +73 -0
  27. sage/categories/additive_magmas.py +1044 -0
  28. sage/categories/additive_monoids.py +114 -0
  29. sage/categories/additive_semigroups.py +184 -0
  30. sage/categories/affine_weyl_groups.py +238 -0
  31. sage/categories/algebra_ideals.py +95 -0
  32. sage/categories/algebra_modules.py +96 -0
  33. sage/categories/algebras.py +349 -0
  34. sage/categories/algebras_with_basis.py +377 -0
  35. sage/categories/all.py +160 -0
  36. sage/categories/aperiodic_semigroups.py +29 -0
  37. sage/categories/associative_algebras.py +47 -0
  38. sage/categories/bialgebras.py +101 -0
  39. sage/categories/bialgebras_with_basis.py +414 -0
  40. sage/categories/bimodules.py +206 -0
  41. sage/categories/chain_complexes.py +268 -0
  42. sage/categories/classical_crystals.py +480 -0
  43. sage/categories/coalgebras.py +405 -0
  44. sage/categories/coalgebras_with_basis.py +232 -0
  45. sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
  46. sage/categories/coercion_methods.pyx +52 -0
  47. sage/categories/commutative_additive_groups.py +104 -0
  48. sage/categories/commutative_additive_monoids.py +45 -0
  49. sage/categories/commutative_additive_semigroups.py +48 -0
  50. sage/categories/commutative_algebra_ideals.py +87 -0
  51. sage/categories/commutative_algebras.py +94 -0
  52. sage/categories/commutative_ring_ideals.py +58 -0
  53. sage/categories/commutative_rings.py +736 -0
  54. sage/categories/complete_discrete_valuation.py +293 -0
  55. sage/categories/complex_reflection_groups.py +145 -0
  56. sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
  57. sage/categories/coxeter_group_algebras.py +186 -0
  58. sage/categories/coxeter_groups.py +3402 -0
  59. sage/categories/crystals.py +2628 -0
  60. sage/categories/cw_complexes.py +216 -0
  61. sage/categories/dedekind_domains.py +137 -0
  62. sage/categories/discrete_valuation.py +325 -0
  63. sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
  64. sage/categories/division_rings.py +114 -0
  65. sage/categories/domains.py +95 -0
  66. sage/categories/drinfeld_modules.py +789 -0
  67. sage/categories/dual.py +42 -0
  68. sage/categories/enumerated_sets.py +1146 -0
  69. sage/categories/euclidean_domains.py +271 -0
  70. sage/categories/examples/algebras_with_basis.py +102 -0
  71. sage/categories/examples/all.py +1 -0
  72. sage/categories/examples/commutative_additive_monoids.py +130 -0
  73. sage/categories/examples/commutative_additive_semigroups.py +199 -0
  74. sage/categories/examples/coxeter_groups.py +8 -0
  75. sage/categories/examples/crystals.py +236 -0
  76. sage/categories/examples/cw_complexes.py +163 -0
  77. sage/categories/examples/facade_sets.py +187 -0
  78. sage/categories/examples/filtered_algebras_with_basis.py +204 -0
  79. sage/categories/examples/filtered_modules_with_basis.py +154 -0
  80. sage/categories/examples/finite_coxeter_groups.py +252 -0
  81. sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
  82. sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
  83. sage/categories/examples/finite_enumerated_sets.py +208 -0
  84. sage/categories/examples/finite_monoids.py +150 -0
  85. sage/categories/examples/finite_semigroups.py +190 -0
  86. sage/categories/examples/finite_weyl_groups.py +191 -0
  87. sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
  88. sage/categories/examples/graded_modules_with_basis.py +168 -0
  89. sage/categories/examples/graphs.py +122 -0
  90. sage/categories/examples/hopf_algebras_with_basis.py +145 -0
  91. sage/categories/examples/infinite_enumerated_sets.py +190 -0
  92. sage/categories/examples/lie_algebras.py +352 -0
  93. sage/categories/examples/lie_algebras_with_basis.py +196 -0
  94. sage/categories/examples/magmas.py +162 -0
  95. sage/categories/examples/manifolds.py +94 -0
  96. sage/categories/examples/monoids.py +144 -0
  97. sage/categories/examples/posets.py +178 -0
  98. sage/categories/examples/semigroups.py +580 -0
  99. sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  100. sage/categories/examples/semigroups_cython.pyx +221 -0
  101. sage/categories/examples/semirings.py +249 -0
  102. sage/categories/examples/sets_cat.py +706 -0
  103. sage/categories/examples/sets_with_grading.py +101 -0
  104. sage/categories/examples/with_realizations.py +542 -0
  105. sage/categories/fields.py +991 -0
  106. sage/categories/filtered_algebras.py +63 -0
  107. sage/categories/filtered_algebras_with_basis.py +548 -0
  108. sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
  109. sage/categories/filtered_modules.py +210 -0
  110. sage/categories/filtered_modules_with_basis.py +1209 -0
  111. sage/categories/finite_complex_reflection_groups.py +1506 -0
  112. sage/categories/finite_coxeter_groups.py +1138 -0
  113. sage/categories/finite_crystals.py +103 -0
  114. sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
  115. sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
  116. sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
  117. sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
  118. sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
  119. sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
  120. sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
  121. sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
  122. sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
  123. sage/categories/finite_enumerated_sets.py +769 -0
  124. sage/categories/finite_fields.py +252 -0
  125. sage/categories/finite_groups.py +256 -0
  126. sage/categories/finite_lattice_posets.py +242 -0
  127. sage/categories/finite_monoids.py +316 -0
  128. sage/categories/finite_permutation_groups.py +339 -0
  129. sage/categories/finite_posets.py +1994 -0
  130. sage/categories/finite_semigroups.py +136 -0
  131. sage/categories/finite_sets.py +93 -0
  132. sage/categories/finite_weyl_groups.py +39 -0
  133. sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
  134. sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
  135. sage/categories/finitely_generated_magmas.py +57 -0
  136. sage/categories/finitely_generated_semigroups.py +214 -0
  137. sage/categories/function_fields.py +76 -0
  138. sage/categories/g_sets.py +77 -0
  139. sage/categories/gcd_domains.py +65 -0
  140. sage/categories/generalized_coxeter_groups.py +94 -0
  141. sage/categories/graded_algebras.py +85 -0
  142. sage/categories/graded_algebras_with_basis.py +258 -0
  143. sage/categories/graded_bialgebras.py +32 -0
  144. sage/categories/graded_bialgebras_with_basis.py +32 -0
  145. sage/categories/graded_coalgebras.py +65 -0
  146. sage/categories/graded_coalgebras_with_basis.py +51 -0
  147. sage/categories/graded_hopf_algebras.py +41 -0
  148. sage/categories/graded_hopf_algebras_with_basis.py +169 -0
  149. sage/categories/graded_lie_algebras.py +91 -0
  150. sage/categories/graded_lie_algebras_with_basis.py +44 -0
  151. sage/categories/graded_lie_conformal_algebras.py +74 -0
  152. sage/categories/graded_modules.py +133 -0
  153. sage/categories/graded_modules_with_basis.py +329 -0
  154. sage/categories/graphs.py +138 -0
  155. sage/categories/group_algebras.py +430 -0
  156. sage/categories/groupoid.py +94 -0
  157. sage/categories/groups.py +667 -0
  158. sage/categories/h_trivial_semigroups.py +64 -0
  159. sage/categories/hecke_modules.py +185 -0
  160. sage/categories/highest_weight_crystals.py +980 -0
  161. sage/categories/hopf_algebras.py +219 -0
  162. sage/categories/hopf_algebras_with_basis.py +309 -0
  163. sage/categories/infinite_enumerated_sets.py +115 -0
  164. sage/categories/integral_domains.py +203 -0
  165. sage/categories/j_trivial_semigroups.py +29 -0
  166. sage/categories/kac_moody_algebras.py +82 -0
  167. sage/categories/kahler_algebras.py +203 -0
  168. sage/categories/l_trivial_semigroups.py +63 -0
  169. sage/categories/lambda_bracket_algebras.py +280 -0
  170. sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
  171. sage/categories/lattice_posets.py +89 -0
  172. sage/categories/left_modules.py +49 -0
  173. sage/categories/lie_algebras.py +1070 -0
  174. sage/categories/lie_algebras_with_basis.py +261 -0
  175. sage/categories/lie_conformal_algebras.py +350 -0
  176. sage/categories/lie_conformal_algebras_with_basis.py +147 -0
  177. sage/categories/lie_groups.py +73 -0
  178. sage/categories/loop_crystals.py +1290 -0
  179. sage/categories/magmas.py +1189 -0
  180. sage/categories/magmas_and_additive_magmas.py +149 -0
  181. sage/categories/magmatic_algebras.py +365 -0
  182. sage/categories/manifolds.py +352 -0
  183. sage/categories/matrix_algebras.py +40 -0
  184. sage/categories/metric_spaces.py +387 -0
  185. sage/categories/modular_abelian_varieties.py +78 -0
  186. sage/categories/modules.py +989 -0
  187. sage/categories/modules_with_basis.py +2794 -0
  188. sage/categories/monoid_algebras.py +38 -0
  189. sage/categories/monoids.py +739 -0
  190. sage/categories/noetherian_rings.py +87 -0
  191. sage/categories/number_fields.py +242 -0
  192. sage/categories/ore_modules.py +189 -0
  193. sage/categories/partially_ordered_monoids.py +49 -0
  194. sage/categories/permutation_groups.py +63 -0
  195. sage/categories/pointed_sets.py +42 -0
  196. sage/categories/polyhedra.py +74 -0
  197. sage/categories/poor_man_map.py +270 -0
  198. sage/categories/posets.py +722 -0
  199. sage/categories/principal_ideal_domains.py +270 -0
  200. sage/categories/quantum_group_representations.py +543 -0
  201. sage/categories/quotient_fields.py +728 -0
  202. sage/categories/r_trivial_semigroups.py +45 -0
  203. sage/categories/regular_crystals.py +898 -0
  204. sage/categories/regular_supercrystals.py +170 -0
  205. sage/categories/right_modules.py +49 -0
  206. sage/categories/ring_ideals.py +74 -0
  207. sage/categories/rings.py +1904 -0
  208. sage/categories/rngs.py +175 -0
  209. sage/categories/schemes.py +393 -0
  210. sage/categories/semigroups.py +1060 -0
  211. sage/categories/semirings.py +71 -0
  212. sage/categories/semisimple_algebras.py +114 -0
  213. sage/categories/sets_with_grading.py +235 -0
  214. sage/categories/shephard_groups.py +43 -0
  215. sage/categories/signed_tensor.py +120 -0
  216. sage/categories/simplicial_complexes.py +134 -0
  217. sage/categories/simplicial_sets.py +1206 -0
  218. sage/categories/super_algebras.py +149 -0
  219. sage/categories/super_algebras_with_basis.py +144 -0
  220. sage/categories/super_hopf_algebras_with_basis.py +126 -0
  221. sage/categories/super_lie_conformal_algebras.py +193 -0
  222. sage/categories/super_modules.py +229 -0
  223. sage/categories/super_modules_with_basis.py +193 -0
  224. sage/categories/supercommutative_algebras.py +99 -0
  225. sage/categories/supercrystals.py +406 -0
  226. sage/categories/tensor.py +110 -0
  227. sage/categories/topological_spaces.py +170 -0
  228. sage/categories/triangular_kac_moody_algebras.py +439 -0
  229. sage/categories/tutorial.py +58 -0
  230. sage/categories/unique_factorization_domains.py +318 -0
  231. sage/categories/unital_algebras.py +426 -0
  232. sage/categories/vector_bundles.py +159 -0
  233. sage/categories/vector_spaces.py +357 -0
  234. sage/categories/weyl_groups.py +853 -0
  235. sage/combinat/all__sagemath_categories.py +34 -0
  236. sage/combinat/backtrack.py +180 -0
  237. sage/combinat/combinat.py +2269 -0
  238. sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  239. sage/combinat/combinat_cython.pxd +6 -0
  240. sage/combinat/combinat_cython.pyx +390 -0
  241. sage/combinat/combination.py +796 -0
  242. sage/combinat/combinatorial_map.py +416 -0
  243. sage/combinat/composition.py +2192 -0
  244. sage/combinat/dlx.py +510 -0
  245. sage/combinat/integer_lists/__init__.py +7 -0
  246. sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
  247. sage/combinat/integer_lists/base.pxd +16 -0
  248. sage/combinat/integer_lists/base.pyx +713 -0
  249. sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
  250. sage/combinat/integer_lists/invlex.pxd +4 -0
  251. sage/combinat/integer_lists/invlex.pyx +1650 -0
  252. sage/combinat/integer_lists/lists.py +328 -0
  253. sage/combinat/integer_lists/nn.py +48 -0
  254. sage/combinat/integer_vector.py +1818 -0
  255. sage/combinat/integer_vector_weighted.py +413 -0
  256. sage/combinat/matrices/all__sagemath_categories.py +5 -0
  257. sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
  258. sage/combinat/matrices/dancing_links.pyx +1159 -0
  259. sage/combinat/matrices/dancing_links_c.h +380 -0
  260. sage/combinat/matrices/dlxcpp.py +136 -0
  261. sage/combinat/partition.py +10070 -0
  262. sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
  263. sage/combinat/partitions.pyx +743 -0
  264. sage/combinat/permutation.py +10168 -0
  265. sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  266. sage/combinat/permutation_cython.pxd +11 -0
  267. sage/combinat/permutation_cython.pyx +407 -0
  268. sage/combinat/q_analogues.py +1090 -0
  269. sage/combinat/ranker.py +268 -0
  270. sage/combinat/subset.py +1561 -0
  271. sage/combinat/subsets_hereditary.py +202 -0
  272. sage/combinat/subsets_pairwise.py +184 -0
  273. sage/combinat/tools.py +63 -0
  274. sage/combinat/tuple.py +348 -0
  275. sage/data_structures/all.py +2 -0
  276. sage/data_structures/all__sagemath_categories.py +2 -0
  277. sage/data_structures/binary_matrix.pxd +138 -0
  278. sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
  279. sage/data_structures/binary_search.pxd +3 -0
  280. sage/data_structures/binary_search.pyx +66 -0
  281. sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
  282. sage/data_structures/bitset.pxd +40 -0
  283. sage/data_structures/bitset.pyx +2385 -0
  284. sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
  285. sage/data_structures/bitset_base.pxd +926 -0
  286. sage/data_structures/bitset_base.pyx +117 -0
  287. sage/data_structures/bitset_intrinsics.h +487 -0
  288. sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  289. sage/data_structures/blas_dict.pxd +12 -0
  290. sage/data_structures/blas_dict.pyx +469 -0
  291. sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
  292. sage/data_structures/list_of_pairs.pxd +16 -0
  293. sage/data_structures/list_of_pairs.pyx +122 -0
  294. sage/data_structures/mutable_poset.py +3312 -0
  295. sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
  296. sage/data_structures/pairing_heap.h +346 -0
  297. sage/data_structures/pairing_heap.pxd +88 -0
  298. sage/data_structures/pairing_heap.pyx +1464 -0
  299. sage/data_structures/sparse_bitset.pxd +62 -0
  300. sage/data_structures/stream.py +5070 -0
  301. sage/databases/all__sagemath_categories.py +7 -0
  302. sage/databases/sql_db.py +2236 -0
  303. sage/ext/all__sagemath_categories.py +3 -0
  304. sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
  305. sage/ext/fast_callable.pxd +4 -0
  306. sage/ext/fast_callable.pyx +2746 -0
  307. sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
  308. sage/ext/fast_eval.pxd +1 -0
  309. sage/ext/fast_eval.pyx +102 -0
  310. sage/ext/interpreters/__init__.py +1 -0
  311. sage/ext/interpreters/all__sagemath_categories.py +2 -0
  312. sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
  313. sage/ext/interpreters/wrapper_el.pxd +18 -0
  314. sage/ext/interpreters/wrapper_el.pyx +148 -0
  315. sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
  316. sage/ext/interpreters/wrapper_py.pxd +17 -0
  317. sage/ext/interpreters/wrapper_py.pyx +133 -0
  318. sage/functions/airy.py +937 -0
  319. sage/functions/all.py +97 -0
  320. sage/functions/bessel.py +2102 -0
  321. sage/functions/error.py +784 -0
  322. sage/functions/exp_integral.py +1529 -0
  323. sage/functions/gamma.py +1087 -0
  324. sage/functions/generalized.py +672 -0
  325. sage/functions/hyperbolic.py +747 -0
  326. sage/functions/hypergeometric.py +1156 -0
  327. sage/functions/jacobi.py +1705 -0
  328. sage/functions/log.py +1402 -0
  329. sage/functions/min_max.py +338 -0
  330. sage/functions/orthogonal_polys.py +3106 -0
  331. sage/functions/other.py +2303 -0
  332. sage/functions/piecewise.py +1505 -0
  333. sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
  334. sage/functions/prime_pi.pyx +262 -0
  335. sage/functions/special.py +1212 -0
  336. sage/functions/spike_function.py +278 -0
  337. sage/functions/transcendental.py +690 -0
  338. sage/functions/trig.py +1062 -0
  339. sage/functions/wigner.py +726 -0
  340. sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  341. sage/geometry/abc.pyx +82 -0
  342. sage/geometry/all__sagemath_categories.py +1 -0
  343. sage/groups/all__sagemath_categories.py +11 -0
  344. sage/groups/generic.py +1733 -0
  345. sage/groups/groups_catalog.py +113 -0
  346. sage/groups/perm_gps/all__sagemath_categories.py +1 -0
  347. sage/groups/perm_gps/partn_ref/all.py +1 -0
  348. sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
  349. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
  350. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
  351. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
  352. sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
  353. sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
  354. sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
  355. sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
  356. sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
  357. sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
  358. sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
  359. sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
  360. sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
  361. sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
  362. sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
  363. sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
  364. sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
  365. sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
  366. sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
  367. sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
  368. sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
  369. sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
  370. sage/interfaces/abc.py +140 -0
  371. sage/interfaces/all.py +58 -0
  372. sage/interfaces/all__sagemath_categories.py +1 -0
  373. sage/interfaces/expect.py +1643 -0
  374. sage/interfaces/interface.py +1682 -0
  375. sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
  376. sage/interfaces/process.pxd +5 -0
  377. sage/interfaces/process.pyx +288 -0
  378. sage/interfaces/quit.py +167 -0
  379. sage/interfaces/sage0.py +604 -0
  380. sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
  381. sage/interfaces/sagespawn.pyx +308 -0
  382. sage/interfaces/tab_completion.py +101 -0
  383. sage/misc/all__sagemath_categories.py +78 -0
  384. sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
  385. sage/misc/allocator.pxd +6 -0
  386. sage/misc/allocator.pyx +47 -0
  387. sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
  388. sage/misc/binary_tree.pxd +29 -0
  389. sage/misc/binary_tree.pyx +537 -0
  390. sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  391. sage/misc/callable_dict.pyx +89 -0
  392. sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
  393. sage/misc/citation.pyx +159 -0
  394. sage/misc/converting_dict.py +293 -0
  395. sage/misc/defaults.py +129 -0
  396. sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
  397. sage/misc/derivative.pyx +223 -0
  398. sage/misc/functional.py +2005 -0
  399. sage/misc/html.py +589 -0
  400. sage/misc/latex.py +2673 -0
  401. sage/misc/latex_macros.py +236 -0
  402. sage/misc/latex_standalone.py +1833 -0
  403. sage/misc/map_threaded.py +38 -0
  404. sage/misc/mathml.py +76 -0
  405. sage/misc/method_decorator.py +88 -0
  406. sage/misc/mrange.py +755 -0
  407. sage/misc/multireplace.py +41 -0
  408. sage/misc/object_multiplexer.py +92 -0
  409. sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
  410. sage/misc/parser.pyx +1107 -0
  411. sage/misc/random_testing.py +264 -0
  412. sage/misc/rest_index_of_methods.py +377 -0
  413. sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
  414. sage/misc/search.pxd +2 -0
  415. sage/misc/search.pyx +68 -0
  416. sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
  417. sage/misc/stopgap.pyx +95 -0
  418. sage/misc/table.py +853 -0
  419. sage/monoids/all__sagemath_categories.py +1 -0
  420. sage/monoids/indexed_free_monoid.py +1071 -0
  421. sage/monoids/monoid.py +82 -0
  422. sage/numerical/all__sagemath_categories.py +1 -0
  423. sage/numerical/backends/all__sagemath_categories.py +1 -0
  424. sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  425. sage/numerical/backends/generic_backend.pxd +61 -0
  426. sage/numerical/backends/generic_backend.pyx +1893 -0
  427. sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  428. sage/numerical/backends/generic_sdp_backend.pxd +38 -0
  429. sage/numerical/backends/generic_sdp_backend.pyx +755 -0
  430. sage/parallel/all.py +6 -0
  431. sage/parallel/decorate.py +575 -0
  432. sage/parallel/map_reduce.py +1997 -0
  433. sage/parallel/multiprocessing_sage.py +76 -0
  434. sage/parallel/ncpus.py +35 -0
  435. sage/parallel/parallelism.py +364 -0
  436. sage/parallel/reference.py +47 -0
  437. sage/parallel/use_fork.py +333 -0
  438. sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  439. sage/rings/abc.pxd +31 -0
  440. sage/rings/abc.pyx +526 -0
  441. sage/rings/algebraic_closure_finite_field.py +1154 -0
  442. sage/rings/all__sagemath_categories.py +91 -0
  443. sage/rings/big_oh.py +227 -0
  444. sage/rings/continued_fraction.py +2754 -0
  445. sage/rings/continued_fraction_gosper.py +220 -0
  446. sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
  447. sage/rings/factorint.pyx +295 -0
  448. sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
  449. sage/rings/fast_arith.pxd +21 -0
  450. sage/rings/fast_arith.pyx +535 -0
  451. sage/rings/finite_rings/all__sagemath_categories.py +9 -0
  452. sage/rings/finite_rings/conway_polynomials.py +542 -0
  453. sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  454. sage/rings/finite_rings/element_base.pxd +12 -0
  455. sage/rings/finite_rings/element_base.pyx +1176 -0
  456. sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  457. sage/rings/finite_rings/finite_field_base.pxd +7 -0
  458. sage/rings/finite_rings/finite_field_base.pyx +2171 -0
  459. sage/rings/finite_rings/finite_field_constructor.py +827 -0
  460. sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
  461. sage/rings/finite_rings/galois_group.py +154 -0
  462. sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  463. sage/rings/finite_rings/hom_finite_field.pxd +23 -0
  464. sage/rings/finite_rings/hom_finite_field.pyx +856 -0
  465. sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  466. sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
  467. sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
  468. sage/rings/finite_rings/homset.py +357 -0
  469. sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
  470. sage/rings/finite_rings/integer_mod.pxd +56 -0
  471. sage/rings/finite_rings/integer_mod.pyx +4586 -0
  472. sage/rings/finite_rings/integer_mod_limits.h +11 -0
  473. sage/rings/finite_rings/integer_mod_ring.py +2044 -0
  474. sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
  475. sage/rings/finite_rings/residue_field.pxd +30 -0
  476. sage/rings/finite_rings/residue_field.pyx +1811 -0
  477. sage/rings/finite_rings/stdint.pxd +19 -0
  478. sage/rings/fraction_field.py +1452 -0
  479. sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
  480. sage/rings/fraction_field_element.pyx +1357 -0
  481. sage/rings/function_field/all.py +7 -0
  482. sage/rings/function_field/all__sagemath_categories.py +2 -0
  483. sage/rings/function_field/constructor.py +218 -0
  484. sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
  485. sage/rings/function_field/element.pxd +11 -0
  486. sage/rings/function_field/element.pyx +1008 -0
  487. sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
  488. sage/rings/function_field/element_rational.pyx +513 -0
  489. sage/rings/function_field/extensions.py +230 -0
  490. sage/rings/function_field/function_field.py +1468 -0
  491. sage/rings/function_field/function_field_rational.py +1005 -0
  492. sage/rings/function_field/ideal.py +1155 -0
  493. sage/rings/function_field/ideal_rational.py +629 -0
  494. sage/rings/function_field/jacobian_base.py +826 -0
  495. sage/rings/function_field/jacobian_hess.py +1053 -0
  496. sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
  497. sage/rings/function_field/maps.py +1039 -0
  498. sage/rings/function_field/order.py +281 -0
  499. sage/rings/function_field/order_basis.py +586 -0
  500. sage/rings/function_field/order_rational.py +576 -0
  501. sage/rings/function_field/place.py +426 -0
  502. sage/rings/function_field/place_rational.py +181 -0
  503. sage/rings/generic.py +320 -0
  504. sage/rings/homset.py +332 -0
  505. sage/rings/ideal.py +1885 -0
  506. sage/rings/ideal_monoid.py +215 -0
  507. sage/rings/infinity.py +1890 -0
  508. sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
  509. sage/rings/integer.pxd +45 -0
  510. sage/rings/integer.pyx +7874 -0
  511. sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
  512. sage/rings/integer_ring.pxd +8 -0
  513. sage/rings/integer_ring.pyx +1693 -0
  514. sage/rings/laurent_series_ring.py +931 -0
  515. sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  516. sage/rings/laurent_series_ring_element.pxd +11 -0
  517. sage/rings/laurent_series_ring_element.pyx +1927 -0
  518. sage/rings/lazy_series.py +7815 -0
  519. sage/rings/lazy_series_ring.py +4356 -0
  520. sage/rings/localization.py +1043 -0
  521. sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
  522. sage/rings/morphism.pxd +39 -0
  523. sage/rings/morphism.pyx +3299 -0
  524. sage/rings/multi_power_series_ring.py +1145 -0
  525. sage/rings/multi_power_series_ring_element.py +2184 -0
  526. sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
  527. sage/rings/noncommutative_ideals.pyx +423 -0
  528. sage/rings/number_field/all__sagemath_categories.py +1 -0
  529. sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  530. sage/rings/number_field/number_field_base.pxd +8 -0
  531. sage/rings/number_field/number_field_base.pyx +507 -0
  532. sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  533. sage/rings/number_field/number_field_element_base.pxd +6 -0
  534. sage/rings/number_field/number_field_element_base.pyx +36 -0
  535. sage/rings/number_field/number_field_ideal.py +3550 -0
  536. sage/rings/padics/all__sagemath_categories.py +4 -0
  537. sage/rings/padics/local_generic.py +1670 -0
  538. sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
  539. sage/rings/padics/local_generic_element.pxd +5 -0
  540. sage/rings/padics/local_generic_element.pyx +1017 -0
  541. sage/rings/padics/misc.py +256 -0
  542. sage/rings/padics/padic_generic.py +1911 -0
  543. sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
  544. sage/rings/padics/pow_computer.pxd +38 -0
  545. sage/rings/padics/pow_computer.pyx +671 -0
  546. sage/rings/padics/precision_error.py +24 -0
  547. sage/rings/polynomial/all__sagemath_categories.py +25 -0
  548. sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  549. sage/rings/polynomial/commutative_polynomial.pxd +6 -0
  550. sage/rings/polynomial/commutative_polynomial.pyx +24 -0
  551. sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
  552. sage/rings/polynomial/cyclotomic.pyx +404 -0
  553. sage/rings/polynomial/flatten.py +711 -0
  554. sage/rings/polynomial/ideal.py +102 -0
  555. sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
  556. sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
  557. sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  558. sage/rings/polynomial/laurent_polynomial.pxd +18 -0
  559. sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
  560. sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
  561. sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
  562. sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
  563. sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  564. sage/rings/polynomial/multi_polynomial.pxd +12 -0
  565. sage/rings/polynomial/multi_polynomial.pyx +3082 -0
  566. sage/rings/polynomial/multi_polynomial_element.py +2570 -0
  567. sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
  568. sage/rings/polynomial/multi_polynomial_ring.py +947 -0
  569. sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
  570. sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
  571. sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
  572. sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
  573. sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
  574. sage/rings/polynomial/polydict.pxd +45 -0
  575. sage/rings/polynomial/polydict.pyx +2701 -0
  576. sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
  577. sage/rings/polynomial/polynomial_compiled.pxd +59 -0
  578. sage/rings/polynomial/polynomial_compiled.pyx +509 -0
  579. sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
  580. sage/rings/polynomial/polynomial_element.pxd +64 -0
  581. sage/rings/polynomial/polynomial_element.pyx +13255 -0
  582. sage/rings/polynomial/polynomial_element_generic.py +1637 -0
  583. sage/rings/polynomial/polynomial_fateman.py +97 -0
  584. sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
  585. sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
  586. sage/rings/polynomial/polynomial_ring.py +3784 -0
  587. sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
  588. sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
  589. sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
  590. sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
  591. sage/rings/polynomial/polynomial_singular_interface.py +549 -0
  592. sage/rings/polynomial/symmetric_ideal.py +989 -0
  593. sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
  594. sage/rings/polynomial/symmetric_reduction.pxd +8 -0
  595. sage/rings/polynomial/symmetric_reduction.pyx +669 -0
  596. sage/rings/polynomial/term_order.py +2279 -0
  597. sage/rings/polynomial/toy_buchberger.py +449 -0
  598. sage/rings/polynomial/toy_d_basis.py +387 -0
  599. sage/rings/polynomial/toy_variety.py +362 -0
  600. sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
  601. sage/rings/power_series_mpoly.pxd +9 -0
  602. sage/rings/power_series_mpoly.pyx +161 -0
  603. sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
  604. sage/rings/power_series_poly.pxd +10 -0
  605. sage/rings/power_series_poly.pyx +1317 -0
  606. sage/rings/power_series_ring.py +1441 -0
  607. sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  608. sage/rings/power_series_ring_element.pxd +12 -0
  609. sage/rings/power_series_ring_element.pyx +3028 -0
  610. sage/rings/puiseux_series_ring.py +487 -0
  611. sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  612. sage/rings/puiseux_series_ring_element.pxd +7 -0
  613. sage/rings/puiseux_series_ring_element.pyx +1055 -0
  614. sage/rings/qqbar_decorators.py +167 -0
  615. sage/rings/quotient_ring.py +1598 -0
  616. sage/rings/quotient_ring_element.py +979 -0
  617. sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
  618. sage/rings/rational.pxd +20 -0
  619. sage/rings/rational.pyx +4284 -0
  620. sage/rings/rational_field.py +1730 -0
  621. sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
  622. sage/rings/real_double.pxd +16 -0
  623. sage/rings/real_double.pyx +2218 -0
  624. sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
  625. sage/rings/real_lazy.pxd +30 -0
  626. sage/rings/real_lazy.pyx +1773 -0
  627. sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
  628. sage/rings/ring.pxd +30 -0
  629. sage/rings/ring.pyx +850 -0
  630. sage/rings/semirings/all.py +3 -0
  631. sage/rings/semirings/non_negative_integer_semiring.py +107 -0
  632. sage/rings/semirings/tropical_mpolynomial.py +972 -0
  633. sage/rings/semirings/tropical_polynomial.py +997 -0
  634. sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
  635. sage/rings/semirings/tropical_semiring.pyx +676 -0
  636. sage/rings/semirings/tropical_variety.py +1701 -0
  637. sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
  638. sage/rings/sum_of_squares.pxd +3 -0
  639. sage/rings/sum_of_squares.pyx +336 -0
  640. sage/rings/tests.py +504 -0
  641. sage/schemes/affine/affine_homset.py +508 -0
  642. sage/schemes/affine/affine_morphism.py +1574 -0
  643. sage/schemes/affine/affine_point.py +460 -0
  644. sage/schemes/affine/affine_rational_point.py +308 -0
  645. sage/schemes/affine/affine_space.py +1264 -0
  646. sage/schemes/affine/affine_subscheme.py +592 -0
  647. sage/schemes/affine/all.py +25 -0
  648. sage/schemes/all__sagemath_categories.py +5 -0
  649. sage/schemes/generic/algebraic_scheme.py +2092 -0
  650. sage/schemes/generic/all.py +5 -0
  651. sage/schemes/generic/ambient_space.py +400 -0
  652. sage/schemes/generic/divisor.py +465 -0
  653. sage/schemes/generic/divisor_group.py +313 -0
  654. sage/schemes/generic/glue.py +84 -0
  655. sage/schemes/generic/homset.py +820 -0
  656. sage/schemes/generic/hypersurface.py +234 -0
  657. sage/schemes/generic/morphism.py +2107 -0
  658. sage/schemes/generic/point.py +237 -0
  659. sage/schemes/generic/scheme.py +1190 -0
  660. sage/schemes/generic/spec.py +199 -0
  661. sage/schemes/product_projective/all.py +6 -0
  662. sage/schemes/product_projective/homset.py +236 -0
  663. sage/schemes/product_projective/morphism.py +517 -0
  664. sage/schemes/product_projective/point.py +568 -0
  665. sage/schemes/product_projective/rational_point.py +550 -0
  666. sage/schemes/product_projective/space.py +1301 -0
  667. sage/schemes/product_projective/subscheme.py +466 -0
  668. sage/schemes/projective/all.py +24 -0
  669. sage/schemes/projective/proj_bdd_height.py +453 -0
  670. sage/schemes/projective/projective_homset.py +718 -0
  671. sage/schemes/projective/projective_morphism.py +2792 -0
  672. sage/schemes/projective/projective_point.py +1484 -0
  673. sage/schemes/projective/projective_rational_point.py +569 -0
  674. sage/schemes/projective/projective_space.py +2571 -0
  675. sage/schemes/projective/projective_subscheme.py +1574 -0
  676. sage/sets/all.py +17 -0
  677. sage/sets/cartesian_product.py +376 -0
  678. sage/sets/condition_set.py +525 -0
  679. sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
  680. sage/sets/disjoint_set.pxd +36 -0
  681. sage/sets/disjoint_set.pyx +998 -0
  682. sage/sets/disjoint_union_enumerated_sets.py +625 -0
  683. sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
  684. sage/sets/family.pxd +12 -0
  685. sage/sets/family.pyx +1556 -0
  686. sage/sets/finite_enumerated_set.py +406 -0
  687. sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
  688. sage/sets/finite_set_map_cy.pxd +34 -0
  689. sage/sets/finite_set_map_cy.pyx +708 -0
  690. sage/sets/finite_set_maps.py +591 -0
  691. sage/sets/image_set.py +448 -0
  692. sage/sets/integer_range.py +829 -0
  693. sage/sets/non_negative_integers.py +241 -0
  694. sage/sets/positive_integers.py +93 -0
  695. sage/sets/primes.py +188 -0
  696. sage/sets/real_set.py +2760 -0
  697. sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
  698. sage/sets/recursively_enumerated_set.pxd +31 -0
  699. sage/sets/recursively_enumerated_set.pyx +2082 -0
  700. sage/sets/set.py +2083 -0
  701. sage/sets/set_from_iterator.py +1021 -0
  702. sage/sets/totally_ordered_finite_set.py +329 -0
  703. sage/symbolic/all__sagemath_categories.py +1 -0
  704. sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
  705. sage/symbolic/function.pxd +29 -0
  706. sage/symbolic/function.pyx +1488 -0
  707. sage/symbolic/symbols.py +56 -0
  708. sage/tests/all__sagemath_categories.py +1 -0
  709. sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
  710. sage/tests/cython.pyx +37 -0
  711. sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
  712. sage/tests/stl_vector.pyx +171 -0
  713. sage/typeset/all.py +6 -0
  714. sage/typeset/ascii_art.py +295 -0
  715. sage/typeset/character_art.py +789 -0
  716. sage/typeset/character_art_factory.py +572 -0
  717. sage/typeset/symbols.py +334 -0
  718. sage/typeset/unicode_art.py +183 -0
  719. sage/typeset/unicode_characters.py +101 -0
@@ -0,0 +1,3402 @@
1
+ # sage_setup: distribution = sagemath-categories
2
+ r"""
3
+ Coxeter Groups
4
+ """
5
+ # ****************************************************************************
6
+ # Copyright (C) 2009 Nicolas M. Thiery <nthiery at users.sf.net>
7
+ # 2015 Christian Stump <christian.stump at gmail.com>
8
+ #
9
+ # Distributed under the terms of the GNU General Public License (GPL)
10
+ # https://www.gnu.org/licenses/
11
+ # *****************************************************************************
12
+ # With contributions from Dan Bump, Steve Pon, Qiang Wang, Anne Schilling, Christian Stump, Mark Shimozono
13
+ from copy import copy
14
+ from collections import deque
15
+
16
+ from sage.categories.category_singleton import Category_singleton
17
+ from sage.categories.enumerated_sets import EnumeratedSets
18
+ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
19
+ from sage.categories.generalized_coxeter_groups import GeneralizedCoxeterGroups
20
+ from sage.misc.abstract_method import abstract_method
21
+ from sage.misc.cachefunc import cached_method, cached_in_parent_method
22
+ from sage.misc.call import attrcall
23
+ from sage.misc.constant_function import ConstantFunction
24
+ from sage.misc.flatten import flatten
25
+ from sage.misc.lazy_import import LazyImport
26
+ from sage.structure.element import have_same_parent, parent
27
+
28
+
29
+ class CoxeterGroups(Category_singleton):
30
+ r"""
31
+ The category of Coxeter groups.
32
+
33
+ A *Coxeter group* is a group `W` with a distinguished (finite)
34
+ family of involutions `(s_i)_{i\in I}`, called the *simple
35
+ reflections*, subject to relations of the form `(s_is_j)^{m_{i,j}} = 1`.
36
+
37
+ `I` is the *index set* of `W` and `|I|` is the *rank* of `W`.
38
+
39
+ See :wikipedia:`Coxeter_group` for details.
40
+
41
+ EXAMPLES::
42
+
43
+ sage: C = CoxeterGroups(); C
44
+ Category of Coxeter groups
45
+ sage: C.super_categories()
46
+ [Category of generalized Coxeter groups]
47
+
48
+ sage: W = C.example(); W
49
+ The symmetric group on {0, ..., 3}
50
+
51
+ sage: W.simple_reflections()
52
+ Finite family {0: (1, 0, 2, 3), 1: (0, 2, 1, 3), 2: (0, 1, 3, 2)}
53
+
54
+ Here are some further examples::
55
+
56
+ sage: FiniteCoxeterGroups().example()
57
+ The 5-th dihedral group of order 10
58
+ sage: FiniteWeylGroups().example()
59
+ The symmetric group on {0, ..., 3}
60
+ sage: WeylGroup(["B", 3]) # needs sage.combinat sage.groups
61
+ Weyl Group of type ['B', 3] (as a matrix group acting on the ambient space)
62
+
63
+ sage: S4 = SymmetricGroup(4); S4 # needs sage.groups
64
+ Symmetric group of order 4! as a permutation group
65
+ sage: S4 in CoxeterGroups().Finite() # needs sage.groups
66
+ True
67
+
68
+ Those will eventually be also in this category::
69
+
70
+ sage: DihedralGroup(5) # needs sage.groups
71
+ Dihedral group of order 10 as a permutation group
72
+
73
+ .. TODO:: add a demo of usual computations on Coxeter groups.
74
+
75
+ .. SEEALSO::
76
+
77
+ - :mod:`sage.combinat.root_system`
78
+ - :class:`WeylGroups`
79
+ - :class:`GeneralizedCoxeterGroups`
80
+
81
+ .. WARNING::
82
+
83
+ It is assumed that morphisms in this category preserve the
84
+ distinguished choice of simple reflections. In particular,
85
+ subobjects in this category are parabolic subgroups. In this
86
+ sense, this category might be better named ``Coxeter
87
+ Systems``. In the long run we might want to have two distinct
88
+ categories, one for Coxeter groups (with morphisms being just
89
+ group morphisms) and one for Coxeter systems::
90
+
91
+ sage: CoxeterGroups().is_full_subcategory(Groups())
92
+ False
93
+ sage: from sage.categories.generalized_coxeter_groups import GeneralizedCoxeterGroups
94
+ sage: CoxeterGroups().is_full_subcategory(GeneralizedCoxeterGroups())
95
+ True
96
+
97
+ TESTS::
98
+
99
+ sage: W = CoxeterGroups().example()
100
+ sage: TestSuite(W).run()
101
+ """
102
+
103
+ def super_categories(self):
104
+ """
105
+ EXAMPLES::
106
+
107
+ sage: CoxeterGroups().super_categories()
108
+ [Category of generalized Coxeter groups]
109
+ """
110
+ return [GeneralizedCoxeterGroups()]
111
+
112
+ def additional_structure(self):
113
+ r"""
114
+ Return ``None``.
115
+
116
+ Indeed, all the structure Coxeter groups have in addition to
117
+ groups (simple reflections, ...) is already defined in the
118
+ super category.
119
+
120
+ .. SEEALSO:: :meth:`Category.additional_structure`
121
+
122
+ EXAMPLES::
123
+
124
+ sage: CoxeterGroups().additional_structure()
125
+ """
126
+ return None
127
+
128
+ Finite = LazyImport('sage.categories.finite_coxeter_groups', 'FiniteCoxeterGroups')
129
+ Algebras = LazyImport('sage.categories.coxeter_group_algebras', 'CoxeterGroupAlgebras')
130
+
131
+ class ParentMethods:
132
+ @abstract_method
133
+ def coxeter_matrix(self):
134
+ """
135
+ Return the Coxeter matrix associated to ``self``.
136
+
137
+ EXAMPLES::
138
+
139
+ sage: G = WeylGroup(['A', 3]) # needs sage.combinat sage.groups
140
+ sage: G.coxeter_matrix() # needs sage.combinat sage.groups
141
+ [1 3 2]
142
+ [3 1 3]
143
+ [2 3 1]
144
+ """
145
+
146
+ @cached_method
147
+ def index_set(self):
148
+ """
149
+ Return the index set of ``self``.
150
+
151
+ EXAMPLES::
152
+
153
+ sage: # needs sage.combinat sage.groups
154
+ sage: W = CoxeterGroup([[1,3],[3,1]])
155
+ sage: W.index_set()
156
+ (1, 2)
157
+ sage: W = CoxeterGroup([[1,3],[3,1]], index_set=['x', 'y'])
158
+ sage: W.index_set()
159
+ ('x', 'y')
160
+ sage: W = CoxeterGroup(['H', 3])
161
+ sage: W.index_set()
162
+ (1, 2, 3)
163
+ """
164
+ return self.coxeter_matrix().index_set()
165
+
166
+ def coxeter_diagram(self):
167
+ """
168
+ Return the Coxeter diagram of ``self``.
169
+
170
+ EXAMPLES::
171
+
172
+ sage: # needs sage.combinat sage.graphs sage.groups
173
+ sage: W = CoxeterGroup(['H', 3], implementation='reflection')
174
+ sage: G = W.coxeter_diagram(); G
175
+ Graph on 3 vertices
176
+ sage: G.edges(sort=True)
177
+ [(1, 2, 3), (2, 3, 5)]
178
+ sage: CoxeterGroup(G) is W
179
+ True
180
+ sage: G = Graph([(0, 1, 3), (1, 2, oo)])
181
+ sage: W = CoxeterGroup(G)
182
+ sage: W.coxeter_diagram() == G
183
+ True
184
+ sage: CoxeterGroup(W.coxeter_diagram()) is W
185
+ True
186
+ """
187
+ return self.coxeter_matrix().coxeter_graph()
188
+
189
+ def coxeter_type(self):
190
+ """
191
+ Return the Coxeter type of ``self``.
192
+
193
+ EXAMPLES::
194
+
195
+ sage: W = CoxeterGroup(['H', 3]) # needs sage.combinat sage.groups
196
+ sage: W.coxeter_type() # needs sage.combinat sage.groups
197
+ Coxeter type of ['H', 3]
198
+ """
199
+ return self.coxeter_matrix().coxeter_type()
200
+
201
+ def braid_relations(self):
202
+ r"""
203
+ Return the braid relations of ``self`` as a list of reduced
204
+ words of the braid relations.
205
+
206
+ EXAMPLES::
207
+
208
+ sage: W = WeylGroup(["A", 2]) # needs sage.combinat sage.groups
209
+ sage: W.braid_relations() # needs sage.combinat sage.groups
210
+ [[[1, 2, 1], [2, 1, 2]]]
211
+
212
+ sage: W = WeylGroup(["B", 3]) # needs sage.combinat sage.groups
213
+ sage: W.braid_relations() # needs sage.combinat sage.groups
214
+ [[[1, 2, 1], [2, 1, 2]], [[1, 3], [3, 1]], [[2, 3, 2, 3], [3, 2, 3, 2]]]
215
+ """
216
+ rels = []
217
+ M = self.coxeter_matrix()
218
+ I = self.index_set()
219
+ for ii, i in enumerate(I):
220
+ for j in I[ii + 1:]:
221
+ m = M[i, j]
222
+ rel = [i, j] * m
223
+ rels.append([rel[:m], rel[m:] if m % 2 else
224
+ list(reversed(rel[m:]))])
225
+ return rels
226
+
227
+ def braid_group_as_finitely_presented_group(self):
228
+ r"""
229
+ Return the associated braid group.
230
+
231
+ EXAMPLES::
232
+
233
+ sage: W = CoxeterGroup(['A', 2]) # needs sage.combinat sage.groups
234
+ sage: W.braid_group_as_finitely_presented_group() # needs sage.combinat sage.groups
235
+ Finitely presented group < S1, S2 | S1*S2*S1*S2^-1*S1^-1*S2^-1 >
236
+
237
+ sage: W = WeylGroup(['B', 2]) # needs sage.combinat sage.groups
238
+ sage: W.braid_group_as_finitely_presented_group() # needs sage.combinat sage.groups
239
+ Finitely presented group < S1, S2 | (S1*S2)^2*(S1^-1*S2^-1)^2 >
240
+
241
+ sage: W = ReflectionGroup(['B',3], index_set=["AA","BB","5"]) # optional - gap3
242
+ sage: W.braid_group_as_finitely_presented_group() # optional - gap3
243
+ Finitely presented group < SAA, SBB, S5 |
244
+ (SAA*SBB)^2*(SAA^-1*SBB^-1)^2, SAA*S5*SAA^-1*S5^-1,
245
+ SBB*S5*SBB*S5^-1*SBB^-1*S5^-1 >
246
+ """
247
+ from sage.groups.free_group import FreeGroup
248
+ from sage.misc.misc_c import prod
249
+
250
+ I = self.index_set()
251
+ F = FreeGroup(["S%s" % i for i in I])
252
+ S = F.gens()
253
+ rels = self.braid_relations()
254
+ return F / [prod(S[I.index(i)] for i in l) * prod(S[I.index(i)]**-1 for i in reversed(r)) for l, r in rels]
255
+
256
+ def braid_orbit_iter(self, word):
257
+ r"""
258
+ Iterate over the braid orbit of a word ``word`` of indices.
259
+
260
+ The input word does not need to be a reduced expression of
261
+ an element.
262
+
263
+ INPUT:
264
+
265
+ - ``word`` -- list (or iterable) of indices in
266
+ ``self.index_set()``
267
+
268
+ OUTPUT:
269
+
270
+ all lists that can be obtained from
271
+ ``word`` by replacements of braid relations
272
+
273
+ EXAMPLES::
274
+
275
+ sage: W = CoxeterGroups().example()
276
+ sage: sorted(W.braid_orbit_iter([0, 1, 2, 1])) # needs sage.combinat sage.graphs sage.modules
277
+ [[0, 1, 2, 1], [0, 2, 1, 2], [2, 0, 1, 2]]
278
+ """
279
+ word = list(word)
280
+ from sage.combinat.root_system.braid_orbit import BraidOrbit
281
+
282
+ braid_rels = self.braid_relations()
283
+ I = self.index_set()
284
+
285
+ from sage.rings.integer_ring import ZZ
286
+ be_careful = any(i not in ZZ for i in I)
287
+
288
+ if be_careful:
289
+ Iinv = {i: j for j, i in enumerate(I)}
290
+ word = [Iinv[i] for i in word]
291
+ braid_rels = [[[Iinv[i] for i in l],
292
+ [Iinv[i] for i in r]] for l, r in braid_rels]
293
+
294
+ orb = BraidOrbit(word, braid_rels)
295
+
296
+ if be_careful:
297
+ for word in orb:
298
+ yield [I[i] for i in word]
299
+ else:
300
+ for I in orb:
301
+ yield list(I)
302
+
303
+ def braid_orbit(self, word):
304
+ r"""
305
+ Return the braid orbit of a word ``word`` of indices.
306
+
307
+ The input word does not need to be a reduced expression of
308
+ an element.
309
+
310
+ INPUT:
311
+
312
+ - ``word`` -- a list (or iterable) of indices in
313
+ ``self.index_set()``
314
+
315
+ OUTPUT:
316
+
317
+ a list of all lists that can be obtained from
318
+ ``word`` by replacements of braid relations
319
+
320
+ See :meth:`braid_relations` for the definition of braid
321
+ relations.
322
+
323
+ EXAMPLES::
324
+
325
+ sage: W = CoxeterGroups().example()
326
+ sage: s = W.simple_reflections()
327
+ sage: w = s[0] * s[1] * s[2] * s[1]
328
+ sage: word = w.reduced_word(); word
329
+ [0, 1, 2, 1]
330
+
331
+ sage: sorted(W.braid_orbit(word)) # needs sage.combinat sage.graphs sage.modules
332
+ [[0, 1, 2, 1], [0, 2, 1, 2], [2, 0, 1, 2]]
333
+
334
+ sage: sorted(W.braid_orbit([2,1,1,2,1])) # needs sage.combinat sage.graphs sage.modules
335
+ [[1, 2, 1, 1, 2], [2, 1, 1, 2, 1], [2, 1, 2, 1, 2], [2, 2, 1, 2, 2]]
336
+
337
+ sage: # optional - gap3
338
+ sage: W = ReflectionGroup(['A',3], index_set=["AA","BB","5"])
339
+ sage: w = W.long_element()
340
+ sage: W.braid_orbit(w.reduced_word())
341
+ [['BB', '5', 'AA', 'BB', '5', 'AA'],
342
+ ['5', 'BB', '5', 'AA', 'BB', '5'],
343
+ ['BB', 'AA', 'BB', '5', 'BB', 'AA'],
344
+ ['AA', '5', 'BB', 'AA', '5', 'BB'],
345
+ ['5', 'AA', 'BB', 'AA', '5', 'BB'],
346
+ ['AA', 'BB', '5', 'AA', 'BB', 'AA'],
347
+ ['AA', 'BB', 'AA', '5', 'BB', 'AA'],
348
+ ['AA', 'BB', '5', 'BB', 'AA', 'BB'],
349
+ ['BB', 'AA', '5', 'BB', 'AA', '5'],
350
+ ['BB', '5', 'AA', 'BB', 'AA', '5'],
351
+ ['AA', '5', 'BB', '5', 'AA', 'BB'],
352
+ ['5', 'BB', 'AA', '5', 'BB', '5'],
353
+ ['5', 'BB', 'AA', 'BB', '5', 'BB'],
354
+ ['5', 'AA', 'BB', '5', 'AA', 'BB'],
355
+ ['BB', '5', 'BB', 'AA', 'BB', '5'],
356
+ ['BB', 'AA', '5', 'BB', '5', 'AA']]
357
+
358
+ .. TODO::
359
+
360
+ The result should be full featured finite enumerated set
361
+ (e.g., counting can be done much faster than iterating).
362
+
363
+ .. SEEALSO::
364
+
365
+ :meth:`.reduced_words`
366
+ """
367
+ return list(self.braid_orbit_iter(word))
368
+
369
+ def __iter__(self):
370
+ r"""
371
+ Return an iterator over the elements of this Coxeter group.
372
+
373
+ EXAMPLES::
374
+
375
+ sage: D5 = FiniteCoxeterGroups().example(5)
376
+ sage: sorted(list(D5)) # indirect doctest (but see :meth:`._test_enumerated_set_iter_list`)
377
+ [(),
378
+ (1,),
379
+ (1, 2),
380
+ (1, 2, 1),
381
+ (1, 2, 1, 2),
382
+ (1, 2, 1, 2, 1),
383
+ (2,),
384
+ (2, 1),
385
+ (2, 1, 2),
386
+ (2, 1, 2, 1)]
387
+
388
+ sage: # needs sage.combinat sage.groups
389
+ sage: W = WeylGroup(["A", 2, 1])
390
+ sage: g = iter(W)
391
+ sage: next(g)
392
+ [1 0 0]
393
+ [0 1 0]
394
+ [0 0 1]
395
+ sage: next(g)
396
+ [-1 1 1]
397
+ [ 0 1 0]
398
+ [ 0 0 1]
399
+ sage: next(g)
400
+ [ 1 0 0]
401
+ [ 1 -1 1]
402
+ [ 0 0 1]
403
+ """
404
+ return iter(self.weak_order_ideal(predicate=ConstantFunction(True)))
405
+
406
+ def _element_constructor_(self, x, **args):
407
+ """
408
+ Construct an element of ``self`` from ``x``.
409
+
410
+ EXAMPLES::
411
+
412
+ sage: # needs sage.combinat sage.groups
413
+ sage: W1 = WeylGroup("G2", prefix='s')
414
+ sage: W2 = CoxeterGroup("G2")
415
+ sage: W3 = CoxeterGroup("G2", implementation='permutation')
416
+ sage: W1(W2.an_element())
417
+ s1*s2
418
+ sage: W2(W1.an_element())
419
+ [ 2 -a]
420
+ [ a -1]
421
+ sage: W1(W3.an_element())
422
+ s1*s2
423
+ sage: s1, s2 = W1.simple_reflections()
424
+ sage: W = CoxeterGroup("A1")
425
+ sage: W(s1 * s2)
426
+ Traceback (most recent call last):
427
+ ...
428
+ ValueError: inconsistent number of rows: should be 1 but got 3
429
+ """
430
+ P = parent(x)
431
+ if P in CoxeterGroups():
432
+ try:
433
+ return self.from_reduced_word(x.reduced_word())
434
+ except KeyError:
435
+ # Unable to convert using the reduced word
436
+ # because of an incompatible index
437
+ pass
438
+ return self.element_class(self, x, **args)
439
+
440
+ def weak_order_ideal(self, predicate, side='right', category=None):
441
+ """
442
+ Return a weak order ideal defined by a predicate.
443
+
444
+ INPUT:
445
+
446
+ - ``predicate`` -- a predicate on the elements of ``self`` defining an
447
+ weak order ideal in ``self``
448
+ - ``side`` -- ``'left'`` or ``'right'`` (default: ``'right'``)
449
+
450
+ OUTPUT: an enumerated set
451
+
452
+ EXAMPLES::
453
+
454
+ sage: D6 = FiniteCoxeterGroups().example(5)
455
+ sage: I = D6.weak_order_ideal(predicate=lambda w: w.length() <= 3)
456
+ sage: I.cardinality()
457
+ 7
458
+ sage: list(I)
459
+ [(), (1,), (2,), (1, 2), (2, 1), (1, 2, 1), (2, 1, 2)]
460
+
461
+ We now consider an infinite Coxeter group::
462
+
463
+ sage: W = WeylGroup(["A",1,1]) # needs sage.groups sage.rings.number_field
464
+ sage: I = W.weak_order_ideal(predicate=lambda w: w.length() <= 2) # needs sage.groups sage.rings.number_field
465
+ sage: list(iter(I)) # needs sage.groups sage.rings.number_field
466
+ [
467
+ [1 0] [-1 2] [ 1 0] [ 3 -2] [-1 2]
468
+ [0 1], [ 0 1], [ 2 -1], [ 2 -1], [-2 3]
469
+ ]
470
+
471
+ Even when the result is finite, some features of
472
+ :class:`FiniteEnumeratedSets` are not available::
473
+
474
+ sage: I.cardinality() # todo: not implemented
475
+ 5
476
+ sage: list(I) # todo: not implemented
477
+
478
+ unless this finiteness is explicitly specified::
479
+
480
+ sage: I = W.weak_order_ideal(predicate=lambda w: w.length() <= 2, # needs sage.groups sage.rings.number_field
481
+ ....: category=FiniteEnumeratedSets())
482
+ sage: I.cardinality() # needs sage.groups sage.rings.number_field
483
+ 5
484
+ sage: list(I) # needs sage.groups sage.rings.number_field
485
+ [
486
+ [1 0] [-1 2] [ 1 0] [ 3 -2] [-1 2]
487
+ [0 1], [ 0 1], [ 2 -1], [ 2 -1], [-2 3]
488
+ ]
489
+
490
+ .. rubric:: Background
491
+
492
+ The weak order is returned as a :class:`RecursivelyEnumeratedSet_forest`.
493
+ This is achieved by assigning to each element `u1` of the
494
+ ideal a single ancestor `u=u1 s_i`, where `i` is the
495
+ smallest descent of `u`.
496
+
497
+ This allows for iterating through the elements in
498
+ roughly Constant Amortized Time and constant memory
499
+ (taking the operations and size of the generated objects
500
+ as constants).
501
+
502
+ TESTS:
503
+
504
+ We iterate over each level (i.e., breadth-first-search in the
505
+ search forest), see :issue:`19926`::
506
+
507
+ sage: W = CoxeterGroup(['A',2]) # needs sage.groups sage.rings.number_field
508
+ sage: [x.length() for x in W] # needs sage.groups sage.rings.number_field
509
+ [0, 1, 1, 2, 2, 3]
510
+ """
511
+ from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
512
+
513
+ def succ(u):
514
+ for i in u.descents(positive=True, side=side):
515
+ u1 = u.apply_simple_reflection(i, side)
516
+ if i == u1.first_descent(side=side) and predicate(u1):
517
+ yield u1
518
+
519
+ from sage.categories.finite_coxeter_groups import FiniteCoxeterGroups
520
+ default_category = FiniteEnumeratedSets() if self in FiniteCoxeterGroups() else EnumeratedSets()
521
+ cat = default_category.or_subcategory(category)
522
+ return RecursivelyEnumeratedSet_forest((self.one(),), succ,
523
+ algorithm='breadth',
524
+ category=cat)
525
+
526
+ @cached_method
527
+ def coxeter_element(self):
528
+ """
529
+ Return a Coxeter element.
530
+
531
+ The result is the product of the simple reflections, in some order.
532
+
533
+ .. NOTE::
534
+
535
+ This implementation is shared with well generated
536
+ complex reflection groups. It would be nicer to put it
537
+ in some joint super category; however, in the current
538
+ state of the art, there is none where it is clear that
539
+ this is the right construction for obtaining a Coxeter
540
+ element.
541
+
542
+ In this context, this is an element having a regular
543
+ eigenvector (a vector not contained in any reflection
544
+ hyperplane of ``self``).
545
+
546
+ EXAMPLES::
547
+
548
+ sage: # needs sage.combinat sage.groups
549
+ sage: CoxeterGroup(['A', 4]).coxeter_element().reduced_word()
550
+ [1, 2, 3, 4]
551
+ sage: CoxeterGroup(['B', 4]).coxeter_element().reduced_word()
552
+ [1, 2, 3, 4]
553
+ sage: CoxeterGroup(['D', 4]).coxeter_element().reduced_word()
554
+ [1, 2, 4, 3]
555
+ sage: CoxeterGroup(['F', 4]).coxeter_element().reduced_word()
556
+ [1, 2, 3, 4]
557
+ sage: CoxeterGroup(['E', 8]).coxeter_element().reduced_word()
558
+ [1, 3, 2, 4, 5, 6, 7, 8]
559
+ sage: CoxeterGroup(['H', 3]).coxeter_element().reduced_word()
560
+ [1, 2, 3]
561
+
562
+ This method is also used for well generated finite complex
563
+ reflection groups::
564
+
565
+ sage: W = ReflectionGroup((1,1,4)) # optional - gap3
566
+ sage: W.coxeter_element().reduced_word() # optional - gap3
567
+ [1, 2, 3]
568
+
569
+ sage: W = ReflectionGroup((2,1,4)) # optional - gap3
570
+ sage: W.coxeter_element().reduced_word() # optional - gap3
571
+ [1, 2, 3, 4]
572
+
573
+ sage: W = ReflectionGroup((4,1,4)) # optional - gap3
574
+ sage: W.coxeter_element().reduced_word() # optional - gap3
575
+ [1, 2, 3, 4]
576
+
577
+ sage: W = ReflectionGroup((4,4,4)) # optional - gap3
578
+ sage: W.coxeter_element().reduced_word() # optional - gap3
579
+ [1, 2, 3, 4]
580
+
581
+ TESTS::
582
+
583
+ sage: WeylGroup(['A', 4]).coxeter_element().reduced_word() # needs sage.combinat sage.groups
584
+ [1, 2, 3, 4]
585
+ sage: SymmetricGroup(3).coxeter_element() # needs sage.groups
586
+ (1,3,2)
587
+ """
588
+ return self.prod(self.simple_reflections())
589
+
590
+ @cached_method
591
+ def standard_coxeter_elements(self):
592
+ r"""
593
+ Return all standard Coxeter elements in ``self``.
594
+
595
+ This is the set of all elements in ``self`` obtained from any
596
+ product of the simple reflections in ``self``.
597
+
598
+ .. NOTE::
599
+
600
+ - ``self`` is assumed to be well-generated.
601
+ - This works even beyond real reflection groups, but the conjugacy
602
+ class is not unique and we only obtain one such class.
603
+
604
+ EXAMPLES::
605
+
606
+ sage: W = ReflectionGroup(4) # optional - gap3
607
+ sage: sorted(W.standard_coxeter_elements()) # optional - gap3
608
+ [(1,7,6,12,23,20)(2,8,17,24,9,5)(3,16,10,19,15,21)(4,14,11,22,18,13),
609
+ (1,10,4,12,21,22)(2,11,19,24,13,3)(5,15,7,17,16,23)(6,18,8,20,14,9)]
610
+
611
+ TESTS::
612
+
613
+ sage: W = SymmetricGroup(3) # needs sage.groups
614
+ sage: sorted(W.standard_coxeter_elements()) # needs sage.combinat sage.groups
615
+ [(1,2,3), (1,3,2)]
616
+
617
+ sage: W = Permutations(3)
618
+ sage: sorted(W.standard_coxeter_elements()) # needs sage.graphs
619
+ [[2, 3, 1], [3, 1, 2]]
620
+
621
+ sage: W = CoxeterGroup(['D', 3]) # needs sage.combinat sage.groups
622
+ sage: sorted(W.standard_coxeter_elements()) # needs sage.combinat sage.groups
623
+ [
624
+ [-1 1 1] [ 0 -1 1] [ 0 1 -1] [ 1 -1 -1]
625
+ [-1 0 1] [ 1 -1 0] [ 0 0 -1] [ 1 -1 0]
626
+ [-1 1 0], [ 0 -1 0], [ 1 0 -1], [ 1 0 -1]
627
+ ]
628
+
629
+ sage: W = ColoredPermutations(3,2) # needs sage.combinat
630
+ sage: len(W.standard_coxeter_elements()) # needs sage.combinat sage.graphs
631
+ 2
632
+ """
633
+ if not self.is_irreducible() or not self.is_well_generated():
634
+ raise ValueError("this method is available for irreducible, well-generated complex reflection groups")
635
+ from sage.combinat.permutation import Permutations
636
+ return {self.from_reduced_word(w)
637
+ for w in Permutations(self.index_set())}
638
+
639
+ def grassmannian_elements(self, side='right'):
640
+ """
641
+ Return the left or right Grassmannian elements of ``self``
642
+ as an enumerated set.
643
+
644
+ INPUT:
645
+
646
+ - ``side`` -- (default: ``'right'``) ``'left'`` or ``'right'``
647
+
648
+ EXAMPLES::
649
+
650
+ sage: S = CoxeterGroups().example()
651
+ sage: G = S.grassmannian_elements()
652
+ sage: G.cardinality()
653
+ 12
654
+ sage: G.list()
655
+ [(0, 1, 2, 3), (1, 0, 2, 3), (0, 2, 1, 3), (0, 1, 3, 2),
656
+ (2, 0, 1, 3), (1, 2, 0, 3), (0, 3, 1, 2), (0, 2, 3, 1),
657
+ (3, 0, 1, 2), (1, 3, 0, 2), (1, 2, 3, 0), (2, 3, 0, 1)]
658
+ sage: sorted(tuple(w.descents()) for w in G)
659
+ [(), (0,), (0,), (0,), (1,), (1,), (1,), (1,), (1,), (2,), (2,), (2,)]
660
+ sage: G = S.grassmannian_elements(side = "left")
661
+ sage: G.cardinality()
662
+ 12
663
+ sage: sorted(tuple(w.descents(side = "left")) for w in G)
664
+ [(), (0,), (0,), (0,), (1,), (1,), (1,), (1,), (1,), (2,), (2,), (2,)]
665
+ """
666
+ order_side = "left" if side == "right" else "right"
667
+ return self.weak_order_ideal(attrcall("is_grassmannian", side=side),
668
+ side=order_side)
669
+
670
+ def fully_commutative_elements(self):
671
+ r"""
672
+ Return the set of fully commutative elements in this Coxeter group.
673
+
674
+ .. SEEALSO::
675
+
676
+ :class:`~sage.combinat.fully_commutative_elements.FullyCommutativeElements`
677
+
678
+ EXAMPLES::
679
+
680
+ sage: CoxeterGroup(['A', 3]).fully_commutative_elements() # needs sage.combinat sage.groups
681
+ Fully commutative elements of
682
+ Finite Coxeter group over Integer Ring with Coxeter matrix:
683
+ [1 3 2]
684
+ [3 1 3]
685
+ [2 3 1]
686
+ """
687
+ from sage.combinat.fully_commutative_elements import FullyCommutativeElements
688
+ return FullyCommutativeElements(self)
689
+
690
+ def _test_reduced_word(self, **options):
691
+ """
692
+ Run sanity checks on :meth:`CoxeterGroups.ElementMethods.reduced_word` and
693
+ :meth:`~sage.categories.complex_reflection_or_generalized_coxeter_groups.ComplexReflectionOrGeneralizedCoxeterGroups.ParentMethods.from_reduced_word`
694
+
695
+ EXAMPLES::
696
+
697
+ sage: W = CoxeterGroups().example()
698
+ sage: W._test_reduced_word()
699
+ """
700
+ tester = self._tester(**options)
701
+ s = self.simple_reflections()
702
+ for x in tester.some_elements():
703
+ red = x.reduced_word()
704
+ tester.assertEqual(self.from_reduced_word(red), x)
705
+ tester.assertEqual(self.prod(s[i] for i in red), x)
706
+
707
+ def simple_projection(self, i, side='right', length_increasing=True):
708
+ r"""
709
+ Return the simple projection `\pi_i` (or `\overline\pi_i` if ``length_increasing`` is ``False``).
710
+
711
+ INPUT:
712
+
713
+ - ``i`` -- an element of the index set of ``self``
714
+
715
+ See :meth:`.simple_projections` for the options and for
716
+ the definition of the simple projections.
717
+
718
+ EXAMPLES::
719
+
720
+ sage: W = CoxeterGroups().example()
721
+ sage: W
722
+ The symmetric group on {0, ..., 3}
723
+ sage: s = W.simple_reflections()
724
+ sage: sigma = W.an_element()
725
+ sage: sigma
726
+ (1, 2, 3, 0)
727
+ sage: u0 = W.simple_projection(0)
728
+ sage: d0 = W.simple_projection(0, length_increasing=False)
729
+ sage: sigma.length()
730
+ 3
731
+ sage: pi=sigma*s[0]
732
+ sage: pi.length()
733
+ 4
734
+ sage: u0(sigma)
735
+ (2, 1, 3, 0)
736
+ sage: pi
737
+ (2, 1, 3, 0)
738
+ sage: u0(pi)
739
+ (2, 1, 3, 0)
740
+ sage: d0(sigma)
741
+ (1, 2, 3, 0)
742
+ sage: d0(pi)
743
+ (1, 2, 3, 0)
744
+ """
745
+ if not (i in self.index_set() or i == 0):
746
+ raise ValueError("%s is not 0 and not in the Dynkin node set %s" % (i, self.index_set()))
747
+ return lambda x: x.apply_simple_projection(i, side=side,
748
+ length_increasing=length_increasing)
749
+
750
+ def kazhdan_lusztig_cells(self, side='left'):
751
+ r"""
752
+ Compute the left, right, or two-sided Kazhdan-Lusztig cells of
753
+ ``self`` if ``self`` is finite.
754
+
755
+ The cells are computed by using :func:`kazhdan_lusztig_cell()
756
+ <CoxeterGroups.ElementMethods.kazhdan_lusztig_cell()>`.
757
+
758
+ As detailed there, installation of the optional package ``coxeter3``
759
+ is recommended (though not required) before using this function
760
+ as it speeds up the computation.
761
+
762
+ INPUT:
763
+
764
+ - ``side`` -- (default: ``'left'``) either ``'left'``,
765
+ ``'right'``, or ``'two-sided'``
766
+
767
+ EXAMPLES:
768
+
769
+ We compute the right cells in the Coxeter group of type `A_2`
770
+ below. Note that each Coxeter group may be created with multiple
771
+ implementations, namely, 'reflection' (default), 'permutation',
772
+ 'matrix', or 'coxeter3'. The choice of implementation affects the
773
+ representation of elements in the output cells but not the method
774
+ used for the cell computation::
775
+
776
+ sage: # needs sage.combinat sage.groups
777
+ sage: W = CoxeterGroup('A2')
778
+ sage: KL_cells = W.kazhdan_lusztig_cells(side='right')
779
+ sage: set([tuple(sorted(C, key=lambda w: w.reduced_word()))
780
+ ....: for C in KL_cells])
781
+ {(
782
+ [-1 1] [ 0 -1]
783
+ [ 0 1], [ 1 -1]
784
+ ),
785
+ (
786
+ [ 0 -1]
787
+ [-1 0]
788
+ ),
789
+ (
790
+ [1 0]
791
+ [0 1]
792
+ ),
793
+ (
794
+ [ 1 0] [-1 1]
795
+ [ 1 -1], [-1 0]
796
+ )}
797
+ sage: len(KL_cells)
798
+ 4
799
+
800
+ sage: W = CoxeterGroup('A2', implementation='permutation') # needs sage.combinat sage.groups
801
+ sage: len(W.kazhdan_lusztig_cells(side='right')) # needs sage.combinat sage.groups
802
+ 4
803
+
804
+ We compute the left cells in the Coxeter group of type `A_3`
805
+ below. If the optional package ``coxeter3`` is installed, it
806
+ runs in the background even if the group is not created with
807
+ the ``'coxeter3'`` implementation::
808
+
809
+ sage: # optional - coxeter3, needs sage.combinat sage.groups sage.libs.gap sage.modules sage.rings.number_field
810
+ sage: W = CoxeterGroup('A3', implementation='coxeter3')
811
+ sage: KL_cells = W.kazhdan_lusztig_cells()
812
+ sage: set([tuple(sorted(C)) for C in KL_cells])
813
+ {([],),
814
+ ([1], [2, 1], [3, 2, 1]),
815
+ ([1, 2], [2], [3, 2]),
816
+ ([1, 2, 1], [1, 3, 2, 1], [2, 1, 3, 2, 1]),
817
+ ([1, 2, 1, 3], [1, 2, 3, 2, 1], [2, 3, 2, 1]),
818
+ ([1, 2, 1, 3, 2], [1, 2, 3, 2], [2, 3, 2]),
819
+ ([1, 2, 1, 3, 2, 1],),
820
+ ([1, 2, 3], [2, 3], [3]),
821
+ ([1, 3], [2, 1, 3]),
822
+ ([1, 3, 2], [2, 1, 3, 2])}
823
+ sage: len(KL_cells)
824
+ 10
825
+ sage: W = CoxeterGroup('A3', implementation='permutation')
826
+ sage: len(W.kazhdan_lusztig_cells())
827
+ 10
828
+
829
+ Computing the two-sided cells in `B_3`::
830
+
831
+ sage: # optional - coxeter3, needs sage.combinat sage.groups sage.libs.gap sage.modules sage.rings.number_field
832
+ sage: W = CoxeterGroup('B3', implementation='coxeter3')
833
+ sage: b3_cells = W.kazhdan_lusztig_cells('two-sided')
834
+ sage: len(b3_cells)
835
+ 6
836
+ sage: set([tuple(sorted(C))
837
+ ....: for C in W.kazhdan_lusztig_cells()])
838
+ {([],),
839
+ ([1], [1, 2, 3, 2, 1], [2, 1], [2, 3, 2, 1], [3, 2, 1]),
840
+ ([1, 2], [1, 2, 3, 2], [2], [2, 3, 2], [3, 2]),
841
+ ([1, 2, 3], [2, 3], [3], [3, 2, 3]),
842
+ ([2, 1, 2], [2, 3, 2, 1, 2], [3, 2, 1, 2]),
843
+ ([2, 1, 2, 3], [2, 3, 2, 1, 2, 3], [3, 2, 1, 2, 3]),
844
+ ([2, 1, 2, 3, 2], [2, 3, 2, 1, 2, 3, 2], [3, 2, 1, 2, 3, 2]),
845
+ ([2, 1, 2, 3, 2, 1],
846
+ [2, 3, 2, 1, 2, 3, 2, 1],
847
+ [3, 2, 1, 2, 3, 2, 1],
848
+ [3, 2, 3, 2, 1, 2]),
849
+ ([2, 3, 1], [3, 1], [3, 2, 3, 1]),
850
+ ([2, 3, 1, 2], [3, 1, 2], [3, 2, 3, 1, 2]),
851
+ ([2, 3, 1, 2, 3], [3, 1, 2, 3], [3, 2, 3, 1, 2, 3]),
852
+ ([2, 3, 1, 2, 3, 2],
853
+ [3, 1, 2, 3, 2],
854
+ [3, 2, 3, 1, 2, 3, 2],
855
+ [3, 2, 3, 2],
856
+ [3, 2, 3, 2, 1, 2, 3, 2]),
857
+ ([2, 3, 1, 2, 3, 2, 1],
858
+ [3, 1, 2, 3, 2, 1],
859
+ [3, 2, 3, 1, 2, 3, 2, 1],
860
+ [3, 2, 3, 2, 1],
861
+ [3, 2, 3, 2, 1, 2, 3]),
862
+ ([3, 2, 3, 2, 1, 2, 3, 2, 1],)}
863
+
864
+ TESTS::
865
+
866
+ sage: W = CoxeterGroup(['A', 2, 1]) # needs sage.combinat sage.groups
867
+ sage: W.kazhdan_lusztig_cells() # needs sage.combinat sage.groups
868
+ Traceback (most recent call last):
869
+ ...
870
+ ValueError: the Coxeter group must be finite to compute Kazhdan--Lusztig cells
871
+ """
872
+ if not self.coxeter_type().is_finite():
873
+ raise ValueError('the Coxeter group must be finite to compute Kazhdan--Lusztig cells')
874
+
875
+ # The identity is its own left-, right-, and two-sided- cell.
876
+ identity = frozenset([self.one()])
877
+ cells = {identity}
878
+
879
+ for w in self:
880
+ if not any(w in c for c in cells):
881
+ cell = w.kazhdan_lusztig_cell(side=side)
882
+ cells.add(frozenset(cell))
883
+
884
+ return cells
885
+
886
+ @cached_method
887
+ def simple_projections(self, side='right', length_increasing=True):
888
+ r"""
889
+ Return the family of simple projections, also known as 0-Hecke or Demazure operators.
890
+
891
+ INPUT:
892
+
893
+ - ``self`` -- a Coxeter group `W`
894
+ - ``side`` -- ``'left'`` or ``'right'`` (default: ``'right'``)
895
+ - ``length_increasing`` -- boolean (default: ``True``); whether
896
+ the operator increases or decreases length
897
+
898
+ This returns the simple projections of `W`, as a family.
899
+
900
+ To each simple reflection `s_i` of `W`, corresponds a
901
+ *simple projection* `\pi_i` from `W` to `W` defined by:
902
+
903
+ `\pi_i(w) = w s_i` if `i` is not a descent of `w`
904
+ `\pi_i(w) = w` otherwise.
905
+
906
+ The simple projections `(\pi_i)_{i\in I}` move elements
907
+ down the right permutohedron, toward the maximal element.
908
+ They satisfy the same braid relations as the simple reflections,
909
+ but are idempotents `\pi_i^2=\pi` not involutions `s_i^2 = 1`. As such,
910
+ the simple projections generate the `0`-Hecke monoid.
911
+
912
+ By symmetry, one can also define the projections
913
+ `(\overline\pi_i)_{i\in I}` (when the option ``length_increasing`` is False):
914
+
915
+ `\overline\pi_i(w) = w s_i` if `i` is a descent of `w`
916
+ `\overline\pi_i(w) = w` otherwise.
917
+
918
+ as well as the analogues acting on the left (when the option ``side`` is 'left').
919
+
920
+ EXAMPLES::
921
+
922
+ sage: W = CoxeterGroups().example(); W
923
+ The symmetric group on {0, ..., 3}
924
+ sage: s = W.simple_reflections()
925
+ sage: sigma = W.an_element(); sigma
926
+ (1, 2, 3, 0)
927
+ sage: pi = W.simple_projections(); pi
928
+ Finite family {0: <function ...<lambda> at ...>,
929
+ 1: <function ...<lambda> at ...>,
930
+ 2: <function ...<lambda> ...>}
931
+ sage: pi[1](sigma)
932
+ (1, 3, 2, 0)
933
+ sage: W.simple_projection(1)(sigma)
934
+ (1, 3, 2, 0)
935
+ """
936
+ from sage.sets.family import Family
937
+ return Family(self.index_set(), lambda i: self.simple_projection(i, side=side, length_increasing=length_increasing))
938
+
939
+ def sign_representation(self, base_ring=None):
940
+ r"""
941
+ Return the sign representation of ``self`` over ``base_ring``.
942
+
943
+ INPUT:
944
+
945
+ - ``base_ring`` -- (optional) the base ring; the default is `\ZZ`
946
+
947
+ EXAMPLES::
948
+
949
+ sage: W = WeylGroup(['D', 4]) # needs sage.combinat sage.groups
950
+ sage: W.sign_representation(QQ) # needs sage.combinat sage.groups
951
+ Sign representation of
952
+ Weyl Group of type ['D', 4] (as a matrix group acting on the ambient space)
953
+ over Rational Field
954
+
955
+ sage: # optional - gap3
956
+ sage: W = CoxeterGroup(['B',3], implementation="coxeter3")
957
+ sage: W.sign_representation()
958
+ Sign representation of Coxeter group of type ['B', 3]
959
+ implemented by Coxeter3 over Integer Ring
960
+ """
961
+ if base_ring is None:
962
+ from sage.rings.integer_ring import ZZ
963
+ base_ring = ZZ
964
+ from sage.modules.with_basis.representation import SignRepresentationCoxeterGroup
965
+ return SignRepresentationCoxeterGroup(self, base_ring)
966
+
967
+ def reflection_representation(self, base_ring=None, side='left'):
968
+ r"""
969
+ Return the reflection representation of ``self``.
970
+
971
+ This is also the canonical faithful representation of a
972
+ Coxeter group.
973
+
974
+ INPUT:
975
+
976
+ - ``base_ring`` -- (optional) the base ring; the default is
977
+ the base ring of :meth:`canonical_representation`
978
+ - ``side`` -- ignored
979
+
980
+ EXAMPLES::
981
+
982
+ sage: W = CoxeterGroup(['D', 4]) # needs sage.graphs sage.groups
983
+ sage: W.reflection_representation() # needs sage.graphs sage.groups
984
+ Reflection representation of Finite Coxeter group over
985
+ Integer Ring with Coxeter matrix:
986
+ [1 3 2 2]
987
+ [3 1 3 3]
988
+ [2 3 1 2]
989
+ [2 3 2 1]
990
+
991
+ sage: W = CoxeterGroup(['I', 13]) # needs sage.graphs sage.modules sage.rings.number_field
992
+ sage: W.reflection_representation() # needs sage.graphs sage.modules sage.rings.number_field
993
+ Reflection representation of Finite Coxeter group over
994
+ Universal Cyclotomic Field with Coxeter matrix:
995
+ [ 1 13]
996
+ [13 1]
997
+
998
+ sage: W = WeylGroup(["B", 3, 1]) # needs sage.graphs sage.groups
999
+ sage: W.reflection_representation(QQ) # needs sage.graphs sage.groups
1000
+ Reflection representation of Weyl Group of type ['B', 3, 1]
1001
+ (as a matrix group acting on the root space)
1002
+ """
1003
+ from sage.modules.with_basis.representation import ReflectionRepresentation
1004
+ return ReflectionRepresentation(self, base_ring)
1005
+
1006
+ def demazure_product(self, Q):
1007
+ r"""
1008
+ Return the Demazure product of the list ``Q`` in ``self``.
1009
+
1010
+ INPUT:
1011
+
1012
+ - ``Q`` -- list of elements from the index set of ``self``
1013
+
1014
+ This returns the Coxeter group element that represents the
1015
+ composition of 0-Hecke or Demazure operators.
1016
+
1017
+ See :meth:`CoxeterGroups.ParentMethods.simple_projections`.
1018
+
1019
+ EXAMPLES::
1020
+
1021
+ sage: # needs sage.combinat sage.groups
1022
+ sage: W = WeylGroup(['A', 2])
1023
+ sage: w = W.demazure_product([2,2,1])
1024
+ sage: w.reduced_word()
1025
+ [2, 1]
1026
+ sage: w = W.demazure_product([2,1,2,1,2])
1027
+ sage: w.reduced_word()
1028
+ [1, 2, 1]
1029
+
1030
+ sage: W = WeylGroup(['B', 2]) # needs sage.combinat sage.groups
1031
+ sage: w = W.demazure_product([2,1,2,1,2]) # needs sage.combinat sage.groups
1032
+ sage: w.reduced_word() # needs sage.combinat sage.groups
1033
+ [2, 1, 2, 1]
1034
+ """
1035
+ return self.one().apply_demazure_product(Q)
1036
+
1037
+ def bruhat_interval(self, x, y):
1038
+ """
1039
+ Return the list of ``t`` such that ``x <= t <= y``.
1040
+
1041
+ EXAMPLES::
1042
+
1043
+ sage: W = WeylGroup("A3", prefix='s') # needs sage.combinat sage.groups
1044
+ sage: s1, s2, s3 = W.simple_reflections() # needs sage.combinat sage.groups
1045
+ sage: W.bruhat_interval(s2, s1*s3*s2*s1*s3) # needs sage.combinat sage.groups
1046
+ [s1*s2*s3*s2*s1, s2*s3*s2*s1, s3*s1*s2*s1, s1*s2*s3*s1,
1047
+ s1*s2*s3*s2, s3*s2*s1, s2*s3*s1, s2*s3*s2, s1*s2*s1,
1048
+ s3*s1*s2, s1*s2*s3, s2*s1, s3*s2, s2*s3, s1*s2, s2]
1049
+
1050
+ sage: W = WeylGroup(['A', 2, 1], prefix='s') # needs sage.combinat sage.groups
1051
+ sage: s0, s1, s2 = W.simple_reflections() # needs sage.combinat sage.groups
1052
+ sage: W.bruhat_interval(1, s0*s1*s2) # needs sage.combinat sage.groups
1053
+ [s0*s1*s2, s1*s2, s0*s2, s0*s1, s2, s1, s0, 1]
1054
+ """
1055
+ if x == 1:
1056
+ x = self.one()
1057
+ if y == 1:
1058
+ y = self.one()
1059
+ if x == y:
1060
+ return [x]
1061
+ ret = []
1062
+ if not x.bruhat_le(y):
1063
+ return ret
1064
+ ret.append([y])
1065
+ while ret[-1]:
1066
+ nextlayer = []
1067
+ for z in ret[-1]:
1068
+ for t in z.bruhat_lower_covers():
1069
+ if t not in nextlayer:
1070
+ if x.bruhat_le(t):
1071
+ nextlayer.append(t)
1072
+ ret.append(nextlayer)
1073
+ return flatten(ret)
1074
+
1075
+ def bruhat_interval_poset(self, x, y, facade=False):
1076
+ r"""
1077
+ Return the poset of the Bruhat interval between ``x`` and ``y``
1078
+ in Bruhat order.
1079
+
1080
+ EXAMPLES::
1081
+
1082
+ sage: W = WeylGroup("A3", prefix='s') # needs sage.combinat sage.groups
1083
+ sage: s1, s2, s3 = W.simple_reflections() # needs sage.combinat sage.groups
1084
+ sage: W.bruhat_interval_poset(s2, s1*s3*s2*s1*s3) # needs sage.combinat sage.groups
1085
+ Finite poset containing 16 elements
1086
+
1087
+ sage: W = WeylGroup(['A', 2, 1], prefix='s') # needs sage.combinat sage.groups
1088
+ sage: s0, s1, s2 = W.simple_reflections() # needs sage.combinat sage.groups
1089
+ sage: W.bruhat_interval_poset(1, s0*s1*s2) # needs sage.combinat sage.groups
1090
+ Finite poset containing 8 elements
1091
+
1092
+ TESTS::
1093
+
1094
+ sage: W.bruhat_interval_poset(s0*s1*s2, s0*s1*s2) # needs sage.combinat sage.groups
1095
+ Finite poset containing 1 elements
1096
+ """
1097
+ if x == 1:
1098
+ x = self.one()
1099
+ if y == 1:
1100
+ y = self.one()
1101
+ from sage.combinat.posets.posets import Poset
1102
+ if x == y:
1103
+ return Poset([[x], []])
1104
+ if not x.bruhat_le(y):
1105
+ return Poset()
1106
+ curlayer = {y}
1107
+ d = {}
1108
+ while curlayer:
1109
+ nextlayer = set()
1110
+ for z in curlayer:
1111
+ for t in z.bruhat_lower_covers():
1112
+ if not x.bruhat_le(t):
1113
+ continue
1114
+ if t in d:
1115
+ d[t].append(z)
1116
+ else:
1117
+ d[t] = [z]
1118
+ if t not in nextlayer:
1119
+ nextlayer.add(t)
1120
+ curlayer = nextlayer
1121
+
1122
+ from sage.graphs.digraph import DiGraph
1123
+ return Poset(DiGraph(d, format='dict_of_lists',
1124
+ data_structure='static_sparse'),
1125
+ cover_relations=True,
1126
+ facade=facade)
1127
+
1128
+ def bruhat_graph(self, x=None, y=None, edge_labels=False):
1129
+ r"""
1130
+ Return the Bruhat graph as a directed graph, with an edge `u \to v`
1131
+ if and only if `u < v` in the Bruhat order, and `u = r \cdot v`.
1132
+
1133
+ The Bruhat graph `\Gamma(x,y)`, defined if `x \leq y` in the
1134
+ Bruhat order, has as its vertices the Bruhat interval
1135
+ `\{ t | x \leq t \leq y \}`, and as its edges are the pairs
1136
+ `(u, v)` such that `u = r \cdot v` where `r` is a reflection,
1137
+ that is, a conjugate of a simple reflection.
1138
+
1139
+ REFERENCES:
1140
+
1141
+ Carrell, The Bruhat graph of a Coxeter group, a conjecture of Deodhar,
1142
+ and rational smoothness of Schubert varieties. Algebraic groups and
1143
+ their generalizations: classical methods (University Park, PA, 1991),
1144
+ 53--61, Proc. Sympos. Pure Math., 56, Part 1, Amer. Math. Soc.,
1145
+ Providence, RI, 1994.
1146
+
1147
+ EXAMPLES::
1148
+
1149
+ sage: W = CoxeterGroup(['H', 3]) # needs sage.combinat sage.graphs sage.groups
1150
+ sage: G = W.bruhat_graph(); G # needs sage.combinat sage.graphs sage.groups
1151
+ Digraph on 120 vertices
1152
+
1153
+ sage: # needs sage.combinat sage.graphs sage.groups
1154
+ sage: W = CoxeterGroup(['A', 2, 1])
1155
+ sage: s1, s2, s3 = W.simple_reflections()
1156
+ sage: W.bruhat_graph(s1, s1*s3*s2*s3)
1157
+ Digraph on 6 vertices
1158
+ sage: W.bruhat_graph(s1, s3*s2*s3)
1159
+ Digraph on 0 vertices
1160
+
1161
+ sage: W = WeylGroup("A3", prefix='s') # needs sage.combinat sage.graphs sage.groups
1162
+ sage: s1, s2, s3 = W.simple_reflections() # needs sage.combinat sage.graphs sage.groups
1163
+ sage: G = W.bruhat_graph(s1*s3, s1*s2*s3*s2*s1); G # needs sage.combinat sage.graphs sage.groups
1164
+ Digraph on 10 vertices
1165
+
1166
+ Check that the graph has the correct number of edges
1167
+ (see :issue:`17744`)::
1168
+
1169
+ sage: len(G.edges(sort=False)) # needs sage.combinat sage.graphs sage.groups
1170
+ 16
1171
+ """
1172
+ if x is None or x == 1:
1173
+ x = self.one()
1174
+ if y is None:
1175
+ if self.is_finite():
1176
+ y = self.long_element()
1177
+ else:
1178
+ raise TypeError("infinite groups must specify a maximal element")
1179
+ elif y == 1:
1180
+ y = self.one()
1181
+
1182
+ # Sort bruhat_interval in weakly decreasing order of length.
1183
+ # We do this so we do not need to check the length in the
1184
+ # for loops below.
1185
+ g = sorted(self.bruhat_interval(x, y), key=lambda w: -w.length())
1186
+ d = []
1187
+
1188
+ if self.is_finite():
1189
+ ref = self.reflections()
1190
+ for i, u in enumerate(g):
1191
+ for v in g[:i]:
1192
+ w = u * v.inverse()
1193
+ if w in ref:
1194
+ if edge_labels:
1195
+ d.append((u, v, w))
1196
+ else:
1197
+ d.append((u, v))
1198
+ else:
1199
+ for i, u in enumerate(g):
1200
+ for v in g[:i]:
1201
+ w = u * v.inverse()
1202
+ if w.is_reflection():
1203
+ if edge_labels:
1204
+ d.append((u, v, w))
1205
+ else:
1206
+ d.append((u, v))
1207
+
1208
+ from sage.graphs.digraph import DiGraph
1209
+ return DiGraph(d)
1210
+
1211
+ def canonical_representation(self):
1212
+ r"""
1213
+ Return the canonical faithful representation of ``self``.
1214
+
1215
+ .. SEEALSO::
1216
+
1217
+ To obtain the underlying module with the action, use
1218
+ :meth:`reflection_representation`.
1219
+
1220
+ EXAMPLES::
1221
+
1222
+ sage: W = WeylGroup("A3") # needs sage.combinat sage.groups
1223
+ sage: W.canonical_representation() # needs sage.combinat sage.groups
1224
+ Finite Coxeter group over Integer Ring with Coxeter matrix:
1225
+ [1 3 2]
1226
+ [3 1 3]
1227
+ [2 3 1]
1228
+ """
1229
+ from sage.groups.matrix_gps.coxeter_group import CoxeterMatrixGroup
1230
+ return CoxeterMatrixGroup(self.coxeter_matrix(),
1231
+ index_set=self.index_set())
1232
+
1233
+ def elements_of_length(self, n):
1234
+ r"""
1235
+ Return all elements of length `n`.
1236
+
1237
+ EXAMPLES::
1238
+
1239
+ sage: A = AffinePermutationGroup(['A', 2, 1]) # needs sage.combinat sage.groups
1240
+ sage: [len(list(A.elements_of_length(i))) for i in [0..5]] # needs sage.combinat sage.groups
1241
+ [1, 3, 6, 9, 12, 15]
1242
+
1243
+ sage: W = CoxeterGroup(['H', 3]) # needs sage.combinat sage.groups
1244
+ sage: [len(list(W.elements_of_length(i))) for i in range(4)] # needs sage.combinat sage.groups
1245
+ [1, 3, 5, 7]
1246
+
1247
+ sage: W = CoxeterGroup(['A', 2]) # needs sage.combinat sage.groups
1248
+ sage: [len(list(W.elements_of_length(i))) for i in range(6)] # needs sage.combinat sage.groups
1249
+ [1, 2, 2, 1, 0, 0]
1250
+ """
1251
+ I = self.weak_order_ideal(ConstantFunction(True), side='right')
1252
+ return I.elements_of_depth_iterator(n)
1253
+
1254
+ def random_element_of_length(self, n):
1255
+ r"""
1256
+ Return a random element of length ``n`` in ``self``.
1257
+
1258
+ Starts at the identity, then chooses an upper cover at random.
1259
+
1260
+ Not very uniform: actually constructs a uniformly random
1261
+ reduced word of length `n`. Thus we most likely get
1262
+ elements with lots of reduced words!
1263
+
1264
+ EXAMPLES::
1265
+
1266
+ sage: # needs sage.combinat sage.groups
1267
+ sage: A = AffinePermutationGroup(['A', 7, 1])
1268
+ sage: p = A.random_element_of_length(10)
1269
+ sage: p in A
1270
+ True
1271
+ sage: p.length() == 10
1272
+ True
1273
+
1274
+ sage: # needs sage.combinat sage.groups
1275
+ sage: W = CoxeterGroup(['A', 4])
1276
+ sage: p = W.random_element_of_length(5)
1277
+ sage: p in W
1278
+ True
1279
+ sage: p.length() == 5
1280
+ True
1281
+ """
1282
+ from sage.misc.prandom import randint
1283
+ x = self.one()
1284
+ for _ in range(1, n + 1):
1285
+ antiD = x.descents(positive=True)
1286
+ rnd = randint(0, len(antiD) - 1)
1287
+ x = x.apply_simple_reflection_right(antiD[rnd])
1288
+ return x
1289
+
1290
+ # parabolic_subgroup
1291
+
1292
+ def _test_simple_projections(self, **options):
1293
+ """
1294
+ Run sanity checks on :meth:`.simple_projections`
1295
+ and :meth:`CoxeterGroups.ElementMethods.apply_simple_projection`
1296
+
1297
+ EXAMPLES::
1298
+
1299
+ sage: W = CoxeterGroups().example()
1300
+ sage: W._test_simple_projections()
1301
+ """
1302
+ tester = self._tester(**options)
1303
+ for side in ['left', 'right']:
1304
+ pi = self.simple_projections(side=side)
1305
+ opi = self.simple_projections(side=side, length_increasing=False)
1306
+ for i in self.index_set():
1307
+ for w in tester.some_elements():
1308
+ tester.assertEqual(pi[i](w), w.apply_simple_projection(i, side=side))
1309
+ tester.assertEqual(pi[i](w), w.apply_simple_projection(i, side=side, length_increasing=True))
1310
+ tester.assertEqual(opi[i](w), w.apply_simple_projection(i, side=side, length_increasing=False))
1311
+ tester.assertTrue(pi[i](w).has_descent(i, side=side))
1312
+ tester.assertFalse(opi[i](w).has_descent(i, side=side))
1313
+ tester.assertEqual({pi[i](w), opi[i](w)},
1314
+ {w, w.apply_simple_reflection(i, side=side)})
1315
+
1316
+ def _test_has_descent(self, **options):
1317
+ """
1318
+ Run sanity checks on the method
1319
+ :meth:`CoxeterGroups.ElementMethods.has_descent` of the
1320
+ elements of ``self``.
1321
+
1322
+ EXAMPLES::
1323
+
1324
+ sage: W = CoxeterGroups().example()
1325
+ sage: W._test_has_descent()
1326
+
1327
+ sage: # needs sage.combinat sage.groups
1328
+ sage: W = Permutations(4)
1329
+ sage: W._test_has_descent()
1330
+ sage: sage.combinat.permutation.Permutations.options.mult = "r2l"
1331
+ sage: W._test_has_descent()
1332
+ sage: sage.combinat.permutation.Permutations.options._reset()
1333
+
1334
+ sage: W = SignedPermutations(3) # needs sage.combinat
1335
+ sage: W._test_has_descent()
1336
+ """
1337
+ tester = self._tester(**options)
1338
+ s = self.simple_reflections()
1339
+ for i in self.index_set():
1340
+ tester.assertTrue(not self.one().has_descent(i))
1341
+ tester.assertTrue(not self.one().has_descent(i, side='left'))
1342
+ tester.assertTrue(not self.one().has_descent(i, side='right'))
1343
+ tester.assertTrue(self.one().has_descent(i, positive=True))
1344
+ tester.assertTrue(self.one().has_descent(i, positive=True, side='left'))
1345
+ tester.assertTrue(self.one().has_descent(i, positive=True, side='right'))
1346
+ for j in self.index_set():
1347
+ tester.assertEqual(s[i].has_descent(j, side='left'), i == j)
1348
+ tester.assertEqual(s[i].has_descent(j, side='right'), i == j)
1349
+ tester.assertEqual(s[i].has_descent(j), i == j)
1350
+ tester.assertEqual(s[i].has_descent(j, positive=True, side='left'), i != j)
1351
+ tester.assertEqual(s[i].has_descent(j, positive=True, side='right'), i != j)
1352
+ tester.assertEqual(s[i].has_descent(j, positive=True), i != j)
1353
+ if i == j:
1354
+ continue
1355
+ u = s[i].apply_simple_reflection_right(j)
1356
+ v = s[j].apply_simple_reflection_right(i)
1357
+ tester.assertTrue(u.has_descent(i, side='left'))
1358
+ tester.assertTrue(u.has_descent(j, side='right'))
1359
+ tester.assertEqual(u.has_descent(j, side='left'), u == v)
1360
+ tester.assertEqual(u.has_descent(i, side='right'), u == v)
1361
+
1362
+ def _test_descents(self, **options):
1363
+ """
1364
+ Run sanity checks on the method
1365
+ :meth:`CoxeterGroups.ElementMethods.descents` of the
1366
+ elements of ``self``.
1367
+
1368
+ EXAMPLES::
1369
+
1370
+ sage: W = CoxeterGroups().example()
1371
+ sage: W._test_descents()
1372
+ """
1373
+ tester = self._tester(**options)
1374
+ s = self.simple_reflections()
1375
+ tester.assertEqual(len(self.one().descents(side='right')), 0)
1376
+ tester.assertEqual(len(self.one().descents(side='left')), 0)
1377
+ for i in self.index_set():
1378
+ si = s[i]
1379
+ tester.assertEqual([i], si.descents(side='left'))
1380
+ tester.assertEqual([i], si.descents(side='right'))
1381
+ tester.assertNotIn(i, si.descents(positive=True, side='left'))
1382
+ tester.assertNotIn(i, si.descents(positive=True, side='right'))
1383
+
1384
+ def _test_coxeter_relations(self, **options):
1385
+ r"""
1386
+ Test whether the Coxeter relations hold for ``self``.
1387
+
1388
+ This checks nothing in the case of infinite order.
1389
+
1390
+ TESTS::
1391
+
1392
+ sage: A = AffinePermutationGroup(['A', 7, 1]) # needs sage.combinat sage.modules
1393
+ sage: A._test_coxeter_relations() # needs sage.combinat sage.modules
1394
+
1395
+ sage: cm = CartanMatrix([[2,-5,0], [-2,2,-1], [0,-1,2]]) # needs sage.graphs sage.modules
1396
+ sage: W = WeylGroup(cm) # needs sage.combinat sage.graphs sage.groups sage.modules
1397
+ sage: W._test_coxeter_relations() # needs sage.combinat sage.graphs sage.groups sage.modules
1398
+
1399
+ sage: # needs sage.combinat sage.groups
1400
+ sage: W = Permutations(4)
1401
+ sage: W._test_coxeter_relations()
1402
+ sage: sage.combinat.permutation.Permutations.options.mult = "r2l"
1403
+ sage: W._test_coxeter_relations()
1404
+ sage: sage.combinat.permutation.Permutations.options._reset()
1405
+
1406
+ sage: W = SignedPermutations(3) # needs sage.combinat
1407
+ sage: W._test_coxeter_relations() # needs sage.combinat
1408
+ """
1409
+ tester = self._tester(**options)
1410
+ s = self.simple_reflections()
1411
+ one = self.one()
1412
+ for si in s:
1413
+ tester.assertEqual(si**2, one)
1414
+ try:
1415
+ cox_mat = self.coxeter_matrix()
1416
+ except ImportError:
1417
+ return
1418
+ I = cox_mat.index_set()
1419
+ for ii, i in enumerate(I):
1420
+ for j in I[ii + 1:]:
1421
+ mij = cox_mat[i, j]
1422
+ if mij == -1: # -1 stands for infinity
1423
+ continue
1424
+ l = s[i] * s[j]
1425
+ tester.assertEqual(l**mij, one, "Coxeter relation fails")
1426
+ for p in range(1, mij):
1427
+ tester.assertNotEqual(l**p, one, "unexpected relation")
1428
+
1429
+ class ElementMethods:
1430
+ def has_descent(self, i, side='right', positive=False) -> bool:
1431
+ """
1432
+ Return whether `i` is a (left/right) descent of ``self``.
1433
+
1434
+ See :meth:`.descents` for a description of the options.
1435
+
1436
+ EXAMPLES::
1437
+
1438
+ sage: W = CoxeterGroups().example()
1439
+ sage: s = W.simple_reflections()
1440
+ sage: w = s[0] * s[1] * s[2]
1441
+ sage: w.has_descent(2)
1442
+ True
1443
+ sage: [ w.has_descent(i) for i in [0,1,2] ]
1444
+ [False, False, True]
1445
+ sage: [ w.has_descent(i, side='left') for i in [0,1,2] ]
1446
+ [True, False, False]
1447
+ sage: [ w.has_descent(i, positive=True) for i in [0,1,2] ]
1448
+ [True, True, False]
1449
+
1450
+ This default implementation delegates the work to
1451
+ :meth:`.has_left_descent` and :meth:`.has_right_descent`.
1452
+ """
1453
+ if not isinstance(positive, bool):
1454
+ raise TypeError("%s is not a boolean" % bool)
1455
+ if side == 'right':
1456
+ return self.has_right_descent(i) != positive
1457
+ if side != 'left':
1458
+ raise ValueError("%s is neither 'right' nor 'left'" % side)
1459
+ return self.has_left_descent(i) != positive
1460
+
1461
+ # @abstract_method(optional = True)
1462
+ def has_right_descent(self, i) -> bool:
1463
+ """
1464
+ Return whether `i` is a right descent of ``self``.
1465
+
1466
+ EXAMPLES::
1467
+
1468
+ sage: W = CoxeterGroups().example(); W
1469
+ The symmetric group on {0, ..., 3}
1470
+ sage: w = W.an_element(); w
1471
+ (1, 2, 3, 0)
1472
+ sage: w.has_right_descent(0)
1473
+ False
1474
+ sage: w.has_right_descent(1)
1475
+ False
1476
+ sage: w.has_right_descent(2)
1477
+ True
1478
+ """
1479
+ return (~self).has_left_descent(i)
1480
+
1481
+ def has_left_descent(self, i) -> bool:
1482
+ """
1483
+ Return whether `i` is a left descent of ``self``.
1484
+
1485
+ This default implementation uses that a left descent of
1486
+ `w` is a right descent of `w^{-1}`.
1487
+
1488
+ EXAMPLES::
1489
+
1490
+ sage: W = CoxeterGroups().example(); W
1491
+ The symmetric group on {0, ..., 3}
1492
+ sage: w = W.an_element(); w
1493
+ (1, 2, 3, 0)
1494
+ sage: w.has_left_descent(0)
1495
+ True
1496
+ sage: w.has_left_descent(1)
1497
+ False
1498
+ sage: w.has_left_descent(2)
1499
+ False
1500
+
1501
+ TESTS::
1502
+
1503
+ sage: w.has_left_descent.__module__
1504
+ 'sage.categories.coxeter_groups'
1505
+ """
1506
+ return (~self).has_right_descent(i)
1507
+
1508
+ def first_descent(self, side='right', index_set=None, positive=False):
1509
+ """
1510
+ Return the first left (resp. right) descent of self, as
1511
+ an element of ``index_set``, or ``None`` if there is none.
1512
+
1513
+ See :meth:`.descents` for a description of the options.
1514
+
1515
+ EXAMPLES::
1516
+
1517
+ sage: W = CoxeterGroups().example()
1518
+ sage: s = W.simple_reflections()
1519
+ sage: w = s[2]*s[0]
1520
+ sage: w.first_descent()
1521
+ 0
1522
+ sage: w = s[0]*s[2]
1523
+ sage: w.first_descent()
1524
+ 0
1525
+ sage: w = s[0]*s[1]
1526
+ sage: w.first_descent()
1527
+ 1
1528
+ """
1529
+ if index_set is None:
1530
+ index_set = self.parent().index_set()
1531
+ for i in index_set:
1532
+ if self.has_descent(i, side=side, positive=positive):
1533
+ return i
1534
+ return None
1535
+
1536
+ def descents(self, side='right', index_set=None, positive=False):
1537
+ """
1538
+ Return the descents of self, as a list of elements of the
1539
+ index_set.
1540
+
1541
+ INPUT:
1542
+
1543
+ - ``index_set`` -- a subset (as a list or iterable) of the nodes of the Dynkin diagram;
1544
+ (default: all of them)
1545
+ - ``side`` -- ``'left'`` or ``'right'`` (default: ``'right'``)
1546
+ - ``positive`` -- boolean (default: ``False``)
1547
+
1548
+ The ``index_set`` option can be used to restrict to the
1549
+ parabolic subgroup indexed by ``index_set``.
1550
+
1551
+ If positive is ``True``, then returns the non-descents
1552
+ instead
1553
+
1554
+ .. TODO::
1555
+
1556
+ find a better name for ``positive``: complement? non_descent?
1557
+
1558
+ Caveat: the return type may change to some other iterable
1559
+ (tuple, ...) in the future. Please use keyword arguments
1560
+ also, as the order of the arguments may change as well.
1561
+
1562
+ EXAMPLES::
1563
+
1564
+ sage: W = CoxeterGroups().example()
1565
+ sage: s = W.simple_reflections()
1566
+ sage: w = s[0]*s[1]
1567
+ sage: w.descents()
1568
+ [1]
1569
+ sage: w = s[0]*s[2]
1570
+ sage: w.descents()
1571
+ [0, 2]
1572
+
1573
+ .. TODO:: side, index_set, positive
1574
+ """
1575
+ if index_set is None:
1576
+ index_set = self.parent().index_set()
1577
+ return [i for i in index_set if self.has_descent(i, side=side,
1578
+ positive=positive)]
1579
+
1580
+ def is_grassmannian(self, side='right') -> bool:
1581
+ """
1582
+ Return whether ``self`` is Grassmannian.
1583
+
1584
+ INPUT:
1585
+
1586
+ - ``side`` -- ``'left'`` or ``'right'`` (default: ``'right'``)
1587
+
1588
+ An element is Grassmannian if it has at
1589
+ most one descent on the right (resp. on the left).
1590
+
1591
+ EXAMPLES::
1592
+
1593
+ sage: W = CoxeterGroups().example(); W
1594
+ The symmetric group on {0, ..., 3}
1595
+ sage: s = W.simple_reflections()
1596
+ sage: W.one().is_grassmannian()
1597
+ True
1598
+ sage: s[1].is_grassmannian()
1599
+ True
1600
+ sage: (s[1]*s[2]).is_grassmannian()
1601
+ True
1602
+ sage: (s[0]*s[1]).is_grassmannian()
1603
+ True
1604
+ sage: (s[1]*s[2]*s[1]).is_grassmannian()
1605
+ False
1606
+
1607
+ sage: (s[0]*s[2]*s[1]).is_grassmannian(side='left')
1608
+ False
1609
+ sage: (s[0]*s[2]*s[1]).is_grassmannian(side='right')
1610
+ True
1611
+ sage: (s[0]*s[2]*s[1]).is_grassmannian()
1612
+ True
1613
+ """
1614
+ return len(self.descents(side=side)) <= 1
1615
+
1616
+ def is_fully_commutative(self) -> bool:
1617
+ r"""
1618
+ Check if ``self`` is a fully-commutative element.
1619
+
1620
+ We use the characterization that an element `w` in a Coxeter
1621
+ system `(W,S)` is fully-commutative if and only if for every pair
1622
+ of generators `s,t \in S` for which `m(s,t)>2`, no reduced
1623
+ word of `w` contains the 'braid' word `sts...` of length
1624
+ `m(s,t)` as a contiguous subword. See [Ste1996]_.
1625
+
1626
+ EXAMPLES::
1627
+
1628
+ sage: # needs sage.combinat sage.groups
1629
+ sage: W = CoxeterGroup(['A', 3])
1630
+ sage: len([1 for w in W if w.is_fully_commutative()])
1631
+ 14
1632
+ sage: W = CoxeterGroup(['B', 3])
1633
+ sage: len([1 for w in W if w.is_fully_commutative()])
1634
+ 24
1635
+
1636
+ TESTS::
1637
+
1638
+ sage: W = CoxeterGroup(matrix(2,2,[1,7,7,1]), index_set='ab') # needs sage.combinat sage.groups
1639
+ sage: len([1 for w in W if w.is_fully_commutative()]) # needs sage.combinat sage.groups
1640
+ 13
1641
+ """
1642
+ word = self.reduced_word()
1643
+ from sage.combinat.root_system.braid_orbit import is_fully_commutative as is_fully_comm
1644
+
1645
+ group = self.parent()
1646
+ braid_rels = group.braid_relations()
1647
+ I = group.index_set()
1648
+
1649
+ from sage.rings.integer_ring import ZZ
1650
+ be_careful = any(i not in ZZ for i in I)
1651
+
1652
+ if be_careful:
1653
+ Iinv = {i: j for j, i in enumerate(I)}
1654
+ word = [Iinv[i] for i in word]
1655
+ braid_rels = [[[Iinv[i] for i in l],
1656
+ [Iinv[i] for i in r]] for l, r in braid_rels]
1657
+
1658
+ return is_fully_comm(word, braid_rels)
1659
+
1660
+ def reduced_word_reverse_iterator(self):
1661
+ """
1662
+ Return a reverse iterator on a reduced word for ``self``.
1663
+
1664
+ EXAMPLES::
1665
+
1666
+ sage: W = CoxeterGroups().example()
1667
+ sage: s = W.simple_reflections()
1668
+ sage: sigma = s[0]*s[1]*s[2]
1669
+ sage: rI=sigma.reduced_word_reverse_iterator()
1670
+ sage: [i for i in rI]
1671
+ [2, 1, 0]
1672
+ sage: s[0]*s[1]*s[2]==sigma
1673
+ True
1674
+ sage: sigma.length()
1675
+ 3
1676
+
1677
+ .. SEEALSO::
1678
+
1679
+ :meth:`.reduced_word`
1680
+
1681
+ Default implementation: recursively remove the first right
1682
+ descent until the identity is reached (see :meth:`.first_descent` and
1683
+ :meth:`~sage.categories.complex_reflection_or_generalized_coxeter_groups.ComplexReflectionOrGeneralizedCoxeterGroups.ElementMethods.apply_simple_reflection`).
1684
+ """
1685
+ while True:
1686
+ i = self.first_descent()
1687
+ if i is None:
1688
+ return
1689
+ self = self.apply_simple_reflection(i, 'right')
1690
+ yield i
1691
+
1692
+ def reduced_word(self):
1693
+ r"""
1694
+ Return a reduced word for ``self``.
1695
+
1696
+ This is a word `[i_1,i_2,\ldots,i_k]` of minimal length
1697
+ such that
1698
+ `s_{i_1} s_{i_2} \cdots s_{i_k} = \operatorname{self}`,
1699
+ where the `s_i` are the simple reflections.
1700
+
1701
+ EXAMPLES::
1702
+
1703
+ sage: W = CoxeterGroups().example()
1704
+ sage: s = W.simple_reflections()
1705
+ sage: w = s[0]*s[1]*s[2]
1706
+ sage: w.reduced_word()
1707
+ [0, 1, 2]
1708
+ sage: w = s[0]*s[2]
1709
+ sage: w.reduced_word()
1710
+ [2, 0]
1711
+
1712
+ .. SEEALSO::
1713
+
1714
+ - :meth:`.reduced_words`, :meth:`.reduced_word_reverse_iterator`,
1715
+ - :meth:`length`, :meth:`reduced_word_graph`
1716
+ """
1717
+ result = list(self.reduced_word_reverse_iterator())
1718
+ return list(reversed(result))
1719
+
1720
+ def reduced_words_iter(self):
1721
+ r"""
1722
+ Iterate over all reduced words for ``self``.
1723
+
1724
+ See :meth:`reduced_word` for the definition of a reduced
1725
+ word.
1726
+
1727
+ The algorithm uses the Matsumoto property that any two
1728
+ reduced expressions are related by braid relations, see
1729
+ Theorem 3.3.1(ii) in [BB2005]_.
1730
+
1731
+ .. SEEALSO::
1732
+
1733
+ :meth:`braid_orbit_iter`
1734
+
1735
+ EXAMPLES::
1736
+
1737
+ sage: W = CoxeterGroups().example()
1738
+ sage: s = W.simple_reflections()
1739
+ sage: w = s[0] * s[2]
1740
+ sage: sorted(w.reduced_words_iter()) # needs sage.combinat sage.graphs sage.modules
1741
+ [[0, 2], [2, 0]]
1742
+ """
1743
+ return self.parent().braid_orbit_iter(self.reduced_word())
1744
+
1745
+ def reduced_words(self):
1746
+ r"""
1747
+ Return all reduced words for ``self``.
1748
+
1749
+ See :meth:`reduced_word` for the definition of a reduced
1750
+ word.
1751
+
1752
+ The algorithm uses the Matsumoto property that any two
1753
+ reduced expressions are related by braid relations, see
1754
+ Theorem 3.3.1(ii) in [BB2005]_.
1755
+
1756
+ .. SEEALSO::
1757
+
1758
+ :meth:`braid_orbit`
1759
+
1760
+ EXAMPLES::
1761
+
1762
+ sage: W = CoxeterGroups().example()
1763
+ sage: s = W.simple_reflections()
1764
+ sage: w = s[0] * s[2]
1765
+ sage: sorted(w.reduced_words()) # needs sage.graphs sage.modules
1766
+ [[0, 2], [2, 0]]
1767
+
1768
+ sage: W = WeylGroup(['E', 6]) # needs sage.combinat sage.groups
1769
+ sage: w = W.from_reduced_word([2,3,4,2]) # needs sage.combinat sage.groups
1770
+ sage: sorted(w.reduced_words()) # needs sage.combinat sage.groups
1771
+ [[2, 3, 4, 2], [3, 2, 4, 2], [3, 4, 2, 4]]
1772
+
1773
+ sage: # optional - gap3, needs sage.combinat sage.groups
1774
+ sage: W = ReflectionGroup(['A',3],
1775
+ ....: index_set=["AA","BB","5"])
1776
+ sage: w = W.long_element()
1777
+ sage: w.reduced_words()
1778
+ [['BB', '5', 'AA', 'BB', '5', 'AA'],
1779
+ ['5', 'BB', '5', 'AA', 'BB', '5'],
1780
+ ['BB', 'AA', 'BB', '5', 'BB', 'AA'],
1781
+ ['AA', '5', 'BB', 'AA', '5', 'BB'],
1782
+ ['5', 'AA', 'BB', 'AA', '5', 'BB'],
1783
+ ['AA', 'BB', '5', 'AA', 'BB', 'AA'],
1784
+ ['AA', 'BB', 'AA', '5', 'BB', 'AA'],
1785
+ ['AA', 'BB', '5', 'BB', 'AA', 'BB'],
1786
+ ['BB', 'AA', '5', 'BB', 'AA', '5'],
1787
+ ['BB', '5', 'AA', 'BB', 'AA', '5'],
1788
+ ['AA', '5', 'BB', '5', 'AA', 'BB'],
1789
+ ['5', 'BB', 'AA', '5', 'BB', '5'],
1790
+ ['5', 'BB', 'AA', 'BB', '5', 'BB'],
1791
+ ['5', 'AA', 'BB', '5', 'AA', 'BB'],
1792
+ ['BB', '5', 'BB', 'AA', 'BB', '5'],
1793
+ ['BB', 'AA', '5', 'BB', '5', 'AA']]
1794
+
1795
+ .. TODO::
1796
+
1797
+ The result should be full featured finite enumerated set
1798
+ (e.g., counting can be done much faster than iterating).
1799
+
1800
+ .. SEEALSO::
1801
+
1802
+ :meth:`.reduced_word`, :meth:`.reduced_word_reverse_iterator`,
1803
+ :meth:`length`, :meth:`reduced_word_graph`
1804
+ """
1805
+ return list(self.reduced_words_iter())
1806
+
1807
+ def support(self):
1808
+ r"""
1809
+ Return the support of ``self``, that is the simple reflections that
1810
+ appear in the reduced expressions of ``self``.
1811
+
1812
+ OUTPUT: the support of ``self`` as a set of integers
1813
+
1814
+ EXAMPLES::
1815
+
1816
+ sage: W = CoxeterGroups().example()
1817
+ sage: w = W.from_reduced_word([1,2,1])
1818
+ sage: w.support()
1819
+ {1, 2}
1820
+ """
1821
+ return set(self.reduced_word())
1822
+
1823
+ def has_full_support(self) -> bool:
1824
+ r"""
1825
+ Return whether ``self`` has full support.
1826
+
1827
+ An element is said to have full support if its support contains
1828
+ all simple reflections.
1829
+
1830
+ EXAMPLES::
1831
+
1832
+ sage: W = CoxeterGroups().example()
1833
+ sage: w = W.from_reduced_word([1,2,1])
1834
+ sage: w.has_full_support()
1835
+ False
1836
+ sage: w = W.from_reduced_word([1,2,1,0,1])
1837
+ sage: w.has_full_support()
1838
+ True
1839
+ """
1840
+ return self.support() == set(self.parent().index_set())
1841
+
1842
+ def reduced_word_graph(self):
1843
+ r"""
1844
+ Return the reduced word graph of ``self``.
1845
+
1846
+ The reduced word graph of an element `w` in a Coxeter group
1847
+ is the graph whose vertices are the reduced words for `w`
1848
+ (see :meth:`reduced_word` for a definition of this term),
1849
+ and which has an `m`-colored edge between two reduced words
1850
+ `x` and `y` whenever `x` and `y` differ by exactly one
1851
+ length-`m` braid move (with `m \geq 2`).
1852
+
1853
+ This graph is always connected (a theorem due to Tits) and
1854
+ has no multiple edges.
1855
+
1856
+ EXAMPLES::
1857
+
1858
+ sage: # needs sage.combinat sage.graphs sage.groups
1859
+ sage: W = WeylGroup(['A', 3], prefix='s')
1860
+ sage: w0 = W.long_element()
1861
+ sage: G = w0.reduced_word_graph()
1862
+ sage: G.num_verts()
1863
+ 16
1864
+ sage: len(w0.reduced_words())
1865
+ 16
1866
+ sage: G.num_edges()
1867
+ 18
1868
+ sage: len([e for e in G.edges(sort=False) if e[2] == 2])
1869
+ 10
1870
+ sage: len([e for e in G.edges(sort=False) if e[2] == 3])
1871
+ 8
1872
+
1873
+ TESTS::
1874
+
1875
+ sage: p = Permutation([3,2,4,1])
1876
+ sage: pp = WeylGroup(['A',3]).from_reduced_word(p.reduced_word()) # needs sage.combinat sage.groups
1877
+ sage: pp.reduced_word_graph() # needs sage.combinat sage.graphs sage.groups
1878
+ Graph on 3 vertices
1879
+
1880
+ sage: # needs sage.combinat sage.graphs sage.groups
1881
+ sage: w1 = W.one()
1882
+ sage: G = w1.reduced_word_graph()
1883
+ sage: G.num_verts()
1884
+ 1
1885
+ sage: G.num_edges()
1886
+ 0
1887
+
1888
+ .. SEEALSO::
1889
+
1890
+ :meth:`.reduced_words`, :meth:`.reduced_word_reverse_iterator`,
1891
+ :meth:`length`, :meth:`reduced_word`
1892
+ """
1893
+ R = self.reduced_words()
1894
+ from sage.graphs.graph import Graph
1895
+ # Special case for when the graph does not contain any edges
1896
+ if len(R) == 1:
1897
+ return Graph({tuple(R[0]): []}, immutable=True)
1898
+
1899
+ P = self.parent()
1900
+ edges = []
1901
+ for i, x in enumerate(R):
1902
+ x = tuple(x)
1903
+ for y in R[i:]:
1904
+ y = tuple(y)
1905
+ # Check that the reduced expressions differ by only
1906
+ # a single braid move
1907
+ j = 0
1908
+ while j < len(x) and x[j] == y[j]:
1909
+ j += 1
1910
+ if j == len(x):
1911
+ continue
1912
+ a, b = x[j], y[j]
1913
+ m = P.coxeter_matrix()[a, b]
1914
+ subword = [a, b] * (m // 2)
1915
+ subword2 = [b, a] * (m // 2)
1916
+ if m % 2:
1917
+ subword.append(a)
1918
+ subword2.append(b)
1919
+ if (x[j:j + m] != tuple(subword)
1920
+ or y[j:j + m] != tuple(subword2)
1921
+ or x[j + m:] != y[j + m:]):
1922
+ continue
1923
+ edges.append([x, y, m])
1924
+ G = Graph(edges, immutable=True, format='list_of_edges')
1925
+ colors = {2: 'blue', 3: 'red', 4: 'green'}
1926
+ G.set_latex_options(edge_labels=True,
1927
+ color_by_label=lambda x: colors[x])
1928
+ return G
1929
+
1930
+ def length(self):
1931
+ r"""
1932
+ Return the length of ``self``.
1933
+
1934
+ This is the minimal length of
1935
+ a product of simple reflections giving ``self``.
1936
+
1937
+ EXAMPLES::
1938
+
1939
+ sage: W = CoxeterGroups().example()
1940
+ sage: s1 = W.simple_reflection(1)
1941
+ sage: s2 = W.simple_reflection(2)
1942
+ sage: s1.length()
1943
+ 1
1944
+ sage: (s1*s2).length()
1945
+ 2
1946
+ sage: W = CoxeterGroups().example()
1947
+ sage: s = W.simple_reflections()
1948
+ sage: w = s[0]*s[1]*s[0]
1949
+ sage: w.length()
1950
+ 3
1951
+ sage: W = CoxeterGroups().example()
1952
+ sage: R.<x> = ZZ[]
1953
+ sage: s = sum(x^w.length() for w in W)
1954
+ sage: p = prod(sum(x^i for i in range(j)) for j in range(1, 5))
1955
+ sage: s - p
1956
+ 0
1957
+
1958
+ .. SEEALSO::
1959
+
1960
+ :meth:`.reduced_word`
1961
+
1962
+ .. TODO::
1963
+
1964
+ Should use reduced_word_iterator (or reverse_iterator)
1965
+ """
1966
+ return len(self.reduced_word())
1967
+
1968
+ def reflection_length(self):
1969
+ """
1970
+ Return the reflection length of ``self``.
1971
+
1972
+ The reflection length is the length of the shortest expression
1973
+ of the element as a product of reflections.
1974
+
1975
+ .. SEEALSO::
1976
+
1977
+ :meth:`absolute_length`
1978
+
1979
+ EXAMPLES::
1980
+
1981
+ sage: W = WeylGroup(['A', 3]) # needs sage.combinat sage.groups
1982
+ sage: s = W.simple_reflections() # needs sage.combinat sage.groups
1983
+ sage: (s[1]*s[2]*s[3]).reflection_length() # needs sage.combinat sage.groups
1984
+ 3
1985
+
1986
+ sage: W = SymmetricGroup(4) # needs sage.groups
1987
+ sage: s = W.simple_reflections() # needs sage.groups
1988
+ sage: (s[3]*s[2]*s[3]).reflection_length() # needs sage.combinat sage.groups
1989
+ 1
1990
+ """
1991
+ return self.absolute_length()
1992
+
1993
+ def absolute_length(self):
1994
+ """
1995
+ Return the absolute length of ``self``.
1996
+
1997
+ The absolute length is the length of the shortest expression
1998
+ of the element as a product of reflections. In general,
1999
+ we use Theorem 1.1 in [Dy2001]_.
2000
+
2001
+ .. SEEALSO::
2002
+
2003
+ :meth:`absolute_le`,
2004
+ :meth:`absolute_chain`
2005
+
2006
+ EXAMPLES::
2007
+
2008
+ sage: W = WeylGroup(["A", 3]) # needs sage.combinat sage.groups
2009
+ sage: s = W.simple_reflections() # needs sage.combinat sage.groups
2010
+ sage: (s[1]*s[2]*s[3]).absolute_length() # needs sage.combinat sage.groups
2011
+ 3
2012
+
2013
+ sage: W = SymmetricGroup(4) # needs sage.groups
2014
+ sage: s = W.simple_reflections() # needs sage.groups
2015
+ sage: (s[3]*s[2]*s[1]).absolute_length() # needs sage.combinat sage.groups
2016
+ 3
2017
+
2018
+ sage: # needs sage.graphs sage.groups
2019
+ sage: W = CoxeterGroup(["A",2,1])
2020
+ sage: (r, s, t) = W.simple_reflections()
2021
+ sage: (r * s * r * t).absolute_length()
2022
+ 2
2023
+ sage: W.one().absolute_length()
2024
+ 0
2025
+ sage: r.absolute_length()
2026
+ 1
2027
+ sage: (r * s).absolute_length()
2028
+ 2
2029
+ sage: (r * s * r).absolute_length()
2030
+ 1
2031
+ sage: W = CoxeterGroup(['A', 3, 1])
2032
+ sage: (r, s, t, u) = W.simple_reflections()
2033
+ sage: (r * s * t * u).absolute_length()
2034
+ 4
2035
+ sage: (r * s * t * u * s).absolute_length()
2036
+ 3
2037
+ """
2038
+ if self.length() <= 2: # trivial cases
2039
+ return self.length()
2040
+ return len(self.absolute_chain_reflections())
2041
+
2042
+ def absolute_chain(self):
2043
+ r"""
2044
+ Return a (saturated) chain in absolute order from ``1``
2045
+ to ``self``.
2046
+
2047
+ .. SEEALSO::
2048
+
2049
+ :meth:`absolute_chain_reflections`
2050
+
2051
+ EXAMPLES::
2052
+
2053
+ sage: # needs sage.graphs sage.groups
2054
+ sage: W = CoxeterGroup(['A', 2, 1])
2055
+ sage: (r, s, t) = W.simple_reflections()
2056
+ sage: (r * s * r * t).absolute_chain()
2057
+ [
2058
+ [1 0 0] [ 0 -1 2] [ 2 1 -2]
2059
+ [0 1 0] [-1 0 2] [ 1 2 -2]
2060
+ [0 0 1], [ 0 0 1], [ 1 1 -1]
2061
+ ]
2062
+ """
2063
+ reflections = self.absolute_chain_reflections()
2064
+ P = self.parent()
2065
+ return [P.prod(reversed(reflections[:i]))
2066
+ for i in range(len(reflections) + 1)]
2067
+
2068
+ def absolute_chain_reflections(self):
2069
+ r"""
2070
+ Return a list of reflection which, when (left) multiplied in order,
2071
+ give ``self``.
2072
+
2073
+ This method is based on Theorem 1.1 in [Dy2001]_, combined with
2074
+ the strong exchange condition. As an example, if `W` is a type
2075
+ `A_2` Coxeter group with simple reflections `a`, `b`, then the
2076
+ absolute chain reflections for the element `w = ab` is the list
2077
+ `[a, aba]` as `w = (aba) a = ab`.
2078
+
2079
+ .. SEEALSO::
2080
+
2081
+ :meth:`absolute_length`,
2082
+ :meth:`absolute_chain`
2083
+
2084
+ EXAMPLES::
2085
+
2086
+ sage: # needs sage.graphs sage.groups
2087
+ sage: W = CoxeterGroup(["A",2,1])
2088
+ sage: W.one().absolute_chain_reflections()
2089
+ []
2090
+ sage: (r, s, t) = W.simple_reflections()
2091
+ sage: r.absolute_chain_reflections()
2092
+ [
2093
+ [-1 1 1]
2094
+ [ 0 1 0]
2095
+ [ 0 0 1]
2096
+ ]
2097
+ sage: (r * s).absolute_chain_reflections()
2098
+ [
2099
+ [-1 1 1] [ 0 -1 2]
2100
+ [ 0 1 0] [-1 0 2]
2101
+ [ 0 0 1], [ 0 0 1]
2102
+ ]
2103
+ sage: (r * s * r * t).absolute_chain_reflections()
2104
+ [
2105
+ [ 0 -1 2] [-1 -2 4]
2106
+ [-1 0 2] [-2 -1 4]
2107
+ [ 0 0 1], [-1 -1 3]
2108
+ ]
2109
+ sage: W = CoxeterGroup(['A', 3, 1])
2110
+ sage: (r, s, t, u) = W.simple_reflections()
2111
+ sage: (r * s * t * u).absolute_chain_reflections()
2112
+ [
2113
+ [-1 1 0 1] [ 0 -1 1 1] [ 0 0 -1 2] [-3 2 0 2]
2114
+ [ 0 1 0 0] [-1 0 1 1] [-1 1 -1 2] [-2 2 0 1]
2115
+ [ 0 0 1 0] [ 0 0 1 0] [-1 0 0 2] [-2 1 1 1]
2116
+ [ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1], [-2 1 0 2]
2117
+ ]
2118
+ sage: (r * s * t * u * s).absolute_chain_reflections()
2119
+ [
2120
+ [-1 1 0 1] [ 0 0 -1 2] [-3 2 0 2]
2121
+ [ 0 1 0 0] [-1 1 -1 2] [-2 2 0 1]
2122
+ [ 0 0 1 0] [-1 0 0 2] [-2 1 1 1]
2123
+ [ 0 0 0 1], [ 0 0 0 1], [-2 1 0 2]
2124
+ ]
2125
+ """
2126
+ P = self.parent()
2127
+ if self.is_one():
2128
+ return []
2129
+ w = self.reduced_word()
2130
+ n = len(w)
2131
+
2132
+ if n == 1: # trivial case
2133
+ return [self]
2134
+ if n == 2: # trivial case
2135
+ left_refl = P.simple_reflection(w[0])
2136
+ return [left_refl, self * left_refl]
2137
+
2138
+ import itertools
2139
+ s = P.simple_reflections()
2140
+ rev = P.one()
2141
+ cur = P.one()
2142
+ reflections = []
2143
+ for val in w:
2144
+ cur = cur * s[val]
2145
+ reflections.append(cur * rev)
2146
+ rev = s[val] * rev
2147
+ for ell in range(n):
2148
+ for chain in itertools.combinations(reflections, ell):
2149
+ if P.prod(reversed(chain)) == self:
2150
+ return list(chain)
2151
+ # If we get here it's cause ell == n and so we need all of the
2152
+ # refelctions
2153
+ return reflections
2154
+
2155
+ def absolute_le(self, other):
2156
+ r"""
2157
+ Return whether ``self`` is smaller than ``other`` in the absolute
2158
+ order.
2159
+
2160
+ A general reflection is an element of the form `w s_i w^{-1}`,
2161
+ where `s_i` is a simple reflection. The absolute order is defined
2162
+ analogously to the weak order but using general reflections rather
2163
+ than just simple reflections.
2164
+
2165
+ This partial order can be used to define noncrossing partitions
2166
+ associated with this Coxeter group.
2167
+
2168
+ .. SEEALSO::
2169
+
2170
+ :meth:`absolute_length`
2171
+
2172
+ EXAMPLES::
2173
+
2174
+ sage: # needs sage.combinat sage.groups
2175
+ sage: W = WeylGroup(["A", 3])
2176
+ sage: s = W.simple_reflections()
2177
+ sage: w0 = s[1]
2178
+ sage: w1 = s[1]*s[2]*s[3]
2179
+ sage: w0.absolute_le(w1)
2180
+ True
2181
+ sage: w1.absolute_le(w0)
2182
+ False
2183
+ sage: w1.absolute_le(w1)
2184
+ True
2185
+
2186
+ TESTS:
2187
+
2188
+ Check that this is independent of the implementation of the group, see :issue:`34799`::
2189
+
2190
+ sage: # needs sage.combinat sage.groups
2191
+ sage: W1 = WeylGroup(['A', 2])
2192
+ sage: W2 = Permutations(3)
2193
+ sage: P = lambda pi: W2(list(pi.to_permutation()))
2194
+ sage: d1 = set((P(w1), P(w2)) for w1 in W1 for w2 in W1
2195
+ ....: if w1.absolute_le(w2))
2196
+ sage: d2 = set((w1, w2) for w1 in W2 for w2 in W2
2197
+ ....: if w1.absolute_le(w2))
2198
+ sage: d1 == d2
2199
+ True
2200
+ sage: sage.combinat.permutation.Permutations.options.mult = "r2l"
2201
+ sage: d3 = set((w1, w2)
2202
+ ....: for w1 in W2 for w2 in W2 if w1.absolute_le(w2))
2203
+ sage: d1 == d3
2204
+ True
2205
+ sage: sage.combinat.permutation.Permutations.options._reset()
2206
+
2207
+ sage: # needs sage.combinat sage.groups
2208
+ sage: W1 = WeylGroup(['B', 2])
2209
+ sage: W2 = SignedPermutations(2)
2210
+ sage: P = lambda pi: W2(list(pi.to_permutation()))
2211
+ sage: d1 = set((P(w1), P(w2))
2212
+ ....: for w1 in W1 for w2 in W1 if w1.absolute_le(w2))
2213
+ sage: d2 = set((w1, w2)
2214
+ ....: for w1 in W2 for w2 in W2 if w1.absolute_le(w2))
2215
+ sage: d1 == d2
2216
+ True
2217
+ """
2218
+ if self == other:
2219
+ return True
2220
+ if self.absolute_length() >= other.absolute_length():
2221
+ return False
2222
+ return self.absolute_length() + (self.inverse() * other).absolute_length() == other.absolute_length()
2223
+
2224
+ def absolute_covers(self):
2225
+ r"""
2226
+ Return the list of covers of ``self`` in absolute order.
2227
+
2228
+ .. SEEALSO::
2229
+
2230
+ :meth:`absolute_length`
2231
+
2232
+ EXAMPLES::
2233
+
2234
+ sage: # needs sage.combinat sage.groups
2235
+ sage: W = WeylGroup(["A", 3])
2236
+ sage: s = W.simple_reflections()
2237
+ sage: w0 = s[1]
2238
+ sage: w1 = s[1]*s[2]*s[3]
2239
+ sage: list(w0.absolute_covers())
2240
+ [
2241
+ [0 0 1 0] [0 1 0 0] [0 1 0 0] [0 0 0 1] [0 1 0 0]
2242
+ [1 0 0 0] [1 0 0 0] [0 0 1 0] [1 0 0 0] [0 0 0 1]
2243
+ [0 1 0 0] [0 0 0 1] [1 0 0 0] [0 0 1 0] [0 0 1 0]
2244
+ [0 0 0 1], [0 0 1 0], [0 0 0 1], [0 1 0 0], [1 0 0 0]
2245
+ ]
2246
+ """
2247
+ W = self.parent()
2248
+ for t in W.reflections():
2249
+ if self.absolute_length() < (self * t).absolute_length():
2250
+ yield self * t
2251
+
2252
+ def canonical_matrix(self):
2253
+ r"""
2254
+ Return the matrix of ``self`` in the canonical faithful
2255
+ representation.
2256
+
2257
+ This is an `n`-dimension real faithful essential representation,
2258
+ where `n` is the number of generators of the Coxeter group.
2259
+ Note that this is not always the most natural matrix
2260
+ representation, for instance in type `A_n`.
2261
+
2262
+ EXAMPLES::
2263
+
2264
+ sage: W = WeylGroup(["A", 3]) # needs sage.combinat sage.groups
2265
+ sage: s = W.simple_reflections() # needs sage.combinat sage.groups
2266
+ sage: (s[1]*s[2]*s[3]).canonical_matrix() # needs sage.combinat sage.groups
2267
+ [ 0 0 -1]
2268
+ [ 1 0 -1]
2269
+ [ 0 1 -1]
2270
+ """
2271
+ G = self.parent().canonical_representation()
2272
+ return G.prod(G.simple_reflection(i) for i in self.reduced_word()).matrix()
2273
+
2274
+ def coset_representative(self, index_set, side='right'):
2275
+ r"""
2276
+ Return the unique shortest element of the Coxeter group
2277
+ `W` which is in the same left (resp. right) coset as
2278
+ ``self``, with respect to the parabolic subgroup `W_I`.
2279
+
2280
+ INPUT:
2281
+
2282
+ - ``index_set`` -- a subset (or iterable) of the nodes of the Dynkin diagram
2283
+ - ``side`` -- ``'left'`` or ``'right'``
2284
+
2285
+ EXAMPLES::
2286
+
2287
+ sage: W = CoxeterGroups().example(5)
2288
+ sage: s = W.simple_reflections()
2289
+ sage: w = s[2]*s[1]*s[3]
2290
+ sage: w.coset_representative([]).reduced_word()
2291
+ [2, 3, 1]
2292
+ sage: w.coset_representative([1]).reduced_word()
2293
+ [2, 3]
2294
+ sage: w.coset_representative([1,2]).reduced_word()
2295
+ [2, 3]
2296
+ sage: w.coset_representative([1,3] ).reduced_word()
2297
+ [2]
2298
+ sage: w.coset_representative([2,3] ).reduced_word()
2299
+ [2, 1]
2300
+ sage: w.coset_representative([1,2,3] ).reduced_word()
2301
+ []
2302
+ sage: w.coset_representative([], side='left').reduced_word()
2303
+ [2, 3, 1]
2304
+ sage: w.coset_representative([1], side='left').reduced_word()
2305
+ [2, 3, 1]
2306
+ sage: w.coset_representative([1,2], side='left').reduced_word()
2307
+ [3]
2308
+ sage: w.coset_representative([1,3], side='left').reduced_word()
2309
+ [2, 3, 1]
2310
+ sage: w.coset_representative([2,3], side='left').reduced_word()
2311
+ [1]
2312
+ sage: w.coset_representative([1,2,3], side='left').reduced_word()
2313
+ []
2314
+ """
2315
+ while True:
2316
+ i = self.first_descent(side=side, index_set=index_set)
2317
+ if i is None:
2318
+ return self
2319
+ self = self.apply_simple_reflection(i, side=side)
2320
+
2321
+ def apply_simple_projection(self, i, side='right', length_increasing=True):
2322
+ r"""
2323
+ Return the result of the application of the simple
2324
+ projection `\pi_i` (resp. `\overline\pi_i`) on ``self``.
2325
+
2326
+ INPUT:
2327
+
2328
+ - ``i`` -- an element of the index set of the Coxeter group
2329
+ - ``side`` -- ``'left'`` or ``'right'`` (default: ``'right'``)
2330
+ - ``length_increasing`` -- boolean (default: ``True``);
2331
+ specifying the direction of the projection
2332
+
2333
+ See :meth:`CoxeterGroups.ParentMethods.simple_projections`
2334
+ for the definition of the simple projections.
2335
+
2336
+ EXAMPLES::
2337
+
2338
+ sage: W = CoxeterGroups().example()
2339
+ sage: w = W.an_element()
2340
+ sage: w
2341
+ (1, 2, 3, 0)
2342
+ sage: w.apply_simple_projection(2)
2343
+ (1, 2, 3, 0)
2344
+ sage: w.apply_simple_projection(2, length_increasing=False)
2345
+ (1, 2, 0, 3)
2346
+
2347
+ sage: # needs sage.combinat sage.groups
2348
+ sage: W = WeylGroup(['C', 4], prefix='s')
2349
+ sage: v = W.from_reduced_word([1,2,3,4,3,1])
2350
+ sage: v
2351
+ s1*s2*s3*s4*s3*s1
2352
+ sage: v.apply_simple_projection(2)
2353
+ s1*s2*s3*s4*s3*s1*s2
2354
+ sage: v.apply_simple_projection(2, side='left')
2355
+ s1*s2*s3*s4*s3*s1
2356
+ sage: v.apply_simple_projection(1, length_increasing=False)
2357
+ s1*s2*s3*s4*s3
2358
+ """
2359
+ if self.has_descent(i, side=side, positive=length_increasing):
2360
+ return self.apply_simple_reflection(i, side=side)
2361
+ return self
2362
+
2363
+ def binary_factorizations(self, predicate=ConstantFunction(True)):
2364
+ """
2365
+ Return the set of all the factorizations `self = u v` such
2366
+ that `l(self) = l(u) + l(v)`.
2367
+
2368
+ Iterating through this set is Constant Amortized Time
2369
+ (counting arithmetic operations in the Coxeter group as
2370
+ constant time) complexity, and memory linear in the length
2371
+ of ``self``.
2372
+
2373
+ One can pass as optional argument a predicate p such that
2374
+ `p(u)` implies `p(u')` for any `u` left factor of ``self``
2375
+ and `u'` left factor of `u`. Then this returns only the
2376
+ factorizations `self = uv` such `p(u)` holds.
2377
+
2378
+ EXAMPLES:
2379
+
2380
+ We construct the set of all factorizations of the maximal
2381
+ element of the group::
2382
+
2383
+ sage: # needs sage.combinat sage.groups
2384
+ sage: W = WeylGroup(['A', 3])
2385
+ sage: s = W.simple_reflections()
2386
+ sage: w0 = W.from_reduced_word([1,2,3,1,2,1])
2387
+ sage: w0.binary_factorizations().cardinality()
2388
+ 24
2389
+
2390
+ The same number of factorizations, by bounded length::
2391
+
2392
+ sage: [w0.binary_factorizations( # needs sage.combinat sage.groups
2393
+ ....: lambda u: u.length() <= l
2394
+ ....: ).cardinality()
2395
+ ....: for l in [-1,0,1,2,3,4,5,6]]
2396
+ [0, 1, 4, 9, 15, 20, 23, 24]
2397
+
2398
+ The number of factorizations of the elements just below
2399
+ the maximal element::
2400
+
2401
+ sage: [(s[i]*w0).binary_factorizations().cardinality() # needs sage.combinat sage.groups
2402
+ ....: for i in [1,2,3]]
2403
+ [12, 12, 12]
2404
+ sage: w0.binary_factorizations(lambda u: False).cardinality() # needs sage.combinat sage.groups
2405
+ 0
2406
+
2407
+ TESTS::
2408
+
2409
+ sage: w0.binary_factorizations().category() # needs sage.combinat sage.groups
2410
+ Category of finite enumerated sets
2411
+
2412
+ Check that this is independent of the implementation of the group, see :issue:`34799`::
2413
+
2414
+ sage: # needs sage.combinat sage.groups
2415
+ sage: W1 = WeylGroup(['A', 3])
2416
+ sage: W2 = Permutations(4)
2417
+ sage: P = lambda pi: W2(list(pi.to_permutation()))
2418
+ sage: d1 = {P(pi): set((P(w[0]), P(w[1]))
2419
+ ....: for w in pi.binary_factorizations())
2420
+ ....: for pi in W1}
2421
+ sage: d2 = {pi: set(pi.binary_factorizations()) for pi in W2}
2422
+ sage: d1 == d2
2423
+ True
2424
+ sage: sage.combinat.permutation.Permutations.options.mult = "r2l"
2425
+ sage: d3 = {pi: set(pi.binary_factorizations()) for pi in W2}
2426
+ sage: d1 == d3
2427
+ True
2428
+ sage: sage.combinat.permutation.Permutations.options._reset()
2429
+ """
2430
+ from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
2431
+ W = self.parent()
2432
+ if not predicate(W.one()):
2433
+ from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
2434
+ return FiniteEnumeratedSet([])
2435
+
2436
+ def succ(u_v):
2437
+ u, v = u_v
2438
+ for i in v.descents(side='left'):
2439
+ u1 = u.apply_simple_reflection_right(i)
2440
+ if i == u1.first_descent() and predicate(u1):
2441
+ yield u1, v.apply_simple_reflection_left(i)
2442
+ return RecursivelyEnumeratedSet_forest(((W.one(), self),), succ,
2443
+ category=FiniteEnumeratedSets())
2444
+
2445
+ @cached_in_parent_method
2446
+ def bruhat_lower_covers(self):
2447
+ r"""
2448
+ Return all elements that ``self`` covers in (strong) Bruhat order.
2449
+
2450
+ If ``w = self`` has a descent at `i`, then the elements that
2451
+ `w` covers are exactly `\{ws_i, u_1s_i, u_2s_i,..., u_js_i\}`,
2452
+ where the `u_k` are elements that `ws_i` covers that also
2453
+ do not have a descent at `i`.
2454
+
2455
+ EXAMPLES::
2456
+
2457
+ sage: W = WeylGroup(["A", 3]) # needs sage.combinat sage.groups
2458
+ sage: w = W.from_reduced_word([3,2,3]) # needs sage.combinat sage.groups
2459
+ sage: print([v.reduced_word() for v in w.bruhat_lower_covers()]) # needs sage.combinat sage.groups
2460
+ [[3, 2], [2, 3]]
2461
+
2462
+ sage: # needs sage.combinat sage.groups
2463
+ sage: W = WeylGroup(["A", 3])
2464
+ sage: print([v.reduced_word()
2465
+ ....: for v in W.simple_reflection(1).bruhat_lower_covers()])
2466
+ [[]]
2467
+ sage: print([v.reduced_word()
2468
+ ....: for v in W.one().bruhat_lower_covers()])
2469
+ []
2470
+ sage: W = WeylGroup(["B", 4, 1])
2471
+ sage: w = W.from_reduced_word([0,2])
2472
+ sage: print([v.reduced_word() for v in w.bruhat_lower_covers()])
2473
+ [[2], [0]]
2474
+ sage: W = WeylGroup("A3", prefix='s', implementation='permutation')
2475
+ sage: s1, s2, s3 = W.simple_reflections()
2476
+ sage: (s1*s2*s3*s1).bruhat_lower_covers()
2477
+ [s2*s1*s3, s1*s2*s1, s1*s2*s3]
2478
+
2479
+ We now show how to construct the Bruhat poset::
2480
+
2481
+ sage: # needs sage.combinat sage.groups
2482
+ sage: W = WeylGroup(["A", 3])
2483
+ sage: covers = tuple([u, v]
2484
+ ....: for v in W for u in v.bruhat_lower_covers())
2485
+ sage: P = Poset((W, covers), cover_relations=True) # needs sage.graphs
2486
+ sage: P.show() # needs sage.graphs sage.plot
2487
+
2488
+ Alternatively, one can just use::
2489
+
2490
+ sage: P = W.bruhat_poset() # needs sage.combinat sage.graphs sage.groups
2491
+
2492
+ The algorithm is taken from Stembridge's 'coxeter/weyl' package for Maple.
2493
+ """
2494
+ desc = self.first_descent(side='right')
2495
+ if desc is None:
2496
+ return []
2497
+ ww = self.apply_simple_reflection(desc, side='right')
2498
+ return [u.apply_simple_reflection(desc, side='right') for u in ww.bruhat_lower_covers() if not u.has_descent(desc, side='right')] + [ww]
2499
+
2500
+ @cached_in_parent_method
2501
+ def bruhat_upper_covers(self):
2502
+ r"""
2503
+ Return all elements that cover ``self`` in (strong) Bruhat order.
2504
+
2505
+ The algorithm works recursively, using the 'inverse' of the method described for
2506
+ lower covers :meth:`bruhat_lower_covers`. Namely, it runs through all `i` in the
2507
+ index set. Let `w` equal ``self``. If `w` has no right descent `i`, then `w s_i` is a cover;
2508
+ if `w` has a decent at `i`, then `u_j s_i` is a cover of `w` where `u_j` is a cover
2509
+ of `w s_i`.
2510
+
2511
+ EXAMPLES::
2512
+
2513
+ sage: W = WeylGroup(['A', 3, 1], prefix='s') # needs sage.combinat sage.groups
2514
+ sage: w = W.from_reduced_word([1,2,1]) # needs sage.combinat sage.groups
2515
+ sage: w.bruhat_upper_covers() # needs sage.combinat sage.groups
2516
+ [s1*s2*s1*s0, s1*s2*s0*s1, s0*s1*s2*s1, s3*s1*s2*s1, s2*s3*s1*s2, s1*s2*s3*s1]
2517
+
2518
+ sage: W = WeylGroup(['A', 3]) # needs sage.combinat sage.groups
2519
+ sage: w = W.long_element() # needs sage.combinat sage.groups
2520
+ sage: w.bruhat_upper_covers() # needs sage.combinat sage.groups
2521
+ []
2522
+
2523
+ sage: # needs sage.combinat sage.groups
2524
+ sage: W = WeylGroup(['A', 3])
2525
+ sage: w = W.from_reduced_word([1,2,1])
2526
+ sage: S = [v for v in W if w in v.bruhat_lower_covers()]
2527
+ sage: C = w.bruhat_upper_covers()
2528
+ sage: set(S) == set(C)
2529
+ True
2530
+ """
2531
+ Covers = set()
2532
+ for i in self.parent().index_set():
2533
+ if i in self.descents(side='right'):
2534
+ Covers.update(x.apply_simple_reflection(i, side='right')
2535
+ for x in self.apply_simple_reflection(i, side='right').bruhat_upper_covers()
2536
+ if i not in x.descents(side='right'))
2537
+ else:
2538
+ Covers.add(self.apply_simple_reflection(i, side='right'))
2539
+ return sorted(Covers)
2540
+
2541
+ @cached_in_parent_method
2542
+ def bruhat_lower_covers_reflections(self):
2543
+ r"""
2544
+ Return all 2-tuples of lower_covers and reflections (``v``, ``r``) where ``v`` is covered by ``self`` and ``r`` is the reflection such that ``self`` = ``v`` ``r``.
2545
+
2546
+ ALGORITHM:
2547
+
2548
+ See :meth:`.bruhat_lower_covers`
2549
+
2550
+ EXAMPLES::
2551
+
2552
+ sage: W = WeylGroup(['A', 3], prefix='s') # needs sage.combinat sage.groups
2553
+ sage: w = W.from_reduced_word([3,1,2,1]) # needs sage.combinat sage.groups
2554
+ sage: w.bruhat_lower_covers_reflections() # needs sage.combinat sage.groups
2555
+ [(s1*s2*s1, s1*s2*s3*s2*s1), (s3*s2*s1, s2), (s3*s1*s2, s1)]
2556
+
2557
+ TESTS:
2558
+
2559
+ Check bug discovered in :issue:`32669` is fixed::
2560
+
2561
+ sage: W = CoxeterGroup(['A', 3], implementation='permutation') # needs sage.combinat sage.groups
2562
+ sage: W.w0.bruhat_lower_covers_reflections() # needs sage.combinat sage.groups
2563
+ [((1,3,7,9)(2,11,6,10)(4,8,5,12), (2,5)(3,9)(4,6)(8,11)(10,12)),
2564
+ ((1,11)(3,10)(4,9)(5,7)(6,12), (1,4)(2,8)(3,5)(7,10)(9,11)),
2565
+ ((1,9,7,3)(2,10,6,11)(4,12,5,8), (1,7)(2,4)(5,6)(8,10)(11,12))]
2566
+ """
2567
+ i = self.first_descent(side='right')
2568
+ if i is None:
2569
+ return []
2570
+ wi = self.apply_simple_reflection(i, side='right')
2571
+ return [(u.apply_simple_reflection(i, side='right'),
2572
+ r.apply_conjugation_by_simple_reflection(i))
2573
+ for u, r in wi.bruhat_lower_covers_reflections()
2574
+ if not u.has_descent(i, side='right')] + [
2575
+ (wi, self.parent().simple_reflection(i))]
2576
+
2577
+ def lower_cover_reflections(self, side='right'):
2578
+ r"""
2579
+ Return the reflections ``t`` such that ``self`` covers ``self`` ``t``.
2580
+
2581
+ If ``side`` is 'left', ``self`` covers ``t`` ``self``.
2582
+
2583
+ EXAMPLES::
2584
+
2585
+ sage: # needs sage.combinat sage.groups
2586
+ sage: W = WeylGroup(['A', 3],prefix='s')
2587
+ sage: w = W.from_reduced_word([3,1,2,1])
2588
+ sage: w.lower_cover_reflections()
2589
+ [s1*s2*s3*s2*s1, s2, s1]
2590
+ sage: w.lower_cover_reflections(side='left')
2591
+ [s2*s3*s2, s3, s1]
2592
+ """
2593
+ if side == 'left':
2594
+ self = self.inverse()
2595
+ return [x[1] for x in self.bruhat_lower_covers_reflections()]
2596
+
2597
+ @cached_in_parent_method
2598
+ def bruhat_upper_covers_reflections(self):
2599
+ r"""
2600
+ Return all 2-tuples of covers and reflections (``v``, ``r``) where ``v`` covers ``self`` and ``r`` is the reflection such that ``self`` = ``v`` ``r``.
2601
+
2602
+ ALGORITHM:
2603
+
2604
+ See :meth:`.bruhat_upper_covers`
2605
+
2606
+ EXAMPLES::
2607
+
2608
+ sage: W = WeylGroup(['A', 4], prefix='s') # needs sage.combinat sage.groups
2609
+ sage: w = W.from_reduced_word([3,1,2,1]) # needs sage.combinat sage.groups
2610
+ sage: w.bruhat_upper_covers_reflections() # needs sage.combinat sage.groups
2611
+ [(s1*s2*s3*s2*s1, s3), (s2*s3*s1*s2*s1, s2*s3*s2),
2612
+ (s3*s4*s1*s2*s1, s4), (s4*s3*s1*s2*s1, s1*s2*s3*s4*s3*s2*s1)]
2613
+ """
2614
+ Covers = set()
2615
+ for i in self.parent().index_set():
2616
+ wi = self.apply_simple_reflection(i)
2617
+ if i in self.descents():
2618
+ Covers.update((u.apply_simple_reflection(i), r.apply_conjugation_by_simple_reflection(i))
2619
+ for u, r in wi.bruhat_upper_covers_reflections() if i not in u.descents())
2620
+ else:
2621
+ Covers.add((wi, self.parent().simple_reflection(i)))
2622
+ return sorted(Covers)
2623
+
2624
+ def cover_reflections(self, side='right'):
2625
+ r"""
2626
+ Return the set of reflections ``t`` such that ``self`` ``t`` covers ``self``.
2627
+
2628
+ If ``side`` is 'left', ``t`` ``self`` covers ``self``.
2629
+
2630
+ EXAMPLES::
2631
+
2632
+ sage: # needs sage.combinat sage.groups
2633
+ sage: W = WeylGroup(['A', 4], prefix='s')
2634
+ sage: w = W.from_reduced_word([3,1,2,1])
2635
+ sage: w.cover_reflections()
2636
+ [s3, s2*s3*s2, s4, s1*s2*s3*s4*s3*s2*s1]
2637
+ sage: w.cover_reflections(side='left')
2638
+ [s4, s2, s1*s2*s1, s3*s4*s3]
2639
+ """
2640
+ if side == 'left':
2641
+ self = self.inverse()
2642
+ return [x[1] for x in self.bruhat_upper_covers_reflections()]
2643
+
2644
+ @cached_in_parent_method
2645
+ def bruhat_le(self, other):
2646
+ """
2647
+ Return whether ``self`` <= ``other`` in the Bruhat order.
2648
+
2649
+ INPUT:
2650
+
2651
+ - ``other`` -- an element of the same Coxeter group
2652
+
2653
+ OUTPUT: boolean
2654
+
2655
+ EXAMPLES::
2656
+
2657
+ sage: # needs sage.combinat sage.groups
2658
+ sage: W = WeylGroup(["A", 3])
2659
+ sage: u = W.from_reduced_word([1,2,1])
2660
+ sage: v = W.from_reduced_word([1,2,3,2,1])
2661
+ sage: u.bruhat_le(u)
2662
+ True
2663
+ sage: u.bruhat_le(v)
2664
+ True
2665
+ sage: v.bruhat_le(u)
2666
+ False
2667
+ sage: v.bruhat_le(v)
2668
+ True
2669
+ sage: s = W.simple_reflections()
2670
+ sage: s[1].bruhat_le(W.one())
2671
+ False
2672
+
2673
+ The implementation uses the equivalent condition that any
2674
+ reduced word for ``other`` contains a reduced word for
2675
+ ``self`` as subword. See Stembridge, A short derivation of
2676
+ the Möbius function for the Bruhat order. J. Algebraic
2677
+ Combinatoric 25 (2007), no. 2, 141--148, Proposition 1.1.
2678
+
2679
+ Complexity: `O(l * c)`, where `l` is the minimum of the
2680
+ lengths of `u` and of `v`, and `c` is the cost of the low
2681
+ level methods :meth:`first_descent`, :meth:`has_descent`,
2682
+ :meth:`~sage.categories.complex_reflection_or_generalized_coxeter_groups.ComplexReflectionOrGeneralizedCoxeterGroups.ElementMethods.apply_simple_reflection`),
2683
+ etc. Those are typically `O(n)`, where `n` is the rank of the
2684
+ Coxeter group.
2685
+
2686
+ TESTS:
2687
+
2688
+ We now run consistency tests with permutations and
2689
+ :meth:`bruhat_lower_covers`::
2690
+
2691
+ sage: W = WeylGroup(["A", 3]) # needs sage.combinat sage.groups
2692
+ sage: P4 = Permutations(4)
2693
+ sage: def P4toW(w): return W.from_reduced_word(w.reduced_word())
2694
+ sage: for u in P4: # needs sage.combinat sage.groups
2695
+ ....: for v in P4:
2696
+ ....: assert u.bruhat_lequal(v) == P4toW(u).bruhat_le(P4toW(v))
2697
+
2698
+ sage: # needs sage.combinat sage.graphs sage.groups
2699
+ sage: W = WeylGroup(["B", 3])
2700
+ sage: P = W.bruhat_poset() # This is built from bruhat_lower_covers
2701
+ sage: Q = Poset((W, attrcall("bruhat_le"))) # long time (10s)
2702
+ sage: all(u.bruhat_le(v) == P.is_lequal(u,v) # long time (7s)
2703
+ ....: for u in W for v in W)
2704
+ True
2705
+ sage: all(P.is_lequal(u,v) == Q.is_lequal(u,v) # long time (9s)
2706
+ ....: for u in W for v in W)
2707
+ True
2708
+ """
2709
+ if not have_same_parent(self, other):
2710
+ raise TypeError("%s and %s do not have the same parent" % (self, other))
2711
+ # could first compare the length, when that information is cheap
2712
+ desc = other.first_descent()
2713
+ if desc is not None:
2714
+ return self.apply_simple_projection(desc, length_increasing=False).bruhat_le(other.apply_simple_reflection(desc))
2715
+ return self == other
2716
+
2717
+ @cached_in_parent_method
2718
+ def weak_le(self, other, side='right'):
2719
+ r"""
2720
+ Perform the comparison between ``self`` and ``other`` in
2721
+ weak (Bruhat) order.
2722
+
2723
+ INPUT:
2724
+
2725
+ - ``other`` -- an element of the same Coxeter group
2726
+ - ``side`` -- string (default: ``'right'``); ``'left'`` or ``'right'``
2727
+
2728
+ OUTPUT: boolean
2729
+
2730
+ This returns whether `u \leq v`, where `u` is ``self`` and `v`
2731
+ is ``other``, in left (resp. right) weak order, that is if `v`
2732
+ can be obtained from `u` by length increasing multiplication by
2733
+ simple reflections on the left (resp. right).
2734
+
2735
+ EXAMPLES::
2736
+
2737
+ sage: # needs sage.combinat sage.groups
2738
+ sage: W = WeylGroup(["A", 3])
2739
+ sage: u = W.from_reduced_word([1,2])
2740
+ sage: v = W.from_reduced_word([1,2,3,2])
2741
+ sage: u.weak_le(u)
2742
+ True
2743
+ sage: u.weak_le(v)
2744
+ True
2745
+ sage: v.weak_le(u)
2746
+ False
2747
+ sage: v.weak_le(v)
2748
+ True
2749
+
2750
+ Comparison for left weak order is achieved with the option ``side``::
2751
+
2752
+ sage: u.weak_le(v, side='left') # needs sage.combinat sage.groups
2753
+ False
2754
+
2755
+ The implementation uses the equivalent condition that any
2756
+ reduced word for `u` is a right (resp. left) prefix of
2757
+ some reduced word for `v`.
2758
+
2759
+ Complexity: `O(l * c)`, where `l` is the minimum of the
2760
+ lengths of `u` and of `v`, and `c` is the cost of the low
2761
+ level methods :meth:`first_descent`, :meth:`has_descent`,
2762
+ :meth:`~sage.categories.complex_reflection_or_generalized_coxeter_groups.ComplexReflectionOrGeneralizedCoxeterGroups.ElementMethods.apply_simple_reflection`),
2763
+ etc. Those are typically `O(n)`, where `n` is the rank of the
2764
+ Coxeter group.
2765
+
2766
+ We now run consistency tests with permutations::
2767
+
2768
+ sage: W = WeylGroup(["A", 3]) # needs sage.combinat sage.groups
2769
+ sage: P4 = Permutations(4)
2770
+ sage: def P4toW(w): return W.from_reduced_word(w.reduced_word())
2771
+ sage: for u in P4: # long time (5s on sage.math, 2011), needs sage.combinat sage.groups
2772
+ ....: for v in P4:
2773
+ ....: assert u.permutohedron_lequal(v) == P4toW(u).weak_le(P4toW(v))
2774
+ ....: assert u.permutohedron_lequal(v, side='left') == P4toW(u).weak_le(P4toW(v), side='left')
2775
+ """
2776
+ if not have_same_parent(self, other):
2777
+ raise TypeError(f"{self} and {other} do not have the same parent")
2778
+ # could first compare the length, when that information is cheap
2779
+ prefix_side = 'left' if side == 'right' else 'right'
2780
+
2781
+ while True:
2782
+ desc = self.first_descent(side=prefix_side)
2783
+ if desc is None:
2784
+ return True
2785
+ if not other.has_descent(desc, side=prefix_side):
2786
+ return False
2787
+ self = self.apply_simple_reflection(desc, side=prefix_side)
2788
+ other = other.apply_simple_reflection(desc, side=prefix_side)
2789
+
2790
+ def weak_covers(self, side='right', index_set=None, positive=False):
2791
+ """
2792
+ Return all elements that ``self`` covers in weak order.
2793
+
2794
+ INPUT:
2795
+
2796
+ - ``side`` -- ``'left'`` or ``'right'`` (default: ``'right'``)
2797
+ - ``positive`` -- boolean (default: ``False``)
2798
+ - ``index_set`` -- list of indices or None
2799
+
2800
+ OUTPUT: list
2801
+
2802
+ EXAMPLES::
2803
+
2804
+ sage: W = WeylGroup(['A', 3]) # needs sage.combinat sage.groups
2805
+ sage: w = W.from_reduced_word([3,2,1]) # needs sage.combinat sage.groups
2806
+ sage: [x.reduced_word() for x in w.weak_covers()] # needs sage.combinat sage.groups
2807
+ [[3, 2]]
2808
+
2809
+ To obtain instead elements that cover self, set ``positive=True``::
2810
+
2811
+ sage: [x.reduced_word() for x in w.weak_covers(positive=True)] # needs sage.combinat sage.groups
2812
+ [[3, 1, 2, 1], [2, 3, 2, 1]]
2813
+
2814
+ To obtain covers for left weak order, set the option side to 'left'::
2815
+
2816
+ sage: # needs sage.combinat sage.groups
2817
+ sage: [x.reduced_word() for x in w.weak_covers(side='left')]
2818
+ [[2, 1]]
2819
+ sage: w = W.from_reduced_word([3,2,3,1])
2820
+ sage: [x.reduced_word() for x in w.weak_covers()]
2821
+ [[2, 3, 2], [3, 2, 1]]
2822
+ sage: [x.reduced_word() for x in w.weak_covers(side='left')]
2823
+ [[3, 2, 1], [2, 3, 1]]
2824
+
2825
+ Covers w.r.t. a parabolic subgroup are obtained with the option ``index_set``::
2826
+
2827
+ sage: [x.reduced_word() for x in w.weak_covers(index_set=[1,2])] # needs sage.combinat sage.groups
2828
+ [[2, 3, 2]]
2829
+ """
2830
+ return [self.apply_simple_reflection(i, side=side)
2831
+ for i in self.descents(side=side, index_set=index_set,
2832
+ positive=positive)]
2833
+
2834
+ def coxeter_sorting_word(self, c):
2835
+ r"""
2836
+ Return the ``c``-sorting word of ``self``.
2837
+
2838
+ For a Coxeter element `c` and an element `w`, the `c`-sorting
2839
+ word of `w` is the lexicographic minimal reduced expression of
2840
+ `w` in the infinite word `c^\infty`.
2841
+
2842
+ INPUT:
2843
+
2844
+ - ``c`` -- a Coxeter element
2845
+
2846
+ OUTPUT: the ``c``-sorting word of ``self`` as a list of integers
2847
+
2848
+ EXAMPLES::
2849
+
2850
+ sage: W = CoxeterGroups().example()
2851
+ sage: c = W.from_reduced_word([0,2,1])
2852
+ sage: w = W.from_reduced_word([1,2,1,0,1])
2853
+ sage: w.coxeter_sorting_word(c)
2854
+ [2, 1, 2, 0, 1]
2855
+ """
2856
+ if hasattr(c, "reduced_word"):
2857
+ c = c.reduced_word()
2858
+ elif not isinstance(c, list):
2859
+ c = list(c)
2860
+ n = self.parent().rank()
2861
+ pi = self
2862
+ l = pi.length()
2863
+ i = 0
2864
+ sorting_word = []
2865
+ while l > 0:
2866
+ s = c[i]
2867
+ if pi.has_left_descent(s):
2868
+ pi = pi.apply_simple_reflection_left(s)
2869
+ l -= 1
2870
+ sorting_word.append(s)
2871
+ i += 1
2872
+ if i == n:
2873
+ i = 0
2874
+ return sorting_word
2875
+
2876
+ def is_coxeter_sortable(self, c, sorting_word=None):
2877
+ r"""
2878
+ Return whether ``self`` is ``c``-sortable.
2879
+
2880
+ Given a Coxeter element `c`, an element `w` is `c`-sortable if
2881
+ its `c`-sorting word decomposes into a sequence of weakly
2882
+ decreasing subwords of `c`.
2883
+
2884
+ INPUT:
2885
+
2886
+ - ``c`` -- a Coxeter element
2887
+ - ``sorting_word`` -- sorting word (default: ``None``); used to
2888
+ not recompute the `c`-sorting word if already computed
2889
+
2890
+ EXAMPLES::
2891
+
2892
+ sage: W = CoxeterGroups().example()
2893
+ sage: c = W.from_reduced_word([0,2,1])
2894
+ sage: w = W.from_reduced_word([1,2,1,0,1])
2895
+ sage: w.coxeter_sorting_word(c)
2896
+ [2, 1, 2, 0, 1]
2897
+ sage: w.is_coxeter_sortable(c)
2898
+ False
2899
+ sage: w = W.from_reduced_word([0,2,1,0,2])
2900
+ sage: w.coxeter_sorting_word(c)
2901
+ [2, 0, 1, 2, 0]
2902
+ sage: w.is_coxeter_sortable(c)
2903
+ True
2904
+
2905
+ sage: W = CoxeterGroup(['A', 3]) # needs sage.combinat sage.groups
2906
+ sage: c = W.from_reduced_word([1,2,3]) # needs sage.combinat sage.groups
2907
+
2908
+ Number of `c`-sortable elements in `A_3` (Catalan number)::
2909
+
2910
+ sage: len([w for w in W if w.is_coxeter_sortable(c)]) # needs sage.rings.number_field
2911
+ 14
2912
+
2913
+ TESTS::
2914
+
2915
+ sage: W = SymmetricGroup(3) # needs sage.groups
2916
+ sage: c = Permutation((1,2,3))
2917
+ sage: sorted(w for w in W if w.is_coxeter_sortable(c)) # needs sage.combinat sage.groups
2918
+ [(), (2,3), (1,2), (1,3,2), (1,3)]
2919
+ """
2920
+ if hasattr(c, "reduced_word"):
2921
+ c = c.reduced_word()
2922
+ elif not isinstance(c, list):
2923
+ c = list(c)
2924
+ if sorting_word is None:
2925
+ sorting_word = self.coxeter_sorting_word(c)
2926
+ n = len(c)
2927
+ containment_list = [True] * n
2928
+ l = 0
2929
+ i = 0
2930
+ while l < len(sorting_word):
2931
+ s = c[i]
2932
+ t = sorting_word[l]
2933
+ if s == t:
2934
+ l += 1
2935
+ if not containment_list[i]:
2936
+ return False
2937
+ else:
2938
+ containment_list[i] = False
2939
+ i += 1
2940
+ if i == n:
2941
+ i = 0
2942
+ return True
2943
+
2944
+ def apply_demazure_product(self, element, side='right',
2945
+ length_increasing=True):
2946
+ r"""
2947
+ Return the Demazure or 0-Hecke product of ``self`` with another Coxeter group element.
2948
+
2949
+ See :meth:`CoxeterGroups.ParentMethods.simple_projections`.
2950
+
2951
+ INPUT:
2952
+
2953
+ - ``element`` -- either an element of the same Coxeter
2954
+ group as ``self`` or a tuple or a list (such as a
2955
+ reduced word) of elements from the index set of the
2956
+ Coxeter group.
2957
+
2958
+ - ``side`` -- ``'left'`` or ``'right'`` (default: ``'right'``); the
2959
+ side of ``self`` on which the element should be
2960
+ applied. If ``side`` is 'left' then the operation is
2961
+ applied on the left.
2962
+
2963
+ - ``length_increasing`` -- boolean (default: ``True``)
2964
+ whether to act length increasingly or decreasingly
2965
+
2966
+ EXAMPLES::
2967
+
2968
+ sage: # needs sage.combinat sage.groups
2969
+ sage: W = WeylGroup(['C', 4], prefix='s')
2970
+ sage: v = W.from_reduced_word([1,2,3,4,3,1])
2971
+ sage: v.apply_demazure_product([1,3,4,3,3])
2972
+ s4*s1*s2*s3*s4*s3*s1
2973
+ sage: v.apply_demazure_product([1,3,4,3], side='left')
2974
+ s3*s4*s1*s2*s3*s4*s2*s3*s1
2975
+ sage: v.apply_demazure_product((1,3,4,3), side='left')
2976
+ s3*s4*s1*s2*s3*s4*s2*s3*s1
2977
+ sage: v.apply_demazure_product(v)
2978
+ s2*s3*s4*s1*s2*s3*s4*s2*s3*s2*s1
2979
+ """
2980
+ # if self and element have the same parent
2981
+ if self.parent().is_parent_of(element):
2982
+ the_word = element.reduced_word()
2983
+ else:
2984
+ # check for a list or tuple of elements of the index set
2985
+ if isinstance(element, tuple):
2986
+ element = list(element)
2987
+ elif not isinstance(element, list):
2988
+ raise TypeError(f"Bad Coxeter group element input: {element}")
2989
+ I = self.parent().index_set()
2990
+ if not all(i in I for i in element):
2991
+ raise ValueError("%s does not have all its members in the index set of the %s" % (element, self.parent()))
2992
+ # the copy is so that if we need to reverse the list, the original will not
2993
+ # get reversed
2994
+ the_word = copy(element)
2995
+ if side == 'left':
2996
+ the_word.reverse()
2997
+ for i in the_word:
2998
+ self = self.apply_simple_projection(i, side=side, length_increasing=length_increasing)
2999
+ return self
3000
+
3001
+ def min_demazure_product_greater(self, element):
3002
+ r"""
3003
+ Find the unique Bruhat-minimum element ``u`` such that ``v`` `\le`
3004
+ ``w`` * ``u`` where ``v`` is ``self``, ``w`` is ``element`` and
3005
+ ``*`` is the Demazure product.
3006
+
3007
+ INPUT:
3008
+
3009
+ - ``element`` -- is either an element of the same Coxeter group as
3010
+ ``self`` or a list (such as a reduced word) of elements from the
3011
+ index set of the Coxeter group
3012
+
3013
+ EXAMPLES::
3014
+
3015
+ sage: # needs sage.combinat sage.groups
3016
+ sage: W = WeylGroup(['A', 4], prefix='s')
3017
+ sage: v = W.from_reduced_word([2,3,4,1,2])
3018
+ sage: u = W.from_reduced_word([2,3,2,1])
3019
+ sage: v.min_demazure_product_greater(u)
3020
+ s4*s2
3021
+ sage: v.min_demazure_product_greater([2,3,2,1])
3022
+ s4*s2
3023
+ sage: v.min_demazure_product_greater((2,3,2,1))
3024
+ s4*s2
3025
+ """
3026
+ # if self and element have the same parent
3027
+ if self.parent().is_parent_of(element):
3028
+ the_word = element.reduced_word()
3029
+ # else require that ``element`` is a list or tuple of index_set elements
3030
+ else:
3031
+ if not isinstance(element, (tuple, list)):
3032
+ raise TypeError("Bad Coxeter group element input: %s" % (element))
3033
+ I = self.parent().index_set()
3034
+ if not all(i in I for i in element):
3035
+ raise ValueError("%s does not have all its members in the index set of the %s" % (element, self.parent()))
3036
+ the_word = element
3037
+ for i in the_word:
3038
+ if self.has_descent(i, side='left'):
3039
+ self = self.apply_simple_reflection(i, side='left')
3040
+ return self
3041
+
3042
+ def deodhar_factor_element(self, w, index_set):
3043
+ r"""
3044
+ Return Deodhar's Bruhat order factoring element.
3045
+
3046
+ INPUT:
3047
+
3048
+ - ``w`` -- an element of the same Coxeter group ``W`` as ``self``
3049
+ - ``index_set`` -- a subset of Dynkin nodes defining a parabolic
3050
+ subgroup ``W'`` of ``W``
3051
+
3052
+ It is assumed that ``v = self`` and ``w`` are minimum length coset representatives
3053
+ for ``W/W'`` such that ``v`` `\le` ``w`` in Bruhat order.
3054
+
3055
+ OUTPUT:
3056
+
3057
+ Deodhar's element ``f(v,w)`` is the unique element of ``W'`` such that,
3058
+ for all ``v'`` and ``w'`` in ``W'``, ``vv'`` `\le` ``ww'`` in ``W`` if and only if
3059
+ ``v'`` `\le` ``f(v,w) * w'`` in ``W'`` where ``*`` is the Demazure product.
3060
+
3061
+ EXAMPLES::
3062
+
3063
+ sage: # needs sage.combinat sage.groups
3064
+ sage: W = WeylGroup(['A', 5], prefix='s')
3065
+ sage: v = W.from_reduced_word([5])
3066
+ sage: w = W.from_reduced_word([4,5,2,3,1,2])
3067
+ sage: v.deodhar_factor_element(w, [1,3,4])
3068
+ s3*s1
3069
+ sage: W = WeylGroup(['C', 2])
3070
+ sage: w = W.from_reduced_word([2,1])
3071
+ sage: w.deodhar_factor_element(W.from_reduced_word([2]),[1])
3072
+ Traceback (most recent call last):
3073
+ ...
3074
+ ValueError: [2, 1] is not of minimum length in its coset
3075
+ for the parabolic subgroup with index set [1]
3076
+
3077
+ REFERENCES:
3078
+
3079
+ - [Deo1987a]_
3080
+ """
3081
+ if self != self.coset_representative(index_set):
3082
+ raise ValueError("%s is not of minimum length in its coset for the parabolic subgroup with index set %s" % (self.reduced_word(), index_set))
3083
+ if w != w.coset_representative(index_set):
3084
+ raise ValueError("%s is not of minimum length in its coset for the parabolic subgroup with index set %s" % (w.reduced_word(), index_set))
3085
+ if not self.bruhat_le(w):
3086
+ raise ValueError("Must have %s <= %s" % (self.reduced_word(), w.reduced_word()))
3087
+ if w.is_one():
3088
+ return w
3089
+ i = w.first_descent(side='left')
3090
+ sw = w.apply_simple_reflection(i, side='left')
3091
+ sv = self.apply_simple_reflection(i, side='left')
3092
+ if self.has_descent(i, side='left'):
3093
+ return sv.deodhar_factor_element(sw, index_set)
3094
+ dsp = self.deodhar_factor_element(sw, index_set)
3095
+ des = sv.first_descent(side='right', index_set=index_set)
3096
+ if des is None:
3097
+ return dsp
3098
+ return dsp.apply_simple_projection(des, side='left')
3099
+
3100
+ def deodhar_lift_up(self, w, index_set):
3101
+ r"""
3102
+ Letting ``v = self``, given a Bruhat relation ``v W'`` `\le` ``w W'`` among cosets
3103
+ with respect to the subgroup ``W'`` given by the Dynkin node subset ``index_set``,
3104
+ returns the Bruhat-minimum lift ``x`` of ``wW'`` such that ``v`` `\le` ``x``.
3105
+
3106
+ INPUT:
3107
+
3108
+ - ``w`` -- an element of the same Coxeter group ``W`` as ``self``
3109
+ - ``index_set`` -- a subset of Dynkin nodes defining a parabolic
3110
+ subgroup ``W'``
3111
+
3112
+ OUTPUT:
3113
+
3114
+ The unique Bruhat-minimum element ``x`` in ``W`` such that ``x W' = w W'``
3115
+ and ``v`` `\le` ``x``.
3116
+
3117
+ .. SEEALSO:: :meth:`sage.categories.coxeter_groups.CoxeterGroups.ElementMethods.deodhar_lift_down`
3118
+
3119
+ EXAMPLES::
3120
+
3121
+ sage: # needs sage.combinat sage.groups
3122
+ sage: W = WeylGroup(['A', 3], prefix='s')
3123
+ sage: v = W.from_reduced_word([1,2,3])
3124
+ sage: w = W.from_reduced_word([1,3,2])
3125
+ sage: v.deodhar_lift_up(w, [3])
3126
+ s1*s2*s3*s2
3127
+ """
3128
+ vmin = self.coset_representative(index_set)
3129
+ wmin = w.coset_representative(index_set)
3130
+ if not vmin.bruhat_le(wmin):
3131
+ raise ValueError("Must have %s <= %s mod the parabolic subgroup with index set %s" % (self.reduced_word(), w.reduced_word(), index_set))
3132
+ vJ = vmin.inverse() * self
3133
+ dsp = vmin.deodhar_factor_element(wmin, index_set)
3134
+ return wmin * vJ.min_demazure_product_greater(dsp)
3135
+
3136
+ def deodhar_lift_down(self, w, index_set):
3137
+ r"""
3138
+ Letting ``v = self``, given a Bruhat relation ``v W'`` `\ge` ``w W'`` among cosets
3139
+ with respect to the subgroup ``W'`` given by the Dynkin node subset ``index_set``,
3140
+ returns the Bruhat-maximum lift ``x`` of ``wW'`` such that ``v`` `\ge` ``x``.
3141
+
3142
+ INPUT:
3143
+
3144
+ - ``w`` -- an element of the same Coxeter group ``W`` as ``self``
3145
+ - ``index_set`` -- a subset of Dynkin nodes defining a parabolic subgroup ``W'``
3146
+
3147
+ OUTPUT:
3148
+
3149
+ The unique Bruhat-maximum element ``x`` in ``W`` such that ``x W' = w W'``
3150
+ and ``v`` `\ge` ``x``.
3151
+
3152
+ .. SEEALSO:: :meth:`sage.categories.coxeter_groups.CoxeterGroups.ElementMethods.deodhar_lift_up`
3153
+
3154
+ EXAMPLES::
3155
+
3156
+ sage: # needs sage.combinat sage.groups
3157
+ sage: W = WeylGroup(['A', 3], prefix='s')
3158
+ sage: v = W.from_reduced_word([1,2,3,2])
3159
+ sage: w = W.from_reduced_word([3,2])
3160
+ sage: v.deodhar_lift_down(w, [3])
3161
+ s2*s3*s2
3162
+ """
3163
+ vmin = self.coset_representative(index_set)
3164
+ wmin = w.coset_representative(index_set)
3165
+ if not wmin.bruhat_le(vmin):
3166
+ raise ValueError("Must have %s <= %s mod the parabolic subgroup with index set %s" % (w.reduced_word(), self.reduced_word(), index_set))
3167
+
3168
+ vJ = vmin.inverse() * self
3169
+ dsp = wmin.deodhar_factor_element(vmin, index_set)
3170
+ return wmin * dsp.apply_demazure_product(vJ)
3171
+
3172
+ @cached_in_parent_method
3173
+ def inversions_as_reflections(self):
3174
+ r"""
3175
+ Return the set of reflections ``r`` such that ``self`` ``r < self``.
3176
+
3177
+ EXAMPLES::
3178
+
3179
+ sage: W = WeylGroup(['A', 3], prefix='s') # needs sage.combinat sage.groups
3180
+ sage: w = W.from_reduced_word([3,1,2,1]) # needs sage.combinat sage.groups
3181
+ sage: w.inversions_as_reflections() # needs sage.combinat sage.groups
3182
+ [s1, s1*s2*s1, s2, s1*s2*s3*s2*s1]
3183
+ """
3184
+ i = self.first_descent()
3185
+ if i is None:
3186
+ return []
3187
+ wi = self.apply_simple_reflection(i)
3188
+ return [self.parent().simple_reflection(i)] + [u.apply_conjugation_by_simple_reflection(i) for u in wi.inversions_as_reflections()]
3189
+
3190
+ def left_inversions_as_reflections(self):
3191
+ r"""
3192
+ Return the set of reflections ``r`` such that ``r`` ``self`` < ``self``.
3193
+
3194
+ EXAMPLES::
3195
+
3196
+ sage: W = WeylGroup(['A', 3], prefix='s') # needs sage.combinat sage.groups
3197
+ sage: w = W.from_reduced_word([3,1,2,1]) # needs sage.combinat sage.groups
3198
+ sage: w.left_inversions_as_reflections() # needs sage.combinat sage.groups
3199
+ [s1, s3, s1*s2*s3*s2*s1, s2*s3*s2]
3200
+ """
3201
+ return self.inverse().inversions_as_reflections()
3202
+
3203
+ def lower_covers(self, side='right', index_set=None):
3204
+ """
3205
+ Return all elements that ``self`` covers in weak order.
3206
+
3207
+ INPUT:
3208
+
3209
+ - ``side`` -- ``'left'`` or ``'right'`` (default: ``'right'``)
3210
+ - ``index_set`` -- list of indices or ``None``
3211
+
3212
+ OUTPUT: list
3213
+
3214
+ EXAMPLES::
3215
+
3216
+ sage: W = WeylGroup(['A', 3]) # needs sage.combinat sage.groups
3217
+ sage: w = W.from_reduced_word([3,2,1]) # needs sage.combinat sage.groups
3218
+ sage: [x.reduced_word() for x in w.lower_covers()] # needs sage.combinat sage.groups
3219
+ [[3, 2]]
3220
+
3221
+ To obtain covers for left weak order, set the option side to 'left'::
3222
+
3223
+ sage: [x.reduced_word() for x in w.lower_covers(side='left')] # needs sage.combinat sage.groups
3224
+ [[2, 1]]
3225
+ sage: w = W.from_reduced_word([3,2,3,1]) # needs sage.combinat sage.groups
3226
+ sage: [x.reduced_word() for x in w.lower_covers()] # needs sage.combinat sage.groups
3227
+ [[2, 3, 2], [3, 2, 1]]
3228
+
3229
+ Covers w.r.t. a parabolic subgroup are obtained with the option ``index_set``::
3230
+
3231
+ sage: [x.reduced_word() for x in w.lower_covers(index_set=[1,2])] # needs sage.combinat sage.groups
3232
+ [[2, 3, 2]]
3233
+ sage: [x.reduced_word() for x in w.lower_covers(side='left')] # needs sage.combinat sage.groups
3234
+ [[3, 2, 1], [2, 3, 1]]
3235
+ """
3236
+ return self.weak_covers(side=side, index_set=index_set,
3237
+ positive=False)
3238
+
3239
+ def upper_covers(self, side='right', index_set=None):
3240
+ """
3241
+ Return all elements that cover ``self`` in weak order.
3242
+
3243
+ INPUT:
3244
+
3245
+ - ``side`` -- ``'left'`` or ``'right'`` (default: ``'right'``)
3246
+ - ``index_set`` -- list of indices or ``None``
3247
+
3248
+ OUTPUT: list
3249
+
3250
+ EXAMPLES::
3251
+
3252
+ sage: W = WeylGroup(['A', 3]) # needs sage.combinat sage.groups
3253
+ sage: w = W.from_reduced_word([2,3]) # needs sage.combinat sage.groups
3254
+ sage: [x.reduced_word() for x in w.upper_covers()] # needs sage.combinat sage.groups
3255
+ [[2, 3, 1], [2, 3, 2]]
3256
+
3257
+ To obtain covers for left weak order, set the option ``side`` to 'left'::
3258
+
3259
+ sage: [x.reduced_word() for x in w.upper_covers(side='left')] # needs sage.combinat sage.groups
3260
+ [[1, 2, 3], [2, 3, 2]]
3261
+
3262
+ Covers w.r.t. a parabolic subgroup are obtained with the option ``index_set``::
3263
+
3264
+ sage: [x.reduced_word() for x in w.upper_covers(index_set=[1])] # needs sage.combinat sage.groups
3265
+ [[2, 3, 1]]
3266
+ sage: [x.reduced_word() # needs sage.combinat sage.groups
3267
+ ....: for x in w.upper_covers(side='left', index_set=[1])]
3268
+ [[1, 2, 3]]
3269
+ """
3270
+ return self.weak_covers(side=side, index_set=index_set,
3271
+ positive=True)
3272
+
3273
+ def kazhdan_lusztig_cell(self, side='left'):
3274
+ r"""
3275
+ Compute the left, right, or two-sided Kazhdan-Lusztig cell
3276
+ containing the element ``self`` depending on the specified ``side``.
3277
+
3278
+ Let `C'` denote the Kazhdan-Lusztig `C^{\prime}`-basis of the
3279
+ Iwahori-Hecke algebra `H` of a Coxeter system `(W,S)`. Two elements
3280
+ `x,y` of the Coxeter group `W` are said to lie in the same left
3281
+ Kazhdan-Lusztig cell if there exist sequences `x = w_1, w_2, \ldots,
3282
+ w_k = y` and `y = u_1, u_2, \ldots, u_l = x` such that for all
3283
+ `1 \leq i < k` and all `1 \leq j < l`, there exist some Coxeter
3284
+ generators `s,t \in S` for which `C'_{w_{i+1}}` appears in
3285
+ `C'_s C'_{w_i}` and `C'_{u_{j+1}}` appears in `C'_s C'_{u_j}`
3286
+ in `H`. Right and two-sided Kazhdan-Lusztig cells of `W` are
3287
+ defined similarly; see [Lus2013]_.
3288
+
3289
+ In this function, we compute products in the `C^{\prime}` basis by
3290
+ using :class:`IwahoriHeckeAlgebra.Cp`. As mentioned in that class,
3291
+ installing the optional package ``coxeter3`` is recommended
3292
+ (though not required) before using this function because the
3293
+ package speeds up product computations that are sometimes
3294
+ computationally infeasible without it.
3295
+
3296
+ INPUT:
3297
+
3298
+ - ``w`` -- an element of ``self``
3299
+
3300
+ - ``side`` -- (default: ``'left'``) the kind of cell to compute;
3301
+ must be either ``'left'``, ``'right'``, or ``'two-sided'``
3302
+
3303
+ EXAMPLES:
3304
+
3305
+ We compute the left cell of the generator `s_1` in type `A_3` in
3306
+ three different implementations of the Coxeter group. Note that the
3307
+ choice of implementation affects the representation of elements in
3308
+ the output cell but not the method used for the cell computation::
3309
+
3310
+ sage: W = CoxeterGroup('A3', implementation='permutation') # needs sage.combinat sage.groups
3311
+ sage: s1, s2, s3 = W.simple_reflections() # needs sage.combinat sage.groups
3312
+ sage: s1.kazhdan_lusztig_cell() # needs sage.combinat sage.groups
3313
+ {(1,2,3,12)(4,5,10,11)(6,7,8,9),
3314
+ (1,2,10)(3,6,5)(4,7,8)(9,12,11),
3315
+ (1,7)(2,4)(5,6)(8,10)(11,12)}
3316
+
3317
+ The cell computation uses the optional package ``coxeter3`` in
3318
+ the background if available to speed up the computation,
3319
+ even in the different implementations::
3320
+
3321
+ sage: # optional - coxeter3, needs sage.combinat sage.groups sage.modules
3322
+ sage: W = WeylGroup('A3', prefix='s')
3323
+ sage: s1,s2,s3 = W.simple_reflections()
3324
+ sage: s1.kazhdan_lusztig_cell()
3325
+ {s3*s2*s1, s2*s1, s1}
3326
+ sage: W = CoxeterGroup('A3', implementation='coxeter3')
3327
+ sage: s1,s2,s3 = W.simple_reflections()
3328
+ sage: s1.kazhdan_lusztig_cell()
3329
+ {[1], [2, 1], [3, 2, 1]}
3330
+
3331
+ Next, we compute a right cell and a two-sided cell in `A_3`::
3332
+
3333
+ sage: # optional - coxeter3, needs sage.combinat sage.groups sage.modules
3334
+ sage: W = CoxeterGroup('A3', implementation='coxeter3')
3335
+ sage: s1,s2,s3 = W.simple_reflections()
3336
+ sage: w = s1 * s3
3337
+ sage: w.kazhdan_lusztig_cell(side='right')
3338
+ {[1, 3], [1, 3, 2]}
3339
+ sage: w.kazhdan_lusztig_cell(side='two-sided')
3340
+ {[1, 3], [1, 3, 2], [2, 1, 3], [2, 1, 3, 2]}
3341
+
3342
+ Some slightly longer computations in `B_4`::
3343
+
3344
+ sage: # optional - coxeter3, needs sage.combinat sage.groups sage.modules
3345
+ sage: W = CoxeterGroup('B4', implementation='coxeter3')
3346
+ sage: s1,s2,s3,s4 = W.simple_reflections()
3347
+ sage: s1.kazhdan_lusztig_cell(side='right') # long time (4 seconds)
3348
+ {[1],
3349
+ [1, 2],
3350
+ [1, 2, 3],
3351
+ [1, 2, 3, 4],
3352
+ [1, 2, 3, 4, 3],
3353
+ [1, 2, 3, 4, 3, 2],
3354
+ [1, 2, 3, 4, 3, 2, 1]}
3355
+ sage: (s4*s2*s3*s4).kazhdan_lusztig_cell(side='two-sided') # long time (8 seconds)
3356
+ {[2, 3, 1],
3357
+ [2, 3, 1, 2],
3358
+ [2, 3, 4, 1],
3359
+ [2, 3, 4, 1, 2],
3360
+ [2, 3, 4, 1, 2, 3],
3361
+ [2, 3, 4, 1, 2, 3, 4],
3362
+ [2, 3, 4, 3, 1],
3363
+ [2, 3, 4, 3, 1, 2],
3364
+ ...
3365
+ [4, 3, 4, 2, 3, 4, 1, 2, 3, 4]}
3366
+ """
3367
+ from sage.algebras.iwahori_hecke_algebra import IwahoriHeckeAlgebra
3368
+ from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing
3369
+ from sage.rings.integer_ring import ZZ
3370
+
3371
+ R = LaurentPolynomialRing(ZZ, 'v')
3372
+ v = R.gen(0)
3373
+ H = IwahoriHeckeAlgebra(self.parent(), v**2)
3374
+ Cp = H.Cp()
3375
+
3376
+ w = self.parent()(self)
3377
+
3378
+ vertices, edges = {w}, set()
3379
+ queue = deque([w])
3380
+
3381
+ while queue:
3382
+ x = queue.pop()
3383
+ cp_x = Cp(x)
3384
+ for s in self.parent().simple_reflections():
3385
+ cp_s = Cp(s)
3386
+ terms = []
3387
+ # Determine the Cp basis elements appearing in the product of Cp_s and Cp_w
3388
+ if side == 'left' or side == 'two-sided':
3389
+ terms.extend(list(cp_s * cp_x))
3390
+ if side == 'right' or side == 'two-sided':
3391
+ terms.extend(list(cp_x * cp_s))
3392
+ for y, _ in terms:
3393
+ # the result of multiplication will always have coeff != 0
3394
+ if y != x:
3395
+ edges.add((x, y))
3396
+ if y not in vertices:
3397
+ vertices.add(y)
3398
+ queue.appendleft(y)
3399
+
3400
+ from sage.graphs.digraph import DiGraph
3401
+ g = DiGraph([list(vertices), list(edges)])
3402
+ return set(g.strongly_connected_component_containing_vertex(w))