passagemath-modules 10.6.31rc3__cp314-cp314-musllinux_1_2_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of passagemath-modules might be problematic. Click here for more details.

Files changed (808) hide show
  1. passagemath_modules-10.6.31rc3.dist-info/METADATA +281 -0
  2. passagemath_modules-10.6.31rc3.dist-info/RECORD +808 -0
  3. passagemath_modules-10.6.31rc3.dist-info/WHEEL +5 -0
  4. passagemath_modules-10.6.31rc3.dist-info/top_level.txt +2 -0
  5. passagemath_modules.libs/libgcc_s-0cd532bd.so.1 +0 -0
  6. passagemath_modules.libs/libgfortran-2c33b284.so.5.0.0 +0 -0
  7. passagemath_modules.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  8. passagemath_modules.libs/libgsl-42cda06f.so.28.0.0 +0 -0
  9. passagemath_modules.libs/libmpc-d8ebe4b5.so.3.3.1 +0 -0
  10. passagemath_modules.libs/libmpfr-aaecbfc0.so.6.2.1 +0 -0
  11. passagemath_modules.libs/libopenblasp-r0-905cb27d.3.29.so +0 -0
  12. passagemath_modules.libs/libquadmath-bb76a5fc.so.0.0.0 +0 -0
  13. sage/algebras/all__sagemath_modules.py +20 -0
  14. sage/algebras/catalog.py +148 -0
  15. sage/algebras/clifford_algebra.py +3107 -0
  16. sage/algebras/clifford_algebra_element.cpython-314-x86_64-linux-musl.so +0 -0
  17. sage/algebras/clifford_algebra_element.pxd +16 -0
  18. sage/algebras/clifford_algebra_element.pyx +997 -0
  19. sage/algebras/commutative_dga.py +4252 -0
  20. sage/algebras/exterior_algebra_groebner.cpython-314-x86_64-linux-musl.so +0 -0
  21. sage/algebras/exterior_algebra_groebner.pxd +55 -0
  22. sage/algebras/exterior_algebra_groebner.pyx +727 -0
  23. sage/algebras/finite_dimensional_algebras/all.py +2 -0
  24. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +1029 -0
  25. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.cpython-314-x86_64-linux-musl.so +0 -0
  26. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pxd +12 -0
  27. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx +706 -0
  28. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py +196 -0
  29. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py +255 -0
  30. sage/algebras/finite_gca.py +528 -0
  31. sage/algebras/group_algebra.py +232 -0
  32. sage/algebras/lie_algebras/abelian.py +197 -0
  33. sage/algebras/lie_algebras/affine_lie_algebra.py +1213 -0
  34. sage/algebras/lie_algebras/all.py +25 -0
  35. sage/algebras/lie_algebras/all__sagemath_modules.py +1 -0
  36. sage/algebras/lie_algebras/bch.py +177 -0
  37. sage/algebras/lie_algebras/bgg_dual_module.py +1184 -0
  38. sage/algebras/lie_algebras/bgg_resolution.py +232 -0
  39. sage/algebras/lie_algebras/center_uea.py +767 -0
  40. sage/algebras/lie_algebras/classical_lie_algebra.py +2516 -0
  41. sage/algebras/lie_algebras/examples.py +683 -0
  42. sage/algebras/lie_algebras/free_lie_algebra.py +973 -0
  43. sage/algebras/lie_algebras/heisenberg.py +820 -0
  44. sage/algebras/lie_algebras/lie_algebra.py +1562 -0
  45. sage/algebras/lie_algebras/lie_algebra_element.cpython-314-x86_64-linux-musl.so +0 -0
  46. sage/algebras/lie_algebras/lie_algebra_element.pxd +68 -0
  47. sage/algebras/lie_algebras/lie_algebra_element.pyx +2122 -0
  48. sage/algebras/lie_algebras/morphism.py +661 -0
  49. sage/algebras/lie_algebras/nilpotent_lie_algebra.py +457 -0
  50. sage/algebras/lie_algebras/onsager.py +1324 -0
  51. sage/algebras/lie_algebras/poincare_birkhoff_witt.py +816 -0
  52. sage/algebras/lie_algebras/quotient.py +462 -0
  53. sage/algebras/lie_algebras/rank_two_heisenberg_virasoro.py +355 -0
  54. sage/algebras/lie_algebras/representation.py +1040 -0
  55. sage/algebras/lie_algebras/structure_coefficients.py +459 -0
  56. sage/algebras/lie_algebras/subalgebra.py +967 -0
  57. sage/algebras/lie_algebras/symplectic_derivation.py +289 -0
  58. sage/algebras/lie_algebras/verma_module.py +1630 -0
  59. sage/algebras/lie_algebras/virasoro.py +1186 -0
  60. sage/algebras/octonion_algebra.cpython-314-x86_64-linux-musl.so +0 -0
  61. sage/algebras/octonion_algebra.pxd +20 -0
  62. sage/algebras/octonion_algebra.pyx +987 -0
  63. sage/algebras/orlik_solomon.py +907 -0
  64. sage/algebras/orlik_terao.py +779 -0
  65. sage/algebras/steenrod/all.py +7 -0
  66. sage/algebras/steenrod/steenrod_algebra.py +4258 -0
  67. sage/algebras/steenrod/steenrod_algebra_bases.py +1179 -0
  68. sage/algebras/steenrod/steenrod_algebra_misc.py +1167 -0
  69. sage/algebras/steenrod/steenrod_algebra_mult.py +954 -0
  70. sage/algebras/weyl_algebra.py +1126 -0
  71. sage/all__sagemath_modules.py +62 -0
  72. sage/calculus/all__sagemath_modules.py +19 -0
  73. sage/calculus/expr.py +205 -0
  74. sage/calculus/integration.cpython-314-x86_64-linux-musl.so +0 -0
  75. sage/calculus/integration.pyx +698 -0
  76. sage/calculus/interpolation.cpython-314-x86_64-linux-musl.so +0 -0
  77. sage/calculus/interpolation.pxd +13 -0
  78. sage/calculus/interpolation.pyx +387 -0
  79. sage/calculus/interpolators.cpython-314-x86_64-linux-musl.so +0 -0
  80. sage/calculus/interpolators.pyx +326 -0
  81. sage/calculus/ode.cpython-314-x86_64-linux-musl.so +0 -0
  82. sage/calculus/ode.pxd +5 -0
  83. sage/calculus/ode.pyx +610 -0
  84. sage/calculus/riemann.cpython-314-x86_64-linux-musl.so +0 -0
  85. sage/calculus/riemann.pyx +1521 -0
  86. sage/calculus/test_sympy.py +201 -0
  87. sage/calculus/transforms/all.py +7 -0
  88. sage/calculus/transforms/dft.py +844 -0
  89. sage/calculus/transforms/dwt.cpython-314-x86_64-linux-musl.so +0 -0
  90. sage/calculus/transforms/dwt.pxd +7 -0
  91. sage/calculus/transforms/dwt.pyx +160 -0
  92. sage/calculus/transforms/fft.cpython-314-x86_64-linux-musl.so +0 -0
  93. sage/calculus/transforms/fft.pxd +12 -0
  94. sage/calculus/transforms/fft.pyx +487 -0
  95. sage/calculus/wester.py +662 -0
  96. sage/coding/abstract_code.py +1108 -0
  97. sage/coding/ag_code.py +868 -0
  98. sage/coding/ag_code_decoders.cpython-314-x86_64-linux-musl.so +0 -0
  99. sage/coding/ag_code_decoders.pyx +2639 -0
  100. sage/coding/all.py +15 -0
  101. sage/coding/bch_code.py +494 -0
  102. sage/coding/binary_code.cpython-314-x86_64-linux-musl.so +0 -0
  103. sage/coding/binary_code.pxd +124 -0
  104. sage/coding/binary_code.pyx +4139 -0
  105. sage/coding/bounds_catalog.py +43 -0
  106. sage/coding/channel.py +819 -0
  107. sage/coding/channels_catalog.py +29 -0
  108. sage/coding/code_bounds.py +755 -0
  109. sage/coding/code_constructions.py +804 -0
  110. sage/coding/codes_catalog.py +111 -0
  111. sage/coding/cyclic_code.py +1329 -0
  112. sage/coding/databases.py +316 -0
  113. sage/coding/decoder.py +373 -0
  114. sage/coding/decoders_catalog.py +88 -0
  115. sage/coding/delsarte_bounds.py +709 -0
  116. sage/coding/encoder.py +390 -0
  117. sage/coding/encoders_catalog.py +64 -0
  118. sage/coding/extended_code.py +468 -0
  119. sage/coding/gabidulin_code.py +1058 -0
  120. sage/coding/golay_code.py +404 -0
  121. sage/coding/goppa_code.py +441 -0
  122. sage/coding/grs_code.py +2371 -0
  123. sage/coding/guava.py +107 -0
  124. sage/coding/guruswami_sudan/all.py +1 -0
  125. sage/coding/guruswami_sudan/gs_decoder.py +897 -0
  126. sage/coding/guruswami_sudan/interpolation.py +409 -0
  127. sage/coding/guruswami_sudan/utils.py +176 -0
  128. sage/coding/hamming_code.py +176 -0
  129. sage/coding/information_set_decoder.py +1032 -0
  130. sage/coding/kasami_codes.cpython-314-x86_64-linux-musl.so +0 -0
  131. sage/coding/kasami_codes.pyx +351 -0
  132. sage/coding/linear_code.py +3067 -0
  133. sage/coding/linear_code_no_metric.py +1354 -0
  134. sage/coding/linear_rank_metric.py +961 -0
  135. sage/coding/parity_check_code.py +353 -0
  136. sage/coding/punctured_code.py +719 -0
  137. sage/coding/reed_muller_code.py +999 -0
  138. sage/coding/self_dual_codes.py +942 -0
  139. sage/coding/source_coding/all.py +2 -0
  140. sage/coding/source_coding/huffman.py +553 -0
  141. sage/coding/subfield_subcode.py +423 -0
  142. sage/coding/two_weight_db.py +399 -0
  143. sage/combinat/all__sagemath_modules.py +7 -0
  144. sage/combinat/cartesian_product.py +347 -0
  145. sage/combinat/family.py +11 -0
  146. sage/combinat/free_module.py +1977 -0
  147. sage/combinat/root_system/all.py +147 -0
  148. sage/combinat/root_system/ambient_space.py +527 -0
  149. sage/combinat/root_system/associahedron.py +471 -0
  150. sage/combinat/root_system/braid_move_calculator.py +143 -0
  151. sage/combinat/root_system/braid_orbit.cpython-314-x86_64-linux-musl.so +0 -0
  152. sage/combinat/root_system/braid_orbit.pyx +144 -0
  153. sage/combinat/root_system/branching_rules.py +2301 -0
  154. sage/combinat/root_system/cartan_matrix.py +1245 -0
  155. sage/combinat/root_system/cartan_type.py +3069 -0
  156. sage/combinat/root_system/coxeter_group.py +162 -0
  157. sage/combinat/root_system/coxeter_matrix.py +1261 -0
  158. sage/combinat/root_system/coxeter_type.py +681 -0
  159. sage/combinat/root_system/dynkin_diagram.py +900 -0
  160. sage/combinat/root_system/extended_affine_weyl_group.py +2993 -0
  161. sage/combinat/root_system/fundamental_group.py +795 -0
  162. sage/combinat/root_system/hecke_algebra_representation.py +1203 -0
  163. sage/combinat/root_system/integrable_representations.py +1227 -0
  164. sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +1965 -0
  165. sage/combinat/root_system/pieri_factors.py +1147 -0
  166. sage/combinat/root_system/plot.py +1615 -0
  167. sage/combinat/root_system/root_lattice_realization_algebras.py +1214 -0
  168. sage/combinat/root_system/root_lattice_realizations.py +4628 -0
  169. sage/combinat/root_system/root_space.py +487 -0
  170. sage/combinat/root_system/root_system.py +882 -0
  171. sage/combinat/root_system/type_A.py +348 -0
  172. sage/combinat/root_system/type_A_affine.py +227 -0
  173. sage/combinat/root_system/type_A_infinity.py +241 -0
  174. sage/combinat/root_system/type_B.py +347 -0
  175. sage/combinat/root_system/type_BC_affine.py +287 -0
  176. sage/combinat/root_system/type_B_affine.py +216 -0
  177. sage/combinat/root_system/type_C.py +317 -0
  178. sage/combinat/root_system/type_C_affine.py +188 -0
  179. sage/combinat/root_system/type_D.py +357 -0
  180. sage/combinat/root_system/type_D_affine.py +208 -0
  181. sage/combinat/root_system/type_E.py +641 -0
  182. sage/combinat/root_system/type_E_affine.py +231 -0
  183. sage/combinat/root_system/type_F.py +387 -0
  184. sage/combinat/root_system/type_F_affine.py +137 -0
  185. sage/combinat/root_system/type_G.py +293 -0
  186. sage/combinat/root_system/type_G_affine.py +132 -0
  187. sage/combinat/root_system/type_H.py +105 -0
  188. sage/combinat/root_system/type_I.py +110 -0
  189. sage/combinat/root_system/type_Q.py +150 -0
  190. sage/combinat/root_system/type_affine.py +509 -0
  191. sage/combinat/root_system/type_dual.py +704 -0
  192. sage/combinat/root_system/type_folded.py +301 -0
  193. sage/combinat/root_system/type_marked.py +748 -0
  194. sage/combinat/root_system/type_reducible.py +601 -0
  195. sage/combinat/root_system/type_relabel.py +730 -0
  196. sage/combinat/root_system/type_super_A.py +837 -0
  197. sage/combinat/root_system/weight_lattice_realizations.py +1188 -0
  198. sage/combinat/root_system/weight_space.py +639 -0
  199. sage/combinat/root_system/weyl_characters.py +2238 -0
  200. sage/crypto/__init__.py +4 -0
  201. sage/crypto/all.py +28 -0
  202. sage/crypto/block_cipher/all.py +7 -0
  203. sage/crypto/block_cipher/des.py +1065 -0
  204. sage/crypto/block_cipher/miniaes.py +2171 -0
  205. sage/crypto/block_cipher/present.py +909 -0
  206. sage/crypto/block_cipher/sdes.py +1527 -0
  207. sage/crypto/boolean_function.cpython-314-x86_64-linux-musl.so +0 -0
  208. sage/crypto/boolean_function.pxd +10 -0
  209. sage/crypto/boolean_function.pyx +1487 -0
  210. sage/crypto/cipher.py +78 -0
  211. sage/crypto/classical.py +3668 -0
  212. sage/crypto/classical_cipher.py +569 -0
  213. sage/crypto/cryptosystem.py +387 -0
  214. sage/crypto/key_exchange/all.py +7 -0
  215. sage/crypto/key_exchange/catalog.py +24 -0
  216. sage/crypto/key_exchange/diffie_hellman.py +323 -0
  217. sage/crypto/key_exchange/key_exchange_scheme.py +107 -0
  218. sage/crypto/lattice.py +312 -0
  219. sage/crypto/lfsr.py +295 -0
  220. sage/crypto/lwe.py +840 -0
  221. sage/crypto/mq/__init__.py +4 -0
  222. sage/crypto/mq/mpolynomialsystemgenerator.py +204 -0
  223. sage/crypto/mq/rijndael_gf.py +2345 -0
  224. sage/crypto/mq/sbox.py +7 -0
  225. sage/crypto/mq/sr.py +3344 -0
  226. sage/crypto/public_key/all.py +5 -0
  227. sage/crypto/public_key/blum_goldwasser.py +776 -0
  228. sage/crypto/sbox.cpython-314-x86_64-linux-musl.so +0 -0
  229. sage/crypto/sbox.pyx +2090 -0
  230. sage/crypto/sboxes.py +2090 -0
  231. sage/crypto/stream.py +390 -0
  232. sage/crypto/stream_cipher.py +297 -0
  233. sage/crypto/util.py +519 -0
  234. sage/ext/all__sagemath_modules.py +1 -0
  235. sage/ext/interpreters/__init__.py +1 -0
  236. sage/ext/interpreters/all__sagemath_modules.py +2 -0
  237. sage/ext/interpreters/wrapper_cc.cpython-314-x86_64-linux-musl.so +0 -0
  238. sage/ext/interpreters/wrapper_cc.pxd +30 -0
  239. sage/ext/interpreters/wrapper_cc.pyx +252 -0
  240. sage/ext/interpreters/wrapper_cdf.cpython-314-x86_64-linux-musl.so +0 -0
  241. sage/ext/interpreters/wrapper_cdf.pxd +26 -0
  242. sage/ext/interpreters/wrapper_cdf.pyx +245 -0
  243. sage/ext/interpreters/wrapper_rdf.cpython-314-x86_64-linux-musl.so +0 -0
  244. sage/ext/interpreters/wrapper_rdf.pxd +23 -0
  245. sage/ext/interpreters/wrapper_rdf.pyx +221 -0
  246. sage/ext/interpreters/wrapper_rr.cpython-314-x86_64-linux-musl.so +0 -0
  247. sage/ext/interpreters/wrapper_rr.pxd +28 -0
  248. sage/ext/interpreters/wrapper_rr.pyx +335 -0
  249. sage/geometry/all__sagemath_modules.py +5 -0
  250. sage/geometry/toric_lattice.py +1745 -0
  251. sage/geometry/toric_lattice_element.cpython-314-x86_64-linux-musl.so +0 -0
  252. sage/geometry/toric_lattice_element.pyx +432 -0
  253. sage/groups/abelian_gps/abelian_group.py +1925 -0
  254. sage/groups/abelian_gps/abelian_group_element.py +164 -0
  255. sage/groups/abelian_gps/all__sagemath_modules.py +5 -0
  256. sage/groups/abelian_gps/dual_abelian_group.py +421 -0
  257. sage/groups/abelian_gps/dual_abelian_group_element.py +179 -0
  258. sage/groups/abelian_gps/element_base.py +341 -0
  259. sage/groups/abelian_gps/values.py +488 -0
  260. sage/groups/additive_abelian/additive_abelian_group.py +476 -0
  261. sage/groups/additive_abelian/additive_abelian_wrapper.py +857 -0
  262. sage/groups/additive_abelian/all.py +4 -0
  263. sage/groups/additive_abelian/qmodnz.py +231 -0
  264. sage/groups/additive_abelian/qmodnz_element.py +349 -0
  265. sage/groups/affine_gps/affine_group.py +535 -0
  266. sage/groups/affine_gps/all.py +1 -0
  267. sage/groups/affine_gps/catalog.py +17 -0
  268. sage/groups/affine_gps/euclidean_group.py +246 -0
  269. sage/groups/affine_gps/group_element.py +562 -0
  270. sage/groups/all__sagemath_modules.py +12 -0
  271. sage/groups/galois_group.py +479 -0
  272. sage/groups/matrix_gps/all.py +4 -0
  273. sage/groups/matrix_gps/all__sagemath_modules.py +13 -0
  274. sage/groups/matrix_gps/catalog.py +26 -0
  275. sage/groups/matrix_gps/coxeter_group.py +927 -0
  276. sage/groups/matrix_gps/finitely_generated.py +487 -0
  277. sage/groups/matrix_gps/group_element.cpython-314-x86_64-linux-musl.so +0 -0
  278. sage/groups/matrix_gps/group_element.pxd +11 -0
  279. sage/groups/matrix_gps/group_element.pyx +431 -0
  280. sage/groups/matrix_gps/linear.py +440 -0
  281. sage/groups/matrix_gps/matrix_group.py +617 -0
  282. sage/groups/matrix_gps/named_group.py +296 -0
  283. sage/groups/matrix_gps/orthogonal.py +544 -0
  284. sage/groups/matrix_gps/symplectic.py +251 -0
  285. sage/groups/matrix_gps/unitary.py +436 -0
  286. sage/groups/misc_gps/all__sagemath_modules.py +1 -0
  287. sage/groups/misc_gps/argument_groups.py +1905 -0
  288. sage/groups/misc_gps/imaginary_groups.py +479 -0
  289. sage/groups/perm_gps/all__sagemath_modules.py +1 -0
  290. sage/groups/perm_gps/partn_ref/all__sagemath_modules.py +1 -0
  291. sage/groups/perm_gps/partn_ref/refinement_binary.cpython-314-x86_64-linux-musl.so +0 -0
  292. sage/groups/perm_gps/partn_ref/refinement_binary.pxd +41 -0
  293. sage/groups/perm_gps/partn_ref/refinement_binary.pyx +1167 -0
  294. sage/groups/perm_gps/partn_ref/refinement_matrices.cpython-314-x86_64-linux-musl.so +0 -0
  295. sage/groups/perm_gps/partn_ref/refinement_matrices.pxd +31 -0
  296. sage/groups/perm_gps/partn_ref/refinement_matrices.pyx +385 -0
  297. sage/homology/algebraic_topological_model.py +595 -0
  298. sage/homology/all.py +2 -0
  299. sage/homology/all__sagemath_modules.py +8 -0
  300. sage/homology/chain_complex.py +2148 -0
  301. sage/homology/chain_complex_homspace.py +165 -0
  302. sage/homology/chain_complex_morphism.py +629 -0
  303. sage/homology/chain_homotopy.py +604 -0
  304. sage/homology/chains.py +653 -0
  305. sage/homology/free_resolution.py +923 -0
  306. sage/homology/graded_resolution.py +567 -0
  307. sage/homology/hochschild_complex.py +756 -0
  308. sage/homology/homology_group.py +188 -0
  309. sage/homology/homology_morphism.py +422 -0
  310. sage/homology/homology_vector_space_with_basis.py +1454 -0
  311. sage/homology/koszul_complex.py +169 -0
  312. sage/homology/matrix_utils.py +205 -0
  313. sage/libs/all__sagemath_modules.py +1 -0
  314. sage/libs/gsl/__init__.py +1 -0
  315. sage/libs/gsl/airy.pxd +56 -0
  316. sage/libs/gsl/all.pxd +66 -0
  317. sage/libs/gsl/array.cpython-314-x86_64-linux-musl.so +0 -0
  318. sage/libs/gsl/array.pxd +5 -0
  319. sage/libs/gsl/array.pyx +102 -0
  320. sage/libs/gsl/bessel.pxd +208 -0
  321. sage/libs/gsl/blas.pxd +116 -0
  322. sage/libs/gsl/blas_types.pxd +34 -0
  323. sage/libs/gsl/block.pxd +52 -0
  324. sage/libs/gsl/chebyshev.pxd +37 -0
  325. sage/libs/gsl/clausen.pxd +12 -0
  326. sage/libs/gsl/combination.pxd +47 -0
  327. sage/libs/gsl/complex.pxd +151 -0
  328. sage/libs/gsl/coulomb.pxd +30 -0
  329. sage/libs/gsl/coupling.pxd +21 -0
  330. sage/libs/gsl/dawson.pxd +12 -0
  331. sage/libs/gsl/debye.pxd +24 -0
  332. sage/libs/gsl/dilog.pxd +14 -0
  333. sage/libs/gsl/eigen.pxd +46 -0
  334. sage/libs/gsl/elementary.pxd +12 -0
  335. sage/libs/gsl/ellint.pxd +48 -0
  336. sage/libs/gsl/elljac.pxd +8 -0
  337. sage/libs/gsl/erf.pxd +32 -0
  338. sage/libs/gsl/errno.pxd +26 -0
  339. sage/libs/gsl/exp.pxd +44 -0
  340. sage/libs/gsl/expint.pxd +44 -0
  341. sage/libs/gsl/fermi_dirac.pxd +44 -0
  342. sage/libs/gsl/fft.pxd +121 -0
  343. sage/libs/gsl/fit.pxd +50 -0
  344. sage/libs/gsl/gamma.pxd +94 -0
  345. sage/libs/gsl/gegenbauer.pxd +26 -0
  346. sage/libs/gsl/histogram.pxd +176 -0
  347. sage/libs/gsl/hyperg.pxd +52 -0
  348. sage/libs/gsl/integration.pxd +69 -0
  349. sage/libs/gsl/interp.pxd +109 -0
  350. sage/libs/gsl/laguerre.pxd +24 -0
  351. sage/libs/gsl/lambert.pxd +16 -0
  352. sage/libs/gsl/legendre.pxd +90 -0
  353. sage/libs/gsl/linalg.pxd +185 -0
  354. sage/libs/gsl/log.pxd +26 -0
  355. sage/libs/gsl/math.pxd +43 -0
  356. sage/libs/gsl/matrix.pxd +143 -0
  357. sage/libs/gsl/matrix_complex.pxd +130 -0
  358. sage/libs/gsl/min.pxd +67 -0
  359. sage/libs/gsl/monte.pxd +56 -0
  360. sage/libs/gsl/ntuple.pxd +32 -0
  361. sage/libs/gsl/odeiv.pxd +70 -0
  362. sage/libs/gsl/permutation.pxd +78 -0
  363. sage/libs/gsl/poly.pxd +40 -0
  364. sage/libs/gsl/pow_int.pxd +12 -0
  365. sage/libs/gsl/psi.pxd +28 -0
  366. sage/libs/gsl/qrng.pxd +29 -0
  367. sage/libs/gsl/random.pxd +257 -0
  368. sage/libs/gsl/rng.pxd +100 -0
  369. sage/libs/gsl/roots.pxd +72 -0
  370. sage/libs/gsl/sort.pxd +36 -0
  371. sage/libs/gsl/statistics.pxd +59 -0
  372. sage/libs/gsl/sum.pxd +55 -0
  373. sage/libs/gsl/synchrotron.pxd +16 -0
  374. sage/libs/gsl/transport.pxd +24 -0
  375. sage/libs/gsl/trig.pxd +58 -0
  376. sage/libs/gsl/types.pxd +137 -0
  377. sage/libs/gsl/vector.pxd +101 -0
  378. sage/libs/gsl/vector_complex.pxd +83 -0
  379. sage/libs/gsl/wavelet.pxd +49 -0
  380. sage/libs/gsl/zeta.pxd +28 -0
  381. sage/libs/mpc/__init__.pxd +114 -0
  382. sage/libs/mpc/types.pxd +28 -0
  383. sage/libs/mpfr/__init__.pxd +299 -0
  384. sage/libs/mpfr/types.pxd +26 -0
  385. sage/libs/mpmath/__init__.py +1 -0
  386. sage/libs/mpmath/all.py +27 -0
  387. sage/libs/mpmath/all__sagemath_modules.py +1 -0
  388. sage/libs/mpmath/utils.cpython-314-x86_64-linux-musl.so +0 -0
  389. sage/libs/mpmath/utils.pxd +4 -0
  390. sage/libs/mpmath/utils.pyx +319 -0
  391. sage/matrix/action.cpython-314-x86_64-linux-musl.so +0 -0
  392. sage/matrix/action.pxd +26 -0
  393. sage/matrix/action.pyx +596 -0
  394. sage/matrix/all.py +9 -0
  395. sage/matrix/args.cpython-314-x86_64-linux-musl.so +0 -0
  396. sage/matrix/args.pxd +144 -0
  397. sage/matrix/args.pyx +1668 -0
  398. sage/matrix/benchmark.py +1258 -0
  399. sage/matrix/berlekamp_massey.py +95 -0
  400. sage/matrix/compute_J_ideal.py +926 -0
  401. sage/matrix/constructor.cpython-314-x86_64-linux-musl.so +0 -0
  402. sage/matrix/constructor.pyx +750 -0
  403. sage/matrix/docs.py +430 -0
  404. sage/matrix/echelon_matrix.cpython-314-x86_64-linux-musl.so +0 -0
  405. sage/matrix/echelon_matrix.pyx +155 -0
  406. sage/matrix/matrix.pxd +2 -0
  407. sage/matrix/matrix0.cpython-314-x86_64-linux-musl.so +0 -0
  408. sage/matrix/matrix0.pxd +68 -0
  409. sage/matrix/matrix0.pyx +6324 -0
  410. sage/matrix/matrix1.cpython-314-x86_64-linux-musl.so +0 -0
  411. sage/matrix/matrix1.pxd +8 -0
  412. sage/matrix/matrix1.pyx +2851 -0
  413. sage/matrix/matrix2.cpython-314-x86_64-linux-musl.so +0 -0
  414. sage/matrix/matrix2.pxd +25 -0
  415. sage/matrix/matrix2.pyx +20181 -0
  416. sage/matrix/matrix_cdv.cpython-314-x86_64-linux-musl.so +0 -0
  417. sage/matrix/matrix_cdv.pxd +4 -0
  418. sage/matrix/matrix_cdv.pyx +93 -0
  419. sage/matrix/matrix_complex_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  420. sage/matrix/matrix_complex_double_dense.pxd +5 -0
  421. sage/matrix/matrix_complex_double_dense.pyx +98 -0
  422. sage/matrix/matrix_dense.cpython-314-x86_64-linux-musl.so +0 -0
  423. sage/matrix/matrix_dense.pxd +5 -0
  424. sage/matrix/matrix_dense.pyx +343 -0
  425. sage/matrix/matrix_domain_dense.pxd +5 -0
  426. sage/matrix/matrix_domain_sparse.pxd +5 -0
  427. sage/matrix/matrix_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  428. sage/matrix/matrix_double_dense.pxd +7 -0
  429. sage/matrix/matrix_double_dense.pyx +3906 -0
  430. sage/matrix/matrix_double_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  431. sage/matrix/matrix_double_sparse.pxd +6 -0
  432. sage/matrix/matrix_double_sparse.pyx +248 -0
  433. sage/matrix/matrix_generic_dense.cpython-314-x86_64-linux-musl.so +0 -0
  434. sage/matrix/matrix_generic_dense.pxd +7 -0
  435. sage/matrix/matrix_generic_dense.pyx +354 -0
  436. sage/matrix/matrix_generic_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  437. sage/matrix/matrix_generic_sparse.pxd +7 -0
  438. sage/matrix/matrix_generic_sparse.pyx +461 -0
  439. sage/matrix/matrix_laurent_mpolynomial_dense.cpython-314-x86_64-linux-musl.so +0 -0
  440. sage/matrix/matrix_laurent_mpolynomial_dense.pxd +5 -0
  441. sage/matrix/matrix_laurent_mpolynomial_dense.pyx +115 -0
  442. sage/matrix/matrix_misc.py +313 -0
  443. sage/matrix/matrix_numpy_dense.cpython-314-x86_64-linux-musl.so +0 -0
  444. sage/matrix/matrix_numpy_dense.pxd +14 -0
  445. sage/matrix/matrix_numpy_dense.pyx +450 -0
  446. sage/matrix/matrix_numpy_integer_dense.cpython-314-x86_64-linux-musl.so +0 -0
  447. sage/matrix/matrix_numpy_integer_dense.pxd +7 -0
  448. sage/matrix/matrix_numpy_integer_dense.pyx +59 -0
  449. sage/matrix/matrix_polynomial_dense.cpython-314-x86_64-linux-musl.so +0 -0
  450. sage/matrix/matrix_polynomial_dense.pxd +5 -0
  451. sage/matrix/matrix_polynomial_dense.pyx +5341 -0
  452. sage/matrix/matrix_real_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  453. sage/matrix/matrix_real_double_dense.pxd +7 -0
  454. sage/matrix/matrix_real_double_dense.pyx +122 -0
  455. sage/matrix/matrix_space.py +2848 -0
  456. sage/matrix/matrix_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  457. sage/matrix/matrix_sparse.pxd +5 -0
  458. sage/matrix/matrix_sparse.pyx +1222 -0
  459. sage/matrix/matrix_window.cpython-314-x86_64-linux-musl.so +0 -0
  460. sage/matrix/matrix_window.pxd +37 -0
  461. sage/matrix/matrix_window.pyx +242 -0
  462. sage/matrix/misc_mpfr.cpython-314-x86_64-linux-musl.so +0 -0
  463. sage/matrix/misc_mpfr.pyx +80 -0
  464. sage/matrix/operation_table.py +1182 -0
  465. sage/matrix/special.py +3666 -0
  466. sage/matrix/strassen.cpython-314-x86_64-linux-musl.so +0 -0
  467. sage/matrix/strassen.pyx +851 -0
  468. sage/matrix/symplectic_basis.py +541 -0
  469. sage/matrix/template.pxd +6 -0
  470. sage/matrix/tests.py +71 -0
  471. sage/matroids/advanced.py +77 -0
  472. sage/matroids/all.py +13 -0
  473. sage/matroids/basis_exchange_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  474. sage/matroids/basis_exchange_matroid.pxd +96 -0
  475. sage/matroids/basis_exchange_matroid.pyx +2344 -0
  476. sage/matroids/basis_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  477. sage/matroids/basis_matroid.pxd +45 -0
  478. sage/matroids/basis_matroid.pyx +1217 -0
  479. sage/matroids/catalog.py +44 -0
  480. sage/matroids/chow_ring.py +473 -0
  481. sage/matroids/chow_ring_ideal.py +849 -0
  482. sage/matroids/circuit_closures_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  483. sage/matroids/circuit_closures_matroid.pxd +16 -0
  484. sage/matroids/circuit_closures_matroid.pyx +559 -0
  485. sage/matroids/circuits_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  486. sage/matroids/circuits_matroid.pxd +38 -0
  487. sage/matroids/circuits_matroid.pyx +947 -0
  488. sage/matroids/constructor.py +1086 -0
  489. sage/matroids/database_collections.py +365 -0
  490. sage/matroids/database_matroids.py +5338 -0
  491. sage/matroids/dual_matroid.py +583 -0
  492. sage/matroids/extension.cpython-314-x86_64-linux-musl.so +0 -0
  493. sage/matroids/extension.pxd +34 -0
  494. sage/matroids/extension.pyx +519 -0
  495. sage/matroids/flats_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  496. sage/matroids/flats_matroid.pxd +28 -0
  497. sage/matroids/flats_matroid.pyx +715 -0
  498. sage/matroids/gammoid.py +600 -0
  499. sage/matroids/graphic_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  500. sage/matroids/graphic_matroid.pxd +39 -0
  501. sage/matroids/graphic_matroid.pyx +2024 -0
  502. sage/matroids/lean_matrix.cpython-314-x86_64-linux-musl.so +0 -0
  503. sage/matroids/lean_matrix.pxd +126 -0
  504. sage/matroids/lean_matrix.pyx +3667 -0
  505. sage/matroids/linear_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  506. sage/matroids/linear_matroid.pxd +180 -0
  507. sage/matroids/linear_matroid.pyx +6649 -0
  508. sage/matroids/matroid.cpython-314-x86_64-linux-musl.so +0 -0
  509. sage/matroids/matroid.pxd +243 -0
  510. sage/matroids/matroid.pyx +8759 -0
  511. sage/matroids/matroids_catalog.py +190 -0
  512. sage/matroids/matroids_plot_helpers.py +890 -0
  513. sage/matroids/minor_matroid.py +480 -0
  514. sage/matroids/minorfix.h +9 -0
  515. sage/matroids/named_matroids.py +5 -0
  516. sage/matroids/rank_matroid.py +268 -0
  517. sage/matroids/set_system.cpython-314-x86_64-linux-musl.so +0 -0
  518. sage/matroids/set_system.pxd +38 -0
  519. sage/matroids/set_system.pyx +800 -0
  520. sage/matroids/transversal_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  521. sage/matroids/transversal_matroid.pxd +14 -0
  522. sage/matroids/transversal_matroid.pyx +893 -0
  523. sage/matroids/union_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  524. sage/matroids/union_matroid.pxd +20 -0
  525. sage/matroids/union_matroid.pyx +331 -0
  526. sage/matroids/unpickling.cpython-314-x86_64-linux-musl.so +0 -0
  527. sage/matroids/unpickling.pyx +843 -0
  528. sage/matroids/utilities.py +809 -0
  529. sage/misc/all__sagemath_modules.py +20 -0
  530. sage/misc/c3.cpython-314-x86_64-linux-musl.so +0 -0
  531. sage/misc/c3.pyx +238 -0
  532. sage/misc/compat.py +87 -0
  533. sage/misc/element_with_label.py +173 -0
  534. sage/misc/func_persist.py +79 -0
  535. sage/misc/pickle_old.cpython-314-x86_64-linux-musl.so +0 -0
  536. sage/misc/pickle_old.pyx +19 -0
  537. sage/misc/proof.py +7 -0
  538. sage/misc/replace_dot_all.py +472 -0
  539. sage/misc/sagedoc_conf.py +168 -0
  540. sage/misc/sphinxify.py +167 -0
  541. sage/misc/test_class_pickling.py +85 -0
  542. sage/modules/all.py +42 -0
  543. sage/modules/complex_double_vector.py +25 -0
  544. sage/modules/diamond_cutting.py +380 -0
  545. sage/modules/fg_pid/all.py +1 -0
  546. sage/modules/fg_pid/fgp_element.py +456 -0
  547. sage/modules/fg_pid/fgp_module.py +2091 -0
  548. sage/modules/fg_pid/fgp_morphism.py +550 -0
  549. sage/modules/filtered_vector_space.py +1271 -0
  550. sage/modules/finite_submodule_iter.cpython-314-x86_64-linux-musl.so +0 -0
  551. sage/modules/finite_submodule_iter.pxd +27 -0
  552. sage/modules/finite_submodule_iter.pyx +452 -0
  553. sage/modules/fp_graded/all.py +1 -0
  554. sage/modules/fp_graded/element.py +346 -0
  555. sage/modules/fp_graded/free_element.py +298 -0
  556. sage/modules/fp_graded/free_homspace.py +53 -0
  557. sage/modules/fp_graded/free_module.py +1060 -0
  558. sage/modules/fp_graded/free_morphism.py +217 -0
  559. sage/modules/fp_graded/homspace.py +563 -0
  560. sage/modules/fp_graded/module.py +1340 -0
  561. sage/modules/fp_graded/morphism.py +1990 -0
  562. sage/modules/fp_graded/steenrod/all.py +1 -0
  563. sage/modules/fp_graded/steenrod/homspace.py +65 -0
  564. sage/modules/fp_graded/steenrod/module.py +477 -0
  565. sage/modules/fp_graded/steenrod/morphism.py +404 -0
  566. sage/modules/fp_graded/steenrod/profile.py +241 -0
  567. sage/modules/free_module.py +8447 -0
  568. sage/modules/free_module_element.cpython-314-x86_64-linux-musl.so +0 -0
  569. sage/modules/free_module_element.pxd +22 -0
  570. sage/modules/free_module_element.pyx +5445 -0
  571. sage/modules/free_module_homspace.py +369 -0
  572. sage/modules/free_module_integer.py +896 -0
  573. sage/modules/free_module_morphism.py +823 -0
  574. sage/modules/free_module_pseudohomspace.py +352 -0
  575. sage/modules/free_module_pseudomorphism.py +578 -0
  576. sage/modules/free_quadratic_module.py +1706 -0
  577. sage/modules/free_quadratic_module_integer_symmetric.py +1790 -0
  578. sage/modules/matrix_morphism.py +1745 -0
  579. sage/modules/misc.py +103 -0
  580. sage/modules/module_functors.py +192 -0
  581. sage/modules/multi_filtered_vector_space.py +719 -0
  582. sage/modules/ore_module.py +2208 -0
  583. sage/modules/ore_module_element.py +178 -0
  584. sage/modules/ore_module_homspace.py +147 -0
  585. sage/modules/ore_module_morphism.py +968 -0
  586. sage/modules/quotient_module.py +699 -0
  587. sage/modules/real_double_vector.py +22 -0
  588. sage/modules/submodule.py +255 -0
  589. sage/modules/tensor_operations.py +567 -0
  590. sage/modules/torsion_quadratic_module.py +1352 -0
  591. sage/modules/tutorial_free_modules.py +248 -0
  592. sage/modules/vector_complex_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  593. sage/modules/vector_complex_double_dense.pxd +6 -0
  594. sage/modules/vector_complex_double_dense.pyx +117 -0
  595. sage/modules/vector_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  596. sage/modules/vector_double_dense.pxd +6 -0
  597. sage/modules/vector_double_dense.pyx +604 -0
  598. sage/modules/vector_integer_dense.cpython-314-x86_64-linux-musl.so +0 -0
  599. sage/modules/vector_integer_dense.pxd +15 -0
  600. sage/modules/vector_integer_dense.pyx +361 -0
  601. sage/modules/vector_integer_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  602. sage/modules/vector_integer_sparse.pxd +29 -0
  603. sage/modules/vector_integer_sparse.pyx +406 -0
  604. sage/modules/vector_modn_dense.cpython-314-x86_64-linux-musl.so +0 -0
  605. sage/modules/vector_modn_dense.pxd +12 -0
  606. sage/modules/vector_modn_dense.pyx +394 -0
  607. sage/modules/vector_modn_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  608. sage/modules/vector_modn_sparse.pxd +21 -0
  609. sage/modules/vector_modn_sparse.pyx +298 -0
  610. sage/modules/vector_numpy_dense.cpython-314-x86_64-linux-musl.so +0 -0
  611. sage/modules/vector_numpy_dense.pxd +15 -0
  612. sage/modules/vector_numpy_dense.pyx +304 -0
  613. sage/modules/vector_numpy_integer_dense.cpython-314-x86_64-linux-musl.so +0 -0
  614. sage/modules/vector_numpy_integer_dense.pxd +7 -0
  615. sage/modules/vector_numpy_integer_dense.pyx +54 -0
  616. sage/modules/vector_rational_dense.cpython-314-x86_64-linux-musl.so +0 -0
  617. sage/modules/vector_rational_dense.pxd +15 -0
  618. sage/modules/vector_rational_dense.pyx +387 -0
  619. sage/modules/vector_rational_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  620. sage/modules/vector_rational_sparse.pxd +30 -0
  621. sage/modules/vector_rational_sparse.pyx +413 -0
  622. sage/modules/vector_real_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  623. sage/modules/vector_real_double_dense.pxd +6 -0
  624. sage/modules/vector_real_double_dense.pyx +126 -0
  625. sage/modules/vector_space_homspace.py +430 -0
  626. sage/modules/vector_space_morphism.py +989 -0
  627. sage/modules/with_basis/all.py +15 -0
  628. sage/modules/with_basis/cell_module.py +494 -0
  629. sage/modules/with_basis/indexed_element.cpython-314-x86_64-linux-musl.so +0 -0
  630. sage/modules/with_basis/indexed_element.pxd +13 -0
  631. sage/modules/with_basis/indexed_element.pyx +1058 -0
  632. sage/modules/with_basis/invariant.py +1075 -0
  633. sage/modules/with_basis/morphism.py +1636 -0
  634. sage/modules/with_basis/representation.py +2939 -0
  635. sage/modules/with_basis/subquotient.py +685 -0
  636. sage/numerical/all__sagemath_modules.py +6 -0
  637. sage/numerical/gauss_legendre.cpython-314-x86_64-linux-musl.so +0 -0
  638. sage/numerical/gauss_legendre.pyx +381 -0
  639. sage/numerical/optimize.py +910 -0
  640. sage/probability/all.py +10 -0
  641. sage/probability/probability_distribution.cpython-314-x86_64-linux-musl.so +0 -0
  642. sage/probability/probability_distribution.pyx +1242 -0
  643. sage/probability/random_variable.py +411 -0
  644. sage/quadratic_forms/all.py +4 -0
  645. sage/quadratic_forms/all__sagemath_modules.py +15 -0
  646. sage/quadratic_forms/binary_qf.py +2042 -0
  647. sage/quadratic_forms/bqf_class_group.py +748 -0
  648. sage/quadratic_forms/constructions.py +93 -0
  649. sage/quadratic_forms/count_local_2.cpython-314-x86_64-linux-musl.so +0 -0
  650. sage/quadratic_forms/count_local_2.pyx +365 -0
  651. sage/quadratic_forms/extras.py +195 -0
  652. sage/quadratic_forms/quadratic_form.py +1753 -0
  653. sage/quadratic_forms/quadratic_form__count_local_2.py +221 -0
  654. sage/quadratic_forms/quadratic_form__equivalence_testing.py +708 -0
  655. sage/quadratic_forms/quadratic_form__evaluate.cpython-314-x86_64-linux-musl.so +0 -0
  656. sage/quadratic_forms/quadratic_form__evaluate.pyx +139 -0
  657. sage/quadratic_forms/quadratic_form__local_density_congruence.py +977 -0
  658. sage/quadratic_forms/quadratic_form__local_field_invariants.py +1072 -0
  659. sage/quadratic_forms/quadratic_form__neighbors.py +424 -0
  660. sage/quadratic_forms/quadratic_form__reduction_theory.py +488 -0
  661. sage/quadratic_forms/quadratic_form__split_local_covering.py +416 -0
  662. sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +657 -0
  663. sage/quadratic_forms/quadratic_form__theta.py +352 -0
  664. sage/quadratic_forms/quadratic_form__variable_substitutions.py +370 -0
  665. sage/quadratic_forms/random_quadraticform.py +209 -0
  666. sage/quadratic_forms/ternary.cpython-314-x86_64-linux-musl.so +0 -0
  667. sage/quadratic_forms/ternary.pyx +1154 -0
  668. sage/quadratic_forms/ternary_qf.py +2027 -0
  669. sage/rings/all__sagemath_modules.py +28 -0
  670. sage/rings/asymptotic/all__sagemath_modules.py +1 -0
  671. sage/rings/asymptotic/misc.py +1252 -0
  672. sage/rings/cc.py +4 -0
  673. sage/rings/cfinite_sequence.py +1306 -0
  674. sage/rings/complex_conversion.cpython-314-x86_64-linux-musl.so +0 -0
  675. sage/rings/complex_conversion.pxd +8 -0
  676. sage/rings/complex_conversion.pyx +23 -0
  677. sage/rings/complex_double.cpython-314-x86_64-linux-musl.so +0 -0
  678. sage/rings/complex_double.pxd +21 -0
  679. sage/rings/complex_double.pyx +2654 -0
  680. sage/rings/complex_mpc.cpython-314-x86_64-linux-musl.so +0 -0
  681. sage/rings/complex_mpc.pxd +21 -0
  682. sage/rings/complex_mpc.pyx +2576 -0
  683. sage/rings/complex_mpfr.cpython-314-x86_64-linux-musl.so +0 -0
  684. sage/rings/complex_mpfr.pxd +18 -0
  685. sage/rings/complex_mpfr.pyx +3602 -0
  686. sage/rings/derivation.py +2334 -0
  687. sage/rings/finite_rings/all__sagemath_modules.py +1 -0
  688. sage/rings/finite_rings/maps_finite_field.py +191 -0
  689. sage/rings/function_field/all__sagemath_modules.py +8 -0
  690. sage/rings/function_field/derivations.py +102 -0
  691. sage/rings/function_field/derivations_rational.py +132 -0
  692. sage/rings/function_field/differential.py +853 -0
  693. sage/rings/function_field/divisor.py +1107 -0
  694. sage/rings/function_field/drinfeld_modules/action.py +199 -0
  695. sage/rings/function_field/drinfeld_modules/all.py +1 -0
  696. sage/rings/function_field/drinfeld_modules/charzero_drinfeld_module.py +673 -0
  697. sage/rings/function_field/drinfeld_modules/drinfeld_module.py +2087 -0
  698. sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py +1131 -0
  699. sage/rings/function_field/drinfeld_modules/homset.py +420 -0
  700. sage/rings/function_field/drinfeld_modules/morphism.py +820 -0
  701. sage/rings/function_field/hermite_form_polynomial.cpython-314-x86_64-linux-musl.so +0 -0
  702. sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
  703. sage/rings/function_field/khuri_makdisi.cpython-314-x86_64-linux-musl.so +0 -0
  704. sage/rings/function_field/khuri_makdisi.pyx +935 -0
  705. sage/rings/invariants/all.py +4 -0
  706. sage/rings/invariants/invariant_theory.py +4597 -0
  707. sage/rings/invariants/reconstruction.py +395 -0
  708. sage/rings/polynomial/all__sagemath_modules.py +17 -0
  709. sage/rings/polynomial/integer_valued_polynomials.py +1230 -0
  710. sage/rings/polynomial/laurent_polynomial_mpair.cpython-314-x86_64-linux-musl.so +0 -0
  711. sage/rings/polynomial/laurent_polynomial_mpair.pxd +15 -0
  712. sage/rings/polynomial/laurent_polynomial_mpair.pyx +2023 -0
  713. sage/rings/polynomial/ore_function_element.py +952 -0
  714. sage/rings/polynomial/ore_function_field.py +1028 -0
  715. sage/rings/polynomial/ore_polynomial_element.cpython-314-x86_64-linux-musl.so +0 -0
  716. sage/rings/polynomial/ore_polynomial_element.pxd +48 -0
  717. sage/rings/polynomial/ore_polynomial_element.pyx +3145 -0
  718. sage/rings/polynomial/ore_polynomial_ring.py +1334 -0
  719. sage/rings/polynomial/polynomial_real_mpfr_dense.cpython-314-x86_64-linux-musl.so +0 -0
  720. sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +788 -0
  721. sage/rings/polynomial/q_integer_valued_polynomials.py +1264 -0
  722. sage/rings/polynomial/skew_polynomial_element.cpython-314-x86_64-linux-musl.so +0 -0
  723. sage/rings/polynomial/skew_polynomial_element.pxd +9 -0
  724. sage/rings/polynomial/skew_polynomial_element.pyx +684 -0
  725. sage/rings/polynomial/skew_polynomial_finite_field.cpython-314-x86_64-linux-musl.so +0 -0
  726. sage/rings/polynomial/skew_polynomial_finite_field.pxd +19 -0
  727. sage/rings/polynomial/skew_polynomial_finite_field.pyx +1093 -0
  728. sage/rings/polynomial/skew_polynomial_finite_order.cpython-314-x86_64-linux-musl.so +0 -0
  729. sage/rings/polynomial/skew_polynomial_finite_order.pxd +10 -0
  730. sage/rings/polynomial/skew_polynomial_finite_order.pyx +567 -0
  731. sage/rings/polynomial/skew_polynomial_ring.py +908 -0
  732. sage/rings/real_double_element_gsl.cpython-314-x86_64-linux-musl.so +0 -0
  733. sage/rings/real_double_element_gsl.pxd +8 -0
  734. sage/rings/real_double_element_gsl.pyx +794 -0
  735. sage/rings/real_field.py +58 -0
  736. sage/rings/real_mpfr.cpython-314-x86_64-linux-musl.so +0 -0
  737. sage/rings/real_mpfr.pxd +29 -0
  738. sage/rings/real_mpfr.pyx +6122 -0
  739. sage/rings/ring_extension.cpython-314-x86_64-linux-musl.so +0 -0
  740. sage/rings/ring_extension.pxd +42 -0
  741. sage/rings/ring_extension.pyx +2779 -0
  742. sage/rings/ring_extension_conversion.cpython-314-x86_64-linux-musl.so +0 -0
  743. sage/rings/ring_extension_conversion.pxd +16 -0
  744. sage/rings/ring_extension_conversion.pyx +462 -0
  745. sage/rings/ring_extension_element.cpython-314-x86_64-linux-musl.so +0 -0
  746. sage/rings/ring_extension_element.pxd +21 -0
  747. sage/rings/ring_extension_element.pyx +1635 -0
  748. sage/rings/ring_extension_homset.py +64 -0
  749. sage/rings/ring_extension_morphism.cpython-314-x86_64-linux-musl.so +0 -0
  750. sage/rings/ring_extension_morphism.pxd +35 -0
  751. sage/rings/ring_extension_morphism.pyx +920 -0
  752. sage/schemes/all__sagemath_modules.py +1 -0
  753. sage/schemes/projective/all__sagemath_modules.py +1 -0
  754. sage/schemes/projective/coherent_sheaf.py +300 -0
  755. sage/schemes/projective/cohomology.py +510 -0
  756. sage/stats/all.py +15 -0
  757. sage/stats/basic_stats.py +489 -0
  758. sage/stats/distributions/all.py +7 -0
  759. sage/stats/distributions/catalog.py +34 -0
  760. sage/stats/distributions/dgs.h +50 -0
  761. sage/stats/distributions/dgs.pxd +111 -0
  762. sage/stats/distributions/dgs_bern.h +400 -0
  763. sage/stats/distributions/dgs_gauss.h +614 -0
  764. sage/stats/distributions/dgs_misc.h +104 -0
  765. sage/stats/distributions/discrete_gaussian_integer.cpython-314-x86_64-linux-musl.so +0 -0
  766. sage/stats/distributions/discrete_gaussian_integer.pxd +14 -0
  767. sage/stats/distributions/discrete_gaussian_integer.pyx +498 -0
  768. sage/stats/distributions/discrete_gaussian_lattice.py +908 -0
  769. sage/stats/distributions/discrete_gaussian_polynomial.py +141 -0
  770. sage/stats/hmm/all.py +15 -0
  771. sage/stats/hmm/chmm.cpython-314-x86_64-linux-musl.so +0 -0
  772. sage/stats/hmm/chmm.pyx +1595 -0
  773. sage/stats/hmm/distributions.cpython-314-x86_64-linux-musl.so +0 -0
  774. sage/stats/hmm/distributions.pxd +29 -0
  775. sage/stats/hmm/distributions.pyx +531 -0
  776. sage/stats/hmm/hmm.cpython-314-x86_64-linux-musl.so +0 -0
  777. sage/stats/hmm/hmm.pxd +17 -0
  778. sage/stats/hmm/hmm.pyx +1388 -0
  779. sage/stats/hmm/util.cpython-314-x86_64-linux-musl.so +0 -0
  780. sage/stats/hmm/util.pxd +7 -0
  781. sage/stats/hmm/util.pyx +165 -0
  782. sage/stats/intlist.cpython-314-x86_64-linux-musl.so +0 -0
  783. sage/stats/intlist.pxd +14 -0
  784. sage/stats/intlist.pyx +588 -0
  785. sage/stats/r.py +49 -0
  786. sage/stats/time_series.cpython-314-x86_64-linux-musl.so +0 -0
  787. sage/stats/time_series.pxd +6 -0
  788. sage/stats/time_series.pyx +2546 -0
  789. sage/tensor/all.py +2 -0
  790. sage/tensor/modules/all.py +8 -0
  791. sage/tensor/modules/alternating_contr_tensor.py +761 -0
  792. sage/tensor/modules/comp.py +5598 -0
  793. sage/tensor/modules/ext_pow_free_module.py +824 -0
  794. sage/tensor/modules/finite_rank_free_module.py +3589 -0
  795. sage/tensor/modules/format_utilities.py +333 -0
  796. sage/tensor/modules/free_module_alt_form.py +858 -0
  797. sage/tensor/modules/free_module_automorphism.py +1207 -0
  798. sage/tensor/modules/free_module_basis.py +1074 -0
  799. sage/tensor/modules/free_module_element.py +284 -0
  800. sage/tensor/modules/free_module_homset.py +652 -0
  801. sage/tensor/modules/free_module_linear_group.py +564 -0
  802. sage/tensor/modules/free_module_morphism.py +1581 -0
  803. sage/tensor/modules/free_module_tensor.py +3289 -0
  804. sage/tensor/modules/reflexive_module.py +386 -0
  805. sage/tensor/modules/tensor_free_module.py +780 -0
  806. sage/tensor/modules/tensor_free_submodule.py +538 -0
  807. sage/tensor/modules/tensor_free_submodule_basis.py +140 -0
  808. sage/tensor/modules/tensor_with_indices.py +1043 -0
@@ -0,0 +1,4628 @@
1
+ # sage_setup: distribution = sagemath-modules
2
+ """
3
+ Root lattice realizations
4
+ """
5
+ # ****************************************************************************
6
+ # Copyright (C) 2007-2013 Nicolas M. Thiery <nthiery at users.sf.net>
7
+ # 2012 Nicolas Borie <nicolas.borie at univ-mlv.fr>
8
+ #
9
+ # (with contributions of many others)
10
+ #
11
+ # Distributed under the terms of the GNU General Public License (GPL)
12
+ # https://www.gnu.org/licenses/
13
+ # ****************************************************************************
14
+
15
+ from sage.misc.abstract_method import abstract_method, AbstractMethod
16
+ from sage.misc.call import attrcall
17
+ from sage.misc.cachefunc import cached_method, cached_in_parent_method
18
+ from sage.misc.lazy_attribute import lazy_attribute
19
+ from sage.misc.lazy_import import LazyImport
20
+ from sage.categories.coxeter_groups import CoxeterGroups
21
+ from sage.categories.category_types import Category_over_base_ring
22
+ from sage.categories.enumerated_sets import EnumeratedSets
23
+ from sage.categories.modules_with_basis import ModulesWithBasis
24
+ from sage.structure.element import Element
25
+ from sage.sets.family import Family
26
+ from sage.rings.integer_ring import ZZ
27
+ from sage.rings.rational_field import QQ
28
+ from sage.matrix.constructor import matrix
29
+ from sage.modules.free_module_element import vector
30
+ from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet
31
+ from sage.combinat.root_system.plot import PlotOptions, barycentric_projection_matrix
32
+ from itertools import combinations_with_replacement
33
+
34
+
35
+ class RootLatticeRealizations(Category_over_base_ring):
36
+ r"""
37
+ The category of root lattice realizations over a given base ring.
38
+
39
+ A *root lattice realization* `L` over a base ring `R` is a free
40
+ module (or vector space if `R` is a field) endowed with an embedding
41
+ of the root lattice of some root system.
42
+
43
+ Typical root lattice realizations over `\ZZ` include the root
44
+ lattice, weight lattice, and ambient lattice. Typical root lattice
45
+ realizations over `\QQ` include the root space, weight space, and
46
+ ambient space.
47
+
48
+ To describe the embedding, a root lattice realization must
49
+ implement a method
50
+ :meth:`~RootLatticeRealizations.ParentMethods.simple_root`
51
+ returning for each `i` in the index set the image of the simple root
52
+ `\alpha_i` under the embedding.
53
+
54
+ A root lattice realization must further implement a method on elements
55
+ :meth:`~RootLatticeRealizations.ElementMethods.scalar`, computing
56
+ the scalar product with elements of the coroot lattice or coroot space.
57
+
58
+ Using those, this category provides tools for reflections, roots,
59
+ the Weyl group and its action, ...
60
+
61
+ .. SEEALSO::
62
+
63
+ - :class:`~sage.combinat.root_system.root_system.RootSystem`
64
+ - :class:`~sage.combinat.root_system.weight_lattice_realizations.WeightLatticeRealizations`
65
+ - :class:`~sage.combinat.root_system.root_space.RootSpace`
66
+ - :class:`~sage.combinat.root_system.weight_space.WeightSpace`
67
+ - :class:`~sage.combinat.root_system.ambient_space.AmbientSpace`
68
+
69
+ EXAMPLES:
70
+
71
+ Here, we consider the root system of type `A_7`, and embed the root
72
+ lattice element `x = \alpha_2 + 2 \alpha_6` in several root lattice
73
+ realizations::
74
+
75
+ sage: R = RootSystem(["A",7])
76
+ sage: alpha = R.root_lattice().simple_roots()
77
+ sage: x = alpha[2] + 2 * alpha[5]
78
+
79
+ sage: L = R.root_space()
80
+ sage: L(x)
81
+ alpha[2] + 2*alpha[5]
82
+
83
+ sage: L = R.weight_lattice()
84
+ sage: L(x) # needs sage.graphs
85
+ -Lambda[1] + 2*Lambda[2] - Lambda[3] - 2*Lambda[4] + 4*Lambda[5] - 2*Lambda[6]
86
+
87
+ sage: L = R.ambient_space()
88
+ sage: L(x)
89
+ (0, 1, -1, 0, 2, -2, 0, 0)
90
+
91
+ We embed the root space element `x = \alpha_2 + 1/2 \alpha_6` in
92
+ several root lattice realizations::
93
+
94
+ sage: alpha = R.root_space().simple_roots()
95
+ sage: x = alpha[2] + 1/2 * alpha[5]
96
+
97
+ sage: L = R.weight_space()
98
+ sage: L(x) # needs sage.graphs
99
+ -Lambda[1] + 2*Lambda[2] - Lambda[3] - 1/2*Lambda[4] + Lambda[5] - 1/2*Lambda[6]
100
+
101
+ sage: L = R.ambient_space()
102
+ sage: L(x)
103
+ (0, 1, -1, 0, 1/2, -1/2, 0, 0)
104
+
105
+ Of course, one can't embed the root space in the weight lattice::
106
+
107
+ sage: L = R.weight_lattice()
108
+ sage: L(x)
109
+ Traceback (most recent call last):
110
+ ...
111
+ TypeError: do not know how to make x (= alpha[2] + 1/2*alpha[5])
112
+ an element of self (=Weight lattice of the Root system of type ['A', 7])
113
+
114
+ If `K_1` is a subring of `K_2`, then one could in theory have
115
+ an embedding from the root space over `K_1` to any root
116
+ lattice realization over `K_2`; this is not implemented::
117
+
118
+ sage: K1 = QQ
119
+ sage: K2 = QQ['q']
120
+ sage: L = R.weight_space(K2)
121
+
122
+ sage: alpha = R.root_space(K2).simple_roots()
123
+ sage: L(alpha[1]) # needs sage.graphs
124
+ 2*Lambda[1] - Lambda[2]
125
+
126
+ sage: alpha = R.root_space(K1).simple_roots()
127
+ sage: L(alpha[1])
128
+ Traceback (most recent call last):
129
+ ...
130
+ TypeError: do not know how to make x (= alpha[1]) an element of self
131
+ (=Weight space over the Univariate Polynomial Ring in q
132
+ over Rational Field of the Root system of type ['A', 7])
133
+
134
+ By a slight abuse, the embedding of the root lattice is not actually
135
+ required to be faithful. Typically for an affine root system, the
136
+ null root of the root lattice is killed in the non extended weight
137
+ lattice::
138
+
139
+ sage: R = RootSystem(["A", 3, 1])
140
+ sage: delta = R.root_lattice().null_root() # needs sage.graphs
141
+ sage: L = R.weight_lattice()
142
+ sage: L(delta) # needs sage.graphs
143
+ 0
144
+
145
+ TESTS::
146
+
147
+ sage: TestSuite(L).run() # needs sage.graphs
148
+ """
149
+
150
+ @cached_method
151
+ def super_categories(self):
152
+ """
153
+ EXAMPLES::
154
+
155
+ sage: from sage.combinat.root_system.root_lattice_realizations import RootLatticeRealizations
156
+ sage: RootLatticeRealizations(QQ).super_categories()
157
+ [Category of vector spaces with basis over Rational Field]
158
+ """
159
+ return [ModulesWithBasis(self.base_ring())]
160
+
161
+ Algebras = LazyImport('sage.combinat.root_system.root_lattice_realization_algebras', 'Algebras')
162
+
163
+ class ParentMethods:
164
+
165
+ def __init_extra__(self):
166
+ r"""
167
+ Register the embedding of the root lattice into ``self``.
168
+
169
+ Also registers the embedding of the root space over the same
170
+ base field `K` into ``self`` if `K` is not `\ZZ`.
171
+
172
+ EXAMPLES:
173
+
174
+ We embed the simple root `\alpha_2` of the root lattice in
175
+ the weight lattice::
176
+
177
+ sage: R = RootSystem(["A",3])
178
+ sage: alpha = R.root_lattice().simple_roots()
179
+ sage: L = R.weight_lattice()
180
+ sage: L(alpha[2]) # needs sage.graphs
181
+ -Lambda[1] + 2*Lambda[2] - Lambda[3]
182
+
183
+ .. NOTE::
184
+
185
+ More examples are given in :class:`RootLatticeRealizations`;
186
+ The embeddings are systematically tested in
187
+ :meth:`_test_root_lattice_realization`.
188
+ """
189
+ from .root_space import RootSpace
190
+ K = self.base_ring()
191
+ # If self is the root lattice or the root space, we don't want
192
+ # to register its trivial embedding into itself. This builds
193
+ # the domains from which we want to register an embedding.
194
+ domains = []
195
+ if not isinstance(self, RootSpace) or K is not ZZ:
196
+ domains.append(self.root_system.root_lattice())
197
+ if not isinstance(self, RootSpace):
198
+ domains.append(self.root_system.root_space(K))
199
+ # Build and register the embeddings
200
+ for domain in domains:
201
+ domain.module_morphism(self.simple_root,
202
+ codomain=self
203
+ ).register_as_coercion()
204
+ if self.cartan_type().is_affine():
205
+ self._to_classical.register_as_conversion()
206
+
207
+ def cartan_type(self):
208
+ """
209
+ EXAMPLES::
210
+
211
+ sage: r = RootSystem(['A',4]).root_space()
212
+ sage: r.cartan_type()
213
+ ['A', 4]
214
+ """
215
+ return self.root_system.cartan_type()
216
+
217
+ def index_set(self):
218
+ """
219
+ EXAMPLES::
220
+
221
+ sage: r = RootSystem(['A',4]).root_space()
222
+ sage: r.index_set()
223
+ (1, 2, 3, 4)
224
+ """
225
+ return self.root_system.index_set()
226
+
227
+ def dynkin_diagram(self):
228
+ """
229
+ EXAMPLES::
230
+
231
+ sage: r = RootSystem(['A',4]).root_space()
232
+ sage: r.dynkin_diagram() # needs sage.graphs
233
+ O---O---O---O
234
+ 1 2 3 4
235
+ A4
236
+ """
237
+ return self.root_system.dynkin_diagram()
238
+
239
+ def _name_string_helper(self, name, capitalize=True, base_ring=True, type=True, prefix=""):
240
+ """
241
+ EXAMPLES::
242
+
243
+ sage: r = RootSystem(['A',4]).root_space()
244
+ sage: r._name_string_helper("root")
245
+ "Root space over the Rational Field of the Root system of type ['A', 4]"
246
+ sage: r._name_string_helper("root", base_ring=False)
247
+ "Root space of the Root system of type ['A', 4]"
248
+ sage: r._name_string_helper("root", base_ring=False, type=False)
249
+ 'Root space'
250
+ sage: r._name_string_helper("root", capitalize=False, base_ring=False, type=False)
251
+ 'root space'
252
+
253
+ sage: r = RootSystem(['A',4]).coroot_space()
254
+ sage: r._name_string_helper("weight", prefix="extended ")
255
+ "Extended coweight space over the Rational Field of the Root system of type ['A', 4]"
256
+ """
257
+ s = prefix
258
+ if self.root_system.dual_side:
259
+ s += "co"
260
+
261
+ s += name + " "
262
+
263
+ if self.base_ring() == ZZ:
264
+ s += "lattice "
265
+ else:
266
+ s += "space "
267
+ if base_ring:
268
+ s += "over the %s " % self.base_ring()
269
+
270
+ if type:
271
+ s += "of the "
272
+ if self.root_system.dual_side:
273
+ s += repr(self.root_system.dual)
274
+ else:
275
+ s += repr(self.root_system)
276
+
277
+ if capitalize:
278
+ s = s[:1].upper() + s[1:]
279
+
280
+ return s.strip()
281
+
282
+ def some_elements(self):
283
+ """
284
+ Return some elements of this root lattice realization.
285
+
286
+ EXAMPLES::
287
+
288
+ sage: L = RootSystem(["A",2]).weight_lattice()
289
+ sage: L.some_elements() # needs sage.graphs
290
+ [2*Lambda[1] + 2*Lambda[2], 2*Lambda[1] - Lambda[2],
291
+ -Lambda[1] + 2*Lambda[2], Lambda[1], Lambda[2]]
292
+ sage: L = RootSystem(["A",2]).root_lattice()
293
+ sage: L.some_elements()
294
+ [2*alpha[1] + 2*alpha[2], alpha[1], alpha[2]]
295
+ """
296
+ result = [self.an_element()]
297
+ try:
298
+ result.extend(self.simple_roots())
299
+ except ImportError:
300
+ pass
301
+ try:
302
+ result.extend(self.fundamental_weights())
303
+ except (AttributeError, ImportError):
304
+ pass
305
+ return result
306
+
307
+ ##########################################################################
308
+ # checks
309
+ ##########################################################################
310
+
311
+ def _test_root_lattice_realization(self, **options):
312
+ """
313
+ Run sanity checks on this root lattice realization.
314
+
315
+ - embedding of the root lattice
316
+ - embedding of the root space over the same base ring
317
+ - scalar products between simple roots and simple coroots
318
+ - ...
319
+
320
+ .. SEEALSO:: :class:`TestSuite`
321
+
322
+ EXAMPLES::
323
+
324
+ sage: RootSystem(['A',3]).root_lattice()._test_root_lattice_realization()
325
+ """
326
+ tester = self._tester(**options)
327
+ try:
328
+ alpha = self.simple_roots()
329
+ alphacheck = self.simple_coroots()
330
+ except ImportError:
331
+ return
332
+ R = self.base_ring()
333
+ tester.assertEqual(alpha .keys(), self.index_set())
334
+ tester.assertEqual(alphacheck.keys(), self.index_set())
335
+
336
+ # Check the consistency between simple_root and simple_roots
337
+ for i in self.index_set():
338
+ tester.assertEqual(self.simple_root(i), alpha[i])
339
+
340
+ # Check the embeddings from the root lattice and the root space over the same base ring
341
+ root_lattice = self.root_system.root_lattice()
342
+ root_space = self.root_system.root_space(R)
343
+ tester.assertIsNot(self.coerce_map_from(root_lattice), None)
344
+ tester.assertIsNot(self.coerce_map_from(root_space), None)
345
+ for i in self.index_set():
346
+ # This embedding maps simple roots to simple roots
347
+ tester.assertEqual(self(root_lattice.simple_root(i)), alpha[i])
348
+ tester.assertEqual(self(root_space .simple_root(i)), alpha[i])
349
+
350
+ # Check that the scalar products match with the Dynkin diagram
351
+ try:
352
+ dynkin_diagram = self.dynkin_diagram()
353
+ except ImportError:
354
+ return
355
+ for i in self.index_set():
356
+ for j in self.index_set():
357
+ tester.assertEqual(alpha[j].scalar(alphacheck[i]), R(dynkin_diagram[i,j]))
358
+
359
+ # Check associated_coroot, if it is implemented
360
+ if not isinstance(self.element_class.associated_coroot, AbstractMethod):
361
+ for i in self.index_set():
362
+ tester.assertEqual(alpha[i].associated_coroot(), alphacheck[i])
363
+
364
+ if self.cartan_type().is_affine():
365
+ # Check that the null root is orthogonal to all coroots
366
+ # and similarly for the null coroot
367
+ nullroot = self.null_root()
368
+ nullcoroot = self.null_coroot()
369
+ special_node = self.cartan_type().special_node()
370
+ for i in alpha.keys():
371
+ tester.assertTrue(nullroot.scalar(alphacheck[i]).is_zero())
372
+ tester.assertTrue(alpha[i].scalar(nullcoroot).is_zero())
373
+ # Check the projection on the classical space
374
+ classical = self.classical()
375
+ alpha_classical = classical.alpha()
376
+ for i in alpha.keys():
377
+ if i != special_node or self.cartan_type().is_untwisted_affine():
378
+ tester.assertEqual(classical(alpha[i]), alpha_classical[i])
379
+
380
+ # Todo: add tests of highest root, roots, has_descent, ...
381
+
382
+ ##########################################################################
383
+ # highest root
384
+ ##########################################################################
385
+
386
+ @cached_method
387
+ def highest_root(self):
388
+ """
389
+ Return the highest root (for an irreducible finite root system).
390
+
391
+ EXAMPLES::
392
+
393
+ sage: RootSystem(['A',4]).ambient_space().highest_root()
394
+ (1, 0, 0, 0, -1)
395
+
396
+ sage: RootSystem(['E',6]).weight_space().highest_root() # needs sage.graphs
397
+ Lambda[2]
398
+ """
399
+ if not self.root_system.is_finite():
400
+ raise ValueError("The root system of %s is not of finite Cartan type" % self)
401
+ if not self.root_system.is_irreducible():
402
+ raise ValueError("The root system of %s is reducible" % self)
403
+ return self.a_long_simple_root().to_dominant_chamber()
404
+
405
+ @cached_method
406
+ def a_long_simple_root(self):
407
+ """
408
+ Return a long simple root, corresponding to the highest outgoing edge
409
+ in the Dynkin diagram.
410
+
411
+ .. warning::
412
+
413
+ This may be broken in affine type `A_{2n}^{(2)}`
414
+
415
+ Is it meaningful/broken for non irreducible?
416
+
417
+ .. TODO::
418
+
419
+ implement CartanType.nodes_by_length as in
420
+ MuPAD-Combinat (using CartanType.symmetrizer), and use it
421
+ here.
422
+
423
+ TESTS::
424
+
425
+ sage: X = RootSystem(['A',1]).weight_space()
426
+ sage: X.a_long_simple_root() # needs sage.graphs
427
+ 2*Lambda[1]
428
+ sage: X = RootSystem(['A',5]).weight_space()
429
+ sage: X.a_long_simple_root() # needs sage.graphs
430
+ 2*Lambda[1] - Lambda[2]
431
+ """
432
+ if self.dynkin_diagram().rank() == 1:
433
+ return self.simple_roots()[self.index_set()[0]]
434
+ longest = next(self.dynkin_diagram().edge_iterator())
435
+ for j in self.dynkin_diagram().edge_iterator():
436
+ if j[2] > longest[2]:
437
+ longest = j
438
+ return self.simple_roots()[longest[0]]
439
+
440
+ ##########################################################################
441
+ # simple roots
442
+ ##########################################################################
443
+
444
+ @abstract_method
445
+ def simple_root(self, i):
446
+ """
447
+ Return the `i`-th simple root.
448
+
449
+ This should be overridden by any subclass, and typically
450
+ implemented as a cached method for efficiency.
451
+
452
+ EXAMPLES::
453
+
454
+ sage: r = RootSystem(["A",3]).root_lattice()
455
+ sage: r.simple_root(1)
456
+ alpha[1]
457
+
458
+ TESTS::
459
+
460
+ sage: super(sage.combinat.root_system.root_space.RootSpace, r).simple_root(1)
461
+ Traceback (most recent call last):
462
+ ...
463
+ NotImplementedError: <abstract method simple_root at ...>
464
+ """
465
+
466
+ @cached_method
467
+ def simple_roots(self):
468
+ r"""
469
+ Return the family `(\alpha_i)_{i\in I}` of the simple roots.
470
+
471
+ EXAMPLES::
472
+
473
+ sage: alpha = RootSystem(["A",3]).root_lattice().simple_roots()
474
+ sage: [alpha[i] for i in [1,2,3]]
475
+ [alpha[1], alpha[2], alpha[3]]
476
+ """
477
+ if not hasattr(self,"_simple_roots"):
478
+ self._simple_roots = Family(self.index_set(), self.simple_root)
479
+ # Should we use rename to set a nice name for this family?
480
+ # self._simple_roots.rename('alpha')
481
+ # This break some doctests
482
+ return self._simple_roots
483
+
484
+ @cached_method
485
+ def alpha(self):
486
+ r"""
487
+ Return the family `(\alpha_i)_{i\in I}` of the simple roots,
488
+ with the extra feature that, for simple irreducible root
489
+ systems, `\alpha_0` yields the opposite of the highest root.
490
+
491
+ EXAMPLES::
492
+
493
+ sage: alpha = RootSystem(["A",2]).root_lattice().alpha()
494
+ sage: alpha[1]
495
+ alpha[1]
496
+ sage: alpha[0] # needs sage.graphs
497
+ -alpha[1] - alpha[2]
498
+ """
499
+ if self.root_system.is_finite() and self.root_system.is_irreducible():
500
+ return Family(self.index_set(), self.simple_root,
501
+ hidden_keys=[0],
502
+ hidden_function=lambda i: - self.highest_root())
503
+ return self.simple_roots()
504
+
505
+ @cached_method
506
+ def basic_imaginary_roots(self):
507
+ r"""
508
+ Return the basic imaginary roots of ``self``.
509
+
510
+ The basic imaginary roots `\delta` are the set of imaginary roots
511
+ in `-C^{\vee}` where `C` is the dominant chamber (i.e.,
512
+ `\langle \beta, \alpha_i^{\vee} \rangle \leq 0` for all `i \in I`).
513
+ All imaginary roots are `W`-conjugate to a simple imaginary root.
514
+
515
+ EXAMPLES::
516
+
517
+ sage: RootSystem(['A', 2]).root_lattice().basic_imaginary_roots()
518
+ ()
519
+ sage: Q = RootSystem(['A', 2, 1]).root_lattice()
520
+ sage: Q.basic_imaginary_roots() # needs sage.graphs
521
+ (alpha[0] + alpha[1] + alpha[2],)
522
+ sage: delta = Q.basic_imaginary_roots()[0] # needs sage.graphs
523
+ sage: all(delta.scalar(Q.simple_coroot(i)) <= 0 # needs sage.graphs
524
+ ....: for i in Q.index_set())
525
+ True
526
+ """
527
+ if self.cartan_type().is_finite():
528
+ return ()
529
+ if self.cartan_type().is_affine():
530
+ return (self.null_root(),)
531
+ raise ValueError("only implemented for finite and affine types")
532
+
533
+ @cached_method
534
+ def simple_roots_tilde(self):
535
+ r"""
536
+ Return the family `(\tilde\alpha_i)_{i\in I}` of the simple roots.
537
+
538
+ INPUT:
539
+
540
+ - ``self`` -- an affine root lattice realization
541
+
542
+ The `\tilde \alpha_i` give the embedding of the root
543
+ lattice of the other affinization of the same classical
544
+ root lattice into this root lattice (space?).
545
+
546
+ This uses the fact that `\alpha_i = \tilde \alpha_i` for
547
+ `i` not a special node, and that
548
+
549
+ .. MATH::
550
+
551
+ \delta = \sum a_i \alpha_i = \sum b_i \tilde \alpha_i
552
+
553
+ EXAMPLES:
554
+
555
+ In simply laced cases, this is boring::
556
+
557
+ sage: RootSystem(["A",3, 1]).root_lattice().simple_roots_tilde() # needs sage.graphs
558
+ Finite family {0: alpha[0], 1: alpha[1], 2: alpha[2], 3: alpha[3]}
559
+
560
+ This was checked by hand::
561
+
562
+ sage: RootSystem(["C",2,1]).coroot_lattice().simple_roots_tilde() # needs sage.graphs
563
+ Finite family {0: alphacheck[0] - alphacheck[2],
564
+ 1: alphacheck[1],
565
+ 2: alphacheck[2]}
566
+ sage: RootSystem(["B",2,1]).coroot_lattice().simple_roots_tilde() # needs sage.graphs
567
+ Finite family {0: alphacheck[0] - alphacheck[1],
568
+ 1: alphacheck[1],
569
+ 2: alphacheck[2]}
570
+
571
+ What about type BC?
572
+ """
573
+ i0 = self.cartan_type().special_node()
574
+ I0 = self.cartan_type().classical().index_set()
575
+ other_affinization = self.cartan_type().other_affinization()
576
+ b = other_affinization.col_annihilator()
577
+ alpha = self.simple_roots()
578
+ result = { i: alpha[i] for i in I0 }
579
+ result[i0] = (self.null_root() - self.linear_combination( (alpha[i], b[i]) for i in I0)) / b[i0]
580
+ return Family(result)
581
+
582
+ ##########################################################################
583
+ # roots
584
+ ##########################################################################
585
+
586
+ def roots(self):
587
+ """
588
+ Return the roots of ``self``.
589
+
590
+ EXAMPLES::
591
+
592
+ sage: RootSystem(['A',2]).ambient_lattice().roots()
593
+ [(1, -1, 0), (1, 0, -1), (0, 1, -1), (-1, 1, 0), (-1, 0, 1), (0, -1, 1)]
594
+
595
+ This matches with :wikipedia:`Root_systems`::
596
+
597
+ sage: for T in CartanType.samples(finite=True, crystallographic=True): # needs sage.graphs
598
+ ....: print("%s %3s %3s"%(T, len(RootSystem(T).root_lattice().roots()),
599
+ ....: len(RootSystem(T).weight_lattice().roots())))
600
+ ['A', 1] 2 2
601
+ ['A', 5] 30 30
602
+ ['B', 1] 2 2
603
+ ['B', 5] 50 50
604
+ ['C', 1] 2 2
605
+ ['C', 5] 50 50
606
+ ['D', 2] 4 4
607
+ ['D', 3] 12 12
608
+ ['D', 5] 40 40
609
+ ['E', 6] 72 72
610
+ ['E', 7] 126 126
611
+ ['E', 8] 240 240
612
+ ['F', 4] 48 48
613
+ ['G', 2] 12 12
614
+
615
+ .. TODO::
616
+
617
+ The result should be an enumerated set, and handle
618
+ infinite root systems.
619
+ """
620
+ if not self.cartan_type().is_finite():
621
+ from sage.sets.disjoint_union_enumerated_sets \
622
+ import DisjointUnionEnumeratedSets
623
+ D = DisjointUnionEnumeratedSets([self.positive_roots(),
624
+ self.negative_roots()])
625
+ D.rename("All roots of type {}".format(self.cartan_type()))
626
+ return D
627
+
628
+ return list(self.positive_roots()) + list(self.negative_roots())
629
+
630
+ def short_roots(self):
631
+ """
632
+ Return a list of the short roots of ``self``.
633
+
634
+ EXAMPLES::
635
+
636
+ sage: L = RootSystem(['B',3]).root_lattice()
637
+ sage: sorted(L.short_roots()) # needs sage.graphs
638
+ [-alpha[1] - alpha[2] - alpha[3],
639
+ alpha[1] + alpha[2] + alpha[3],
640
+ -alpha[2] - alpha[3],
641
+ alpha[2] + alpha[3],
642
+ -alpha[3],
643
+ alpha[3]]
644
+ """
645
+ if not self.cartan_type().is_finite():
646
+ raise NotImplementedError("only implemented for finite Cartan types")
647
+ return [x for x in self.roots() if x.is_short_root()]
648
+
649
+ def long_roots(self):
650
+ """
651
+ Return a list of the long roots of ``self``.
652
+
653
+ EXAMPLES::
654
+
655
+ sage: L = RootSystem(['B',3]).root_lattice()
656
+ sage: sorted(L.long_roots()) # needs sage.graphs
657
+ [-alpha[1], -alpha[1] - 2*alpha[2] - 2*alpha[3],
658
+ -alpha[1] - alpha[2], -alpha[1] - alpha[2] - 2*alpha[3],
659
+ alpha[1], alpha[1] + alpha[2],
660
+ alpha[1] + alpha[2] + 2*alpha[3],
661
+ alpha[1] + 2*alpha[2] + 2*alpha[3], -alpha[2],
662
+ -alpha[2] - 2*alpha[3], alpha[2], alpha[2] + 2*alpha[3]]
663
+ """
664
+ if not self.cartan_type().is_finite():
665
+ raise NotImplementedError("only implemented for finite Cartan types")
666
+ return [x for x in self.roots() if x.is_long_root()]
667
+
668
+ @cached_method
669
+ def positive_roots(self, index_set=None):
670
+ r"""
671
+ Return the positive roots of ``self``.
672
+
673
+ If ``index_set`` is not ``None``, returns the positive roots of
674
+ the parabolic subsystem with simple roots in ``index_set``.
675
+
676
+ Algorithm for finite type: generate them from the simple roots by
677
+ applying successive reflections toward the positive chamber.
678
+
679
+ EXAMPLES::
680
+
681
+ sage: L = RootSystem(['A',3]).root_lattice()
682
+ sage: sorted(L.positive_roots()) # needs sage.graphs
683
+ [alpha[1], alpha[1] + alpha[2],
684
+ alpha[1] + alpha[2] + alpha[3], alpha[2],
685
+ alpha[2] + alpha[3], alpha[3]]
686
+ sage: sorted(L.positive_roots((1,2))) # needs sage.graphs
687
+ [alpha[1], alpha[1] + alpha[2], alpha[2]]
688
+ sage: sorted(L.positive_roots(())) # needs sage.graphs
689
+ []
690
+
691
+ sage: L = RootSystem(['A',3,1]).root_lattice()
692
+ sage: PR = L.positive_roots(); PR # needs sage.graphs
693
+ Disjoint union of Family (Positive real roots of type ['A', 3, 1],
694
+ Positive imaginary roots of type ['A', 3, 1])
695
+ sage: [PR.unrank(i) for i in range(10)] # needs sage.graphs
696
+ [alpha[1],
697
+ alpha[2],
698
+ alpha[3],
699
+ alpha[1] + alpha[2],
700
+ alpha[2] + alpha[3],
701
+ alpha[1] + alpha[2] + alpha[3],
702
+ alpha[0] + 2*alpha[1] + alpha[2] + alpha[3],
703
+ alpha[0] + alpha[1] + 2*alpha[2] + alpha[3],
704
+ alpha[0] + alpha[1] + alpha[2] + 2*alpha[3],
705
+ alpha[0] + 2*alpha[1] + 2*alpha[2] + alpha[3]]
706
+ """
707
+ if self.cartan_type().is_affine():
708
+ from sage.sets.disjoint_union_enumerated_sets \
709
+ import DisjointUnionEnumeratedSets
710
+ return DisjointUnionEnumeratedSets([self.positive_real_roots(),
711
+ self.positive_imaginary_roots()])
712
+ if not self.cartan_type().is_finite():
713
+ raise NotImplementedError("Only implemented for finite and"
714
+ " affine Cartan types")
715
+ if index_set is None:
716
+ index_set = tuple(self.cartan_type().index_set())
717
+ return RecursivelyEnumeratedSet([self.simple_root(i) for i in index_set],
718
+ attrcall('pred', index_set=index_set),
719
+ structure='graded', enumeration='breadth',
720
+ category=EnumeratedSets().Finite())
721
+
722
+ @cached_method
723
+ def nonparabolic_positive_roots(self, index_set=None):
724
+ r"""
725
+ Return the positive roots of ``self`` that are not in the
726
+ parabolic subsystem indicated by ``index_set``.
727
+
728
+ If ``index_set`` is ``None``, as in :meth:`positive_roots`
729
+ it is assumed to be the entire Dynkin node set. Then the
730
+ parabolic subsystem consists of all positive roots and the
731
+ empty list is returned.
732
+
733
+ EXAMPLES::
734
+
735
+ sage: L = RootSystem(['A',3]).root_lattice()
736
+ sage: L.nonparabolic_positive_roots() # needs sage.graphs
737
+ []
738
+ sage: sorted(L.nonparabolic_positive_roots((1,2))) # needs sage.graphs
739
+ [alpha[1] + alpha[2] + alpha[3], alpha[2] + alpha[3], alpha[3]]
740
+ sage: sorted(L.nonparabolic_positive_roots(())) # needs sage.graphs
741
+ [alpha[1], alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3],
742
+ alpha[2], alpha[2] + alpha[3], alpha[3]]
743
+ """
744
+ if not self.cartan_type().is_finite():
745
+ raise NotImplementedError("Only implemented for "
746
+ "finite Cartan type")
747
+ if index_set is None:
748
+ return []
749
+ return [x for x in self.positive_roots()
750
+ if x not in self.positive_roots(index_set)]
751
+
752
+ @cached_method
753
+ def nonparabolic_positive_root_sum(self, index_set=None):
754
+ r"""
755
+ Return the sum of positive roots not in a parabolic subsystem.
756
+
757
+ The conventions for ``index_set`` are as in :meth:`nonparabolic_positive_roots`.
758
+
759
+ EXAMPLES::
760
+
761
+ sage: Q = RootSystem(['A',3]).root_lattice()
762
+ sage: Q.nonparabolic_positive_root_sum((1,2)) # needs sage.graphs
763
+ alpha[1] + 2*alpha[2] + 3*alpha[3]
764
+ sage: Q.nonparabolic_positive_root_sum() # needs sage.graphs
765
+ 0
766
+ sage: Q.nonparabolic_positive_root_sum(()) # needs sage.graphs
767
+ 3*alpha[1] + 4*alpha[2] + 3*alpha[3]
768
+ """
769
+ return self.sum(self.nonparabolic_positive_roots(index_set))
770
+
771
+ def positive_real_roots(self):
772
+ """
773
+ Return the positive real roots of ``self``.
774
+
775
+ EXAMPLES::
776
+
777
+ sage: L = RootSystem(['A',3]).root_lattice()
778
+ sage: sorted(L.positive_real_roots()) # needs sage.graphs
779
+ [alpha[1], alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3],
780
+ alpha[2], alpha[2] + alpha[3], alpha[3]]
781
+
782
+ sage: L = RootSystem(['A',3,1]).root_lattice()
783
+ sage: PRR = L.positive_real_roots(); PRR # needs sage.graphs
784
+ Positive real roots of type ['A', 3, 1]
785
+ sage: [PRR.unrank(i) for i in range(10)] # needs sage.graphs
786
+ [alpha[1],
787
+ alpha[2],
788
+ alpha[3],
789
+ alpha[1] + alpha[2],
790
+ alpha[2] + alpha[3],
791
+ alpha[1] + alpha[2] + alpha[3],
792
+ alpha[0] + 2*alpha[1] + alpha[2] + alpha[3],
793
+ alpha[0] + alpha[1] + 2*alpha[2] + alpha[3],
794
+ alpha[0] + alpha[1] + alpha[2] + 2*alpha[3],
795
+ alpha[0] + 2*alpha[1] + 2*alpha[2] + alpha[3]]
796
+
797
+ sage: Q = RootSystem(['A',4,2]).root_lattice()
798
+ sage: PR = Q.positive_roots() # needs sage.graphs
799
+ sage: [PR.unrank(i) for i in range(5)] # needs sage.graphs
800
+ [alpha[1],
801
+ alpha[2],
802
+ alpha[1] + alpha[2],
803
+ 2*alpha[1] + alpha[2],
804
+ alpha[0] + alpha[1] + alpha[2]]
805
+
806
+ sage: Q = RootSystem(['D',3,2]).root_lattice()
807
+ sage: PR = Q.positive_roots() # needs sage.graphs
808
+ sage: [PR.unrank(i) for i in range(5)] # needs sage.graphs
809
+ [alpha[1],
810
+ alpha[2],
811
+ alpha[1] + 2*alpha[2],
812
+ alpha[1] + alpha[2],
813
+ alpha[0] + alpha[1] + 2*alpha[2]]
814
+ """
815
+ if self.cartan_type().is_finite():
816
+ return tuple(RecursivelyEnumeratedSet(self.simple_roots(),
817
+ attrcall('pred'), structure='graded',
818
+ enumeration='breadth'))
819
+ if not self.cartan_type().is_affine():
820
+ raise NotImplementedError("only implemented for finite and affine Cartan types")
821
+
822
+ from sage.categories.cartesian_product import cartesian_product
823
+ from sage.combinat.root_system.root_system import RootSystem
824
+ from sage.sets.positive_integers import PositiveIntegers
825
+ from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets
826
+
827
+ Q = RootSystem(self.cartan_type().classical()).root_space(self.base_ring())
828
+
829
+ # Start with the classical positive roots
830
+ alpha = self.simple_roots()
831
+
832
+ def lift(x):
833
+ """
834
+ Lift up the classical element into ``self``.
835
+ """
836
+ return self.sum(c*alpha[i] for i,c in x)
837
+ P = Family(Q.positive_real_roots(), lift)
838
+
839
+ # Add all of the delta shifts
840
+ delta = self.null_root()
841
+ if self.cartan_type().is_untwisted_affine():
842
+ C = cartesian_product([PositiveIntegers(), Q.roots()])
843
+ F = Family(C, lambda x: lift(x[1]) + x[0]*delta)
844
+ D = DisjointUnionEnumeratedSets([P, F])
845
+ elif self.cartan_type().type() == 'BC' or self.cartan_type().dual().type() == 'BC':
846
+ Cs = cartesian_product([PositiveIntegers(), Q.short_roots()])
847
+ Cl = cartesian_product([PositiveIntegers(), Q.long_roots()])
848
+ Fs = Family(Cl, lambda x: (lift(x[1]) + (2*x[0]-1)*delta) / 2)
849
+ Fm = Family(Cs, lambda x: lift(x[1]) + x[0]*delta)
850
+ Fl = Family(Cl, lambda x: lift(x[1]) + 2*x[0]*delta)
851
+ D = DisjointUnionEnumeratedSets([P, Fs, Fm, Fl])
852
+ else: # Other twisted types
853
+ Cs = cartesian_product([PositiveIntegers(), Q.short_roots()])
854
+ Cl = cartesian_product([PositiveIntegers(), Q.long_roots()])
855
+ Fs = Family(Cs, lambda x: lift(x[1]) + x[0]*delta)
856
+ if self.cartan_type().dual() == 'G': # D_4^3
857
+ k = 3
858
+ else:
859
+ k = 2
860
+ Fl = Family(Cl, lambda x: lift(x[1]) + x[0]*k*delta)
861
+ D = DisjointUnionEnumeratedSets([P, Fs, Fl])
862
+
863
+ # Return the final union
864
+ D.rename("Positive real roots of type {}".format(self.cartan_type()))
865
+ return D
866
+
867
+ def positive_imaginary_roots(self):
868
+ """
869
+ Return the positive imaginary roots of ``self``.
870
+
871
+ EXAMPLES::
872
+
873
+ sage: L = RootSystem(['A',3]).root_lattice()
874
+ sage: L.positive_imaginary_roots()
875
+ ()
876
+
877
+ sage: L = RootSystem(['A',3,1]).root_lattice()
878
+ sage: PIR = L.positive_imaginary_roots(); PIR # needs sage.graphs
879
+ Positive imaginary roots of type ['A', 3, 1]
880
+ sage: [PIR.unrank(i) for i in range(5)] # needs sage.graphs
881
+ [alpha[0] + alpha[1] + alpha[2] + alpha[3],
882
+ 2*alpha[0] + 2*alpha[1] + 2*alpha[2] + 2*alpha[3],
883
+ 3*alpha[0] + 3*alpha[1] + 3*alpha[2] + 3*alpha[3],
884
+ 4*alpha[0] + 4*alpha[1] + 4*alpha[2] + 4*alpha[3],
885
+ 5*alpha[0] + 5*alpha[1] + 5*alpha[2] + 5*alpha[3]]
886
+ """
887
+ if self.cartan_type().is_finite():
888
+ return ()
889
+ if not self.cartan_type().is_affine():
890
+ raise NotImplementedError("only implemented for finite and affine Cartan types")
891
+ from sage.sets.positive_integers import PositiveIntegers
892
+ delta = self.null_root()
893
+ F = Family(PositiveIntegers(), lambda x: x*delta)
894
+ F.rename("Positive imaginary roots of type {}".format(self.cartan_type()))
895
+ return F
896
+
897
+ @cached_method
898
+ def positive_roots_by_height(self, increasing=True):
899
+ r"""
900
+ Return a list of positive roots in increasing order by height.
901
+
902
+ If ``increasing`` is False, returns them in decreasing order.
903
+
904
+ .. warning::
905
+
906
+ Raise an error if the Cartan type is not finite.
907
+
908
+ EXAMPLES::
909
+
910
+ sage: L = RootSystem(['C',2]).root_lattice()
911
+ sage: L.positive_roots_by_height() # needs sage.graphs
912
+ [alpha[2], alpha[1], alpha[1] + alpha[2], 2*alpha[1] + alpha[2]]
913
+ sage: L.positive_roots_by_height(increasing=False) # needs sage.graphs
914
+ [2*alpha[1] + alpha[2], alpha[1] + alpha[2], alpha[2], alpha[1]]
915
+
916
+ sage: L = RootSystem(['A',2,1]).root_lattice()
917
+ sage: L.positive_roots_by_height() # needs sage.graphs
918
+ Traceback (most recent call last):
919
+ ...
920
+ NotImplementedError: Only implemented for finite Cartan type
921
+ """
922
+
923
+ if not self.cartan_type().is_finite():
924
+ raise NotImplementedError("Only implemented for finite Cartan type")
925
+ ranks = self.root_poset().level_sets()
926
+ if not increasing:
927
+ ranks.reverse()
928
+ roots = []
929
+ for x in ranks:
930
+ roots += x
931
+ return [x.element for x in roots]
932
+
933
+ @cached_method
934
+ def positive_roots_parabolic(self, index_set=None):
935
+ r"""
936
+ Return the set of positive roots for the parabolic subsystem with Dynkin node set ``index_set``.
937
+
938
+ INPUT:
939
+
940
+ - ``index_set`` -- (default: ``None``) the Dynkin node set of the
941
+ parabolic subsystem. It should be a tuple. The default value
942
+ implies the entire Dynkin node set
943
+
944
+ EXAMPLES::
945
+
946
+ sage: lattice = RootSystem(['A',3]).root_lattice()
947
+ sage: sorted(lattice.positive_roots_parabolic((1,3)), key=str) # needs sage.graphs
948
+ [alpha[1], alpha[3]]
949
+ sage: sorted(lattice.positive_roots_parabolic((2,3)), key=str) # needs sage.graphs
950
+ [alpha[2], alpha[2] + alpha[3], alpha[3]]
951
+ sage: sorted(lattice.positive_roots_parabolic(), key=str) # needs sage.graphs
952
+ [alpha[1], alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3],
953
+ alpha[2], alpha[2] + alpha[3], alpha[3]]
954
+
955
+ .. WARNING::
956
+
957
+ This returns an error if the Cartan type is not finite.
958
+ """
959
+ if not self.cartan_type().is_finite():
960
+ raise NotImplementedError("Only implemented for finite Cartan type")
961
+ if index_set is None:
962
+ index_set = tuple(self.cartan_type().index_set())
963
+
964
+ def parabolic_covers(alpha):
965
+ return [x for x in alpha.pred() if x.is_parabolic_root(index_set)]
966
+
967
+ generators = [x for x in self.simple_roots() if x.is_parabolic_root(index_set)]
968
+ return RecursivelyEnumeratedSet(generators, parabolic_covers,
969
+ structure='graded', enumeration='breadth')
970
+
971
+ @cached_method
972
+ def positive_roots_nonparabolic(self, index_set=None):
973
+ r"""
974
+ Return the set of positive roots outside the parabolic subsystem with Dynkin node set ``index_set``.
975
+
976
+ INPUT:
977
+
978
+ - ``index_set`` -- (default: ``None``) the Dynkin node set of the
979
+ parabolic subsystem. It should be a tuple. The default value
980
+ implies the entire Dynkin node set
981
+
982
+ EXAMPLES::
983
+
984
+ sage: # needs sage.graphs
985
+ sage: lattice = RootSystem(['A',3]).root_lattice()
986
+ sage: sorted(lattice.positive_roots_nonparabolic((1,3)), key=str)
987
+ [alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3],
988
+ alpha[2], alpha[2] + alpha[3]]
989
+ sage: sorted(lattice.positive_roots_nonparabolic((2,3)), key=str)
990
+ [alpha[1], alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3]]
991
+ sage: lattice.positive_roots_nonparabolic()
992
+ []
993
+ sage: lattice.positive_roots_nonparabolic((1,2,3))
994
+ []
995
+
996
+ .. WARNING::
997
+
998
+ This returns an error if the Cartan type is not finite.
999
+ """
1000
+ if not self.cartan_type().is_finite():
1001
+ raise NotImplementedError("Only implemented for finite Cartan type")
1002
+ if index_set is None:
1003
+ index_set = tuple(self.cartan_type().index_set())
1004
+ return [x for x in self.positive_roots() if not x.is_parabolic_root(index_set)]
1005
+
1006
+ @cached_method
1007
+ def positive_roots_nonparabolic_sum(self, index_set=None):
1008
+ r"""
1009
+ Return the sum of positive roots outside the parabolic subsystem with Dynkin node set ``index_set``.
1010
+
1011
+ INPUT:
1012
+
1013
+ - ``index_set`` -- (default: ``None``) the Dynkin node set of the
1014
+ parabolic subsystem. It should be a tuple. The default value
1015
+ implies the entire Dynkin node set
1016
+
1017
+ EXAMPLES::
1018
+
1019
+ sage: # needs sage.graphs
1020
+ sage: lattice = RootSystem(['A',3]).root_lattice()
1021
+ sage: lattice.positive_roots_nonparabolic_sum((1,3))
1022
+ 2*alpha[1] + 4*alpha[2] + 2*alpha[3]
1023
+ sage: lattice.positive_roots_nonparabolic_sum((2,3))
1024
+ 3*alpha[1] + 2*alpha[2] + alpha[3]
1025
+ sage: lattice.positive_roots_nonparabolic_sum(())
1026
+ 3*alpha[1] + 4*alpha[2] + 3*alpha[3]
1027
+ sage: lattice.positive_roots_nonparabolic_sum()
1028
+ 0
1029
+ sage: lattice.positive_roots_nonparabolic_sum((1,2,3))
1030
+ 0
1031
+
1032
+ .. WARNING::
1033
+
1034
+ This returns an error if the Cartan type is not finite.
1035
+ """
1036
+
1037
+ if not self.cartan_type().is_finite():
1038
+ raise ValueError("Cartan type %s is not finite" % (self.cartan_type()))
1039
+ if index_set is None or index_set == tuple(self.cartan_type().index_set()):
1040
+ return self.zero()
1041
+ return sum(self.positive_roots_nonparabolic(index_set))
1042
+
1043
+ def root_poset(self, restricted=False, facade=False):
1044
+ r"""
1045
+ Return the (restricted) root poset associated to ``self``.
1046
+
1047
+ The elements are given by the positive roots (resp. non-simple,
1048
+ positive roots), and `\alpha \leq \beta` iff `\beta - \alpha` is a
1049
+ nonnegative linear combination of simple roots.
1050
+
1051
+ INPUT:
1052
+
1053
+ - ``restricted`` -- boolean (default: ``False``); if ``True``, only
1054
+ non-simple roots are considered.
1055
+ - ``facade`` -- boolean (default: ``False``); passes facade option
1056
+ to the poset generator
1057
+
1058
+ EXAMPLES::
1059
+
1060
+ sage: # needs sage.graphs
1061
+ sage: Phi = RootSystem(['A',1]).root_poset(); Phi
1062
+ Finite poset containing 1 elements
1063
+ sage: Phi.cover_relations()
1064
+ []
1065
+ sage: Phi = RootSystem(['A',2]).root_poset(); Phi
1066
+ Finite poset containing 3 elements
1067
+ sage: sorted(Phi.cover_relations(), key=str)
1068
+ [[alpha[1], alpha[1] + alpha[2]], [alpha[2], alpha[1] + alpha[2]]]
1069
+ sage: Phi = RootSystem(['A',3]).root_poset(restricted=True); Phi
1070
+ Finite poset containing 3 elements
1071
+ sage: sorted(Phi.cover_relations(), key=str)
1072
+ [[alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3]],
1073
+ [alpha[2] + alpha[3], alpha[1] + alpha[2] + alpha[3]]]
1074
+ sage: Phi = RootSystem(['B',2]).root_poset(); Phi
1075
+ Finite poset containing 4 elements
1076
+ sage: sorted(Phi.cover_relations(), key=str)
1077
+ [[alpha[1] + alpha[2], alpha[1] + 2*alpha[2]],
1078
+ [alpha[1], alpha[1] + alpha[2]],
1079
+ [alpha[2], alpha[1] + alpha[2]]]
1080
+
1081
+ TESTS:
1082
+
1083
+ Check that :issue:`17982` is fixed::
1084
+
1085
+ sage: RootSystem(['A', 2]).ambient_space().root_poset() # needs sage.graphs
1086
+ Finite poset containing 3 elements
1087
+ """
1088
+ from sage.combinat.posets.posets import Poset
1089
+ rels = []
1090
+ pos_roots = set(self.positive_roots())
1091
+ simple_roots = self.simple_roots()
1092
+ if restricted:
1093
+ pos_roots = [beta for beta in pos_roots if beta not in simple_roots]
1094
+ for root in pos_roots:
1095
+ for simple_root in simple_roots:
1096
+ root_cover = root + simple_root
1097
+ if root_cover in pos_roots:
1098
+ rels.append((root, root_cover))
1099
+ return Poset((pos_roots, rels), cover_relations=True, facade=facade)
1100
+
1101
+ def nonnesting_partition_lattice(self, facade=False):
1102
+ r"""
1103
+ Return the lattice of nonnesting partitions.
1104
+
1105
+ This is the lattice of order ideals of the root poset.
1106
+
1107
+ This has been defined by Postnikov, see Remark 2 in [Reiner97]_.
1108
+
1109
+ .. SEEALSO::
1110
+
1111
+ :meth:`generalized_nonnesting_partition_lattice`, :meth:`root_poset`
1112
+
1113
+ EXAMPLES::
1114
+
1115
+ sage: R = RootSystem(['A', 3])
1116
+ sage: RS = R.root_lattice()
1117
+ sage: P = RS.nonnesting_partition_lattice(); P # needs sage.graphs
1118
+ Finite lattice containing 14 elements
1119
+ sage: P.coxeter_transformation()**10 == 1 # needs sage.graphs sage.libs.flint
1120
+ True
1121
+
1122
+ sage: # needs sage.graphs
1123
+ sage: R = RootSystem(['B', 3])
1124
+ sage: RS = R.root_lattice()
1125
+ sage: P = RS.nonnesting_partition_lattice(); P
1126
+ Finite lattice containing 20 elements
1127
+ sage: P.coxeter_transformation()**7 == 1 # needs sage.libs.flint
1128
+ True
1129
+
1130
+ REFERENCES:
1131
+
1132
+ .. [Reiner97] Victor Reiner. *Non-crossing partitions for
1133
+ classical reflection groups*. Discrete Mathematics 177 (1997)
1134
+ .. [Arm06] Drew Armstrong. *Generalized Noncrossing Partitions and
1135
+ Combinatorics of Coxeter Groups*. :arxiv:`math/0611106`
1136
+ """
1137
+ return self.root_poset(facade=facade).order_ideals_lattice(facade=facade)
1138
+
1139
+ def generalized_nonnesting_partition_lattice(self, m, facade=False):
1140
+ r"""
1141
+ Return the lattice of `m`-nonnesting partitions.
1142
+
1143
+ This has been defined by Athanasiadis, see chapter 5 of [Arm06]_.
1144
+
1145
+ INPUT:
1146
+
1147
+ - ``m`` -- integer
1148
+
1149
+ .. SEEALSO::
1150
+
1151
+ :meth:`nonnesting_partition_lattice`
1152
+
1153
+ EXAMPLES::
1154
+
1155
+ sage: R = RootSystem(['A', 2])
1156
+ sage: RS = R.root_lattice()
1157
+ sage: P = RS.generalized_nonnesting_partition_lattice(2); P # needs sage.graphs
1158
+ Finite lattice containing 12 elements
1159
+ sage: P.coxeter_transformation()**20 == 1 # needs sage.graphs sage.libs.flint
1160
+ True
1161
+ """
1162
+ Phi_plus = self.positive_roots()
1163
+ L = self.nonnesting_partition_lattice(facade=True)
1164
+ chains = [chain for chain in L.chains().list() if len(chain) <= m]
1165
+ multichains = []
1166
+ for chain in chains:
1167
+ for multilist in combinations_with_replacement(list(range(len(chain))), m):
1168
+ if len(set(multilist)) == len(chain):
1169
+ multichains.append(tuple([chain[i] for i in multilist]))
1170
+
1171
+ def is_saturated_chain(chain):
1172
+ for i in range(1, m + 1):
1173
+ for j in range(1, m - i + 1):
1174
+ for alpha in chain[i - 1]:
1175
+ for beta in chain[j - 1]:
1176
+ gamma = alpha + beta
1177
+ if gamma in Phi_plus and gamma not in chain[i+j-1]:
1178
+ return False
1179
+ cochain = [[beta for beta in Phi_plus if beta not in ideal]
1180
+ for ideal in chain]
1181
+ for i in range(1, m + 1):
1182
+ for j in range(1, m + 1):
1183
+ for alpha in cochain[i - 1]:
1184
+ for beta in cochain[j - 1]:
1185
+ gamma = alpha + beta
1186
+ if gamma in Phi_plus and gamma not in cochain[min(m - 1, i + j - 1)]:
1187
+ return False
1188
+ return True
1189
+
1190
+ def is_componentwise_subset(chain1, chain2):
1191
+ return all(chain1[i].issubset(chain2[i])
1192
+ for i in range(len(chain1)))
1193
+ from sage.combinat.posets.lattices import LatticePoset
1194
+ saturated_chains = [multichain for multichain in multichains
1195
+ if is_saturated_chain(multichain)]
1196
+ return LatticePoset((saturated_chains, is_componentwise_subset),
1197
+ facade=facade)
1198
+
1199
+ def almost_positive_roots(self):
1200
+ r"""
1201
+ Return the almost positive roots of ``self``.
1202
+
1203
+ These are the positive roots together with the simple negative roots.
1204
+
1205
+ .. SEEALSO:: :meth:`almost_positive_root_decomposition`, :meth:`tau_plus_minus`
1206
+
1207
+ EXAMPLES::
1208
+
1209
+ sage: L = RootSystem(['A',2]).root_lattice()
1210
+ sage: L.almost_positive_roots() # needs sage.graphs
1211
+ [-alpha[1], alpha[1], alpha[1] + alpha[2], -alpha[2], alpha[2]]
1212
+ """
1213
+ if not self.cartan_type().is_finite():
1214
+ raise ValueError("%s is not a finite Cartan type" % (self.cartan_type()))
1215
+ return sorted([ -beta for beta in self.simple_roots() ] + list(self.positive_roots()))
1216
+
1217
+ def negative_roots(self):
1218
+ r"""
1219
+ Return the negative roots of ``self``.
1220
+
1221
+ EXAMPLES::
1222
+
1223
+ sage: L = RootSystem(['A', 2]).weight_lattice()
1224
+ sage: sorted(L.negative_roots()) # needs sage.graphs
1225
+ [-2*Lambda[1] + Lambda[2], -Lambda[1] - Lambda[2], Lambda[1] - 2*Lambda[2]]
1226
+
1227
+ Algorithm: negate the positive roots
1228
+ """
1229
+ if not self.cartan_type().is_finite():
1230
+ raise ValueError("%s is not a finite Cartan type" % self.cartan_type())
1231
+ return self.positive_roots().map(attrcall('__neg__'), is_injective=True)
1232
+
1233
+ ##########################################################################
1234
+ # coroots
1235
+ ##########################################################################
1236
+
1237
+ def coroot_lattice(self):
1238
+ """
1239
+ Return the coroot lattice.
1240
+
1241
+ EXAMPLES::
1242
+
1243
+ sage: RootSystem(['A',2]).root_lattice().coroot_lattice()
1244
+ Coroot lattice of the Root system of type ['A', 2]
1245
+ """
1246
+ return self.root_system.coroot_lattice()
1247
+
1248
+ def coroot_space(self, base_ring=QQ):
1249
+ r"""
1250
+ Return the coroot space over ``base_ring``.
1251
+
1252
+ INPUT:
1253
+
1254
+ - ``base_ring`` -- a ring (default: `\QQ`)
1255
+
1256
+ EXAMPLES::
1257
+
1258
+ sage: RootSystem(['A',2]).root_lattice().coroot_space()
1259
+ Coroot space over the Rational Field of the Root system of type ['A', 2]
1260
+
1261
+ sage: RootSystem(['A',2]).root_lattice().coroot_space(QQ['q'])
1262
+ Coroot space over the Univariate Polynomial Ring in q over Rational Field
1263
+ of the Root system of type ['A', 2]
1264
+ """
1265
+ return self.root_system.coroot_space(base_ring=base_ring)
1266
+
1267
+ def simple_coroot(self, i):
1268
+ """
1269
+ Return the `i`-th simple coroot.
1270
+
1271
+ EXAMPLES::
1272
+
1273
+ sage: RootSystem(['A',2]).root_lattice().simple_coroot(1)
1274
+ alphacheck[1]
1275
+ """
1276
+ return self.coroot_lattice().simple_root(i)
1277
+
1278
+ @cached_method
1279
+ def simple_coroots(self):
1280
+ r"""
1281
+ Return the family `(\alpha^\vee_i)_{i\in I}` of the simple coroots.
1282
+
1283
+ EXAMPLES::
1284
+
1285
+ sage: alphacheck = RootSystem(['A',3]).root_lattice().simple_coroots()
1286
+ sage: [alphacheck[i] for i in [1, 2, 3]]
1287
+ [alphacheck[1], alphacheck[2], alphacheck[3]]
1288
+ """
1289
+ if not hasattr(self,"cache_simple_coroots"):
1290
+ self.cache_simple_coroots = Family(self.index_set(), self.simple_coroot)
1291
+ # Should we use rename to set a nice name for this family?
1292
+ # self.cache_simple_coroots.rename('alphacheck')
1293
+ # break some doctests
1294
+ return self.cache_simple_coroots
1295
+
1296
+ @cached_method
1297
+ def alphacheck(self):
1298
+ r"""
1299
+ Return the family `(\alpha^\vee_i)_{i \in I}` of the simple
1300
+ coroots, with the extra feature that, for simple irreducible
1301
+ root systems, `\alpha^\vee_0` yields the coroot associated to
1302
+ the opposite of the highest root (caveat: for non-simply-laced
1303
+ root systems, this is not the opposite of the highest coroot!).
1304
+
1305
+ EXAMPLES::
1306
+
1307
+ sage: alphacheck = RootSystem(["A",2]).ambient_space().alphacheck()
1308
+ sage: alphacheck
1309
+ Finite family {1: (1, -1, 0), 2: (0, 1, -1)}
1310
+
1311
+ Here is now `\alpha^\vee_0`:
1312
+
1313
+ (-1, 0, 1)
1314
+
1315
+ .. TODO:: add a non simply laced example
1316
+
1317
+ Finally, here is an affine example::
1318
+
1319
+ sage: RootSystem(["A",2,1]).weight_space().alphacheck()
1320
+ Finite family {0: alphacheck[0], 1: alphacheck[1], 2: alphacheck[2]}
1321
+
1322
+ sage: RootSystem(["A",3]).ambient_space().alphacheck()
1323
+ Finite family {1: (1, -1, 0, 0), 2: (0, 1, -1, 0), 3: (0, 0, 1, -1)}
1324
+ """
1325
+ if self.root_system.is_finite() and self.root_system.is_irreducible():
1326
+ return Family(self.index_set(), self.simple_coroot,
1327
+ hidden_keys=[0], hidden_function=lambda i: - self.cohighest_root())
1328
+ else:
1329
+ return self.simple_coroots()
1330
+
1331
+ @cached_method
1332
+ def cohighest_root(self):
1333
+ """
1334
+ Return the associated coroot of the highest root.
1335
+
1336
+ .. NOTE:: this is usually not the highest coroot.
1337
+
1338
+ EXAMPLES::
1339
+
1340
+ sage: RootSystem(['A', 3]).ambient_space().cohighest_root()
1341
+ (1, 0, 0, -1)
1342
+ """
1343
+ return self.highest_root().associated_coroot()
1344
+
1345
+ ##########################################################################
1346
+ # null_root
1347
+ ##########################################################################
1348
+
1349
+ @cached_method
1350
+ def null_root(self):
1351
+ """
1352
+ Return the null root of ``self``.
1353
+
1354
+ The null root is the smallest non trivial positive root which is
1355
+ orthogonal to all simple coroots. It exists for any affine root
1356
+ system.
1357
+
1358
+ EXAMPLES::
1359
+
1360
+ sage: RootSystem(['C',2,1]).root_lattice().null_root() # needs sage.graphs
1361
+ alpha[0] + 2*alpha[1] + alpha[2]
1362
+ sage: RootSystem(['D',4,1]).root_lattice().null_root() # needs sage.graphs
1363
+ alpha[0] + alpha[1] + 2*alpha[2] + alpha[3] + alpha[4]
1364
+ sage: RootSystem(['F',4,1]).root_lattice().null_root() # needs sage.graphs
1365
+ alpha[0] + 2*alpha[1] + 3*alpha[2] + 4*alpha[3] + 2*alpha[4]
1366
+ """
1367
+ if self.cartan_type().is_affine():
1368
+ coef = self.cartan_type().a()
1369
+ return sum(coef[k]*self.simple_roots()[k] for k in coef.keys())
1370
+
1371
+ ##########################################################################
1372
+ # null_coroot (Also called CanonicalCentralElement)
1373
+ ##########################################################################
1374
+
1375
+ @cached_method
1376
+ def null_coroot(self):
1377
+ """
1378
+ Return the null coroot of ``self``.
1379
+
1380
+ The null coroot is the smallest non trivial positive coroot which is
1381
+ orthogonal to all simple roots. It exists for any affine root
1382
+ system.
1383
+
1384
+ EXAMPLES::
1385
+
1386
+ sage: RootSystem(['C',2,1]).root_lattice().null_coroot() # needs sage.graphs
1387
+ alphacheck[0] + alphacheck[1] + alphacheck[2]
1388
+ sage: RootSystem(['D',4,1]).root_lattice().null_coroot() # needs sage.graphs
1389
+ alphacheck[0] + alphacheck[1] + 2*alphacheck[2]
1390
+ + alphacheck[3] + alphacheck[4]
1391
+ sage: RootSystem(['F',4,1]).root_lattice().null_coroot() # needs sage.graphs
1392
+ alphacheck[0] + 2*alphacheck[1] + 3*alphacheck[2]
1393
+ + 2*alphacheck[3] + alphacheck[4]
1394
+ """
1395
+ if not self.cartan_type().is_affine():
1396
+ raise ValueError("%s is not an affine Cartan type" % (self.cartan_type()))
1397
+ coef = self.cartan_type().acheck()
1398
+ return sum(coef[k]*self.simple_coroots()[k] for k in coef.keys())
1399
+
1400
+ ##########################################################################
1401
+ # fundamental weights
1402
+ ##########################################################################
1403
+
1404
+ def fundamental_weights_from_simple_roots(self):
1405
+ r"""
1406
+ Return the fundamental weights.
1407
+
1408
+ This is computed from the simple roots by using the
1409
+ inverse of the Cartan matrix. This method is therefore
1410
+ only valid for finite types and if this realization of the
1411
+ root lattice is large enough to contain them.
1412
+
1413
+ EXAMPLES:
1414
+
1415
+ In the root space, we retrieve the inverse of the Cartan matrix::
1416
+
1417
+ sage: L = RootSystem(["B",3]).root_space()
1418
+ sage: L.fundamental_weights_from_simple_roots() # needs sage.graphs
1419
+ Finite family {1: alpha[1] + alpha[2] + alpha[3],
1420
+ 2: alpha[1] + 2*alpha[2] + 2*alpha[3],
1421
+ 3: 1/2*alpha[1] + alpha[2] + 3/2*alpha[3]}
1422
+ sage: ~L.cartan_type().cartan_matrix() # needs sage.graphs
1423
+ [ 1 1 1/2]
1424
+ [ 1 2 1]
1425
+ [ 1 2 3/2]
1426
+
1427
+ In the weight lattice and the ambient space, we retrieve
1428
+ the fundamental weights::
1429
+
1430
+ sage: L = RootSystem(["B",3]).weight_lattice()
1431
+ sage: L.fundamental_weights_from_simple_roots() # needs sage.graphs
1432
+ Finite family {1: Lambda[1], 2: Lambda[2], 3: Lambda[3]}
1433
+
1434
+ sage: L = RootSystem(["B",3]).ambient_space()
1435
+ sage: L.fundamental_weights()
1436
+ Finite family {1: (1, 0, 0), 2: (1, 1, 0), 3: (1/2, 1/2, 1/2)}
1437
+ sage: L.fundamental_weights_from_simple_roots() # needs sage.graphs
1438
+ Finite family {1: (1, 0, 0), 2: (1, 1, 0), 3: (1/2, 1/2, 1/2)}
1439
+
1440
+ However the fundamental weights do not belong to the root
1441
+ lattice::
1442
+
1443
+ sage: L = RootSystem(["B",3]).root_lattice()
1444
+ sage: L.fundamental_weights_from_simple_roots() # needs sage.graphs
1445
+ Traceback (most recent call last):
1446
+ ...
1447
+ ValueError: The fundamental weights do not live in this realization
1448
+ of the root lattice
1449
+
1450
+ Beware of the usual `GL_n` vs `SL_n` catch in type `A`::
1451
+
1452
+ sage: L = RootSystem(["A",3]).ambient_space()
1453
+ sage: L.fundamental_weights()
1454
+ Finite family {1: (1, 0, 0, 0), 2: (1, 1, 0, 0), 3: (1, 1, 1, 0)}
1455
+ sage: L.fundamental_weights_from_simple_roots() # needs sage.graphs
1456
+ Finite family {1: (3/4, -1/4, -1/4, -1/4),
1457
+ 2: (1/2, 1/2, -1/2, -1/2),
1458
+ 3: (1/4, 1/4, 1/4, -3/4)}
1459
+
1460
+ sage: L = RootSystem(["A",3]).ambient_lattice()
1461
+ sage: L.fundamental_weights_from_simple_roots() # needs sage.graphs
1462
+ Traceback (most recent call last):
1463
+ ...
1464
+ ValueError: The fundamental weights do not live in this realization
1465
+ of the root lattice
1466
+ """
1467
+ # We first scale the inverse of the Cartan matrix to be
1468
+ # with integer coefficients; then the linear combination
1469
+ # of the simple roots is guaranteed to live in this space,
1470
+ # and then we rely on division by d to fail gracefully.
1471
+ M = self.cartan_type().cartan_matrix()
1472
+ d = M.det()
1473
+ if not d:
1474
+ raise TypeError("The Cartan matrix is not invertible")
1475
+ M = d*~M
1476
+ fundamental_weights = [self.linear_combination(zip(self.simple_roots(), column))
1477
+ for column in M.columns()]
1478
+ try:
1479
+ fundamental_weights = [x/d for x in fundamental_weights]
1480
+ except ValueError:
1481
+ raise ValueError("The fundamental weights do not live in this realization of the root lattice")
1482
+ return Family(dict(zip(self.index_set(),fundamental_weights)))
1483
+
1484
+ ##########################################################################
1485
+ # reflections
1486
+ ##########################################################################
1487
+
1488
+ def reflection(self, root, coroot=None):
1489
+ """
1490
+ Return the reflection along the ``root``, and across the hyperplane
1491
+ defined by ``coroot``, as a function from ``self`` to ``self``.
1492
+
1493
+ EXAMPLES::
1494
+
1495
+ sage: # needs sage.graphs
1496
+ sage: space = RootSystem(['A',2]).weight_lattice()
1497
+ sage: x = space.simple_roots()[1]
1498
+ sage: y = space.simple_coroots()[1]
1499
+ sage: s = space.reflection(x,y)
1500
+ sage: x
1501
+ 2*Lambda[1] - Lambda[2]
1502
+ sage: s(x)
1503
+ -2*Lambda[1] + Lambda[2]
1504
+ sage: s(-x)
1505
+ 2*Lambda[1] - Lambda[2]
1506
+ """
1507
+ if coroot is None:
1508
+ coroot = root.associated_coroot()
1509
+ return lambda v: v - v.scalar(coroot) * root
1510
+
1511
+ @cached_method
1512
+ def simple_reflection(self, i):
1513
+ """
1514
+ Return the `i`-th simple reflection, as a function from
1515
+ ``self`` to ``self``.
1516
+
1517
+ INPUT:
1518
+
1519
+ - ``i`` -- an element of the index set of ``self``
1520
+
1521
+ EXAMPLES::
1522
+
1523
+ sage: space = RootSystem(['A',2]).ambient_lattice()
1524
+ sage: s = space.simple_reflection(1)
1525
+ sage: x = space.simple_roots()[1]; x
1526
+ (1, -1, 0)
1527
+ sage: s(x)
1528
+ (-1, 1, 0)
1529
+ """
1530
+ return self.reflection(self.simple_root(i), self.simple_coroot(i))
1531
+
1532
+ @cached_method
1533
+ def simple_reflections(self):
1534
+ r"""
1535
+ Return the family `(s_i)_{i\in I}` of the simple reflections
1536
+ of this root system.
1537
+
1538
+ EXAMPLES::
1539
+
1540
+ sage: r = RootSystem(["A", 2]).root_lattice()
1541
+ sage: s = r.simple_reflections()
1542
+ sage: s[1]( r.simple_root(1) ) # needs sage.graphs
1543
+ -alpha[1]
1544
+
1545
+ TESTS::
1546
+
1547
+ sage: s
1548
+ simple reflections
1549
+ """
1550
+ res = self.alpha().zip(self.reflection, self.alphacheck())
1551
+ # Should we use rename to set a nice name for this family?
1552
+ res.rename('simple reflections')
1553
+ return res
1554
+
1555
+ s = simple_reflections
1556
+
1557
+ ##########################################################################
1558
+ # projections
1559
+ ##########################################################################
1560
+
1561
+ def projection(self, root, coroot=None, to_negative=True):
1562
+ r"""
1563
+ Return the projection along the ``root``, and across the
1564
+ hyperplane defined by ``coroot``, as a function `\pi` from ``self`` to
1565
+ ``self``.
1566
+
1567
+ `\pi` is a half-linear map which stabilizes the negative
1568
+ half space and acts by reflection on the positive half space.
1569
+
1570
+ If ``to_negative`` is ``False``, then project onto the positive
1571
+ half space instead.
1572
+
1573
+ EXAMPLES::
1574
+
1575
+ sage: # needs sage.graphs
1576
+ sage: space = RootSystem(['A',2]).weight_lattice()
1577
+ sage: x = space.simple_roots()[1]
1578
+ sage: y = space.simple_coroots()[1]
1579
+ sage: pi = space.projection(x,y)
1580
+ sage: x
1581
+ 2*Lambda[1] - Lambda[2]
1582
+ sage: pi(x)
1583
+ -2*Lambda[1] + Lambda[2]
1584
+ sage: pi(-x)
1585
+ -2*Lambda[1] + Lambda[2]
1586
+ sage: pi = space.projection(x,y,False)
1587
+ sage: pi(-x)
1588
+ 2*Lambda[1] - Lambda[2]
1589
+ """
1590
+ if coroot is None:
1591
+ coroot = root.associated_coroot()
1592
+
1593
+ return lambda v: v - v.scalar(coroot) * root if ((v.scalar(coroot) > 0) == to_negative) else v
1594
+
1595
+ @cached_method
1596
+ def simple_projection(self, i, to_negative=True):
1597
+ """
1598
+ Return the projection along the `i`-th simple root, and across the
1599
+ hyperplane define by the `i`-th simple coroot, as a function from
1600
+ ``self`` to ``self``.
1601
+
1602
+ INPUT:
1603
+
1604
+ - ``i`` -- an element of the index set of ``self``
1605
+
1606
+ EXAMPLES::
1607
+
1608
+ sage: # needs sage.graphs
1609
+ sage: space = RootSystem(['A',2]).weight_lattice()
1610
+ sage: x = space.simple_roots()[1]
1611
+ sage: pi = space.simple_projection(1)
1612
+ sage: x
1613
+ 2*Lambda[1] - Lambda[2]
1614
+ sage: pi(x)
1615
+ -2*Lambda[1] + Lambda[2]
1616
+ sage: pi(-x)
1617
+ -2*Lambda[1] + Lambda[2]
1618
+ sage: pi = space.simple_projection(1,False)
1619
+ sage: pi(-x)
1620
+ 2*Lambda[1] - Lambda[2]
1621
+ """
1622
+ return self.projection(self.simple_root(i), self.simple_coroot(i), to_negative)
1623
+
1624
+ @cached_method
1625
+ def simple_projections(self, to_negative=True):
1626
+ r"""
1627
+ Return the family `(s_i)_{i\in I}` of the simple projections
1628
+ of this root system.
1629
+
1630
+ EXAMPLES::
1631
+
1632
+ sage: space = RootSystem(['A',2]).weight_lattice()
1633
+ sage: pi = space.simple_projections() # needs sage.graphs
1634
+ sage: x = space.simple_roots() # needs sage.graphs
1635
+ sage: pi[1](x[2]) # needs sage.graphs
1636
+ -Lambda[1] + 2*Lambda[2]
1637
+
1638
+ TESTS::
1639
+
1640
+ sage: pi # needs sage.graphs
1641
+ pi
1642
+ """
1643
+ if to_negative is not True:
1644
+ raise NotImplementedError("only implemented when 'to_negative' is True")
1645
+ res = self.alpha().zip(self.projection, self.alphacheck())
1646
+ # Should this use rename to set a nice name for this family?
1647
+ res.rename('pi')
1648
+ return res
1649
+
1650
+ ##########################################################################
1651
+ # Weyl group
1652
+ ##########################################################################
1653
+
1654
+ def weyl_group(self, prefix=None):
1655
+ """
1656
+ Return the Weyl group associated to ``self``.
1657
+
1658
+ EXAMPLES::
1659
+
1660
+ sage: RootSystem(['F',4]).ambient_space().weyl_group() # needs sage.libs.gap
1661
+ Weyl Group of type ['F', 4] (as a matrix group acting on the ambient space)
1662
+ sage: RootSystem(['F',4]).root_space().weyl_group() # needs sage.graphs sage.libs.gap
1663
+ Weyl Group of type ['F', 4] (as a matrix group acting on the root space)
1664
+ """
1665
+ from sage.combinat.root_system.weyl_group import WeylGroup
1666
+ return WeylGroup(self, prefix=prefix)
1667
+
1668
+ ##########################################################################
1669
+ # The piecewise linear involutive operators tau_plus and tau_minus on self,
1670
+ # and the orbit decomposition of the almost positive roots
1671
+ # by the associated dihedral group
1672
+ ##########################################################################
1673
+
1674
+ # TODO: find a better name; at least, this temporary one won't
1675
+ # create conflicts
1676
+ def tau_epsilon_operator_on_almost_positive_roots(self, J):
1677
+ r"""
1678
+ The `\tau_\epsilon` operator on almost positive roots.
1679
+
1680
+ Given a subset `J` of non adjacent vertices of the Dynkin
1681
+ diagram, this constructs the operator on the almost positive
1682
+ roots which fixes the negative simple roots `\alpha_i` for `i`
1683
+ not in `J`, and acts otherwise by:
1684
+
1685
+ .. MATH::
1686
+
1687
+ \tau_+( \beta ) = (\prod_{i \in J} s_i) (\beta)
1688
+
1689
+ See Equation (1.2) of [CFZ2002]_.
1690
+
1691
+ EXAMPLES::
1692
+
1693
+ sage: L = RootSystem(['A',4]).root_lattice()
1694
+ sage: tau = L.tau_epsilon_operator_on_almost_positive_roots([1,3]) # needs sage.graphs sage.libs.gap
1695
+ sage: alpha = L.simple_roots() # needs sage.graphs
1696
+
1697
+ The action on a negative simple root not in `J`::
1698
+
1699
+ sage: tau(-alpha[2]) # needs sage.graphs sage.libs.gap
1700
+ -alpha[2]
1701
+
1702
+ The action on a negative simple root in `J`::
1703
+
1704
+ sage: tau(-alpha[1]) # needs sage.graphs sage.libs.gap
1705
+ alpha[1]
1706
+
1707
+ The action on all almost positive roots::
1708
+
1709
+ sage: for root in L.almost_positive_roots(): # needs sage.graphs sage.libs.gap
1710
+ ....: print('tau({:<41}) = {}'.format(str(root), tau(root)))
1711
+ tau(-alpha[1] ) = alpha[1]
1712
+ tau(alpha[1] ) = -alpha[1]
1713
+ tau(alpha[1] + alpha[2] ) = alpha[2] + alpha[3]
1714
+ tau(alpha[1] + alpha[2] + alpha[3] ) = alpha[2]
1715
+ tau(alpha[1] + alpha[2] + alpha[3] + alpha[4]) = alpha[2] + alpha[3] + alpha[4]
1716
+ tau(-alpha[2] ) = -alpha[2]
1717
+ tau(alpha[2] ) = alpha[1] + alpha[2] + alpha[3]
1718
+ tau(alpha[2] + alpha[3] ) = alpha[1] + alpha[2]
1719
+ tau(alpha[2] + alpha[3] + alpha[4] ) = alpha[1] + alpha[2] + alpha[3] + alpha[4]
1720
+ tau(-alpha[3] ) = alpha[3]
1721
+ tau(alpha[3] ) = -alpha[3]
1722
+ tau(alpha[3] + alpha[4] ) = alpha[4]
1723
+ tau(-alpha[4] ) = -alpha[4]
1724
+ tau(alpha[4] ) = alpha[3] + alpha[4]
1725
+
1726
+ This method works on any root lattice realization::
1727
+
1728
+ sage: L = RootSystem(['B',3]).ambient_space()
1729
+ sage: tau = L.tau_epsilon_operator_on_almost_positive_roots([1,3]) # needs sage.libs.gap
1730
+ sage: for root in L.almost_positive_roots(): # needs sage.graphs sage.libs.gap
1731
+ ....: print('tau({:<41}) = {}'.format(str(root), tau(root)))
1732
+ tau((-1, 1, 0) ) = (1, -1, 0)
1733
+ tau((1, 0, 0) ) = (0, 1, 0)
1734
+ tau((1, -1, 0) ) = (-1, 1, 0)
1735
+ tau((1, 1, 0) ) = (1, 1, 0)
1736
+ tau((1, 0, -1) ) = (0, 1, 1)
1737
+ tau((1, 0, 1) ) = (0, 1, -1)
1738
+ tau((0, -1, 1) ) = (0, -1, 1)
1739
+ tau((0, 1, 0) ) = (1, 0, 0)
1740
+ tau((0, 1, -1) ) = (1, 0, 1)
1741
+ tau((0, 1, 1) ) = (1, 0, -1)
1742
+ tau((0, 0, -1) ) = (0, 0, 1)
1743
+ tau((0, 0, 1) ) = (0, 0, -1)
1744
+
1745
+ .. SEEALSO:: :meth:`tau_plus_minus`
1746
+ """
1747
+ W = self.weyl_group()
1748
+ t = W.from_reduced_word(J)
1749
+ simple_roots = self.simple_roots()
1750
+ other_negative_simple_roots = set(-simple_roots[i] for i in self.index_set() if i not in J)
1751
+
1752
+ def tau_epsilon(alpha):
1753
+ if alpha in other_negative_simple_roots:
1754
+ return alpha
1755
+ else:
1756
+ return t.action(alpha)
1757
+ return tau_epsilon
1758
+
1759
+ def tau_plus_minus(self):
1760
+ r"""
1761
+ Return the `\tau^+` and `\tau^-` piecewise linear operators on ``self``.
1762
+
1763
+ Those operators are induced by the bipartition `\{L,R\}` of
1764
+ the simple roots of ``self``, and stabilize the almost
1765
+ positive roots. Namely, `\tau_+` fixes the negative simple
1766
+ roots `\alpha_i` for `i` in `R`, and acts otherwise by:
1767
+
1768
+ .. MATH::
1769
+
1770
+ \tau_+( \beta ) = (\prod_{i \in L} s_i) (\beta)
1771
+
1772
+ `\tau_-` acts analogously, with `L` and `R` interchanged.
1773
+
1774
+ Those operators are used to construct the associahedron, a
1775
+ polytopal realization of the cluster complex (see
1776
+ :class:`Associahedron`).
1777
+
1778
+ .. SEEALSO:: :meth:`tau_epsilon_operator_on_almost_positive_roots`
1779
+
1780
+ EXAMPLES:
1781
+
1782
+ We explore the example of [CFZ2002]_ Eq.(1.3)::
1783
+
1784
+ sage: S = RootSystem(['A',2]).root_lattice()
1785
+ sage: taup, taum = S.tau_plus_minus() # needs sage.graphs sage.libs.gap
1786
+ sage: for beta in S.almost_positive_roots(): # needs sage.graphs sage.libs.gap
1787
+ ....: print("{} , {} , {}".format(beta, taup(beta), taum(beta)))
1788
+ -alpha[1] , alpha[1] , -alpha[1]
1789
+ alpha[1] , -alpha[1] , alpha[1] + alpha[2]
1790
+ alpha[1] + alpha[2] , alpha[2] , alpha[1]
1791
+ -alpha[2] , -alpha[2] , alpha[2]
1792
+ alpha[2] , alpha[1] + alpha[2] , -alpha[2]
1793
+ """
1794
+ ct = self.cartan_type()
1795
+ L,R = ct.index_set_bipartition()
1796
+ return self.tau_epsilon_operator_on_almost_positive_roots(L), self.tau_epsilon_operator_on_almost_positive_roots(R)
1797
+
1798
+ def almost_positive_roots_decomposition(self):
1799
+ r"""
1800
+ Return the decomposition of the almost positive roots of ``self``.
1801
+
1802
+ This is the list of the orbits of the almost positive roots
1803
+ under the action of the dihedral group generated by the
1804
+ operators `\tau_+` and `\tau_-`.
1805
+
1806
+ .. SEEALSO::
1807
+
1808
+ - :meth:`almost_positive_roots`
1809
+ - :meth:`tau_plus_minus`
1810
+
1811
+ EXAMPLES::
1812
+
1813
+ sage: RootSystem(['A',2]).root_lattice().almost_positive_roots_decomposition() # needs sage.graphs sage.libs.gap
1814
+ [[-alpha[1], alpha[1], alpha[1] + alpha[2], alpha[2], -alpha[2]]]
1815
+
1816
+ sage: RootSystem(['B',2]).root_lattice().almost_positive_roots_decomposition() # needs sage.graphs sage.libs.gap
1817
+ [[-alpha[1], alpha[1], alpha[1] + 2*alpha[2]],
1818
+ [-alpha[2], alpha[2], alpha[1] + alpha[2]]]
1819
+
1820
+ sage: RootSystem(['D',4]).root_lattice().almost_positive_roots_decomposition() # needs sage.graphs sage.libs.gap
1821
+ [[-alpha[1], alpha[1], alpha[1] + alpha[2], alpha[2] + alpha[3] + alpha[4]],
1822
+ [-alpha[2], alpha[2], alpha[1] + alpha[2] + alpha[3] + alpha[4],
1823
+ alpha[1] + 2*alpha[2] + alpha[3] + alpha[4]],
1824
+ [-alpha[3], alpha[3], alpha[2] + alpha[3], alpha[1] + alpha[2] + alpha[4]],
1825
+ [-alpha[4], alpha[4], alpha[2] + alpha[4], alpha[1] + alpha[2] + alpha[3]]]
1826
+ """
1827
+ # TODO: this should use a generic function for computing
1828
+ # orbits under the action of a group:
1829
+ # def orbits(seeds, operators)
1830
+ # INPUT:
1831
+
1832
+ # - seeds: a list of elements
1833
+ # - operators: a list of functions
1834
+ #
1835
+ # Returns the orbits generated by seeds under the action of the operators
1836
+ tau_plus, tau_minus = self.tau_plus_minus()
1837
+
1838
+ I = set(self.index_set())
1839
+ Delta = self.simple_roots()
1840
+ L, R = self.cartan_type().index_set_bipartition()
1841
+
1842
+ orbits = []
1843
+ while I:
1844
+ i = I.pop()
1845
+ alpha = -self.simple_root(i)
1846
+ orbit = [alpha]
1847
+ if i in L:
1848
+ plus = False
1849
+ beta = tau_plus(alpha)
1850
+ else:
1851
+ plus = True
1852
+ beta = tau_minus(alpha)
1853
+ while -beta not in Delta and beta not in orbit:
1854
+ orbit.append(beta)
1855
+ if beta in Delta:
1856
+ j = beta.leading_support()
1857
+ I.discard(j)
1858
+ if plus:
1859
+ beta = tau_plus(beta)
1860
+ else:
1861
+ beta = tau_minus(beta)
1862
+ plus = not plus
1863
+ if -beta in Delta:
1864
+ orbit.append(beta)
1865
+ orbits.append(orbit)
1866
+ return orbits
1867
+
1868
+ ##########################################################################
1869
+ # Methods for affine root lattice realizations
1870
+ # Should eventually go in an Affine nested class
1871
+ ##########################################################################
1872
+
1873
+ @cached_method
1874
+ def classical(self):
1875
+ """
1876
+ Return the corresponding root/weight/ambient lattice/space.
1877
+
1878
+ EXAMPLES::
1879
+
1880
+ sage: RootSystem(["A",4,1]).root_lattice().classical()
1881
+ Root lattice of the Root system of type ['A', 4]
1882
+ sage: RootSystem(["A",4,1]).weight_lattice().classical()
1883
+ Weight lattice of the Root system of type ['A', 4]
1884
+ sage: RootSystem(["A",4,1]).ambient_space().classical()
1885
+ Ambient space of the Root system of type ['A', 4]
1886
+ """
1887
+ from .root_space import RootSpace
1888
+ from .weight_space import WeightSpace
1889
+ R = self.cartan_type().classical().root_system()
1890
+ if isinstance(self, RootSpace):
1891
+ return R.root_space(self.base_ring())
1892
+ elif isinstance(self, WeightSpace):
1893
+ return R.weight_space(self.base_ring())
1894
+ else:
1895
+ return R.ambient_space(self.base_ring())
1896
+
1897
+ @lazy_attribute
1898
+ def _to_classical(self):
1899
+ r"""
1900
+ The projection onto the classical ambient space.
1901
+
1902
+ EXAMPLES::
1903
+
1904
+ sage: L = RootSystem(["A",2,1]).ambient_space()
1905
+ sage: e = L.basis()
1906
+ sage: L._to_classical(e["delta"])
1907
+ (0, 0, 0)
1908
+ sage: L._to_classical(e["deltacheck"])
1909
+ (0, 0, 0)
1910
+ sage: L._to_classical(e[0])
1911
+ (1, 0, 0)
1912
+ sage: L._to_classical(e[1])
1913
+ (0, 1, 0)
1914
+ sage: L._to_classical(e[2])
1915
+ (0, 0, 1)
1916
+ """
1917
+ return self.module_morphism(self._to_classical_on_basis, codomain=self.classical())
1918
+
1919
+ def _classical_alpha_0(self):
1920
+ """
1921
+ Return the projection of `\alpha_0` in the classical space.
1922
+
1923
+ This is used e.g. to construct the projections onto the
1924
+ classical space.
1925
+
1926
+ EXAMPLES:
1927
+
1928
+ This is the opposite of the highest root in the untwisted case::
1929
+
1930
+ sage: L = RootSystem(["B",3,1]).root_space()
1931
+ sage: L._classical_alpha_0() # needs sage.graphs
1932
+ -alpha[1] - 2*alpha[2] - 2*alpha[3]
1933
+ sage: L._to_classical_on_basis(0) # needs sage.graphs
1934
+ -alpha[1] - 2*alpha[2] - 2*alpha[3]
1935
+ sage: L.classical().highest_root() # needs sage.graphs
1936
+ alpha[1] + 2*alpha[2] + 2*alpha[3]
1937
+
1938
+ But not in the other cases::
1939
+
1940
+ sage: L = RootSystem(CartanType(["B",3,1]).dual()).root_space()
1941
+ sage: L._to_classical_on_basis(0) # needs sage.graphs
1942
+ -alpha[1] - 2*alpha[2] - alpha[3]
1943
+ sage: L.classical().highest_root() # needs sage.graphs
1944
+ 2*alpha[1] + 2*alpha[2] + alpha[3]
1945
+ """
1946
+ cartan_type = self.cartan_type()
1947
+ special_node = cartan_type.special_node()
1948
+ a = self.cartan_type().col_annihilator()
1949
+ classical = self.classical()
1950
+ return -classical.sum(a[i] * self.simple_root(i)
1951
+ for i in self.index_set() if i != special_node) \
1952
+ / a[special_node]
1953
+
1954
+ ######################################################################
1955
+ # Root system plots
1956
+
1957
+ def plot(self,
1958
+ roots='simple',
1959
+ coroots=False,
1960
+ reflection_hyperplanes='simple',
1961
+ fundamental_weights=None,
1962
+ fundamental_chamber=None,
1963
+ alcoves=None,
1964
+ alcove_labels=False,
1965
+ alcove_walk=None,
1966
+ **options):
1967
+ r"""
1968
+ Return a picture of this root lattice realization.
1969
+
1970
+ INPUT:
1971
+
1972
+ - ``roots`` -- which roots to display, if any
1973
+ Can be one of the following:
1974
+
1975
+ * ``'simple'`` -- the simple roots (the default)
1976
+ * ``'classical'`` -- not yet implemented
1977
+ * ``'all'`` -- only works in the finite case
1978
+ * A list or tuple of roots
1979
+ * ``False``
1980
+
1981
+ - ``coroots`` -- which coroots to display, if any
1982
+ Can be one of the following:
1983
+
1984
+ * ``'simple'`` -- the simple coroots (the default)
1985
+ * ``'classical'`` -- not yet implemented
1986
+ * ``'all'`` -- only works in the finite case
1987
+ * A list or tuple of coroots
1988
+ * ``False``
1989
+
1990
+ - ``fundamental_weights`` -- boolean or ``None`` (default: ``None``)
1991
+ whether to display the fundamental weights.
1992
+ If ``None``, the fundamental weights are drawn if available.
1993
+
1994
+ - ``reflection_hyperplanes`` -- which reflection
1995
+ hyperplanes to display, if any. Can be one of the
1996
+ following:
1997
+
1998
+ * ``'simple'`` -- the simple roots
1999
+ * ``'classical'`` -- not yet implemented
2000
+ * ``'all'`` -- only works in the finite case
2001
+ * A list or tuple of roots
2002
+ * ``False`` (the default)
2003
+
2004
+ - ``fundamental_chamber`` -- whether and how to draw the
2005
+ fundamental chamber. Can be one of the following:
2006
+
2007
+ * A boolean -- Set to ``True`` to draw the fundamental
2008
+ chamber
2009
+ * ``'classical'`` -- draw the classical fundamental chamber
2010
+ * ``None`` -- (the default) The fundamental chamber is
2011
+ drawn except in the root lattice where this is not yet
2012
+ implemented. For affine types the classical
2013
+ fundamental chamber is drawn instead.
2014
+
2015
+ - ``alcoves`` -- one of the following (default: ``True``):
2016
+
2017
+ * A boolean -- whether to display the alcoves
2018
+ * A list of alcoves -- The alcoves to be drawn. Each alcove is
2019
+ specified by the coordinates of its center in the root lattice
2020
+ (affine type only). Otherwise the alcoves that intersect the
2021
+ bounding box are drawn.
2022
+
2023
+ - ``alcove_labels`` -- one of the following (default: ``False``):
2024
+
2025
+ * A boolean -- whether to display the elements of the Weyl group
2026
+ indexing the alcoves. This currently requires to also
2027
+ set the ``alcoves`` option.
2028
+ * A number `l` -- the label is drawn at level `l` (affine type
2029
+ only), which only makes sense if ``affine`` is ``False``.
2030
+
2031
+ - ``bounding_box`` -- a rational number or a list of pairs
2032
+ thereof (default: 3)
2033
+
2034
+ Specifies a bounding box, in the coordinate system for
2035
+ this plot, in which to plot alcoves and other infinite
2036
+ objects. If the bounding box is a number `a`, then the
2037
+ bounding box is of the form `[-a,a]` in all directions.
2038
+ Beware that there can be some border effects and the
2039
+ returned graphic is not necessarily strictly contained
2040
+ in the bounding box.
2041
+
2042
+ - ``alcove_walk`` -- an alcove walk or ``None`` (default: ``None``)
2043
+
2044
+ The alcove walk is described by a list (or iterable) of
2045
+ vertices of the Dynkin diagram which specifies which
2046
+ wall is crossed at each step, starting from the
2047
+ fundamental alcove.
2048
+
2049
+ - ``projection`` -- one of the following (default: ``True``):
2050
+
2051
+ * ``True`` -- the default projection for the root
2052
+ lattice realization is used.
2053
+ * ``False`` -- no projection is used.
2054
+ * ``barycentric`` -- a barycentric projection is used.
2055
+ * A function -- If a function is specified, it should implement a
2056
+ linear (or affine) map taking as input an element of
2057
+ this root lattice realization and returning its
2058
+ desired coordinates in the plot, as a vector with
2059
+ rational coordinates.
2060
+
2061
+ - ``color`` -- a function mapping vertices of the Dynkin
2062
+ diagram to colors (default: ``'black'`` for 0,
2063
+ ``'blue'`` for 1, ``'red'`` for 2, ``'green'`` for 3)
2064
+
2065
+ This is used to set the color for the simple roots,
2066
+ fundamental weights, reflection hyperplanes, alcove
2067
+ facets, etc. If the color is ``None``, the object is not
2068
+ drawn.
2069
+
2070
+ - ``labels`` -- boolean (default: ``True``)
2071
+ whether to display labels on the simple roots,
2072
+ fundamental weights, etc.
2073
+
2074
+ EXAMPLES::
2075
+
2076
+ sage: L = RootSystem(["A",2,1]).ambient_space().plot() # long time, needs sage.plot sage.symbolic
2077
+
2078
+ .. SEEALSO::
2079
+
2080
+ - :meth:`plot_parse_options`
2081
+ - :meth:`plot_roots`, :meth:`plot_coroots`
2082
+ - :meth:`plot_fundamental_weights`
2083
+ - :meth:`plot_fundamental_chamber`
2084
+ - :meth:`plot_reflection_hyperplanes`
2085
+ - :meth:`plot_alcoves`
2086
+ - :meth:`plot_alcove_walk`
2087
+ - :meth:`plot_ls_paths`
2088
+ - :meth:`plot_mv_polytope`
2089
+ - :meth:`plot_crystal`
2090
+ """
2091
+ plot_options = self.plot_parse_options(**options)
2092
+ G = plot_options.empty()
2093
+
2094
+ if roots:
2095
+ G += self.plot_roots(roots, plot_options=plot_options)
2096
+
2097
+ # if coroots is None:
2098
+ # coroot_lattice = self.root_system.coroot_lattice()
2099
+ # if self.has_coerce_map_from(coroot_lattice):
2100
+ # coroots="simple"
2101
+ # else:
2102
+ # coroots=False
2103
+ if coroots:
2104
+ G += self.plot_coroots(coroots, plot_options=plot_options)
2105
+
2106
+ if fundamental_weights is None:
2107
+ fundamental_weights = hasattr(self, "fundamental_weights")
2108
+ if fundamental_weights:
2109
+ G += self.plot_fundamental_weights(plot_options=plot_options)
2110
+
2111
+ if reflection_hyperplanes:
2112
+ G += self.plot_reflection_hyperplanes(reflection_hyperplanes, plot_options=plot_options)
2113
+
2114
+ if alcoves is None:
2115
+ alcoves = self.cartan_type().is_affine() and hasattr(self, "fundamental_weights")
2116
+ if alcoves:
2117
+ G += self.plot_alcoves(alcoves, alcove_labels=alcove_labels, plot_options=plot_options)
2118
+
2119
+ if fundamental_chamber is None:
2120
+ if not hasattr(self, "fundamental_weights"):
2121
+ fundamental_chamber = False
2122
+ elif self.cartan_type().is_affine():
2123
+ fundamental_chamber = "classical"
2124
+ else:
2125
+ fundamental_chamber = True
2126
+ if fundamental_chamber:
2127
+ G += self.plot_fundamental_chamber(fundamental_chamber, plot_options=plot_options)
2128
+
2129
+ if alcove_walk is not None:
2130
+ G += self.plot_alcove_walk(alcove_walk, plot_options=plot_options)
2131
+
2132
+ return plot_options.finalize(G)
2133
+
2134
+ def plot_parse_options(self, **args):
2135
+ r"""
2136
+ Return an option object to be used for root system plotting.
2137
+
2138
+ EXAMPLES::
2139
+
2140
+ sage: L = RootSystem(["A",2,1]).ambient_space()
2141
+ sage: options = L.plot_parse_options(); options # needs sage.geometry.polyhedron sage.symbolic
2142
+ <sage.combinat.root_system.plot.PlotOptions object at ...>
2143
+
2144
+ .. SEEALSO::
2145
+
2146
+ - :meth:`plot` for a description of the plotting options
2147
+ - :ref:`sage.combinat.root_system.plot` for a tutorial
2148
+ on root system plotting
2149
+ """
2150
+ if len(args) == 1 and "plot_options" in args:
2151
+ return args["plot_options"]
2152
+ else:
2153
+ return PlotOptions(self, **args)
2154
+
2155
+ def _plot_projection(self, x):
2156
+ r"""
2157
+ Implement the default projection to be used for plots.
2158
+
2159
+ EXAMPLES:
2160
+
2161
+ By default, this is just the identity::
2162
+
2163
+ sage: L = RootSystem(["B",3]).root_lattice()
2164
+ sage: l = L.an_element(); l
2165
+ 2*alpha[1] + 2*alpha[2] + 3*alpha[3]
2166
+ sage: L._plot_projection(l) # needs sage.symbolic
2167
+ 2*alpha[1] + 2*alpha[2] + 3*alpha[3]
2168
+
2169
+ In the ambient space of type `A_2`, this is the
2170
+ barycentric projection. In the ambient space of affine
2171
+ type this goes through the classical ambient space.
2172
+
2173
+ .. SEEALSO::
2174
+
2175
+ - :meth:`sage.combinat.root_system.type_A.AmbientSpace._plot_projection`
2176
+ - :meth:`sage.combinat.root_system.type_affine.AmbientSpace._plot_projection`
2177
+ - :meth:`plot` for a description of the plotting options
2178
+ - :ref:`sage.combinat.root_system.plot` for a tutorial
2179
+ on root system plotting
2180
+ """
2181
+ return x
2182
+
2183
+ @cached_method
2184
+ def _plot_projection_barycentric_matrix(self):
2185
+ """
2186
+ A rational approximation of the matrix for the barycentric
2187
+ projection.
2188
+
2189
+ OUTPUT: a matrix with rational coefficients whose column sum is zero
2190
+
2191
+ .. SEEALSO::
2192
+
2193
+ - :func:`sage.combinat.root_system.plot.barycentric_projection_matrix`
2194
+ - :meth:`_plot_projection_barycentric`
2195
+
2196
+ EXAMPLES::
2197
+
2198
+ sage: # needs sage.symbolic
2199
+ sage: RootSystem(["A",0]).ambient_space()._plot_projection_barycentric_matrix()
2200
+ []
2201
+ sage: m = RootSystem(["A",1]).ambient_space()._plot_projection_barycentric_matrix(); m
2202
+ [ 1 -1]
2203
+ sage: sum(m.columns())
2204
+ (0)
2205
+ sage: m = RootSystem(["A",2]).ambient_space()._plot_projection_barycentric_matrix(); m
2206
+ [ 1/2 -1 1/2]
2207
+ [ 989/1142 0 -989/1142]
2208
+ sage: sum(m.columns())
2209
+ (0, 0)
2210
+ sage: m = RootSystem(["A",3]).ambient_space()._plot_projection_barycentric_matrix(); m
2211
+ [ 1277/1564 -1277/1564 0 0]
2212
+ [1009460/2141389 849/1801 -1121/1189 0]
2213
+ [ 1/3 1/3 1/3 -1]
2214
+ sage: sum(m.columns())
2215
+ (0, 0, 0)
2216
+ """
2217
+ from sage.symbolic.constants import pi
2218
+ m = matrix(QQ, barycentric_projection_matrix(self.dimension()-1, angle=2*pi/3).n(20))
2219
+ # We want to guarantee that the sum of the columns of the
2220
+ # result is zero. This is close to be the case for the
2221
+ # original matrix and for the current rational
2222
+ # approximation. We tidy up the work by replacing the
2223
+ # first column by the opposite of the sum of the others.
2224
+ if self.dimension() > 1: # not needed in the trivial cases
2225
+ m.set_column(0, -sum(m[:,1:].columns()))
2226
+ m.set_immutable()
2227
+ return m
2228
+
2229
+ def _plot_projection_barycentric(self, x):
2230
+ r"""
2231
+ Implement the barycentric projection to be used for plots.
2232
+
2233
+ It is in fact a rational approximation thereof, but the
2234
+ sum of the basis vectors is guaranteed to be mapped to
2235
+ zero.
2236
+
2237
+ EXAMPLES::
2238
+
2239
+ sage: L = RootSystem(["A",2]).ambient_space()
2240
+ sage: e = L.basis()
2241
+ sage: L._plot_projection_barycentric(e[0]) # needs sage.symbolic
2242
+ (1/2, 989/1142)
2243
+ sage: L._plot_projection_barycentric(e[1]) # needs sage.symbolic
2244
+ (-1, 0)
2245
+ sage: L._plot_projection_barycentric(e[2]) # needs sage.symbolic
2246
+ (1/2, -989/1142)
2247
+
2248
+ .. SEEALSO::
2249
+
2250
+ - :meth:`_plot_projection`, :meth:`plot`
2251
+ - :ref:`sage.combinat.root_system.plot` for a tutorial
2252
+ on root system plotting
2253
+ """
2254
+ return self._plot_projection_barycentric_matrix()*vector(x)
2255
+
2256
+ def plot_roots(self, collection='simple', **options):
2257
+ r"""
2258
+ Plot the (simple/classical) roots of this root lattice.
2259
+
2260
+ INPUT:
2261
+
2262
+ - ``collection`` -- which roots to display
2263
+ can be one of the following:
2264
+
2265
+ * ``'simple'`` (the default)
2266
+ * ``'classical'``
2267
+ * ``'all'``
2268
+
2269
+ - ``**options`` -- plotting options
2270
+
2271
+ .. SEEALSO::
2272
+
2273
+ - :meth:`plot` for a description of the plotting options
2274
+ - :ref:`sage.combinat.root_system.plot` for a tutorial
2275
+ on root system plotting
2276
+
2277
+ EXAMPLES::
2278
+
2279
+ sage: RootSystem(["B",3]).ambient_space().plot_roots() # needs sage.geometry.polyhedron sage.plot
2280
+ Graphics3d Object
2281
+ sage: RootSystem(["B",3]).ambient_space().plot_roots("all") # needs sage.geometry.polyhedron sage.plot
2282
+ Graphics3d Object
2283
+
2284
+ TESTS::
2285
+
2286
+ sage: list(RootSystem(["A",2]).root_lattice().plot_roots()) # needs sage.plot sage.symbolic
2287
+ [Arrow from (0.0,0.0) to (1.0,0.0),
2288
+ Text '$\alpha_{1}$' at the point (1.05,0.0),
2289
+ Arrow from (0.0,0.0) to (0.0,1.0),
2290
+ Text '$\alpha_{2}$' at the point (0.0,1.05)]
2291
+
2292
+ sage: list(RootSystem(["A",2]).weight_lattice().plot_roots(labels=False)) # needs sage.plot sage.symbolic
2293
+ [Arrow from (0.0,0.0) to (2.0,-1.0),
2294
+ Arrow from (0.0,0.0) to (-1.0,2.0)]
2295
+
2296
+ sage: list(RootSystem(["A",2]).ambient_lattice().plot_roots()) # needs sage.plot sage.symbolic
2297
+ [Arrow from (0.0,0.0) to (1.5,0.86...),
2298
+ Text '$\alpha_{1}$' at the point (1.575...,0.90...),
2299
+ Arrow from (0.0,0.0) to (-1.5,0.86...),
2300
+ Text '$\alpha_{2}$' at the point (-1.575...,0.90...)]
2301
+
2302
+ sage: list(RootSystem(["B",2]).ambient_space().plot_roots()) # needs sage.plot sage.symbolic
2303
+ [Arrow from (0.0,0.0) to (1.0,-1.0),
2304
+ Text '$\alpha_{1}$' at the point (1.05,-1.05),
2305
+ Arrow from (0.0,0.0) to (0.0,1.0),
2306
+ Text '$\alpha_{2}$' at the point (0.0,1.05)]
2307
+
2308
+ sage: list(RootSystem(["A",2]).root_lattice().plot_roots("all")) # needs sage.plot sage.symbolic
2309
+ [Arrow from (0.0,0.0) to (1.0,0.0),
2310
+ Text '$\alpha_{1}$' at the point (1.05,0.0),
2311
+ Arrow from (0.0,0.0) to (0.0,1.0),
2312
+ Text '$\alpha_{2}$' at the point (0.0,1.05),
2313
+ Arrow from (0.0,0.0) to (1.0,1.0),
2314
+ Text '$\alpha_{1} + \alpha_{2}$' at the point (1.05,1.05),
2315
+ Arrow from (0.0,0.0) to (-1.0,0.0),
2316
+ Text '$-\alpha_{1}$' at the point (-1.05,0.0),
2317
+ Arrow from (0.0,0.0) to (0.0,-1.0),
2318
+ Text '$-\alpha_{2}$' at the point (0.0,-1.05),
2319
+ Arrow from (0.0,0.0) to (-1.0,-1.0),
2320
+ Text '$-\alpha_{1} - \alpha_{2}$' at the point (-1.05,-1.05)]
2321
+ """
2322
+ plot_options = self.plot_parse_options(**options)
2323
+ root_lattice = self.root_system.root_lattice()
2324
+ if collection == "simple":
2325
+ roots = root_lattice.simple_roots()
2326
+ elif collection == "classical":
2327
+ if not self.cartan_type().is_affine():
2328
+ raise ValueError("plotting classical roots only available in affine type")
2329
+ raise NotImplementedError("classical roots")
2330
+ elif collection == "all":
2331
+ if not self.cartan_type().is_finite():
2332
+ raise ValueError("plotting all roots only available in finite type")
2333
+ roots = root_lattice.roots()
2334
+ elif isinstance(collection, (list, tuple)):
2335
+ roots = collection
2336
+ else:
2337
+ raise ValueError("Unknown value: %s" % collection)
2338
+ roots = Family(roots, self)
2339
+ return plot_options.family_of_vectors(roots)
2340
+
2341
+ def plot_coroots(self, collection='simple', **options):
2342
+ r"""
2343
+ Plot the (simple/classical) coroots of this root lattice.
2344
+
2345
+ INPUT:
2346
+
2347
+ - ``collection`` -- which coroots to display
2348
+ Can be one of the following:
2349
+
2350
+ * ``'simple'`` (the default)
2351
+ * ``'classical'``
2352
+ * ``'all'``
2353
+
2354
+ - ``**options`` -- plotting options
2355
+
2356
+ .. SEEALSO::
2357
+
2358
+ - :meth:`plot` for a description of the plotting options
2359
+ - :ref:`sage.combinat.root_system.plot` for a tutorial
2360
+ on root system plotting
2361
+
2362
+ EXAMPLES::
2363
+
2364
+ sage: RootSystem(["B",3]).ambient_space().plot_coroots() # needs sage.plot sage.symbolic
2365
+ Graphics3d Object
2366
+
2367
+ TESTS::
2368
+
2369
+ sage: list(RootSystem(["B",2]).ambient_space().plot_coroots()) # needs sage.plot sage.symbolic
2370
+ [Arrow from (0.0,0.0) to (1.0,-1.0),
2371
+ Text '$\alpha^\vee_{1}$' at the point (1.05,-1.05),
2372
+ Arrow from (0.0,0.0) to (0.0,2.0),
2373
+ Text '$\alpha^\vee_{2}$' at the point (0.0,2.1)]
2374
+ """
2375
+ # Functionally speaking, this is duplicated from plot_roots ...
2376
+ # Can we avoid that, say by going to the dual space?
2377
+ plot_options = self.plot_parse_options(**options)
2378
+ coroot_lattice = self.root_system.coroot_lattice()
2379
+ if not self.has_coerce_map_from(coroot_lattice):
2380
+ raise ValueError("Can't plot the coroots: there is no embedding of the coroot lattice to this space")
2381
+ if collection == "simple":
2382
+ coroots = coroot_lattice.simple_roots()
2383
+ elif collection == "classical":
2384
+ if not self.cartan_type().is_affine():
2385
+ raise ValueError("plotting classical coroots only available in affine type")
2386
+ raise NotImplementedError("classical coroots")
2387
+ elif collection == "all":
2388
+ if not self.cartan_type().is_finite():
2389
+ raise ValueError("plotting all coroots only available in finite type")
2390
+ coroots = coroot_lattice.roots()
2391
+ elif isinstance(collection, (list, tuple)):
2392
+ coroots = collection
2393
+ else:
2394
+ raise ValueError("Unknown value: %s" % collection)
2395
+ coroots = Family(coroots, self)
2396
+ return plot_options.family_of_vectors(coroots)
2397
+
2398
+ def plot_fundamental_weights(self, **options):
2399
+ r"""
2400
+ Plot the fundamental weights of this root lattice.
2401
+
2402
+ INPUT:
2403
+
2404
+ - ``**options`` -- plotting options
2405
+
2406
+ .. SEEALSO::
2407
+
2408
+ - :meth:`plot` for a description of the plotting options
2409
+ - :ref:`sage.combinat.root_system.plot` for a tutorial
2410
+ on root system plotting
2411
+
2412
+ EXAMPLES::
2413
+
2414
+ sage: RootSystem(["B",3]).ambient_space().plot_fundamental_weights() # needs sage.geometry.polyhedron sage.plot
2415
+ Graphics3d Object
2416
+
2417
+ TESTS::
2418
+
2419
+ sage: sorted(RootSystem(["A",2]).weight_lattice().plot_fundamental_weights(), key=str) # needs sage.plot sage.symbolic
2420
+ [Arrow from (0.0,0.0) to (0.0,1.0),
2421
+ Arrow from (0.0,0.0) to (1.0,0.0),
2422
+ Text '$\Lambda_{1}$' at the point (1.05,0.0),
2423
+ Text '$\Lambda_{2}$' at the point (0.0,1.05)]
2424
+
2425
+ sage: sorted(RootSystem(["A",2]).ambient_lattice().plot_fundamental_weights(), key=str) # needs sage.plot sage.symbolic
2426
+ [Arrow from (0.0,0.0) to (-0.5,0.86602451838...),
2427
+ Arrow from (0.0,0.0) to (0.5,0.86602451838...),
2428
+ Text '$\Lambda_{1}$' at the point (0.525,0.909325744308...),
2429
+ Text '$\Lambda_{2}$' at the point (-0.525,0.909325744308...)]
2430
+ """
2431
+ plot_options = self.plot_parse_options(**options)
2432
+ # We build the family of fundamental weights in this space,
2433
+ # indexed by the fundamental weights in the weight lattice.
2434
+ #
2435
+ # To this end, we don't use the embedding of the weight
2436
+ # lattice into self as for the roots or coroots because
2437
+ # the ambient space can define the fundamental weights
2438
+ # slightly differently (the usual GL_n vs SL_n catch).
2439
+ weight_lattice = self.root_system.weight_lattice()
2440
+ fundamental_weights = Family(dict(zip(weight_lattice.fundamental_weights(),
2441
+ self.fundamental_weights())))
2442
+ return plot_options.family_of_vectors(fundamental_weights)
2443
+
2444
+ def plot_reflection_hyperplanes(self, collection='simple', **options):
2445
+ r"""
2446
+ Plot the simple reflection hyperplanes.
2447
+
2448
+ INPUT:
2449
+
2450
+ - ``collection`` -- which reflection hyperplanes to display
2451
+ Can be one of the following:
2452
+
2453
+ * ``'simple'`` (the default)
2454
+ * ``'classical'``
2455
+ * ``'all'``
2456
+
2457
+ - ``**options`` -- plotting options
2458
+
2459
+ .. SEEALSO::
2460
+
2461
+ - :meth:`plot` for a description of the plotting options
2462
+ - :ref:`sage.combinat.root_system.plot` for a tutorial
2463
+ on root system plotting
2464
+
2465
+ EXAMPLES::
2466
+
2467
+ sage: # needs sage.plot sage.symbolic
2468
+ sage: RootSystem(["A",2,1]).ambient_space().plot_reflection_hyperplanes()
2469
+ Graphics object consisting of 6 graphics primitives
2470
+ sage: RootSystem(["G",2,1]).ambient_space().plot_reflection_hyperplanes()
2471
+ Graphics object consisting of 6 graphics primitives
2472
+ sage: RootSystem(["A",3]).weight_space().plot_reflection_hyperplanes()
2473
+ Graphics3d Object
2474
+ sage: RootSystem(["B",3]).ambient_space().plot_reflection_hyperplanes()
2475
+ Graphics3d Object
2476
+ sage: RootSystem(["A",3,1]).weight_space().plot_reflection_hyperplanes()
2477
+ Graphics3d Object
2478
+ sage: RootSystem(["B",3,1]).ambient_space().plot_reflection_hyperplanes()
2479
+ Graphics3d Object
2480
+ sage: RootSystem(["A",2,1]).weight_space().plot_reflection_hyperplanes(affine=False, level=1)
2481
+ Graphics3d Object
2482
+ sage: RootSystem(["A",2]).root_lattice().plot_reflection_hyperplanes()
2483
+ Graphics object consisting of 4 graphics primitives
2484
+
2485
+ TESTS::
2486
+
2487
+ sage: L = RootSystem(["A",2]).ambient_space()
2488
+ sage: print(L.plot_reflection_hyperplanes().description()) # needs sage.plot sage.symbolic
2489
+ Text '$H_{\alpha^\vee_{1}}$' at the point (-1.81...,3.15...)
2490
+ Text '$H_{\alpha^\vee_{2}}$' at the point (1.81...,3.15...)
2491
+ Line defined by 2 points: [(-1.73..., 3.0), (1.73..., -3.0)]
2492
+ Line defined by 2 points: [(1.73..., 3.0), (-1.73..., -3.0)]
2493
+
2494
+ sage: print(L.plot_reflection_hyperplanes("all").description()) # needs sage.plot sage.symbolic
2495
+ Text '$H_{\alpha^\vee_{1} + \alpha^\vee_{2}}$' at the point (3.15...,0.0)
2496
+ Text '$H_{\alpha^\vee_{1}}$' at the point (-1.81...,3.15...)
2497
+ Text '$H_{\alpha^\vee_{2}}$' at the point (1.81...,3.15...)
2498
+ Line defined by 2 points: [(-1.73..., 3.0), (1.73..., -3.0)]
2499
+ Line defined by 2 points: [(1.73..., 3.0), (-1.73..., -3.0)]
2500
+ Line defined by 2 points: [(3.0, 0.0), (-3.0, 0.0)]
2501
+
2502
+ sage: L = RootSystem(["A",2,1]).ambient_space()
2503
+ sage: print(L.plot_reflection_hyperplanes().description()) # needs sage.plot sage.symbolic
2504
+ Text '$H_{\alpha^\vee_{0}}$' at the point (3.15...,0.90...)
2505
+ Text '$H_{\alpha^\vee_{1}}$' at the point (-1.81...,3.15...)
2506
+ Text '$H_{\alpha^\vee_{2}}$' at the point (1.81...,3.15...)
2507
+ Line defined by 2 points: [(-1.73..., 3.0), (1.73..., -3.0)]
2508
+ Line defined by 2 points: [(1.73..., 3.0), (-1.73..., -3.0)]
2509
+ Line defined by 2 points: [(3.0, 0.86...), (-3.0, 0.86...)]
2510
+
2511
+ .. TODO:: Provide an option for transparency?
2512
+ """
2513
+ plot_options = self.plot_parse_options(**options)
2514
+
2515
+ coroot_lattice = self.root_system.coroot_lattice()
2516
+ # Recall that the coroots are given by the roots of the coroot lattice
2517
+ if collection == "simple":
2518
+ coroots = coroot_lattice.simple_roots()
2519
+ elif collection == "classical":
2520
+ if not self.cartan_type().is_affine():
2521
+ raise ValueError("plotting classical reflection hyperplanes only available in affine type")
2522
+ raise NotImplementedError("classical roots")
2523
+ elif collection == "all":
2524
+ if not self.cartan_type().is_finite():
2525
+ raise ValueError("plotting all reflection hyperplanes only available in finite type")
2526
+ coroots = coroot_lattice.positive_roots()
2527
+ elif isinstance(collection, (list, tuple)):
2528
+ coroots = collection
2529
+ else:
2530
+ raise ValueError("Unknown value: %s" % collection)
2531
+
2532
+ G = plot_options.empty()
2533
+ for coroot in coroots:
2534
+ G += plot_options.reflection_hyperplane(coroot)
2535
+ return plot_options.finalize(G)
2536
+
2537
+ def plot_hedron(self, **options):
2538
+ r"""
2539
+ Plot the polyhedron whose vertices are given by the orbit
2540
+ of `\rho`.
2541
+
2542
+ In type `A`, this is the usual permutohedron.
2543
+
2544
+ .. SEEALSO::
2545
+
2546
+ - :meth:`plot` for a description of the plotting options
2547
+ - :ref:`sage.combinat.root_system.plot` for a tutorial
2548
+ on root system plotting
2549
+
2550
+ EXAMPLES::
2551
+
2552
+ sage: # needs sage.plot sage.symbolic
2553
+ sage: RootSystem(["A",2]).ambient_space().plot_hedron()
2554
+ Graphics object consisting of 8 graphics primitives
2555
+ sage: RootSystem(["A",3]).ambient_space().plot_hedron()
2556
+ Graphics3d Object
2557
+ sage: RootSystem(["B",3]).ambient_space().plot_hedron()
2558
+ Graphics3d Object
2559
+ sage: RootSystem(["C",3]).ambient_space().plot_hedron()
2560
+ Graphics3d Object
2561
+ sage: RootSystem(["D",3]).ambient_space().plot_hedron()
2562
+ Graphics3d Object
2563
+
2564
+ Surprise: polyhedra of large dimension know how to
2565
+ project themselves nicely::
2566
+
2567
+ sage: RootSystem(["F",4]).ambient_space().plot_hedron() # long time, needs sage.plot sage.symbolic
2568
+ Graphics3d Object
2569
+
2570
+ TESTS::
2571
+
2572
+ sage: L = RootSystem(["B",2]).ambient_space()
2573
+ sage: print(L.plot_hedron().description()) # needs sage.plot sage.symbolic
2574
+ Polygon defined by 8 points: [(1.5, 0.5), (0.5, 1.5), (-0.5, 1.5), (-1.5, 0.5), (-1.5, -0.5), (-0.5, -1.5), (0.5, -1.5), (1.5, -0.5)]
2575
+ Line defined by 2 points: [(-0.5, -1.5), (0.5, -1.5)]
2576
+ Line defined by 2 points: [(-0.5, 1.5), (0.5, 1.5)]
2577
+ Line defined by 2 points: [(-1.5, -0.5), (-0.5, -1.5)]
2578
+ Line defined by 2 points: [(-1.5, -0.5), (-1.5, 0.5)]
2579
+ Line defined by 2 points: [(-1.5, 0.5), (-0.5, 1.5)]
2580
+ Line defined by 2 points: [(0.5, -1.5), (1.5, -0.5)]
2581
+ Line defined by 2 points: [(0.5, 1.5), (1.5, 0.5)]
2582
+ Line defined by 2 points: [(1.5, -0.5), (1.5, 0.5)]
2583
+ Point set defined by 8 point(s): [(-1.5, -0.5), (-1.5, 0.5), (-0.5, -1.5), (-0.5, 1.5), (0.5, -1.5), (0.5, 1.5), (1.5, -0.5), (1.5, 0.5)]
2584
+ """
2585
+ from sage.geometry.polyhedron.constructor import Polyhedron
2586
+ plot_options = self.plot_parse_options(**options)
2587
+ if not self.cartan_type().is_finite():
2588
+ raise ValueError("the Cartan type must be finite")
2589
+ vertices = [plot_options.projection(vertex)
2590
+ for vertex in self.rho().orbit()]
2591
+ return Polyhedron(vertices=vertices).plot()
2592
+
2593
+ def plot_fundamental_chamber(self, style='normal', **options):
2594
+ r"""
2595
+ Plot the (classical) fundamental chamber.
2596
+
2597
+ INPUT:
2598
+
2599
+ - ``style`` -- ``'normal'`` or ``'classical'`` (default: ``'normal'``)
2600
+
2601
+ - ``**options`` -- plotting options
2602
+
2603
+ .. SEEALSO::
2604
+
2605
+ - :meth:`plot` for a description of the plotting options
2606
+ - :ref:`sage.combinat.root_system.plot` for a tutorial
2607
+ on root system plotting
2608
+
2609
+ EXAMPLES:
2610
+
2611
+ 2D plots::
2612
+
2613
+ sage: # needs sage.geometry.polyhedron sage.plot
2614
+ sage: RootSystem(["B",2]).ambient_space().plot_fundamental_chamber()
2615
+ Graphics object consisting of 1 graphics primitive
2616
+ sage: RootSystem(["B",2,1]).ambient_space().plot_fundamental_chamber()
2617
+ Graphics object consisting of 1 graphics primitive
2618
+ sage: RootSystem(["B",2,1]).ambient_space().plot_fundamental_chamber("classical")
2619
+ Graphics object consisting of 1 graphics primitive
2620
+
2621
+ 3D plots::
2622
+
2623
+ sage: # needs sage.geometry.polyhedron sage.plot
2624
+ sage: RootSystem(["A",3,1]).weight_space() .plot_fundamental_chamber()
2625
+ Graphics3d Object
2626
+ sage: RootSystem(["B",3,1]).ambient_space().plot_fundamental_chamber()
2627
+ Graphics3d Object
2628
+
2629
+ This feature is currently not available in the root lattice/space::
2630
+
2631
+ sage: list(RootSystem(["A",2]).root_lattice().plot_fundamental_chamber()) # needs sage.geometry.polyhedron sage.plot
2632
+ Traceback (most recent call last):
2633
+ ...
2634
+ TypeError: classical fundamental chamber not yet available in the root lattice
2635
+
2636
+ TESTS::
2637
+
2638
+ sage: L = RootSystem(["B",2,1]).ambient_space()
2639
+ sage: print(L.plot_fundamental_chamber().description()) # needs sage.geometry.polyhedron sage.plot
2640
+ Polygon defined by 3 points: [(0.5, 0.5), (1.0, 0.0), (0.0, 0.0)]
2641
+
2642
+ sage: print(L.plot_fundamental_chamber(style='classical').description()) # needs sage.geometry.polyhedron sage.plot
2643
+ Polygon defined by 3 points: [(0.0, 0.0), (3.0, 3.0), (3.0, 0.0)]
2644
+ """
2645
+ plot_options = self.plot_parse_options(**options)
2646
+ if not hasattr(self, "fundamental_weights"):
2647
+ raise TypeError("classical fundamental chamber not yet available in the root lattice")
2648
+ Lambda = self.fundamental_weights()
2649
+ cartan_type = self.cartan_type()
2650
+ if style == "classical":
2651
+ if not cartan_type.is_affine():
2652
+ raise TypeError("classical fundamental chamber only available in affine type")
2653
+ I = cartan_type.classical().index_set()
2654
+ lines = [Lambda[cartan_type.special_node()]]
2655
+ else:
2656
+ I = cartan_type.index_set()
2657
+ lines = []
2658
+ return plot_options.cone(rays=[Lambda[i] for i in I],
2659
+ lines=lines,
2660
+ color='lightgrey',
2661
+ alpha=.3)
2662
+
2663
+ def plot_alcoves(self, alcoves=True, alcove_labels=False, wireframe=False, **options):
2664
+ r"""
2665
+ Plot the alcoves and optionally their labels.
2666
+
2667
+ INPUT:
2668
+
2669
+ - ``alcoves`` -- list of alcoves or ``True`` (default: ``True``)
2670
+
2671
+ - ``alcove_labels`` -- boolean or a number specifying at
2672
+ which level to put the label (default: ``False``)
2673
+
2674
+ - ``**options`` -- plotting options
2675
+
2676
+ .. SEEALSO::
2677
+
2678
+ - :meth:`plot` for a description of the plotting options
2679
+ - :ref:`sage.combinat.root_system.plot` for a
2680
+ tutorial on root system plotting, and in particular
2681
+ how the alcoves can be specified.
2682
+
2683
+ EXAMPLES:
2684
+
2685
+ 2D plots::
2686
+
2687
+ sage: RootSystem(["B",2,1]).ambient_space().plot_alcoves() # long time (3s), needs sage.plot sage.symbolic
2688
+ Graphics object consisting of 228 graphics primitives
2689
+
2690
+ 3D plots::
2691
+
2692
+ sage: RootSystem(["A",2,1]).weight_space() .plot_alcoves(affine=False) # long time (3s), needs sage.plot sage.symbolic
2693
+ Graphics3d Object
2694
+ sage: RootSystem(["G",2,1]).ambient_space().plot_alcoves(affine=False, level=1) # long time (3s), needs sage.plot sage.symbolic
2695
+ Graphics3d Object
2696
+
2697
+ Here we plot a single alcove::
2698
+
2699
+ sage: L = RootSystem(["A",3,1]).ambient_space()
2700
+ sage: W = L.weyl_group() # needs sage.graphs sage.libs.gap
2701
+ sage: L.plot(alcoves=[W.one()], reflection_hyperplanes=False, bounding_box=2) # needs sage.graphs sage.libs.gap sage.plot sage.symbolic
2702
+ Graphics3d Object
2703
+
2704
+ TESTS::
2705
+
2706
+ sage: L = RootSystem(["A",2,1]).weight_space()
2707
+ sage: p = L.plot_alcoves(alcoves=[[0,0]]) # needs sage.plot sage.symbolic
2708
+ sage: print(p.description()) # needs sage.plot sage.symbolic
2709
+ Line defined by 2 points: [(-1.0, 0.0), (0.0, -1.0)]
2710
+ Line defined by 2 points: [(-1.0, 1.0), (-1.0, 0.0)]
2711
+ Line defined by 2 points: [(-1.0, 1.0), (0.0, 0.0)]
2712
+ Line defined by 2 points: [(0.0, 0.0), (-1.0, 0.0)]
2713
+ Line defined by 2 points: [(0.0, 0.0), (0.0, -1.0)]
2714
+ Line defined by 2 points: [(0.0, 0.0), (1.0, -1.0)]
2715
+ Line defined by 2 points: [(0.0, 1.0), (-1.0, 1.0)]
2716
+ Line defined by 2 points: [(0.0, 1.0), (0.0, 0.0)]
2717
+ Line defined by 2 points: [(0.0, 1.0), (1.0, 0.0)]
2718
+ Line defined by 2 points: [(1.0, -1.0), (0.0, -1.0)]
2719
+ Line defined by 2 points: [(1.0, 0.0), (0.0, 0.0)]
2720
+ Line defined by 2 points: [(1.0, 0.0), (1.0, -1.0)]
2721
+ sage: sorted((line.options()['rgbcolor'], line.options()['thickness']) for line in p) # needs sage.plot sage.symbolic
2722
+ [('black', 2), ('black', 2), ('black', 2),
2723
+ ('black', 2), ('black', 2), ('black', 2),
2724
+ ('blue', 1), ('blue', 1), ('blue', 1),
2725
+ ('red', 1), ('red', 1), ('red', 1)]
2726
+ """
2727
+ plot_options = self.plot_parse_options(**options)
2728
+ if not hasattr(self, "fundamental_weights"):
2729
+ raise TypeError("alcoves not yet available in the root lattice")
2730
+ Lambda = self.fundamental_weights()
2731
+ cartan_type = self.cartan_type()
2732
+ I = cartan_type.index_set()
2733
+ W = self.weyl_group()
2734
+ if alcove_labels is not False:
2735
+ rho = self.rho()
2736
+ if alcove_labels is not True:
2737
+ # The input is the desired level
2738
+ rho = rho * alcove_labels / rho.level()
2739
+ else:
2740
+ rho = plot_options.intersection_at_level_1(rho)
2741
+ # The rays of the fundamental alcove
2742
+ fundamental_alcove_rays = Lambda.map(plot_options.intersection_at_level_1)
2743
+
2744
+ def alcove_in_bounding_box(w):
2745
+ return any(plot_options.in_bounding_box(w.action(fundamental_alcove_rays[i]))
2746
+ for i in I)
2747
+
2748
+ def alcove_facet(w, i):
2749
+ # Alcove facets with degenerate intersection with the
2750
+ # bounding box bring no information; we might as well
2751
+ # not draw them. Besides this avoids ugly fat points
2752
+ # in dimension 2.
2753
+ return plot_options.cone(rays=[w.action(fundamental_alcove_rays[j]) for j in I if j != i],
2754
+ color=plot_options.color(i),
2755
+ thickness=plot_options.thickness(i),
2756
+ wireframe=wireframe,
2757
+ draw_degenerate=False)
2758
+
2759
+ def alcove_label(w):
2760
+ label = "$1$" if w.is_one() else "$s_{"+"".join(str(j) for j in w.reduced_word())+"}$"
2761
+ position = plot_options.projection(w.action(rho))
2762
+ if position in plot_options.bounding_box:
2763
+ return plot_options.text(label, position)
2764
+ else:
2765
+ return plot_options.empty()
2766
+
2767
+ G = plot_options.empty()
2768
+ if alcoves is not True:
2769
+ alcoves = list(alcoves)
2770
+ if alcoves is True or (alcoves and W.is_parent_of(alcoves[0])):
2771
+ if alcoves is True:
2772
+ alcoves = W.weak_order_ideal(alcove_in_bounding_box, side='right')
2773
+ # We assume that the fundamental alcove lies within
2774
+ # the bounding box, and explore the alcoves
2775
+ # intersecting the bounding box by going up right
2776
+ # order (i.e. going away from the fundamental alcove)
2777
+ for w in alcoves:
2778
+ for i in w.descents(side='right', positive=True):
2779
+ G += alcove_facet(w, i)
2780
+ if alcove_labels is not False:
2781
+ G += alcove_label(w)
2782
+ else:
2783
+ if not cartan_type.is_affine():
2784
+ raise TypeError("alcoves=list only available in affine type")
2785
+ translation_factors = cartan_type.translation_factors()
2786
+ simple_roots = self.simple_roots()
2787
+ translation_vectors = Family({i: translation_factors[i]*simple_roots[i]
2788
+ for i in cartan_type.classical().index_set()})
2789
+ # The elements of the classical Weyl group, as elements of W
2790
+ W0 = [W.from_reduced_word(w.reduced_word()) for w in self.weyl_group().classical()]
2791
+ for alcove in alcoves:
2792
+ # The translation mapping the center of the
2793
+ # fundamental polygon to polygon indexed by alcove
2794
+ shift = sum(x*v for x,v in zip(alcove, translation_vectors))
2795
+ shift = W.from_morphism(shift.translation)
2796
+ for w in W0:
2797
+ for i in w.descents(side='right', positive=True):
2798
+ G += alcove_facet(shift * w, i)
2799
+ if alcove_labels:
2800
+ G += alcove_label(w)
2801
+ return plot_options.finalize(G)
2802
+
2803
+ # In this alternative commented-out implementation, the
2804
+ # alcove picture is constructed directly in the
2805
+ # projection. It only works for rank 2+1 with, but it is
2806
+ # faster; we keep for reference for now. With #12553
2807
+ # (Cythoned PPL polytopes), the difference is likely to
2808
+ # disappear. If this is confirmed, the code below should be discarded.
2809
+ #
2810
+ # from sage.plot.line import line
2811
+ # translation_vectors = Family({i: translation_factors[i]*plot_options.projection(simple_roots[i])
2812
+ # for i in cartan_type.classical().index_set()})
2813
+ #
2814
+ # # For each polygon P to be drawn, alcoves_shift contains the translation
2815
+ # # from fundamental polygon to P in the plot coordinate system
2816
+ # def immutable_vector(x):
2817
+ # # Takes care of possible numerical instabilities
2818
+ # x = x.numerical_approx(8)
2819
+ # x.set_immutable()
2820
+ # return x
2821
+ #
2822
+ # # Construct the fundamental polygon
2823
+ # # The classical group acting on ``self``
2824
+ # W0 = self.weyl_group().classical().list()
2825
+ # # The coordinates of the vertices of the fundamental alcove
2826
+ # fundamental_alcove_rays = Lambda.map(plot_options.intersection_at_level_1)
2827
+ # # The coordinates of the vertices of the fundamental polygon
2828
+ # fundamental_polygon_rays = {
2829
+ # (i, w): plot_options.projection(w.action(fundamental_alcove_rays[i]))
2830
+ # for w in W0
2831
+ # for i in I
2832
+ # }
2833
+ #
2834
+ # # Get the center of the polygons
2835
+ # if alcoves is True:
2836
+ # def neighbors(x):
2837
+ # return filter(lambda y: plot_options.bounding_box.contains(plot_options.origin_projected+y),
2838
+ # [immutable_vector(x+epsilon*t) for t in translation_vectors for epsilon in [-1,1]])
2839
+ # alcoves_shift = list(RecursivelyEnumeratedSet([immutable_vector(plot_options.origin_projected)], neighbors))
2840
+ # else:
2841
+ # alcoves_shift = [sum(x*v for x,v in zip(alcove, translation_vectors))
2842
+ # for alcove in alcoves]
2843
+ #
2844
+ # G = plot_options.empty()
2845
+ # for shift in alcoves_shift:
2846
+ # # for each center of polygon and each element of classical
2847
+ # # parabolic subgroup, we have to draw an alcove.
2848
+ # polygon_center = plot_options.origin_projected + shift
2849
+ #
2850
+ # for w in W0:
2851
+ # for i in I:
2852
+ # facet_indices = [j for j in I if j != i]
2853
+ # assert len(facet_indices) == 2
2854
+ # facet = [fundamental_polygon_rays[j, w] + shift for j in facet_indices]
2855
+ # # This takes a bit of time; do we really want that feature?
2856
+ # #if not all(bounding_box_as_polytope.contains(v) for v in facet):
2857
+ # # continue
2858
+ # G += line(facet,
2859
+ # rgbcolor = plot_options.color(i),
2860
+ # thickness = 2 if i == special_node else 1)
2861
+
2862
+ def plot_bounding_box(self, **options):
2863
+ r"""
2864
+ Plot the bounding box.
2865
+
2866
+ INPUT:
2867
+
2868
+ - ``**options`` -- plotting options
2869
+
2870
+ This is mostly for testing purposes.
2871
+
2872
+ .. SEEALSO::
2873
+
2874
+ - :meth:`plot` for a description of the plotting options
2875
+ - :ref:`sage.combinat.root_system.plot` for a tutorial
2876
+ on root system plotting
2877
+
2878
+ EXAMPLES::
2879
+
2880
+ sage: L = RootSystem(["A",2,1]).ambient_space()
2881
+ sage: L.plot_bounding_box() # needs sage.plot sage.symbolic
2882
+ Graphics object consisting of 1 graphics primitive
2883
+
2884
+ TESTS::
2885
+
2886
+ sage: list(L.plot_bounding_box()) # needs sage.plot sage.symbolic
2887
+ [Polygon defined by 4 points]
2888
+ """
2889
+ plot_options = self.plot_parse_options(**options)
2890
+ return plot_options.bounding_box.plot(color='gray', alpha=0.5, wireframe=False)
2891
+
2892
+ def plot_alcove_walk(self, word, start=None, foldings=None, color='orange', **options):
2893
+ r"""
2894
+ Plot an alcove walk.
2895
+
2896
+ INPUT:
2897
+
2898
+ - ``word`` -- list of elements of the index set
2899
+ - ``foldings`` -- list of booleans or ``None`` (default: ``None``)
2900
+ - ``start`` -- an element of this space (default: ``None`` for `\rho`)
2901
+ - ``**options`` -- plotting options
2902
+
2903
+ .. SEEALSO::
2904
+
2905
+ - :meth:`plot` for a description of the plotting options
2906
+ - :ref:`sage.combinat.root_system.plot` for a tutorial
2907
+ on root system plotting
2908
+
2909
+ EXAMPLES:
2910
+
2911
+ An alcove walk of type `A_2^{(1)}`::
2912
+
2913
+ sage: L = RootSystem(["A",2,1]).ambient_space()
2914
+ sage: w1 = [0,2,1,2,0,2,1,0,2,1,2,1,2,0,2,0,1,2,0]
2915
+ sage: p = L.plot_alcoves(bounding_box=5) # long time (5s) # needs sage.plot sage.symbolic
2916
+ sage: p += L.plot_alcove_walk(w1) # long time # needs sage.plot sage.symbolic
2917
+ sage: p # long time # needs sage.plot sage.symbolic
2918
+ Graphics object consisting of 375 graphics primitives
2919
+
2920
+ The same plot with another alcove walk::
2921
+
2922
+ sage: w2 = [2,1,2,0,2,0,2,1,2,0,1,2,1,2,1,0,1,2,0,2,0,1,2,0,2]
2923
+ sage: p += L.plot_alcove_walk(w2, color='orange') # long time, needs sage.plot sage.symbolic
2924
+
2925
+ And another with some foldings::
2926
+
2927
+ sage: pic = L.plot_alcoves(bounding_box=3) # long time, needs sage.plot sage.symbolic
2928
+ sage: pic += L.plot_alcove_walk([0,1,2,0,2,0,1,2,0,1], # long time (3s), needs sage.plot sage.symbolic
2929
+ ....: foldings=[False, False, True, False, False,
2930
+ ....: False, True, False, True, False],
2931
+ ....: color='green'); pic
2932
+ Graphics object consisting of 155 graphics primitives
2933
+
2934
+ TESTS::
2935
+
2936
+ sage: L = RootSystem(["A",2,1]).weight_space()
2937
+ sage: p = L.plot_alcove_walk([0,1,2,0,2,0,1,2,0,1], # needs sage.plot sage.symbolic
2938
+ ....: foldings=[False, False, True, False, False,
2939
+ ....: False, True, False, True, False],
2940
+ ....: color='green',
2941
+ ....: start=L.rho())
2942
+ sage: print(p.description()) # needs sage.plot sage.symbolic
2943
+ Line defined by 2 points: [(-1.0, 8.0), (-1.5, 9.0)]
2944
+ Line defined by 2 points: [(1.0, 4.0), (1.5, 4.5)]
2945
+ Line defined by 2 points: [(1.0, 7.0), (1.5, 6.0)]
2946
+ Arrow from (-1.0,5.0) to (-2.0,7.0)
2947
+ Arrow from (-1.0,8.0) to (1.0,7.0)
2948
+ Arrow from (-1.5,9.0) to (-1.0,8.0)
2949
+ Arrow from (-2.0,7.0) to (-1.0,8.0)
2950
+ Arrow from (1.0,1.0) to (2.0,2.0)
2951
+ Arrow from (1.0,4.0) to (-1.0,5.0)
2952
+ Arrow from (1.0,7.0) to (2.0,8.0)
2953
+ Arrow from (1.5,4.5) to (1.0,4.0)
2954
+ Arrow from (1.5,6.0) to (1.0,7.0)
2955
+ Arrow from (2.0,2.0) to (1.0,4.0)
2956
+ """
2957
+ from sage.plot.line import line
2958
+ from sage.plot.arrow import arrow
2959
+ plot_options = self.plot_parse_options(**options)
2960
+ W = self.weyl_group()
2961
+ s = W.simple_reflections()
2962
+ if start is None:
2963
+ start = plot_options.intersection_at_level_1(self.rho())
2964
+ if foldings is None:
2965
+ foldings = [False] * len(word)
2966
+ w = W.one()
2967
+ source = plot_options.projection(start)
2968
+ G = plot_options.empty()
2969
+ for (i, folding) in zip(word, foldings):
2970
+ w = w * s[i]
2971
+ target = plot_options.projection(w.action(start))
2972
+ if folding:
2973
+ middle = (source + target) / 2
2974
+ G += line([source, middle], rgbcolor=color)
2975
+ G += arrow(middle, source, rgbcolor=color, arrowsize=plot_options._arrowsize)
2976
+ # reset w
2977
+ w = w * s[i]
2978
+ else:
2979
+ G += arrow(source, target, rgbcolor=color, arrowsize=plot_options._arrowsize)
2980
+ source = target
2981
+ return G
2982
+
2983
+ @cached_method
2984
+ def _maximum_root_length(self):
2985
+ r"""
2986
+ Return the square of the maximum of the root lengths for irreducible finite type root systems.
2987
+
2988
+ EXAMPLES::
2989
+
2990
+ sage: Q = RootSystem(['C',2]).root_lattice()
2991
+ sage: Q._maximum_root_length()
2992
+ 4
2993
+ sage: Q = RootSystem(['G',2]).root_lattice()
2994
+ sage: Q._maximum_root_length()
2995
+ 6
2996
+ sage: Q = RootSystem(['A',3]).root_lattice()
2997
+ sage: Q._maximum_root_length()
2998
+ 2
2999
+ """
3000
+ ct = self.cartan_type()
3001
+ if not ct.is_irreducible():
3002
+ raise NotImplementedError("Implemented only for irreducible finite root systems")
3003
+ if not ct.is_finite():
3004
+ raise NotImplementedError("Implemented only for irreducible finite root systems")
3005
+ L = self.root_system.ambient_space() # uses peculiarities of ambient embedding
3006
+ return max([root.scalar(root) for root in L.simple_roots()])
3007
+
3008
+ def plot_ls_paths(self, paths, plot_labels=None, colored_labels=True, **options):
3009
+ r"""
3010
+ Plot LS paths.
3011
+
3012
+ INPUT:
3013
+
3014
+ - ``paths`` -- a finite crystal or list of LS paths
3015
+ - ``plot_labels`` -- (default: ``None``) the distance to plot
3016
+ the LS labels from the endpoint of the path; set to ``None``
3017
+ to not display the labels
3018
+ - ``colored_labels`` -- boolean (default: ``True``); if ``True``, then
3019
+ color the labels the same color as the LS path
3020
+ - ``**options`` -- plotting options
3021
+
3022
+ .. SEEALSO::
3023
+
3024
+ - :meth:`plot` for a description of the plotting options
3025
+ - :ref:`sage.combinat.root_system.plot` for a tutorial
3026
+ on root system plotting
3027
+
3028
+ EXAMPLES::
3029
+
3030
+ sage: B = crystals.LSPaths(['A',2], [1,1]) # needs sage.combinat
3031
+ sage: L = RootSystem(['A',2]).ambient_space()
3032
+ sage: L.plot_fundamental_weights() + L.plot_ls_paths(B) # needs sage.combinat sage.plot sage.symbolic
3033
+ Graphics object consisting of 14 graphics primitives
3034
+
3035
+ This also works in 3 dimensions::
3036
+
3037
+ sage: B = crystals.LSPaths(['B',3], [2,0,0]) # needs sage.combinat
3038
+ sage: L = RootSystem(['B',3]).ambient_space()
3039
+ sage: L.plot_ls_paths(B) # needs sage.combinat sage.plot sage.symbolic
3040
+ Graphics3d Object
3041
+ """
3042
+ if not isinstance(paths, (list, tuple, set)):
3043
+ from sage.combinat.crystals.littelmann_path import CrystalOfLSPaths
3044
+ from sage.categories.finite_crystals import FiniteCrystals
3045
+ if not isinstance(paths, CrystalOfLSPaths):
3046
+ raise ValueError("the input must be LS paths")
3047
+ if paths not in FiniteCrystals():
3048
+ raise ValueError("the crystal must be finite")
3049
+
3050
+ from sage.plot.line import line
3051
+ from sage.plot.colors import rainbow
3052
+ plot_options = self.plot_parse_options(**options)
3053
+ color = rainbow(len(paths), 'rgbtuple')
3054
+ G = plot_options.empty()
3055
+ for i,b in enumerate(paths):
3056
+ prev = plot_options.projection(self.zero())
3057
+ for x in b.value:
3058
+ next = prev + plot_options.projection(self(x))
3059
+ G += line([prev, next], rgbcolor=color[i])
3060
+ prev = next
3061
+ if plot_labels is not None:
3062
+ if colored_labels:
3063
+ G += plot_options.text(b, prev + prev.normalized()*plot_labels, rgbcolor=color[i])
3064
+ else:
3065
+ G += plot_options.text(b, prev + prev.normalized()*plot_labels)
3066
+ return G
3067
+
3068
+ def plot_mv_polytope(self, mv_polytope, mark_endpoints=True,
3069
+ circle_size=0.06, circle_thickness=1.6,
3070
+ wireframe='blue', fill='green', alpha=1,
3071
+ **options):
3072
+ r"""
3073
+ Plot an MV polytope.
3074
+
3075
+ INPUT:
3076
+
3077
+ - ``mv_polytope`` -- an MV polytope
3078
+ - ``mark_endpoints`` -- boolean (default: ``True``); mark the endpoints
3079
+ of the MV polytope
3080
+ - ``circle_size`` -- (default: 0.06) the size of the circles
3081
+ - ``circle_thickness`` -- (default: 1.6) the thinkness of the
3082
+ extra rings of circles
3083
+ - ``wireframe`` -- (default: ``'blue'``) color to draw the
3084
+ wireframe of the polytope with
3085
+ - ``fill`` -- (default: ``'green'``) color to fill the polytope with
3086
+ - ``alpha`` -- (default: 1) the alpha value (opacity) of the fill
3087
+ - ``**options`` -- plotting options
3088
+
3089
+ .. SEEALSO::
3090
+
3091
+ - :meth:`plot` for a description of the plotting options
3092
+ - :ref:`sage.combinat.root_system.plot` for a tutorial
3093
+ on root system plotting
3094
+
3095
+ EXAMPLES::
3096
+
3097
+ sage: B = crystals.infinity.MVPolytopes(['C',2]) # needs sage.combinat
3098
+ sage: L = RootSystem(['C',2]).ambient_space()
3099
+ sage: p = B.highest_weight_vector().f_string([1,2,1,2]) # needs sage.combinat
3100
+ sage: L.plot_fundamental_weights() + L.plot_mv_polytope(p) # needs sage.combinat sage.geometry.polyhedron sage.plot sage.symbolic
3101
+ Graphics object consisting of 14 graphics primitives
3102
+
3103
+ This also works in 3 dimensions::
3104
+
3105
+ sage: B = crystals.infinity.MVPolytopes(['A',3]) # needs sage.combinat
3106
+ sage: L = RootSystem(['A',3]).ambient_space()
3107
+ sage: p = B.highest_weight_vector().f_string([2,1,3,2]) # needs sage.combinat
3108
+ sage: L.plot_mv_polytope(p) # needs sage.combinat sage.geometry.polyhedron sage.plot sage.symbolic
3109
+ Graphics3d Object
3110
+ """
3111
+ from sage.geometry.polyhedron.constructor import Polyhedron
3112
+ plot_options = self.plot_parse_options(**options)
3113
+
3114
+ # Setup the shift for plotting
3115
+ pbw_data = mv_polytope._pbw_datum.parent
3116
+ al = self.simple_roots()
3117
+ red = tuple(mv_polytope._pbw_datum.long_word)
3118
+ roots = [self.sum(c*al[a] for a,c in root)
3119
+ for root in pbw_data._root_list_from(red)]
3120
+ datum = mv_polytope._pbw_datum.lusztig_datum
3121
+ end_pt = self.sum(roots[i] * c for i,c in enumerate(datum))
3122
+ shift = plot_options.projection(end_pt)
3123
+
3124
+ vertices = [plot_options.projection(vertex) - shift
3125
+ for vertex in mv_polytope._polytope_vertices(self)]
3126
+ p = Polyhedron(vertices=vertices).plot(wireframe=wireframe,
3127
+ fill=fill, alpha=alpha)
3128
+ if mark_endpoints:
3129
+ from sage.plot.circle import circle
3130
+
3131
+ p += circle(plot_options.projection(self.zero()),
3132
+ circle_size, fill=True,
3133
+ thickness=circle_thickness, color=wireframe)
3134
+
3135
+ p += circle(-shift,
3136
+ circle_size, fill=True,
3137
+ thickness=circle_thickness, color=wireframe)
3138
+ return p
3139
+
3140
+ def plot_crystal(self, crystal,
3141
+ plot_labels=True, label_color='black',
3142
+ edge_labels=False,
3143
+ circle_size=0.06, circle_thickness=1.6,
3144
+ **options):
3145
+ r"""
3146
+ Plot a finite crystal.
3147
+
3148
+ INPUT:
3149
+
3150
+ - ``crystal`` -- the finite crystal to plot
3151
+ - ``plot_labels`` -- boolean (default: ``True``); can be one of the
3152
+ following:
3153
+
3154
+ * ``True`` -- use the latex labels
3155
+ * ``'circles'`` -- use circles for multiplicity up to 4; if the
3156
+ multiplicity is larger, then it uses the multiplicity
3157
+ * ``'multiplicities'`` -- use the multiplicities
3158
+
3159
+ - ``label_color`` -- (default: ``'black'``) the color of the
3160
+ labels
3161
+ - ``edge_labels`` -- boolean (default: ``False``); if ``True``, then draw
3162
+ in the edge label
3163
+ - ``circle_size`` -- (default: 0.06) the size of the circles
3164
+ - ``circle_thickness`` -- (default: 1.6) the thinkness of the
3165
+ extra rings of circles
3166
+ - ``**options`` -- plotting options
3167
+
3168
+ .. SEEALSO::
3169
+
3170
+ - :meth:`plot` for a description of the plotting options
3171
+ - :ref:`sage.combinat.root_system.plot` for a tutorial
3172
+ on root system plotting
3173
+
3174
+ EXAMPLES::
3175
+
3176
+ sage: # needs sage.combinat sage.plot sage.symbolic
3177
+ sage: L = RootSystem(['A',2]).ambient_space()
3178
+ sage: C = crystals.Tableaux(['A',2], shape=[2,1])
3179
+ sage: L.plot_crystal(C, plot_labels='multiplicities')
3180
+ Graphics object consisting of 15 graphics primitives
3181
+ sage: C = crystals.Tableaux(['A',2], shape=[8,4])
3182
+ sage: p = L.plot_crystal(C, plot_labels='circles')
3183
+ sage: p.show(figsize=15)
3184
+
3185
+ A 3-dimensional example::
3186
+
3187
+ sage: L = RootSystem(['B',3]).ambient_space()
3188
+ sage: C = crystals.Tableaux(['B',3], shape=[2,1]) # needs sage.combinat
3189
+ sage: L.plot_crystal(C, plot_labels='circles', # long time # needs sage.combinat sage.plot sage.symbolic
3190
+ ....: edge_labels=True)
3191
+ Graphics3d Object
3192
+
3193
+ TESTS:
3194
+
3195
+ Check that :issue:`29548` is fixed::
3196
+
3197
+ sage: LS = crystals.LSPaths(['A',2], [1,1]) # needs sage.combinat
3198
+ sage: L = RootSystem(['A',2]).ambient_space()
3199
+ sage: L.plot_crystal(LS) # needs sage.combinat sage.plot sage.symbolic
3200
+ Graphics object consisting of 16 graphics primitives
3201
+ """
3202
+ from sage.plot.arrow import arrow
3203
+ from sage.plot.circle import circle
3204
+ from sage.plot.colors import rgbcolor
3205
+ from sage.categories.finite_crystals import FiniteCrystals
3206
+
3207
+ if crystal not in FiniteCrystals():
3208
+ raise ValueError("only implemented for finite crystals")
3209
+ plot_options = self.plot_parse_options(**options)
3210
+ label_color = rgbcolor(label_color)
3211
+
3212
+ g = crystal.digraph()
3213
+ mults = {}
3214
+ for x in g.vertex_iterator():
3215
+ wt = self(x.weight())
3216
+ mults[wt] = mults.get(wt, []) + [x]
3217
+ positions = {x: plot_options.projection(x) for x in mults.keys()}
3218
+
3219
+ G = plot_options.empty()
3220
+ if plot_labels == 'circles':
3221
+ for wt,m in mults.items():
3222
+ m = len(m)
3223
+ if m > 4:
3224
+ G += plot_options.text(m, positions[wt], rgbcolor=label_color)
3225
+ continue
3226
+
3227
+ if m >= 1:
3228
+ G += circle(positions[wt], circle_size, fill=True,
3229
+ thickness=circle_thickness,
3230
+ rgbcolor=label_color)
3231
+ for i in range(2,m+1):
3232
+ G += circle(positions[wt], i*circle_size,
3233
+ thickness=circle_thickness,
3234
+ rgbcolor=label_color)
3235
+
3236
+ elif plot_labels == 'multiplicities':
3237
+ for wt,m in mults.items():
3238
+ G += plot_options.text(len(m), positions[wt], rgbcolor=label_color)
3239
+
3240
+ elif plot_labels:
3241
+ for wt,m in mults.items():
3242
+ for elt in m:
3243
+ # TODO: Destack the multiple weights
3244
+ G += plot_options.text(elt, positions[wt], rgbcolor=label_color)
3245
+
3246
+ for h,t,i in g.edges(sort=True):
3247
+ G += arrow(positions[self(h.weight())], positions[self(t.weight())],
3248
+ zorder=1, rgbcolor=plot_options.color(i),
3249
+ arrowsize=plot_options._arrowsize)
3250
+ if edge_labels:
3251
+ mid = (positions[self(h.weight())] + positions[self(t.weight())]) / QQ(2)
3252
+ if plot_options.dimension >= 2:
3253
+ diff = (positions[self(h.weight())] - positions[self(t.weight())]).normalized()
3254
+ if plot_options.dimension >= 3:
3255
+ from copy import copy
3256
+ diff2 = copy(diff)
3257
+ diff[0], diff[1] = -diff[1], diff[0]
3258
+ if abs(diff.dot_product(diff2)) > 0.9:
3259
+ diff[1], diff[2] = -diff[2], diff[1]
3260
+ else:
3261
+ diff[0], diff[1] = -diff[1], diff[0]
3262
+
3263
+ mid += diff / QQ(10)
3264
+ G += plot_options.text(i, mid, rgbcolor=plot_options.color(i))
3265
+ return G
3266
+
3267
+ @cached_method
3268
+ def dual_type_cospace(self):
3269
+ r"""
3270
+ Return the cospace of dual type.
3271
+
3272
+ For example, if invoked on the root lattice of type `['B',2]`, returns the
3273
+ coroot lattice of type `['C',2]`.
3274
+
3275
+ .. WARNING::
3276
+
3277
+ Not implemented for ambient spaces.
3278
+
3279
+ EXAMPLES::
3280
+
3281
+ sage: CartanType(['B',2]).root_system().root_lattice().dual_type_cospace()
3282
+ Coroot lattice of the Root system of type ['C', 2]
3283
+ sage: CartanType(['F',4]).root_system().coweight_lattice().dual_type_cospace()
3284
+ Weight lattice of the Root system of type ['F', 4]
3285
+ relabelled by {1: 4, 2: 3, 3: 2, 4: 1}
3286
+ """
3287
+ from .root_space import RootSpace
3288
+ from .weight_space import WeightSpace
3289
+
3290
+ if isinstance(self, RootSpace):
3291
+ if self.root_system.dual_side:
3292
+ return self.cartan_type().root_system().root_space(self.base_ring())
3293
+ else:
3294
+ return self.cartan_type().dual().root_system().coroot_space(self.base_ring())
3295
+ if isinstance(self, WeightSpace):
3296
+ if self.root_system.dual_side:
3297
+ return self.cartan_type().root_system().weight_space(self.base_ring())
3298
+ else:
3299
+ return self.cartan_type().dual().root_system().coweight_space(self.base_ring())
3300
+ raise TypeError("Not implemented for %s" % self)
3301
+
3302
+ @abstract_method(optional=True)
3303
+ def to_ambient_space_morphism(self):
3304
+ r"""
3305
+ Return the morphism to the ambient space.
3306
+
3307
+ EXAMPLES::
3308
+
3309
+ sage: B2rs = CartanType(['B',2]).root_system()
3310
+ sage: B2rs.root_lattice().to_ambient_space_morphism()
3311
+ Generic morphism:
3312
+ From: Root lattice of the Root system of type ['B', 2]
3313
+ To: Ambient space of the Root system of type ['B', 2]
3314
+ sage: B2rs.coroot_lattice().to_ambient_space_morphism()
3315
+ Generic morphism:
3316
+ From: Coroot lattice of the Root system of type ['B', 2]
3317
+ To: Ambient space of the Root system of type ['B', 2]
3318
+ sage: B2rs.weight_lattice().to_ambient_space_morphism()
3319
+ Generic morphism:
3320
+ From: Weight lattice of the Root system of type ['B', 2]
3321
+ To: Ambient space of the Root system of type ['B', 2]
3322
+ """
3323
+
3324
+ ##########################################################################
3325
+
3326
+ class ElementMethods:
3327
+
3328
+ @abstract_method
3329
+ def scalar(self, lambdacheck):
3330
+ """
3331
+ Implement the natural pairing with the coroot lattice.
3332
+
3333
+ INPUT:
3334
+
3335
+ - ``self`` -- an element of a root lattice realization
3336
+ - ``lambdacheck`` -- an element of the coroot lattice or coroot space
3337
+
3338
+ OUTPUT: the scalar product of ``self`` and ``lambdacheck``
3339
+
3340
+ EXAMPLES::
3341
+
3342
+ sage: L = RootSystem(['A',4]).root_lattice()
3343
+ sage: alpha = L.simple_roots()
3344
+ sage: alphacheck = L.simple_coroots()
3345
+ sage: alpha[1].scalar(alphacheck[1]) # needs sage.graphs
3346
+ 2
3347
+ sage: alpha[1].scalar(alphacheck[2]) # needs sage.graphs
3348
+ -1
3349
+ sage: matrix([ [ alpha[i].scalar(alphacheck[j]) # needs sage.graphs
3350
+ ....: for i in L.index_set() ]
3351
+ ....: for j in L.index_set() ])
3352
+ [ 2 -1 0 0]
3353
+ [-1 2 -1 0]
3354
+ [ 0 -1 2 -1]
3355
+ [ 0 0 -1 2]
3356
+
3357
+ TESTS::
3358
+
3359
+ sage: super(sage.combinat.root_system.root_space.RootSpaceElement,alpha[1]).scalar(alphacheck[1])
3360
+ Traceback (most recent call last):
3361
+ ...
3362
+ NotImplementedError: <abstract method scalar at ...>
3363
+ """
3364
+
3365
+ def symmetric_form(self, alpha):
3366
+ r"""
3367
+ Return the symmetric form of ``self`` with ``alpha``.
3368
+
3369
+ Consider the simple roots `\alpha_i` and let `(b_{ij})_{ij}`
3370
+ denote the symmetrized Cartan matrix `(a_{ij})_{ij}`, we have
3371
+
3372
+ .. MATH::
3373
+
3374
+ (\alpha_i | \alpha_j) = b_{ij}
3375
+
3376
+ and extended bilinearly. See Chapter 6 in Kac, Infinite
3377
+ Dimensional Lie Algebras for more details.
3378
+
3379
+ EXAMPLES::
3380
+
3381
+ sage: # needs sage.graphs
3382
+ sage: Q = RootSystem(['B',2,1]).root_lattice()
3383
+ sage: alpha = Q.simple_roots()
3384
+ sage: alpha[1].symmetric_form(alpha[0])
3385
+ 0
3386
+ sage: alpha[1].symmetric_form(alpha[1])
3387
+ 4
3388
+ sage: elt = alpha[0] - 3*alpha[1] + alpha[2]
3389
+ sage: elt.symmetric_form(alpha[1])
3390
+ -14
3391
+ sage: elt.symmetric_form(alpha[0]+2*alpha[2])
3392
+ 14
3393
+
3394
+ sage: Q = RootSystem(CartanType(['A',4,2]).dual()).root_lattice()
3395
+ sage: Qc = RootSystem(['A',4,2]).coroot_lattice()
3396
+ sage: alpha = Q.simple_roots()
3397
+ sage: alphac = Qc.simple_roots()
3398
+ sage: elt = alpha[0] + 2*alpha[1] + 2*alpha[2]
3399
+ sage: eltc = alphac[0] + 2*alphac[1] + 2*alphac[2]
3400
+ sage: elt.symmetric_form(alpha[1]) # needs sage.graphs
3401
+ 0
3402
+ sage: eltc.symmetric_form(alphac[1]) # needs sage.graphs
3403
+ 0
3404
+ """
3405
+ cm = self.parent().dynkin_diagram().cartan_matrix()
3406
+ sym = cm.symmetrized_matrix()
3407
+ iset = self.parent().index_set()
3408
+ return sum(cl*sym[iset.index(ml),iset.index(mr)]*cr
3409
+ for ml,cl in self for mr,cr in alpha)
3410
+
3411
+ def norm_squared(self):
3412
+ """
3413
+ Return the norm squared of ``self`` with respect to the
3414
+ symmetric form.
3415
+
3416
+ EXAMPLES::
3417
+
3418
+ sage: # needs sage.graphs
3419
+ sage: Q = RootSystem(['B',2,1]).root_lattice()
3420
+ sage: alpha = Q.simple_roots()
3421
+ sage: alpha[1].norm_squared()
3422
+ 4
3423
+ sage: alpha[2].norm_squared()
3424
+ 2
3425
+ sage: elt = alpha[0] - 3*alpha[1] + alpha[2]
3426
+ sage: elt.norm_squared()
3427
+ 50
3428
+ sage: elt = alpha[0] + alpha[1] + 2*alpha[2]
3429
+ sage: elt.norm_squared()
3430
+ 0
3431
+
3432
+ sage: Q = RootSystem(CartanType(['A',4,2]).dual()).root_lattice()
3433
+ sage: Qc = RootSystem(['A',4,2]).coroot_lattice()
3434
+ sage: alpha = Q.simple_roots()
3435
+ sage: alphac = Qc.simple_roots()
3436
+ sage: elt = alpha[0] + 2*alpha[1] + 2*alpha[2]
3437
+ sage: eltc = alphac[0] + 2*alphac[1] + 2*alphac[2]
3438
+ sage: elt.norm_squared() # needs sage.graphs
3439
+ 0
3440
+ sage: eltc.norm_squared() # needs sage.graphs
3441
+ 0
3442
+ """
3443
+ return self.symmetric_form(self)
3444
+
3445
+ ##########################################################################
3446
+ # Action and orbits w.r.t. the Weyl group
3447
+ ##########################################################################
3448
+
3449
+ def simple_reflection(self, i):
3450
+ r"""
3451
+ Return the image of ``self`` by the `i`-th simple reflection.
3452
+
3453
+ EXAMPLES::
3454
+
3455
+ sage: alpha = RootSystem(["A", 3]).root_lattice().alpha()
3456
+ sage: alpha[1].simple_reflection(2) # needs sage.graphs
3457
+ alpha[1] + alpha[2]
3458
+
3459
+ sage: Q = RootSystem(['A', 3, 1]).weight_lattice(extended=True)
3460
+ sage: Lambda = Q.fundamental_weights()
3461
+ sage: L = Lambda[0] + Q.null_root() # needs sage.graphs
3462
+ sage: L.simple_reflection(0) # needs sage.graphs
3463
+ -Lambda[0] + Lambda[1] + Lambda[3]
3464
+ """
3465
+ # Subclasses should optimize whenever possible!
3466
+ return self.parent().simple_reflection(i)(self)
3467
+
3468
+ def simple_reflections(self):
3469
+ """
3470
+ The images of ``self`` by all the simple reflections.
3471
+
3472
+ EXAMPLES::
3473
+
3474
+ sage: alpha = RootSystem(["A", 3]).root_lattice().alpha()
3475
+ sage: alpha[1].simple_reflections() # needs sage.graphs
3476
+ [-alpha[1], alpha[1] + alpha[2], alpha[1]]
3477
+ """
3478
+ return [s(self) for s in self.parent().simple_reflections()]
3479
+
3480
+ def _orbit_iter(self):
3481
+ """
3482
+ Iterate the orbit of ``self`` under the action of the Weyl group.
3483
+
3484
+ Call this method when the orbit just needs to be iterated over.
3485
+
3486
+ EXAMPLES::
3487
+
3488
+ sage: L = RootSystem(["A", 2]).ambient_lattice()
3489
+ sage: sorted(L.rho()._orbit_iter()) # the output order is not specified
3490
+ [(1, 2, 0), (1, 0, 2), (2, 1, 0),
3491
+ (2, 0, 1), (0, 1, 2), (0, 2, 1)]
3492
+ """
3493
+ R = RecursivelyEnumeratedSet([self], attrcall('simple_reflections'),
3494
+ structure=None, enumeration='breadth')
3495
+ return iter(R)
3496
+
3497
+ def orbit(self):
3498
+ r"""
3499
+ The orbit of ``self`` under the action of the Weyl group.
3500
+
3501
+ EXAMPLES:
3502
+
3503
+ `\rho` is a regular element whose orbit is in bijection
3504
+ with the Weyl group. In particular, it has 6 elements for
3505
+ the symmetric group `S_3`::
3506
+
3507
+ sage: L = RootSystem(["A", 2]).ambient_lattice()
3508
+ sage: sorted(L.rho().orbit()) # the output order is not specified
3509
+ [(1, 2, 0), (1, 0, 2), (2, 1, 0),
3510
+ (2, 0, 1), (0, 1, 2), (0, 2, 1)]
3511
+
3512
+ sage: L = RootSystem(["A", 3]).weight_lattice()
3513
+ sage: len(L.rho().orbit()) # needs sage.graphs
3514
+ 24
3515
+ sage: len(L.fundamental_weights()[1].orbit()) # needs sage.graphs
3516
+ 4
3517
+ sage: len(L.fundamental_weights()[2].orbit()) # needs sage.graphs
3518
+ 6
3519
+
3520
+ TESTS::
3521
+
3522
+ sage: la = RootSystem(['A',1,1]).weight_lattice().fundamental_weight(0)
3523
+ sage: la.orbit()
3524
+ Traceback (most recent call last):
3525
+ ...
3526
+ ValueError: cannot list an infinite set
3527
+ """
3528
+ if not self.parent().cartan_type().is_finite():
3529
+ raise ValueError("cannot list an infinite set")
3530
+ return list(self._orbit_iter())
3531
+
3532
+ def _dot_orbit_iter(self):
3533
+ """
3534
+ Iterate the orbit of ``self`` under the dot or affine action
3535
+ of the Weyl group.
3536
+
3537
+ Call this method when the dot orbit just needs to be
3538
+ iterated over.
3539
+
3540
+ EXAMPLES::
3541
+
3542
+ sage: L = RootSystem(['A', 2]).ambient_lattice()
3543
+ sage: sorted(L.rho()._dot_orbit_iter()) # the output order is not specified
3544
+ [(-2, 1, 4), (-2, 3, 2), (2, -1, 2),
3545
+ (2, 1, 0), (0, -1, 4), (0, 3, 0)]
3546
+ sage: sorted(L.rho()._orbit_iter()) # the output order is not specified
3547
+ [(1, 2, 0), (1, 0, 2), (2, 1, 0),
3548
+ (2, 0, 1), (0, 1, 2), (0, 2, 1)]
3549
+ """
3550
+ I = self.parent().index_set()
3551
+
3552
+ def apply_action(la):
3553
+ return [la.dot_action([i]) for i in I]
3554
+ R = RecursivelyEnumeratedSet([self], apply_action, structure=None,
3555
+ enumeration='breadth')
3556
+ return iter(R)
3557
+
3558
+ def dot_orbit(self):
3559
+ r"""
3560
+ The orbit of ``self`` under the dot or affine action of
3561
+ the Weyl group.
3562
+
3563
+ EXAMPLES::
3564
+
3565
+ sage: L = RootSystem(['A', 2]).ambient_lattice()
3566
+ sage: sorted(L.rho().dot_orbit()) # the output order is not specified # needs sage.graphs
3567
+ [(-2, 1, 4), (-2, 3, 2), (2, -1, 2),
3568
+ (2, 1, 0), (0, -1, 4), (0, 3, 0)]
3569
+
3570
+ sage: L = RootSystem(['B',2]).weight_lattice()
3571
+ sage: sorted(L.fundamental_weights()[1].dot_orbit()) # the output order is not specified # needs sage.graphs
3572
+ [-4*Lambda[1], -4*Lambda[1] + 4*Lambda[2],
3573
+ -3*Lambda[1] - 2*Lambda[2], -3*Lambda[1] + 4*Lambda[2],
3574
+ Lambda[1], Lambda[1] - 6*Lambda[2],
3575
+ 2*Lambda[1] - 6*Lambda[2], 2*Lambda[1] - 2*Lambda[2]]
3576
+
3577
+ We compare the dot action orbit to the regular orbit::
3578
+
3579
+ sage: # needs sage.graphs
3580
+ sage: L = RootSystem(['A', 3]).weight_lattice()
3581
+ sage: len(L.rho().dot_orbit())
3582
+ 24
3583
+ sage: len((-L.rho()).dot_orbit())
3584
+ 1
3585
+ sage: La = L.fundamental_weights()
3586
+ sage: len(La[1].dot_orbit())
3587
+ 24
3588
+ sage: len(La[1].orbit())
3589
+ 4
3590
+ sage: len((-L.rho() + La[1]).dot_orbit())
3591
+ 4
3592
+ sage: len(La[2].dot_orbit())
3593
+ 24
3594
+ sage: len(La[2].orbit())
3595
+ 6
3596
+ sage: len((-L.rho() + La[2]).dot_orbit())
3597
+ 6
3598
+ """
3599
+ return list(self._dot_orbit_iter())
3600
+
3601
+ affine_orbit = dot_orbit
3602
+
3603
+ ##########################################################################
3604
+ #
3605
+ ##########################################################################
3606
+
3607
+ @abstract_method(optional=True)
3608
+ def associated_coroot(self):
3609
+ """
3610
+ Return the coroot associated to this root.
3611
+
3612
+ EXAMPLES::
3613
+
3614
+ sage: alpha = RootSystem(["A", 3]).root_space().simple_roots()
3615
+ sage: alpha[1].associated_coroot() # needs sage.graphs
3616
+ alphacheck[1]
3617
+ """
3618
+
3619
+ def reflection(self, root, use_coroot=False):
3620
+ r"""
3621
+ Reflect ``self`` across the hyperplane orthogonal to ``root``.
3622
+
3623
+ If ``use_coroot`` is ``True``, ``root`` is interpreted as a coroot.
3624
+
3625
+ EXAMPLES::
3626
+
3627
+ sage: R = RootSystem(['C',4])
3628
+ sage: weight_lattice = R.weight_lattice()
3629
+ sage: mu = weight_lattice.from_vector(vector([0,0,1,2]))
3630
+ sage: coroot_lattice = R.coroot_lattice()
3631
+ sage: alphavee = coroot_lattice.from_vector(vector([0,0,1,1]))
3632
+ sage: mu.reflection(alphavee, use_coroot=True) # needs sage.graphs
3633
+ 6*Lambda[2] - 5*Lambda[3] + 2*Lambda[4]
3634
+ sage: root_lattice = R.root_lattice()
3635
+ sage: beta = root_lattice.from_vector(vector([0,1,1,0]))
3636
+ sage: mu.reflection(beta) # needs sage.graphs
3637
+ Lambda[1] - Lambda[2] + 3*Lambda[4]
3638
+ """
3639
+ if use_coroot:
3640
+ return self - self.scalar(root) * root.associated_coroot()
3641
+ else:
3642
+ return self - self.scalar(root.associated_coroot()) * root
3643
+
3644
+ ##########################################################################
3645
+ # Descents
3646
+ ##########################################################################
3647
+
3648
+ def has_descent(self, i, positive=False) -> bool:
3649
+ """
3650
+ Test if ``self`` has a descent at position `i`, that is, if ``self`` is
3651
+ on the strict negative side of the `i`-th simple reflection
3652
+ hyperplane.
3653
+
3654
+ If positive is ``True``, tests if it is on the strict positive
3655
+ side instead.
3656
+
3657
+ EXAMPLES::
3658
+
3659
+ sage: # needs sage.graphs
3660
+ sage: space = RootSystem(['A',5]).weight_space()
3661
+ sage: alpha = RootSystem(['A',5]).weight_space().simple_roots()
3662
+ sage: [alpha[i].has_descent(1) for i in space.index_set()]
3663
+ [False, True, False, False, False]
3664
+ sage: [(-alpha[i]).has_descent(1) for i in space.index_set()]
3665
+ [True, False, False, False, False]
3666
+ sage: [alpha[i].has_descent(1, True) for i in space.index_set()]
3667
+ [True, False, False, False, False]
3668
+ sage: [(-alpha[i]).has_descent(1, True) for i in space.index_set()]
3669
+ [False, True, False, False, False]
3670
+ sage: (alpha[1]+alpha[2]+alpha[4]).has_descent(3)
3671
+ True
3672
+ sage: (alpha[1]+alpha[2]+alpha[4]).has_descent(1)
3673
+ False
3674
+ sage: (alpha[1]+alpha[2]+alpha[4]).has_descent(1, True)
3675
+ True
3676
+ """
3677
+ s = self.scalar(self.parent().simple_coroots()[i])
3678
+ if positive:
3679
+ return s > 0
3680
+ else:
3681
+ return s < 0
3682
+
3683
+ def first_descent(self, index_set=None, positive=False):
3684
+ """
3685
+ Return the first descent of pt.
3686
+
3687
+ One can use the ``index_set`` option to restrict to the parabolic
3688
+ subgroup indexed by ``index_set``.
3689
+
3690
+ EXAMPLES::
3691
+
3692
+ sage: # needs sage.graphs
3693
+ sage: space = RootSystem(['A',5]).weight_space()
3694
+ sage: alpha = space.simple_roots()
3695
+ sage: (alpha[1]+alpha[2]+alpha[4]).first_descent()
3696
+ 3
3697
+ sage: (alpha[1]+alpha[2]+alpha[4]).first_descent([1,2,5])
3698
+ 5
3699
+ sage: (alpha[1]+alpha[2]+alpha[4]).first_descent([1,2,5,3,4])
3700
+ 5
3701
+ """
3702
+ if index_set is None:
3703
+ index_set = self.parent().index_set()
3704
+ for i in index_set:
3705
+ if self.has_descent(i, positive):
3706
+ return i
3707
+ return None
3708
+
3709
+ def descents(self, index_set=None, positive=False):
3710
+ """
3711
+ Return the descents of pt.
3712
+
3713
+ EXAMPLES::
3714
+
3715
+ sage: space=RootSystem(['A',5]).weight_space()
3716
+ sage: alpha = space.simple_roots() # needs sage.graphs
3717
+ sage: (alpha[1]+alpha[2]+alpha[4]).descents() # needs sage.graphs
3718
+ [3, 5]
3719
+ """
3720
+ if index_set is None:
3721
+ index_set = self.parent().index_set()
3722
+ return [ i for i in index_set if self.has_descent(i, positive) ]
3723
+
3724
+ def to_dominant_chamber(self, index_set=None, positive=True, reduced_word=False):
3725
+ r"""
3726
+ Return the unique dominant element in the Weyl group orbit of the vector ``self``.
3727
+
3728
+ If ``positive`` is ``False``, returns the antidominant orbit element.
3729
+
3730
+ With the ``index_set`` optional parameter, this is done with
3731
+ respect to the corresponding parabolic subgroup.
3732
+
3733
+ If ``reduced_word`` is ``True``, returns the 2-tuple (``weight``, ``direction``)
3734
+ where ``weight`` is the (anti)dominant orbit element and ``direction`` is a reduced word
3735
+ for the Weyl group element sending ``weight`` to ``self``.
3736
+
3737
+ .. warning::
3738
+
3739
+ In infinite type, an orbit may not contain a dominant element.
3740
+ In this case the function may go into an infinite loop.
3741
+
3742
+ For affine root systems, errors are generated if
3743
+ the orbit does not contain the requested kind of representative.
3744
+ If the input vector is of positive (resp. negative)
3745
+ level, then there is a dominant (resp. antidominant) element in its orbit
3746
+ but not an antidominant (resp. dominant) one. If the vector is of level zero,
3747
+ then there are neither dominant nor antidominant orbit representatives, except
3748
+ for multiples of the null root, which are themselves both dominant and antidominant
3749
+ orbit representatives.
3750
+
3751
+ EXAMPLES::
3752
+
3753
+ sage: # needs sage.graphs
3754
+ sage: space = RootSystem(['A',5]).weight_space()
3755
+ sage: alpha = RootSystem(['A',5]).weight_space().simple_roots()
3756
+ sage: alpha[1].to_dominant_chamber()
3757
+ Lambda[1] + Lambda[5]
3758
+ sage: alpha[1].to_dominant_chamber([1,2])
3759
+ Lambda[1] + Lambda[2] - Lambda[3]
3760
+ sage: wl = RootSystem(['A',2,1]).weight_lattice(extended=True)
3761
+ sage: mu = wl.from_vector(vector([1,-3,0]))
3762
+ sage: mu.to_dominant_chamber(positive=False, reduced_word=True)
3763
+ (-Lambda[1] - Lambda[2] - delta, [0, 2])
3764
+
3765
+ sage: # needs sage.graphs
3766
+ sage: R = RootSystem(['A',1,1])
3767
+ sage: rl = R.root_lattice()
3768
+ sage: nu = rl.zero()
3769
+ sage: nu.to_dominant_chamber()
3770
+ 0
3771
+ sage: nu.to_dominant_chamber(positive=False)
3772
+ 0
3773
+ sage: mu = rl.from_vector(vector([0,1]))
3774
+ sage: mu.to_dominant_chamber()
3775
+ Traceback (most recent call last):
3776
+ ...
3777
+ ValueError: alpha[1] is not in the orbit of the fundamental chamber
3778
+ sage: mu.to_dominant_chamber(positive=False)
3779
+ Traceback (most recent call last):
3780
+ ...
3781
+ ValueError: alpha[1] is not in the orbit of the negative of the fundamental chamber
3782
+ """
3783
+
3784
+ if index_set is None:
3785
+ # default index set is the entire Dynkin node set
3786
+ index_set = self.parent().index_set()
3787
+ cartan_type = self.parent().cartan_type()
3788
+ # generate errors for infinite loop cases in affine type
3789
+ if cartan_type.is_affine():
3790
+ if index_set == self.parent().index_set():
3791
+ # If the full affine Weyl group is being used
3792
+ level = self.level()
3793
+ if level > 0:
3794
+ if not positive:
3795
+ raise ValueError("%s is not in the orbit of the fundamental chamber" % (self))
3796
+ elif level < 0:
3797
+ if positive:
3798
+ raise ValueError("%s is not in the orbit of the negative of the fundamental chamber" % (self))
3799
+ elif not (self == self.parent().zero()):
3800
+ # nonzero level zero weight
3801
+ if positive:
3802
+ raise ValueError("%s is not in the orbit of the fundamental chamber" % (self))
3803
+ else:
3804
+ raise ValueError("%s is not in the orbit of the negative of the fundamental chamber" % (self))
3805
+ if reduced_word:
3806
+ direction = []
3807
+ while True:
3808
+ # The first index where it is *not* yet on the positive side
3809
+ i = self.first_descent(index_set, positive=(not positive))
3810
+ if i is None:
3811
+ if reduced_word:
3812
+ return self, direction
3813
+ else:
3814
+ return self
3815
+ else:
3816
+ if reduced_word:
3817
+ direction.append(i)
3818
+ self = self.simple_reflection(i)
3819
+
3820
+ def reduced_word(self, index_set=None, positive=True):
3821
+ r"""
3822
+ Return a reduced word for the inverse of the shortest Weyl group element that sends the vector ``self`` into the dominant chamber.
3823
+
3824
+ With the ``index_set`` optional parameter, this is done with
3825
+ respect to the corresponding parabolic subgroup.
3826
+
3827
+ If ``positive`` is False, use the antidominant chamber instead.
3828
+
3829
+ EXAMPLES::
3830
+
3831
+ sage: space = RootSystem(['A',5]).weight_space()
3832
+ sage: alpha = RootSystem(['A',5]).weight_space().simple_roots() # needs sage.graphs
3833
+ sage: alpha[1].reduced_word() # needs sage.graphs
3834
+ [2, 3, 4, 5]
3835
+ sage: alpha[1].reduced_word([1,2]) # needs sage.graphs
3836
+ [2]
3837
+ """
3838
+ return self.to_dominant_chamber(index_set=index_set,positive=positive,reduced_word=True)[1]
3839
+
3840
+ def is_dominant(self, index_set=None, positive=True):
3841
+ r"""
3842
+ Return whether ``self`` is dominant.
3843
+
3844
+ This is done with respect to the sub--root system indicated by the subset of Dynkin nodes
3845
+ ``index_set``. If ``index_set`` is ``None``, then the entire Dynkin node set is used.
3846
+ If positive is ``False``, then the dominance condition is replaced by antidominance.
3847
+
3848
+ EXAMPLES::
3849
+
3850
+ sage: L = RootSystem(['A',2]).ambient_lattice()
3851
+ sage: Lambda = L.fundamental_weights()
3852
+ sage: [x.is_dominant() for x in Lambda]
3853
+ [True, True]
3854
+ sage: [x.is_dominant(positive=False) for x in Lambda]
3855
+ [False, False]
3856
+ sage: (Lambda[1]-Lambda[2]).is_dominant()
3857
+ False
3858
+ sage: (-Lambda[1]+Lambda[2]).is_dominant()
3859
+ False
3860
+ sage: (Lambda[1]-Lambda[2]).is_dominant([1])
3861
+ True
3862
+ sage: (Lambda[1]-Lambda[2]).is_dominant([2])
3863
+ False
3864
+ sage: [x.is_dominant() for x in L.roots()]
3865
+ [False, True, False, False, False, False]
3866
+ sage: [x.is_dominant(positive=False) for x in L.roots()]
3867
+ [False, False, False, False, True, False]
3868
+ """
3869
+ return self.first_descent(index_set, not positive) is None
3870
+
3871
+ def is_dominant_weight(self): # Or is_dominant_integral_weight?
3872
+ """
3873
+ Test whether ``self`` is a dominant element of the weight lattice.
3874
+
3875
+ EXAMPLES::
3876
+
3877
+ sage: L = RootSystem(['A',2]).ambient_lattice()
3878
+ sage: Lambda = L.fundamental_weights()
3879
+ sage: [x.is_dominant() for x in Lambda]
3880
+ [True, True]
3881
+ sage: (3*Lambda[1]+Lambda[2]).is_dominant()
3882
+ True
3883
+ sage: (Lambda[1]-Lambda[2]).is_dominant()
3884
+ False
3885
+ sage: (-Lambda[1]+Lambda[2]).is_dominant()
3886
+ False
3887
+
3888
+ Tests that the scalar products with the coroots are all
3889
+ nonnegative integers. For example, if `x` is the sum of a
3890
+ dominant element of the weight lattice plus some other element
3891
+ orthogonal to all coroots, then the implementation correctly
3892
+ reports `x` to be a dominant weight::
3893
+
3894
+ sage: x = Lambda[1] + L([-1,-1,-1])
3895
+ sage: x.is_dominant_weight()
3896
+ True
3897
+ """
3898
+ alphacheck = self.parent().simple_coroots()
3899
+ from sage.rings.semirings.non_negative_integer_semiring import NN
3900
+ return all(self.inner_product(alphacheck[i]) in NN
3901
+ for i in self.parent().index_set())
3902
+
3903
+ def is_verma_dominant(self, positive=True):
3904
+ r"""
3905
+ Return if ``self`` is Verma dominant.
3906
+
3907
+ A weight `\lambda` is *Verma dominant* if
3908
+
3909
+ .. MATH::
3910
+
3911
+ \langle \lambda + \rho, \alpha^{\vee} \rangle \notin \ZZ_{<0}
3912
+
3913
+ for all positive roots `\alpha`. Note that begin Verma dominant does
3914
+ *not* imply that `\langle \lambda+\rho, \alpha^{\vee} \rangle \geq 0`
3915
+ for any positive root `\alpha`. This is used to determine if
3916
+ a Verma module is simple or projective.
3917
+
3918
+ INPUT:
3919
+
3920
+ - ``positive`` -- boolean (default: ``True``); if ``False``, then
3921
+ this checks if the weight is Verma anti-dominant, where
3922
+ `\ZZ_{<0}` is replaced with `\ZZ_{>0}` in the definition.
3923
+
3924
+ EXAMPLES::
3925
+
3926
+ sage: # needs sage.graphs
3927
+ sage: P = RootSystem(['A', 3]).weight_space()
3928
+ sage: La = P.fundamental_weights()
3929
+ sage: alphacheck = P.coroot_lattice().positive_roots()
3930
+ sage: rho = P.rho()
3931
+ sage: (La[1] + 2*La[2]).is_verma_dominant()
3932
+ True
3933
+ sage: la = La[1] - 3/2*La[3] - rho
3934
+ sage: la.is_verma_dominant()
3935
+ True
3936
+ sage: la.is_verma_dominant(positive=False)
3937
+ False
3938
+ sage: [(la+rho).scalar(coroot) for coroot in alphacheck]
3939
+ [1, 0, -3/2, 1, -3/2, -1/2]
3940
+ sage: mu = 1/2*La[1] - 3/2*La[3] - rho
3941
+ sage: mu.is_verma_dominant()
3942
+ False
3943
+ sage: mu.is_verma_dominant(positive=False)
3944
+ True
3945
+ sage: [(mu+rho).scalar(coroot) for coroot in alphacheck]
3946
+ [1/2, 0, -3/2, 1/2, -3/2, -1]
3947
+ """
3948
+ P = self.parent()
3949
+ alphacheck = P.coroot_lattice().positive_roots()
3950
+ wt = self + P.rho()
3951
+ if positive:
3952
+ return not any((c := wt.scalar(ac)) in ZZ and c < 0 for ac in alphacheck)
3953
+ return not any((c := wt.scalar(ac)) in ZZ and c > 0 for ac in alphacheck)
3954
+
3955
+ ##########################################################################
3956
+ # weak order
3957
+ ##########################################################################
3958
+
3959
+ def succ(self, index_set=None):
3960
+ r"""
3961
+ Return the immediate successors of ``self`` for the weak order.
3962
+
3963
+ INPUT:
3964
+
3965
+ - ``index_set`` -- a subset (as a list or iterable) of the
3966
+ nodes of the Dynkin diagram; (default: ``None`` for all of them)
3967
+
3968
+ If ``index_set`` is specified, the successors for the
3969
+ corresponding parabolic subsystem are returned.
3970
+
3971
+ EXAMPLES::
3972
+
3973
+ sage: # needs sage.graphs
3974
+ sage: L = RootSystem(['A',3]).weight_lattice()
3975
+ sage: Lambda = L.fundamental_weights()
3976
+ sage: Lambda[1].succ()
3977
+ [-Lambda[1] + Lambda[2]]
3978
+ sage: L.rho().succ()
3979
+ [-Lambda[1] + 2*Lambda[2] + Lambda[3],
3980
+ 2*Lambda[1] - Lambda[2] + 2*Lambda[3],
3981
+ Lambda[1] + 2*Lambda[2] - Lambda[3]]
3982
+ sage: (-L.rho()).succ()
3983
+ []
3984
+ sage: L.rho().succ(index_set=[1])
3985
+ [-Lambda[1] + 2*Lambda[2] + Lambda[3]]
3986
+ sage: L.rho().succ(index_set=[2])
3987
+ [2*Lambda[1] - Lambda[2] + 2*Lambda[3]]
3988
+ """
3989
+ return [ self.simple_reflection(i) for i in self.descents(index_set=index_set, positive=True) ]
3990
+
3991
+ def pred(self, index_set=None):
3992
+ r"""
3993
+ Return the immediate predecessors of ``self`` for the weak order.
3994
+
3995
+ INPUT:
3996
+
3997
+ - ``index_set`` -- a subset (as a list or iterable) of the
3998
+ nodes of the Dynkin diagram; (default: ``None`` for all of them)
3999
+
4000
+ If ``index_set`` is specified, the successors for the
4001
+ corresponding parabolic subsystem are returned.
4002
+
4003
+ EXAMPLES::
4004
+
4005
+ sage: L = RootSystem(['A',3]).weight_lattice()
4006
+ sage: Lambda = L.fundamental_weights()
4007
+ sage: Lambda[1].pred()
4008
+ []
4009
+ sage: L.rho().pred()
4010
+ []
4011
+ sage: (-L.rho()).pred() # needs sage.graphs
4012
+ [Lambda[1] - 2*Lambda[2] - Lambda[3],
4013
+ -2*Lambda[1] + Lambda[2] - 2*Lambda[3],
4014
+ -Lambda[1] - 2*Lambda[2] + Lambda[3]]
4015
+ sage: (-L.rho()).pred(index_set=[1]) # needs sage.graphs
4016
+ [Lambda[1] - 2*Lambda[2] - Lambda[3]]
4017
+ """
4018
+ return [ self.simple_reflection(i) for i in self.descents(index_set) ]
4019
+
4020
+ def greater(self):
4021
+ r"""
4022
+ Return the elements in the orbit of ``self`` which are
4023
+ greater than ``self`` in the weak order.
4024
+
4025
+ EXAMPLES::
4026
+
4027
+ sage: L = RootSystem(['A',3]).ambient_lattice()
4028
+ sage: e = L.basis()
4029
+ sage: e[2].greater()
4030
+ [(0, 0, 1, 0), (0, 0, 0, 1)]
4031
+ sage: len(L.rho().greater())
4032
+ 24
4033
+ sage: len((-L.rho()).greater())
4034
+ 1
4035
+ sage: sorted([len(x.greater()) for x in L.rho().orbit()])
4036
+ [1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 8, 8, 8, 8, 12, 12, 12, 24]
4037
+ """
4038
+ R = RecursivelyEnumeratedSet([self], attrcall('succ'), structure=None)
4039
+ return list(R.naive_search_iterator())
4040
+
4041
+ def smaller(self):
4042
+ r"""
4043
+ Return the elements in the orbit of ``self`` which are
4044
+ smaller than ``self`` in the weak order.
4045
+
4046
+ EXAMPLES::
4047
+
4048
+ sage: L = RootSystem(['A',3]).ambient_lattice()
4049
+ sage: e = L.basis()
4050
+ sage: e[2].smaller()
4051
+ [(0, 0, 1, 0), (0, 1, 0, 0), (1, 0, 0, 0)]
4052
+ sage: len(L.rho().smaller())
4053
+ 1
4054
+ sage: len((-L.rho()).smaller())
4055
+ 24
4056
+ sage: sorted([len(x.smaller()) for x in L.rho().orbit()])
4057
+ [1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 8, 8, 8, 8, 12, 12, 12, 24]
4058
+ """
4059
+ R = RecursivelyEnumeratedSet([self], attrcall('pred'), structure=None)
4060
+ return list(R.naive_search_iterator())
4061
+
4062
+ def extraspecial_pair(self):
4063
+ r"""
4064
+ Return the extraspecial pair of ``self`` under the ordering
4065
+ defined by
4066
+ :meth:`~sage.combinat.root_system.root_lattice_realizations.RootLatticeRealizations.ParentMethods.positive_roots_by_height`.
4067
+
4068
+ The *extraspecial pair* of a positive root `\gamma` with some total
4069
+ ordering `<` of the root lattice that respects height is the pair
4070
+ of positive roots `(\alpha, \beta)` such that `\gamma = \alpha +
4071
+ \beta` and `\alpha` is as small as possible.
4072
+
4073
+ EXAMPLES::
4074
+
4075
+ sage: Q = RootSystem(['G', 2]).root_lattice()
4076
+ sage: Q.highest_root().extraspecial_pair() # needs sage.graphs
4077
+ (alpha[2], 3*alpha[1] + alpha[2])
4078
+ """
4079
+ if self.is_positive_root():
4080
+ r = self
4081
+ else:
4082
+ r = -self
4083
+ p_roots = self.parent().positive_roots_by_height()
4084
+ # We won't need any roots higher than us
4085
+ p_roots = p_roots[:p_roots.index(r)]
4086
+ for i, a in enumerate(p_roots):
4087
+ for b in p_roots[i + 1:]:
4088
+ if a + b == r:
4089
+ return (a, b)
4090
+ raise ValueError("Unable to find an extraspecial pair")
4091
+
4092
+ def height(self):
4093
+ r"""
4094
+ Return the height of ``self``.
4095
+
4096
+ The height of a root `\alpha = \sum_i a_i \alpha_i` is defined
4097
+ to be `h(\alpha) := \sum_i a_i`.
4098
+
4099
+ EXAMPLES::
4100
+
4101
+ sage: Q = RootSystem(['G', 2]).root_lattice()
4102
+ sage: Q.highest_root().height() # needs sage.graphs
4103
+ 5
4104
+ """
4105
+ return sum(self.coefficients())
4106
+
4107
+ ##########################################################################
4108
+ # Level
4109
+ ##########################################################################
4110
+
4111
+ def level(self):
4112
+ """
4113
+ EXAMPLES::
4114
+
4115
+ sage: L = RootSystem(['A',2,1]).weight_lattice()
4116
+ sage: L.rho().level() # needs sage.graphs
4117
+ 3
4118
+ """
4119
+ if not self.parent().cartan_type().is_affine():
4120
+ raise ValueError("%s does not belong to a lattice of affine Cartan type" % self)
4121
+ return self.scalar(self.parent().null_coroot())
4122
+
4123
+ @cached_in_parent_method
4124
+ def to_simple_root(self, reduced_word=False):
4125
+ r"""
4126
+ Return (the index of) a simple root in the orbit of the positive root ``self``.
4127
+
4128
+ INPUT:
4129
+
4130
+ - ``self`` -- a positive root
4131
+ - ``reduced_word`` -- boolean (default: ``False``)
4132
+
4133
+ OUTPUT:
4134
+
4135
+ - The index `i` of a simple root `\alpha_i`.
4136
+ If ``reduced_word`` is ``True``, this returns instead a pair
4137
+ ``(i, word)``, where word is a sequence of reflections
4138
+ mapping `\alpha_i` up the root poset to ``self``.
4139
+
4140
+ EXAMPLES::
4141
+
4142
+ sage: L = RootSystem(["A",3]).root_lattice()
4143
+ sage: positive_roots = L.positive_roots()
4144
+ sage: for alpha in sorted(positive_roots): # needs sage.graphs
4145
+ ....: print("{} {}".format(alpha, alpha.to_simple_root()))
4146
+ alpha[1] 1
4147
+ alpha[1] + alpha[2] 2
4148
+ alpha[1] + alpha[2] + alpha[3] 3
4149
+ alpha[2] 2
4150
+ alpha[2] + alpha[3] 3
4151
+ alpha[3] 3
4152
+ sage: for alpha in sorted(positive_roots): # needs sage.graphs
4153
+ ....: print("{} {}".format(alpha, alpha.to_simple_root(reduced_word=True)))
4154
+ alpha[1] (1, ())
4155
+ alpha[1] + alpha[2] (2, (1,))
4156
+ alpha[1] + alpha[2] + alpha[3] (3, (1, 2))
4157
+ alpha[2] (2, ())
4158
+ alpha[2] + alpha[3] (3, (2,))
4159
+ alpha[3] (3, ())
4160
+
4161
+ ALGORITHM:
4162
+
4163
+ This method walks from ``self`` down to the antidominant
4164
+ chamber by applying successively the simple reflection
4165
+ given by the first descent. Since ``self`` is a positive
4166
+ root, each step goes down the root poset, and one must
4167
+ eventually cross a simple root `\alpha_i`.
4168
+
4169
+ .. SEEALSO::
4170
+
4171
+ - :meth:`first_descent`
4172
+ - :meth:`to_dominant_chamber`
4173
+
4174
+ .. WARNING::
4175
+
4176
+ The behavior is not specified if the input is not a
4177
+ positive root. For a finite root system, this is
4178
+ currently caught (albeit with a not perfect message)::
4179
+
4180
+ sage: alpha = L.simple_roots() # needs sage.graphs
4181
+ sage: (2*alpha[1]).to_simple_root() # needs sage.graphs
4182
+ Traceback (most recent call last):
4183
+ ...
4184
+ ValueError: -2*alpha[1] - 2*alpha[2] - 2*alpha[3] is not a positive root
4185
+
4186
+ For an infinite root system, this method may run into
4187
+ an infinite recursion if the input is not a positive
4188
+ root.
4189
+ """
4190
+ F = self.parent().simple_roots().inverse_family()
4191
+ try:
4192
+ j = F[self]
4193
+ if reduced_word:
4194
+ return (j, ())
4195
+ else:
4196
+ return j
4197
+ except KeyError:
4198
+ pass
4199
+ j = self.first_descent(positive=True)
4200
+ if j is None:
4201
+ raise ValueError("%s is not a positive root" % self)
4202
+ result = self.simple_reflection(j).to_simple_root(reduced_word=reduced_word)
4203
+ if reduced_word:
4204
+ return (result[0], (j,) + result[1])
4205
+ else:
4206
+ return result
4207
+
4208
+ @cached_in_parent_method
4209
+ def associated_reflection(self):
4210
+ r"""
4211
+ Given a positive root ``self``, return a reduced word for the reflection orthogonal to ``self``.
4212
+
4213
+ Since the answer is cached, it is a tuple instead of a list.
4214
+
4215
+ EXAMPLES::
4216
+
4217
+ sage: C3_rl = RootSystem(['C',3]).root_lattice() # needs sage.graphs
4218
+ sage: C3_rl.simple_root(3).weyl_action([1,2]).associated_reflection() # needs sage.graphs
4219
+ (1, 2, 3, 2, 1)
4220
+ sage: C3_rl.simple_root(2).associated_reflection() # needs sage.graphs
4221
+ (2,)
4222
+ """
4223
+ i, reduced_word = self.to_simple_root(reduced_word=True)
4224
+ return reduced_word + (i,) + tuple(reversed(reduced_word))
4225
+
4226
+ def translation(self, x):
4227
+ """
4228
+ Return `x` translated by `t`, that is, `x+level(x) t`.
4229
+
4230
+ INPUT:
4231
+
4232
+ - ``self`` -- an element `t` at level `0`
4233
+ - ``x`` -- an element of the same space
4234
+
4235
+ EXAMPLES::
4236
+
4237
+ sage: L = RootSystem(['A',2,1]).weight_lattice()
4238
+ sage: alpha = L.simple_roots() # needs sage.graphs
4239
+ sage: Lambda = L.fundamental_weights() # needs sage.graphs
4240
+ sage: t = alpha[2] # needs sage.graphs
4241
+
4242
+ Let us look at the translation of an element of level `1`::
4243
+
4244
+ sage: Lambda[1].level() # needs sage.graphs
4245
+ 1
4246
+ sage: t.translation(Lambda[1]) # needs sage.graphs
4247
+ -Lambda[0] + 2*Lambda[2]
4248
+ sage: Lambda[1] + t # needs sage.graphs
4249
+ -Lambda[0] + 2*Lambda[2]
4250
+
4251
+ and of an element of level `0`::
4252
+
4253
+ sage: alpha[1].level() # needs sage.graphs
4254
+ 0
4255
+ sage: t.translation(alpha [1]) # needs sage.graphs
4256
+ -Lambda[0] + 2*Lambda[1] - Lambda[2]
4257
+ sage: alpha[1] + 0*t # needs sage.graphs
4258
+ -Lambda[0] + 2*Lambda[1] - Lambda[2]
4259
+
4260
+ The arguments are given in this seemingly unnatural order to
4261
+ make it easy to construct the translation function::
4262
+
4263
+ sage: f = t.translation # needs sage.graphs
4264
+ sage: f(Lambda[1]) # needs sage.graphs
4265
+ -Lambda[0] + 2*Lambda[2]
4266
+ """
4267
+ if not self.level().is_zero():
4268
+ raise ValueError(f"{self} is not of level zero")
4269
+ return x + x.level() * self
4270
+
4271
+ def weyl_action(self, element, inverse=False):
4272
+ r"""
4273
+ Act on ``self`` by an element of the Coxeter or Weyl group.
4274
+
4275
+ INPUT:
4276
+
4277
+ - ``element`` -- an element of a Coxeter or Weyl group
4278
+ of the same Cartan type, or a tuple or a list (such as a
4279
+ reduced word) of elements from the index set
4280
+
4281
+ - ``inverse`` -- boolean (default: ``False``); whether to
4282
+ act by the inverse element
4283
+
4284
+ EXAMPLES::
4285
+
4286
+ sage: wl = RootSystem(['A',3]).weight_lattice()
4287
+ sage: mu = wl.from_vector(vector([1,0,-2]))
4288
+ sage: mu
4289
+ Lambda[1] - 2*Lambda[3]
4290
+ sage: mudom, rw = mu.to_dominant_chamber(positive=False, # needs sage.graphs
4291
+ ....: reduced_word=True)
4292
+ sage: mudom, rw # needs sage.graphs
4293
+ (-Lambda[2] - Lambda[3], [1, 2])
4294
+
4295
+ Acting by a (reduced) word::
4296
+
4297
+ sage: mudom.weyl_action(rw) # needs sage.graphs
4298
+ Lambda[1] - 2*Lambda[3]
4299
+ sage: mu.weyl_action(rw, inverse=True) # needs sage.graphs
4300
+ -Lambda[2] - Lambda[3]
4301
+
4302
+ Acting by an element of the Coxeter or Weyl group on a vector in its own
4303
+ lattice of definition (implemented by matrix multiplication on a vector)::
4304
+
4305
+ sage: w = wl.weyl_group().from_reduced_word([1, 2]) # needs sage.graphs sage.libs.gap
4306
+ sage: mudom.weyl_action(w) # needs sage.graphs sage.libs.gap
4307
+ Lambda[1] - 2*Lambda[3]
4308
+
4309
+ Acting by an element of an isomorphic Coxeter or Weyl group (implemented by the
4310
+ action of a corresponding reduced word)::
4311
+
4312
+ sage: # needs sage.libs.gap
4313
+ sage: W = WeylGroup(['A',3], prefix='s')
4314
+ sage: w = W.from_reduced_word([1, 2])
4315
+ sage: wl.weyl_group() == W # needs sage.graphs
4316
+ False
4317
+ sage: mudom.weyl_action(w) # needs sage.graphs
4318
+ Lambda[1] - 2*Lambda[3]
4319
+ """
4320
+ # TODO, some day: accept an iterator
4321
+ if isinstance(element, (tuple, list, range)):
4322
+ # Action by a (reduced) word
4323
+ the_word = list(element)
4324
+ I = self.parent().index_set()
4325
+ if not all(i in I for i in the_word):
4326
+ raise ValueError("Not all members of %s are in the index set of the %s" % (element, self.parent()))
4327
+ else:
4328
+ if not isinstance(element, Element):
4329
+ raise TypeError("%s should be an element of a Coxeter group" % (element))
4330
+ W = element.parent()
4331
+ if W is self.parent().weyl_group():
4332
+ # Action by an element of the Coxeter or Weyl group of ``self``
4333
+ if inverse is True:
4334
+ element = element.inverse()
4335
+ return element.action(self)
4336
+ else:
4337
+ # Action by an element of an isomorphic Coxeter or Weyl group
4338
+ if not (W in CoxeterGroups() and W.cartan_type() == self.parent().cartan_type()):
4339
+ raise TypeError("%s should be an element of a Coxeter group of type %s" % (element, self.parent().cartan_type()))
4340
+ the_word = element.reduced_word()
4341
+ if inverse is False:
4342
+ the_word.reverse()
4343
+ for i in the_word:
4344
+ self = self.simple_reflection(i)
4345
+ return self
4346
+
4347
+ def weyl_stabilizer(self, index_set=None):
4348
+ r"""
4349
+ Return the subset of Dynkin nodes whose reflections fix ``self``.
4350
+
4351
+ If ``index_set`` is not ``None``, only consider nodes in this set.
4352
+ Note that if ``self`` is dominant or antidominant, then its stabilizer is the
4353
+ parabolic subgroup defined by the returned node set.
4354
+
4355
+ EXAMPLES::
4356
+
4357
+ sage: wl = RootSystem(['A',2,1]).weight_lattice(extended=True)
4358
+ sage: al = wl.null_root() # needs sage.graphs
4359
+ sage: al.weyl_stabilizer() # needs sage.graphs
4360
+ [0, 1, 2]
4361
+ sage: wl = RootSystem(['A',4]).weight_lattice()
4362
+ sage: mu = wl.from_vector(vector([1,1,0,0]))
4363
+ sage: mu.weyl_stabilizer()
4364
+ [3, 4]
4365
+ sage: mu.weyl_stabilizer(index_set = [1,2,3])
4366
+ [3]
4367
+ """
4368
+ if index_set is None:
4369
+ index_set = self.parent().cartan_type().index_set()
4370
+ alphavee = self.parent().coroot_lattice().basis()
4371
+ return [i for i in index_set if self.scalar(alphavee[i]) == 0]
4372
+
4373
+ def dot_action(self, w, inverse=False):
4374
+ r"""
4375
+ Act on ``self`` by ``w`` using the dot or affine action.
4376
+
4377
+ Let `w` be an element of the Weyl group. The *dot action*
4378
+ or *affine action* is given by:
4379
+
4380
+ .. MATH::
4381
+
4382
+ w \bullet \lambda = w (\lambda + \rho) - \rho,
4383
+
4384
+ where `\rho` is the sum of the fundamental weights.
4385
+
4386
+ INPUT:
4387
+
4388
+ - ``w`` -- an element of a Coxeter or Weyl group of
4389
+ the same Cartan type, or a tuple or a list (such
4390
+ as a reduced word) of elements from the index set
4391
+
4392
+ - ``inverse`` -- boolean (default: ``False``); whether
4393
+ to act by the inverse element
4394
+
4395
+ EXAMPLES::
4396
+
4397
+ sage: P = RootSystem(['B',3]).weight_lattice()
4398
+ sage: La = P.fundamental_weights()
4399
+ sage: mu = La[1] + 2*La[2] - 3*La[3]
4400
+ sage: mu.dot_action([1]) # needs sage.graphs
4401
+ -3*Lambda[1] + 4*Lambda[2] - 3*Lambda[3]
4402
+ sage: mu.dot_action([3]) # needs sage.graphs
4403
+ Lambda[1] + Lambda[3]
4404
+ sage: mu.dot_action([1,2,3]) # needs sage.graphs
4405
+ -4*Lambda[1] + Lambda[2] + 3*Lambda[3]
4406
+
4407
+ We check that the origin of this action is at `-\rho`::
4408
+
4409
+ sage: all((-P.rho()).dot_action([i]) == -P.rho() # needs sage.graphs
4410
+ ....: for i in P.index_set())
4411
+ True
4412
+
4413
+ REFERENCES:
4414
+
4415
+ - :wikipedia:`Affine_action`
4416
+ """
4417
+ rho = self.parent().rho()
4418
+ return (self + rho).weyl_action(w, inverse=inverse) - rho
4419
+
4420
+ def is_parabolic_root(self, index_set):
4421
+ r"""
4422
+ Return whether ``root`` is in the parabolic subsystem with Dynkin nodes ``index_set``.
4423
+
4424
+ This assumes that ``self`` is a root.
4425
+
4426
+ INPUT:
4427
+
4428
+ - ``index_set`` -- the Dynkin node set of the parabolic subsystem
4429
+
4430
+ .. TODO:: This implementation is only valid in the root or weight lattice
4431
+
4432
+ EXAMPLES::
4433
+
4434
+ sage: alpha = RootSystem(['A',3]).root_lattice().from_vector(vector([1,1,0]))
4435
+ sage: alpha.is_parabolic_root([1,3])
4436
+ False
4437
+ sage: alpha.is_parabolic_root([1,2])
4438
+ True
4439
+ sage: alpha.is_parabolic_root([2])
4440
+ False
4441
+ """
4442
+ for i in self.support():
4443
+ if i not in index_set:
4444
+ return False
4445
+ return True
4446
+
4447
+ def is_short_root(self):
4448
+ r"""
4449
+ Return ``True`` if ``self`` is a short (real) root.
4450
+
4451
+ Returns ``False`` unless the parent is an irreducible root system of finite type
4452
+ having two root lengths and ``self`` is of the shorter length.
4453
+ There is no check of whether ``self`` is actually a root.
4454
+
4455
+ EXAMPLES::
4456
+
4457
+ sage: # needs sage.graphs
4458
+ sage: Q = RootSystem(['C',2]).root_lattice()
4459
+ sage: al = Q.simple_root(1).weyl_action([1,2]); al
4460
+ alpha[1] + alpha[2]
4461
+ sage: al.is_short_root()
4462
+ True
4463
+ sage: bt = Q.simple_root(2).weyl_action([2,1,2]); bt
4464
+ -2*alpha[1] - alpha[2]
4465
+ sage: bt.is_short_root()
4466
+ False
4467
+ sage: RootSystem(['A',2]).root_lattice().simple_root(1).is_short_root()
4468
+ False
4469
+
4470
+ An example in affine type::
4471
+
4472
+ sage: # needs sage.graphs
4473
+ sage: Q = RootSystem(['B',2,1]).root_lattice()
4474
+ sage: alpha = Q.simple_roots()
4475
+ sage: alpha[0].is_short_root()
4476
+ False
4477
+ sage: alpha[1].is_short_root()
4478
+ False
4479
+ sage: alpha[2].is_short_root()
4480
+ True
4481
+ """
4482
+ ct = self.parent().cartan_type()
4483
+ if not ct.is_irreducible():
4484
+ raise ValueError("Cartan type needs to be irreducible!")
4485
+ if not ct.is_finite():
4486
+ return self.norm_squared() == min(alpha.norm_squared()
4487
+ for alpha in self.parent().simple_roots())
4488
+ L = self.parent().root_system.ambient_space() # uses peculiarities of ambient embedding
4489
+ ls = L(self)
4490
+ return ls.scalar(ls) < L._maximum_root_length()
4491
+ #Alternative implementation
4492
+ #if ct.is_simply_laced():
4493
+ # return False
4494
+ #L = self.parent().root_system.ambient_space() # uses peculiarities of ambient embedding
4495
+ #ls = L(self)
4496
+ #lensq = ls.scalar(ls)
4497
+ #if lensq > 2:
4498
+ # return False
4499
+ #if lensq == 1:
4500
+ # return True
4501
+ ## now only types BCFG remain and the square length is 2
4502
+ #if ct.type() == 'C' or ct.type() == 'G':
4503
+ # return True
4504
+ #return False
4505
+
4506
+ def to_dual_type_cospace(self):
4507
+ r"""
4508
+ Map ``self`` to the dual type cospace.
4509
+
4510
+ For example, if ``self`` is in the root lattice of type `['B',2]`, send it to
4511
+ the coroot lattice of type `['C',2]`.
4512
+
4513
+ EXAMPLES::
4514
+
4515
+ sage: v = CartanType(['C',3]).root_system().weight_lattice().an_element(); v
4516
+ 2*Lambda[1] + 2*Lambda[2] + 3*Lambda[3]
4517
+ sage: w = v.to_dual_type_cospace(); w
4518
+ 2*Lambdacheck[1] + 2*Lambdacheck[2] + 3*Lambdacheck[3]
4519
+ sage: w.parent()
4520
+ Coweight lattice of the Root system of type ['B', 3]
4521
+ """
4522
+ return self.parent().dual_type_cospace().from_vector(self.to_vector())
4523
+
4524
+ def to_classical(self):
4525
+ r"""
4526
+ Map ``self`` to the classical lattice/space.
4527
+
4528
+ Only makes sense for affine type.
4529
+
4530
+ EXAMPLES::
4531
+
4532
+ sage: R = CartanType(['A',3,1]).root_system()
4533
+ sage: alpha = R.root_lattice().an_element(); alpha
4534
+ 2*alpha[0] + 2*alpha[1] + 3*alpha[2]
4535
+ sage: alb = alpha.to_classical(); alb # needs sage.graphs
4536
+ alpha[2] - 2*alpha[3]
4537
+ sage: alb.parent() # needs sage.graphs
4538
+ Root lattice of the Root system of type ['A', 3]
4539
+ sage: v = R.ambient_space().an_element(); v
4540
+ 2*e[0] + 2*e[1] + 3*e[2]
4541
+ sage: v.to_classical() # needs sage.graphs
4542
+ (2, 2, 3, 0)
4543
+ """
4544
+ return self.parent().classical()(self)
4545
+
4546
+ @abstract_method(optional=True)
4547
+ def to_ambient(self):
4548
+ r"""
4549
+ Map ``self`` to the ambient space.
4550
+
4551
+ EXAMPLES::
4552
+
4553
+ sage: B4_rs = CartanType(['B',4]).root_system()
4554
+ sage: alpha = B4_rs.root_lattice().an_element(); alpha
4555
+ 2*alpha[1] + 2*alpha[2] + 3*alpha[3]
4556
+ sage: alpha.to_ambient()
4557
+ (2, 0, 1, -3)
4558
+ sage: mu = B4_rs.weight_lattice().an_element(); mu
4559
+ 2*Lambda[1] + 2*Lambda[2] + 3*Lambda[3]
4560
+ sage: mu.to_ambient()
4561
+ (7, 5, 3, 0)
4562
+ sage: v = B4_rs.ambient_space().an_element(); v
4563
+ (2, 2, 3, 0)
4564
+ sage: v.to_ambient()
4565
+ (2, 2, 3, 0)
4566
+ sage: alphavee = B4_rs.coroot_lattice().an_element(); alphavee
4567
+ 2*alphacheck[1] + 2*alphacheck[2] + 3*alphacheck[3]
4568
+ sage: alphavee.to_ambient()
4569
+ (2, 0, 1, -3)
4570
+ """
4571
+
4572
+ def is_long_root(self):
4573
+ """
4574
+ Return ``True`` if ``self`` is a long (real) root.
4575
+
4576
+ EXAMPLES::
4577
+
4578
+ sage: Q = RootSystem(['B',2,1]).root_lattice()
4579
+ sage: alpha = Q.simple_roots()
4580
+ sage: alpha[0].is_long_root() # needs sage.graphs
4581
+ True
4582
+ sage: alpha[1].is_long_root() # needs sage.graphs
4583
+ True
4584
+ sage: alpha[2].is_long_root() # needs sage.graphs
4585
+ False
4586
+ """
4587
+ alpha = self.parent().simple_roots()
4588
+ norm_sq = self.norm_squared()
4589
+ return max(sroot.norm_squared() for sroot in alpha) == norm_sq \
4590
+ and all(c * alpha[i].norm_squared() / norm_sq in ZZ for i,c in self)
4591
+
4592
+ def is_imaginary_root(self):
4593
+ r"""
4594
+ Return ``True`` if ``self`` is an imaginary root.
4595
+
4596
+ A root `\alpha` is imaginary if it is not `W`-conjugate
4597
+ to a simple root where `W` is the corresponding Weyl group.
4598
+
4599
+ EXAMPLES::
4600
+
4601
+ sage: Q = RootSystem(['B',2,1]).root_lattice()
4602
+ sage: alpha = Q.simple_roots()
4603
+ sage: alpha[0].is_imaginary_root() # needs sage.graphs
4604
+ False
4605
+ sage: elt = alpha[0] + alpha[1] + 2*alpha[2]
4606
+ sage: elt.is_imaginary_root() # needs sage.graphs
4607
+ True
4608
+ """
4609
+ return self.norm_squared() <= 0
4610
+
4611
+ def is_real_root(self):
4612
+ r"""
4613
+ Return ``True`` if ``self`` is a real root.
4614
+
4615
+ A root `\alpha` is real if it is `W`-conjugate to a simple
4616
+ root where `W` is the corresponding Weyl group.
4617
+
4618
+ EXAMPLES::
4619
+
4620
+ sage: Q = RootSystem(['B',2,1]).root_lattice()
4621
+ sage: alpha = Q.simple_roots()
4622
+ sage: alpha[0].is_real_root() # needs sage.graphs
4623
+ True
4624
+ sage: elt = alpha[0] + alpha[1] + 2*alpha[2]
4625
+ sage: elt.is_real_root() # needs sage.graphs
4626
+ False
4627
+ """
4628
+ return self.norm_squared() > 0