passagemath-categories 10.6.32__cp314-cp314t-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_categories-10.6.32.dist-info/METADATA +156 -0
- passagemath_categories-10.6.32.dist-info/RECORD +719 -0
- passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
- passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
- passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
- passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
- passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
- sage/all__sagemath_categories.py +28 -0
- sage/arith/all.py +38 -0
- sage/arith/constants.pxd +27 -0
- sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/functions.pxd +4 -0
- sage/arith/functions.pyx +221 -0
- sage/arith/misc.py +6552 -0
- sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/multi_modular.pxd +39 -0
- sage/arith/multi_modular.pyx +994 -0
- sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/rational_reconstruction.pxd +4 -0
- sage/arith/rational_reconstruction.pyx +115 -0
- sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/srange.pyx +571 -0
- sage/calculus/all__sagemath_categories.py +2 -0
- sage/calculus/functional.py +481 -0
- sage/calculus/functions.py +151 -0
- sage/categories/additive_groups.py +73 -0
- sage/categories/additive_magmas.py +1044 -0
- sage/categories/additive_monoids.py +114 -0
- sage/categories/additive_semigroups.py +184 -0
- sage/categories/affine_weyl_groups.py +238 -0
- sage/categories/algebra_ideals.py +95 -0
- sage/categories/algebra_modules.py +96 -0
- sage/categories/algebras.py +349 -0
- sage/categories/algebras_with_basis.py +377 -0
- sage/categories/all.py +160 -0
- sage/categories/aperiodic_semigroups.py +29 -0
- sage/categories/associative_algebras.py +47 -0
- sage/categories/bialgebras.py +101 -0
- sage/categories/bialgebras_with_basis.py +414 -0
- sage/categories/bimodules.py +206 -0
- sage/categories/chain_complexes.py +268 -0
- sage/categories/classical_crystals.py +480 -0
- sage/categories/coalgebras.py +405 -0
- sage/categories/coalgebras_with_basis.py +232 -0
- sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/coercion_methods.pyx +52 -0
- sage/categories/commutative_additive_groups.py +104 -0
- sage/categories/commutative_additive_monoids.py +45 -0
- sage/categories/commutative_additive_semigroups.py +48 -0
- sage/categories/commutative_algebra_ideals.py +87 -0
- sage/categories/commutative_algebras.py +94 -0
- sage/categories/commutative_ring_ideals.py +58 -0
- sage/categories/commutative_rings.py +736 -0
- sage/categories/complete_discrete_valuation.py +293 -0
- sage/categories/complex_reflection_groups.py +145 -0
- sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
- sage/categories/coxeter_group_algebras.py +186 -0
- sage/categories/coxeter_groups.py +3402 -0
- sage/categories/crystals.py +2628 -0
- sage/categories/cw_complexes.py +216 -0
- sage/categories/dedekind_domains.py +137 -0
- sage/categories/discrete_valuation.py +325 -0
- sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
- sage/categories/division_rings.py +114 -0
- sage/categories/domains.py +95 -0
- sage/categories/drinfeld_modules.py +789 -0
- sage/categories/dual.py +42 -0
- sage/categories/enumerated_sets.py +1146 -0
- sage/categories/euclidean_domains.py +271 -0
- sage/categories/examples/algebras_with_basis.py +102 -0
- sage/categories/examples/all.py +1 -0
- sage/categories/examples/commutative_additive_monoids.py +130 -0
- sage/categories/examples/commutative_additive_semigroups.py +199 -0
- sage/categories/examples/coxeter_groups.py +8 -0
- sage/categories/examples/crystals.py +236 -0
- sage/categories/examples/cw_complexes.py +163 -0
- sage/categories/examples/facade_sets.py +187 -0
- sage/categories/examples/filtered_algebras_with_basis.py +204 -0
- sage/categories/examples/filtered_modules_with_basis.py +154 -0
- sage/categories/examples/finite_coxeter_groups.py +252 -0
- sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
- sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
- sage/categories/examples/finite_enumerated_sets.py +208 -0
- sage/categories/examples/finite_monoids.py +150 -0
- sage/categories/examples/finite_semigroups.py +190 -0
- sage/categories/examples/finite_weyl_groups.py +191 -0
- sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
- sage/categories/examples/graded_modules_with_basis.py +168 -0
- sage/categories/examples/graphs.py +122 -0
- sage/categories/examples/hopf_algebras_with_basis.py +145 -0
- sage/categories/examples/infinite_enumerated_sets.py +190 -0
- sage/categories/examples/lie_algebras.py +352 -0
- sage/categories/examples/lie_algebras_with_basis.py +196 -0
- sage/categories/examples/magmas.py +162 -0
- sage/categories/examples/manifolds.py +94 -0
- sage/categories/examples/monoids.py +144 -0
- sage/categories/examples/posets.py +178 -0
- sage/categories/examples/semigroups.py +580 -0
- sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/examples/semigroups_cython.pyx +221 -0
- sage/categories/examples/semirings.py +249 -0
- sage/categories/examples/sets_cat.py +706 -0
- sage/categories/examples/sets_with_grading.py +101 -0
- sage/categories/examples/with_realizations.py +542 -0
- sage/categories/fields.py +991 -0
- sage/categories/filtered_algebras.py +63 -0
- sage/categories/filtered_algebras_with_basis.py +548 -0
- sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
- sage/categories/filtered_modules.py +210 -0
- sage/categories/filtered_modules_with_basis.py +1209 -0
- sage/categories/finite_complex_reflection_groups.py +1506 -0
- sage/categories/finite_coxeter_groups.py +1138 -0
- sage/categories/finite_crystals.py +103 -0
- sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
- sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
- sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
- sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
- sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
- sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
- sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
- sage/categories/finite_enumerated_sets.py +769 -0
- sage/categories/finite_fields.py +252 -0
- sage/categories/finite_groups.py +256 -0
- sage/categories/finite_lattice_posets.py +242 -0
- sage/categories/finite_monoids.py +316 -0
- sage/categories/finite_permutation_groups.py +339 -0
- sage/categories/finite_posets.py +1994 -0
- sage/categories/finite_semigroups.py +136 -0
- sage/categories/finite_sets.py +93 -0
- sage/categories/finite_weyl_groups.py +39 -0
- sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
- sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
- sage/categories/finitely_generated_magmas.py +57 -0
- sage/categories/finitely_generated_semigroups.py +214 -0
- sage/categories/function_fields.py +76 -0
- sage/categories/g_sets.py +77 -0
- sage/categories/gcd_domains.py +65 -0
- sage/categories/generalized_coxeter_groups.py +94 -0
- sage/categories/graded_algebras.py +85 -0
- sage/categories/graded_algebras_with_basis.py +258 -0
- sage/categories/graded_bialgebras.py +32 -0
- sage/categories/graded_bialgebras_with_basis.py +32 -0
- sage/categories/graded_coalgebras.py +65 -0
- sage/categories/graded_coalgebras_with_basis.py +51 -0
- sage/categories/graded_hopf_algebras.py +41 -0
- sage/categories/graded_hopf_algebras_with_basis.py +169 -0
- sage/categories/graded_lie_algebras.py +91 -0
- sage/categories/graded_lie_algebras_with_basis.py +44 -0
- sage/categories/graded_lie_conformal_algebras.py +74 -0
- sage/categories/graded_modules.py +133 -0
- sage/categories/graded_modules_with_basis.py +329 -0
- sage/categories/graphs.py +138 -0
- sage/categories/group_algebras.py +430 -0
- sage/categories/groupoid.py +94 -0
- sage/categories/groups.py +667 -0
- sage/categories/h_trivial_semigroups.py +64 -0
- sage/categories/hecke_modules.py +185 -0
- sage/categories/highest_weight_crystals.py +980 -0
- sage/categories/hopf_algebras.py +219 -0
- sage/categories/hopf_algebras_with_basis.py +309 -0
- sage/categories/infinite_enumerated_sets.py +115 -0
- sage/categories/integral_domains.py +203 -0
- sage/categories/j_trivial_semigroups.py +29 -0
- sage/categories/kac_moody_algebras.py +82 -0
- sage/categories/kahler_algebras.py +203 -0
- sage/categories/l_trivial_semigroups.py +63 -0
- sage/categories/lambda_bracket_algebras.py +280 -0
- sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
- sage/categories/lattice_posets.py +89 -0
- sage/categories/left_modules.py +49 -0
- sage/categories/lie_algebras.py +1070 -0
- sage/categories/lie_algebras_with_basis.py +261 -0
- sage/categories/lie_conformal_algebras.py +350 -0
- sage/categories/lie_conformal_algebras_with_basis.py +147 -0
- sage/categories/lie_groups.py +73 -0
- sage/categories/loop_crystals.py +1290 -0
- sage/categories/magmas.py +1189 -0
- sage/categories/magmas_and_additive_magmas.py +149 -0
- sage/categories/magmatic_algebras.py +365 -0
- sage/categories/manifolds.py +352 -0
- sage/categories/matrix_algebras.py +40 -0
- sage/categories/metric_spaces.py +387 -0
- sage/categories/modular_abelian_varieties.py +78 -0
- sage/categories/modules.py +989 -0
- sage/categories/modules_with_basis.py +2794 -0
- sage/categories/monoid_algebras.py +38 -0
- sage/categories/monoids.py +739 -0
- sage/categories/noetherian_rings.py +87 -0
- sage/categories/number_fields.py +242 -0
- sage/categories/ore_modules.py +189 -0
- sage/categories/partially_ordered_monoids.py +49 -0
- sage/categories/permutation_groups.py +63 -0
- sage/categories/pointed_sets.py +42 -0
- sage/categories/polyhedra.py +74 -0
- sage/categories/poor_man_map.py +270 -0
- sage/categories/posets.py +722 -0
- sage/categories/principal_ideal_domains.py +270 -0
- sage/categories/quantum_group_representations.py +543 -0
- sage/categories/quotient_fields.py +728 -0
- sage/categories/r_trivial_semigroups.py +45 -0
- sage/categories/regular_crystals.py +898 -0
- sage/categories/regular_supercrystals.py +170 -0
- sage/categories/right_modules.py +49 -0
- sage/categories/ring_ideals.py +74 -0
- sage/categories/rings.py +1904 -0
- sage/categories/rngs.py +175 -0
- sage/categories/schemes.py +393 -0
- sage/categories/semigroups.py +1060 -0
- sage/categories/semirings.py +71 -0
- sage/categories/semisimple_algebras.py +114 -0
- sage/categories/sets_with_grading.py +235 -0
- sage/categories/shephard_groups.py +43 -0
- sage/categories/signed_tensor.py +120 -0
- sage/categories/simplicial_complexes.py +134 -0
- sage/categories/simplicial_sets.py +1206 -0
- sage/categories/super_algebras.py +149 -0
- sage/categories/super_algebras_with_basis.py +144 -0
- sage/categories/super_hopf_algebras_with_basis.py +126 -0
- sage/categories/super_lie_conformal_algebras.py +193 -0
- sage/categories/super_modules.py +229 -0
- sage/categories/super_modules_with_basis.py +193 -0
- sage/categories/supercommutative_algebras.py +99 -0
- sage/categories/supercrystals.py +406 -0
- sage/categories/tensor.py +110 -0
- sage/categories/topological_spaces.py +170 -0
- sage/categories/triangular_kac_moody_algebras.py +439 -0
- sage/categories/tutorial.py +58 -0
- sage/categories/unique_factorization_domains.py +318 -0
- sage/categories/unital_algebras.py +426 -0
- sage/categories/vector_bundles.py +159 -0
- sage/categories/vector_spaces.py +357 -0
- sage/categories/weyl_groups.py +853 -0
- sage/combinat/all__sagemath_categories.py +34 -0
- sage/combinat/backtrack.py +180 -0
- sage/combinat/combinat.py +2269 -0
- sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/combinat_cython.pxd +6 -0
- sage/combinat/combinat_cython.pyx +390 -0
- sage/combinat/combination.py +796 -0
- sage/combinat/combinatorial_map.py +416 -0
- sage/combinat/composition.py +2192 -0
- sage/combinat/dlx.py +510 -0
- sage/combinat/integer_lists/__init__.py +7 -0
- sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/base.pxd +16 -0
- sage/combinat/integer_lists/base.pyx +713 -0
- sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/invlex.pxd +4 -0
- sage/combinat/integer_lists/invlex.pyx +1650 -0
- sage/combinat/integer_lists/lists.py +328 -0
- sage/combinat/integer_lists/nn.py +48 -0
- sage/combinat/integer_vector.py +1818 -0
- sage/combinat/integer_vector_weighted.py +413 -0
- sage/combinat/matrices/all__sagemath_categories.py +5 -0
- sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/matrices/dancing_links.pyx +1159 -0
- sage/combinat/matrices/dancing_links_c.h +380 -0
- sage/combinat/matrices/dlxcpp.py +136 -0
- sage/combinat/partition.py +10070 -0
- sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/partitions.pyx +743 -0
- sage/combinat/permutation.py +10168 -0
- sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/permutation_cython.pxd +11 -0
- sage/combinat/permutation_cython.pyx +407 -0
- sage/combinat/q_analogues.py +1090 -0
- sage/combinat/ranker.py +268 -0
- sage/combinat/subset.py +1561 -0
- sage/combinat/subsets_hereditary.py +202 -0
- sage/combinat/subsets_pairwise.py +184 -0
- sage/combinat/tools.py +63 -0
- sage/combinat/tuple.py +348 -0
- sage/data_structures/all.py +2 -0
- sage/data_structures/all__sagemath_categories.py +2 -0
- sage/data_structures/binary_matrix.pxd +138 -0
- sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/binary_search.pxd +3 -0
- sage/data_structures/binary_search.pyx +66 -0
- sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset.pxd +40 -0
- sage/data_structures/bitset.pyx +2385 -0
- sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset_base.pxd +926 -0
- sage/data_structures/bitset_base.pyx +117 -0
- sage/data_structures/bitset_intrinsics.h +487 -0
- sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/blas_dict.pxd +12 -0
- sage/data_structures/blas_dict.pyx +469 -0
- sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/list_of_pairs.pxd +16 -0
- sage/data_structures/list_of_pairs.pyx +122 -0
- sage/data_structures/mutable_poset.py +3312 -0
- sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/pairing_heap.h +346 -0
- sage/data_structures/pairing_heap.pxd +88 -0
- sage/data_structures/pairing_heap.pyx +1464 -0
- sage/data_structures/sparse_bitset.pxd +62 -0
- sage/data_structures/stream.py +5070 -0
- sage/databases/all__sagemath_categories.py +7 -0
- sage/databases/sql_db.py +2236 -0
- sage/ext/all__sagemath_categories.py +3 -0
- sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_callable.pxd +4 -0
- sage/ext/fast_callable.pyx +2746 -0
- sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_eval.pxd +1 -0
- sage/ext/fast_eval.pyx +102 -0
- sage/ext/interpreters/__init__.py +1 -0
- sage/ext/interpreters/all__sagemath_categories.py +2 -0
- sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_el.pxd +18 -0
- sage/ext/interpreters/wrapper_el.pyx +148 -0
- sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_py.pxd +17 -0
- sage/ext/interpreters/wrapper_py.pyx +133 -0
- sage/functions/airy.py +937 -0
- sage/functions/all.py +97 -0
- sage/functions/bessel.py +2102 -0
- sage/functions/error.py +784 -0
- sage/functions/exp_integral.py +1529 -0
- sage/functions/gamma.py +1087 -0
- sage/functions/generalized.py +672 -0
- sage/functions/hyperbolic.py +747 -0
- sage/functions/hypergeometric.py +1156 -0
- sage/functions/jacobi.py +1705 -0
- sage/functions/log.py +1402 -0
- sage/functions/min_max.py +338 -0
- sage/functions/orthogonal_polys.py +3106 -0
- sage/functions/other.py +2303 -0
- sage/functions/piecewise.py +1505 -0
- sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/functions/prime_pi.pyx +262 -0
- sage/functions/special.py +1212 -0
- sage/functions/spike_function.py +278 -0
- sage/functions/transcendental.py +690 -0
- sage/functions/trig.py +1062 -0
- sage/functions/wigner.py +726 -0
- sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/geometry/abc.pyx +82 -0
- sage/geometry/all__sagemath_categories.py +1 -0
- sage/groups/all__sagemath_categories.py +11 -0
- sage/groups/generic.py +1733 -0
- sage/groups/groups_catalog.py +113 -0
- sage/groups/perm_gps/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/all.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
- sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
- sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
- sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
- sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
- sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
- sage/interfaces/abc.py +140 -0
- sage/interfaces/all.py +58 -0
- sage/interfaces/all__sagemath_categories.py +1 -0
- sage/interfaces/expect.py +1643 -0
- sage/interfaces/interface.py +1682 -0
- sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/process.pxd +5 -0
- sage/interfaces/process.pyx +288 -0
- sage/interfaces/quit.py +167 -0
- sage/interfaces/sage0.py +604 -0
- sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/sagespawn.pyx +308 -0
- sage/interfaces/tab_completion.py +101 -0
- sage/misc/all__sagemath_categories.py +78 -0
- sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/allocator.pxd +6 -0
- sage/misc/allocator.pyx +47 -0
- sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/binary_tree.pxd +29 -0
- sage/misc/binary_tree.pyx +537 -0
- sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/callable_dict.pyx +89 -0
- sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/citation.pyx +159 -0
- sage/misc/converting_dict.py +293 -0
- sage/misc/defaults.py +129 -0
- sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/derivative.pyx +223 -0
- sage/misc/functional.py +2005 -0
- sage/misc/html.py +589 -0
- sage/misc/latex.py +2673 -0
- sage/misc/latex_macros.py +236 -0
- sage/misc/latex_standalone.py +1833 -0
- sage/misc/map_threaded.py +38 -0
- sage/misc/mathml.py +76 -0
- sage/misc/method_decorator.py +88 -0
- sage/misc/mrange.py +755 -0
- sage/misc/multireplace.py +41 -0
- sage/misc/object_multiplexer.py +92 -0
- sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/parser.pyx +1107 -0
- sage/misc/random_testing.py +264 -0
- sage/misc/rest_index_of_methods.py +377 -0
- sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/search.pxd +2 -0
- sage/misc/search.pyx +68 -0
- sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/stopgap.pyx +95 -0
- sage/misc/table.py +853 -0
- sage/monoids/all__sagemath_categories.py +1 -0
- sage/monoids/indexed_free_monoid.py +1071 -0
- sage/monoids/monoid.py +82 -0
- sage/numerical/all__sagemath_categories.py +1 -0
- sage/numerical/backends/all__sagemath_categories.py +1 -0
- sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_backend.pxd +61 -0
- sage/numerical/backends/generic_backend.pyx +1893 -0
- sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_sdp_backend.pxd +38 -0
- sage/numerical/backends/generic_sdp_backend.pyx +755 -0
- sage/parallel/all.py +6 -0
- sage/parallel/decorate.py +575 -0
- sage/parallel/map_reduce.py +1997 -0
- sage/parallel/multiprocessing_sage.py +76 -0
- sage/parallel/ncpus.py +35 -0
- sage/parallel/parallelism.py +364 -0
- sage/parallel/reference.py +47 -0
- sage/parallel/use_fork.py +333 -0
- sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/abc.pxd +31 -0
- sage/rings/abc.pyx +526 -0
- sage/rings/algebraic_closure_finite_field.py +1154 -0
- sage/rings/all__sagemath_categories.py +91 -0
- sage/rings/big_oh.py +227 -0
- sage/rings/continued_fraction.py +2754 -0
- sage/rings/continued_fraction_gosper.py +220 -0
- sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/factorint.pyx +295 -0
- sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fast_arith.pxd +21 -0
- sage/rings/fast_arith.pyx +535 -0
- sage/rings/finite_rings/all__sagemath_categories.py +9 -0
- sage/rings/finite_rings/conway_polynomials.py +542 -0
- sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_base.pxd +12 -0
- sage/rings/finite_rings/element_base.pyx +1176 -0
- sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/finite_field_base.pxd +7 -0
- sage/rings/finite_rings/finite_field_base.pyx +2171 -0
- sage/rings/finite_rings/finite_field_constructor.py +827 -0
- sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
- sage/rings/finite_rings/galois_group.py +154 -0
- sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_finite_field.pxd +23 -0
- sage/rings/finite_rings/hom_finite_field.pyx +856 -0
- sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
- sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
- sage/rings/finite_rings/homset.py +357 -0
- sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/integer_mod.pxd +56 -0
- sage/rings/finite_rings/integer_mod.pyx +4586 -0
- sage/rings/finite_rings/integer_mod_limits.h +11 -0
- sage/rings/finite_rings/integer_mod_ring.py +2044 -0
- sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/residue_field.pxd +30 -0
- sage/rings/finite_rings/residue_field.pyx +1811 -0
- sage/rings/finite_rings/stdint.pxd +19 -0
- sage/rings/fraction_field.py +1452 -0
- sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fraction_field_element.pyx +1357 -0
- sage/rings/function_field/all.py +7 -0
- sage/rings/function_field/all__sagemath_categories.py +2 -0
- sage/rings/function_field/constructor.py +218 -0
- sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element.pxd +11 -0
- sage/rings/function_field/element.pyx +1008 -0
- sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element_rational.pyx +513 -0
- sage/rings/function_field/extensions.py +230 -0
- sage/rings/function_field/function_field.py +1468 -0
- sage/rings/function_field/function_field_rational.py +1005 -0
- sage/rings/function_field/ideal.py +1155 -0
- sage/rings/function_field/ideal_rational.py +629 -0
- sage/rings/function_field/jacobian_base.py +826 -0
- sage/rings/function_field/jacobian_hess.py +1053 -0
- sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
- sage/rings/function_field/maps.py +1039 -0
- sage/rings/function_field/order.py +281 -0
- sage/rings/function_field/order_basis.py +586 -0
- sage/rings/function_field/order_rational.py +576 -0
- sage/rings/function_field/place.py +426 -0
- sage/rings/function_field/place_rational.py +181 -0
- sage/rings/generic.py +320 -0
- sage/rings/homset.py +332 -0
- sage/rings/ideal.py +1885 -0
- sage/rings/ideal_monoid.py +215 -0
- sage/rings/infinity.py +1890 -0
- sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer.pxd +45 -0
- sage/rings/integer.pyx +7874 -0
- sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer_ring.pxd +8 -0
- sage/rings/integer_ring.pyx +1693 -0
- sage/rings/laurent_series_ring.py +931 -0
- sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/laurent_series_ring_element.pxd +11 -0
- sage/rings/laurent_series_ring_element.pyx +1927 -0
- sage/rings/lazy_series.py +7815 -0
- sage/rings/lazy_series_ring.py +4356 -0
- sage/rings/localization.py +1043 -0
- sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/morphism.pxd +39 -0
- sage/rings/morphism.pyx +3299 -0
- sage/rings/multi_power_series_ring.py +1145 -0
- sage/rings/multi_power_series_ring_element.py +2184 -0
- sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/noncommutative_ideals.pyx +423 -0
- sage/rings/number_field/all__sagemath_categories.py +1 -0
- sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_base.pxd +8 -0
- sage/rings/number_field/number_field_base.pyx +507 -0
- sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_element_base.pxd +6 -0
- sage/rings/number_field/number_field_element_base.pyx +36 -0
- sage/rings/number_field/number_field_ideal.py +3550 -0
- sage/rings/padics/all__sagemath_categories.py +4 -0
- sage/rings/padics/local_generic.py +1670 -0
- sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/local_generic_element.pxd +5 -0
- sage/rings/padics/local_generic_element.pyx +1017 -0
- sage/rings/padics/misc.py +256 -0
- sage/rings/padics/padic_generic.py +1911 -0
- sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/pow_computer.pxd +38 -0
- sage/rings/padics/pow_computer.pyx +671 -0
- sage/rings/padics/precision_error.py +24 -0
- sage/rings/polynomial/all__sagemath_categories.py +25 -0
- sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/commutative_polynomial.pxd +6 -0
- sage/rings/polynomial/commutative_polynomial.pyx +24 -0
- sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/cyclotomic.pyx +404 -0
- sage/rings/polynomial/flatten.py +711 -0
- sage/rings/polynomial/ideal.py +102 -0
- sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
- sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
- sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/laurent_polynomial.pxd +18 -0
- sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
- sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
- sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
- sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
- sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial.pxd +12 -0
- sage/rings/polynomial/multi_polynomial.pyx +3082 -0
- sage/rings/polynomial/multi_polynomial_element.py +2570 -0
- sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
- sage/rings/polynomial/multi_polynomial_ring.py +947 -0
- sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
- sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
- sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polydict.pxd +45 -0
- sage/rings/polynomial/polydict.pyx +2701 -0
- sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_compiled.pxd +59 -0
- sage/rings/polynomial/polynomial_compiled.pyx +509 -0
- sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_element.pxd +64 -0
- sage/rings/polynomial/polynomial_element.pyx +13255 -0
- sage/rings/polynomial/polynomial_element_generic.py +1637 -0
- sage/rings/polynomial/polynomial_fateman.py +97 -0
- sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
- sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
- sage/rings/polynomial/polynomial_ring.py +3784 -0
- sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
- sage/rings/polynomial/polynomial_singular_interface.py +549 -0
- sage/rings/polynomial/symmetric_ideal.py +989 -0
- sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/symmetric_reduction.pxd +8 -0
- sage/rings/polynomial/symmetric_reduction.pyx +669 -0
- sage/rings/polynomial/term_order.py +2279 -0
- sage/rings/polynomial/toy_buchberger.py +449 -0
- sage/rings/polynomial/toy_d_basis.py +387 -0
- sage/rings/polynomial/toy_variety.py +362 -0
- sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_mpoly.pxd +9 -0
- sage/rings/power_series_mpoly.pyx +161 -0
- sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_poly.pxd +10 -0
- sage/rings/power_series_poly.pyx +1317 -0
- sage/rings/power_series_ring.py +1441 -0
- sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_ring_element.pxd +12 -0
- sage/rings/power_series_ring_element.pyx +3028 -0
- sage/rings/puiseux_series_ring.py +487 -0
- sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/puiseux_series_ring_element.pxd +7 -0
- sage/rings/puiseux_series_ring_element.pyx +1055 -0
- sage/rings/qqbar_decorators.py +167 -0
- sage/rings/quotient_ring.py +1598 -0
- sage/rings/quotient_ring_element.py +979 -0
- sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/rational.pxd +20 -0
- sage/rings/rational.pyx +4284 -0
- sage/rings/rational_field.py +1730 -0
- sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_double.pxd +16 -0
- sage/rings/real_double.pyx +2218 -0
- sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_lazy.pxd +30 -0
- sage/rings/real_lazy.pyx +1773 -0
- sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/ring.pxd +30 -0
- sage/rings/ring.pyx +850 -0
- sage/rings/semirings/all.py +3 -0
- sage/rings/semirings/non_negative_integer_semiring.py +107 -0
- sage/rings/semirings/tropical_mpolynomial.py +972 -0
- sage/rings/semirings/tropical_polynomial.py +997 -0
- sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/semirings/tropical_semiring.pyx +676 -0
- sage/rings/semirings/tropical_variety.py +1701 -0
- sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/sum_of_squares.pxd +3 -0
- sage/rings/sum_of_squares.pyx +336 -0
- sage/rings/tests.py +504 -0
- sage/schemes/affine/affine_homset.py +508 -0
- sage/schemes/affine/affine_morphism.py +1574 -0
- sage/schemes/affine/affine_point.py +460 -0
- sage/schemes/affine/affine_rational_point.py +308 -0
- sage/schemes/affine/affine_space.py +1264 -0
- sage/schemes/affine/affine_subscheme.py +592 -0
- sage/schemes/affine/all.py +25 -0
- sage/schemes/all__sagemath_categories.py +5 -0
- sage/schemes/generic/algebraic_scheme.py +2092 -0
- sage/schemes/generic/all.py +5 -0
- sage/schemes/generic/ambient_space.py +400 -0
- sage/schemes/generic/divisor.py +465 -0
- sage/schemes/generic/divisor_group.py +313 -0
- sage/schemes/generic/glue.py +84 -0
- sage/schemes/generic/homset.py +820 -0
- sage/schemes/generic/hypersurface.py +234 -0
- sage/schemes/generic/morphism.py +2107 -0
- sage/schemes/generic/point.py +237 -0
- sage/schemes/generic/scheme.py +1190 -0
- sage/schemes/generic/spec.py +199 -0
- sage/schemes/product_projective/all.py +6 -0
- sage/schemes/product_projective/homset.py +236 -0
- sage/schemes/product_projective/morphism.py +517 -0
- sage/schemes/product_projective/point.py +568 -0
- sage/schemes/product_projective/rational_point.py +550 -0
- sage/schemes/product_projective/space.py +1301 -0
- sage/schemes/product_projective/subscheme.py +466 -0
- sage/schemes/projective/all.py +24 -0
- sage/schemes/projective/proj_bdd_height.py +453 -0
- sage/schemes/projective/projective_homset.py +718 -0
- sage/schemes/projective/projective_morphism.py +2792 -0
- sage/schemes/projective/projective_point.py +1484 -0
- sage/schemes/projective/projective_rational_point.py +569 -0
- sage/schemes/projective/projective_space.py +2571 -0
- sage/schemes/projective/projective_subscheme.py +1574 -0
- sage/sets/all.py +17 -0
- sage/sets/cartesian_product.py +376 -0
- sage/sets/condition_set.py +525 -0
- sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/disjoint_set.pxd +36 -0
- sage/sets/disjoint_set.pyx +998 -0
- sage/sets/disjoint_union_enumerated_sets.py +625 -0
- sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/family.pxd +12 -0
- sage/sets/family.pyx +1556 -0
- sage/sets/finite_enumerated_set.py +406 -0
- sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/finite_set_map_cy.pxd +34 -0
- sage/sets/finite_set_map_cy.pyx +708 -0
- sage/sets/finite_set_maps.py +591 -0
- sage/sets/image_set.py +448 -0
- sage/sets/integer_range.py +829 -0
- sage/sets/non_negative_integers.py +241 -0
- sage/sets/positive_integers.py +93 -0
- sage/sets/primes.py +188 -0
- sage/sets/real_set.py +2760 -0
- sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/recursively_enumerated_set.pxd +31 -0
- sage/sets/recursively_enumerated_set.pyx +2082 -0
- sage/sets/set.py +2083 -0
- sage/sets/set_from_iterator.py +1021 -0
- sage/sets/totally_ordered_finite_set.py +329 -0
- sage/symbolic/all__sagemath_categories.py +1 -0
- sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/symbolic/function.pxd +29 -0
- sage/symbolic/function.pyx +1488 -0
- sage/symbolic/symbols.py +56 -0
- sage/tests/all__sagemath_categories.py +1 -0
- sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/cython.pyx +37 -0
- sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/stl_vector.pyx +171 -0
- sage/typeset/all.py +6 -0
- sage/typeset/ascii_art.py +295 -0
- sage/typeset/character_art.py +789 -0
- sage/typeset/character_art_factory.py +572 -0
- sage/typeset/symbols.py +334 -0
- sage/typeset/unicode_art.py +183 -0
- sage/typeset/unicode_characters.py +101 -0
|
@@ -0,0 +1,2628 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
# sage.doctest: needs sage.graphs sage.combinat sage.modules
|
|
3
|
+
r"""
|
|
4
|
+
Crystals
|
|
5
|
+
|
|
6
|
+
TESTS:
|
|
7
|
+
|
|
8
|
+
Catch warnings produced by :func:`check_tkz_graph`::
|
|
9
|
+
|
|
10
|
+
sage: from sage.graphs.graph_latex import check_tkz_graph
|
|
11
|
+
sage: check_tkz_graph() # random
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
#*****************************************************************************
|
|
15
|
+
# Copyright (C) 2010 Anne Schilling <anne at math.ucdavis.edu>
|
|
16
|
+
#
|
|
17
|
+
# This program is free software: you can redistribute it and/or modify
|
|
18
|
+
# it under the terms of the GNU General Public License as published by
|
|
19
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
20
|
+
# (at your option) any later version.
|
|
21
|
+
# https://www.gnu.org/licenses/
|
|
22
|
+
#*****************************************************************************
|
|
23
|
+
|
|
24
|
+
import collections.abc
|
|
25
|
+
|
|
26
|
+
from sage.misc.cachefunc import cached_method
|
|
27
|
+
from sage.misc.abstract_method import abstract_method
|
|
28
|
+
from sage.misc.lazy_import import LazyImport
|
|
29
|
+
from sage.categories.category_singleton import Category_singleton
|
|
30
|
+
from sage.categories.enumerated_sets import EnumeratedSets
|
|
31
|
+
from sage.categories.tensor import TensorProductsCategory
|
|
32
|
+
from sage.categories.morphism import Morphism
|
|
33
|
+
from sage.categories.homset import Hom, Homset
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class Crystals(Category_singleton):
|
|
37
|
+
r"""
|
|
38
|
+
The category of crystals.
|
|
39
|
+
|
|
40
|
+
See :mod:`sage.combinat.crystals.crystals` for an introduction to crystals.
|
|
41
|
+
|
|
42
|
+
EXAMPLES::
|
|
43
|
+
|
|
44
|
+
sage: C = Crystals()
|
|
45
|
+
sage: C
|
|
46
|
+
Category of crystals
|
|
47
|
+
sage: C.super_categories()
|
|
48
|
+
[Category of... enumerated sets]
|
|
49
|
+
sage: C.example()
|
|
50
|
+
Highest weight crystal of type A_3 of highest weight omega_1
|
|
51
|
+
|
|
52
|
+
Parents in this category should implement the following methods:
|
|
53
|
+
|
|
54
|
+
- either an attribute ``_cartan_type`` or a method ``cartan_type``
|
|
55
|
+
|
|
56
|
+
- ``module_generators``: a list (or container) of distinct elements
|
|
57
|
+
which generate the crystal using `f_i`
|
|
58
|
+
|
|
59
|
+
Furthermore, their elements ``x`` should implement the following
|
|
60
|
+
methods:
|
|
61
|
+
|
|
62
|
+
- ``x.e(i)`` (returning `e_i(x)`)
|
|
63
|
+
|
|
64
|
+
- ``x.f(i)`` (returning `f_i(x)`)
|
|
65
|
+
|
|
66
|
+
- ``x.epsilon(i)`` (returning `\varepsilon_i(x)`)
|
|
67
|
+
|
|
68
|
+
- ``x.phi(i)`` (returning `\varphi_i(x)`)
|
|
69
|
+
|
|
70
|
+
EXAMPLES::
|
|
71
|
+
|
|
72
|
+
sage: from sage.misc.abstract_method import abstract_methods_of_class
|
|
73
|
+
sage: abstract_methods_of_class(Crystals().element_class)
|
|
74
|
+
{'optional': [], 'required': ['e', 'epsilon', 'f', 'phi', 'weight']}
|
|
75
|
+
|
|
76
|
+
TESTS::
|
|
77
|
+
|
|
78
|
+
sage: TestSuite(C).run()
|
|
79
|
+
sage: B = Crystals().example()
|
|
80
|
+
sage: TestSuite(B).run(verbose = True)
|
|
81
|
+
running ._test_an_element() . . . pass
|
|
82
|
+
running ._test_cardinality() . . . pass
|
|
83
|
+
running ._test_category() . . . pass
|
|
84
|
+
running ._test_construction() . . . pass
|
|
85
|
+
running ._test_elements() . . .
|
|
86
|
+
Running the test suite of self.an_element()
|
|
87
|
+
running ._test_category() . . . pass
|
|
88
|
+
running ._test_eq() . . . pass
|
|
89
|
+
running ._test_new() . . . pass
|
|
90
|
+
running ._test_not_implemented_methods() . . . pass
|
|
91
|
+
running ._test_pickling() . . . pass
|
|
92
|
+
running ._test_stembridge_local_axioms() . . . pass
|
|
93
|
+
pass
|
|
94
|
+
running ._test_elements_eq_reflexive() . . . pass
|
|
95
|
+
running ._test_elements_eq_symmetric() . . . pass
|
|
96
|
+
running ._test_elements_eq_transitive() . . . pass
|
|
97
|
+
running ._test_elements_neq() . . . pass
|
|
98
|
+
running ._test_enumerated_set_contains() . . . pass
|
|
99
|
+
running ._test_enumerated_set_iter_cardinality() . . . pass
|
|
100
|
+
running ._test_enumerated_set_iter_list() . . . pass
|
|
101
|
+
running ._test_eq() . . . pass
|
|
102
|
+
running ._test_fast_iter() . . . pass
|
|
103
|
+
running ._test_new() . . . pass
|
|
104
|
+
running ._test_not_implemented_methods() . . . pass
|
|
105
|
+
running ._test_pickling() . . . pass
|
|
106
|
+
running ._test_some_elements() . . . pass
|
|
107
|
+
running ._test_stembridge_local_axioms() . . . pass
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
def super_categories(self):
|
|
111
|
+
r"""
|
|
112
|
+
EXAMPLES::
|
|
113
|
+
|
|
114
|
+
sage: Crystals().super_categories()
|
|
115
|
+
[Category of enumerated sets]
|
|
116
|
+
"""
|
|
117
|
+
return [EnumeratedSets()]
|
|
118
|
+
|
|
119
|
+
def example(self, choice='highwt', **kwds):
|
|
120
|
+
r"""
|
|
121
|
+
Return an example of a crystal, as per
|
|
122
|
+
:meth:`Category.example()
|
|
123
|
+
<sage.categories.category.Category.example>`.
|
|
124
|
+
|
|
125
|
+
INPUT:
|
|
126
|
+
|
|
127
|
+
- ``choice`` -- string (default: ``'highwt'``); can be either ``'highwt'``
|
|
128
|
+
for the highest weight crystal of type A, or ``'naive'`` for an
|
|
129
|
+
example of a broken crystal
|
|
130
|
+
|
|
131
|
+
- ``**kwds`` -- keyword arguments passed onto the constructor for the
|
|
132
|
+
chosen crystal
|
|
133
|
+
|
|
134
|
+
EXAMPLES::
|
|
135
|
+
|
|
136
|
+
sage: Crystals().example(choice='highwt', n=5)
|
|
137
|
+
Highest weight crystal of type A_5 of highest weight omega_1
|
|
138
|
+
sage: Crystals().example(choice='naive')
|
|
139
|
+
A broken crystal, defined by digraph, of dimension five.
|
|
140
|
+
"""
|
|
141
|
+
import sage.categories.examples.crystals as examples
|
|
142
|
+
if choice == "naive":
|
|
143
|
+
return examples.NaiveCrystal(**kwds)
|
|
144
|
+
else:
|
|
145
|
+
from sage.rings.integer import Integer
|
|
146
|
+
if isinstance(choice, Integer):
|
|
147
|
+
return examples.HighestWeightCrystalOfTypeA(n=choice, **kwds)
|
|
148
|
+
else:
|
|
149
|
+
return examples.HighestWeightCrystalOfTypeA(**kwds)
|
|
150
|
+
|
|
151
|
+
class MorphismMethods:
|
|
152
|
+
@cached_method
|
|
153
|
+
def is_isomorphism(self):
|
|
154
|
+
"""
|
|
155
|
+
Check if ``self`` is a crystal isomorphism.
|
|
156
|
+
|
|
157
|
+
EXAMPLES::
|
|
158
|
+
|
|
159
|
+
sage: B = crystals.Tableaux(['C',2], shape=[1,1])
|
|
160
|
+
sage: C = crystals.Tableaux(['C',2], ([2,1], [1,1]))
|
|
161
|
+
sage: psi = B.crystal_morphism(C.module_generators[1:], codomain=C)
|
|
162
|
+
sage: psi.is_isomorphism()
|
|
163
|
+
False
|
|
164
|
+
"""
|
|
165
|
+
if self.domain().cardinality() != self.codomain().cardinality():
|
|
166
|
+
return False
|
|
167
|
+
if self.domain().cardinality() == float('inf'):
|
|
168
|
+
raise NotImplementedError("unable to determine if an isomorphism")
|
|
169
|
+
|
|
170
|
+
index_set = self._cartan_type.index_set()
|
|
171
|
+
G = self.domain().digraph(index_set=index_set)
|
|
172
|
+
if self.codomain().cardinality() != G.num_verts():
|
|
173
|
+
return False
|
|
174
|
+
H = self.codomain().digraph(index_set=index_set)
|
|
175
|
+
return G.is_isomorphic(H, edge_labels=True)
|
|
176
|
+
|
|
177
|
+
# TODO: This could be moved to sets
|
|
178
|
+
@cached_method
|
|
179
|
+
def is_embedding(self):
|
|
180
|
+
"""
|
|
181
|
+
Check if ``self`` is an injective crystal morphism.
|
|
182
|
+
|
|
183
|
+
EXAMPLES::
|
|
184
|
+
|
|
185
|
+
sage: B = crystals.Tableaux(['C',2], shape=[1,1])
|
|
186
|
+
sage: C = crystals.Tableaux(['C',2], ([2,1], [1,1]))
|
|
187
|
+
sage: psi = B.crystal_morphism(C.module_generators[1:], codomain=C)
|
|
188
|
+
sage: psi.is_embedding()
|
|
189
|
+
True
|
|
190
|
+
|
|
191
|
+
sage: C = crystals.Tableaux(['A',2], shape=[2,1])
|
|
192
|
+
sage: B = crystals.infinity.Tableaux(['A',2])
|
|
193
|
+
sage: La = RootSystem(['A',2]).weight_lattice().fundamental_weights()
|
|
194
|
+
sage: W = crystals.elementary.T(['A',2], La[1]+La[2])
|
|
195
|
+
sage: T = W.tensor(B)
|
|
196
|
+
sage: mg = T(W.module_generators[0], B.module_generators[0])
|
|
197
|
+
sage: psi = Hom(C,T)([mg])
|
|
198
|
+
sage: psi.is_embedding()
|
|
199
|
+
True
|
|
200
|
+
"""
|
|
201
|
+
if self.domain().cardinality() > self.codomain().cardinality():
|
|
202
|
+
return False
|
|
203
|
+
if self.domain().cardinality() == float('inf'):
|
|
204
|
+
raise NotImplementedError("unable to determine if an embedding")
|
|
205
|
+
S = set()
|
|
206
|
+
for x in self.domain():
|
|
207
|
+
y = self(x)
|
|
208
|
+
if y is None or y in S:
|
|
209
|
+
return False
|
|
210
|
+
S.add(y)
|
|
211
|
+
return True
|
|
212
|
+
|
|
213
|
+
@cached_method
|
|
214
|
+
def is_strict(self):
|
|
215
|
+
"""
|
|
216
|
+
Check if ``self`` is a strict crystal morphism.
|
|
217
|
+
|
|
218
|
+
EXAMPLES::
|
|
219
|
+
|
|
220
|
+
sage: B = crystals.Tableaux(['C',2], shape=[1,1])
|
|
221
|
+
sage: C = crystals.Tableaux(['C',2], ([2,1], [1,1]))
|
|
222
|
+
sage: psi = B.crystal_morphism(C.module_generators[1:], codomain=C)
|
|
223
|
+
sage: psi.is_strict()
|
|
224
|
+
True
|
|
225
|
+
"""
|
|
226
|
+
if self.domain().cardinality() == float('inf'):
|
|
227
|
+
raise NotImplementedError("unable to determine if strict")
|
|
228
|
+
index_set = self._cartan_type.index_set()
|
|
229
|
+
for x in self.domain():
|
|
230
|
+
y = self(x)
|
|
231
|
+
if any(self(x.f(i)) != y.f(i) or self(x.e(i)) != y.e(i)
|
|
232
|
+
for i in index_set):
|
|
233
|
+
return False
|
|
234
|
+
return True
|
|
235
|
+
|
|
236
|
+
class ParentMethods:
|
|
237
|
+
|
|
238
|
+
def an_element(self):
|
|
239
|
+
"""
|
|
240
|
+
Return an element of ``self``.
|
|
241
|
+
|
|
242
|
+
sage: C = crystals.Letters(['A', 5])
|
|
243
|
+
sage: C.an_element()
|
|
244
|
+
1
|
|
245
|
+
"""
|
|
246
|
+
return self.first()
|
|
247
|
+
|
|
248
|
+
@cached_method
|
|
249
|
+
def weight_lattice_realization(self):
|
|
250
|
+
"""
|
|
251
|
+
Return the weight lattice realization used to express weights
|
|
252
|
+
in ``self``.
|
|
253
|
+
|
|
254
|
+
This default implementation uses the ambient space of the
|
|
255
|
+
root system for (non relabelled) finite types and the
|
|
256
|
+
weight lattice otherwise. This is a legacy from when
|
|
257
|
+
ambient spaces were partially implemented, and may be
|
|
258
|
+
changed in the future.
|
|
259
|
+
|
|
260
|
+
For affine types, this returns the extended weight lattice
|
|
261
|
+
by default.
|
|
262
|
+
|
|
263
|
+
EXAMPLES::
|
|
264
|
+
|
|
265
|
+
sage: C = crystals.Letters(['A', 5])
|
|
266
|
+
sage: C.weight_lattice_realization()
|
|
267
|
+
Ambient space of the Root system of type ['A', 5]
|
|
268
|
+
sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1)
|
|
269
|
+
sage: K.weight_lattice_realization()
|
|
270
|
+
Weight lattice of the Root system of type ['A', 2, 1]
|
|
271
|
+
|
|
272
|
+
TESTS:
|
|
273
|
+
|
|
274
|
+
Check that crystals have the correct weight lattice realization::
|
|
275
|
+
|
|
276
|
+
sage: A = crystals.KirillovReshetikhin(['A',2,1], 1, 1).affinization()
|
|
277
|
+
sage: A.weight_lattice_realization()
|
|
278
|
+
Extended weight lattice of the Root system of type ['A', 2, 1]
|
|
279
|
+
|
|
280
|
+
sage: B = crystals.AlcovePaths(['A',2,1],[1,0,0])
|
|
281
|
+
sage: B.weight_lattice_realization()
|
|
282
|
+
Extended weight lattice of the Root system of type ['A', 2, 1]
|
|
283
|
+
|
|
284
|
+
sage: C = crystals.AlcovePaths("B3",[1,0,0])
|
|
285
|
+
sage: C.weight_lattice_realization()
|
|
286
|
+
Ambient space of the Root system of type ['B', 3]
|
|
287
|
+
|
|
288
|
+
sage: M = crystals.infinity.NakajimaMonomials(['A',3,2])
|
|
289
|
+
sage: M.weight_lattice_realization()
|
|
290
|
+
Extended weight lattice of the Root system of type ['B', 2, 1]^*
|
|
291
|
+
sage: M = crystals.infinity.NakajimaMonomials(['A',2])
|
|
292
|
+
sage: M.weight_lattice_realization()
|
|
293
|
+
Ambient space of the Root system of type ['A', 2]
|
|
294
|
+
sage: A = CartanMatrix([[2,-3],[-3,2]])
|
|
295
|
+
sage: M = crystals.infinity.NakajimaMonomials(A)
|
|
296
|
+
sage: M.weight_lattice_realization()
|
|
297
|
+
Weight lattice of the Root system of type Dynkin diagram of rank 2
|
|
298
|
+
|
|
299
|
+
sage: Y = crystals.infinity.GeneralizedYoungWalls(3)
|
|
300
|
+
sage: Y.weight_lattice_realization()
|
|
301
|
+
Extended weight lattice of the Root system of type ['A', 3, 1]
|
|
302
|
+
"""
|
|
303
|
+
F = self.cartan_type().root_system()
|
|
304
|
+
if self.cartan_type().is_finite() and F.ambient_space() is not None:
|
|
305
|
+
return F.ambient_space()
|
|
306
|
+
if self.cartan_type().is_affine():
|
|
307
|
+
return F.weight_lattice(extended=True)
|
|
308
|
+
return F.weight_lattice()
|
|
309
|
+
|
|
310
|
+
def cartan_type(self):
|
|
311
|
+
"""
|
|
312
|
+
Return the Cartan type of the crystal.
|
|
313
|
+
|
|
314
|
+
EXAMPLES::
|
|
315
|
+
|
|
316
|
+
sage: C = crystals.Letters(['A',2])
|
|
317
|
+
sage: C.cartan_type()
|
|
318
|
+
['A', 2]
|
|
319
|
+
"""
|
|
320
|
+
return self._cartan_type
|
|
321
|
+
|
|
322
|
+
@cached_method
|
|
323
|
+
def index_set(self):
|
|
324
|
+
"""
|
|
325
|
+
Return the index set of the Dynkin diagram underlying the crystal.
|
|
326
|
+
|
|
327
|
+
EXAMPLES::
|
|
328
|
+
|
|
329
|
+
sage: C = crystals.Letters(['A', 5])
|
|
330
|
+
sage: C.index_set()
|
|
331
|
+
(1, 2, 3, 4, 5)
|
|
332
|
+
"""
|
|
333
|
+
return self.cartan_type().index_set()
|
|
334
|
+
|
|
335
|
+
def Lambda(self):
|
|
336
|
+
"""
|
|
337
|
+
Return the fundamental weights in the weight lattice
|
|
338
|
+
realization for the root system associated with the crystal
|
|
339
|
+
|
|
340
|
+
EXAMPLES::
|
|
341
|
+
|
|
342
|
+
sage: C = crystals.Letters(['A', 5])
|
|
343
|
+
sage: C.Lambda()
|
|
344
|
+
Finite family {1: (1, 0, 0, 0, 0, 0), 2: (1, 1, 0, 0, 0, 0), 3: (1, 1, 1, 0, 0, 0), 4: (1, 1, 1, 1, 0, 0), 5: (1, 1, 1, 1, 1, 0)}
|
|
345
|
+
"""
|
|
346
|
+
return self.weight_lattice_realization().fundamental_weights()
|
|
347
|
+
|
|
348
|
+
def __iter__(self, index_set=None, max_depth=float('inf')):
|
|
349
|
+
"""
|
|
350
|
+
Return an iterator over the elements of ``self``.
|
|
351
|
+
|
|
352
|
+
INPUT:
|
|
353
|
+
|
|
354
|
+
- ``index_set`` -- (default: ``None``) the index set; if ``None``
|
|
355
|
+
then use the index set of the crystal
|
|
356
|
+
|
|
357
|
+
- ``max_depth`` -- (default: infinity) the maximum depth to build
|
|
358
|
+
|
|
359
|
+
The iteration order is not specified except that, if
|
|
360
|
+
``max_depth`` is finite, then the iteration goes depth by
|
|
361
|
+
depth.
|
|
362
|
+
|
|
363
|
+
EXAMPLES::
|
|
364
|
+
|
|
365
|
+
sage: C = crystals.LSPaths(['A',2,1],[-1,0,1])
|
|
366
|
+
sage: C.__iter__.__module__
|
|
367
|
+
'sage.categories.crystals'
|
|
368
|
+
sage: g = C.__iter__()
|
|
369
|
+
sage: for _ in range(5): next(g)
|
|
370
|
+
(-Lambda[0] + Lambda[2],)
|
|
371
|
+
(Lambda[1] - Lambda[2],)
|
|
372
|
+
(Lambda[0] - Lambda[1] + delta,)
|
|
373
|
+
(Lambda[0] - Lambda[1],)
|
|
374
|
+
(Lambda[1] - Lambda[2] + delta,)
|
|
375
|
+
|
|
376
|
+
sage: sorted(C.__iter__(index_set=[1,2]), key=str)
|
|
377
|
+
[(-Lambda[0] + Lambda[2],),
|
|
378
|
+
(Lambda[0] - Lambda[1],),
|
|
379
|
+
(Lambda[1] - Lambda[2],)]
|
|
380
|
+
|
|
381
|
+
sage: sorted(C.__iter__(max_depth=1), key=str)
|
|
382
|
+
[(-Lambda[0] + Lambda[2],),
|
|
383
|
+
(Lambda[0] - Lambda[1] + delta,),
|
|
384
|
+
(Lambda[1] - Lambda[2],)]
|
|
385
|
+
"""
|
|
386
|
+
if index_set is None:
|
|
387
|
+
index_set = self.index_set()
|
|
388
|
+
succ = lambda x: [x.f(i) for i in index_set] + [x.e(i) for i in index_set]
|
|
389
|
+
from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet
|
|
390
|
+
R = RecursivelyEnumeratedSet(self.module_generators, succ, structure=None)
|
|
391
|
+
return R.breadth_first_search_iterator(max_depth)
|
|
392
|
+
|
|
393
|
+
def subcrystal(self, index_set=None, generators=None, max_depth=float('inf'),
|
|
394
|
+
direction='both', contained=None,
|
|
395
|
+
virtualization=None, scaling_factors=None,
|
|
396
|
+
cartan_type=None, category=None):
|
|
397
|
+
r"""
|
|
398
|
+
Construct the subcrystal from ``generators`` using `e_i` and/or
|
|
399
|
+
`f_i` for all `i` in ``index_set``.
|
|
400
|
+
|
|
401
|
+
INPUT:
|
|
402
|
+
|
|
403
|
+
- ``index_set`` -- (default: ``None``) the index set; if ``None``
|
|
404
|
+
then use the index set of the crystal
|
|
405
|
+
|
|
406
|
+
- ``generators`` -- (default: ``None``) the list of generators; if
|
|
407
|
+
``None`` then use the module generators of the crystal
|
|
408
|
+
|
|
409
|
+
- ``max_depth`` -- (default: infinity) the maximum depth to build
|
|
410
|
+
|
|
411
|
+
- ``direction`` -- (default: ``'both'``) the direction to build
|
|
412
|
+
the subcrystal; it can be one of the following:
|
|
413
|
+
|
|
414
|
+
- ``'both'`` -- using both `e_i` and `f_i`
|
|
415
|
+
- ``'upper'`` -- using `e_i`
|
|
416
|
+
- ``'lower'`` -- using `f_i`
|
|
417
|
+
|
|
418
|
+
- ``contained`` -- (optional) a set or function defining the
|
|
419
|
+
containment in the subcrystal
|
|
420
|
+
|
|
421
|
+
- ``virtualization``, ``scaling_factors`` -- (optional)
|
|
422
|
+
dictionaries whose key `i` corresponds to the sets `\sigma_i`
|
|
423
|
+
and `\gamma_i` respectively used to define virtual crystals; see
|
|
424
|
+
:class:`~sage.combinat.crystals.virtual_crystal.VirtualCrystal`
|
|
425
|
+
|
|
426
|
+
- ``cartan_type`` -- (optional) specify the Cartan type of the
|
|
427
|
+
subcrystal
|
|
428
|
+
|
|
429
|
+
- ``category`` -- (optional) specify the category of the subcrystal
|
|
430
|
+
|
|
431
|
+
EXAMPLES::
|
|
432
|
+
|
|
433
|
+
sage: C = crystals.KirillovReshetikhin(['A',3,1], 1, 2)
|
|
434
|
+
sage: S = list(C.subcrystal(index_set=[1,2])); S
|
|
435
|
+
[[[1, 1]], [[1, 2]], [[2, 2]], [[1, 3]], [[2, 3]], [[3, 3]]]
|
|
436
|
+
sage: C.cardinality()
|
|
437
|
+
10
|
|
438
|
+
sage: len(S)
|
|
439
|
+
6
|
|
440
|
+
sage: list(C.subcrystal(index_set=[1,3], generators=[C(1,4)]))
|
|
441
|
+
[[[1, 4]], [[2, 4]], [[1, 3]], [[2, 3]]]
|
|
442
|
+
sage: list(C.subcrystal(index_set=[1,3], generators=[C(1,4)], max_depth=1))
|
|
443
|
+
[[[1, 4]], [[2, 4]], [[1, 3]]]
|
|
444
|
+
sage: list(C.subcrystal(index_set=[1,3], generators=[C(1,4)], direction='upper'))
|
|
445
|
+
[[[1, 4]], [[1, 3]]]
|
|
446
|
+
sage: list(C.subcrystal(index_set=[1,3], generators=[C(1,4)], direction='lower'))
|
|
447
|
+
[[[1, 4]], [[2, 4]]]
|
|
448
|
+
|
|
449
|
+
sage: G = C.subcrystal(index_set=[1,2,3]).digraph()
|
|
450
|
+
sage: GA = crystals.Tableaux('A3', shape=[2]).digraph()
|
|
451
|
+
sage: G.is_isomorphic(GA, edge_labels=True)
|
|
452
|
+
True
|
|
453
|
+
|
|
454
|
+
We construct the subcrystal which contains the necessary data
|
|
455
|
+
to construct the corresponding dual equivalence graph::
|
|
456
|
+
|
|
457
|
+
sage: C = crystals.Tableaux(['A',5], shape=[3,3])
|
|
458
|
+
sage: is_wt0 = lambda x: all(x.epsilon(i) == x.phi(i) for i in x.parent().index_set())
|
|
459
|
+
sage: def check(x):
|
|
460
|
+
....: if is_wt0(x):
|
|
461
|
+
....: return True
|
|
462
|
+
....: for i in x.parent().index_set()[:-1]:
|
|
463
|
+
....: L = [x.e(i), x.e_string([i,i+1]), x.f(i), x.f_string([i,i+1])]
|
|
464
|
+
....: if any(y is not None and is_wt0(y) for y in L):
|
|
465
|
+
....: return True
|
|
466
|
+
....: return False
|
|
467
|
+
sage: wt0 = [x for x in C if is_wt0(x)]
|
|
468
|
+
sage: S = C.subcrystal(contained=check, generators=wt0)
|
|
469
|
+
sage: S.module_generators[0]
|
|
470
|
+
[[1, 3, 5], [2, 4, 6]]
|
|
471
|
+
sage: S.module_generators[0].e(2).e(3).f(2).f(3)
|
|
472
|
+
[[1, 2, 5], [3, 4, 6]]
|
|
473
|
+
|
|
474
|
+
An example of a type `B_2` virtual crystal inside of a
|
|
475
|
+
type `A_3` ambient crystal::
|
|
476
|
+
|
|
477
|
+
sage: A = crystals.Tableaux(['A',3], shape=[2,1,1])
|
|
478
|
+
sage: S = A.subcrystal(virtualization={1:[1,3], 2:[2]},
|
|
479
|
+
....: scaling_factors={1:1,2:1}, cartan_type=['B',2])
|
|
480
|
+
sage: B = crystals.Tableaux(['B',2], shape=[1])
|
|
481
|
+
sage: S.digraph().is_isomorphic(B.digraph(), edge_labels=True)
|
|
482
|
+
True
|
|
483
|
+
|
|
484
|
+
TESTS:
|
|
485
|
+
|
|
486
|
+
Check that :issue:`23942` is fixed::
|
|
487
|
+
|
|
488
|
+
sage: B = crystals.infinity.Tableaux(['A',2])
|
|
489
|
+
sage: S = B.subcrystal(max_depth=3, category=HighestWeightCrystals())
|
|
490
|
+
sage: S.category()
|
|
491
|
+
Category of finite highest weight crystals
|
|
492
|
+
|
|
493
|
+
sage: K = crystals.KirillovReshetikhin(['A',3,1], 2,3)
|
|
494
|
+
sage: S = K.subcrystal(index_set=[1,3], category=HighestWeightCrystals())
|
|
495
|
+
sage: S.category()
|
|
496
|
+
Category of finite highest weight crystals
|
|
497
|
+
"""
|
|
498
|
+
from sage.combinat.crystals.subcrystal import Subcrystal
|
|
499
|
+
from sage.categories.finite_crystals import FiniteCrystals
|
|
500
|
+
|
|
501
|
+
if cartan_type is None:
|
|
502
|
+
cartan_type = self.cartan_type()
|
|
503
|
+
else:
|
|
504
|
+
from sage.combinat.root_system.cartan_type import CartanType
|
|
505
|
+
cartan_type = CartanType(cartan_type)
|
|
506
|
+
if index_set is None:
|
|
507
|
+
index_set = cartan_type.index_set()
|
|
508
|
+
if generators is None:
|
|
509
|
+
generators = self.module_generators
|
|
510
|
+
|
|
511
|
+
if max_depth == float('inf'):
|
|
512
|
+
if self not in FiniteCrystals():
|
|
513
|
+
if (contained is None and index_set == self.index_set()
|
|
514
|
+
and generators == self.module_generators
|
|
515
|
+
and scaling_factors is None and virtualization is None):
|
|
516
|
+
return self
|
|
517
|
+
return Subcrystal(self, contained, generators,
|
|
518
|
+
virtualization, scaling_factors,
|
|
519
|
+
cartan_type, index_set, category)
|
|
520
|
+
|
|
521
|
+
# else self is a finite crystal
|
|
522
|
+
if direction == 'both':
|
|
523
|
+
if category is None:
|
|
524
|
+
category = FiniteCrystals()
|
|
525
|
+
else:
|
|
526
|
+
category = FiniteCrystals() & category
|
|
527
|
+
return Subcrystal(self, contained, generators,
|
|
528
|
+
virtualization, scaling_factors,
|
|
529
|
+
cartan_type, index_set, category)
|
|
530
|
+
|
|
531
|
+
# TODO: Make this work for virtual crystals as well
|
|
532
|
+
if direction == 'both':
|
|
533
|
+
succ = lambda x: [x.f(i) for i in index_set] + [x.e(i) for i in index_set]
|
|
534
|
+
elif direction == 'upper':
|
|
535
|
+
succ = lambda x: [x.e(i) for i in index_set]
|
|
536
|
+
elif direction == 'lower':
|
|
537
|
+
succ = lambda x: [x.f(i) for i in index_set]
|
|
538
|
+
else:
|
|
539
|
+
raise ValueError("direction must be either 'both', 'upper', or 'lower'")
|
|
540
|
+
|
|
541
|
+
from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet
|
|
542
|
+
subset = RecursivelyEnumeratedSet(generators, succ,
|
|
543
|
+
structure=None, enumeration='breadth',
|
|
544
|
+
max_depth=max_depth)
|
|
545
|
+
|
|
546
|
+
# We perform the filtering here since checking containment
|
|
547
|
+
# in a frozenset should be fast
|
|
548
|
+
if contained is not None:
|
|
549
|
+
try:
|
|
550
|
+
subset = frozenset(x for x in subset if x in contained)
|
|
551
|
+
except TypeError: # It does not have a containment test
|
|
552
|
+
subset = frozenset(x for x in subset if contained(x))
|
|
553
|
+
else:
|
|
554
|
+
subset = frozenset(subset)
|
|
555
|
+
|
|
556
|
+
if category is None:
|
|
557
|
+
category = FiniteCrystals()
|
|
558
|
+
else:
|
|
559
|
+
category = FiniteCrystals() & category
|
|
560
|
+
|
|
561
|
+
if self in FiniteCrystals() and len(subset) == self.cardinality():
|
|
562
|
+
if index_set == self.index_set():
|
|
563
|
+
return self
|
|
564
|
+
|
|
565
|
+
return Subcrystal(self, subset, generators,
|
|
566
|
+
virtualization, scaling_factors,
|
|
567
|
+
cartan_type, index_set, category)
|
|
568
|
+
|
|
569
|
+
def _Hom_(self, Y, category=None, **options):
|
|
570
|
+
r"""
|
|
571
|
+
Return the homset from ``self`` to ``Y`` in the
|
|
572
|
+
category ``category``.
|
|
573
|
+
|
|
574
|
+
INPUT:
|
|
575
|
+
|
|
576
|
+
- ``Y`` -- a crystal
|
|
577
|
+
- ``category`` -- a subcategory of :class:`Crystals`() or ``None``
|
|
578
|
+
|
|
579
|
+
The sole purpose of this method is to construct the homset
|
|
580
|
+
as a :class:`~sage.categories.crystals.CrystalHomset`. If
|
|
581
|
+
``category`` is specified and is not a subcategory of
|
|
582
|
+
:class:`Crystals`, a :exc:`TypeError` is raised instead.
|
|
583
|
+
|
|
584
|
+
This method is not meant to be called directly. Please use
|
|
585
|
+
:func:`sage.categories.homset.Hom` instead.
|
|
586
|
+
|
|
587
|
+
EXAMPLES::
|
|
588
|
+
|
|
589
|
+
sage: B = crystals.elementary.B(['A',2], 1)
|
|
590
|
+
sage: H = B._Hom_(B); H
|
|
591
|
+
Set of Crystal Morphisms from The 1-elementary crystal of type ['A', 2]
|
|
592
|
+
to The 1-elementary crystal of type ['A', 2]
|
|
593
|
+
"""
|
|
594
|
+
if category is None:
|
|
595
|
+
category = self.category()
|
|
596
|
+
elif not category.is_subcategory(Crystals()):
|
|
597
|
+
raise TypeError("{} is not a subcategory of Crystals()".format(category))
|
|
598
|
+
if Y not in Crystals():
|
|
599
|
+
raise TypeError("{} is not a crystal".format(Y))
|
|
600
|
+
return CrystalHomset(self, Y, category=category, **options)
|
|
601
|
+
|
|
602
|
+
def crystal_morphism(self, on_gens, codomain=None,
|
|
603
|
+
cartan_type=None, index_set=None, generators=None,
|
|
604
|
+
automorphism=None,
|
|
605
|
+
virtualization=None, scaling_factors=None,
|
|
606
|
+
category=None, check=True):
|
|
607
|
+
r"""
|
|
608
|
+
Construct a crystal morphism from ``self`` to another crystal
|
|
609
|
+
``codomain``.
|
|
610
|
+
|
|
611
|
+
INPUT:
|
|
612
|
+
|
|
613
|
+
- ``on_gens`` -- a function or list that determines the image
|
|
614
|
+
of the generators (if given a list, then this uses the order
|
|
615
|
+
of the generators of the domain) of ``self`` under the
|
|
616
|
+
crystal morphism
|
|
617
|
+
- ``codomain`` -- (default: ``self``) the codomain of the morphism
|
|
618
|
+
- ``cartan_type`` -- (optional) the Cartan type of the morphism;
|
|
619
|
+
the default is the Cartan type of ``self``
|
|
620
|
+
- ``index_set`` -- (optional) the index set of the morphism;
|
|
621
|
+
the default is the index set of the Cartan type
|
|
622
|
+
- ``generators`` -- (optional) the generators to define the
|
|
623
|
+
morphism; the default is the generators of ``self``
|
|
624
|
+
- ``automorphism`` -- (optional) the automorphism to perform the
|
|
625
|
+
twisting
|
|
626
|
+
- ``virtualization`` -- (optional) a dictionary whose keys are
|
|
627
|
+
in the index set of the domain and whose values are lists of
|
|
628
|
+
entries in the index set of the codomain; the default is the
|
|
629
|
+
identity dictionary
|
|
630
|
+
- ``scaling_factors`` -- (optional) a dictionary whose keys are
|
|
631
|
+
in the index set of the domain and whose values are scaling
|
|
632
|
+
factors for the weight, `\varepsilon` and `\varphi`; the
|
|
633
|
+
default are all scaling factors to be one
|
|
634
|
+
- ``category`` -- (optional) the category for the crystal morphism;
|
|
635
|
+
the default is the category of :class:`Crystals`.
|
|
636
|
+
- ``check`` -- boolean (default: ``True``); check if the crystal
|
|
637
|
+
morphism is valid
|
|
638
|
+
|
|
639
|
+
.. SEEALSO::
|
|
640
|
+
|
|
641
|
+
For more examples, see
|
|
642
|
+
:class:`sage.categories.crystals.CrystalHomset`.
|
|
643
|
+
|
|
644
|
+
EXAMPLES:
|
|
645
|
+
|
|
646
|
+
We construct the natural embedding of a crystal using tableaux
|
|
647
|
+
into the tensor product of single boxes via the reading word::
|
|
648
|
+
|
|
649
|
+
sage: B = crystals.Tableaux(['A',2], shape=[2,1])
|
|
650
|
+
sage: F = crystals.Tableaux(['A',2], shape=[1])
|
|
651
|
+
sage: T = crystals.TensorProduct(F, F, F)
|
|
652
|
+
sage: mg = T.highest_weight_vectors()[2]; mg
|
|
653
|
+
[[[1]], [[2]], [[1]]]
|
|
654
|
+
sage: psi = B.crystal_morphism([mg], codomain=T); psi
|
|
655
|
+
['A', 2] Crystal morphism:
|
|
656
|
+
From: The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
|
|
657
|
+
To: Full tensor product of the crystals
|
|
658
|
+
[The crystal of tableaux of type ['A', 2] and shape(s) [[1]],
|
|
659
|
+
The crystal of tableaux of type ['A', 2] and shape(s) [[1]],
|
|
660
|
+
The crystal of tableaux of type ['A', 2] and shape(s) [[1]]]
|
|
661
|
+
Defn: [[1, 1], [2]] |--> [[[1]], [[2]], [[1]]]
|
|
662
|
+
sage: b = B.module_generators[0]
|
|
663
|
+
sage: b.pp()
|
|
664
|
+
1 1
|
|
665
|
+
2
|
|
666
|
+
sage: psi(b)
|
|
667
|
+
[[[1]], [[2]], [[1]]]
|
|
668
|
+
sage: psi(b.f(2))
|
|
669
|
+
[[[1]], [[3]], [[1]]]
|
|
670
|
+
sage: psi(b.f_string([2,1,1]))
|
|
671
|
+
[[[2]], [[3]], [[2]]]
|
|
672
|
+
sage: lw = b.to_lowest_weight()[0]
|
|
673
|
+
sage: lw.pp()
|
|
674
|
+
2 3
|
|
675
|
+
3
|
|
676
|
+
sage: psi(lw)
|
|
677
|
+
[[[3]], [[3]], [[2]]]
|
|
678
|
+
sage: psi(lw) == mg.to_lowest_weight()[0]
|
|
679
|
+
True
|
|
680
|
+
|
|
681
|
+
We now take the other isomorphic highest weight component
|
|
682
|
+
in the tensor product::
|
|
683
|
+
|
|
684
|
+
sage: mg = T.highest_weight_vectors()[1]; mg
|
|
685
|
+
[[[2]], [[1]], [[1]]]
|
|
686
|
+
sage: psi = B.crystal_morphism([mg], codomain=T)
|
|
687
|
+
sage: psi(lw)
|
|
688
|
+
[[[3]], [[2]], [[3]]]
|
|
689
|
+
|
|
690
|
+
We construct a crystal morphism of classical crystals using a
|
|
691
|
+
Kirillov-Reshetikhin crystal::
|
|
692
|
+
|
|
693
|
+
sage: B = crystals.Tableaux(['D', 4], shape=[1,1])
|
|
694
|
+
sage: K = crystals.KirillovReshetikhin(['D',4,1], 2,2)
|
|
695
|
+
sage: K.module_generators
|
|
696
|
+
[[], [[1], [2]], [[1, 1], [2, 2]]]
|
|
697
|
+
sage: v = K.module_generators[1]
|
|
698
|
+
sage: psi = B.crystal_morphism([v], codomain=K, category=FiniteCrystals())
|
|
699
|
+
sage: psi
|
|
700
|
+
['D', 4] -> ['D', 4, 1] Virtual Crystal morphism:
|
|
701
|
+
From: The crystal of tableaux of type ['D', 4] and shape(s) [[1, 1]]
|
|
702
|
+
To: Kirillov-Reshetikhin crystal of type ['D', 4, 1] with (r,s)=(2,2)
|
|
703
|
+
Defn: [[1], [2]] |--> [[1], [2]]
|
|
704
|
+
sage: b = B.module_generators[0]
|
|
705
|
+
sage: psi(b)
|
|
706
|
+
[[1], [2]]
|
|
707
|
+
sage: psi(b.to_lowest_weight()[0])
|
|
708
|
+
[[-2], [-1]]
|
|
709
|
+
|
|
710
|
+
We can define crystal morphisms using a different set of
|
|
711
|
+
generators. For example, we construct an example using the
|
|
712
|
+
lowest weight vector::
|
|
713
|
+
|
|
714
|
+
sage: B = crystals.Tableaux(['A',2], shape=[1])
|
|
715
|
+
sage: La = RootSystem(['A',2]).weight_lattice().fundamental_weights()
|
|
716
|
+
sage: T = crystals.elementary.T(['A',2], La[2])
|
|
717
|
+
sage: Bp = T.tensor(B)
|
|
718
|
+
sage: C = crystals.Tableaux(['A',2], shape=[2,1])
|
|
719
|
+
sage: x = C.module_generators[0].f_string([1,2])
|
|
720
|
+
sage: psi = Bp.crystal_morphism([x], generators=Bp.lowest_weight_vectors())
|
|
721
|
+
sage: psi(Bp.highest_weight_vector())
|
|
722
|
+
[[1, 1], [2]]
|
|
723
|
+
|
|
724
|
+
We can also use a dictionary to specify the generators and
|
|
725
|
+
their images::
|
|
726
|
+
|
|
727
|
+
sage: psi = Bp.crystal_morphism({Bp.lowest_weight_vectors()[0]: x})
|
|
728
|
+
sage: psi(Bp.highest_weight_vector())
|
|
729
|
+
[[1, 1], [2]]
|
|
730
|
+
|
|
731
|
+
We construct a twisted crystal morphism induced from the diagram
|
|
732
|
+
automorphism of type `A_3^{(1)}`::
|
|
733
|
+
|
|
734
|
+
sage: La = RootSystem(['A',3,1]).weight_lattice(extended=True).fundamental_weights()
|
|
735
|
+
sage: B0 = crystals.GeneralizedYoungWalls(3, La[0])
|
|
736
|
+
sage: B1 = crystals.GeneralizedYoungWalls(3, La[1])
|
|
737
|
+
sage: phi = B0.crystal_morphism(B1.module_generators, automorphism={0:1, 1:2, 2:3, 3:0})
|
|
738
|
+
sage: phi
|
|
739
|
+
['A', 3, 1] Twisted Crystal morphism:
|
|
740
|
+
From: Highest weight crystal of generalized Young walls of Cartan type ['A', 3, 1] and highest weight Lambda[0]
|
|
741
|
+
To: Highest weight crystal of generalized Young walls of Cartan type ['A', 3, 1] and highest weight Lambda[1]
|
|
742
|
+
Defn: [] |--> []
|
|
743
|
+
sage: x = B0.module_generators[0].f_string([0,1,2,3]); x
|
|
744
|
+
[[0, 3], [1], [2]]
|
|
745
|
+
sage: phi(x)
|
|
746
|
+
[[], [1, 0], [2], [3]]
|
|
747
|
+
|
|
748
|
+
We construct a virtual crystal morphism from type `G_2` into
|
|
749
|
+
type `D_4`::
|
|
750
|
+
|
|
751
|
+
sage: D = crystals.Tableaux(['D',4], shape=[1,1])
|
|
752
|
+
sage: G = crystals.Tableaux(['G',2], shape=[1])
|
|
753
|
+
sage: psi = G.crystal_morphism(D.module_generators,
|
|
754
|
+
....: virtualization={1:[2],2:[1,3,4]},
|
|
755
|
+
....: scaling_factors={1:1, 2:1})
|
|
756
|
+
sage: for x in G:
|
|
757
|
+
....: ascii_art(x, psi(x), sep=' |--> ')
|
|
758
|
+
....: print("")
|
|
759
|
+
1
|
|
760
|
+
1 |--> 2
|
|
761
|
+
<BLANKLINE>
|
|
762
|
+
1
|
|
763
|
+
2 |--> 3
|
|
764
|
+
<BLANKLINE>
|
|
765
|
+
2
|
|
766
|
+
3 |--> -3
|
|
767
|
+
<BLANKLINE>
|
|
768
|
+
3
|
|
769
|
+
0 |--> -3
|
|
770
|
+
<BLANKLINE>
|
|
771
|
+
3
|
|
772
|
+
-3 |--> -2
|
|
773
|
+
<BLANKLINE>
|
|
774
|
+
-3
|
|
775
|
+
-2 |--> -1
|
|
776
|
+
<BLANKLINE>
|
|
777
|
+
-2
|
|
778
|
+
-1 |--> -1
|
|
779
|
+
"""
|
|
780
|
+
# Determine the codomain
|
|
781
|
+
if codomain is None:
|
|
782
|
+
if hasattr(on_gens, 'codomain'):
|
|
783
|
+
codomain = on_gens.codomain()
|
|
784
|
+
elif isinstance(on_gens, collections.abc.Sequence):
|
|
785
|
+
if on_gens:
|
|
786
|
+
codomain = on_gens[0].parent()
|
|
787
|
+
elif isinstance(on_gens, collections.abc.Mapping):
|
|
788
|
+
if on_gens:
|
|
789
|
+
codomain = next(iter(on_gens.values())).parent()
|
|
790
|
+
else:
|
|
791
|
+
for x in self.module_generators:
|
|
792
|
+
y = on_gens(x)
|
|
793
|
+
if y is not None:
|
|
794
|
+
codomain = y.parent()
|
|
795
|
+
break
|
|
796
|
+
if codomain is None:
|
|
797
|
+
codomain = self
|
|
798
|
+
elif codomain not in Crystals():
|
|
799
|
+
raise ValueError("the codomain must be a crystal")
|
|
800
|
+
|
|
801
|
+
homset = Hom(self, codomain, category=category)
|
|
802
|
+
return homset(on_gens, cartan_type, index_set, generators,
|
|
803
|
+
automorphism, virtualization, scaling_factors, check)
|
|
804
|
+
|
|
805
|
+
def digraph(self, subset=None, index_set=None):
|
|
806
|
+
"""
|
|
807
|
+
Return the :class:`DiGraph` associated to ``self``.
|
|
808
|
+
|
|
809
|
+
INPUT:
|
|
810
|
+
|
|
811
|
+
- ``subset`` -- (optional) a subset of vertices for
|
|
812
|
+
which the digraph should be constructed
|
|
813
|
+
|
|
814
|
+
- ``index_set`` -- (optional) the index set to draw arrows
|
|
815
|
+
|
|
816
|
+
EXAMPLES::
|
|
817
|
+
|
|
818
|
+
sage: C = Crystals().example(5)
|
|
819
|
+
sage: C.digraph()
|
|
820
|
+
Digraph on 6 vertices
|
|
821
|
+
|
|
822
|
+
The edges of the crystal graph are by default colored using
|
|
823
|
+
blue for edge 1, red for edge 2, and green for edge 3::
|
|
824
|
+
|
|
825
|
+
sage: C = Crystals().example(3)
|
|
826
|
+
sage: G = C.digraph()
|
|
827
|
+
sage: view(G) # optional - dot2tex graphviz, not tested (opens external window)
|
|
828
|
+
|
|
829
|
+
One may also overwrite the colors::
|
|
830
|
+
|
|
831
|
+
sage: C = Crystals().example(3)
|
|
832
|
+
sage: G = C.digraph()
|
|
833
|
+
sage: G.set_latex_options(color_by_label = {1:"red", 2:"purple", 3:"blue"})
|
|
834
|
+
sage: view(G) # optional - dot2tex graphviz, not tested (opens external window)
|
|
835
|
+
|
|
836
|
+
Or one may add colors to yet unspecified edges::
|
|
837
|
+
|
|
838
|
+
sage: C = Crystals().example(4)
|
|
839
|
+
sage: G = C.digraph()
|
|
840
|
+
sage: C.cartan_type()._index_set_coloring[4]="purple"
|
|
841
|
+
sage: view(G) # optional - dot2tex graphviz, not tested (opens external window)
|
|
842
|
+
|
|
843
|
+
Here is an example of how to take the top part up to a
|
|
844
|
+
given depth of an infinite dimensional crystal::
|
|
845
|
+
|
|
846
|
+
sage: C = CartanType(['C',2,1])
|
|
847
|
+
sage: La = C.root_system().weight_lattice().fundamental_weights()
|
|
848
|
+
sage: T = crystals.HighestWeight(La[0])
|
|
849
|
+
sage: S = T.subcrystal(max_depth=3)
|
|
850
|
+
sage: G = T.digraph(subset=S); G
|
|
851
|
+
Digraph on 5 vertices
|
|
852
|
+
sage: G.vertices(sort=True, key=str)
|
|
853
|
+
[(-Lambda[0] + 2*Lambda[1] - delta,),
|
|
854
|
+
(1/2*Lambda[0] + Lambda[1] - Lambda[2] - 1/2*delta, -1/2*Lambda[0] + Lambda[1] - 1/2*delta),
|
|
855
|
+
(1/2*Lambda[0] - Lambda[1] + Lambda[2] - 1/2*delta, -1/2*Lambda[0] + Lambda[1] - 1/2*delta),
|
|
856
|
+
(Lambda[0] - 2*Lambda[1] + 2*Lambda[2] - delta,),
|
|
857
|
+
(Lambda[0],)]
|
|
858
|
+
|
|
859
|
+
Here is a way to construct a picture of a Demazure crystal using
|
|
860
|
+
the ``subset`` option::
|
|
861
|
+
|
|
862
|
+
sage: B = crystals.Tableaux(['A',2], shape=[2,1])
|
|
863
|
+
sage: t = B.highest_weight_vector()
|
|
864
|
+
sage: D = B.demazure_subcrystal(t, [2,1])
|
|
865
|
+
sage: list(D)
|
|
866
|
+
[[[1, 1], [2]], [[1, 2], [2]], [[1, 1], [3]],
|
|
867
|
+
[[1, 3], [2]], [[1, 3], [3]]]
|
|
868
|
+
sage: view(D) # optional - dot2tex graphviz, not tested (opens external window)
|
|
869
|
+
|
|
870
|
+
We can also choose to display particular arrows using the
|
|
871
|
+
``index_set`` option::
|
|
872
|
+
|
|
873
|
+
sage: C = crystals.KirillovReshetikhin(['D',4,1], 2, 1)
|
|
874
|
+
sage: G = C.digraph(index_set=[1,3])
|
|
875
|
+
sage: len(G.edges(sort=False))
|
|
876
|
+
20
|
|
877
|
+
sage: view(G) # optional - dot2tex graphviz, not tested (opens external window)
|
|
878
|
+
|
|
879
|
+
TESTS:
|
|
880
|
+
|
|
881
|
+
We check that infinite crystals raise an error (:issue:`21986`)::
|
|
882
|
+
|
|
883
|
+
sage: B = crystals.infinity.Tableaux(['A',2])
|
|
884
|
+
sage: B.digraph()
|
|
885
|
+
Traceback (most recent call last):
|
|
886
|
+
...
|
|
887
|
+
NotImplementedError: crystals not known to be finite
|
|
888
|
+
must specify either the subset or depth
|
|
889
|
+
sage: B.digraph(depth=10)
|
|
890
|
+
Digraph on 161 vertices
|
|
891
|
+
|
|
892
|
+
.. TODO:: Add more tests.
|
|
893
|
+
"""
|
|
894
|
+
from sage.graphs.digraph import DiGraph
|
|
895
|
+
d = {}
|
|
896
|
+
|
|
897
|
+
# Parse optional arguments
|
|
898
|
+
if subset is None:
|
|
899
|
+
if self not in Crystals().Finite():
|
|
900
|
+
raise NotImplementedError("crystals not known to be finite"
|
|
901
|
+
" must specify the subset")
|
|
902
|
+
subset = self
|
|
903
|
+
if index_set is None:
|
|
904
|
+
index_set = self.index_set()
|
|
905
|
+
|
|
906
|
+
for x in subset:
|
|
907
|
+
d[x] = {}
|
|
908
|
+
for i in index_set:
|
|
909
|
+
child = x.f(i)
|
|
910
|
+
if child is None or child not in subset:
|
|
911
|
+
continue
|
|
912
|
+
d[x][child] = i
|
|
913
|
+
G = DiGraph(d)
|
|
914
|
+
from sage.graphs.dot2tex_utils import have_dot2tex
|
|
915
|
+
if have_dot2tex():
|
|
916
|
+
G.set_latex_options(format='dot2tex',
|
|
917
|
+
edge_labels=True,
|
|
918
|
+
color_by_label=self.cartan_type()._index_set_coloring)
|
|
919
|
+
return G
|
|
920
|
+
|
|
921
|
+
def latex_file(self, filename):
|
|
922
|
+
r"""
|
|
923
|
+
Export a file, suitable for pdflatex, to ``filename``.
|
|
924
|
+
|
|
925
|
+
This requires
|
|
926
|
+
a proper installation of ``dot2tex`` in sage-python. For more
|
|
927
|
+
information see the documentation for ``self.latex()``.
|
|
928
|
+
|
|
929
|
+
EXAMPLES::
|
|
930
|
+
|
|
931
|
+
sage: C = crystals.Letters(['A', 5])
|
|
932
|
+
sage: fn = tmp_filename(ext='.tex')
|
|
933
|
+
sage: C.latex_file(fn)
|
|
934
|
+
"""
|
|
935
|
+
header = r"""\documentclass{article}
|
|
936
|
+
\usepackage[x11names, rgb]{xcolor}
|
|
937
|
+
\usepackage[utf8]{inputenc}
|
|
938
|
+
\usepackage{tikz}
|
|
939
|
+
\usetikzlibrary{snakes,arrows,shapes}
|
|
940
|
+
\usepackage{amsmath}
|
|
941
|
+
\usepackage[active,tightpage]{preview}
|
|
942
|
+
\newenvironment{bla}{}{}
|
|
943
|
+
\PreviewEnvironment{bla}
|
|
944
|
+
|
|
945
|
+
\begin{document}
|
|
946
|
+
\begin{bla}"""
|
|
947
|
+
|
|
948
|
+
footer = r"""\end{bla}
|
|
949
|
+
\end{document}"""
|
|
950
|
+
|
|
951
|
+
f = open(filename, 'w')
|
|
952
|
+
f.write(header + self.latex() + footer)
|
|
953
|
+
f.close()
|
|
954
|
+
|
|
955
|
+
def _latex_(self, **options):
|
|
956
|
+
r"""
|
|
957
|
+
Return the crystal graph as a latex string. This can be exported
|
|
958
|
+
to a file with ``self.latex_file('filename')``.
|
|
959
|
+
|
|
960
|
+
EXAMPLES::
|
|
961
|
+
|
|
962
|
+
sage: T = crystals.Tableaux(['A',2],shape=[1])
|
|
963
|
+
sage: T._latex_()
|
|
964
|
+
'...tikzpicture...'
|
|
965
|
+
sage: view(T) # optional - dot2tex graphviz, not tested (opens external window)
|
|
966
|
+
|
|
967
|
+
One can for example also color the edges using the following options::
|
|
968
|
+
|
|
969
|
+
sage: T = crystals.Tableaux(['A',2],shape=[1])
|
|
970
|
+
sage: T._latex_(color_by_label={0:"black", 1:"red", 2:"blue"})
|
|
971
|
+
'...tikzpicture...'
|
|
972
|
+
"""
|
|
973
|
+
G = self.digraph()
|
|
974
|
+
G.set_latex_options(**options)
|
|
975
|
+
return G._latex_()
|
|
976
|
+
|
|
977
|
+
latex = _latex_
|
|
978
|
+
|
|
979
|
+
def metapost(self, filename, thicklines=False, labels=True, scaling_factor=1.0, tallness=1.0):
|
|
980
|
+
r"""
|
|
981
|
+
Export a file, suitable for MetaPost, to ``filename``.
|
|
982
|
+
|
|
983
|
+
Root operators `e(1)` or `f(1)` move along red lines, `e(2)` or `f(2)`
|
|
984
|
+
along green. The highest weight is in the lower left. Vertices with
|
|
985
|
+
the same weight are kept close together. The concise labels on the
|
|
986
|
+
nodes are strings introduced by Berenstein and Zelevinsky and
|
|
987
|
+
Littelmann; see Littelmann's paper Cones, Crystals, Patterns,
|
|
988
|
+
sections 5 and 6.
|
|
989
|
+
|
|
990
|
+
For Cartan types B2 or C2, the pattern has the form
|
|
991
|
+
|
|
992
|
+
`a_2 a_3 a_4 a_1`
|
|
993
|
+
|
|
994
|
+
where `c*a_2 = a_3 = 2*a_4 = 0` and `a_1=0`, with `c=2` for B2, `c=1` for C2.
|
|
995
|
+
Applying `e(2)` `a_1` times, `e(1)` `a_2` times, `e(2)` `a_3` times, `e(1)` `a_4` times
|
|
996
|
+
returns to the highest weight. (Observe that Littelmann writes the
|
|
997
|
+
roots in opposite of the usual order, so our `e(1)` is his `e(2)` for
|
|
998
|
+
these Cartan types.) For type A2, the pattern has the form
|
|
999
|
+
|
|
1000
|
+
`a_3 a_2 a_1`
|
|
1001
|
+
|
|
1002
|
+
where applying `e(1)` `a_3` times, `e(2)` `a_2` times then `e(1)` `a_1` times
|
|
1003
|
+
returns to the highest weight. These data determine the vertex and
|
|
1004
|
+
may be translated into a Gelfand-Tsetlin pattern or tableau.
|
|
1005
|
+
|
|
1006
|
+
INPUT:
|
|
1007
|
+
|
|
1008
|
+
- ``filename`` -- name of the output file, e.g., ``'filename.mp'``
|
|
1009
|
+
|
|
1010
|
+
- ``thicklines`` -- boolean (default: ``True``); for thicker edges
|
|
1011
|
+
|
|
1012
|
+
- ``labels`` -- boolean (default: ``False``); whether to suppress
|
|
1013
|
+
labeling of the vertices
|
|
1014
|
+
|
|
1015
|
+
- ``scaling_factor`` -- (default: ``1.0``) increasing or decreasing the
|
|
1016
|
+
scaling factor changes the size of the image
|
|
1017
|
+
|
|
1018
|
+
- ``tallness`` -- (default: ``1.0``) increasing makes the image taller
|
|
1019
|
+
without increasing the width
|
|
1020
|
+
|
|
1021
|
+
EXAMPLES::
|
|
1022
|
+
|
|
1023
|
+
sage: C = crystals.Letters(['A', 2])
|
|
1024
|
+
sage: C.metapost(tmp_filename())
|
|
1025
|
+
|
|
1026
|
+
::
|
|
1027
|
+
|
|
1028
|
+
sage: C = crystals.Letters(['A', 5])
|
|
1029
|
+
sage: C.metapost(tmp_filename())
|
|
1030
|
+
Traceback (most recent call last):
|
|
1031
|
+
...
|
|
1032
|
+
NotImplementedError
|
|
1033
|
+
"""
|
|
1034
|
+
# FIXME: those tests are not robust
|
|
1035
|
+
# Should use instead self.cartan_type() == CartanType(['B',2])
|
|
1036
|
+
if self.cartan_type()[0] == 'B' and self.cartan_type()[1] == 2:
|
|
1037
|
+
word = [2,1,2,1]
|
|
1038
|
+
elif self.cartan_type()[0] == 'C' and self.cartan_type()[1] == 2:
|
|
1039
|
+
word = [2,1,2,1]
|
|
1040
|
+
elif self.cartan_type()[0] == 'A' and self.cartan_type()[1] == 2:
|
|
1041
|
+
word = [1,2,1]
|
|
1042
|
+
else:
|
|
1043
|
+
raise NotImplementedError
|
|
1044
|
+
size = self.cardinality()
|
|
1045
|
+
string_data = []
|
|
1046
|
+
for i in range(size):
|
|
1047
|
+
turtle = self.list()[i]
|
|
1048
|
+
string_datum = []
|
|
1049
|
+
for j in word:
|
|
1050
|
+
turtlewalk = 0
|
|
1051
|
+
while turtle.e(j) is not None:
|
|
1052
|
+
turtle = turtle.e(j)
|
|
1053
|
+
turtlewalk += 1
|
|
1054
|
+
string_datum.append(turtlewalk)
|
|
1055
|
+
string_data.append(string_datum)
|
|
1056
|
+
|
|
1057
|
+
if self.cartan_type()[0] == 'A':
|
|
1058
|
+
if labels:
|
|
1059
|
+
c0 = int(55*scaling_factor)
|
|
1060
|
+
c1 = int(-25*scaling_factor)
|
|
1061
|
+
c2 = int(45*tallness*scaling_factor)
|
|
1062
|
+
c3 = int(-12*scaling_factor)
|
|
1063
|
+
c4 = int(-12*scaling_factor)
|
|
1064
|
+
else:
|
|
1065
|
+
c0 = int(45*scaling_factor)
|
|
1066
|
+
c1 = int(-20*scaling_factor)
|
|
1067
|
+
c2 = int(35*tallness*scaling_factor)
|
|
1068
|
+
c3 = int(12*scaling_factor)
|
|
1069
|
+
c4 = int(-12*scaling_factor)
|
|
1070
|
+
outstring = "verbatimtex\n\\magnification=600\netex\n\nbeginfig(-1);\nsx:=35; sy:=30;\n\nz1000=(%d,0);\nz1001=(%d,%d);\nz1002=(%d,%d);\nz2001=(-3,3);\nz2002=(3,3);\nz2003=(0,-3);\nz2004=(7,0);\nz2005=(0,7);\nz2006=(-7,0);\nz2007=(0,7);\n\n" % (c0,c1,c2,c3,c4)
|
|
1071
|
+
else:
|
|
1072
|
+
if labels:
|
|
1073
|
+
outstring = "verbatimtex\n\\magnification=600\netex\n\nbeginfig(-1);\n\nsx := %d;\nsy=%d;\n\nz1000=(2*sx,0);\nz1001=(-sx,sy);\nz1002=(-16,-10);\n\nz2001=(0,-3);\nz2002=(-5,3);\nz2003=(0,3);\nz2004=(5,3);\nz2005=(10,1);\nz2006=(0,10);\nz2007=(-10,1);\nz2008=(0,-8);\n\n" % (int(scaling_factor*40),int(tallness*scaling_factor*40))
|
|
1074
|
+
else:
|
|
1075
|
+
outstring = "beginfig(-1);\n\nsx := %d;\nsy := %d;\n\nz1000=(2*sx,0);\nz1001=(-sx,sy);\nz1002=(-5,-5);\n\nz1003=(10,10);\n\n" % (int(scaling_factor*35),int(tallness*scaling_factor*35))
|
|
1076
|
+
for i in range(size):
|
|
1077
|
+
if self.cartan_type()[0] == 'A':
|
|
1078
|
+
[a1,a2,a3] = string_data[i]
|
|
1079
|
+
else:
|
|
1080
|
+
[a1,a2,a3,a4] = string_data[i]
|
|
1081
|
+
shift = 0
|
|
1082
|
+
for j in range(i):
|
|
1083
|
+
if self.cartan_type()[0] == 'A':
|
|
1084
|
+
[b1,b2,b3] = string_data[j]
|
|
1085
|
+
if b1+b3 == a1+a3 and b2 == a2:
|
|
1086
|
+
shift += 1
|
|
1087
|
+
else:
|
|
1088
|
+
[b1,b2,b3,b4] = string_data[j]
|
|
1089
|
+
if b1+b3 == a1+a3 and b2+b4 == a2+a4:
|
|
1090
|
+
shift += 1
|
|
1091
|
+
if self.cartan_type()[0] == 'A':
|
|
1092
|
+
outstring = outstring + "z%d=%d*z1000+%d*z1001+%d*z1002;\n" % (i,a1+a3,a2,shift)
|
|
1093
|
+
else:
|
|
1094
|
+
outstring = outstring + "z%d=%d*z1000+%d*z1001+%d*z1002;\n" % (i,a1+a3,a2+a4,shift)
|
|
1095
|
+
outstring = outstring + "\n"
|
|
1096
|
+
if thicklines:
|
|
1097
|
+
outstring = outstring + "pickup pencircle scaled 2\n\n"
|
|
1098
|
+
for i in range(size):
|
|
1099
|
+
for j in range(1,3):
|
|
1100
|
+
dest = self.list()[i].f(j)
|
|
1101
|
+
if dest is not None:
|
|
1102
|
+
dest = self.list().index(dest)
|
|
1103
|
+
if j == 1:
|
|
1104
|
+
col = "red;"
|
|
1105
|
+
else:
|
|
1106
|
+
col = "green; "
|
|
1107
|
+
if self.cartan_type()[0] == 'A':
|
|
1108
|
+
[a1,a2,a3] = string_data[i] # included to facilitate hand editing of the .mp file
|
|
1109
|
+
outstring = outstring+"draw z%d--z%d withcolor %s %% %d %d %d\n" % (i,dest,col,a1,a2,a3)
|
|
1110
|
+
else:
|
|
1111
|
+
[a1,a2,a3,a4] = string_data[i]
|
|
1112
|
+
outstring = outstring+"draw z%d--z%d withcolor %s %% %d %d %d %d\n" % (i,dest,col,a1,a2,a3,a4)
|
|
1113
|
+
outstring += "\npickup pencircle scaled 3;\n\n"
|
|
1114
|
+
for i in range(self.cardinality()):
|
|
1115
|
+
if labels:
|
|
1116
|
+
if self.cartan_type()[0] == 'A':
|
|
1117
|
+
outstring = outstring+"pickup pencircle scaled 15;\nfill z%d+z2004..z%d+z2006..z%d+z2006..z%d+z2007..cycle withcolor white;\nlabel(btex %d etex, z%d+z2001);\nlabel(btex %d etex, z%d+z2002);\nlabel(btex %d etex, z%d+z2003);\npickup pencircle scaled .5;\ndraw z%d+z2004..z%d+z2006..z%d+z2006..z%d+z2007..cycle;\n" % (i,i,i,i,string_data[i][2],i,string_data[i][1],i,string_data[i][0],i,i,i,i,i)
|
|
1118
|
+
else:
|
|
1119
|
+
outstring = outstring+"%%%d %d %d %d\npickup pencircle scaled 1;\nfill z%d+z2005..z%d+z2006..z%d+z2007..z%d+z2008..cycle withcolor white;\nlabel(btex %d etex, z%d+z2001);\nlabel(btex %d etex, z%d+z2002);\nlabel(btex %d etex, z%d+z2003);\nlabel(btex %d etex, z%d+z2004);\npickup pencircle scaled .5;\ndraw z%d+z2005..z%d+z2006..z%d+z2007..z%d+z2008..cycle;\n\n" % (string_data[i][0],string_data[i][1],string_data[i][2],string_data[i][3],i,i,i,i,string_data[i][0],i,string_data[i][1],i,string_data[i][2],i,string_data[i][3],i,i,i,i,i)
|
|
1120
|
+
else:
|
|
1121
|
+
outstring += "drawdot z%d;\n" % i
|
|
1122
|
+
outstring += "\nendfig;\n\nend;\n\n"
|
|
1123
|
+
|
|
1124
|
+
f = open(filename, 'w')
|
|
1125
|
+
f.write(outstring)
|
|
1126
|
+
f.close()
|
|
1127
|
+
|
|
1128
|
+
def dot_tex(self):
|
|
1129
|
+
r"""
|
|
1130
|
+
Return a dot_tex string representation of ``self``.
|
|
1131
|
+
|
|
1132
|
+
EXAMPLES::
|
|
1133
|
+
|
|
1134
|
+
sage: C = crystals.Letters(['A',2])
|
|
1135
|
+
sage: C.dot_tex()
|
|
1136
|
+
'digraph G { \n node [ shape=plaintext ];\n N_0 [ label = " ", texlbl = "$1$" ];\n N_1 [ label = " ", texlbl = "$2$" ];\n N_2 [ label = " ", texlbl = "$3$" ];\n N_0 -> N_1 [ label = " ", texlbl = "1" ];\n N_1 -> N_2 [ label = " ", texlbl = "2" ];\n}'
|
|
1137
|
+
"""
|
|
1138
|
+
import re
|
|
1139
|
+
from sage.combinat import ranker
|
|
1140
|
+
|
|
1141
|
+
rank = ranker.from_list(self.list())[0]
|
|
1142
|
+
vertex_key = lambda x: "N_"+str(rank(x))
|
|
1143
|
+
|
|
1144
|
+
# To do: check the regular expression
|
|
1145
|
+
# Removing %-style comments, newlines, quotes
|
|
1146
|
+
# This should probably be moved to sage.misc.latex
|
|
1147
|
+
from sage.misc.latex import latex
|
|
1148
|
+
quoted_latex = lambda x: re.sub("\"|\r|(%[^\n]*)?\n","", latex(x))
|
|
1149
|
+
|
|
1150
|
+
result = "digraph G { \n node [ shape=plaintext ];\n"
|
|
1151
|
+
|
|
1152
|
+
for x in self:
|
|
1153
|
+
result += " " + vertex_key(x) + " [ label = \" \", texlbl = \"$"+quoted_latex(x)+"$\" ];\n"
|
|
1154
|
+
for x in self:
|
|
1155
|
+
for i in self.index_set():
|
|
1156
|
+
child = x.f(i)
|
|
1157
|
+
if child is None:
|
|
1158
|
+
continue
|
|
1159
|
+
# result += " " + vertex_key(x) + " -> "+vertex_key(child)+ " [ label = \" \", texlbl = \""+quoted_latex(i)+"\" ];\n"
|
|
1160
|
+
if i == 0:
|
|
1161
|
+
option = "dir = back, "
|
|
1162
|
+
(source, target) = (child, x)
|
|
1163
|
+
else:
|
|
1164
|
+
option = ""
|
|
1165
|
+
(source, target) = (x, child)
|
|
1166
|
+
result += " " + vertex_key(source) + " -> "+vertex_key(target) + " [ "+option+"label = \" \", texlbl = \""+quoted_latex(i)+"\" ];\n"
|
|
1167
|
+
result += "}"
|
|
1168
|
+
return result
|
|
1169
|
+
|
|
1170
|
+
def plot(self, **options):
|
|
1171
|
+
"""
|
|
1172
|
+
Return the plot of ``self`` as a directed graph.
|
|
1173
|
+
|
|
1174
|
+
EXAMPLES::
|
|
1175
|
+
|
|
1176
|
+
sage: C = crystals.Letters(['A', 5])
|
|
1177
|
+
sage: print(C.plot()) # needs sage.plot
|
|
1178
|
+
Graphics object consisting of 17 graphics primitives
|
|
1179
|
+
"""
|
|
1180
|
+
return self.digraph().plot(edge_labels=True, vertex_size=0, **options)
|
|
1181
|
+
|
|
1182
|
+
def plot3d(self, **options):
|
|
1183
|
+
"""
|
|
1184
|
+
Return the 3-dimensional plot of ``self`` as a directed graph.
|
|
1185
|
+
|
|
1186
|
+
EXAMPLES::
|
|
1187
|
+
|
|
1188
|
+
sage: C = crystals.KirillovReshetikhin(['A',3,1],2,1)
|
|
1189
|
+
sage: print(C.plot3d()) # needs sage.plot
|
|
1190
|
+
Graphics3d Object
|
|
1191
|
+
"""
|
|
1192
|
+
G = self.digraph(**options)
|
|
1193
|
+
return G.plot3d()
|
|
1194
|
+
|
|
1195
|
+
def tensor(self, *crystals, **options):
|
|
1196
|
+
"""
|
|
1197
|
+
Return the tensor product of ``self`` with the crystals ``B``.
|
|
1198
|
+
|
|
1199
|
+
EXAMPLES::
|
|
1200
|
+
|
|
1201
|
+
sage: C = crystals.Letters(['A', 3])
|
|
1202
|
+
sage: B = crystals.infinity.Tableaux(['A', 3])
|
|
1203
|
+
sage: T = C.tensor(C, B); T
|
|
1204
|
+
Full tensor product of the crystals
|
|
1205
|
+
[The crystal of letters for type ['A', 3],
|
|
1206
|
+
The crystal of letters for type ['A', 3],
|
|
1207
|
+
The infinity crystal of tableaux of type ['A', 3]]
|
|
1208
|
+
sage: tensor([C, C, B]) is T
|
|
1209
|
+
True
|
|
1210
|
+
|
|
1211
|
+
sage: C = crystals.Letters(['A',2])
|
|
1212
|
+
sage: T = C.tensor(C, C, generators=[[C(2),C(1),C(1)],[C(1),C(2),C(1)]]); T
|
|
1213
|
+
The tensor product of the crystals
|
|
1214
|
+
[The crystal of letters for type ['A', 2],
|
|
1215
|
+
The crystal of letters for type ['A', 2],
|
|
1216
|
+
The crystal of letters for type ['A', 2]]
|
|
1217
|
+
sage: T.module_generators
|
|
1218
|
+
([2, 1, 1], [1, 2, 1])
|
|
1219
|
+
"""
|
|
1220
|
+
from sage.combinat.crystals.tensor_product import TensorProductOfCrystals
|
|
1221
|
+
return TensorProductOfCrystals(self, *crystals, **options)
|
|
1222
|
+
|
|
1223
|
+
def direct_sum(self, X):
|
|
1224
|
+
"""
|
|
1225
|
+
Return the direct sum of ``self`` with ``X``.
|
|
1226
|
+
|
|
1227
|
+
EXAMPLES::
|
|
1228
|
+
|
|
1229
|
+
sage: B = crystals.Tableaux(['A',2], shape=[2,1])
|
|
1230
|
+
sage: C = crystals.Letters(['A',2])
|
|
1231
|
+
sage: B.direct_sum(C)
|
|
1232
|
+
Direct sum of the crystals Family
|
|
1233
|
+
(The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
|
|
1234
|
+
The crystal of letters for type ['A', 2])
|
|
1235
|
+
|
|
1236
|
+
As a shorthand, we can use ``+``::
|
|
1237
|
+
|
|
1238
|
+
sage: B + C
|
|
1239
|
+
Direct sum of the crystals Family
|
|
1240
|
+
(The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
|
|
1241
|
+
The crystal of letters for type ['A', 2])
|
|
1242
|
+
"""
|
|
1243
|
+
if X not in Crystals():
|
|
1244
|
+
raise ValueError("{} is not a crystal".format(X))
|
|
1245
|
+
from sage.combinat.crystals.direct_sum import DirectSumOfCrystals
|
|
1246
|
+
return DirectSumOfCrystals([self, X])
|
|
1247
|
+
|
|
1248
|
+
__add__ = direct_sum
|
|
1249
|
+
|
|
1250
|
+
@abstract_method(optional=True)
|
|
1251
|
+
def connected_components_generators(self):
|
|
1252
|
+
"""
|
|
1253
|
+
Return a tuple of generators for each of the connected components
|
|
1254
|
+
of ``self``.
|
|
1255
|
+
|
|
1256
|
+
EXAMPLES::
|
|
1257
|
+
|
|
1258
|
+
sage: B = crystals.Tableaux(['A',2], shape=[2,1])
|
|
1259
|
+
sage: C = crystals.Letters(['A',2])
|
|
1260
|
+
sage: T = crystals.TensorProduct(B,C)
|
|
1261
|
+
sage: T.connected_components_generators()
|
|
1262
|
+
([[[1, 1], [2]], 1], [[[1, 2], [2]], 1], [[[1, 2], [3]], 1])
|
|
1263
|
+
"""
|
|
1264
|
+
|
|
1265
|
+
def connected_components(self):
|
|
1266
|
+
"""
|
|
1267
|
+
Return the connected components of ``self`` as subcrystals.
|
|
1268
|
+
|
|
1269
|
+
EXAMPLES::
|
|
1270
|
+
|
|
1271
|
+
sage: B = crystals.Tableaux(['A',2], shape=[2,1])
|
|
1272
|
+
sage: C = crystals.Letters(['A',2])
|
|
1273
|
+
sage: T = crystals.TensorProduct(B,C)
|
|
1274
|
+
sage: T.connected_components()
|
|
1275
|
+
[Subcrystal of Full tensor product of the crystals
|
|
1276
|
+
[The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
|
|
1277
|
+
The crystal of letters for type ['A', 2]],
|
|
1278
|
+
Subcrystal of Full tensor product of the crystals
|
|
1279
|
+
[The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
|
|
1280
|
+
The crystal of letters for type ['A', 2]],
|
|
1281
|
+
Subcrystal of Full tensor product of the crystals
|
|
1282
|
+
[The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
|
|
1283
|
+
The crystal of letters for type ['A', 2]]]
|
|
1284
|
+
"""
|
|
1285
|
+
return [self.subcrystal(generators=[mg])
|
|
1286
|
+
for mg in self.connected_components_generators()]
|
|
1287
|
+
|
|
1288
|
+
def number_of_connected_components(self):
|
|
1289
|
+
"""
|
|
1290
|
+
Return the number of connected components of ``self``.
|
|
1291
|
+
|
|
1292
|
+
EXAMPLES::
|
|
1293
|
+
|
|
1294
|
+
sage: B = crystals.Tableaux(['A',2], shape=[2,1])
|
|
1295
|
+
sage: C = crystals.Letters(['A',2])
|
|
1296
|
+
sage: T = crystals.TensorProduct(B,C)
|
|
1297
|
+
sage: T.number_of_connected_components()
|
|
1298
|
+
3
|
|
1299
|
+
"""
|
|
1300
|
+
return len(self.connected_components_generators())
|
|
1301
|
+
|
|
1302
|
+
def is_connected(self):
|
|
1303
|
+
"""
|
|
1304
|
+
Return ``True`` if ``self`` is a connected crystal.
|
|
1305
|
+
|
|
1306
|
+
EXAMPLES::
|
|
1307
|
+
|
|
1308
|
+
sage: B = crystals.Tableaux(['A',2], shape=[2,1])
|
|
1309
|
+
sage: C = crystals.Letters(['A',2])
|
|
1310
|
+
sage: T = crystals.TensorProduct(B,C)
|
|
1311
|
+
sage: B.is_connected()
|
|
1312
|
+
True
|
|
1313
|
+
sage: T.is_connected()
|
|
1314
|
+
False
|
|
1315
|
+
"""
|
|
1316
|
+
return self.number_of_connected_components() == 1
|
|
1317
|
+
|
|
1318
|
+
class ElementMethods:
|
|
1319
|
+
|
|
1320
|
+
@cached_method
|
|
1321
|
+
def index_set(self):
|
|
1322
|
+
"""
|
|
1323
|
+
EXAMPLES::
|
|
1324
|
+
|
|
1325
|
+
sage: C = crystals.Letters(['A',5])
|
|
1326
|
+
sage: C(1).index_set()
|
|
1327
|
+
(1, 2, 3, 4, 5)
|
|
1328
|
+
"""
|
|
1329
|
+
return self.parent().index_set()
|
|
1330
|
+
|
|
1331
|
+
def cartan_type(self):
|
|
1332
|
+
"""
|
|
1333
|
+
Return the Cartan type associated to ``self``.
|
|
1334
|
+
|
|
1335
|
+
EXAMPLES::
|
|
1336
|
+
|
|
1337
|
+
sage: C = crystals.Letters(['A', 5])
|
|
1338
|
+
sage: C(1).cartan_type()
|
|
1339
|
+
['A', 5]
|
|
1340
|
+
"""
|
|
1341
|
+
return self.parent().cartan_type()
|
|
1342
|
+
|
|
1343
|
+
@abstract_method
|
|
1344
|
+
def e(self, i):
|
|
1345
|
+
r"""
|
|
1346
|
+
Return `e_i` of ``self`` if it exists or ``None`` otherwise.
|
|
1347
|
+
|
|
1348
|
+
This method should be implemented by the element class of
|
|
1349
|
+
the crystal.
|
|
1350
|
+
|
|
1351
|
+
EXAMPLES::
|
|
1352
|
+
|
|
1353
|
+
sage: C = Crystals().example(5)
|
|
1354
|
+
sage: x = C[2]; x
|
|
1355
|
+
3
|
|
1356
|
+
sage: x.e(1), x.e(2), x.e(3)
|
|
1357
|
+
(None, 2, None)
|
|
1358
|
+
"""
|
|
1359
|
+
|
|
1360
|
+
@abstract_method
|
|
1361
|
+
def f(self, i):
|
|
1362
|
+
r"""
|
|
1363
|
+
Return `f_i` of ``self`` if it exists or ``None`` otherwise.
|
|
1364
|
+
|
|
1365
|
+
This method should be implemented by the element class of
|
|
1366
|
+
the crystal.
|
|
1367
|
+
|
|
1368
|
+
EXAMPLES::
|
|
1369
|
+
|
|
1370
|
+
sage: C = Crystals().example(5)
|
|
1371
|
+
sage: x = C[1]; x
|
|
1372
|
+
2
|
|
1373
|
+
sage: x.f(1), x.f(2), x.f(3)
|
|
1374
|
+
(None, 3, None)
|
|
1375
|
+
"""
|
|
1376
|
+
|
|
1377
|
+
@abstract_method
|
|
1378
|
+
def epsilon(self, i):
|
|
1379
|
+
r"""
|
|
1380
|
+
EXAMPLES::
|
|
1381
|
+
|
|
1382
|
+
sage: C = crystals.Letters(['A',5])
|
|
1383
|
+
sage: C(1).epsilon(1)
|
|
1384
|
+
0
|
|
1385
|
+
sage: C(2).epsilon(1)
|
|
1386
|
+
1
|
|
1387
|
+
"""
|
|
1388
|
+
|
|
1389
|
+
@abstract_method
|
|
1390
|
+
def phi(self, i):
|
|
1391
|
+
r"""
|
|
1392
|
+
EXAMPLES::
|
|
1393
|
+
|
|
1394
|
+
sage: C = crystals.Letters(['A',5])
|
|
1395
|
+
sage: C(1).phi(1)
|
|
1396
|
+
1
|
|
1397
|
+
sage: C(2).phi(1)
|
|
1398
|
+
0
|
|
1399
|
+
"""
|
|
1400
|
+
|
|
1401
|
+
@abstract_method
|
|
1402
|
+
def weight(self):
|
|
1403
|
+
r"""
|
|
1404
|
+
Return the weight of this crystal element.
|
|
1405
|
+
|
|
1406
|
+
This method should be implemented by the element class of
|
|
1407
|
+
the crystal.
|
|
1408
|
+
|
|
1409
|
+
EXAMPLES::
|
|
1410
|
+
|
|
1411
|
+
sage: C = crystals.Letters(['A',5])
|
|
1412
|
+
sage: C(1).weight()
|
|
1413
|
+
(1, 0, 0, 0, 0, 0)
|
|
1414
|
+
"""
|
|
1415
|
+
|
|
1416
|
+
def phi_minus_epsilon(self, i):
|
|
1417
|
+
r"""
|
|
1418
|
+
Return `\varphi_i - \varepsilon_i` of ``self``.
|
|
1419
|
+
|
|
1420
|
+
There are sometimes better implementations using the
|
|
1421
|
+
weight for this. It is used for reflections along a string.
|
|
1422
|
+
|
|
1423
|
+
EXAMPLES::
|
|
1424
|
+
|
|
1425
|
+
sage: C = crystals.Letters(['A',5])
|
|
1426
|
+
sage: C(1).phi_minus_epsilon(1)
|
|
1427
|
+
1
|
|
1428
|
+
"""
|
|
1429
|
+
return self.phi(i) - self.epsilon(i)
|
|
1430
|
+
|
|
1431
|
+
def Epsilon(self):
|
|
1432
|
+
"""
|
|
1433
|
+
EXAMPLES::
|
|
1434
|
+
|
|
1435
|
+
sage: C = crystals.Letters(['A',5])
|
|
1436
|
+
sage: C(0).Epsilon()
|
|
1437
|
+
(0, 0, 0, 0, 0, 0)
|
|
1438
|
+
sage: C(1).Epsilon()
|
|
1439
|
+
(0, 0, 0, 0, 0, 0)
|
|
1440
|
+
sage: C(2).Epsilon()
|
|
1441
|
+
(1, 0, 0, 0, 0, 0)
|
|
1442
|
+
"""
|
|
1443
|
+
Lambda = self.parent().Lambda()
|
|
1444
|
+
return sum(self.epsilon(i) * Lambda[i] for i in self.index_set())
|
|
1445
|
+
|
|
1446
|
+
def Phi(self):
|
|
1447
|
+
"""
|
|
1448
|
+
EXAMPLES::
|
|
1449
|
+
|
|
1450
|
+
sage: C = crystals.Letters(['A',5])
|
|
1451
|
+
sage: C(0).Phi()
|
|
1452
|
+
(0, 0, 0, 0, 0, 0)
|
|
1453
|
+
sage: C(1).Phi()
|
|
1454
|
+
(1, 0, 0, 0, 0, 0)
|
|
1455
|
+
sage: C(2).Phi()
|
|
1456
|
+
(1, 1, 0, 0, 0, 0)
|
|
1457
|
+
"""
|
|
1458
|
+
Lambda = self.parent().Lambda()
|
|
1459
|
+
return sum(self.phi(i) * Lambda[i] for i in self.index_set())
|
|
1460
|
+
|
|
1461
|
+
def f_string(self, list):
|
|
1462
|
+
r"""
|
|
1463
|
+
Applies `f_{i_r} \cdots f_{i_1}` to ``self`` for ``list`` as
|
|
1464
|
+
`[i_1, ..., i_r]`
|
|
1465
|
+
|
|
1466
|
+
EXAMPLES::
|
|
1467
|
+
|
|
1468
|
+
sage: C = crystals.Letters(['A',3])
|
|
1469
|
+
sage: b = C(1)
|
|
1470
|
+
sage: b.f_string([1,2])
|
|
1471
|
+
3
|
|
1472
|
+
sage: b.f_string([2,1])
|
|
1473
|
+
"""
|
|
1474
|
+
b = self
|
|
1475
|
+
for i in list:
|
|
1476
|
+
b = b.f(i)
|
|
1477
|
+
if b is None:
|
|
1478
|
+
return None
|
|
1479
|
+
return b
|
|
1480
|
+
|
|
1481
|
+
def e_string(self, list):
|
|
1482
|
+
r"""
|
|
1483
|
+
Applies `e_{i_r} \cdots e_{i_1}` to ``self`` for ``list`` as
|
|
1484
|
+
`[i_1, ..., i_r]`
|
|
1485
|
+
|
|
1486
|
+
EXAMPLES::
|
|
1487
|
+
|
|
1488
|
+
sage: C = crystals.Letters(['A',3])
|
|
1489
|
+
sage: b = C(3)
|
|
1490
|
+
sage: b.e_string([2,1])
|
|
1491
|
+
1
|
|
1492
|
+
sage: b.e_string([1,2])
|
|
1493
|
+
"""
|
|
1494
|
+
b = self
|
|
1495
|
+
for i in list:
|
|
1496
|
+
b = b.e(i)
|
|
1497
|
+
if b is None:
|
|
1498
|
+
return None
|
|
1499
|
+
return b
|
|
1500
|
+
|
|
1501
|
+
def s(self, i):
|
|
1502
|
+
r"""
|
|
1503
|
+
Return the reflection of ``self`` along its `i`-string.
|
|
1504
|
+
|
|
1505
|
+
EXAMPLES::
|
|
1506
|
+
|
|
1507
|
+
sage: C = crystals.Tableaux(['A',2], shape=[2,1])
|
|
1508
|
+
sage: b = C(rows=[[1,1],[3]])
|
|
1509
|
+
sage: b.s(1)
|
|
1510
|
+
[[2, 2], [3]]
|
|
1511
|
+
sage: b = C(rows=[[1,2],[3]])
|
|
1512
|
+
sage: b.s(2)
|
|
1513
|
+
[[1, 2], [3]]
|
|
1514
|
+
sage: T = crystals.Tableaux(['A',2],shape=[4])
|
|
1515
|
+
sage: t = T(rows=[[1,2,2,2]])
|
|
1516
|
+
sage: t.s(1)
|
|
1517
|
+
[[1, 1, 1, 2]]
|
|
1518
|
+
"""
|
|
1519
|
+
d = self.phi_minus_epsilon(i)
|
|
1520
|
+
b = self
|
|
1521
|
+
if d > 0:
|
|
1522
|
+
for j in range(d):
|
|
1523
|
+
b = b.f(i)
|
|
1524
|
+
else:
|
|
1525
|
+
for j in range(-d):
|
|
1526
|
+
b = b.e(i)
|
|
1527
|
+
return b
|
|
1528
|
+
|
|
1529
|
+
def is_highest_weight(self, index_set=None):
|
|
1530
|
+
r"""
|
|
1531
|
+
Return ``True`` if ``self`` is a highest weight.
|
|
1532
|
+
|
|
1533
|
+
Specifying the option ``index_set`` to be a subset `I` of the
|
|
1534
|
+
index set of the underlying crystal, finds all highest
|
|
1535
|
+
weight vectors for arrows in `I`.
|
|
1536
|
+
|
|
1537
|
+
EXAMPLES::
|
|
1538
|
+
|
|
1539
|
+
sage: C = crystals.Letters(['A',5])
|
|
1540
|
+
sage: C(1).is_highest_weight()
|
|
1541
|
+
True
|
|
1542
|
+
sage: C(2).is_highest_weight()
|
|
1543
|
+
False
|
|
1544
|
+
sage: C(2).is_highest_weight(index_set = [2,3,4,5])
|
|
1545
|
+
True
|
|
1546
|
+
"""
|
|
1547
|
+
if index_set is None:
|
|
1548
|
+
index_set = self.index_set()
|
|
1549
|
+
return all(self.e(i) is None for i in index_set)
|
|
1550
|
+
|
|
1551
|
+
def is_lowest_weight(self, index_set=None):
|
|
1552
|
+
r"""
|
|
1553
|
+
Return ``True`` if ``self`` is a lowest weight.
|
|
1554
|
+
Specifying the option ``index_set`` to be a subset `I` of the
|
|
1555
|
+
index set of the underlying crystal, finds all lowest
|
|
1556
|
+
weight vectors for arrows in `I`.
|
|
1557
|
+
|
|
1558
|
+
EXAMPLES::
|
|
1559
|
+
|
|
1560
|
+
sage: C = crystals.Letters(['A',5])
|
|
1561
|
+
sage: C(1).is_lowest_weight()
|
|
1562
|
+
False
|
|
1563
|
+
sage: C(6).is_lowest_weight()
|
|
1564
|
+
True
|
|
1565
|
+
sage: C(4).is_lowest_weight(index_set = [1,3])
|
|
1566
|
+
True
|
|
1567
|
+
"""
|
|
1568
|
+
if index_set is None:
|
|
1569
|
+
index_set = self.index_set()
|
|
1570
|
+
return all(self.f(i) is None for i in index_set)
|
|
1571
|
+
|
|
1572
|
+
def to_highest_weight(self, index_set=None):
|
|
1573
|
+
r"""
|
|
1574
|
+
Return the highest weight element `u` and a list `[i_1,...,i_k]`
|
|
1575
|
+
such that ``self`` `= f_{i_1} ... f_{i_k} u`, where `i_1,...,i_k` are
|
|
1576
|
+
elements in ``index_set``.
|
|
1577
|
+
|
|
1578
|
+
By default the ``index_set`` is assumed to be
|
|
1579
|
+
the full index set of ``self``.
|
|
1580
|
+
|
|
1581
|
+
EXAMPLES::
|
|
1582
|
+
|
|
1583
|
+
sage: T = crystals.Tableaux(['A',3], shape = [1])
|
|
1584
|
+
sage: t = T(rows = [[3]])
|
|
1585
|
+
sage: t.to_highest_weight()
|
|
1586
|
+
[[[1]], [2, 1]]
|
|
1587
|
+
sage: T = crystals.Tableaux(['A',3], shape = [2,1])
|
|
1588
|
+
sage: t = T(rows = [[1,2],[4]])
|
|
1589
|
+
sage: t.to_highest_weight()
|
|
1590
|
+
[[[1, 1], [2]], [1, 3, 2]]
|
|
1591
|
+
sage: t.to_highest_weight(index_set = [3])
|
|
1592
|
+
[[[1, 2], [3]], [3]]
|
|
1593
|
+
sage: K = crystals.KirillovReshetikhin(['A',3,1],2,1)
|
|
1594
|
+
sage: t = K(rows=[[2],[3]]); t.to_highest_weight(index_set=[1])
|
|
1595
|
+
[[[1], [3]], [1]]
|
|
1596
|
+
sage: t.to_highest_weight()
|
|
1597
|
+
Traceback (most recent call last):
|
|
1598
|
+
...
|
|
1599
|
+
ValueError: this is not a highest weight crystal
|
|
1600
|
+
"""
|
|
1601
|
+
from sage.categories.highest_weight_crystals import HighestWeightCrystals
|
|
1602
|
+
if index_set is None:
|
|
1603
|
+
if HighestWeightCrystals() not in self.parent().categories():
|
|
1604
|
+
raise ValueError("this is not a highest weight crystal")
|
|
1605
|
+
index_set = self.index_set()
|
|
1606
|
+
for i in index_set:
|
|
1607
|
+
next = self.e(i)
|
|
1608
|
+
if next is not None:
|
|
1609
|
+
hw = next.to_highest_weight(index_set=index_set)
|
|
1610
|
+
return [hw[0], [i] + hw[1]]
|
|
1611
|
+
return [self, []]
|
|
1612
|
+
|
|
1613
|
+
def to_lowest_weight(self, index_set=None):
|
|
1614
|
+
r"""
|
|
1615
|
+
Return the lowest weight element `u` and a list `[i_1,...,i_k]`
|
|
1616
|
+
such that ``self`` `= e_{i_1} ... e_{i_k} u`, where `i_1,...,i_k` are
|
|
1617
|
+
elements in ``index_set``.
|
|
1618
|
+
|
|
1619
|
+
By default the ``index_set`` is assumed to be the full index
|
|
1620
|
+
set of ``self``.
|
|
1621
|
+
|
|
1622
|
+
EXAMPLES::
|
|
1623
|
+
|
|
1624
|
+
sage: T = crystals.Tableaux(['A',3], shape = [1])
|
|
1625
|
+
sage: t = T(rows = [[3]])
|
|
1626
|
+
sage: t.to_lowest_weight()
|
|
1627
|
+
[[[4]], [3]]
|
|
1628
|
+
sage: T = crystals.Tableaux(['A',3], shape = [2,1])
|
|
1629
|
+
sage: t = T(rows = [[1,2],[4]])
|
|
1630
|
+
sage: t.to_lowest_weight()
|
|
1631
|
+
[[[3, 4], [4]], [1, 2, 2, 3]]
|
|
1632
|
+
sage: t.to_lowest_weight(index_set = [3])
|
|
1633
|
+
[[[1, 2], [4]], []]
|
|
1634
|
+
sage: K = crystals.KirillovReshetikhin(['A',3,1],2,1)
|
|
1635
|
+
sage: t = K.module_generator(); t
|
|
1636
|
+
[[1], [2]]
|
|
1637
|
+
sage: t.to_lowest_weight(index_set=[1,2,3])
|
|
1638
|
+
[[[3], [4]], [2, 1, 3, 2]]
|
|
1639
|
+
sage: t.to_lowest_weight()
|
|
1640
|
+
Traceback (most recent call last):
|
|
1641
|
+
...
|
|
1642
|
+
ValueError: this is not a highest weight crystal
|
|
1643
|
+
"""
|
|
1644
|
+
from sage.categories.highest_weight_crystals import HighestWeightCrystals
|
|
1645
|
+
if index_set is None:
|
|
1646
|
+
if HighestWeightCrystals() not in self.parent().categories():
|
|
1647
|
+
raise ValueError("this is not a highest weight crystal")
|
|
1648
|
+
index_set = self.index_set()
|
|
1649
|
+
for i in index_set:
|
|
1650
|
+
next = self.f(i)
|
|
1651
|
+
if next is not None:
|
|
1652
|
+
lw = next.to_lowest_weight(index_set=index_set)
|
|
1653
|
+
return [lw[0], [i] + lw[1]]
|
|
1654
|
+
return [self, []]
|
|
1655
|
+
|
|
1656
|
+
def all_paths_to_highest_weight(self, index_set=None):
|
|
1657
|
+
r"""
|
|
1658
|
+
Iterate over all paths to the highest weight from ``self``
|
|
1659
|
+
with respect to ``index_set``.
|
|
1660
|
+
|
|
1661
|
+
INPUT:
|
|
1662
|
+
|
|
1663
|
+
- ``index_set`` -- (optional) a subset of the index set of ``self``
|
|
1664
|
+
|
|
1665
|
+
EXAMPLES::
|
|
1666
|
+
|
|
1667
|
+
sage: B = crystals.infinity.Tableaux("A2")
|
|
1668
|
+
sage: b0 = B.highest_weight_vector()
|
|
1669
|
+
sage: b = b0.f_string([1, 2, 1, 2])
|
|
1670
|
+
sage: L = b.all_paths_to_highest_weight()
|
|
1671
|
+
sage: list(L)
|
|
1672
|
+
[[2, 1, 2, 1], [2, 2, 1, 1]]
|
|
1673
|
+
|
|
1674
|
+
sage: Y = crystals.infinity.GeneralizedYoungWalls(3)
|
|
1675
|
+
sage: y0 = Y.highest_weight_vector()
|
|
1676
|
+
sage: y = y0.f_string([0, 1, 2, 3, 2, 1, 0])
|
|
1677
|
+
sage: list(y.all_paths_to_highest_weight())
|
|
1678
|
+
[[0, 1, 2, 3, 2, 1, 0],
|
|
1679
|
+
[0, 1, 3, 2, 2, 1, 0],
|
|
1680
|
+
[0, 3, 1, 2, 2, 1, 0],
|
|
1681
|
+
[0, 3, 2, 1, 1, 0, 2],
|
|
1682
|
+
[0, 3, 2, 1, 1, 2, 0]]
|
|
1683
|
+
|
|
1684
|
+
sage: B = crystals.Tableaux("A3", shape=[4,2,1])
|
|
1685
|
+
sage: b0 = B.highest_weight_vector()
|
|
1686
|
+
sage: b = b0.f_string([1, 1, 2, 3])
|
|
1687
|
+
sage: list(b.all_paths_to_highest_weight())
|
|
1688
|
+
[[1, 3, 2, 1], [3, 1, 2, 1], [3, 2, 1, 1]]
|
|
1689
|
+
"""
|
|
1690
|
+
if index_set is None:
|
|
1691
|
+
index_set = self.index_set()
|
|
1692
|
+
hw = True
|
|
1693
|
+
for i in index_set:
|
|
1694
|
+
next = self.e(i)
|
|
1695
|
+
if next is not None:
|
|
1696
|
+
for x in next.all_paths_to_highest_weight(index_set):
|
|
1697
|
+
yield [i] + x
|
|
1698
|
+
hw = False
|
|
1699
|
+
if hw:
|
|
1700
|
+
yield []
|
|
1701
|
+
|
|
1702
|
+
def subcrystal(self, index_set=None, max_depth=float("inf"), direction='both',
|
|
1703
|
+
contained=None, cartan_type=None, category=None):
|
|
1704
|
+
r"""
|
|
1705
|
+
Construct the subcrystal generated by ``self`` using `e_i` and/or
|
|
1706
|
+
`f_i` for all `i` in ``index_set``.
|
|
1707
|
+
|
|
1708
|
+
INPUT:
|
|
1709
|
+
|
|
1710
|
+
- ``index_set`` -- (default: ``None``) the index set; if ``None``
|
|
1711
|
+
then use the index set of the crystal
|
|
1712
|
+
|
|
1713
|
+
- ``max_depth`` -- (default: infinity) the maximum depth to build
|
|
1714
|
+
|
|
1715
|
+
- ``direction`` -- (default: ``'both'``) the direction to build
|
|
1716
|
+
the subcrystal; it can be one of the following:
|
|
1717
|
+
|
|
1718
|
+
- ``'both'`` -- using both `e_i` and `f_i`
|
|
1719
|
+
- ``'upper'`` -- using `e_i`
|
|
1720
|
+
- ``'lower'`` -- using `f_i`
|
|
1721
|
+
|
|
1722
|
+
- ``contained`` -- (optional) a set (or function) defining the
|
|
1723
|
+
containment in the subcrystal
|
|
1724
|
+
|
|
1725
|
+
- ``cartan_type`` -- (optional) specify the Cartan type of the
|
|
1726
|
+
subcrystal
|
|
1727
|
+
|
|
1728
|
+
- ``category`` -- (optional) specify the category of the subcrystal
|
|
1729
|
+
|
|
1730
|
+
.. SEEALSO::
|
|
1731
|
+
|
|
1732
|
+
- :meth:`Crystals.ParentMethods.subcrystal()`
|
|
1733
|
+
|
|
1734
|
+
EXAMPLES::
|
|
1735
|
+
|
|
1736
|
+
sage: C = crystals.KirillovReshetikhin(['A',3,1], 1, 2)
|
|
1737
|
+
sage: elt = C(1,4)
|
|
1738
|
+
sage: list(elt.subcrystal(index_set=[1,3]))
|
|
1739
|
+
[[[1, 4]], [[2, 4]], [[1, 3]], [[2, 3]]]
|
|
1740
|
+
sage: list(elt.subcrystal(index_set=[1,3], max_depth=1))
|
|
1741
|
+
[[[1, 4]], [[2, 4]], [[1, 3]]]
|
|
1742
|
+
sage: list(elt.subcrystal(index_set=[1,3], direction='upper'))
|
|
1743
|
+
[[[1, 4]], [[1, 3]]]
|
|
1744
|
+
sage: list(elt.subcrystal(index_set=[1,3], direction='lower'))
|
|
1745
|
+
[[[1, 4]], [[2, 4]]]
|
|
1746
|
+
|
|
1747
|
+
TESTS:
|
|
1748
|
+
|
|
1749
|
+
Check that :issue:`23942` is fixed::
|
|
1750
|
+
|
|
1751
|
+
sage: K = crystals.KirillovReshetikhin(['A',2,1], 1,1)
|
|
1752
|
+
sage: cat = HighestWeightCrystals().Finite()
|
|
1753
|
+
sage: S = K.module_generator().subcrystal(index_set=[1,2], category=cat)
|
|
1754
|
+
sage: S.category()
|
|
1755
|
+
Category of finite highest weight crystals
|
|
1756
|
+
"""
|
|
1757
|
+
return self.parent().subcrystal(generators=[self], index_set=index_set,
|
|
1758
|
+
max_depth=max_depth, direction=direction,
|
|
1759
|
+
category=category)
|
|
1760
|
+
|
|
1761
|
+
def tensor(self, *elts):
|
|
1762
|
+
r"""
|
|
1763
|
+
Return the tensor product of ``self`` with the crystal
|
|
1764
|
+
elements ``elts``.
|
|
1765
|
+
|
|
1766
|
+
EXAMPLES::
|
|
1767
|
+
|
|
1768
|
+
sage: C = crystals.Letters(['A', 3])
|
|
1769
|
+
sage: B = crystals.infinity.Tableaux(['A', 3])
|
|
1770
|
+
sage: c = C[0]
|
|
1771
|
+
sage: b = B.highest_weight_vector()
|
|
1772
|
+
sage: t = c.tensor(c, b)
|
|
1773
|
+
sage: ascii_art(t)
|
|
1774
|
+
1 1 1
|
|
1775
|
+
1 # 1 # 2 2
|
|
1776
|
+
3
|
|
1777
|
+
sage: tensor([c, c, b]) == t
|
|
1778
|
+
True
|
|
1779
|
+
sage: ascii_art(tensor([b, b, c]))
|
|
1780
|
+
1 1 1 1 1 1
|
|
1781
|
+
2 2 # 2 2 # 1
|
|
1782
|
+
3 3
|
|
1783
|
+
"""
|
|
1784
|
+
T = self.parent().tensor(*[b.parent() for b in elts])
|
|
1785
|
+
return T(self, *elts)
|
|
1786
|
+
|
|
1787
|
+
class SubcategoryMethods:
|
|
1788
|
+
"""
|
|
1789
|
+
Methods for all subcategories.
|
|
1790
|
+
"""
|
|
1791
|
+
def TensorProducts(self):
|
|
1792
|
+
r"""
|
|
1793
|
+
Return the full subcategory of objects of ``self`` constructed
|
|
1794
|
+
as tensor products.
|
|
1795
|
+
|
|
1796
|
+
.. SEEALSO::
|
|
1797
|
+
|
|
1798
|
+
- :class:`.tensor.TensorProductsCategory`
|
|
1799
|
+
- :class:`~.covariant_functorial_construction.RegressiveCovariantFunctorialConstruction`.
|
|
1800
|
+
|
|
1801
|
+
EXAMPLES::
|
|
1802
|
+
|
|
1803
|
+
sage: HighestWeightCrystals().TensorProducts()
|
|
1804
|
+
Category of tensor products of highest weight crystals
|
|
1805
|
+
"""
|
|
1806
|
+
return TensorProductsCategory.category_of(self)
|
|
1807
|
+
|
|
1808
|
+
class TensorProducts(TensorProductsCategory):
|
|
1809
|
+
"""
|
|
1810
|
+
The category of crystals constructed by tensor product of crystals.
|
|
1811
|
+
"""
|
|
1812
|
+
@cached_method
|
|
1813
|
+
def extra_super_categories(self):
|
|
1814
|
+
"""
|
|
1815
|
+
EXAMPLES::
|
|
1816
|
+
|
|
1817
|
+
sage: Crystals().TensorProducts().extra_super_categories()
|
|
1818
|
+
[Category of crystals]
|
|
1819
|
+
"""
|
|
1820
|
+
return [self.base_category()]
|
|
1821
|
+
|
|
1822
|
+
Finite = LazyImport('sage.categories.finite_crystals', 'FiniteCrystals')
|
|
1823
|
+
|
|
1824
|
+
###############################################################################
|
|
1825
|
+
## Morphisms
|
|
1826
|
+
|
|
1827
|
+
|
|
1828
|
+
class CrystalMorphism(Morphism):
|
|
1829
|
+
r"""
|
|
1830
|
+
A crystal morphism.
|
|
1831
|
+
|
|
1832
|
+
INPUT:
|
|
1833
|
+
|
|
1834
|
+
- ``parent`` -- a homset
|
|
1835
|
+
- ``cartan_type`` -- (optional) a Cartan type; the default is the
|
|
1836
|
+
Cartan type of the domain
|
|
1837
|
+
- ``virtualization`` -- (optional) a dictionary whose keys are in
|
|
1838
|
+
the index set of the domain and whose values are lists of entries
|
|
1839
|
+
in the index set of the codomain
|
|
1840
|
+
- ``scaling_factors`` -- (optional) a dictionary whose keys are in
|
|
1841
|
+
the index set of the domain and whose values are scaling factors
|
|
1842
|
+
for the weight, `\varepsilon` and `\varphi`
|
|
1843
|
+
"""
|
|
1844
|
+
def __init__(self, parent, cartan_type=None,
|
|
1845
|
+
virtualization=None, scaling_factors=None):
|
|
1846
|
+
"""
|
|
1847
|
+
Initialize ``self``.
|
|
1848
|
+
|
|
1849
|
+
TESTS::
|
|
1850
|
+
|
|
1851
|
+
sage: B = crystals.Tableaux(['A',2], shape=[2,1])
|
|
1852
|
+
sage: H = Hom(B, B)
|
|
1853
|
+
sage: psi = H.an_element()
|
|
1854
|
+
"""
|
|
1855
|
+
if cartan_type is None:
|
|
1856
|
+
cartan_type = parent.domain().cartan_type()
|
|
1857
|
+
self._cartan_type = cartan_type
|
|
1858
|
+
|
|
1859
|
+
index_set = cartan_type.index_set()
|
|
1860
|
+
if scaling_factors is None:
|
|
1861
|
+
scaling_factors = {i: 1 for i in index_set}
|
|
1862
|
+
if virtualization is None:
|
|
1863
|
+
virtualization = {i: (i,) for i in index_set}
|
|
1864
|
+
elif not isinstance(virtualization, collections.abc.Mapping):
|
|
1865
|
+
try:
|
|
1866
|
+
virtualization = dict(virtualization)
|
|
1867
|
+
except (TypeError, ValueError):
|
|
1868
|
+
virtualization = {i: (virtualization(i),) for i in index_set}
|
|
1869
|
+
from sage.sets.family import Family
|
|
1870
|
+
self._virtualization = Family(virtualization)
|
|
1871
|
+
self._scaling_factors = Family(scaling_factors)
|
|
1872
|
+
|
|
1873
|
+
Morphism.__init__(self, parent)
|
|
1874
|
+
|
|
1875
|
+
def _repr_type(self):
|
|
1876
|
+
"""
|
|
1877
|
+
Used internally in printing this morphism.
|
|
1878
|
+
|
|
1879
|
+
TESTS::
|
|
1880
|
+
|
|
1881
|
+
sage: B = crystals.Tableaux(['A',2], shape=[2,1])
|
|
1882
|
+
sage: H = Hom(B, B)
|
|
1883
|
+
sage: psi = H.an_element()
|
|
1884
|
+
sage: psi._repr_type()
|
|
1885
|
+
"['A', 2] Crystal"
|
|
1886
|
+
|
|
1887
|
+
sage: psi = H(lambda x: None, index_set=[1])
|
|
1888
|
+
sage: psi._repr_type()
|
|
1889
|
+
"['A', 1] -> ['A', 2] Virtual Crystal"
|
|
1890
|
+
|
|
1891
|
+
sage: B = crystals.Tableaux(['A',3], shape=[1])
|
|
1892
|
+
sage: BT = crystals.Tableaux(['A',3], shape=[1,1,1])
|
|
1893
|
+
sage: psi = B.crystal_morphism(BT.module_generators, automorphism={1:3, 2:2, 3:1})
|
|
1894
|
+
sage: psi._repr_type()
|
|
1895
|
+
"['A', 3] Twisted Crystal"
|
|
1896
|
+
|
|
1897
|
+
sage: KD = crystals.KirillovReshetikhin(['D',3,1], 2,1)
|
|
1898
|
+
sage: KA = crystals.KirillovReshetikhin(['A',3,1], 2,1)
|
|
1899
|
+
sage: psi = KD.crystal_morphism(KA.module_generators)
|
|
1900
|
+
sage: psi._repr_type()
|
|
1901
|
+
"['D', 3, 1] -> ['A', 3, 1] Virtual Crystal"
|
|
1902
|
+
"""
|
|
1903
|
+
if self.codomain().cartan_type() != self._cartan_type:
|
|
1904
|
+
return "{} -> {} Virtual Crystal".format(self._cartan_type, self.codomain().cartan_type())
|
|
1905
|
+
if any(self._virtualization[i] != (i,) for i in self._cartan_type.index_set()):
|
|
1906
|
+
return "{} Twisted Crystal".format(self._cartan_type)
|
|
1907
|
+
return "{} Crystal".format(self._cartan_type)
|
|
1908
|
+
|
|
1909
|
+
def cartan_type(self):
|
|
1910
|
+
"""
|
|
1911
|
+
Return the Cartan type of ``self``.
|
|
1912
|
+
|
|
1913
|
+
EXAMPLES::
|
|
1914
|
+
|
|
1915
|
+
sage: B = crystals.Tableaux(['A',2], shape=[2,1])
|
|
1916
|
+
sage: psi = Hom(B, B).an_element()
|
|
1917
|
+
sage: psi.cartan_type()
|
|
1918
|
+
['A', 2]
|
|
1919
|
+
"""
|
|
1920
|
+
return self._cartan_type
|
|
1921
|
+
|
|
1922
|
+
# This is needed because is_injective is defined in a superclass, so
|
|
1923
|
+
# we can't overwrite it with the category
|
|
1924
|
+
def is_injective(self):
|
|
1925
|
+
"""
|
|
1926
|
+
Return if ``self`` is an injective crystal morphism.
|
|
1927
|
+
|
|
1928
|
+
EXAMPLES::
|
|
1929
|
+
|
|
1930
|
+
sage: B = crystals.Tableaux(['A',2], shape=[2,1])
|
|
1931
|
+
sage: psi = Hom(B, B).an_element()
|
|
1932
|
+
sage: psi.is_injective()
|
|
1933
|
+
False
|
|
1934
|
+
"""
|
|
1935
|
+
return self.is_embedding()
|
|
1936
|
+
|
|
1937
|
+
# This is here because is_surjective is defined in a superclass, so
|
|
1938
|
+
# we can't overwrite it with the category
|
|
1939
|
+
# TODO: This could be moved to sets
|
|
1940
|
+
@cached_method
|
|
1941
|
+
def is_surjective(self):
|
|
1942
|
+
"""
|
|
1943
|
+
Check if ``self`` is a surjective crystal morphism.
|
|
1944
|
+
|
|
1945
|
+
EXAMPLES::
|
|
1946
|
+
|
|
1947
|
+
sage: B = crystals.Tableaux(['C',2], shape=[1,1])
|
|
1948
|
+
sage: C = crystals.Tableaux(['C',2], ([2,1], [1,1]))
|
|
1949
|
+
sage: psi = B.crystal_morphism(C.module_generators[1:], codomain=C)
|
|
1950
|
+
sage: psi.is_surjective()
|
|
1951
|
+
False
|
|
1952
|
+
sage: im_gens = [None, B.module_generators[0]]
|
|
1953
|
+
sage: psi = C.crystal_morphism(im_gens, codomain=B)
|
|
1954
|
+
sage: psi.is_surjective()
|
|
1955
|
+
True
|
|
1956
|
+
|
|
1957
|
+
sage: C = crystals.Tableaux(['A',2], shape=[2,1])
|
|
1958
|
+
sage: B = crystals.infinity.Tableaux(['A',2])
|
|
1959
|
+
sage: La = RootSystem(['A',2]).weight_lattice().fundamental_weights()
|
|
1960
|
+
sage: W = crystals.elementary.T(['A',2], La[1]+La[2])
|
|
1961
|
+
sage: T = W.tensor(B)
|
|
1962
|
+
sage: mg = T(W.module_generators[0], B.module_generators[0])
|
|
1963
|
+
sage: psi = Hom(C,T)([mg])
|
|
1964
|
+
sage: psi.is_surjective()
|
|
1965
|
+
False
|
|
1966
|
+
"""
|
|
1967
|
+
if self.domain().cardinality() == float('inf'):
|
|
1968
|
+
raise NotImplementedError("unable to determine if surjective")
|
|
1969
|
+
if self.domain().cardinality() < self.codomain().cardinality():
|
|
1970
|
+
return False
|
|
1971
|
+
S = set(self.codomain())
|
|
1972
|
+
for x in self.domain():
|
|
1973
|
+
S.discard(self(x))
|
|
1974
|
+
if not S:
|
|
1975
|
+
return True
|
|
1976
|
+
return False
|
|
1977
|
+
|
|
1978
|
+
def __call__(self, x, *args, **kwds):
|
|
1979
|
+
"""
|
|
1980
|
+
Apply this map to ``x``. We need to do special processing
|
|
1981
|
+
for ``None``.
|
|
1982
|
+
|
|
1983
|
+
EXAMPLES::
|
|
1984
|
+
|
|
1985
|
+
sage: B = crystals.Tableaux(['A',2], shape=[2,1])
|
|
1986
|
+
sage: F = crystals.Tableaux(['A',2], shape=[1])
|
|
1987
|
+
sage: T = crystals.TensorProduct(F, F, F)
|
|
1988
|
+
sage: H = Hom(T, B)
|
|
1989
|
+
sage: b = B.module_generators[0]
|
|
1990
|
+
sage: psi = H((None, b, b, None), generators=T.highest_weight_vectors())
|
|
1991
|
+
sage: psi(None) # needs sage.symbolic
|
|
1992
|
+
sage: [psi(v) for v in T.highest_weight_vectors()]
|
|
1993
|
+
[None, [[1, 1], [2]], [[1, 1], [2]], None]
|
|
1994
|
+
"""
|
|
1995
|
+
if x is None:
|
|
1996
|
+
return None
|
|
1997
|
+
return super().__call__(x, *args, **kwds)
|
|
1998
|
+
|
|
1999
|
+
def virtualization(self):
|
|
2000
|
+
r"""
|
|
2001
|
+
Return the virtualization sets `\sigma_i`.
|
|
2002
|
+
|
|
2003
|
+
EXAMPLES::
|
|
2004
|
+
|
|
2005
|
+
sage: B = crystals.Tableaux(['B',3], shape=[1])
|
|
2006
|
+
sage: C = crystals.Tableaux(['D',4], shape=[2])
|
|
2007
|
+
sage: psi = B.crystal_morphism(C.module_generators)
|
|
2008
|
+
sage: psi.virtualization()
|
|
2009
|
+
Finite family {1: (1,), 2: (2,), 3: (3, 4)}
|
|
2010
|
+
"""
|
|
2011
|
+
return self._virtualization
|
|
2012
|
+
|
|
2013
|
+
def scaling_factors(self):
|
|
2014
|
+
r"""
|
|
2015
|
+
Return the scaling factors `\gamma_i`.
|
|
2016
|
+
|
|
2017
|
+
EXAMPLES::
|
|
2018
|
+
|
|
2019
|
+
sage: B = crystals.Tableaux(['B',3], shape=[1])
|
|
2020
|
+
sage: C = crystals.Tableaux(['D',4], shape=[2])
|
|
2021
|
+
sage: psi = B.crystal_morphism(C.module_generators)
|
|
2022
|
+
sage: psi.scaling_factors()
|
|
2023
|
+
Finite family {1: 2, 2: 2, 3: 1}
|
|
2024
|
+
"""
|
|
2025
|
+
return self._scaling_factors
|
|
2026
|
+
|
|
2027
|
+
|
|
2028
|
+
class CrystalMorphismByGenerators(CrystalMorphism):
|
|
2029
|
+
r"""
|
|
2030
|
+
A crystal morphism defined by a set of generators which create a virtual
|
|
2031
|
+
crystal inside the codomain.
|
|
2032
|
+
|
|
2033
|
+
INPUT:
|
|
2034
|
+
|
|
2035
|
+
- ``parent`` -- a homset
|
|
2036
|
+
- ``on_gens`` -- a function or list that determines the image of the
|
|
2037
|
+
generators (if given a list, then this uses the order of the
|
|
2038
|
+
generators of the domain) of the domain under ``self``
|
|
2039
|
+
- ``cartan_type`` -- (optional) a Cartan type; the default is the
|
|
2040
|
+
Cartan type of the domain
|
|
2041
|
+
- ``virtualization`` -- (optional) a dictionary whose keys are in
|
|
2042
|
+
the index set of the domain and whose values are lists of entries
|
|
2043
|
+
in the index set of the codomain
|
|
2044
|
+
- ``scaling_factors`` -- (optional) a dictionary whose keys are in
|
|
2045
|
+
the index set of the domain and whose values are scaling factors
|
|
2046
|
+
for the weight, `\varepsilon` and `\varphi`
|
|
2047
|
+
- ``gens`` -- (optional) a finite list of generators to define the
|
|
2048
|
+
morphism; the default is to use the highest weight vectors of the crystal
|
|
2049
|
+
- ``check`` -- boolean (default: ``True``); check if the crystal morphism
|
|
2050
|
+
is valid
|
|
2051
|
+
|
|
2052
|
+
.. SEEALSO::
|
|
2053
|
+
|
|
2054
|
+
:meth:`sage.categories.crystals.Crystals.ParentMethods.crystal_morphism`
|
|
2055
|
+
"""
|
|
2056
|
+
def __init__(self, parent, on_gens, cartan_type=None,
|
|
2057
|
+
virtualization=None, scaling_factors=None,
|
|
2058
|
+
gens=None, check=True):
|
|
2059
|
+
"""
|
|
2060
|
+
Construct a virtual crystal morphism.
|
|
2061
|
+
|
|
2062
|
+
TESTS::
|
|
2063
|
+
|
|
2064
|
+
sage: B = crystals.Tableaux(['D',4], shape=[1])
|
|
2065
|
+
sage: H = Hom(B, B)
|
|
2066
|
+
sage: d = {1:1, 2:2, 3:4, 4:3}
|
|
2067
|
+
sage: psi = H(B.module_generators, automorphism=d)
|
|
2068
|
+
|
|
2069
|
+
sage: B = crystals.Tableaux(['B',3], shape=[1])
|
|
2070
|
+
sage: C = crystals.Tableaux(['D',4], shape=[2])
|
|
2071
|
+
sage: H = Hom(B, C)
|
|
2072
|
+
sage: psi = H(C.module_generators)
|
|
2073
|
+
"""
|
|
2074
|
+
CrystalMorphism.__init__(self, parent, cartan_type,
|
|
2075
|
+
virtualization, scaling_factors)
|
|
2076
|
+
|
|
2077
|
+
if gens is None:
|
|
2078
|
+
if isinstance(on_gens, collections.abc.Mapping):
|
|
2079
|
+
gens = on_gens.keys()
|
|
2080
|
+
else:
|
|
2081
|
+
gens = parent.domain().module_generators
|
|
2082
|
+
self._gens = tuple(gens)
|
|
2083
|
+
|
|
2084
|
+
# Make sure on_gens is a function
|
|
2085
|
+
if isinstance(on_gens, collections.abc.Mapping):
|
|
2086
|
+
f = lambda x: on_gens[x]
|
|
2087
|
+
elif isinstance(on_gens, collections.abc.Sequence):
|
|
2088
|
+
if len(self._gens) != len(on_gens):
|
|
2089
|
+
raise ValueError("invalid generator images")
|
|
2090
|
+
d = dict(zip(self._gens, on_gens))
|
|
2091
|
+
f = lambda x: d[x]
|
|
2092
|
+
else:
|
|
2093
|
+
f = on_gens
|
|
2094
|
+
self._on_gens = f
|
|
2095
|
+
self._path_mg_cache = {x: (x, [], []) for x in self._gens}
|
|
2096
|
+
|
|
2097
|
+
# Now that everything is initialized, run the check (if it is wanted)
|
|
2098
|
+
if check:
|
|
2099
|
+
self._check()
|
|
2100
|
+
|
|
2101
|
+
def _repr_defn(self):
|
|
2102
|
+
"""
|
|
2103
|
+
Used in constructing string representation of ``self``.
|
|
2104
|
+
|
|
2105
|
+
EXAMPLES::
|
|
2106
|
+
|
|
2107
|
+
sage: B = crystals.Tableaux(['A',2], shape=[2,1])
|
|
2108
|
+
sage: F = crystals.Tableaux(['A',2], shape=[1])
|
|
2109
|
+
sage: T = crystals.TensorProduct(F, F, F)
|
|
2110
|
+
sage: H = Hom(T, B)
|
|
2111
|
+
sage: b = B.highest_weight_vector()
|
|
2112
|
+
sage: psi = H((None, b, b, None), generators=T.highest_weight_vectors())
|
|
2113
|
+
sage: print(psi._repr_defn())
|
|
2114
|
+
[[[1]], [[1]], [[1]]] |--> None
|
|
2115
|
+
[[[2]], [[1]], [[1]]] |--> [[1, 1], [2]]
|
|
2116
|
+
[[[1]], [[2]], [[1]]] |--> [[1, 1], [2]]
|
|
2117
|
+
[[[3]], [[2]], [[1]]] |--> None
|
|
2118
|
+
"""
|
|
2119
|
+
return '\n'.join('{} |--> {}'.format(mg, im)
|
|
2120
|
+
for mg, im in zip(self._gens, self.im_gens()))
|
|
2121
|
+
|
|
2122
|
+
def _check(self):
|
|
2123
|
+
"""
|
|
2124
|
+
Check if ``self`` is a valid virtual crystal morphism.
|
|
2125
|
+
|
|
2126
|
+
TESTS::
|
|
2127
|
+
|
|
2128
|
+
sage: B = crystals.Tableaux(['D',4], shape=[1])
|
|
2129
|
+
sage: H = Hom(B, B)
|
|
2130
|
+
sage: d = {1:1, 2:2, 3:4, 4:3}
|
|
2131
|
+
sage: psi = H(B.module_generators, automorphism=d) # indirect doctest
|
|
2132
|
+
|
|
2133
|
+
sage: B = crystals.Tableaux(['B',3], shape=[1])
|
|
2134
|
+
sage: C = crystals.Tableaux(['D',4], shape=[2])
|
|
2135
|
+
sage: H = Hom(B, C)
|
|
2136
|
+
sage: psi = H(C.module_generators) # indirect doctest
|
|
2137
|
+
"""
|
|
2138
|
+
index_set = self._cartan_type.index_set()
|
|
2139
|
+
acx = self.domain().weight_lattice_realization().simple_coroots()
|
|
2140
|
+
acy = self.codomain().weight_lattice_realization().simple_coroots()
|
|
2141
|
+
v = self._virtualization
|
|
2142
|
+
sf = self._scaling_factors
|
|
2143
|
+
for x in self._gens:
|
|
2144
|
+
y = self._on_gens(x)
|
|
2145
|
+
if y is None:
|
|
2146
|
+
continue
|
|
2147
|
+
xwt = x.weight()
|
|
2148
|
+
ywt = y.weight()
|
|
2149
|
+
for i in index_set:
|
|
2150
|
+
ind = v[i]
|
|
2151
|
+
if any(sf[i] * xwt.scalar(acx[i]) != ywt.scalar(acy[j]) for j in ind):
|
|
2152
|
+
raise ValueError("invalid crystal morphism: weights do not match")
|
|
2153
|
+
if any(sf[i] * x.epsilon(i) != y.epsilon(j) for j in ind):
|
|
2154
|
+
raise ValueError("invalid crystal morphism: epsilons are not aligned")
|
|
2155
|
+
if any(sf[i] * x.phi(i) != y.phi(j) for j in ind):
|
|
2156
|
+
raise ValueError("invalid crystal morphism: phis are not aligned")
|
|
2157
|
+
|
|
2158
|
+
def _call_(self, x):
|
|
2159
|
+
"""
|
|
2160
|
+
Return the image of ``x`` under ``self``.
|
|
2161
|
+
|
|
2162
|
+
EXAMPLES::
|
|
2163
|
+
|
|
2164
|
+
sage: B = crystals.Tableaux(['A',2], shape=[2,1])
|
|
2165
|
+
sage: H = Hom(B, B)
|
|
2166
|
+
sage: psi = H(B.module_generators)
|
|
2167
|
+
sage: psi(B.highest_weight_vector())
|
|
2168
|
+
[[1, 1], [2]]
|
|
2169
|
+
|
|
2170
|
+
sage: B = crystals.Tableaux(['D',4], shape=[1])
|
|
2171
|
+
sage: H = Hom(B, B)
|
|
2172
|
+
sage: d = {1:1, 2:2, 3:4, 4:3}
|
|
2173
|
+
sage: psi = H(B.module_generators, automorphism=d)
|
|
2174
|
+
sage: b = B.highest_weight_vector()
|
|
2175
|
+
sage: psi(b.f_string([1,2,3]))
|
|
2176
|
+
[[-4]]
|
|
2177
|
+
sage: psi(b.f_string([1,2,4]))
|
|
2178
|
+
[[4]]
|
|
2179
|
+
|
|
2180
|
+
sage: B = crystals.Tableaux(['B',3], shape=[1])
|
|
2181
|
+
sage: C = crystals.Tableaux(['D',4], shape=[2])
|
|
2182
|
+
sage: H = Hom(B, C)
|
|
2183
|
+
sage: psi = H(C.module_generators)
|
|
2184
|
+
sage: psi(B.highest_weight_vector())
|
|
2185
|
+
[[1, 1]]
|
|
2186
|
+
"""
|
|
2187
|
+
mg, ef, indices = self.to_module_generator(x)
|
|
2188
|
+
cur = self._on_gens(mg)
|
|
2189
|
+
for op, i in reversed(list(zip(ef, indices))):
|
|
2190
|
+
if cur is None:
|
|
2191
|
+
return None
|
|
2192
|
+
|
|
2193
|
+
s = []
|
|
2194
|
+
sf = self._scaling_factors[i]
|
|
2195
|
+
for j in self._virtualization[i]:
|
|
2196
|
+
s += [j]*sf
|
|
2197
|
+
if op == 'e':
|
|
2198
|
+
cur = cur.f_string(s)
|
|
2199
|
+
elif op == 'f':
|
|
2200
|
+
cur = cur.e_string(s)
|
|
2201
|
+
return cur
|
|
2202
|
+
|
|
2203
|
+
def __bool__(self) -> bool:
|
|
2204
|
+
"""
|
|
2205
|
+
Return if ``self`` is a nonzero morphism.
|
|
2206
|
+
|
|
2207
|
+
EXAMPLES::
|
|
2208
|
+
|
|
2209
|
+
sage: B = crystals.elementary.Elementary(['A',2], 2)
|
|
2210
|
+
sage: H = Hom(B, B)
|
|
2211
|
+
sage: psi = H(B.module_generators)
|
|
2212
|
+
sage: bool(psi)
|
|
2213
|
+
True
|
|
2214
|
+
sage: psi = H(lambda x: None)
|
|
2215
|
+
sage: bool(psi)
|
|
2216
|
+
False
|
|
2217
|
+
"""
|
|
2218
|
+
return any(self._on_gens(mg) is not None for mg in self._gens)
|
|
2219
|
+
|
|
2220
|
+
# TODO: Does this belong in the element_class of the Crystals() category?
|
|
2221
|
+
def to_module_generator(self, x):
|
|
2222
|
+
"""
|
|
2223
|
+
Return a generator ``mg`` and a path of `e_i` and `f_i` operations
|
|
2224
|
+
to ``mg``.
|
|
2225
|
+
|
|
2226
|
+
OUTPUT: a tuple consisting of:
|
|
2227
|
+
|
|
2228
|
+
- a module generator,
|
|
2229
|
+
- a list of ``'e'`` and ``'f'`` to denote which operation, and
|
|
2230
|
+
- a list of matching indices.
|
|
2231
|
+
|
|
2232
|
+
EXAMPLES::
|
|
2233
|
+
|
|
2234
|
+
sage: B = crystals.elementary.Elementary(['A',2], 2)
|
|
2235
|
+
sage: psi = B.crystal_morphism(B.module_generators)
|
|
2236
|
+
sage: psi.to_module_generator(B(4))
|
|
2237
|
+
(0, ['f', 'f', 'f', 'f'], [2, 2, 2, 2])
|
|
2238
|
+
sage: psi.to_module_generator(B(-2))
|
|
2239
|
+
(0, ['e', 'e'], [2, 2])
|
|
2240
|
+
"""
|
|
2241
|
+
if x in self._path_mg_cache:
|
|
2242
|
+
return self._path_mg_cache[x]
|
|
2243
|
+
|
|
2244
|
+
mg = set(self._path_mg_cache.keys())
|
|
2245
|
+
visited = {None, x}
|
|
2246
|
+
index_set = self._cartan_type.index_set()
|
|
2247
|
+
todo = [x]
|
|
2248
|
+
ef = [[]]
|
|
2249
|
+
indices = [[]]
|
|
2250
|
+
|
|
2251
|
+
while todo:
|
|
2252
|
+
cur = todo.pop(0)
|
|
2253
|
+
cur_ef = ef.pop(0)
|
|
2254
|
+
cur_indices = indices.pop(0)
|
|
2255
|
+
for i in index_set:
|
|
2256
|
+
next = cur.e(i)
|
|
2257
|
+
if next in mg:
|
|
2258
|
+
gen,ef,indices = self._path_mg_cache[next]
|
|
2259
|
+
ef = cur_ef + ['e'] + ef
|
|
2260
|
+
indices = cur_indices + [i] + indices
|
|
2261
|
+
self._path_mg_cache[x] = (gen, ef, indices)
|
|
2262
|
+
return (gen, ef, indices)
|
|
2263
|
+
if next not in visited:
|
|
2264
|
+
todo.append(next)
|
|
2265
|
+
ef.append(cur_ef + ['e'])
|
|
2266
|
+
indices.append(cur_indices + [i])
|
|
2267
|
+
visited.add(next)
|
|
2268
|
+
|
|
2269
|
+
# Now for f's
|
|
2270
|
+
next = cur.f(i)
|
|
2271
|
+
if next in mg:
|
|
2272
|
+
gen,ef,indices = self._path_mg_cache[next]
|
|
2273
|
+
ef = cur_ef + ['f'] + ef
|
|
2274
|
+
indices = cur_indices + [i] + indices
|
|
2275
|
+
self._path_mg_cache[x] = (gen, ef, indices)
|
|
2276
|
+
return (gen, ef, indices)
|
|
2277
|
+
if next not in visited:
|
|
2278
|
+
todo.append(next)
|
|
2279
|
+
ef.append(cur_ef + ['f'])
|
|
2280
|
+
indices.append(cur_indices + [i])
|
|
2281
|
+
visited.add(next)
|
|
2282
|
+
raise ValueError("no module generator in the component of {}".format(x))
|
|
2283
|
+
|
|
2284
|
+
@cached_method
|
|
2285
|
+
def im_gens(self):
|
|
2286
|
+
"""
|
|
2287
|
+
Return the image of the generators of ``self`` as a tuple.
|
|
2288
|
+
|
|
2289
|
+
EXAMPLES::
|
|
2290
|
+
|
|
2291
|
+
sage: B = crystals.Tableaux(['A',2], shape=[2,1])
|
|
2292
|
+
sage: F = crystals.Tableaux(['A',2], shape=[1])
|
|
2293
|
+
sage: T = crystals.TensorProduct(F, F, F)
|
|
2294
|
+
sage: H = Hom(T, B)
|
|
2295
|
+
sage: b = B.highest_weight_vector()
|
|
2296
|
+
sage: psi = H((None, b, b, None), generators=T.highest_weight_vectors())
|
|
2297
|
+
sage: psi.im_gens()
|
|
2298
|
+
(None, [[1, 1], [2]], [[1, 1], [2]], None)
|
|
2299
|
+
"""
|
|
2300
|
+
return tuple([self._on_gens(g) for g in self._gens])
|
|
2301
|
+
|
|
2302
|
+
def image(self):
|
|
2303
|
+
"""
|
|
2304
|
+
Return the image of ``self`` in the codomain as a
|
|
2305
|
+
:class:`~sage.combinat.crystals.subcrystal.Subcrystal`.
|
|
2306
|
+
|
|
2307
|
+
.. WARNING::
|
|
2308
|
+
|
|
2309
|
+
This assumes that ``self`` is a strict crystal morphism.
|
|
2310
|
+
|
|
2311
|
+
EXAMPLES::
|
|
2312
|
+
|
|
2313
|
+
sage: B = crystals.Tableaux(['B',3], shape=[1])
|
|
2314
|
+
sage: C = crystals.Tableaux(['D',4], shape=[2])
|
|
2315
|
+
sage: H = Hom(B, C)
|
|
2316
|
+
sage: psi = H(C.module_generators)
|
|
2317
|
+
sage: psi.image()
|
|
2318
|
+
Virtual crystal of The crystal of tableaux of type ['D', 4] and shape(s) [[2]] of type ['B', 3]
|
|
2319
|
+
"""
|
|
2320
|
+
#if not self.is_strict():
|
|
2321
|
+
# raise NotImplementedError
|
|
2322
|
+
from sage.combinat.crystals.subcrystal import Subcrystal
|
|
2323
|
+
return Subcrystal(self.codomain(),
|
|
2324
|
+
virtualization=self._virtualization,
|
|
2325
|
+
scaling_factors=self._scaling_factors,
|
|
2326
|
+
generators=self.im_gens(),
|
|
2327
|
+
cartan_type=self._cartan_type,
|
|
2328
|
+
index_set=self._cartan_type.index_set(),
|
|
2329
|
+
category=self.domain().category())
|
|
2330
|
+
|
|
2331
|
+
###############################################################################
|
|
2332
|
+
## Homset
|
|
2333
|
+
|
|
2334
|
+
|
|
2335
|
+
class CrystalHomset(Homset):
|
|
2336
|
+
r"""
|
|
2337
|
+
The set of crystal morphisms from one crystal to another.
|
|
2338
|
+
|
|
2339
|
+
An `U_q(\mathfrak{g})` `I`-crystal morphism `\Psi : B \to C` is a map
|
|
2340
|
+
`\Psi : B \cup \{ 0 \} \to C \cup \{ 0 \}` such that:
|
|
2341
|
+
|
|
2342
|
+
- `\Psi(0) = 0`.
|
|
2343
|
+
- If `b \in B` and `\Psi(b) \in C`, then
|
|
2344
|
+
`\mathrm{wt}(\Psi(b)) = \mathrm{wt}(b)`,
|
|
2345
|
+
`\varepsilon_i(\Psi(b)) = \varepsilon_i(b)`, and
|
|
2346
|
+
`\varphi_i(\Psi(b)) = \varphi_i(b)` for all `i \in I`.
|
|
2347
|
+
- If `b, b^{\prime} \in B`, `\Psi(b), \Psi(b^{\prime}) \in C` and
|
|
2348
|
+
`f_i b = b^{\prime}`, then `f_i \Psi(b) = \Psi(b^{\prime})` and
|
|
2349
|
+
`\Psi(b) = e_i \Psi(b^{\prime})` for all `i \in I`.
|
|
2350
|
+
|
|
2351
|
+
If the Cartan type is unambiguous, it is suppressed from the notation.
|
|
2352
|
+
|
|
2353
|
+
We can also generalize the definition of a crystal morphism by considering
|
|
2354
|
+
a map of `\sigma` of the (now possibly different) Dynkin diagrams
|
|
2355
|
+
corresponding to `B` and `C` along with scaling factors
|
|
2356
|
+
`\gamma_i \in \ZZ` for `i \in I`. Let `\sigma_i` denote the orbit of
|
|
2357
|
+
`i` under `\sigma`. We write objects for `B` as `X` with
|
|
2358
|
+
corresponding objects of `C` as `\widehat{X}`.
|
|
2359
|
+
Then a *virtual* crystal morphism `\Psi` is a map such that
|
|
2360
|
+
the following holds:
|
|
2361
|
+
|
|
2362
|
+
- `\Psi(0) = 0`.
|
|
2363
|
+
- If `b \in B` and `\Psi(b) \in C`, then for all `j \in \sigma_i`:
|
|
2364
|
+
|
|
2365
|
+
.. MATH::
|
|
2366
|
+
|
|
2367
|
+
\varepsilon_i(b) = \frac{1}{\gamma_j} \widehat{\varepsilon}_j(\Psi(b)),
|
|
2368
|
+
\quad \varphi_i(b) = \frac{1}{\gamma_j} \widehat{\varphi}_j(\Psi(b)),
|
|
2369
|
+
\quad \mathrm{wt}(\Psi(b)) = \sum_i c_i \sum_{j \in \sigma_i} \gamma_j
|
|
2370
|
+
\widehat{\Lambda}_j,
|
|
2371
|
+
|
|
2372
|
+
where `\mathrm{wt}(b) = \sum_i c_i \Lambda_i`.
|
|
2373
|
+
|
|
2374
|
+
- If `b, b^{\prime} \in B`, `\Psi(b), \Psi(b^{\prime}) \in C` and
|
|
2375
|
+
`f_i b = b^{\prime}`, then independent of the ordering of `\sigma_i`
|
|
2376
|
+
we have:
|
|
2377
|
+
|
|
2378
|
+
.. MATH::
|
|
2379
|
+
|
|
2380
|
+
\Psi(b^{\prime}) = e_i \Psi(b) =
|
|
2381
|
+
\prod_{j \in \sigma_i} \widehat{e}_j^{\gamma_i} \Psi(b), \quad
|
|
2382
|
+
\Psi(b^{\prime}) = f_i \Psi(b) =
|
|
2383
|
+
\prod_{j \in \sigma_i} \widehat{f}_j^{\gamma_i} \Psi(b).
|
|
2384
|
+
|
|
2385
|
+
If `\gamma_i = 1` for all `i \in I` and the Dynkin diagrams are
|
|
2386
|
+
the same, then we call `\Psi` a *twisted* crystal morphism.
|
|
2387
|
+
|
|
2388
|
+
INPUT:
|
|
2389
|
+
|
|
2390
|
+
- ``X`` -- the domain
|
|
2391
|
+
- ``Y`` -- the codomain
|
|
2392
|
+
- ``category`` -- (optional) the category of the crystal morphisms
|
|
2393
|
+
|
|
2394
|
+
.. SEEALSO::
|
|
2395
|
+
|
|
2396
|
+
For the construction of an element of the homset, see
|
|
2397
|
+
:class:`CrystalMorphismByGenerators` and
|
|
2398
|
+
:meth:`~sage.categories.crystals.Crystals.ParentMethods.crystal_morphism`.
|
|
2399
|
+
|
|
2400
|
+
EXAMPLES:
|
|
2401
|
+
|
|
2402
|
+
We begin with the natural embedding of `B(2\Lambda_1)` into
|
|
2403
|
+
`B(\Lambda_1) \otimes B(\Lambda_1)` in type `A_1`::
|
|
2404
|
+
|
|
2405
|
+
sage: B = crystals.Tableaux(['A',1], shape=[2])
|
|
2406
|
+
sage: F = crystals.Tableaux(['A',1], shape=[1])
|
|
2407
|
+
sage: T = crystals.TensorProduct(F, F)
|
|
2408
|
+
sage: v = T.highest_weight_vectors()[0]; v
|
|
2409
|
+
[[[1]], [[1]]]
|
|
2410
|
+
sage: H = Hom(B, T)
|
|
2411
|
+
sage: psi = H([v])
|
|
2412
|
+
sage: b = B.highest_weight_vector(); b
|
|
2413
|
+
[[1, 1]]
|
|
2414
|
+
sage: psi(b)
|
|
2415
|
+
[[[1]], [[1]]]
|
|
2416
|
+
sage: b.f(1)
|
|
2417
|
+
[[1, 2]]
|
|
2418
|
+
sage: psi(b.f(1))
|
|
2419
|
+
[[[1]], [[2]]]
|
|
2420
|
+
|
|
2421
|
+
We now look at the decomposition of `B(\Lambda_1) \otimes B(\Lambda_1)`
|
|
2422
|
+
into `B(2\Lambda_1) \oplus B(0)`::
|
|
2423
|
+
|
|
2424
|
+
sage: B0 = crystals.Tableaux(['A',1], shape=[])
|
|
2425
|
+
sage: D = crystals.DirectSum([B, B0])
|
|
2426
|
+
sage: H = Hom(T, D)
|
|
2427
|
+
sage: psi = H(D.module_generators)
|
|
2428
|
+
sage: psi
|
|
2429
|
+
['A', 1] Crystal morphism:
|
|
2430
|
+
From: Full tensor product of the crystals
|
|
2431
|
+
[The crystal of tableaux of type ['A', 1] and shape(s) [[1]],
|
|
2432
|
+
The crystal of tableaux of type ['A', 1] and shape(s) [[1]]]
|
|
2433
|
+
To: Direct sum of the crystals Family
|
|
2434
|
+
(The crystal of tableaux of type ['A', 1] and shape(s) [[2]],
|
|
2435
|
+
The crystal of tableaux of type ['A', 1] and shape(s) [[]])
|
|
2436
|
+
Defn: [[[1]], [[1]]] |--> [[1, 1]]
|
|
2437
|
+
[[[2]], [[1]]] |--> []
|
|
2438
|
+
sage: psi.is_isomorphism()
|
|
2439
|
+
True
|
|
2440
|
+
|
|
2441
|
+
We can always construct the trivial morphism which sends
|
|
2442
|
+
everything to `0`::
|
|
2443
|
+
|
|
2444
|
+
sage: Binf = crystals.infinity.Tableaux(['B', 2])
|
|
2445
|
+
sage: B = crystals.Tableaux(['B',2], shape=[1])
|
|
2446
|
+
sage: H = Hom(Binf, B)
|
|
2447
|
+
sage: psi = H(lambda x: None)
|
|
2448
|
+
sage: psi(Binf.highest_weight_vector())
|
|
2449
|
+
|
|
2450
|
+
For Kirillov-Reshetikhin crystals, we consider the map to the
|
|
2451
|
+
corresponding classical crystal::
|
|
2452
|
+
|
|
2453
|
+
sage: K = crystals.KirillovReshetikhin(['D',4,1], 2,1)
|
|
2454
|
+
sage: B = K.classical_decomposition()
|
|
2455
|
+
sage: H = Hom(K, B)
|
|
2456
|
+
sage: psi = H(lambda x: x.lift(), cartan_type=['D',4])
|
|
2457
|
+
sage: L = [psi(mg) for mg in K.module_generators]; L
|
|
2458
|
+
[[], [[1], [2]]]
|
|
2459
|
+
sage: all(x.parent() == B for x in L)
|
|
2460
|
+
True
|
|
2461
|
+
|
|
2462
|
+
Next we consider a type `D_4` crystal morphism where we twist by
|
|
2463
|
+
`3 \leftrightarrow 4`::
|
|
2464
|
+
|
|
2465
|
+
sage: B = crystals.Tableaux(['D',4], shape=[1])
|
|
2466
|
+
sage: H = Hom(B, B)
|
|
2467
|
+
sage: d = {1:1, 2:2, 3:4, 4:3}
|
|
2468
|
+
sage: psi = H(B.module_generators, automorphism=d)
|
|
2469
|
+
sage: b = B.highest_weight_vector()
|
|
2470
|
+
sage: b.f_string([1,2,3])
|
|
2471
|
+
[[4]]
|
|
2472
|
+
sage: b.f_string([1,2,4])
|
|
2473
|
+
[[-4]]
|
|
2474
|
+
sage: psi(b.f_string([1,2,3]))
|
|
2475
|
+
[[-4]]
|
|
2476
|
+
sage: psi(b.f_string([1,2,4]))
|
|
2477
|
+
[[4]]
|
|
2478
|
+
|
|
2479
|
+
We construct the natural virtual embedding of a type `B_3` into a type
|
|
2480
|
+
`D_4` crystal::
|
|
2481
|
+
|
|
2482
|
+
sage: B = crystals.Tableaux(['B',3], shape=[1])
|
|
2483
|
+
sage: C = crystals.Tableaux(['D',4], shape=[2])
|
|
2484
|
+
sage: H = Hom(B, C)
|
|
2485
|
+
sage: psi = H(C.module_generators)
|
|
2486
|
+
sage: psi
|
|
2487
|
+
['B', 3] -> ['D', 4] Virtual Crystal morphism:
|
|
2488
|
+
From: The crystal of tableaux of type ['B', 3] and shape(s) [[1]]
|
|
2489
|
+
To: The crystal of tableaux of type ['D', 4] and shape(s) [[2]]
|
|
2490
|
+
Defn: [[1]] |--> [[1, 1]]
|
|
2491
|
+
sage: for b in B: print("{} |--> {}".format(b, psi(b)))
|
|
2492
|
+
[[1]] |--> [[1, 1]]
|
|
2493
|
+
[[2]] |--> [[2, 2]]
|
|
2494
|
+
[[3]] |--> [[3, 3]]
|
|
2495
|
+
[[0]] |--> [[3, -3]]
|
|
2496
|
+
[[-3]] |--> [[-3, -3]]
|
|
2497
|
+
[[-2]] |--> [[-2, -2]]
|
|
2498
|
+
[[-1]] |--> [[-1, -1]]
|
|
2499
|
+
"""
|
|
2500
|
+
def __init__(self, X, Y, category=None):
|
|
2501
|
+
"""
|
|
2502
|
+
Initialize ``self``.
|
|
2503
|
+
|
|
2504
|
+
TESTS::
|
|
2505
|
+
|
|
2506
|
+
sage: B = crystals.Tableaux(['A', 2], shape=[2,1])
|
|
2507
|
+
sage: H = Hom(B, B)
|
|
2508
|
+
sage: Binf = crystals.infinity.Tableaux(['B',2])
|
|
2509
|
+
sage: H = Hom(Binf, B)
|
|
2510
|
+
"""
|
|
2511
|
+
if category is None:
|
|
2512
|
+
category = Crystals()
|
|
2513
|
+
# TODO: Should we make one of the types of morphisms into the self.Element?
|
|
2514
|
+
Homset.__init__(self, X, Y, category)
|
|
2515
|
+
|
|
2516
|
+
def _repr_(self):
|
|
2517
|
+
"""
|
|
2518
|
+
TESTS::
|
|
2519
|
+
|
|
2520
|
+
sage: B = crystals.Tableaux(['A', 2], shape=[2,1])
|
|
2521
|
+
sage: Hom(B, B)
|
|
2522
|
+
Set of Crystal Morphisms from The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
|
|
2523
|
+
to The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
|
|
2524
|
+
"""
|
|
2525
|
+
return "Set of Crystal Morphisms from {} to {}".format(self.domain(), self.codomain())
|
|
2526
|
+
|
|
2527
|
+
def _coerce_impl(self, x):
|
|
2528
|
+
"""
|
|
2529
|
+
Check to see if we can coerce ``x`` into a morphism with the
|
|
2530
|
+
correct parameters.
|
|
2531
|
+
|
|
2532
|
+
EXAMPLES::
|
|
2533
|
+
|
|
2534
|
+
sage: B = crystals.Tableaux(['B',3], shape=[2,1])
|
|
2535
|
+
sage: H = Hom(B, B)
|
|
2536
|
+
sage: H(H.an_element()) # indirect doctest
|
|
2537
|
+
['B', 3] Crystal endomorphism of The crystal of tableaux of type ['B', 3] and shape(s) [[2, 1]]
|
|
2538
|
+
Defn: [[1, 1], [2]] |--> None
|
|
2539
|
+
"""
|
|
2540
|
+
if not isinstance(x, CrystalMorphism):
|
|
2541
|
+
raise TypeError
|
|
2542
|
+
|
|
2543
|
+
if x.parent() is self:
|
|
2544
|
+
return x
|
|
2545
|
+
|
|
2546
|
+
# Case 1: the parent fits
|
|
2547
|
+
if x.parent() == self:
|
|
2548
|
+
return self.element_class(self, x._on_gens,
|
|
2549
|
+
x._virtualization, x._scaling_factors,
|
|
2550
|
+
x._cartan_type, x._gens)
|
|
2551
|
+
|
|
2552
|
+
# TODO: Should we try extraordinary measures (like twisting)?
|
|
2553
|
+
raise ValueError
|
|
2554
|
+
|
|
2555
|
+
def __call__(self, on_gens, cartan_type=None, index_set=None, generators=None,
|
|
2556
|
+
automorphism=None, virtualization=None, scaling_factors=None, check=True):
|
|
2557
|
+
"""
|
|
2558
|
+
Construct a crystal morphism.
|
|
2559
|
+
|
|
2560
|
+
EXAMPLES::
|
|
2561
|
+
|
|
2562
|
+
sage: B = crystals.Tableaux(['A', 2], shape=[2,1])
|
|
2563
|
+
sage: H = Hom(B, B)
|
|
2564
|
+
sage: psi = H(B.module_generators)
|
|
2565
|
+
|
|
2566
|
+
sage: F = crystals.Tableaux(['A',3], shape=[1])
|
|
2567
|
+
sage: T = crystals.TensorProduct(F, F, F)
|
|
2568
|
+
sage: H = Hom(B, T)
|
|
2569
|
+
sage: v = T.highest_weight_vectors()[2]
|
|
2570
|
+
sage: psi = H([v], cartan_type=['A',2])
|
|
2571
|
+
"""
|
|
2572
|
+
if isinstance(on_gens, CrystalMorphism):
|
|
2573
|
+
return self._coerce_impl(on_gens)
|
|
2574
|
+
|
|
2575
|
+
if cartan_type is None:
|
|
2576
|
+
cartan_type = self.domain().cartan_type()
|
|
2577
|
+
else:
|
|
2578
|
+
from sage.combinat.root_system.cartan_type import CartanType
|
|
2579
|
+
cartan_type = CartanType(cartan_type)
|
|
2580
|
+
if index_set is None:
|
|
2581
|
+
index_set = cartan_type.index_set()
|
|
2582
|
+
else:
|
|
2583
|
+
cartan_type = cartan_type.subtype(index_set)
|
|
2584
|
+
|
|
2585
|
+
# Try as a natural folding
|
|
2586
|
+
if cartan_type != self.codomain().cartan_type():
|
|
2587
|
+
fct = self.domain().cartan_type().as_folding()
|
|
2588
|
+
if fct.folding_of() == self.codomain().cartan_type():
|
|
2589
|
+
if virtualization is None:
|
|
2590
|
+
virtualization = fct.folding_orbit()
|
|
2591
|
+
if scaling_factors is None:
|
|
2592
|
+
scaling_factors = fct.scaling_factors()
|
|
2593
|
+
|
|
2594
|
+
if automorphism is not None:
|
|
2595
|
+
if virtualization is not None:
|
|
2596
|
+
raise ValueError("the automorphism and virtualization cannot both be specified")
|
|
2597
|
+
if not isinstance(automorphism, collections.abc.Mapping):
|
|
2598
|
+
try:
|
|
2599
|
+
automorphism = dict(automorphism)
|
|
2600
|
+
virtualization = {i: (automorphism[i],) for i in automorphism}
|
|
2601
|
+
except (TypeError, ValueError):
|
|
2602
|
+
virtualization = {i: (automorphism(i),) for i in index_set}
|
|
2603
|
+
else:
|
|
2604
|
+
virtualization = {i: (automorphism[i],) for i in automorphism}
|
|
2605
|
+
|
|
2606
|
+
return self.element_class(self, on_gens, cartan_type,
|
|
2607
|
+
virtualization, scaling_factors,
|
|
2608
|
+
generators, check)
|
|
2609
|
+
|
|
2610
|
+
def _an_element_(self):
|
|
2611
|
+
"""
|
|
2612
|
+
Return an element of ``self``. Every homset has the crystal morphism
|
|
2613
|
+
which sends all elements to ``None``.
|
|
2614
|
+
|
|
2615
|
+
EXAMPLES::
|
|
2616
|
+
|
|
2617
|
+
sage: B = crystals.Tableaux(['A', 2], shape=[2,1])
|
|
2618
|
+
sage: C = crystals.infinity.Tableaux(['A', 2])
|
|
2619
|
+
sage: H = Hom(B, C)
|
|
2620
|
+
sage: H.an_element()
|
|
2621
|
+
['A', 2] Crystal morphism:
|
|
2622
|
+
From: The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
|
|
2623
|
+
To: The infinity crystal of tableaux of type ['A', 2]
|
|
2624
|
+
Defn: [[1, 1], [2]] |--> None
|
|
2625
|
+
"""
|
|
2626
|
+
return self.element_class(self, lambda x: None)
|
|
2627
|
+
|
|
2628
|
+
Element = CrystalMorphismByGenerators
|