passagemath-modules 10.6.31rc3__cp314-cp314-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-modules might be problematic. Click here for more details.
- passagemath_modules-10.6.31rc3.dist-info/METADATA +281 -0
- passagemath_modules-10.6.31rc3.dist-info/RECORD +807 -0
- passagemath_modules-10.6.31rc3.dist-info/WHEEL +5 -0
- passagemath_modules-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_modules.libs/libgcc_s-2d945d6c.so.1 +0 -0
- passagemath_modules.libs/libgfortran-67378ab2.so.5.0.0 +0 -0
- passagemath_modules.libs/libgmp-28992bcb.so.10.5.0 +0 -0
- passagemath_modules.libs/libgsl-23768756.so.28.0.0 +0 -0
- passagemath_modules.libs/libmpc-7897025b.so.3.3.1 +0 -0
- passagemath_modules.libs/libmpfr-e34bb864.so.6.2.1 +0 -0
- passagemath_modules.libs/libopenblasp-r0-503f0c35.3.29.so +0 -0
- sage/algebras/all__sagemath_modules.py +20 -0
- sage/algebras/catalog.py +148 -0
- sage/algebras/clifford_algebra.py +3107 -0
- sage/algebras/clifford_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/clifford_algebra_element.pxd +16 -0
- sage/algebras/clifford_algebra_element.pyx +997 -0
- sage/algebras/commutative_dga.py +4252 -0
- sage/algebras/exterior_algebra_groebner.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/exterior_algebra_groebner.pxd +55 -0
- sage/algebras/exterior_algebra_groebner.pyx +727 -0
- sage/algebras/finite_dimensional_algebras/all.py +2 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +1029 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pxd +12 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx +706 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py +196 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py +255 -0
- sage/algebras/finite_gca.py +528 -0
- sage/algebras/group_algebra.py +232 -0
- sage/algebras/lie_algebras/abelian.py +197 -0
- sage/algebras/lie_algebras/affine_lie_algebra.py +1213 -0
- sage/algebras/lie_algebras/all.py +25 -0
- sage/algebras/lie_algebras/all__sagemath_modules.py +1 -0
- sage/algebras/lie_algebras/bch.py +177 -0
- sage/algebras/lie_algebras/bgg_dual_module.py +1184 -0
- sage/algebras/lie_algebras/bgg_resolution.py +232 -0
- sage/algebras/lie_algebras/center_uea.py +767 -0
- sage/algebras/lie_algebras/classical_lie_algebra.py +2516 -0
- sage/algebras/lie_algebras/examples.py +683 -0
- sage/algebras/lie_algebras/free_lie_algebra.py +973 -0
- sage/algebras/lie_algebras/heisenberg.py +820 -0
- sage/algebras/lie_algebras/lie_algebra.py +1562 -0
- sage/algebras/lie_algebras/lie_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/lie_algebras/lie_algebra_element.pxd +68 -0
- sage/algebras/lie_algebras/lie_algebra_element.pyx +2122 -0
- sage/algebras/lie_algebras/morphism.py +661 -0
- sage/algebras/lie_algebras/nilpotent_lie_algebra.py +457 -0
- sage/algebras/lie_algebras/onsager.py +1324 -0
- sage/algebras/lie_algebras/poincare_birkhoff_witt.py +816 -0
- sage/algebras/lie_algebras/quotient.py +462 -0
- sage/algebras/lie_algebras/rank_two_heisenberg_virasoro.py +355 -0
- sage/algebras/lie_algebras/representation.py +1040 -0
- sage/algebras/lie_algebras/structure_coefficients.py +459 -0
- sage/algebras/lie_algebras/subalgebra.py +967 -0
- sage/algebras/lie_algebras/symplectic_derivation.py +289 -0
- sage/algebras/lie_algebras/verma_module.py +1630 -0
- sage/algebras/lie_algebras/virasoro.py +1186 -0
- sage/algebras/octonion_algebra.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/octonion_algebra.pxd +20 -0
- sage/algebras/octonion_algebra.pyx +987 -0
- sage/algebras/orlik_solomon.py +907 -0
- sage/algebras/orlik_terao.py +779 -0
- sage/algebras/steenrod/all.py +7 -0
- sage/algebras/steenrod/steenrod_algebra.py +4258 -0
- sage/algebras/steenrod/steenrod_algebra_bases.py +1179 -0
- sage/algebras/steenrod/steenrod_algebra_misc.py +1167 -0
- sage/algebras/steenrod/steenrod_algebra_mult.py +954 -0
- sage/algebras/weyl_algebra.py +1126 -0
- sage/all__sagemath_modules.py +62 -0
- sage/calculus/all__sagemath_modules.py +19 -0
- sage/calculus/expr.py +205 -0
- sage/calculus/integration.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/integration.pyx +698 -0
- sage/calculus/interpolation.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/interpolation.pxd +13 -0
- sage/calculus/interpolation.pyx +387 -0
- sage/calculus/interpolators.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/interpolators.pyx +326 -0
- sage/calculus/ode.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/ode.pxd +5 -0
- sage/calculus/ode.pyx +610 -0
- sage/calculus/riemann.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/riemann.pyx +1521 -0
- sage/calculus/test_sympy.py +201 -0
- sage/calculus/transforms/all.py +7 -0
- sage/calculus/transforms/dft.py +844 -0
- sage/calculus/transforms/dwt.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/transforms/dwt.pxd +7 -0
- sage/calculus/transforms/dwt.pyx +160 -0
- sage/calculus/transforms/fft.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/transforms/fft.pxd +12 -0
- sage/calculus/transforms/fft.pyx +487 -0
- sage/calculus/wester.py +662 -0
- sage/coding/abstract_code.py +1108 -0
- sage/coding/ag_code.py +868 -0
- sage/coding/ag_code_decoders.cpython-314-aarch64-linux-musl.so +0 -0
- sage/coding/ag_code_decoders.pyx +2639 -0
- sage/coding/all.py +15 -0
- sage/coding/bch_code.py +494 -0
- sage/coding/binary_code.cpython-314-aarch64-linux-musl.so +0 -0
- sage/coding/binary_code.pxd +124 -0
- sage/coding/binary_code.pyx +4139 -0
- sage/coding/bounds_catalog.py +43 -0
- sage/coding/channel.py +819 -0
- sage/coding/channels_catalog.py +29 -0
- sage/coding/code_bounds.py +755 -0
- sage/coding/code_constructions.py +804 -0
- sage/coding/codes_catalog.py +111 -0
- sage/coding/cyclic_code.py +1329 -0
- sage/coding/databases.py +316 -0
- sage/coding/decoder.py +373 -0
- sage/coding/decoders_catalog.py +88 -0
- sage/coding/delsarte_bounds.py +709 -0
- sage/coding/encoder.py +390 -0
- sage/coding/encoders_catalog.py +64 -0
- sage/coding/extended_code.py +468 -0
- sage/coding/gabidulin_code.py +1058 -0
- sage/coding/golay_code.py +404 -0
- sage/coding/goppa_code.py +441 -0
- sage/coding/grs_code.py +2371 -0
- sage/coding/guava.py +107 -0
- sage/coding/guruswami_sudan/all.py +1 -0
- sage/coding/guruswami_sudan/gs_decoder.py +897 -0
- sage/coding/guruswami_sudan/interpolation.py +409 -0
- sage/coding/guruswami_sudan/utils.py +176 -0
- sage/coding/hamming_code.py +176 -0
- sage/coding/information_set_decoder.py +1032 -0
- sage/coding/kasami_codes.cpython-314-aarch64-linux-musl.so +0 -0
- sage/coding/kasami_codes.pyx +351 -0
- sage/coding/linear_code.py +3067 -0
- sage/coding/linear_code_no_metric.py +1354 -0
- sage/coding/linear_rank_metric.py +961 -0
- sage/coding/parity_check_code.py +353 -0
- sage/coding/punctured_code.py +719 -0
- sage/coding/reed_muller_code.py +999 -0
- sage/coding/self_dual_codes.py +942 -0
- sage/coding/source_coding/all.py +2 -0
- sage/coding/source_coding/huffman.py +553 -0
- sage/coding/subfield_subcode.py +423 -0
- sage/coding/two_weight_db.py +399 -0
- sage/combinat/all__sagemath_modules.py +7 -0
- sage/combinat/cartesian_product.py +347 -0
- sage/combinat/family.py +11 -0
- sage/combinat/free_module.py +1977 -0
- sage/combinat/root_system/all.py +147 -0
- sage/combinat/root_system/ambient_space.py +527 -0
- sage/combinat/root_system/associahedron.py +471 -0
- sage/combinat/root_system/braid_move_calculator.py +143 -0
- sage/combinat/root_system/braid_orbit.cpython-314-aarch64-linux-musl.so +0 -0
- sage/combinat/root_system/braid_orbit.pyx +144 -0
- sage/combinat/root_system/branching_rules.py +2301 -0
- sage/combinat/root_system/cartan_matrix.py +1245 -0
- sage/combinat/root_system/cartan_type.py +3069 -0
- sage/combinat/root_system/coxeter_group.py +162 -0
- sage/combinat/root_system/coxeter_matrix.py +1261 -0
- sage/combinat/root_system/coxeter_type.py +681 -0
- sage/combinat/root_system/dynkin_diagram.py +900 -0
- sage/combinat/root_system/extended_affine_weyl_group.py +2993 -0
- sage/combinat/root_system/fundamental_group.py +795 -0
- sage/combinat/root_system/hecke_algebra_representation.py +1203 -0
- sage/combinat/root_system/integrable_representations.py +1227 -0
- sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +1965 -0
- sage/combinat/root_system/pieri_factors.py +1147 -0
- sage/combinat/root_system/plot.py +1615 -0
- sage/combinat/root_system/root_lattice_realization_algebras.py +1214 -0
- sage/combinat/root_system/root_lattice_realizations.py +4628 -0
- sage/combinat/root_system/root_space.py +487 -0
- sage/combinat/root_system/root_system.py +882 -0
- sage/combinat/root_system/type_A.py +348 -0
- sage/combinat/root_system/type_A_affine.py +227 -0
- sage/combinat/root_system/type_A_infinity.py +241 -0
- sage/combinat/root_system/type_B.py +347 -0
- sage/combinat/root_system/type_BC_affine.py +287 -0
- sage/combinat/root_system/type_B_affine.py +216 -0
- sage/combinat/root_system/type_C.py +317 -0
- sage/combinat/root_system/type_C_affine.py +188 -0
- sage/combinat/root_system/type_D.py +357 -0
- sage/combinat/root_system/type_D_affine.py +208 -0
- sage/combinat/root_system/type_E.py +641 -0
- sage/combinat/root_system/type_E_affine.py +231 -0
- sage/combinat/root_system/type_F.py +387 -0
- sage/combinat/root_system/type_F_affine.py +137 -0
- sage/combinat/root_system/type_G.py +293 -0
- sage/combinat/root_system/type_G_affine.py +132 -0
- sage/combinat/root_system/type_H.py +105 -0
- sage/combinat/root_system/type_I.py +110 -0
- sage/combinat/root_system/type_Q.py +150 -0
- sage/combinat/root_system/type_affine.py +509 -0
- sage/combinat/root_system/type_dual.py +704 -0
- sage/combinat/root_system/type_folded.py +301 -0
- sage/combinat/root_system/type_marked.py +748 -0
- sage/combinat/root_system/type_reducible.py +601 -0
- sage/combinat/root_system/type_relabel.py +730 -0
- sage/combinat/root_system/type_super_A.py +837 -0
- sage/combinat/root_system/weight_lattice_realizations.py +1188 -0
- sage/combinat/root_system/weight_space.py +639 -0
- sage/combinat/root_system/weyl_characters.py +2238 -0
- sage/crypto/__init__.py +4 -0
- sage/crypto/all.py +28 -0
- sage/crypto/block_cipher/all.py +7 -0
- sage/crypto/block_cipher/des.py +1065 -0
- sage/crypto/block_cipher/miniaes.py +2171 -0
- sage/crypto/block_cipher/present.py +909 -0
- sage/crypto/block_cipher/sdes.py +1527 -0
- sage/crypto/boolean_function.cpython-314-aarch64-linux-musl.so +0 -0
- sage/crypto/boolean_function.pxd +10 -0
- sage/crypto/boolean_function.pyx +1487 -0
- sage/crypto/cipher.py +78 -0
- sage/crypto/classical.py +3668 -0
- sage/crypto/classical_cipher.py +569 -0
- sage/crypto/cryptosystem.py +387 -0
- sage/crypto/key_exchange/all.py +7 -0
- sage/crypto/key_exchange/catalog.py +24 -0
- sage/crypto/key_exchange/diffie_hellman.py +323 -0
- sage/crypto/key_exchange/key_exchange_scheme.py +107 -0
- sage/crypto/lattice.py +312 -0
- sage/crypto/lfsr.py +295 -0
- sage/crypto/lwe.py +840 -0
- sage/crypto/mq/__init__.py +4 -0
- sage/crypto/mq/mpolynomialsystemgenerator.py +204 -0
- sage/crypto/mq/rijndael_gf.py +2345 -0
- sage/crypto/mq/sbox.py +7 -0
- sage/crypto/mq/sr.py +3344 -0
- sage/crypto/public_key/all.py +5 -0
- sage/crypto/public_key/blum_goldwasser.py +776 -0
- sage/crypto/sbox.cpython-314-aarch64-linux-musl.so +0 -0
- sage/crypto/sbox.pyx +2090 -0
- sage/crypto/sboxes.py +2090 -0
- sage/crypto/stream.py +390 -0
- sage/crypto/stream_cipher.py +297 -0
- sage/crypto/util.py +519 -0
- sage/ext/all__sagemath_modules.py +1 -0
- sage/ext/interpreters/__init__.py +1 -0
- sage/ext/interpreters/all__sagemath_modules.py +2 -0
- sage/ext/interpreters/wrapper_cc.cpython-314-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_cc.pxd +30 -0
- sage/ext/interpreters/wrapper_cc.pyx +252 -0
- sage/ext/interpreters/wrapper_cdf.cpython-314-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_cdf.pxd +26 -0
- sage/ext/interpreters/wrapper_cdf.pyx +245 -0
- sage/ext/interpreters/wrapper_rdf.cpython-314-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_rdf.pxd +23 -0
- sage/ext/interpreters/wrapper_rdf.pyx +221 -0
- sage/ext/interpreters/wrapper_rr.cpython-314-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_rr.pxd +28 -0
- sage/ext/interpreters/wrapper_rr.pyx +335 -0
- sage/geometry/all__sagemath_modules.py +5 -0
- sage/geometry/toric_lattice.py +1745 -0
- sage/geometry/toric_lattice_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/geometry/toric_lattice_element.pyx +432 -0
- sage/groups/abelian_gps/abelian_group.py +1925 -0
- sage/groups/abelian_gps/abelian_group_element.py +164 -0
- sage/groups/abelian_gps/all__sagemath_modules.py +5 -0
- sage/groups/abelian_gps/dual_abelian_group.py +421 -0
- sage/groups/abelian_gps/dual_abelian_group_element.py +179 -0
- sage/groups/abelian_gps/element_base.py +341 -0
- sage/groups/abelian_gps/values.py +488 -0
- sage/groups/additive_abelian/additive_abelian_group.py +476 -0
- sage/groups/additive_abelian/additive_abelian_wrapper.py +857 -0
- sage/groups/additive_abelian/all.py +4 -0
- sage/groups/additive_abelian/qmodnz.py +231 -0
- sage/groups/additive_abelian/qmodnz_element.py +349 -0
- sage/groups/affine_gps/affine_group.py +535 -0
- sage/groups/affine_gps/all.py +1 -0
- sage/groups/affine_gps/catalog.py +17 -0
- sage/groups/affine_gps/euclidean_group.py +246 -0
- sage/groups/affine_gps/group_element.py +562 -0
- sage/groups/all__sagemath_modules.py +12 -0
- sage/groups/galois_group.py +479 -0
- sage/groups/matrix_gps/all.py +4 -0
- sage/groups/matrix_gps/all__sagemath_modules.py +13 -0
- sage/groups/matrix_gps/catalog.py +26 -0
- sage/groups/matrix_gps/coxeter_group.py +927 -0
- sage/groups/matrix_gps/finitely_generated.py +487 -0
- sage/groups/matrix_gps/group_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/groups/matrix_gps/group_element.pxd +11 -0
- sage/groups/matrix_gps/group_element.pyx +431 -0
- sage/groups/matrix_gps/linear.py +440 -0
- sage/groups/matrix_gps/matrix_group.py +617 -0
- sage/groups/matrix_gps/named_group.py +296 -0
- sage/groups/matrix_gps/orthogonal.py +544 -0
- sage/groups/matrix_gps/symplectic.py +251 -0
- sage/groups/matrix_gps/unitary.py +436 -0
- sage/groups/misc_gps/all__sagemath_modules.py +1 -0
- sage/groups/misc_gps/argument_groups.py +1905 -0
- sage/groups/misc_gps/imaginary_groups.py +479 -0
- sage/groups/perm_gps/all__sagemath_modules.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_modules.py +1 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.cpython-314-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.pxd +41 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.pyx +1167 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.cpython-314-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.pxd +31 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.pyx +385 -0
- sage/homology/algebraic_topological_model.py +595 -0
- sage/homology/all.py +2 -0
- sage/homology/all__sagemath_modules.py +8 -0
- sage/homology/chain_complex.py +2148 -0
- sage/homology/chain_complex_homspace.py +165 -0
- sage/homology/chain_complex_morphism.py +629 -0
- sage/homology/chain_homotopy.py +604 -0
- sage/homology/chains.py +653 -0
- sage/homology/free_resolution.py +923 -0
- sage/homology/graded_resolution.py +567 -0
- sage/homology/hochschild_complex.py +756 -0
- sage/homology/homology_group.py +188 -0
- sage/homology/homology_morphism.py +422 -0
- sage/homology/homology_vector_space_with_basis.py +1454 -0
- sage/homology/koszul_complex.py +169 -0
- sage/homology/matrix_utils.py +205 -0
- sage/libs/all__sagemath_modules.py +1 -0
- sage/libs/gsl/__init__.py +1 -0
- sage/libs/gsl/airy.pxd +56 -0
- sage/libs/gsl/all.pxd +66 -0
- sage/libs/gsl/array.cpython-314-aarch64-linux-musl.so +0 -0
- sage/libs/gsl/array.pxd +5 -0
- sage/libs/gsl/array.pyx +102 -0
- sage/libs/gsl/bessel.pxd +208 -0
- sage/libs/gsl/blas.pxd +116 -0
- sage/libs/gsl/blas_types.pxd +34 -0
- sage/libs/gsl/block.pxd +52 -0
- sage/libs/gsl/chebyshev.pxd +37 -0
- sage/libs/gsl/clausen.pxd +12 -0
- sage/libs/gsl/combination.pxd +47 -0
- sage/libs/gsl/complex.pxd +151 -0
- sage/libs/gsl/coulomb.pxd +30 -0
- sage/libs/gsl/coupling.pxd +21 -0
- sage/libs/gsl/dawson.pxd +12 -0
- sage/libs/gsl/debye.pxd +24 -0
- sage/libs/gsl/dilog.pxd +14 -0
- sage/libs/gsl/eigen.pxd +46 -0
- sage/libs/gsl/elementary.pxd +12 -0
- sage/libs/gsl/ellint.pxd +48 -0
- sage/libs/gsl/elljac.pxd +8 -0
- sage/libs/gsl/erf.pxd +32 -0
- sage/libs/gsl/errno.pxd +26 -0
- sage/libs/gsl/exp.pxd +44 -0
- sage/libs/gsl/expint.pxd +44 -0
- sage/libs/gsl/fermi_dirac.pxd +44 -0
- sage/libs/gsl/fft.pxd +121 -0
- sage/libs/gsl/fit.pxd +50 -0
- sage/libs/gsl/gamma.pxd +94 -0
- sage/libs/gsl/gegenbauer.pxd +26 -0
- sage/libs/gsl/histogram.pxd +176 -0
- sage/libs/gsl/hyperg.pxd +52 -0
- sage/libs/gsl/integration.pxd +69 -0
- sage/libs/gsl/interp.pxd +109 -0
- sage/libs/gsl/laguerre.pxd +24 -0
- sage/libs/gsl/lambert.pxd +16 -0
- sage/libs/gsl/legendre.pxd +90 -0
- sage/libs/gsl/linalg.pxd +185 -0
- sage/libs/gsl/log.pxd +26 -0
- sage/libs/gsl/math.pxd +43 -0
- sage/libs/gsl/matrix.pxd +143 -0
- sage/libs/gsl/matrix_complex.pxd +130 -0
- sage/libs/gsl/min.pxd +67 -0
- sage/libs/gsl/monte.pxd +56 -0
- sage/libs/gsl/ntuple.pxd +32 -0
- sage/libs/gsl/odeiv.pxd +70 -0
- sage/libs/gsl/permutation.pxd +78 -0
- sage/libs/gsl/poly.pxd +40 -0
- sage/libs/gsl/pow_int.pxd +12 -0
- sage/libs/gsl/psi.pxd +28 -0
- sage/libs/gsl/qrng.pxd +29 -0
- sage/libs/gsl/random.pxd +257 -0
- sage/libs/gsl/rng.pxd +100 -0
- sage/libs/gsl/roots.pxd +72 -0
- sage/libs/gsl/sort.pxd +36 -0
- sage/libs/gsl/statistics.pxd +59 -0
- sage/libs/gsl/sum.pxd +55 -0
- sage/libs/gsl/synchrotron.pxd +16 -0
- sage/libs/gsl/transport.pxd +24 -0
- sage/libs/gsl/trig.pxd +58 -0
- sage/libs/gsl/types.pxd +137 -0
- sage/libs/gsl/vector.pxd +101 -0
- sage/libs/gsl/vector_complex.pxd +83 -0
- sage/libs/gsl/wavelet.pxd +49 -0
- sage/libs/gsl/zeta.pxd +28 -0
- sage/libs/mpc/__init__.pxd +114 -0
- sage/libs/mpc/types.pxd +28 -0
- sage/libs/mpfr/__init__.pxd +299 -0
- sage/libs/mpfr/types.pxd +26 -0
- sage/libs/mpmath/__init__.py +1 -0
- sage/libs/mpmath/all.py +27 -0
- sage/libs/mpmath/all__sagemath_modules.py +1 -0
- sage/libs/mpmath/utils.cpython-314-aarch64-linux-musl.so +0 -0
- sage/libs/mpmath/utils.pxd +4 -0
- sage/libs/mpmath/utils.pyx +319 -0
- sage/matrix/action.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/action.pxd +26 -0
- sage/matrix/action.pyx +596 -0
- sage/matrix/all.py +9 -0
- sage/matrix/args.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/args.pxd +144 -0
- sage/matrix/args.pyx +1668 -0
- sage/matrix/benchmark.py +1258 -0
- sage/matrix/berlekamp_massey.py +95 -0
- sage/matrix/compute_J_ideal.py +926 -0
- sage/matrix/constructor.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/constructor.pyx +750 -0
- sage/matrix/docs.py +430 -0
- sage/matrix/echelon_matrix.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/echelon_matrix.pyx +155 -0
- sage/matrix/matrix.pxd +2 -0
- sage/matrix/matrix0.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix0.pxd +68 -0
- sage/matrix/matrix0.pyx +6324 -0
- sage/matrix/matrix1.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix1.pxd +8 -0
- sage/matrix/matrix1.pyx +2851 -0
- sage/matrix/matrix2.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix2.pxd +25 -0
- sage/matrix/matrix2.pyx +20181 -0
- sage/matrix/matrix_cdv.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_cdv.pxd +4 -0
- sage/matrix/matrix_cdv.pyx +93 -0
- sage/matrix/matrix_complex_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_complex_double_dense.pxd +5 -0
- sage/matrix/matrix_complex_double_dense.pyx +98 -0
- sage/matrix/matrix_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_dense.pxd +5 -0
- sage/matrix/matrix_dense.pyx +343 -0
- sage/matrix/matrix_domain_dense.pxd +5 -0
- sage/matrix/matrix_domain_sparse.pxd +5 -0
- sage/matrix/matrix_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_double_dense.pxd +7 -0
- sage/matrix/matrix_double_dense.pyx +3906 -0
- sage/matrix/matrix_double_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_double_sparse.pxd +6 -0
- sage/matrix/matrix_double_sparse.pyx +248 -0
- sage/matrix/matrix_generic_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_generic_dense.pxd +7 -0
- sage/matrix/matrix_generic_dense.pyx +354 -0
- sage/matrix/matrix_generic_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_generic_sparse.pxd +7 -0
- sage/matrix/matrix_generic_sparse.pyx +461 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.pxd +5 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.pyx +115 -0
- sage/matrix/matrix_misc.py +313 -0
- sage/matrix/matrix_numpy_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_numpy_dense.pxd +14 -0
- sage/matrix/matrix_numpy_dense.pyx +450 -0
- sage/matrix/matrix_numpy_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_numpy_integer_dense.pxd +7 -0
- sage/matrix/matrix_numpy_integer_dense.pyx +59 -0
- sage/matrix/matrix_polynomial_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_polynomial_dense.pxd +5 -0
- sage/matrix/matrix_polynomial_dense.pyx +5341 -0
- sage/matrix/matrix_real_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_real_double_dense.pxd +7 -0
- sage/matrix/matrix_real_double_dense.pyx +122 -0
- sage/matrix/matrix_space.py +2848 -0
- sage/matrix/matrix_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_sparse.pxd +5 -0
- sage/matrix/matrix_sparse.pyx +1222 -0
- sage/matrix/matrix_window.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_window.pxd +37 -0
- sage/matrix/matrix_window.pyx +242 -0
- sage/matrix/misc_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/misc_mpfr.pyx +80 -0
- sage/matrix/operation_table.py +1182 -0
- sage/matrix/special.py +3666 -0
- sage/matrix/strassen.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/strassen.pyx +851 -0
- sage/matrix/symplectic_basis.py +541 -0
- sage/matrix/template.pxd +6 -0
- sage/matrix/tests.py +71 -0
- sage/matroids/advanced.py +77 -0
- sage/matroids/all.py +13 -0
- sage/matroids/basis_exchange_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/basis_exchange_matroid.pxd +96 -0
- sage/matroids/basis_exchange_matroid.pyx +2344 -0
- sage/matroids/basis_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/basis_matroid.pxd +45 -0
- sage/matroids/basis_matroid.pyx +1217 -0
- sage/matroids/catalog.py +44 -0
- sage/matroids/chow_ring.py +473 -0
- sage/matroids/chow_ring_ideal.py +849 -0
- sage/matroids/circuit_closures_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/circuit_closures_matroid.pxd +16 -0
- sage/matroids/circuit_closures_matroid.pyx +559 -0
- sage/matroids/circuits_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/circuits_matroid.pxd +38 -0
- sage/matroids/circuits_matroid.pyx +947 -0
- sage/matroids/constructor.py +1086 -0
- sage/matroids/database_collections.py +365 -0
- sage/matroids/database_matroids.py +5338 -0
- sage/matroids/dual_matroid.py +583 -0
- sage/matroids/extension.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/extension.pxd +34 -0
- sage/matroids/extension.pyx +519 -0
- sage/matroids/flats_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/flats_matroid.pxd +28 -0
- sage/matroids/flats_matroid.pyx +715 -0
- sage/matroids/gammoid.py +600 -0
- sage/matroids/graphic_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/graphic_matroid.pxd +39 -0
- sage/matroids/graphic_matroid.pyx +2024 -0
- sage/matroids/lean_matrix.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/lean_matrix.pxd +126 -0
- sage/matroids/lean_matrix.pyx +3667 -0
- sage/matroids/linear_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/linear_matroid.pxd +180 -0
- sage/matroids/linear_matroid.pyx +6649 -0
- sage/matroids/matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/matroid.pxd +243 -0
- sage/matroids/matroid.pyx +8759 -0
- sage/matroids/matroids_catalog.py +190 -0
- sage/matroids/matroids_plot_helpers.py +890 -0
- sage/matroids/minor_matroid.py +480 -0
- sage/matroids/minorfix.h +9 -0
- sage/matroids/named_matroids.py +5 -0
- sage/matroids/rank_matroid.py +268 -0
- sage/matroids/set_system.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/set_system.pxd +38 -0
- sage/matroids/set_system.pyx +800 -0
- sage/matroids/transversal_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/transversal_matroid.pxd +14 -0
- sage/matroids/transversal_matroid.pyx +893 -0
- sage/matroids/union_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/union_matroid.pxd +20 -0
- sage/matroids/union_matroid.pyx +331 -0
- sage/matroids/unpickling.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/unpickling.pyx +843 -0
- sage/matroids/utilities.py +809 -0
- sage/misc/all__sagemath_modules.py +20 -0
- sage/misc/c3.cpython-314-aarch64-linux-musl.so +0 -0
- sage/misc/c3.pyx +238 -0
- sage/misc/compat.py +87 -0
- sage/misc/element_with_label.py +173 -0
- sage/misc/func_persist.py +79 -0
- sage/misc/pickle_old.cpython-314-aarch64-linux-musl.so +0 -0
- sage/misc/pickle_old.pyx +19 -0
- sage/misc/proof.py +7 -0
- sage/misc/replace_dot_all.py +472 -0
- sage/misc/sagedoc_conf.py +168 -0
- sage/misc/sphinxify.py +167 -0
- sage/misc/test_class_pickling.py +85 -0
- sage/modules/all.py +42 -0
- sage/modules/complex_double_vector.py +25 -0
- sage/modules/diamond_cutting.py +380 -0
- sage/modules/fg_pid/all.py +1 -0
- sage/modules/fg_pid/fgp_element.py +456 -0
- sage/modules/fg_pid/fgp_module.py +2091 -0
- sage/modules/fg_pid/fgp_morphism.py +550 -0
- sage/modules/filtered_vector_space.py +1271 -0
- sage/modules/finite_submodule_iter.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/finite_submodule_iter.pxd +27 -0
- sage/modules/finite_submodule_iter.pyx +452 -0
- sage/modules/fp_graded/all.py +1 -0
- sage/modules/fp_graded/element.py +346 -0
- sage/modules/fp_graded/free_element.py +298 -0
- sage/modules/fp_graded/free_homspace.py +53 -0
- sage/modules/fp_graded/free_module.py +1060 -0
- sage/modules/fp_graded/free_morphism.py +217 -0
- sage/modules/fp_graded/homspace.py +563 -0
- sage/modules/fp_graded/module.py +1340 -0
- sage/modules/fp_graded/morphism.py +1990 -0
- sage/modules/fp_graded/steenrod/all.py +1 -0
- sage/modules/fp_graded/steenrod/homspace.py +65 -0
- sage/modules/fp_graded/steenrod/module.py +477 -0
- sage/modules/fp_graded/steenrod/morphism.py +404 -0
- sage/modules/fp_graded/steenrod/profile.py +241 -0
- sage/modules/free_module.py +8447 -0
- sage/modules/free_module_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/free_module_element.pxd +22 -0
- sage/modules/free_module_element.pyx +5445 -0
- sage/modules/free_module_homspace.py +369 -0
- sage/modules/free_module_integer.py +896 -0
- sage/modules/free_module_morphism.py +823 -0
- sage/modules/free_module_pseudohomspace.py +352 -0
- sage/modules/free_module_pseudomorphism.py +578 -0
- sage/modules/free_quadratic_module.py +1706 -0
- sage/modules/free_quadratic_module_integer_symmetric.py +1790 -0
- sage/modules/matrix_morphism.py +1745 -0
- sage/modules/misc.py +103 -0
- sage/modules/module_functors.py +192 -0
- sage/modules/multi_filtered_vector_space.py +719 -0
- sage/modules/ore_module.py +2208 -0
- sage/modules/ore_module_element.py +178 -0
- sage/modules/ore_module_homspace.py +147 -0
- sage/modules/ore_module_morphism.py +968 -0
- sage/modules/quotient_module.py +699 -0
- sage/modules/real_double_vector.py +22 -0
- sage/modules/submodule.py +255 -0
- sage/modules/tensor_operations.py +567 -0
- sage/modules/torsion_quadratic_module.py +1352 -0
- sage/modules/tutorial_free_modules.py +248 -0
- sage/modules/vector_complex_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_complex_double_dense.pxd +6 -0
- sage/modules/vector_complex_double_dense.pyx +117 -0
- sage/modules/vector_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_double_dense.pxd +6 -0
- sage/modules/vector_double_dense.pyx +604 -0
- sage/modules/vector_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_integer_dense.pxd +15 -0
- sage/modules/vector_integer_dense.pyx +361 -0
- sage/modules/vector_integer_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_integer_sparse.pxd +29 -0
- sage/modules/vector_integer_sparse.pyx +406 -0
- sage/modules/vector_modn_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_modn_dense.pxd +12 -0
- sage/modules/vector_modn_dense.pyx +394 -0
- sage/modules/vector_modn_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_modn_sparse.pxd +21 -0
- sage/modules/vector_modn_sparse.pyx +298 -0
- sage/modules/vector_numpy_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_numpy_dense.pxd +15 -0
- sage/modules/vector_numpy_dense.pyx +304 -0
- sage/modules/vector_numpy_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_numpy_integer_dense.pxd +7 -0
- sage/modules/vector_numpy_integer_dense.pyx +54 -0
- sage/modules/vector_rational_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_rational_dense.pxd +15 -0
- sage/modules/vector_rational_dense.pyx +387 -0
- sage/modules/vector_rational_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_rational_sparse.pxd +30 -0
- sage/modules/vector_rational_sparse.pyx +413 -0
- sage/modules/vector_real_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_real_double_dense.pxd +6 -0
- sage/modules/vector_real_double_dense.pyx +126 -0
- sage/modules/vector_space_homspace.py +430 -0
- sage/modules/vector_space_morphism.py +989 -0
- sage/modules/with_basis/all.py +15 -0
- sage/modules/with_basis/cell_module.py +494 -0
- sage/modules/with_basis/indexed_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/with_basis/indexed_element.pxd +13 -0
- sage/modules/with_basis/indexed_element.pyx +1058 -0
- sage/modules/with_basis/invariant.py +1075 -0
- sage/modules/with_basis/morphism.py +1636 -0
- sage/modules/with_basis/representation.py +2939 -0
- sage/modules/with_basis/subquotient.py +685 -0
- sage/numerical/all__sagemath_modules.py +6 -0
- sage/numerical/gauss_legendre.cpython-314-aarch64-linux-musl.so +0 -0
- sage/numerical/gauss_legendre.pyx +381 -0
- sage/numerical/optimize.py +910 -0
- sage/probability/all.py +10 -0
- sage/probability/probability_distribution.cpython-314-aarch64-linux-musl.so +0 -0
- sage/probability/probability_distribution.pyx +1242 -0
- sage/probability/random_variable.py +411 -0
- sage/quadratic_forms/all.py +4 -0
- sage/quadratic_forms/all__sagemath_modules.py +15 -0
- sage/quadratic_forms/binary_qf.py +2042 -0
- sage/quadratic_forms/bqf_class_group.py +748 -0
- sage/quadratic_forms/constructions.py +93 -0
- sage/quadratic_forms/count_local_2.cpython-314-aarch64-linux-musl.so +0 -0
- sage/quadratic_forms/count_local_2.pyx +365 -0
- sage/quadratic_forms/extras.py +195 -0
- sage/quadratic_forms/quadratic_form.py +1753 -0
- sage/quadratic_forms/quadratic_form__count_local_2.py +221 -0
- sage/quadratic_forms/quadratic_form__equivalence_testing.py +708 -0
- sage/quadratic_forms/quadratic_form__evaluate.cpython-314-aarch64-linux-musl.so +0 -0
- sage/quadratic_forms/quadratic_form__evaluate.pyx +139 -0
- sage/quadratic_forms/quadratic_form__local_density_congruence.py +977 -0
- sage/quadratic_forms/quadratic_form__local_field_invariants.py +1072 -0
- sage/quadratic_forms/quadratic_form__neighbors.py +424 -0
- sage/quadratic_forms/quadratic_form__reduction_theory.py +488 -0
- sage/quadratic_forms/quadratic_form__split_local_covering.py +416 -0
- sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +657 -0
- sage/quadratic_forms/quadratic_form__theta.py +352 -0
- sage/quadratic_forms/quadratic_form__variable_substitutions.py +370 -0
- sage/quadratic_forms/random_quadraticform.py +209 -0
- sage/quadratic_forms/ternary.cpython-314-aarch64-linux-musl.so +0 -0
- sage/quadratic_forms/ternary.pyx +1154 -0
- sage/quadratic_forms/ternary_qf.py +2027 -0
- sage/rings/all__sagemath_modules.py +28 -0
- sage/rings/asymptotic/all__sagemath_modules.py +1 -0
- sage/rings/asymptotic/misc.py +1252 -0
- sage/rings/cc.py +4 -0
- sage/rings/cfinite_sequence.py +1306 -0
- sage/rings/complex_conversion.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/complex_conversion.pxd +8 -0
- sage/rings/complex_conversion.pyx +23 -0
- sage/rings/complex_double.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/complex_double.pxd +21 -0
- sage/rings/complex_double.pyx +2654 -0
- sage/rings/complex_mpc.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/complex_mpc.pxd +21 -0
- sage/rings/complex_mpc.pyx +2576 -0
- sage/rings/complex_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/complex_mpfr.pxd +18 -0
- sage/rings/complex_mpfr.pyx +3602 -0
- sage/rings/derivation.py +2334 -0
- sage/rings/finite_rings/all__sagemath_modules.py +1 -0
- sage/rings/finite_rings/maps_finite_field.py +191 -0
- sage/rings/function_field/all__sagemath_modules.py +8 -0
- sage/rings/function_field/derivations.py +102 -0
- sage/rings/function_field/derivations_rational.py +132 -0
- sage/rings/function_field/differential.py +853 -0
- sage/rings/function_field/divisor.py +1107 -0
- sage/rings/function_field/drinfeld_modules/action.py +199 -0
- sage/rings/function_field/drinfeld_modules/all.py +1 -0
- sage/rings/function_field/drinfeld_modules/charzero_drinfeld_module.py +673 -0
- sage/rings/function_field/drinfeld_modules/drinfeld_module.py +2087 -0
- sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py +1131 -0
- sage/rings/function_field/drinfeld_modules/homset.py +420 -0
- sage/rings/function_field/drinfeld_modules/morphism.py +820 -0
- sage/rings/function_field/hermite_form_polynomial.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
- sage/rings/function_field/khuri_makdisi.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/khuri_makdisi.pyx +935 -0
- sage/rings/invariants/all.py +4 -0
- sage/rings/invariants/invariant_theory.py +4597 -0
- sage/rings/invariants/reconstruction.py +395 -0
- sage/rings/polynomial/all__sagemath_modules.py +17 -0
- sage/rings/polynomial/integer_valued_polynomials.py +1230 -0
- sage/rings/polynomial/laurent_polynomial_mpair.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/laurent_polynomial_mpair.pxd +15 -0
- sage/rings/polynomial/laurent_polynomial_mpair.pyx +2023 -0
- sage/rings/polynomial/ore_function_element.py +952 -0
- sage/rings/polynomial/ore_function_field.py +1028 -0
- sage/rings/polynomial/ore_polynomial_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/ore_polynomial_element.pxd +48 -0
- sage/rings/polynomial/ore_polynomial_element.pyx +3145 -0
- sage/rings/polynomial/ore_polynomial_ring.py +1334 -0
- sage/rings/polynomial/polynomial_real_mpfr_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +788 -0
- sage/rings/polynomial/q_integer_valued_polynomials.py +1264 -0
- sage/rings/polynomial/skew_polynomial_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/skew_polynomial_element.pxd +9 -0
- sage/rings/polynomial/skew_polynomial_element.pyx +684 -0
- sage/rings/polynomial/skew_polynomial_finite_field.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/skew_polynomial_finite_field.pxd +19 -0
- sage/rings/polynomial/skew_polynomial_finite_field.pyx +1093 -0
- sage/rings/polynomial/skew_polynomial_finite_order.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/skew_polynomial_finite_order.pxd +10 -0
- sage/rings/polynomial/skew_polynomial_finite_order.pyx +567 -0
- sage/rings/polynomial/skew_polynomial_ring.py +908 -0
- sage/rings/real_double_element_gsl.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/real_double_element_gsl.pxd +8 -0
- sage/rings/real_double_element_gsl.pyx +794 -0
- sage/rings/real_field.py +58 -0
- sage/rings/real_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/real_mpfr.pxd +29 -0
- sage/rings/real_mpfr.pyx +6122 -0
- sage/rings/ring_extension.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/ring_extension.pxd +42 -0
- sage/rings/ring_extension.pyx +2779 -0
- sage/rings/ring_extension_conversion.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/ring_extension_conversion.pxd +16 -0
- sage/rings/ring_extension_conversion.pyx +462 -0
- sage/rings/ring_extension_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/ring_extension_element.pxd +21 -0
- sage/rings/ring_extension_element.pyx +1635 -0
- sage/rings/ring_extension_homset.py +64 -0
- sage/rings/ring_extension_morphism.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/ring_extension_morphism.pxd +35 -0
- sage/rings/ring_extension_morphism.pyx +920 -0
- sage/schemes/all__sagemath_modules.py +1 -0
- sage/schemes/projective/all__sagemath_modules.py +1 -0
- sage/schemes/projective/coherent_sheaf.py +300 -0
- sage/schemes/projective/cohomology.py +510 -0
- sage/stats/all.py +15 -0
- sage/stats/basic_stats.py +489 -0
- sage/stats/distributions/all.py +7 -0
- sage/stats/distributions/catalog.py +34 -0
- sage/stats/distributions/dgs.h +50 -0
- sage/stats/distributions/dgs.pxd +111 -0
- sage/stats/distributions/dgs_bern.h +400 -0
- sage/stats/distributions/dgs_gauss.h +614 -0
- sage/stats/distributions/dgs_misc.h +104 -0
- sage/stats/distributions/discrete_gaussian_integer.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/distributions/discrete_gaussian_integer.pxd +14 -0
- sage/stats/distributions/discrete_gaussian_integer.pyx +498 -0
- sage/stats/distributions/discrete_gaussian_lattice.py +908 -0
- sage/stats/distributions/discrete_gaussian_polynomial.py +141 -0
- sage/stats/hmm/all.py +15 -0
- sage/stats/hmm/chmm.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/hmm/chmm.pyx +1595 -0
- sage/stats/hmm/distributions.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/hmm/distributions.pxd +29 -0
- sage/stats/hmm/distributions.pyx +531 -0
- sage/stats/hmm/hmm.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/hmm/hmm.pxd +17 -0
- sage/stats/hmm/hmm.pyx +1388 -0
- sage/stats/hmm/util.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/hmm/util.pxd +7 -0
- sage/stats/hmm/util.pyx +165 -0
- sage/stats/intlist.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/intlist.pxd +14 -0
- sage/stats/intlist.pyx +588 -0
- sage/stats/r.py +49 -0
- sage/stats/time_series.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/time_series.pxd +6 -0
- sage/stats/time_series.pyx +2546 -0
- sage/tensor/all.py +2 -0
- sage/tensor/modules/all.py +8 -0
- sage/tensor/modules/alternating_contr_tensor.py +761 -0
- sage/tensor/modules/comp.py +5598 -0
- sage/tensor/modules/ext_pow_free_module.py +824 -0
- sage/tensor/modules/finite_rank_free_module.py +3589 -0
- sage/tensor/modules/format_utilities.py +333 -0
- sage/tensor/modules/free_module_alt_form.py +858 -0
- sage/tensor/modules/free_module_automorphism.py +1207 -0
- sage/tensor/modules/free_module_basis.py +1074 -0
- sage/tensor/modules/free_module_element.py +284 -0
- sage/tensor/modules/free_module_homset.py +652 -0
- sage/tensor/modules/free_module_linear_group.py +564 -0
- sage/tensor/modules/free_module_morphism.py +1581 -0
- sage/tensor/modules/free_module_tensor.py +3289 -0
- sage/tensor/modules/reflexive_module.py +386 -0
- sage/tensor/modules/tensor_free_module.py +780 -0
- sage/tensor/modules/tensor_free_submodule.py +538 -0
- sage/tensor/modules/tensor_free_submodule_basis.py +140 -0
- 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
|