passagemath-combinat 10.6.42__cp314-cp314-musllinux_1_2_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_combinat/__init__.py +3 -0
- passagemath_combinat-10.6.42.dist-info/METADATA +160 -0
- passagemath_combinat-10.6.42.dist-info/RECORD +400 -0
- passagemath_combinat-10.6.42.dist-info/WHEEL +5 -0
- passagemath_combinat-10.6.42.dist-info/top_level.txt +3 -0
- passagemath_combinat.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_combinat.libs/libsymmetrica-81fe8739.so.3.0.0 +0 -0
- sage/algebras/affine_nil_temperley_lieb.py +263 -0
- sage/algebras/all.py +24 -0
- sage/algebras/all__sagemath_combinat.py +35 -0
- sage/algebras/askey_wilson.py +935 -0
- sage/algebras/associated_graded.py +345 -0
- sage/algebras/cellular_basis.py +350 -0
- sage/algebras/cluster_algebra.py +2766 -0
- sage/algebras/down_up_algebra.py +860 -0
- sage/algebras/free_algebra.py +1698 -0
- sage/algebras/free_algebra_element.py +345 -0
- sage/algebras/free_algebra_quotient.py +405 -0
- sage/algebras/free_algebra_quotient_element.py +295 -0
- sage/algebras/free_zinbiel_algebra.py +885 -0
- sage/algebras/hall_algebra.py +783 -0
- sage/algebras/hecke_algebras/all.py +4 -0
- sage/algebras/hecke_algebras/ariki_koike_algebra.py +1796 -0
- sage/algebras/hecke_algebras/ariki_koike_specht_modules.py +475 -0
- sage/algebras/hecke_algebras/cubic_hecke_algebra.py +3520 -0
- sage/algebras/hecke_algebras/cubic_hecke_base_ring.py +1473 -0
- sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py +1079 -0
- sage/algebras/iwahori_hecke_algebra.py +3095 -0
- sage/algebras/jordan_algebra.py +1773 -0
- sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py +113 -0
- sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py +156 -0
- sage/algebras/lie_conformal_algebras/all.py +18 -0
- sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py +134 -0
- sage/algebras/lie_conformal_algebras/examples.py +43 -0
- sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py +131 -0
- sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py +139 -0
- sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py +174 -0
- sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py +167 -0
- sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py +107 -0
- sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py +135 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py +353 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py +236 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py +78 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py +328 -0
- sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py +117 -0
- sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py +86 -0
- sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py +82 -0
- sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py +205 -0
- sage/algebras/nil_coxeter_algebra.py +191 -0
- sage/algebras/q_commuting_polynomials.py +673 -0
- sage/algebras/q_system.py +608 -0
- sage/algebras/quantum_clifford.py +959 -0
- sage/algebras/quantum_groups/ace_quantum_onsager.py +693 -0
- sage/algebras/quantum_groups/all.py +9 -0
- sage/algebras/quantum_groups/fock_space.py +2219 -0
- sage/algebras/quantum_groups/q_numbers.py +207 -0
- sage/algebras/quantum_groups/quantum_group_gap.py +2695 -0
- sage/algebras/quantum_groups/representations.py +591 -0
- sage/algebras/quantum_matrix_coordinate_algebra.py +1006 -0
- sage/algebras/quantum_oscillator.py +623 -0
- sage/algebras/quaternion_algebra.py +20 -0
- sage/algebras/quaternion_algebra_element.py +55 -0
- sage/algebras/rational_cherednik_algebra.py +525 -0
- sage/algebras/schur_algebra.py +670 -0
- sage/algebras/shuffle_algebra.py +1011 -0
- sage/algebras/splitting_algebra.py +779 -0
- sage/algebras/tensor_algebra.py +709 -0
- sage/algebras/yangian.py +1082 -0
- sage/algebras/yokonuma_hecke_algebra.py +1018 -0
- sage/all__sagemath_combinat.py +35 -0
- sage/combinat/SJT.py +255 -0
- sage/combinat/affine_permutation.py +2405 -0
- sage/combinat/algebraic_combinatorics.py +55 -0
- sage/combinat/all.py +53 -0
- sage/combinat/all__sagemath_combinat.py +195 -0
- sage/combinat/alternating_sign_matrix.py +2063 -0
- sage/combinat/baxter_permutations.py +346 -0
- sage/combinat/bijectionist.py +3220 -0
- sage/combinat/binary_recurrence_sequences.py +1180 -0
- sage/combinat/blob_algebra.py +685 -0
- sage/combinat/catalog_partitions.py +27 -0
- sage/combinat/chas/all.py +23 -0
- sage/combinat/chas/fsym.py +1180 -0
- sage/combinat/chas/wqsym.py +2601 -0
- sage/combinat/cluster_complex.py +326 -0
- sage/combinat/colored_permutations.py +2039 -0
- sage/combinat/colored_permutations_representations.py +964 -0
- sage/combinat/composition_signed.py +142 -0
- sage/combinat/composition_tableau.py +855 -0
- sage/combinat/constellation.py +1729 -0
- sage/combinat/core.py +751 -0
- sage/combinat/counting.py +12 -0
- sage/combinat/crystals/affine.py +742 -0
- sage/combinat/crystals/affine_factorization.py +518 -0
- sage/combinat/crystals/affinization.py +331 -0
- sage/combinat/crystals/alcove_path.py +2013 -0
- sage/combinat/crystals/all.py +22 -0
- sage/combinat/crystals/bkk_crystals.py +141 -0
- sage/combinat/crystals/catalog.py +115 -0
- sage/combinat/crystals/catalog_elementary_crystals.py +18 -0
- sage/combinat/crystals/catalog_infinity_crystals.py +33 -0
- sage/combinat/crystals/catalog_kirillov_reshetikhin.py +18 -0
- sage/combinat/crystals/crystals.py +257 -0
- sage/combinat/crystals/direct_sum.py +260 -0
- sage/combinat/crystals/elementary_crystals.py +1251 -0
- sage/combinat/crystals/fast_crystals.py +441 -0
- sage/combinat/crystals/fully_commutative_stable_grothendieck.py +1205 -0
- sage/combinat/crystals/generalized_young_walls.py +1076 -0
- sage/combinat/crystals/highest_weight_crystals.py +436 -0
- sage/combinat/crystals/induced_structure.py +695 -0
- sage/combinat/crystals/infinity_crystals.py +730 -0
- sage/combinat/crystals/kac_modules.py +863 -0
- sage/combinat/crystals/kirillov_reshetikhin.py +4196 -0
- sage/combinat/crystals/kyoto_path_model.py +497 -0
- sage/combinat/crystals/letters.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/letters.pxd +79 -0
- sage/combinat/crystals/letters.pyx +3056 -0
- sage/combinat/crystals/littelmann_path.py +1518 -0
- sage/combinat/crystals/monomial_crystals.py +1262 -0
- sage/combinat/crystals/multisegments.py +462 -0
- sage/combinat/crystals/mv_polytopes.py +467 -0
- sage/combinat/crystals/pbw_crystal.py +511 -0
- sage/combinat/crystals/pbw_datum.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/pbw_datum.pxd +4 -0
- sage/combinat/crystals/pbw_datum.pyx +487 -0
- sage/combinat/crystals/polyhedral_realization.py +372 -0
- sage/combinat/crystals/spins.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/spins.pxd +21 -0
- sage/combinat/crystals/spins.pyx +756 -0
- sage/combinat/crystals/star_crystal.py +290 -0
- sage/combinat/crystals/subcrystal.py +464 -0
- sage/combinat/crystals/tensor_product.py +1177 -0
- sage/combinat/crystals/tensor_product_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/tensor_product_element.pxd +35 -0
- sage/combinat/crystals/tensor_product_element.pyx +1870 -0
- sage/combinat/crystals/virtual_crystal.py +420 -0
- sage/combinat/cyclic_sieving_phenomenon.py +204 -0
- sage/combinat/debruijn_sequence.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/debruijn_sequence.pyx +355 -0
- sage/combinat/decorated_permutation.py +270 -0
- sage/combinat/degree_sequences.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/degree_sequences.pyx +588 -0
- sage/combinat/derangements.py +527 -0
- sage/combinat/descent_algebra.py +1008 -0
- sage/combinat/diagram.py +1551 -0
- sage/combinat/diagram_algebras.py +5886 -0
- sage/combinat/dyck_word.py +4349 -0
- sage/combinat/e_one_star.py +1623 -0
- sage/combinat/enumerated_sets.py +123 -0
- sage/combinat/expnums.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/expnums.pyx +148 -0
- sage/combinat/fast_vector_partitions.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/fast_vector_partitions.pyx +346 -0
- sage/combinat/fqsym.py +1977 -0
- sage/combinat/free_dendriform_algebra.py +954 -0
- sage/combinat/free_prelie_algebra.py +1141 -0
- sage/combinat/fully_commutative_elements.py +1077 -0
- sage/combinat/fully_packed_loop.py +1523 -0
- sage/combinat/gelfand_tsetlin_patterns.py +1409 -0
- sage/combinat/gray_codes.py +311 -0
- sage/combinat/grossman_larson_algebras.py +667 -0
- sage/combinat/growth.py +4352 -0
- sage/combinat/hall_polynomial.py +188 -0
- sage/combinat/hillman_grassl.py +866 -0
- sage/combinat/integer_matrices.py +329 -0
- sage/combinat/integer_vectors_mod_permgroup.py +1238 -0
- sage/combinat/k_tableau.py +4564 -0
- sage/combinat/kazhdan_lusztig.py +215 -0
- sage/combinat/key_polynomial.py +885 -0
- sage/combinat/knutson_tao_puzzles.py +2286 -0
- sage/combinat/lr_tableau.py +311 -0
- sage/combinat/matrices/all.py +24 -0
- sage/combinat/matrices/hadamard_matrix.py +3790 -0
- sage/combinat/matrices/latin.py +2912 -0
- sage/combinat/misc.py +401 -0
- sage/combinat/multiset_partition_into_sets_ordered.py +3541 -0
- sage/combinat/ncsf_qsym/all.py +21 -0
- sage/combinat/ncsf_qsym/combinatorics.py +317 -0
- sage/combinat/ncsf_qsym/generic_basis_code.py +1427 -0
- sage/combinat/ncsf_qsym/ncsf.py +5637 -0
- sage/combinat/ncsf_qsym/qsym.py +4053 -0
- sage/combinat/ncsf_qsym/tutorial.py +447 -0
- sage/combinat/ncsym/all.py +21 -0
- sage/combinat/ncsym/bases.py +855 -0
- sage/combinat/ncsym/dual.py +593 -0
- sage/combinat/ncsym/ncsym.py +2076 -0
- sage/combinat/necklace.py +551 -0
- sage/combinat/non_decreasing_parking_function.py +634 -0
- sage/combinat/nu_dyck_word.py +1474 -0
- sage/combinat/output.py +861 -0
- sage/combinat/parallelogram_polyomino.py +4326 -0
- sage/combinat/parking_functions.py +1602 -0
- sage/combinat/partition_algebra.py +1998 -0
- sage/combinat/partition_kleshchev.py +1982 -0
- sage/combinat/partition_shifting_algebras.py +584 -0
- sage/combinat/partition_tuple.py +3114 -0
- sage/combinat/path_tableaux/all.py +13 -0
- sage/combinat/path_tableaux/catalog.py +29 -0
- sage/combinat/path_tableaux/dyck_path.py +380 -0
- sage/combinat/path_tableaux/frieze.py +476 -0
- sage/combinat/path_tableaux/path_tableau.py +728 -0
- sage/combinat/path_tableaux/semistandard.py +510 -0
- sage/combinat/perfect_matching.py +779 -0
- sage/combinat/plane_partition.py +3300 -0
- sage/combinat/q_bernoulli.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/q_bernoulli.pyx +128 -0
- sage/combinat/quickref.py +81 -0
- sage/combinat/recognizable_series.py +2051 -0
- sage/combinat/regular_sequence.py +4316 -0
- sage/combinat/regular_sequence_bounded.py +543 -0
- sage/combinat/restricted_growth.py +81 -0
- sage/combinat/ribbon.py +20 -0
- sage/combinat/ribbon_shaped_tableau.py +489 -0
- sage/combinat/ribbon_tableau.py +1180 -0
- sage/combinat/rigged_configurations/all.py +46 -0
- sage/combinat/rigged_configurations/bij_abstract_class.py +548 -0
- sage/combinat/rigged_configurations/bij_infinity.py +370 -0
- sage/combinat/rigged_configurations/bij_type_A.py +163 -0
- sage/combinat/rigged_configurations/bij_type_A2_dual.py +338 -0
- sage/combinat/rigged_configurations/bij_type_A2_even.py +218 -0
- sage/combinat/rigged_configurations/bij_type_A2_odd.py +199 -0
- sage/combinat/rigged_configurations/bij_type_B.py +900 -0
- sage/combinat/rigged_configurations/bij_type_C.py +267 -0
- sage/combinat/rigged_configurations/bij_type_D.py +771 -0
- sage/combinat/rigged_configurations/bij_type_D_tri.py +392 -0
- sage/combinat/rigged_configurations/bij_type_D_twisted.py +576 -0
- sage/combinat/rigged_configurations/bij_type_E67.py +402 -0
- sage/combinat/rigged_configurations/bijection.py +143 -0
- sage/combinat/rigged_configurations/kleber_tree.py +1475 -0
- sage/combinat/rigged_configurations/kr_tableaux.py +1898 -0
- sage/combinat/rigged_configurations/rc_crystal.py +461 -0
- sage/combinat/rigged_configurations/rc_infinity.py +540 -0
- sage/combinat/rigged_configurations/rigged_configuration_element.py +2403 -0
- sage/combinat/rigged_configurations/rigged_configurations.py +1918 -0
- sage/combinat/rigged_configurations/rigged_partition.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/rigged_configurations/rigged_partition.pxd +15 -0
- sage/combinat/rigged_configurations/rigged_partition.pyx +680 -0
- sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +499 -0
- sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py +428 -0
- sage/combinat/rsk.py +3438 -0
- sage/combinat/schubert_polynomial.py +508 -0
- sage/combinat/set_partition.py +3318 -0
- sage/combinat/set_partition_iterator.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/set_partition_iterator.pyx +136 -0
- sage/combinat/set_partition_ordered.py +1590 -0
- sage/combinat/sf/abreu_nigro.py +346 -0
- sage/combinat/sf/all.py +52 -0
- sage/combinat/sf/character.py +576 -0
- sage/combinat/sf/classical.py +319 -0
- sage/combinat/sf/dual.py +996 -0
- sage/combinat/sf/elementary.py +549 -0
- sage/combinat/sf/hall_littlewood.py +1028 -0
- sage/combinat/sf/hecke.py +336 -0
- sage/combinat/sf/homogeneous.py +464 -0
- sage/combinat/sf/jack.py +1428 -0
- sage/combinat/sf/k_dual.py +1458 -0
- sage/combinat/sf/kfpoly.py +447 -0
- sage/combinat/sf/llt.py +789 -0
- sage/combinat/sf/macdonald.py +2019 -0
- sage/combinat/sf/monomial.py +525 -0
- sage/combinat/sf/multiplicative.py +113 -0
- sage/combinat/sf/new_kschur.py +1786 -0
- sage/combinat/sf/ns_macdonald.py +964 -0
- sage/combinat/sf/orthogonal.py +246 -0
- sage/combinat/sf/orthotriang.py +355 -0
- sage/combinat/sf/powersum.py +963 -0
- sage/combinat/sf/schur.py +880 -0
- sage/combinat/sf/sf.py +1653 -0
- sage/combinat/sf/sfa.py +7053 -0
- sage/combinat/sf/symplectic.py +253 -0
- sage/combinat/sf/witt.py +721 -0
- sage/combinat/shifted_primed_tableau.py +2735 -0
- sage/combinat/shuffle.py +830 -0
- sage/combinat/sidon_sets.py +146 -0
- sage/combinat/similarity_class_type.py +1721 -0
- sage/combinat/sine_gordon.py +618 -0
- sage/combinat/six_vertex_model.py +784 -0
- sage/combinat/skew_partition.py +2053 -0
- sage/combinat/skew_tableau.py +2989 -0
- sage/combinat/sloane_functions.py +8935 -0
- sage/combinat/specht_module.py +1403 -0
- sage/combinat/species/all.py +48 -0
- sage/combinat/species/characteristic_species.py +321 -0
- sage/combinat/species/composition_species.py +273 -0
- sage/combinat/species/cycle_species.py +284 -0
- sage/combinat/species/empty_species.py +155 -0
- sage/combinat/species/functorial_composition_species.py +148 -0
- sage/combinat/species/generating_series.py +673 -0
- sage/combinat/species/library.py +148 -0
- sage/combinat/species/linear_order_species.py +169 -0
- sage/combinat/species/misc.py +83 -0
- sage/combinat/species/partition_species.py +290 -0
- sage/combinat/species/permutation_species.py +268 -0
- sage/combinat/species/product_species.py +423 -0
- sage/combinat/species/recursive_species.py +476 -0
- sage/combinat/species/set_species.py +192 -0
- sage/combinat/species/species.py +820 -0
- sage/combinat/species/structure.py +539 -0
- sage/combinat/species/subset_species.py +243 -0
- sage/combinat/species/sum_species.py +225 -0
- sage/combinat/subword.py +564 -0
- sage/combinat/subword_complex.py +2122 -0
- sage/combinat/subword_complex_c.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/subword_complex_c.pyx +119 -0
- sage/combinat/super_tableau.py +821 -0
- sage/combinat/superpartition.py +1154 -0
- sage/combinat/symmetric_group_algebra.py +3774 -0
- sage/combinat/symmetric_group_representations.py +1830 -0
- sage/combinat/t_sequences.py +877 -0
- sage/combinat/tableau.py +9506 -0
- sage/combinat/tableau_residues.py +860 -0
- sage/combinat/tableau_tuple.py +5353 -0
- sage/combinat/tiling.py +2432 -0
- sage/combinat/triangles_FHM.py +777 -0
- sage/combinat/tutorial.py +1857 -0
- sage/combinat/vector_partition.py +337 -0
- sage/combinat/words/abstract_word.py +1722 -0
- sage/combinat/words/all.py +59 -0
- sage/combinat/words/alphabet.py +268 -0
- sage/combinat/words/finite_word.py +7201 -0
- sage/combinat/words/infinite_word.py +113 -0
- sage/combinat/words/lyndon_word.py +652 -0
- sage/combinat/words/morphic.py +351 -0
- sage/combinat/words/morphism.py +3878 -0
- sage/combinat/words/paths.py +2932 -0
- sage/combinat/words/shuffle_product.py +278 -0
- sage/combinat/words/suffix_trees.py +1873 -0
- sage/combinat/words/word.py +769 -0
- sage/combinat/words/word_char.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/words/word_char.pyx +847 -0
- sage/combinat/words/word_datatypes.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/words/word_datatypes.pxd +4 -0
- sage/combinat/words/word_datatypes.pyx +1067 -0
- sage/combinat/words/word_generators.py +2026 -0
- sage/combinat/words/word_infinite_datatypes.py +1218 -0
- sage/combinat/words/word_options.py +99 -0
- sage/combinat/words/words.py +2396 -0
- sage/data_structures/all__sagemath_combinat.py +1 -0
- sage/databases/all__sagemath_combinat.py +13 -0
- sage/databases/findstat.py +4897 -0
- sage/databases/oeis.py +2058 -0
- sage/databases/sloane.py +393 -0
- sage/dynamics/all__sagemath_combinat.py +14 -0
- sage/dynamics/cellular_automata/all.py +7 -0
- sage/dynamics/cellular_automata/catalog.py +34 -0
- sage/dynamics/cellular_automata/elementary.py +612 -0
- sage/dynamics/cellular_automata/glca.py +477 -0
- sage/dynamics/cellular_automata/solitons.py +1463 -0
- sage/dynamics/finite_dynamical_system.py +1249 -0
- sage/dynamics/finite_dynamical_system_catalog.py +382 -0
- sage/games/all.py +7 -0
- sage/games/hexad.py +704 -0
- sage/games/quantumino.py +591 -0
- sage/games/sudoku.py +889 -0
- sage/games/sudoku_backtrack.cpython-314-x86_64-linux-musl.so +0 -0
- sage/games/sudoku_backtrack.pyx +189 -0
- sage/groups/all__sagemath_combinat.py +1 -0
- sage/groups/indexed_free_group.py +489 -0
- sage/libs/all__sagemath_combinat.py +6 -0
- sage/libs/lrcalc/__init__.py +1 -0
- sage/libs/lrcalc/lrcalc.py +525 -0
- sage/libs/symmetrica/__init__.py +7 -0
- sage/libs/symmetrica/all.py +101 -0
- sage/libs/symmetrica/kostka.pxi +168 -0
- sage/libs/symmetrica/part.pxi +193 -0
- sage/libs/symmetrica/plet.pxi +42 -0
- sage/libs/symmetrica/sab.pxi +196 -0
- sage/libs/symmetrica/sb.pxi +332 -0
- sage/libs/symmetrica/sc.pxi +192 -0
- sage/libs/symmetrica/schur.pxi +956 -0
- sage/libs/symmetrica/symmetrica.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/symmetrica/symmetrica.pxi +1172 -0
- sage/libs/symmetrica/symmetrica.pyx +39 -0
- sage/monoids/all.py +13 -0
- sage/monoids/automatic_semigroup.py +1054 -0
- sage/monoids/free_abelian_monoid.py +315 -0
- sage/monoids/free_abelian_monoid_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/monoids/free_abelian_monoid_element.pxd +16 -0
- sage/monoids/free_abelian_monoid_element.pyx +397 -0
- sage/monoids/free_monoid.py +335 -0
- sage/monoids/free_monoid_element.py +431 -0
- sage/monoids/hecke_monoid.py +65 -0
- sage/monoids/string_monoid.py +817 -0
- sage/monoids/string_monoid_element.py +547 -0
- sage/monoids/string_ops.py +143 -0
- sage/monoids/trace_monoid.py +972 -0
- sage/rings/all__sagemath_combinat.py +2 -0
- sage/sat/all.py +4 -0
- sage/sat/boolean_polynomials.py +405 -0
- sage/sat/converters/__init__.py +6 -0
- sage/sat/converters/anf2cnf.py +14 -0
- sage/sat/converters/polybori.py +611 -0
- sage/sat/solvers/__init__.py +5 -0
- sage/sat/solvers/cryptominisat.py +287 -0
- sage/sat/solvers/dimacs.py +783 -0
- sage/sat/solvers/picosat.py +228 -0
- sage/sat/solvers/sat_lp.py +156 -0
- sage/sat/solvers/satsolver.cpython-314-x86_64-linux-musl.so +0 -0
- sage/sat/solvers/satsolver.pxd +3 -0
- sage/sat/solvers/satsolver.pyx +405 -0
|
@@ -0,0 +1,2013 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
# sage.doctest: needs sage.combinat sage.graphs sage.modules
|
|
3
|
+
r"""
|
|
4
|
+
Alcove paths
|
|
5
|
+
|
|
6
|
+
AUTHORS:
|
|
7
|
+
|
|
8
|
+
- Brant Jones (2008): initial version
|
|
9
|
+
- Arthur Lubovsky (2013-03-07): rewritten to implement affine type
|
|
10
|
+
- Travis Scrimshaw (2016-06-23): implemented `\mathcal{B}(\infty)`
|
|
11
|
+
|
|
12
|
+
Special thanks to: Nicolas Borie, Anne Schilling, Travis Scrimshaw, and
|
|
13
|
+
Nicolas Thiéry.
|
|
14
|
+
"""
|
|
15
|
+
# ****************************************************************************
|
|
16
|
+
# Copyright (C) 2008 Brant Jones <brant at math.ucdavis.edu>
|
|
17
|
+
# Copyright (C) 2013 Arthur Lubovsky <alubovsky at albany.edu>
|
|
18
|
+
#
|
|
19
|
+
# This program is free software: you can redistribute it and/or modify
|
|
20
|
+
# it under the terms of the GNU General Public License as published by
|
|
21
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
22
|
+
# (at your option) any later version.
|
|
23
|
+
# https://www.gnu.org/licenses/
|
|
24
|
+
# ****************************************************************************
|
|
25
|
+
|
|
26
|
+
from sage.structure.parent import Parent
|
|
27
|
+
from sage.structure.element import Element
|
|
28
|
+
from sage.structure.element_wrapper import ElementWrapper
|
|
29
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
30
|
+
from sage.structure.richcmp import richcmp
|
|
31
|
+
from sage.categories.classical_crystals import ClassicalCrystals
|
|
32
|
+
from sage.categories.loop_crystals import LoopCrystals
|
|
33
|
+
from sage.combinat.root_system.cartan_type import CartanType
|
|
34
|
+
from sage.combinat.root_system.root_system import RootSystem
|
|
35
|
+
from sage.rings.integer import Integer
|
|
36
|
+
from sage.misc.misc_c import prod
|
|
37
|
+
from sage.categories.sets_cat import Sets
|
|
38
|
+
from sage.misc.cachefunc import cached_method, cached_in_parent_method
|
|
39
|
+
from sage.misc.lazy_import import lazy_import
|
|
40
|
+
from sage.categories.highest_weight_crystals import HighestWeightCrystals
|
|
41
|
+
from copy import copy
|
|
42
|
+
from sage.misc.latex import latex
|
|
43
|
+
|
|
44
|
+
lazy_import('sage.graphs.digraph', 'DiGraph')
|
|
45
|
+
lazy_import('sage.combinat.root_system.weyl_group', 'WeylGroup')
|
|
46
|
+
lazy_import('sage.modules.free_module_element', 'vector')
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class CrystalOfAlcovePaths(UniqueRepresentation, Parent):
|
|
50
|
+
r"""
|
|
51
|
+
Crystal of alcove paths generated from a "straight-line" path to the
|
|
52
|
+
negative of a given dominant weight.
|
|
53
|
+
|
|
54
|
+
INPUT:
|
|
55
|
+
|
|
56
|
+
- ``cartan_type`` -- Cartan type of a finite or affine untwisted root
|
|
57
|
+
system
|
|
58
|
+
|
|
59
|
+
- ``weight`` -- dominant weight as a list of (integral) coefficients of
|
|
60
|
+
the fundamental weights
|
|
61
|
+
|
|
62
|
+
- ``highest_weight_crystal`` -- (default: ``True``) if ``True``
|
|
63
|
+
returns the highest weight crystal. If ``False`` returns an
|
|
64
|
+
object which is close to being isomorphic to the tensor product
|
|
65
|
+
of Kirillov-Reshetikhin crystals of column shape in the
|
|
66
|
+
following sense: We get all the vertices, but only some of the
|
|
67
|
+
edges. We'll call the included edges pseudo-Demazure. They are
|
|
68
|
+
all nonzero edges and the 0-edges not at the end of a 0-string
|
|
69
|
+
of edges, i.e. not those with `f_{0}(b) = b'` with
|
|
70
|
+
`\varphi_0(b) =1`. (Whereas Demazure 0-edges are those that
|
|
71
|
+
are not at the beginning of a zero string.) In this case the
|
|
72
|
+
weight `[c_1, c_2, \ldots, c_k]` represents
|
|
73
|
+
`\sum_{i=1}^k c_i \omega_i`.
|
|
74
|
+
|
|
75
|
+
.. NOTE::
|
|
76
|
+
|
|
77
|
+
If ``highest_weight_crystal`` = ``False``, since we do not
|
|
78
|
+
get the full crystal, ``TestSuite`` will fail on the
|
|
79
|
+
Stembridge axioms.
|
|
80
|
+
|
|
81
|
+
.. SEEALSO::
|
|
82
|
+
|
|
83
|
+
- :class:`Crystals`
|
|
84
|
+
|
|
85
|
+
EXAMPLES:
|
|
86
|
+
|
|
87
|
+
The following example appears in Figure 2 of [LP2008]_::
|
|
88
|
+
|
|
89
|
+
sage: C = crystals.AlcovePaths(['G',2],[0,1])
|
|
90
|
+
sage: G = C.digraph()
|
|
91
|
+
sage: GG = DiGraph({
|
|
92
|
+
....: () : {(0) : 2 },
|
|
93
|
+
....: (0) : {(0,8) : 1 },
|
|
94
|
+
....: (0,1) : {(0,1,7) : 2 },
|
|
95
|
+
....: (0,1,2) : {(0,1,2,9) : 1 },
|
|
96
|
+
....: (0,1,2,3) : {(0,1,2,3,4) : 2 },
|
|
97
|
+
....: (0,1,2,6) : {(0,1,2,3) : 1 },
|
|
98
|
+
....: (0,1,2,9) : {(0,1,2,6) : 1 },
|
|
99
|
+
....: (0,1,7) : {(0,1,2) : 2 },
|
|
100
|
+
....: (0,1,7,9) : {(0,1,2,9) : 2 },
|
|
101
|
+
....: (0,5) : {(0,1) : 1, (0,5,7) : 2 },
|
|
102
|
+
....: (0,5,7) : {(0,5,7,9) : 1 },
|
|
103
|
+
....: (0,5,7,9) : {(0,1,7,9) : 1 },
|
|
104
|
+
....: (0,8) : {(0,5) : 1 },
|
|
105
|
+
....: })
|
|
106
|
+
sage: G.is_isomorphic(GG)
|
|
107
|
+
True
|
|
108
|
+
sage: for (u,v,i) in G.edges(sort=True):
|
|
109
|
+
....: print((u.integer_sequence() , v.integer_sequence(), i))
|
|
110
|
+
([], [0], 2)
|
|
111
|
+
([0], [0, 8], 1)
|
|
112
|
+
([0, 1], [0, 1, 7], 2)
|
|
113
|
+
([0, 1, 2], [0, 1, 2, 9], 1)
|
|
114
|
+
([0, 1, 2, 3], [0, 1, 2, 3, 4], 2)
|
|
115
|
+
([0, 1, 2, 6], [0, 1, 2, 3], 1)
|
|
116
|
+
([0, 1, 2, 9], [0, 1, 2, 6], 1)
|
|
117
|
+
([0, 1, 7], [0, 1, 2], 2)
|
|
118
|
+
([0, 1, 7, 9], [0, 1, 2, 9], 2)
|
|
119
|
+
([0, 5], [0, 1], 1)
|
|
120
|
+
([0, 5], [0, 5, 7], 2)
|
|
121
|
+
([0, 5, 7], [0, 5, 7, 9], 1)
|
|
122
|
+
([0, 5, 7, 9], [0, 1, 7, 9], 1)
|
|
123
|
+
([0, 8], [0, 5], 1)
|
|
124
|
+
|
|
125
|
+
Alcove path crystals are a discrete version of Littelmann paths.
|
|
126
|
+
We verify that the alcove path crystal is isomorphic to the LS
|
|
127
|
+
path crystal::
|
|
128
|
+
|
|
129
|
+
sage: C1 = crystals.AlcovePaths(['C',3],[2,1,0])
|
|
130
|
+
sage: g1 = C1.digraph() #long time
|
|
131
|
+
sage: C2 = crystals.LSPaths(['C',3],[2,1,0])
|
|
132
|
+
sage: g2 = C2.digraph() #long time
|
|
133
|
+
sage: g1.is_isomorphic(g2, edge_labels=True) #long time
|
|
134
|
+
True
|
|
135
|
+
|
|
136
|
+
The preferred initialization method is via explicit weights rather than a Cartan type
|
|
137
|
+
and the coefficients of the fundamental weights::
|
|
138
|
+
|
|
139
|
+
sage: R = RootSystem(['C',3])
|
|
140
|
+
sage: P = R.weight_lattice()
|
|
141
|
+
sage: La = P.fundamental_weights()
|
|
142
|
+
sage: C = crystals.AlcovePaths(2*La[1]+La[2]); C
|
|
143
|
+
Highest weight crystal of alcove paths of type ['C', 3] and weight 2*Lambda[1] + Lambda[2]
|
|
144
|
+
sage: C1==C
|
|
145
|
+
True
|
|
146
|
+
|
|
147
|
+
We now explain the data structure::
|
|
148
|
+
|
|
149
|
+
sage: C = crystals.AlcovePaths(['A',2],[2,0]) ; C
|
|
150
|
+
Highest weight crystal of alcove paths of type ['A', 2] and weight 2*Lambda[1]
|
|
151
|
+
sage: C._R.lambda_chain()
|
|
152
|
+
[(alpha[1], 0), (alpha[1] + alpha[2], 0), (alpha[1], 1), (alpha[1] + alpha[2], 1)]
|
|
153
|
+
|
|
154
|
+
The previous list gives the initial "straight line" path from the
|
|
155
|
+
fundamental alcove `A_o` to its translation `A_o - \lambda` where
|
|
156
|
+
`\lambda = 2\omega_1` in this example. The initial path for weight
|
|
157
|
+
`\lambda` is called the `\lambda`-chain. This path is constructed from
|
|
158
|
+
the ordered pairs `(\beta, k)`, by crossing the hyperplane orthogonal to
|
|
159
|
+
`\beta` at height `-k`. We can view a plot of this path as follows::
|
|
160
|
+
|
|
161
|
+
sage: x=C( () )
|
|
162
|
+
sage: x.plot() # not tested - outputs a pdf
|
|
163
|
+
|
|
164
|
+
An element of the crystal is given by a subset of the `\lambda`-chain.
|
|
165
|
+
This subset indicates the hyperplanes where the initial path should be
|
|
166
|
+
folded. The highest weight element is given by the empty subset. ::
|
|
167
|
+
|
|
168
|
+
sage: x
|
|
169
|
+
()
|
|
170
|
+
sage: x.f(1).f(2)
|
|
171
|
+
((alpha[1], 1), (alpha[1] + alpha[2], 1))
|
|
172
|
+
sage: x.f(1).f(2).integer_sequence()
|
|
173
|
+
[2, 3]
|
|
174
|
+
sage: C([2,3])
|
|
175
|
+
((alpha[1], 1), (alpha[1] + alpha[2], 1))
|
|
176
|
+
sage: C([2,3]).is_admissible() #check if a valid vertex
|
|
177
|
+
True
|
|
178
|
+
sage: C([1,3]).is_admissible() #check if a valid vertex
|
|
179
|
+
False
|
|
180
|
+
|
|
181
|
+
Alcove path crystals now works in affine type (:issue:`14143`)::
|
|
182
|
+
|
|
183
|
+
sage: C = crystals.AlcovePaths(['A',2,1],[1,0,0]) ; C
|
|
184
|
+
Highest weight crystal of alcove paths of type ['A', 2, 1] and weight Lambda[0]
|
|
185
|
+
sage: x=C( () )
|
|
186
|
+
sage: x.f(0)
|
|
187
|
+
((alpha[0], 0),)
|
|
188
|
+
sage: C.R
|
|
189
|
+
Root system of type ['A', 2, 1]
|
|
190
|
+
sage: C.weight
|
|
191
|
+
Lambda[0]
|
|
192
|
+
|
|
193
|
+
Test that the tensor products of Kirillov-Reshetikhin crystals
|
|
194
|
+
minus non-pseudo-Demazure arrows is in bijection with alcove path
|
|
195
|
+
construction::
|
|
196
|
+
|
|
197
|
+
sage: K = crystals.KirillovReshetikhin(['B',3,1],2,1)
|
|
198
|
+
sage: T = crystals.TensorProduct(K,K)
|
|
199
|
+
sage: g = T.digraph() #long time
|
|
200
|
+
sage: for e in g.edges(sort=False): #long time
|
|
201
|
+
....: if e[0].phi(0) == 1 and e[2] == 0:
|
|
202
|
+
....: g.delete_edge(e)
|
|
203
|
+
|
|
204
|
+
sage: C = crystals.AlcovePaths(['B',3,1],[0,2,0], highest_weight_crystal=False)
|
|
205
|
+
sage: g2 = C.digraph() #long time
|
|
206
|
+
sage: g.is_isomorphic(g2, edge_labels = True) #long time
|
|
207
|
+
True
|
|
208
|
+
|
|
209
|
+
.. NOTE::
|
|
210
|
+
|
|
211
|
+
In type `C_n^{(1)}`, the Kirillov-Reshetikhin crystal is not connected
|
|
212
|
+
when restricted to pseudo-Demazure arrows, hence the previous example will
|
|
213
|
+
fail for type `C_n^{(1)}` crystals.
|
|
214
|
+
|
|
215
|
+
::
|
|
216
|
+
|
|
217
|
+
sage: R = RootSystem(['B',3])
|
|
218
|
+
sage: P = R.weight_lattice()
|
|
219
|
+
sage: La = P.fundamental_weights()
|
|
220
|
+
sage: D = crystals.AlcovePaths(2*La[2], highest_weight_crystal=False)
|
|
221
|
+
sage: C == D
|
|
222
|
+
True
|
|
223
|
+
|
|
224
|
+
.. WARNING:: Weights from finite root systems index non-highest weight crystals.
|
|
225
|
+
"""
|
|
226
|
+
|
|
227
|
+
@staticmethod
|
|
228
|
+
def __classcall_private__(cls, starting_weight, cartan_type=None,
|
|
229
|
+
highest_weight_crystal=None):
|
|
230
|
+
"""
|
|
231
|
+
Classcall to mend the input.
|
|
232
|
+
|
|
233
|
+
Internally, the
|
|
234
|
+
:class:`~sage.combinat.crystals.alcove_path.CrystalOfAlcovePaths`
|
|
235
|
+
code works with a ``starting_weight`` that is in the weight space
|
|
236
|
+
associated to the crystal. The user can, however, also input a
|
|
237
|
+
``cartan_type`` and the coefficients of the fundamental weights as
|
|
238
|
+
``starting_weight``. This code transforms the input into the right
|
|
239
|
+
format (also necessary for :class:`UniqueRepresentation`).
|
|
240
|
+
|
|
241
|
+
TESTS::
|
|
242
|
+
|
|
243
|
+
sage: C = crystals.AlcovePaths(['A',2,1], [1,0,0])
|
|
244
|
+
sage: C2 = crystals.AlcovePaths(CartanType(['A',2,1]), (1,0,0))
|
|
245
|
+
sage: C is C2
|
|
246
|
+
True
|
|
247
|
+
sage: R = RootSystem(['B',2,1])
|
|
248
|
+
sage: La = R.weight_space().basis()
|
|
249
|
+
sage: B1 = crystals.AlcovePaths(['B',2,1],[0,0,1])
|
|
250
|
+
sage: B2 = crystals.AlcovePaths(La[2])
|
|
251
|
+
sage: B1 is B2
|
|
252
|
+
True
|
|
253
|
+
"""
|
|
254
|
+
if isinstance(cartan_type, bool): # new style signature, optional arguments leak over
|
|
255
|
+
highest_weight_crystal = cartan_type
|
|
256
|
+
elif isinstance(cartan_type, (list, tuple)): # old style signature
|
|
257
|
+
# switch positional arguments
|
|
258
|
+
cartan_type, starting_weight = CartanType(starting_weight), cartan_type
|
|
259
|
+
|
|
260
|
+
if highest_weight_crystal is False:
|
|
261
|
+
if not cartan_type.is_affine():
|
|
262
|
+
raise ValueError("non-highest weight crystals only valid for affine types")
|
|
263
|
+
cartan_type = cartan_type.classical()
|
|
264
|
+
|
|
265
|
+
if cartan_type.is_affine():
|
|
266
|
+
extended = True
|
|
267
|
+
else:
|
|
268
|
+
extended = False
|
|
269
|
+
|
|
270
|
+
R = RootSystem(cartan_type)
|
|
271
|
+
P = R.weight_space(extended=extended)
|
|
272
|
+
Lambda = P.basis()
|
|
273
|
+
offset = R.index_set()[Integer(0)]
|
|
274
|
+
starting_weight = P.sum(starting_weight[j - offset] * Lambda[j]
|
|
275
|
+
for j in R.index_set())
|
|
276
|
+
|
|
277
|
+
# set defaults
|
|
278
|
+
if highest_weight_crystal is None:
|
|
279
|
+
highest_weight_crystal = True
|
|
280
|
+
|
|
281
|
+
if not starting_weight.is_dominant():
|
|
282
|
+
raise ValueError("{0} is not a dominant weight".format(starting_weight))
|
|
283
|
+
|
|
284
|
+
return super().__classcall__(cls, starting_weight,
|
|
285
|
+
highest_weight_crystal)
|
|
286
|
+
|
|
287
|
+
def __init__(self, starting_weight, highest_weight_crystal):
|
|
288
|
+
r"""
|
|
289
|
+
Initialize ``self``.
|
|
290
|
+
|
|
291
|
+
TESTS::
|
|
292
|
+
|
|
293
|
+
sage: C = crystals.AlcovePaths(['G',2],[0,1])
|
|
294
|
+
sage: TestSuite(C).run()
|
|
295
|
+
|
|
296
|
+
sage: C = crystals.AlcovePaths(['A',2,1],[1,0,0])
|
|
297
|
+
sage: TestSuite(C).run() #long time
|
|
298
|
+
|
|
299
|
+
sage: C = crystals.AlcovePaths(['A',2,1],[1,0],False)
|
|
300
|
+
sage: TestSuite(C).run(skip='_test_stembridge_local_axioms') #long time
|
|
301
|
+
|
|
302
|
+
Check that :issue:`20292` is fixed::
|
|
303
|
+
|
|
304
|
+
sage: A = crystals.AlcovePaths(['A',2], [1,0])
|
|
305
|
+
sage: A.category()
|
|
306
|
+
Category of classical crystals
|
|
307
|
+
"""
|
|
308
|
+
##########################################################################
|
|
309
|
+
# NOTE:
|
|
310
|
+
# If cartan_type.is_affine() == True and highest weight crystal == False,
|
|
311
|
+
# since we only use the positive roots of the *finite* root system
|
|
312
|
+
# to get the crystal we set self._finite_cartan_type is true
|
|
313
|
+
#
|
|
314
|
+
# We want the indexing set to include 0 so use the affine type notation
|
|
315
|
+
# for the Cartan type.
|
|
316
|
+
##########################################################################
|
|
317
|
+
cartan_type = starting_weight.parent().cartan_type()
|
|
318
|
+
|
|
319
|
+
self.weight = starting_weight
|
|
320
|
+
self.R = RootSystem(cartan_type)
|
|
321
|
+
self._highest_weight_crystal = highest_weight_crystal
|
|
322
|
+
self._cartan_type = cartan_type
|
|
323
|
+
|
|
324
|
+
if cartan_type.is_finite() and highest_weight_crystal:
|
|
325
|
+
Parent.__init__(self, category=ClassicalCrystals())
|
|
326
|
+
self._R = RootsWithHeight(starting_weight)
|
|
327
|
+
self._finite_cartan_type = True
|
|
328
|
+
elif cartan_type.is_finite() and not highest_weight_crystal:
|
|
329
|
+
Parent.__init__(self, category=LoopCrystals().Finite())
|
|
330
|
+
self._R = RootsWithHeight(starting_weight)
|
|
331
|
+
self._finite_cartan_type = True
|
|
332
|
+
self._cartan_type = cartan_type.affine()
|
|
333
|
+
else:
|
|
334
|
+
assert highest_weight_crystal
|
|
335
|
+
Parent.__init__(self, category=HighestWeightCrystals())
|
|
336
|
+
self._R = RootsWithHeight(starting_weight)
|
|
337
|
+
self._finite_cartan_type = False
|
|
338
|
+
|
|
339
|
+
self.module_generators = (self.element_class(self, ()),)
|
|
340
|
+
|
|
341
|
+
def _repr_(self) -> str:
|
|
342
|
+
"""
|
|
343
|
+
Return a string representation of ``self``.
|
|
344
|
+
|
|
345
|
+
EXAMPLES::
|
|
346
|
+
|
|
347
|
+
sage: C = crystals.AlcovePaths(['A',2,1], [1,0,0])
|
|
348
|
+
sage: C
|
|
349
|
+
Highest weight crystal of alcove paths of type ['A', 2, 1] and weight Lambda[0]
|
|
350
|
+
sage: C = crystals.AlcovePaths(['A',2,1], [1,0], False)
|
|
351
|
+
sage: C
|
|
352
|
+
Crystal of alcove paths of type ['A', 2, 1] and weight Lambda[1]
|
|
353
|
+
"""
|
|
354
|
+
if self._highest_weight_crystal:
|
|
355
|
+
return "Highest weight crystal of alcove paths of type %s and weight %s" % (self._cartan_type, self.weight)
|
|
356
|
+
return "Crystal of alcove paths of type %s and weight %s" % (self._cartan_type, self.weight)
|
|
357
|
+
|
|
358
|
+
def _element_constructor_(self, data):
|
|
359
|
+
"""
|
|
360
|
+
Construct an element of ``self`` from ``data``.
|
|
361
|
+
|
|
362
|
+
EXAMPLES::
|
|
363
|
+
|
|
364
|
+
sage: C = crystals.AlcovePaths(['A',2],[3,2])
|
|
365
|
+
sage: C([8,9])
|
|
366
|
+
((alpha[1], 2), (alpha[1] + alpha[2], 4))
|
|
367
|
+
"""
|
|
368
|
+
if isinstance(data, tuple):
|
|
369
|
+
return self.element_class(self, data)
|
|
370
|
+
elif isinstance(data, list):
|
|
371
|
+
lambda_chain = self._R.lambda_chain()
|
|
372
|
+
# data starts indexing at 0
|
|
373
|
+
return self.element_class(self, tuple(sorted([lambda_chain[i] for i in data])))
|
|
374
|
+
|
|
375
|
+
def vertices(self):
|
|
376
|
+
r"""
|
|
377
|
+
Return a list of all the vertices of the crystal.
|
|
378
|
+
|
|
379
|
+
The vertices are represented as lists of integers recording the folding
|
|
380
|
+
positions.
|
|
381
|
+
|
|
382
|
+
One can compute all vertices of the crystal by finding all the
|
|
383
|
+
admissible subsets of the `\lambda`-chain (see method
|
|
384
|
+
is_admissible, for definition). We use the breadth first
|
|
385
|
+
search algorithm.
|
|
386
|
+
|
|
387
|
+
.. WARNING::
|
|
388
|
+
|
|
389
|
+
This method is (currently) only useful for the case when
|
|
390
|
+
``highest_weight_crystal = False``, where you cannot always
|
|
391
|
+
reach all vertices of the crystal using crystal operators,
|
|
392
|
+
starting from the highest weight vertex. This method is
|
|
393
|
+
typically slower than generating the crystal graph using
|
|
394
|
+
crystal operators.
|
|
395
|
+
|
|
396
|
+
EXAMPLES::
|
|
397
|
+
|
|
398
|
+
sage: C = crystals.AlcovePaths(['C', 2], [1, 0])
|
|
399
|
+
sage: C.vertices()
|
|
400
|
+
[[], [0], [0, 1], [0, 1, 2]]
|
|
401
|
+
sage: C = crystals.AlcovePaths(['C', 2, 1], [2, 1], False)
|
|
402
|
+
sage: len(C.vertices())
|
|
403
|
+
80
|
|
404
|
+
|
|
405
|
+
The number of elements reachable using the crystal operators from the
|
|
406
|
+
module generator::
|
|
407
|
+
|
|
408
|
+
sage: len(list(C))
|
|
409
|
+
55
|
|
410
|
+
"""
|
|
411
|
+
lambda_chain = self._R.lambda_chain()
|
|
412
|
+
len_lambda_chain = len(lambda_chain)
|
|
413
|
+
W = WeylGroup(self._R._cartan_type, prefix='s')
|
|
414
|
+
s = W.simple_reflections()
|
|
415
|
+
highest_weight_crystal = self._highest_weight_crystal
|
|
416
|
+
|
|
417
|
+
if highest_weight_crystal:
|
|
418
|
+
successors = 'bruhat_upper_covers'
|
|
419
|
+
else:
|
|
420
|
+
successors = 'quantum_bruhat_successors'
|
|
421
|
+
|
|
422
|
+
# lst contains ordered pairs (w,l) l= list of positions that get
|
|
423
|
+
# you to the word, it needs to be refreshed
|
|
424
|
+
|
|
425
|
+
# initialization
|
|
426
|
+
lst = []
|
|
427
|
+
for i in range(len_lambda_chain):
|
|
428
|
+
associated_reflection = lambda_chain[i].root.associated_reflection()
|
|
429
|
+
if len(associated_reflection) == 1:
|
|
430
|
+
lst.append((prod([s[j] for j in associated_reflection]), [i]))
|
|
431
|
+
|
|
432
|
+
l = copy(lst)
|
|
433
|
+
|
|
434
|
+
while True:
|
|
435
|
+
lst2 = []
|
|
436
|
+
for x in lst:
|
|
437
|
+
suc = getattr(x[0], successors)()
|
|
438
|
+
for j in range(x[1][-1] + 1, len_lambda_chain):
|
|
439
|
+
temp = x[0] * prod(
|
|
440
|
+
[s[k] for k in lambda_chain[j].root.associated_reflection()])
|
|
441
|
+
if temp in suc:
|
|
442
|
+
lst2.append((temp, x[1] + [j]))
|
|
443
|
+
l.append((temp, x[1] + [j]))
|
|
444
|
+
if not lst2:
|
|
445
|
+
break
|
|
446
|
+
else:
|
|
447
|
+
lst = lst2
|
|
448
|
+
|
|
449
|
+
return [[]] + [i[1] for i in l]
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
class CrystalOfAlcovePathsElement(ElementWrapper):
|
|
453
|
+
"""
|
|
454
|
+
Crystal of alcove paths element.
|
|
455
|
+
|
|
456
|
+
INPUT:
|
|
457
|
+
|
|
458
|
+
- ``data`` -- list of folding positions in the lambda chain (indexing
|
|
459
|
+
starts at 0) or a tuple of :class:`RootsWithHeight` giving folding
|
|
460
|
+
positions in the lambda chain.
|
|
461
|
+
|
|
462
|
+
EXAMPLES::
|
|
463
|
+
|
|
464
|
+
sage: C = crystals.AlcovePaths(['A',2],[3,2])
|
|
465
|
+
sage: x = C ( () )
|
|
466
|
+
sage: x.f(1).f(2)
|
|
467
|
+
((alpha[1], 2), (alpha[1] + alpha[2], 4))
|
|
468
|
+
sage: x.f(1).f(2).integer_sequence()
|
|
469
|
+
[8, 9]
|
|
470
|
+
sage: C([8,9])
|
|
471
|
+
((alpha[1], 2), (alpha[1] + alpha[2], 4))
|
|
472
|
+
"""
|
|
473
|
+
|
|
474
|
+
def __iter__(self):
|
|
475
|
+
r"""
|
|
476
|
+
Initialize ``self``.
|
|
477
|
+
|
|
478
|
+
EXAMPLES::
|
|
479
|
+
|
|
480
|
+
sage: C = crystals.AlcovePaths(['A',2],[1,0])
|
|
481
|
+
sage: lst = list(C)
|
|
482
|
+
sage: for i in lst[2]: i
|
|
483
|
+
(alpha[1], 0)
|
|
484
|
+
(alpha[1] + alpha[2], 0)
|
|
485
|
+
"""
|
|
486
|
+
return iter(self.value)
|
|
487
|
+
|
|
488
|
+
def is_admissible(self):
|
|
489
|
+
r"""
|
|
490
|
+
Diagnostic test to check if ``self`` is a valid element of the crystal.
|
|
491
|
+
|
|
492
|
+
If ``self.value`` is given by
|
|
493
|
+
|
|
494
|
+
.. MATH::
|
|
495
|
+
|
|
496
|
+
(\beta_1, i_1), (\beta_2, i_2), \ldots, (\beta_k, i_k),
|
|
497
|
+
|
|
498
|
+
for highest weight crystals this checks if the sequence
|
|
499
|
+
|
|
500
|
+
.. MATH::
|
|
501
|
+
|
|
502
|
+
1 \rightarrow s_{\beta_1} \rightarrow
|
|
503
|
+
s_{\beta_1}s_{\beta_2} \rightarrow \cdots \rightarrow
|
|
504
|
+
s_{\beta_1}s_{\beta_2} \ldots s_{\beta_k}
|
|
505
|
+
|
|
506
|
+
is a path in the Bruhat graph. If ``highest_weight_crystal=False``,
|
|
507
|
+
then the method checks if the above sequence is a path in the quantum
|
|
508
|
+
Bruhat graph.
|
|
509
|
+
|
|
510
|
+
EXAMPLES::
|
|
511
|
+
|
|
512
|
+
sage: C = crystals.AlcovePaths(['A',2],[1,1]); C
|
|
513
|
+
Highest weight crystal of alcove paths of type ['A', 2] and weight Lambda[1] + Lambda[2]
|
|
514
|
+
sage: roots = sorted(C._R._root_lattice.positive_roots()); roots
|
|
515
|
+
[alpha[1], alpha[1] + alpha[2], alpha[2]]
|
|
516
|
+
sage: r1 = C._R(roots[0],0); r1
|
|
517
|
+
(alpha[1], 0)
|
|
518
|
+
sage: r2 = C._R(roots[2],0); r2
|
|
519
|
+
(alpha[2], 0)
|
|
520
|
+
sage: r3 = C._R(roots[1],1); r3
|
|
521
|
+
(alpha[1] + alpha[2], 1)
|
|
522
|
+
sage: x = C( ( r1,r2) )
|
|
523
|
+
sage: x.is_admissible()
|
|
524
|
+
True
|
|
525
|
+
sage: x = C( (r3,) ); x
|
|
526
|
+
((alpha[1] + alpha[2], 1),)
|
|
527
|
+
sage: x.is_admissible()
|
|
528
|
+
False
|
|
529
|
+
sage: C = crystals.AlcovePaths(['C',2,1],[2,1],False)
|
|
530
|
+
sage: C([7,8]).is_admissible()
|
|
531
|
+
True
|
|
532
|
+
sage: C = crystals.AlcovePaths(['A',2],[3,2])
|
|
533
|
+
sage: C([2,3]).is_admissible()
|
|
534
|
+
True
|
|
535
|
+
|
|
536
|
+
.. TODO:: Better doctest
|
|
537
|
+
"""
|
|
538
|
+
W = WeylGroup(self.parent()._R._cartan_type, prefix='s')
|
|
539
|
+
s = W.simple_reflections()
|
|
540
|
+
highest_weight_crystal = self.parent()._highest_weight_crystal
|
|
541
|
+
|
|
542
|
+
if highest_weight_crystal:
|
|
543
|
+
successors = 'bruhat_upper_covers'
|
|
544
|
+
else:
|
|
545
|
+
successors = 'quantum_bruhat_successors'
|
|
546
|
+
|
|
547
|
+
# start at the identity
|
|
548
|
+
w = W.one()
|
|
549
|
+
for i in self:
|
|
550
|
+
t = prod([s[j] for j in i.root.associated_reflection()])
|
|
551
|
+
successor = w * t
|
|
552
|
+
if successor not in getattr(w, successors)():
|
|
553
|
+
return False
|
|
554
|
+
w = successor
|
|
555
|
+
return True
|
|
556
|
+
|
|
557
|
+
def _latex_(self):
|
|
558
|
+
r"""
|
|
559
|
+
Return a `\LaTeX` representation of ``self``.
|
|
560
|
+
|
|
561
|
+
EXAMPLES::
|
|
562
|
+
|
|
563
|
+
sage: C = crystals.AlcovePaths(['A',2],[1,1])
|
|
564
|
+
sage: C([1,2])._latex_()
|
|
565
|
+
[(\alpha_{1} + \alpha_{2}, 0), (\alpha_{1}, 0)]
|
|
566
|
+
"""
|
|
567
|
+
return [(latex(i.root), i.height) for i in self.value]
|
|
568
|
+
|
|
569
|
+
@cached_in_parent_method
|
|
570
|
+
def integer_sequence(self):
|
|
571
|
+
r"""
|
|
572
|
+
Return a list of integers corresponding to positions in
|
|
573
|
+
the `\lambda`-chain where it is folded.
|
|
574
|
+
|
|
575
|
+
.. TODO::
|
|
576
|
+
|
|
577
|
+
Incorporate this method into the ``_repr_`` for finite Cartan type.
|
|
578
|
+
|
|
579
|
+
.. NOTE::
|
|
580
|
+
|
|
581
|
+
Only works for finite Cartan types and indexing starts at 0.
|
|
582
|
+
|
|
583
|
+
EXAMPLES::
|
|
584
|
+
|
|
585
|
+
sage: C = crystals.AlcovePaths(['A',2],[3,2])
|
|
586
|
+
sage: x = C( () )
|
|
587
|
+
sage: x.f(1).f(2).integer_sequence()
|
|
588
|
+
[8, 9]
|
|
589
|
+
"""
|
|
590
|
+
lambda_chain = self.parent()._R.lambda_chain()
|
|
591
|
+
return [lambda_chain.index(j) for j in self.value]
|
|
592
|
+
|
|
593
|
+
def phi(self, i):
|
|
594
|
+
r"""
|
|
595
|
+
Return the distance to the end of the `i`-string.
|
|
596
|
+
|
|
597
|
+
This method overrides the generic implementation in the category of
|
|
598
|
+
crystals since this computation is more efficient.
|
|
599
|
+
|
|
600
|
+
EXAMPLES::
|
|
601
|
+
|
|
602
|
+
sage: C = crystals.AlcovePaths(['A',2],[1,1])
|
|
603
|
+
sage: [c.phi(1) for c in C]
|
|
604
|
+
[1, 0, 0, 1, 0, 2, 1, 0]
|
|
605
|
+
sage: [c.phi(2) for c in C]
|
|
606
|
+
[1, 2, 1, 0, 0, 0, 0, 1]
|
|
607
|
+
"""
|
|
608
|
+
highest_weight_crystal = self.parent()._highest_weight_crystal
|
|
609
|
+
positions, gi = self._gi(i)
|
|
610
|
+
|
|
611
|
+
m = max(gi)
|
|
612
|
+
|
|
613
|
+
if not highest_weight_crystal and i == 0:
|
|
614
|
+
raise NotImplementedError
|
|
615
|
+
# I think the M below should still work in this case
|
|
616
|
+
|
|
617
|
+
return Integer(m) / 2 - Integer(1) / 2
|
|
618
|
+
|
|
619
|
+
def epsilon(self, i):
|
|
620
|
+
r"""
|
|
621
|
+
Return the distance to the start of the `i`-string.
|
|
622
|
+
|
|
623
|
+
EXAMPLES::
|
|
624
|
+
|
|
625
|
+
sage: C = crystals.AlcovePaths(['A',2],[1,1])
|
|
626
|
+
sage: [c.epsilon(1) for c in C]
|
|
627
|
+
[0, 1, 0, 0, 1, 0, 1, 2]
|
|
628
|
+
sage: [c.epsilon(2) for c in C]
|
|
629
|
+
[0, 0, 1, 2, 1, 1, 0, 0]
|
|
630
|
+
"""
|
|
631
|
+
# crude but functional
|
|
632
|
+
j = 0
|
|
633
|
+
temp = self
|
|
634
|
+
temp = temp.e(i)
|
|
635
|
+
while temp is not None:
|
|
636
|
+
j += 1
|
|
637
|
+
temp = temp.e(i)
|
|
638
|
+
|
|
639
|
+
return j
|
|
640
|
+
|
|
641
|
+
def weight(self):
|
|
642
|
+
"""
|
|
643
|
+
Return the weight of ``self``.
|
|
644
|
+
|
|
645
|
+
EXAMPLES::
|
|
646
|
+
|
|
647
|
+
sage: C = crystals.AlcovePaths(['A',2],[2,0])
|
|
648
|
+
sage: for i in C: i.weight()
|
|
649
|
+
(2, 0, 0)
|
|
650
|
+
(1, 1, 0)
|
|
651
|
+
(0, 2, 0)
|
|
652
|
+
(0, -1, 0)
|
|
653
|
+
(-1, 0, 0)
|
|
654
|
+
(-2, -2, 0)
|
|
655
|
+
sage: B = crystals.AlcovePaths(['A',2,1],[1,0,0])
|
|
656
|
+
sage: p = B.module_generators[0].f_string([0,1,2])
|
|
657
|
+
sage: p.weight()
|
|
658
|
+
Lambda[0] - delta
|
|
659
|
+
|
|
660
|
+
TESTS:
|
|
661
|
+
|
|
662
|
+
Check that crystal morphisms work (:issue:`19481`)::
|
|
663
|
+
|
|
664
|
+
sage: C1 = crystals.AlcovePaths(['A',2],[1,0])
|
|
665
|
+
sage: C2 = crystals.AlcovePaths(['A',2],[2,0])
|
|
666
|
+
sage: phi = C1.crystal_morphism(C2.module_generators, scaling_factors={1:2, 2:2})
|
|
667
|
+
sage: [phi(x) for x in C1]
|
|
668
|
+
[(), ((alpha[1], 0),), ((alpha[1], 0), (alpha[1] + alpha[2], 0))]
|
|
669
|
+
|
|
670
|
+
Check that all weights are of level 0 in the KR crystal setting
|
|
671
|
+
(:issue:`20292`)::
|
|
672
|
+
|
|
673
|
+
sage: A = crystals.AlcovePaths(['A',2,1], [1,0], highest_weight_crystal=False)
|
|
674
|
+
sage: all(x.weight().level() == 0 for x in A)
|
|
675
|
+
True
|
|
676
|
+
"""
|
|
677
|
+
root_space = self.parent().R.root_space()
|
|
678
|
+
weight = -self.parent().weight
|
|
679
|
+
for i in self.value[::-1]:
|
|
680
|
+
root = root_space(i.root)
|
|
681
|
+
weight = -i.height * root + weight.reflection(root)
|
|
682
|
+
|
|
683
|
+
WLR = self.parent().weight_lattice_realization()
|
|
684
|
+
if self.cartan_type().is_affine() and self.parent()._highest_weight_crystal:
|
|
685
|
+
# We assume that WLR is the (extended) weight lattice
|
|
686
|
+
wt = WLR._from_dict({i: Integer(c) for i, c in -weight},
|
|
687
|
+
remove_zeros=False)
|
|
688
|
+
return wt
|
|
689
|
+
La = WLR.fundamental_weights()
|
|
690
|
+
wt = WLR.sum(Integer(c) * La[i] for i, c in -weight)
|
|
691
|
+
if self.cartan_type().is_affine():
|
|
692
|
+
assert not self.parent()._highest_weight_crystal
|
|
693
|
+
wt -= La[0] * wt.level()
|
|
694
|
+
return wt
|
|
695
|
+
|
|
696
|
+
def plot(self):
|
|
697
|
+
r"""
|
|
698
|
+
Return a plot ``self``.
|
|
699
|
+
|
|
700
|
+
.. NOTE::
|
|
701
|
+
|
|
702
|
+
Currently only implemented for types `A_2`, `B_2`, and `C_2`.
|
|
703
|
+
|
|
704
|
+
EXAMPLES::
|
|
705
|
+
|
|
706
|
+
sage: C = crystals.AlcovePaths(['A',2],[2,0])
|
|
707
|
+
sage: x = C( () ).f(1).f(2)
|
|
708
|
+
sage: x.plot() # Not tested - creates a pdf
|
|
709
|
+
"""
|
|
710
|
+
ct = self.parent()._R._cartan_type.dual()
|
|
711
|
+
word = self.parent()._R.word()
|
|
712
|
+
integer_sequence = self.integer_sequence()
|
|
713
|
+
foldings = [False for i in word]
|
|
714
|
+
for i in integer_sequence:
|
|
715
|
+
foldings[i] = True
|
|
716
|
+
affine_ambient_space = RootSystem(ct.affine()).ambient_space()
|
|
717
|
+
return affine_ambient_space.plot() + affine_ambient_space.plot_alcove_walk(word, foldings=foldings, labels=False)
|
|
718
|
+
|
|
719
|
+
def _richcmp_(self, other, op):
|
|
720
|
+
r"""
|
|
721
|
+
Comparison of ``self.value`` and ``other.value``.
|
|
722
|
+
|
|
723
|
+
For inequalities, ``self.value`` is compared to
|
|
724
|
+
``other.value`` in dictionary order.
|
|
725
|
+
|
|
726
|
+
EXAMPLES::
|
|
727
|
+
|
|
728
|
+
sage: C = crystals.AlcovePaths(['B',2],[1,0])
|
|
729
|
+
sage: lst = list(C)
|
|
730
|
+
sage: lst[2] == lst[2]
|
|
731
|
+
True
|
|
732
|
+
sage: lst[2] == lst[1]
|
|
733
|
+
False
|
|
734
|
+
sage: lst[2] != lst[2]
|
|
735
|
+
False
|
|
736
|
+
sage: lst[2] != lst[1]
|
|
737
|
+
True
|
|
738
|
+
|
|
739
|
+
sage: C = crystals.AlcovePaths(['A',2],[2,0])
|
|
740
|
+
sage: x = C(())
|
|
741
|
+
sage: x < x.f(1)
|
|
742
|
+
True
|
|
743
|
+
sage: a = x.f(1) ; b = x.f(1).f(1).f(2)
|
|
744
|
+
sage: a < b
|
|
745
|
+
False
|
|
746
|
+
|
|
747
|
+
sage: C = crystals.AlcovePaths(['A',2],[2,0])
|
|
748
|
+
sage: x = C( () )
|
|
749
|
+
sage: x > x.f(1)
|
|
750
|
+
False
|
|
751
|
+
sage: a = x.f(1) ; b = x.f(1).f(1).f(2)
|
|
752
|
+
sage: a > b
|
|
753
|
+
True
|
|
754
|
+
"""
|
|
755
|
+
return richcmp(self.value, other.value, op)
|
|
756
|
+
|
|
757
|
+
def __hash__(self):
|
|
758
|
+
"""
|
|
759
|
+
Return the hash of ``self``.
|
|
760
|
+
|
|
761
|
+
EXAMPLES::
|
|
762
|
+
|
|
763
|
+
sage: C = crystals.AlcovePaths(['B',2],[1,0])
|
|
764
|
+
sage: lst = list(C)
|
|
765
|
+
sage: hash(lst[2]) == hash(lst[2])
|
|
766
|
+
True
|
|
767
|
+
"""
|
|
768
|
+
return hash(self.value)
|
|
769
|
+
|
|
770
|
+
def _folding_data(self, i):
|
|
771
|
+
r"""
|
|
772
|
+
Compute information needed to build the graph `g_{\alpha_i}`.
|
|
773
|
+
Results of this method are sent to _gi for further processing.
|
|
774
|
+
|
|
775
|
+
INPUT:
|
|
776
|
+
|
|
777
|
+
- ``i`` -- element of the index_set of the underlying root_system
|
|
778
|
+
|
|
779
|
+
OUTPUT:
|
|
780
|
+
|
|
781
|
+
A dictionary where the keys are of type RootsWithHeight which record
|
|
782
|
+
positions where `\pm \alpha_i` shows up in the folded `\lambda` chain.
|
|
783
|
+
The values are `1` if `\alpha_i` is in the corresponding position in
|
|
784
|
+
the folded `\lambda`-chain, `-1` if `-\alpha_i` is in the corresponding
|
|
785
|
+
position in the folded `\lambda`-chain.
|
|
786
|
+
|
|
787
|
+
.. NOTE::
|
|
788
|
+
|
|
789
|
+
*infinity* is a special key that records the "sign at infinity".
|
|
790
|
+
|
|
791
|
+
::
|
|
792
|
+
|
|
793
|
+
sage: C = crystals.AlcovePaths(['A',2],[1,1])
|
|
794
|
+
sage: x = C( () ).f(1)
|
|
795
|
+
sage: fd = x._folding_data(2); fd # # random output
|
|
796
|
+
{(alpha[2], 0): 1, (alpha[1] + alpha[2], 1): 1, 'infinity': 1}
|
|
797
|
+
sage: fd['infinity']
|
|
798
|
+
1
|
|
799
|
+
sage: sorted(fd.values())
|
|
800
|
+
[1, 1, 1]
|
|
801
|
+
"""
|
|
802
|
+
Parent = self.parent()
|
|
803
|
+
|
|
804
|
+
# self.value contains the admissible sequence as a tuple of Element
|
|
805
|
+
|
|
806
|
+
finite_cartan_type = Parent._finite_cartan_type # bool
|
|
807
|
+
J = list(self.value)
|
|
808
|
+
|
|
809
|
+
# NOTE: R is a RootsWithHeight object and NOT a RootSystem object
|
|
810
|
+
R = Parent._R
|
|
811
|
+
weight = Parent.weight
|
|
812
|
+
|
|
813
|
+
signs = {}
|
|
814
|
+
|
|
815
|
+
# 0 arrows in the case of finite Cartan type
|
|
816
|
+
# always allow 0 arrows
|
|
817
|
+
if finite_cartan_type and i == 0:
|
|
818
|
+
Beta = R._root_lattice.highest_root()
|
|
819
|
+
elif i in self.index_set():
|
|
820
|
+
Beta = R._root_lattice.simple_root(i)
|
|
821
|
+
|
|
822
|
+
max_height_Beta = weight.scalar(Beta.associated_coroot())
|
|
823
|
+
|
|
824
|
+
if not J:
|
|
825
|
+
for k in range(max_height_Beta):
|
|
826
|
+
x = R(Beta, k)
|
|
827
|
+
signs[x] = self._sign(Beta)
|
|
828
|
+
signs['infinity'] = self._sign(Beta)
|
|
829
|
+
|
|
830
|
+
else:
|
|
831
|
+
# NOTE: we assume J is sorted by order on Element of RootsWithHeight
|
|
832
|
+
|
|
833
|
+
for k in range(max_height_Beta):
|
|
834
|
+
x = R(Beta, k)
|
|
835
|
+
if x <= J[0]:
|
|
836
|
+
signs[x] = self._sign(Beta)
|
|
837
|
+
|
|
838
|
+
for j in range(len(J)):
|
|
839
|
+
Beta = Beta.reflection(J[j].root)
|
|
840
|
+
sign_Beta = self._sign(Beta)
|
|
841
|
+
max_height_Beta = weight.scalar(
|
|
842
|
+
(sign_Beta * Beta).associated_coroot())
|
|
843
|
+
|
|
844
|
+
# some optimization so we don't initialize too many objects
|
|
845
|
+
# range(c1,c2) can be replaced by range(max_height_Beta) but it
|
|
846
|
+
# checks unnecessary extra things
|
|
847
|
+
|
|
848
|
+
c1 = J[j]._cmp_v[0] * max_height_Beta
|
|
849
|
+
if j == len(J) - 1:
|
|
850
|
+
c2 = max_height_Beta
|
|
851
|
+
else:
|
|
852
|
+
c2 = min(max_height_Beta, J[j+1]._cmp_v[0]*max_height_Beta + 1)
|
|
853
|
+
|
|
854
|
+
for k in range(int(c1), int(c2)):
|
|
855
|
+
|
|
856
|
+
x = R(sign_Beta * Beta, k)
|
|
857
|
+
|
|
858
|
+
if (
|
|
859
|
+
(j < len(J) - 1 and J[j] < x <= J[j + 1]) or
|
|
860
|
+
(j == len(J) - 1 and J[j] < x)
|
|
861
|
+
):
|
|
862
|
+
signs[x] = sign_Beta
|
|
863
|
+
|
|
864
|
+
signs['infinity'] = sign_Beta
|
|
865
|
+
# tail sign tells something about last step in g_alpha
|
|
866
|
+
|
|
867
|
+
if finite_cartan_type and i == 0:
|
|
868
|
+
signs = {x: -signs[x] for x in signs}
|
|
869
|
+
|
|
870
|
+
return signs
|
|
871
|
+
|
|
872
|
+
def e(self, i):
|
|
873
|
+
r"""
|
|
874
|
+
Return the `i`-th crystal raising operator on ``self``.
|
|
875
|
+
|
|
876
|
+
INPUT:
|
|
877
|
+
|
|
878
|
+
- ``i`` -- element of the index set of the underlying root system
|
|
879
|
+
|
|
880
|
+
EXAMPLES::
|
|
881
|
+
|
|
882
|
+
sage: C = crystals.AlcovePaths(['A',2],[2,0]); C
|
|
883
|
+
Highest weight crystal of alcove paths of type ['A', 2] and weight 2*Lambda[1]
|
|
884
|
+
sage: x = C( () )
|
|
885
|
+
sage: x.e(1)
|
|
886
|
+
sage: x.f(1) == x.f(1).f(2).e(2)
|
|
887
|
+
True
|
|
888
|
+
"""
|
|
889
|
+
Parent = self.parent()
|
|
890
|
+
finite_cartan_type = Parent._finite_cartan_type
|
|
891
|
+
|
|
892
|
+
J = list(self.value)
|
|
893
|
+
positions, gi = self._gi(i)
|
|
894
|
+
|
|
895
|
+
m = max(gi)
|
|
896
|
+
m_index = len(gi)-1-list(reversed(gi)).index(m) # last max in gi
|
|
897
|
+
|
|
898
|
+
if finite_cartan_type and i == 0:
|
|
899
|
+
M = Integer(m)/2 + Integer(1)/2
|
|
900
|
+
else:
|
|
901
|
+
M = Integer(m)/2 - Integer(1)/2
|
|
902
|
+
|
|
903
|
+
KR_test = finite_cartan_type and i == 0 and m_index < len(gi) - 1
|
|
904
|
+
KR_test = KR_test and M >= 1
|
|
905
|
+
|
|
906
|
+
###################################################################
|
|
907
|
+
# NOTE:
|
|
908
|
+
# In the KR_case we want to insure that positions[m_index] is in J
|
|
909
|
+
# If m_index > 0 then it's always true
|
|
910
|
+
# If m_index == 0 then M >=1 guarantees this
|
|
911
|
+
###################################################################
|
|
912
|
+
|
|
913
|
+
if ((not finite_cartan_type or i != 0) and m_index < len(gi) - 1) or KR_test:
|
|
914
|
+
# first condition above means that alpha_i is a simple root
|
|
915
|
+
|
|
916
|
+
J.remove(positions[m_index])
|
|
917
|
+
if m_index + 1 < len(positions):
|
|
918
|
+
# if m_index+1 != 'infinity'
|
|
919
|
+
# i.e. positions[m_index+1] makes sense
|
|
920
|
+
J.append(positions[m_index + 1])
|
|
921
|
+
return_value = Parent(tuple(sorted(J)))
|
|
922
|
+
|
|
923
|
+
# we attach to each admissible sequence a list
|
|
924
|
+
# which encodes a path (via root operators) from the () generator
|
|
925
|
+
# to the admissible sequence
|
|
926
|
+
# this is useful for investing the crystal
|
|
927
|
+
|
|
928
|
+
try:
|
|
929
|
+
return_value.i_string = self.i_string + [['e', i]]
|
|
930
|
+
except AttributeError:
|
|
931
|
+
return_value.i_string = [['e', i]]
|
|
932
|
+
|
|
933
|
+
return return_value
|
|
934
|
+
else:
|
|
935
|
+
return None
|
|
936
|
+
|
|
937
|
+
@cached_method
|
|
938
|
+
def _gi(self, i):
|
|
939
|
+
r"""
|
|
940
|
+
Compute information needed to build the graph `g_{\alpha_i}`.
|
|
941
|
+
This graph is used to apply the `i`-th crystal operator.
|
|
942
|
+
|
|
943
|
+
INPUT:
|
|
944
|
+
|
|
945
|
+
- ``i`` -- element of the index_set of the underlying root_system
|
|
946
|
+
|
|
947
|
+
OUTPUT:
|
|
948
|
+
|
|
949
|
+
A tuple ``(positions, gi)``:
|
|
950
|
+
|
|
951
|
+
- ``positions`` -- is a list of RootsWithHeight. These appear sorted in
|
|
952
|
+
their natural order, and record where `\pm \alpha_i` shows up in
|
|
953
|
+
the folded `\lambda`-chain.
|
|
954
|
+
|
|
955
|
+
- ``gi`` -- is a list of integers recording the height
|
|
956
|
+
(up to affine transformation) of `\pm \alpha_i`
|
|
957
|
+
in the folded `\lambda`-chain whose location is recorded by
|
|
958
|
+
``positions``.
|
|
959
|
+
|
|
960
|
+
.. NOTE::
|
|
961
|
+
|
|
962
|
+
- ``positions`` has length one less than ``gi`` since it does not
|
|
963
|
+
contain the position 'infinity'.
|
|
964
|
+
|
|
965
|
+
- To get the real `g_{\alpha_i}` one has to divide by 2 and add 1/2
|
|
966
|
+
or divide by 2 and subtract 1/2 depending on if
|
|
967
|
+
``self._finite_cartan_type==True and i == 0``
|
|
968
|
+
or not. This is done in crystal operator methods.
|
|
969
|
+
|
|
970
|
+
EXAMPLES::
|
|
971
|
+
|
|
972
|
+
sage: C=crystals.AlcovePaths(['A',2],[1,1])
|
|
973
|
+
sage: x=C( () ).f(1)
|
|
974
|
+
sage: x._gi(2)
|
|
975
|
+
([(alpha[2], 0), (alpha[1] + alpha[2], 1)], [1, 3, 5])
|
|
976
|
+
"""
|
|
977
|
+
signs = self._folding_data(i)
|
|
978
|
+
positions = sorted(x for x in signs if x != 'infinity')
|
|
979
|
+
|
|
980
|
+
if not positions:
|
|
981
|
+
return (positions, [signs['infinity']])
|
|
982
|
+
|
|
983
|
+
gi = [signs[positions[0]]]
|
|
984
|
+
for j in range(1, len(positions)):
|
|
985
|
+
gi.append(
|
|
986
|
+
gi[j-1] +
|
|
987
|
+
signs[positions[j-1]] * self._eps(positions[j-1]) +
|
|
988
|
+
signs[positions[j]])
|
|
989
|
+
gi.append(gi[-1] +
|
|
990
|
+
signs[positions[-1]] * self._eps(positions[-1]) +
|
|
991
|
+
signs['infinity'])
|
|
992
|
+
|
|
993
|
+
return (positions, gi)
|
|
994
|
+
|
|
995
|
+
def f(self, i):
|
|
996
|
+
r"""
|
|
997
|
+
Return the `i`-th crystal lowering operator on ``self``.
|
|
998
|
+
|
|
999
|
+
INPUT:
|
|
1000
|
+
|
|
1001
|
+
- ``i`` -- element of the index_set of the underlying root_system
|
|
1002
|
+
|
|
1003
|
+
EXAMPLES::
|
|
1004
|
+
|
|
1005
|
+
sage: C=crystals.AlcovePaths(['B',2],[1,1])
|
|
1006
|
+
sage: x=C( () )
|
|
1007
|
+
sage: x.f(1)
|
|
1008
|
+
((alpha[1], 0),)
|
|
1009
|
+
sage: x.f(1).f(2)
|
|
1010
|
+
((alpha[1], 0), (alpha[1] + alpha[2], 2))
|
|
1011
|
+
"""
|
|
1012
|
+
Parent = self.parent()
|
|
1013
|
+
finite_cartan_type = Parent._finite_cartan_type
|
|
1014
|
+
|
|
1015
|
+
# get a copy in a form of a list of self.value
|
|
1016
|
+
J = list(self.value)
|
|
1017
|
+
positions, gi = self._gi(i)
|
|
1018
|
+
|
|
1019
|
+
m = max(gi)
|
|
1020
|
+
m_index = gi.index(m)
|
|
1021
|
+
|
|
1022
|
+
if finite_cartan_type and i == 0:
|
|
1023
|
+
|
|
1024
|
+
# python doesn't handle fractions natively
|
|
1025
|
+
M = Integer(m)/2 + Integer(1)/2
|
|
1026
|
+
else:
|
|
1027
|
+
M = Integer(m)/2 - Integer(1)/2
|
|
1028
|
+
|
|
1029
|
+
# boolean determining when to move a folding in KR case
|
|
1030
|
+
KR_test = finite_cartan_type and i == 0
|
|
1031
|
+
KR_test = KR_test and M > 1
|
|
1032
|
+
|
|
1033
|
+
# In the KR case, we return a value other than None when
|
|
1034
|
+
# `\alpha_i` is in position m_index - 1
|
|
1035
|
+
# (The following relies on a technical condition (C2) )
|
|
1036
|
+
# note insert reference
|
|
1037
|
+
#
|
|
1038
|
+
# if m_index - 1 == 0 then M > 1 and (C2) forces
|
|
1039
|
+
# `\alhpa_i` in positions[m_index - 1]
|
|
1040
|
+
#
|
|
1041
|
+
# otherwise if m_index - 1 > 0 then (C2) is enough
|
|
1042
|
+
|
|
1043
|
+
if ((not finite_cartan_type or i != 0) and M > 0) or KR_test:
|
|
1044
|
+
# first condition above means that alpha_i is a simple root
|
|
1045
|
+
|
|
1046
|
+
J.append(positions[m_index - 1])
|
|
1047
|
+
if m_index < len(positions):
|
|
1048
|
+
# if m_index != 'infinity'
|
|
1049
|
+
# thus positions[m_index] makes sense
|
|
1050
|
+
J.remove(positions[m_index])
|
|
1051
|
+
return_value = Parent(tuple(sorted(J)))
|
|
1052
|
+
|
|
1053
|
+
# we attach to each admissible sequence a list
|
|
1054
|
+
# which encodes a path (via root operators) from the generator ()
|
|
1055
|
+
|
|
1056
|
+
try:
|
|
1057
|
+
return_value.i_string = self.i_string + [['f', i]]
|
|
1058
|
+
except AttributeError:
|
|
1059
|
+
return_value.i_string = [['f', i]]
|
|
1060
|
+
|
|
1061
|
+
return return_value
|
|
1062
|
+
else:
|
|
1063
|
+
return None
|
|
1064
|
+
|
|
1065
|
+
@staticmethod
|
|
1066
|
+
def _sign(root):
|
|
1067
|
+
r"""
|
|
1068
|
+
Return `1` if root is a positive root, and `-1` if root is a negative
|
|
1069
|
+
root.
|
|
1070
|
+
|
|
1071
|
+
EXAMPLES::
|
|
1072
|
+
|
|
1073
|
+
sage: from sage.combinat.crystals.alcove_path import CrystalOfAlcovePathsElement
|
|
1074
|
+
sage: rl = RootSystem(['A',2]).root_lattice()
|
|
1075
|
+
sage: x = rl.from_vector(vector([0,1]))
|
|
1076
|
+
sage: CrystalOfAlcovePathsElement._sign(x)
|
|
1077
|
+
1
|
|
1078
|
+
"""
|
|
1079
|
+
if root.is_positive_root():
|
|
1080
|
+
return 1
|
|
1081
|
+
else:
|
|
1082
|
+
return -1
|
|
1083
|
+
|
|
1084
|
+
def _eps(self, root):
|
|
1085
|
+
r"""
|
|
1086
|
+
Return `-1` if root is in ``self.value``, otherwise return `1`.
|
|
1087
|
+
|
|
1088
|
+
EXAMPLES::
|
|
1089
|
+
|
|
1090
|
+
sage: C = crystals.AlcovePaths(['C',2],[3,2])
|
|
1091
|
+
sage: x = C( () ).f(1).f(2); x
|
|
1092
|
+
((alpha[1], 2), (2*alpha[1] + alpha[2], 4))
|
|
1093
|
+
sage: x._eps(x.value[0])
|
|
1094
|
+
-1
|
|
1095
|
+
sage: R = C._R
|
|
1096
|
+
sage: y = R ( x.value[0].root, 1 ); y
|
|
1097
|
+
(alpha[1], 1)
|
|
1098
|
+
sage: x._eps(y)
|
|
1099
|
+
1
|
|
1100
|
+
"""
|
|
1101
|
+
if root in self.value:
|
|
1102
|
+
return -1
|
|
1103
|
+
else:
|
|
1104
|
+
return 1
|
|
1105
|
+
|
|
1106
|
+
def path(self):
|
|
1107
|
+
"""
|
|
1108
|
+
Return the path in the (quantum) Bruhat graph corresponding
|
|
1109
|
+
to ``self``.
|
|
1110
|
+
|
|
1111
|
+
EXAMPLES::
|
|
1112
|
+
|
|
1113
|
+
sage: C = crystals.AlcovePaths(['B', 3], [3,1,2])
|
|
1114
|
+
sage: b = C.highest_weight_vector().f_string([1,3,2,1,3,1])
|
|
1115
|
+
sage: b.path()
|
|
1116
|
+
[1, s1, s3*s1, s2*s3*s1, s3*s2*s3*s1]
|
|
1117
|
+
sage: b = C.highest_weight_vector().f_string([2,3,3,2])
|
|
1118
|
+
sage: b.path()
|
|
1119
|
+
[1, s2, s3*s2, s2*s3*s2]
|
|
1120
|
+
sage: b = C.highest_weight_vector().f_string([2,3,3,2,1])
|
|
1121
|
+
sage: b.path()
|
|
1122
|
+
[1, s2, s3*s2, s2*s3*s2, s1*s2*s3*s2]
|
|
1123
|
+
"""
|
|
1124
|
+
W = WeylGroup(self.parent()._R._cartan_type, prefix='s')
|
|
1125
|
+
s = W.simple_reflections()
|
|
1126
|
+
|
|
1127
|
+
# start at the identity
|
|
1128
|
+
w = W.one()
|
|
1129
|
+
ret = [w]
|
|
1130
|
+
for i in self:
|
|
1131
|
+
ret.append(ret[-1] * prod(s[j] for j in i.root.associated_reflection()))
|
|
1132
|
+
return ret
|
|
1133
|
+
|
|
1134
|
+
|
|
1135
|
+
CrystalOfAlcovePaths.Element = CrystalOfAlcovePathsElement
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
class InfinityCrystalOfAlcovePaths(UniqueRepresentation, Parent):
|
|
1139
|
+
r"""
|
|
1140
|
+
`\mathcal{B}(\infty)` crystal of alcove paths.
|
|
1141
|
+
"""
|
|
1142
|
+
@staticmethod
|
|
1143
|
+
def __classcall_private__(cls, cartan_type):
|
|
1144
|
+
"""
|
|
1145
|
+
Normalize input to ensure a unique representation.
|
|
1146
|
+
|
|
1147
|
+
TESTS::
|
|
1148
|
+
|
|
1149
|
+
sage: A1 = crystals.infinity.AlcovePaths(['A',2])
|
|
1150
|
+
sage: A2 = crystals.infinity.AlcovePaths(CartanType(['A',2]))
|
|
1151
|
+
sage: A3 = crystals.infinity.AlcovePaths('A2')
|
|
1152
|
+
sage: A1 is A2 and A2 is A3
|
|
1153
|
+
True
|
|
1154
|
+
"""
|
|
1155
|
+
cartan_type = CartanType(cartan_type)
|
|
1156
|
+
return super().__classcall__(cls, cartan_type)
|
|
1157
|
+
|
|
1158
|
+
def __init__(self, cartan_type):
|
|
1159
|
+
"""
|
|
1160
|
+
Initialize ``self``.
|
|
1161
|
+
|
|
1162
|
+
TESTS::
|
|
1163
|
+
|
|
1164
|
+
sage: A = crystals.infinity.AlcovePaths(['C',3])
|
|
1165
|
+
sage: TestSuite(A).run(max_runs=20)
|
|
1166
|
+
|
|
1167
|
+
sage: A = crystals.infinity.AlcovePaths(['A',2,1])
|
|
1168
|
+
sage: TestSuite(A).run() # long time
|
|
1169
|
+
"""
|
|
1170
|
+
self._cartan_type = cartan_type
|
|
1171
|
+
Parent.__init__(self, category=HighestWeightCrystals().Infinite())
|
|
1172
|
+
|
|
1173
|
+
self.module_generators = (self.element_class(self, (), 0),)
|
|
1174
|
+
|
|
1175
|
+
def _repr_(self) -> str:
|
|
1176
|
+
"""
|
|
1177
|
+
Return a string representation of ``self``.
|
|
1178
|
+
|
|
1179
|
+
EXAMPLES::
|
|
1180
|
+
|
|
1181
|
+
sage: crystals.infinity.AlcovePaths(['E',6])
|
|
1182
|
+
Infinity crystal of alcove paths of type ['E', 6]
|
|
1183
|
+
"""
|
|
1184
|
+
return "Infinity crystal of alcove paths of type {}".format(self._cartan_type)
|
|
1185
|
+
|
|
1186
|
+
class Element(ElementWrapper):
|
|
1187
|
+
def __init__(self, parent, elt, shift):
|
|
1188
|
+
"""
|
|
1189
|
+
Initialize ``self``.
|
|
1190
|
+
|
|
1191
|
+
EXAMPLES::
|
|
1192
|
+
|
|
1193
|
+
sage: A = crystals.infinity.AlcovePaths(['F',4])
|
|
1194
|
+
sage: mg = A.highest_weight_vector()
|
|
1195
|
+
sage: x = mg.f_string([2,3,1,4,4,2,3,1])
|
|
1196
|
+
sage: TestSuite(x).run()
|
|
1197
|
+
"""
|
|
1198
|
+
ElementWrapper.__init__(self, parent, elt)
|
|
1199
|
+
self._shift = shift
|
|
1200
|
+
|
|
1201
|
+
def e(self, i):
|
|
1202
|
+
"""
|
|
1203
|
+
Return the action of `e_i` on ``self``.
|
|
1204
|
+
|
|
1205
|
+
INPUT:
|
|
1206
|
+
|
|
1207
|
+
- ``i`` -- an element of the index set
|
|
1208
|
+
|
|
1209
|
+
EXAMPLES::
|
|
1210
|
+
|
|
1211
|
+
sage: A = crystals.infinity.AlcovePaths(['D',5,1])
|
|
1212
|
+
sage: mg = A.highest_weight_vector()
|
|
1213
|
+
sage: x = mg.f_string([1,3,4,2,5,4,5,5])
|
|
1214
|
+
sage: x.f(4).e(5) == x.e(5).f(4)
|
|
1215
|
+
True
|
|
1216
|
+
"""
|
|
1217
|
+
y = self.projection().e(i)
|
|
1218
|
+
if y is None:
|
|
1219
|
+
return None
|
|
1220
|
+
if not y.value:
|
|
1221
|
+
return self.parent().module_generators[0]
|
|
1222
|
+
|
|
1223
|
+
n = self.parent()._cartan_type.rank()
|
|
1224
|
+
s = lambda rt: int(sum(rt.associated_coroot().coefficients()))
|
|
1225
|
+
shift = self._shift
|
|
1226
|
+
while y.is_admissible():
|
|
1227
|
+
# The only element with a shift of 0 is the highest weight element.
|
|
1228
|
+
# So we do not need to check for the shift being 0.
|
|
1229
|
+
prev = y
|
|
1230
|
+
shift -= 1
|
|
1231
|
+
A = CrystalOfAlcovePaths(self.parent()._cartan_type, [shift]*n)
|
|
1232
|
+
try:
|
|
1233
|
+
y = A(tuple([A._R(rt.root, rt.height - s(rt.root)) for rt in y.value]))
|
|
1234
|
+
except ValueError: # Invalid height (and not admissible)
|
|
1235
|
+
break
|
|
1236
|
+
shift += 1
|
|
1237
|
+
return type(self)(self.parent(),
|
|
1238
|
+
tuple([(rt.root, rt.height - shift*s(rt.root))
|
|
1239
|
+
for rt in prev.value]),
|
|
1240
|
+
shift)
|
|
1241
|
+
|
|
1242
|
+
def f(self, i):
|
|
1243
|
+
"""
|
|
1244
|
+
Return the action of `f_i` on ``self``.
|
|
1245
|
+
|
|
1246
|
+
INPUT:
|
|
1247
|
+
|
|
1248
|
+
- ``i`` -- an element of the index set
|
|
1249
|
+
|
|
1250
|
+
EXAMPLES::
|
|
1251
|
+
|
|
1252
|
+
sage: A = crystals.infinity.AlcovePaths(['E',7,1])
|
|
1253
|
+
sage: mg = A.highest_weight_vector()
|
|
1254
|
+
sage: mg.f_string([1,3,5,6,4,2,0,2,1,0,2,4,7,4,2])
|
|
1255
|
+
((alpha[2], -3), (alpha[5], -1), (alpha[1], -1),
|
|
1256
|
+
(alpha[0] + alpha[1], -2),
|
|
1257
|
+
(alpha[2] + alpha[4] + alpha[5], -2),
|
|
1258
|
+
(alpha[5] + alpha[6], -1), (alpha[1] + alpha[3], -1),
|
|
1259
|
+
(alpha[5] + alpha[6] + alpha[7], -1),
|
|
1260
|
+
(alpha[0] + alpha[1] + alpha[3], -1),
|
|
1261
|
+
(alpha[1] + alpha[3] + alpha[4] + alpha[5], -1))
|
|
1262
|
+
"""
|
|
1263
|
+
s = lambda rt: int(sum(rt.associated_coroot().coefficients()))
|
|
1264
|
+
y = self.projection().f(i)
|
|
1265
|
+
if y is not None:
|
|
1266
|
+
return type(self)(self.parent(),
|
|
1267
|
+
tuple([(rt.root, rt.height - self._shift*s(rt.root))
|
|
1268
|
+
for rt in y.value]),
|
|
1269
|
+
self._shift)
|
|
1270
|
+
|
|
1271
|
+
shift = self._shift + 1
|
|
1272
|
+
n = self.parent()._cartan_type.rank()
|
|
1273
|
+
A = CrystalOfAlcovePaths(self.parent()._cartan_type, [shift]*n)
|
|
1274
|
+
y = A(tuple([A._R(rt, h + shift*s(rt)) for rt, h in self.value])).f(i)
|
|
1275
|
+
return type(self)(self.parent(),
|
|
1276
|
+
tuple([(rt.root, rt.height - shift*s(rt.root))
|
|
1277
|
+
for rt in y.value]),
|
|
1278
|
+
shift)
|
|
1279
|
+
|
|
1280
|
+
def epsilon(self, i):
|
|
1281
|
+
r"""
|
|
1282
|
+
Return `\varepsilon_i` of ``self``.
|
|
1283
|
+
|
|
1284
|
+
INPUT:
|
|
1285
|
+
|
|
1286
|
+
- ``i`` -- an element of the index set
|
|
1287
|
+
|
|
1288
|
+
EXAMPLES::
|
|
1289
|
+
|
|
1290
|
+
sage: A = crystals.infinity.AlcovePaths(['A',7,2])
|
|
1291
|
+
sage: mg = A.highest_weight_vector()
|
|
1292
|
+
sage: x = mg.f_string([1,0,2,3,4,4,4,2,3,3,3])
|
|
1293
|
+
sage: [x.epsilon(i) for i in A.index_set()]
|
|
1294
|
+
[0, 0, 0, 3, 0]
|
|
1295
|
+
sage: x = mg.f_string([2,2,1,1,0,1,0,2,3,3,3,4])
|
|
1296
|
+
sage: [x.epsilon(i) for i in A.index_set()]
|
|
1297
|
+
[1, 2, 0, 1, 1]
|
|
1298
|
+
"""
|
|
1299
|
+
return self.projection().epsilon(i)
|
|
1300
|
+
|
|
1301
|
+
def phi(self, i):
|
|
1302
|
+
r"""
|
|
1303
|
+
Return `\varphi_i` of ``self``.
|
|
1304
|
+
|
|
1305
|
+
Let `A \in \mathcal{B}(\infty)` Define `\varphi_i(A) :=
|
|
1306
|
+
\varepsilon_i(A) + \langle h_i, \mathrm{wt}(A) \rangle`,
|
|
1307
|
+
where `h_i` is the `i`-th simple coroot and `\mathrm{wt}(A)`
|
|
1308
|
+
is the :meth:`weight` of `A`.
|
|
1309
|
+
|
|
1310
|
+
INPUT:
|
|
1311
|
+
|
|
1312
|
+
- ``i`` -- an element of the index set
|
|
1313
|
+
|
|
1314
|
+
EXAMPLES::
|
|
1315
|
+
|
|
1316
|
+
sage: A = crystals.infinity.AlcovePaths(['A',8,2])
|
|
1317
|
+
sage: mg = A.highest_weight_vector()
|
|
1318
|
+
sage: x = mg.f_string([1,0,2,3,4,4,4,2,3,3,3])
|
|
1319
|
+
sage: [x.phi(i) for i in A.index_set()]
|
|
1320
|
+
[1, 1, 1, 3, -2]
|
|
1321
|
+
sage: x = mg.f_string([2,2,1,1,0,1,0,2,3,3,3,4])
|
|
1322
|
+
sage: [x.phi(i) for i in A.index_set()]
|
|
1323
|
+
[4, -1, 0, 0, 2]
|
|
1324
|
+
"""
|
|
1325
|
+
P = self.parent().weight_lattice_realization()
|
|
1326
|
+
h = P.simple_coroots()
|
|
1327
|
+
return self.epsilon(i) + P(self.weight()).scalar(h[i])
|
|
1328
|
+
|
|
1329
|
+
def weight(self):
|
|
1330
|
+
"""
|
|
1331
|
+
Return the weight of ``self``.
|
|
1332
|
+
|
|
1333
|
+
EXAMPLES::
|
|
1334
|
+
|
|
1335
|
+
sage: A = crystals.infinity.AlcovePaths(['E',6])
|
|
1336
|
+
sage: mg = A.highest_weight_vector()
|
|
1337
|
+
sage: fstr = [1,3,4,2,1,2,3,6,5,3,2,6,2]
|
|
1338
|
+
sage: x = mg.f_string(fstr)
|
|
1339
|
+
sage: al = A.weight_lattice_realization().simple_roots()
|
|
1340
|
+
sage: x.weight() == -sum(al[i]*fstr.count(i) for i in A.index_set())
|
|
1341
|
+
True
|
|
1342
|
+
"""
|
|
1343
|
+
P = self.parent().weight_lattice_realization()
|
|
1344
|
+
y = self.projection()
|
|
1345
|
+
return y.weight() - self._shift * P.rho()
|
|
1346
|
+
|
|
1347
|
+
def projection(self, k=None):
|
|
1348
|
+
r"""
|
|
1349
|
+
Return the projection ``self`` onto `B(k \rho)`.
|
|
1350
|
+
|
|
1351
|
+
INPUT:
|
|
1352
|
+
|
|
1353
|
+
- ``k`` -- (optional) if not given, defaults to the smallest
|
|
1354
|
+
value such that ``self`` is not ``None`` under the projection
|
|
1355
|
+
|
|
1356
|
+
EXAMPLES::
|
|
1357
|
+
|
|
1358
|
+
sage: A = crystals.infinity.AlcovePaths(['G',2])
|
|
1359
|
+
sage: mg = A.highest_weight_vector()
|
|
1360
|
+
sage: x = mg.f_string([2,1,1,2,2,2,1,1]); x
|
|
1361
|
+
((alpha[2], -3), (alpha[1] + alpha[2], -3),
|
|
1362
|
+
(3*alpha[1] + 2*alpha[2], -1), (2*alpha[1] + alpha[2], -1))
|
|
1363
|
+
sage: x.projection()
|
|
1364
|
+
((alpha[2], 0), (alpha[1] + alpha[2], 9),
|
|
1365
|
+
(3*alpha[1] + 2*alpha[2], 8), (2*alpha[1] + alpha[2], 14))
|
|
1366
|
+
sage: x.projection().parent()
|
|
1367
|
+
Highest weight crystal of alcove paths of type ['G', 2]
|
|
1368
|
+
and weight 3*Lambda[1] + 3*Lambda[2]
|
|
1369
|
+
|
|
1370
|
+
sage: mg.projection().parent()
|
|
1371
|
+
Highest weight crystal of alcove paths of type ['G', 2]
|
|
1372
|
+
and weight 0
|
|
1373
|
+
sage: mg.f(1).projection().parent()
|
|
1374
|
+
Highest weight crystal of alcove paths of type ['G', 2]
|
|
1375
|
+
and weight Lambda[1] + Lambda[2]
|
|
1376
|
+
sage: mg.f(1).f(2).projection().parent()
|
|
1377
|
+
Highest weight crystal of alcove paths of type ['G', 2]
|
|
1378
|
+
and weight Lambda[1] + Lambda[2]
|
|
1379
|
+
sage: b = mg.f_string([1,2,2,1,2])
|
|
1380
|
+
sage: b.projection().parent()
|
|
1381
|
+
Highest weight crystal of alcove paths of type ['G', 2]
|
|
1382
|
+
and weight 2*Lambda[1] + 2*Lambda[2]
|
|
1383
|
+
sage: b.projection(3).parent()
|
|
1384
|
+
Highest weight crystal of alcove paths of type ['G', 2]
|
|
1385
|
+
and weight 3*Lambda[1] + 3*Lambda[2]
|
|
1386
|
+
sage: b.projection(1)
|
|
1387
|
+
"""
|
|
1388
|
+
if k is None:
|
|
1389
|
+
k = self._shift
|
|
1390
|
+
elif k < self._shift:
|
|
1391
|
+
return None
|
|
1392
|
+
s = lambda rt: int(sum(rt.associated_coroot().coefficients()))
|
|
1393
|
+
n = self.parent()._cartan_type.rank()
|
|
1394
|
+
A = CrystalOfAlcovePaths(self.parent()._cartan_type, [k] * n)
|
|
1395
|
+
return A(tuple([A._R(rt, h + k*s(rt)) for rt, h in self.value]))
|
|
1396
|
+
|
|
1397
|
+
|
|
1398
|
+
class RootsWithHeight(UniqueRepresentation, Parent):
|
|
1399
|
+
r"""
|
|
1400
|
+
Data structure of the ordered pairs `(\beta,k)`,
|
|
1401
|
+
where `\beta` is a positive root and `k` is a nonnegative integer. A total
|
|
1402
|
+
order is implemented on this set, and depends on the weight.
|
|
1403
|
+
|
|
1404
|
+
INPUT:
|
|
1405
|
+
|
|
1406
|
+
- ``cartan_type`` -- Cartan type of a finite or affine untwisted root
|
|
1407
|
+
system
|
|
1408
|
+
|
|
1409
|
+
- ``weight`` -- dominant weight as a list of (integral) coefficients of
|
|
1410
|
+
the fundamental weights
|
|
1411
|
+
|
|
1412
|
+
EXAMPLES::
|
|
1413
|
+
|
|
1414
|
+
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
|
|
1415
|
+
sage: R = RootsWithHeight(['A',2],[1,1]); R
|
|
1416
|
+
Roots with height of Cartan type ['A', 2] and dominant weight Lambda[1] + Lambda[2]
|
|
1417
|
+
|
|
1418
|
+
sage: r1 = R._root_lattice.from_vector(vector([1,0])); r1
|
|
1419
|
+
alpha[1]
|
|
1420
|
+
sage: r2 = R._root_lattice.from_vector(vector([1,1])); r2
|
|
1421
|
+
alpha[1] + alpha[2]
|
|
1422
|
+
|
|
1423
|
+
sage: x = R(r1,0); x
|
|
1424
|
+
(alpha[1], 0)
|
|
1425
|
+
sage: y = R(r2,1); y
|
|
1426
|
+
(alpha[1] + alpha[2], 1)
|
|
1427
|
+
sage: x < y
|
|
1428
|
+
True
|
|
1429
|
+
"""
|
|
1430
|
+
|
|
1431
|
+
@staticmethod
|
|
1432
|
+
def __classcall_private__(cls, starting_weight, cartan_type=None):
|
|
1433
|
+
"""
|
|
1434
|
+
Classcall to mend the input.
|
|
1435
|
+
|
|
1436
|
+
Internally, the RootsWithHeight code works with a ``starting_weight`` that
|
|
1437
|
+
is in the ``weight_space`` associated to the crystal. The user can, however,
|
|
1438
|
+
also input a ``cartan_type`` and the coefficients of the fundamental weights
|
|
1439
|
+
as ``starting_weight``. This code transforms the input into the right
|
|
1440
|
+
format (also necessary for UniqueRepresentation).
|
|
1441
|
+
|
|
1442
|
+
TESTS::
|
|
1443
|
+
|
|
1444
|
+
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
|
|
1445
|
+
sage: R = RootsWithHeight(['A',2],[3,2])
|
|
1446
|
+
sage: S = RootsWithHeight(CartanType(['A',2]), (3,2))
|
|
1447
|
+
sage: R is S
|
|
1448
|
+
True
|
|
1449
|
+
|
|
1450
|
+
sage: R = RootSystem(['B',2,1])
|
|
1451
|
+
sage: La = R.weight_space().basis()
|
|
1452
|
+
sage: C = RootsWithHeight(['B',2,1],[0,0,1])
|
|
1453
|
+
sage: B = RootsWithHeight(La[2])
|
|
1454
|
+
sage: B is C
|
|
1455
|
+
True
|
|
1456
|
+
"""
|
|
1457
|
+
if cartan_type is not None:
|
|
1458
|
+
cartan_type, starting_weight = CartanType(starting_weight), cartan_type
|
|
1459
|
+
|
|
1460
|
+
R = RootSystem(cartan_type)
|
|
1461
|
+
P = R.weight_space()
|
|
1462
|
+
Lambda = P.basis()
|
|
1463
|
+
offset = R.index_set()[Integer(0)]
|
|
1464
|
+
starting_weight = P.sum(starting_weight[j-offset]*Lambda[j] for j in R.index_set())
|
|
1465
|
+
|
|
1466
|
+
return super().__classcall__(cls, starting_weight)
|
|
1467
|
+
|
|
1468
|
+
def __init__(self, weight):
|
|
1469
|
+
r"""
|
|
1470
|
+
Initialize ``self``.
|
|
1471
|
+
|
|
1472
|
+
EXAMPLES::
|
|
1473
|
+
|
|
1474
|
+
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
|
|
1475
|
+
sage: R = RootsWithHeight(['A',2],[3,2])
|
|
1476
|
+
sage: TestSuite(R).run()
|
|
1477
|
+
"""
|
|
1478
|
+
Parent.__init__(self, category=Sets())
|
|
1479
|
+
|
|
1480
|
+
cartan_type = weight.parent().cartan_type()
|
|
1481
|
+
self._cartan_type = cartan_type
|
|
1482
|
+
self._root_system = RootSystem(cartan_type)
|
|
1483
|
+
self._root_lattice = self._root_system.root_lattice()
|
|
1484
|
+
self._weight_lattice = self._root_system.weight_lattice()
|
|
1485
|
+
self.weight = weight
|
|
1486
|
+
|
|
1487
|
+
def _repr_(self):
|
|
1488
|
+
"""
|
|
1489
|
+
Return a string representation of ``self``.
|
|
1490
|
+
|
|
1491
|
+
EXAMPLES::
|
|
1492
|
+
|
|
1493
|
+
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
|
|
1494
|
+
sage: RootsWithHeight(['A',2],[3,2])
|
|
1495
|
+
Roots with height of Cartan type ['A', 2] and dominant weight 3*Lambda[1] + 2*Lambda[2]
|
|
1496
|
+
"""
|
|
1497
|
+
return "Roots with height of Cartan type %s and dominant weight %s" % (
|
|
1498
|
+
self._root_system.cartan_type(), self.weight)
|
|
1499
|
+
|
|
1500
|
+
def _max_height(self, root):
|
|
1501
|
+
r"""
|
|
1502
|
+
If root is `\beta`, return `k = \langle \lambda, \beta^{\vee} \rangle`.
|
|
1503
|
+
|
|
1504
|
+
Only ordered pairs of the form `(\beta, l)` for `0 \leq l < k` are
|
|
1505
|
+
allowed.
|
|
1506
|
+
|
|
1507
|
+
EXAMPLES::
|
|
1508
|
+
|
|
1509
|
+
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
|
|
1510
|
+
sage: C = RootsWithHeight(['A',3],[3,2,0])
|
|
1511
|
+
sage: x = C._root_lattice.from_vector(vector([1,1])); x
|
|
1512
|
+
alpha[1] + alpha[2]
|
|
1513
|
+
sage: C._max_height(x)
|
|
1514
|
+
5
|
|
1515
|
+
"""
|
|
1516
|
+
return self.weight.scalar(root.associated_coroot())
|
|
1517
|
+
|
|
1518
|
+
@cached_method
|
|
1519
|
+
def word(self):
|
|
1520
|
+
r"""
|
|
1521
|
+
Give the initial alcove path (`\lambda`-chain) in terms of simple
|
|
1522
|
+
roots. Used for plotting the path.
|
|
1523
|
+
|
|
1524
|
+
.. NOTE::
|
|
1525
|
+
|
|
1526
|
+
Currently only implemented for finite Cartan types.
|
|
1527
|
+
|
|
1528
|
+
EXAMPLES::
|
|
1529
|
+
|
|
1530
|
+
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
|
|
1531
|
+
sage: R = RootsWithHeight(['A',2],[3,2])
|
|
1532
|
+
sage: R.word()
|
|
1533
|
+
[2, 1, 2, 0, 1, 2, 1, 0, 1, 2]
|
|
1534
|
+
"""
|
|
1535
|
+
cartan_type = self._root_system.cartan_type()
|
|
1536
|
+
if not cartan_type.is_finite():
|
|
1537
|
+
raise NotImplementedError
|
|
1538
|
+
lambda_chain = [x.root for x in self.lambda_chain()]
|
|
1539
|
+
|
|
1540
|
+
coroot_lattice = RootSystem(cartan_type).coroot_lattice()
|
|
1541
|
+
cohighest_root = coroot_lattice.highest_root()
|
|
1542
|
+
|
|
1543
|
+
word = []
|
|
1544
|
+
for i in range(len(lambda_chain)):
|
|
1545
|
+
beta = lambda_chain[i]
|
|
1546
|
+
for j in reversed(range(i)):
|
|
1547
|
+
beta = beta.reflection(lambda_chain[j])
|
|
1548
|
+
# beta is now a simple root or the highest root
|
|
1549
|
+
|
|
1550
|
+
coroot = beta.associated_coroot()
|
|
1551
|
+
support = coroot.support() # the path is in dual affine space
|
|
1552
|
+
if len(support) == 1: # beta is a simple root
|
|
1553
|
+
word.append(support[0])
|
|
1554
|
+
elif coroot == -cohighest_root:
|
|
1555
|
+
word.append(0)
|
|
1556
|
+
else:
|
|
1557
|
+
assert False, 'should never get here'
|
|
1558
|
+
|
|
1559
|
+
return word
|
|
1560
|
+
|
|
1561
|
+
@cached_method
|
|
1562
|
+
def lambda_chain(self):
|
|
1563
|
+
r"""
|
|
1564
|
+
Return the unfolded `\lambda`-chain.
|
|
1565
|
+
|
|
1566
|
+
.. NOTE:: Only works in root systems of finite type.
|
|
1567
|
+
|
|
1568
|
+
EXAMPLES::
|
|
1569
|
+
|
|
1570
|
+
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
|
|
1571
|
+
sage: R = RootsWithHeight(['A',2],[1,1]); R
|
|
1572
|
+
Roots with height of Cartan type ['A', 2] and dominant weight Lambda[1] + Lambda[2]
|
|
1573
|
+
sage: R.lambda_chain()
|
|
1574
|
+
[(alpha[2], 0), (alpha[1] + alpha[2], 0), (alpha[1], 0), (alpha[1] + alpha[2], 1)]
|
|
1575
|
+
"""
|
|
1576
|
+
if not self._root_lattice.cartan_type().is_finite():
|
|
1577
|
+
raise ValueError("Cartan type {0} is not finite".format(self._root_lattice.cartan_type()))
|
|
1578
|
+
|
|
1579
|
+
l = (self(i, j) for i in self._root_lattice.positive_roots()
|
|
1580
|
+
for j in range(self._max_height(i)))
|
|
1581
|
+
|
|
1582
|
+
return sorted(l)
|
|
1583
|
+
|
|
1584
|
+
def _element_constructor_(self, root, height):
|
|
1585
|
+
r"""
|
|
1586
|
+
Construct a :class:`RootsWithHeightElement` with ``self`` as the parent.
|
|
1587
|
+
|
|
1588
|
+
EXAMPLES::
|
|
1589
|
+
|
|
1590
|
+
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
|
|
1591
|
+
sage: rl = RootSystem(['A',2]).root_lattice()
|
|
1592
|
+
sage: x = rl.from_vector(vector([1,1])); x
|
|
1593
|
+
alpha[1] + alpha[2]
|
|
1594
|
+
sage: R = RootsWithHeight(['A',2],[1,1]); R
|
|
1595
|
+
Roots with height of Cartan type ['A', 2] and dominant weight Lambda[1] + Lambda[2]
|
|
1596
|
+
sage: y = R(x,1); y
|
|
1597
|
+
(alpha[1] + alpha[2], 1)
|
|
1598
|
+
"""
|
|
1599
|
+
root = self._root_lattice.from_vector(vector(root))
|
|
1600
|
+
return self.element_class(self, root, height)
|
|
1601
|
+
|
|
1602
|
+
def _an_element_(self):
|
|
1603
|
+
r"""
|
|
1604
|
+
|
|
1605
|
+
EXAMPLES::
|
|
1606
|
+
|
|
1607
|
+
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
|
|
1608
|
+
sage: R = RootsWithHeight(['A',2],[3,2])
|
|
1609
|
+
sage: R._an_element_()
|
|
1610
|
+
(alpha[1], 0)
|
|
1611
|
+
"""
|
|
1612
|
+
return self(self._root_lattice.from_vector(vector([1])), 0)
|
|
1613
|
+
|
|
1614
|
+
|
|
1615
|
+
class RootsWithHeightElement(Element):
|
|
1616
|
+
r"""
|
|
1617
|
+
Element of :class:`RootsWithHeight`.
|
|
1618
|
+
|
|
1619
|
+
INPUT:
|
|
1620
|
+
|
|
1621
|
+
- ``root`` -- a positive root `\beta` in our root system
|
|
1622
|
+
- ``height`` -- integer such that
|
|
1623
|
+
`0 \leq l \leq \langle \lambda, \beta^{\vee} \rangle`
|
|
1624
|
+
|
|
1625
|
+
EXAMPLES::
|
|
1626
|
+
|
|
1627
|
+
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
|
|
1628
|
+
sage: rl = RootSystem(['A',2]).root_lattice()
|
|
1629
|
+
sage: x = rl.from_vector(vector([1,1])); x
|
|
1630
|
+
alpha[1] + alpha[2]
|
|
1631
|
+
sage: R = RootsWithHeight(['A',2],[1,1]); R
|
|
1632
|
+
Roots with height of Cartan type ['A', 2] and dominant weight Lambda[1] + Lambda[2]
|
|
1633
|
+
sage: y = R(x, 1); y
|
|
1634
|
+
(alpha[1] + alpha[2], 1)
|
|
1635
|
+
"""
|
|
1636
|
+
|
|
1637
|
+
def __init__(self, parent, root, height):
|
|
1638
|
+
r"""
|
|
1639
|
+
Initialize ``self``.
|
|
1640
|
+
|
|
1641
|
+
EXAMPLES::
|
|
1642
|
+
|
|
1643
|
+
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
|
|
1644
|
+
sage: rl = RootSystem(['A',2]).root_lattice()
|
|
1645
|
+
sage: x = rl.from_vector(vector([1,1]))
|
|
1646
|
+
sage: R = RootsWithHeight(['A',2],[3,2])
|
|
1647
|
+
sage: y = R(x, 1); y
|
|
1648
|
+
(alpha[1] + alpha[2], 1)
|
|
1649
|
+
sage: TestSuite(x).run()
|
|
1650
|
+
"""
|
|
1651
|
+
Element.__init__(self, parent)
|
|
1652
|
+
max_height = parent._max_height(root)
|
|
1653
|
+
|
|
1654
|
+
# make sure the height is in the right range, this also catches negative
|
|
1655
|
+
# roots
|
|
1656
|
+
|
|
1657
|
+
if not 0 <= height < max_height:
|
|
1658
|
+
raise ValueError("%d out of allowed range [%d,%d)" % (height, 0, max_height))
|
|
1659
|
+
|
|
1660
|
+
v = [height / max_height]
|
|
1661
|
+
v.extend(x / max_height
|
|
1662
|
+
for x in root.associated_coroot().to_vector())
|
|
1663
|
+
# v.insert(0, height/max_height)
|
|
1664
|
+
|
|
1665
|
+
# the map from (root, height) --> _cmp_v is injective
|
|
1666
|
+
|
|
1667
|
+
self._cmp_v = tuple(v)
|
|
1668
|
+
self.root = root
|
|
1669
|
+
self.height = height
|
|
1670
|
+
|
|
1671
|
+
def _repr_(self):
|
|
1672
|
+
r"""
|
|
1673
|
+
Return a string representation of ``self``.
|
|
1674
|
+
|
|
1675
|
+
EXAMPLES::
|
|
1676
|
+
|
|
1677
|
+
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
|
|
1678
|
+
sage: R = RootsWithHeight(['A',2],[3,2])
|
|
1679
|
+
sage: rl = RootSystem(['A',2]).root_lattice()
|
|
1680
|
+
sage: vec = rl.from_vector(vector([1,1])); vec
|
|
1681
|
+
alpha[1] + alpha[2]
|
|
1682
|
+
sage: R(vec,1)
|
|
1683
|
+
(alpha[1] + alpha[2], 1)
|
|
1684
|
+
"""
|
|
1685
|
+
return "(%s, %s)" % (self.root, self.height)
|
|
1686
|
+
|
|
1687
|
+
def __hash__(self):
|
|
1688
|
+
r"""
|
|
1689
|
+
|
|
1690
|
+
EXAMPLES::
|
|
1691
|
+
|
|
1692
|
+
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
|
|
1693
|
+
sage: R = RootsWithHeight(['A',2],[3,2])
|
|
1694
|
+
sage: rl = RootSystem(['A',2]).root_lattice()
|
|
1695
|
+
sage: root = rl.from_vector(vector([1,1]))
|
|
1696
|
+
sage: vec = R(root,0)
|
|
1697
|
+
sage: hash(vec) == hash(vec)
|
|
1698
|
+
True
|
|
1699
|
+
"""
|
|
1700
|
+
return hash(self._cmp_v)
|
|
1701
|
+
|
|
1702
|
+
def __eq__(self, other):
|
|
1703
|
+
r"""
|
|
1704
|
+
|
|
1705
|
+
EXAMPLES::
|
|
1706
|
+
|
|
1707
|
+
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
|
|
1708
|
+
sage: R = RootsWithHeight(['A',2],[3,2])
|
|
1709
|
+
sage: rl = RootSystem(['A',2]).root_lattice()
|
|
1710
|
+
sage: v1 = rl.from_vector(vector([1,1]))
|
|
1711
|
+
sage: v2 = rl.from_vector(vector([1]))
|
|
1712
|
+
sage: x1 = R(v1,1) ; x2 = R(v1,0) ; x3 = R(v2,1)
|
|
1713
|
+
sage: x1.__eq__(x1)
|
|
1714
|
+
True
|
|
1715
|
+
sage: x1.__eq__(x2)
|
|
1716
|
+
False
|
|
1717
|
+
sage: x1.__eq__(x3)
|
|
1718
|
+
False
|
|
1719
|
+
"""
|
|
1720
|
+
try:
|
|
1721
|
+
return self._cmp_v == other._cmp_v
|
|
1722
|
+
except (NameError, AttributeError):
|
|
1723
|
+
return False
|
|
1724
|
+
|
|
1725
|
+
def _richcmp_(self, other, op):
|
|
1726
|
+
r"""
|
|
1727
|
+
Define a total order on :class:`RootsWithHeightElement`. This defines
|
|
1728
|
+
the initial `\lambda`-chain.
|
|
1729
|
+
|
|
1730
|
+
EXAMPLES::
|
|
1731
|
+
|
|
1732
|
+
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight
|
|
1733
|
+
sage: R = RootsWithHeight(['A',2],[3,2])
|
|
1734
|
+
sage: rl = RootSystem(['A',2]).root_lattice()
|
|
1735
|
+
sage: v1 = rl.from_vector(vector([1,1]))
|
|
1736
|
+
sage: v2 = rl.from_vector(vector([1]))
|
|
1737
|
+
sage: x1 = R(v1,1) ; x2 = R(v1,0) ; x3 = R(v2,1)
|
|
1738
|
+
sage: x1 < x2
|
|
1739
|
+
False
|
|
1740
|
+
sage: x1 < x3
|
|
1741
|
+
True
|
|
1742
|
+
"""
|
|
1743
|
+
# I suspect that if you redefine this method to produce a
|
|
1744
|
+
# different (valid) `\lambda`-chain the rest of the
|
|
1745
|
+
# code should still work.
|
|
1746
|
+
# todo: check if self and other have the same parent ?
|
|
1747
|
+
# assert self.parent() is other.parent(), "elements have different parents"
|
|
1748
|
+
return richcmp(self._cmp_v, other._cmp_v, op)
|
|
1749
|
+
|
|
1750
|
+
|
|
1751
|
+
RootsWithHeight.Element = RootsWithHeightElement
|
|
1752
|
+
|
|
1753
|
+
#####################################################################
|
|
1754
|
+
# Test code, by comparing with existing crystal implementations.
|
|
1755
|
+
#####################################################################
|
|
1756
|
+
|
|
1757
|
+
|
|
1758
|
+
def _test_some_specific_examples(clss=CrystalOfAlcovePaths):
|
|
1759
|
+
r"""
|
|
1760
|
+
Test against some specific (finite type) examples.
|
|
1761
|
+
|
|
1762
|
+
EXAMPLES::
|
|
1763
|
+
|
|
1764
|
+
sage: from sage.combinat.crystals.alcove_path import _test_some_specific_examples
|
|
1765
|
+
sage: _test_some_specific_examples(crystals.AlcovePaths)
|
|
1766
|
+
G2 example passed.
|
|
1767
|
+
C3 example passed.
|
|
1768
|
+
B3 example 1 passed.
|
|
1769
|
+
B3 example 2 passed.
|
|
1770
|
+
True
|
|
1771
|
+
"""
|
|
1772
|
+
# This appears in Lenart.
|
|
1773
|
+
C = clss(['G', 2], [0, 1])
|
|
1774
|
+
G = C.digraph()
|
|
1775
|
+
|
|
1776
|
+
GT = DiGraph({
|
|
1777
|
+
(): {(0): 2},
|
|
1778
|
+
(0): {(0, 8): 1},
|
|
1779
|
+
(0, 1): {(0, 1, 7): 2},
|
|
1780
|
+
(0, 1, 2): {(0, 1, 2, 9): 1},
|
|
1781
|
+
(0, 1, 2, 3): {(0, 1, 2, 3, 4): 2},
|
|
1782
|
+
(0, 1, 2, 6): {(0, 1, 2, 3): 1},
|
|
1783
|
+
(0, 1, 2, 9): {(0, 1, 2, 6): 1},
|
|
1784
|
+
(0, 1, 7): {(0, 1, 2): 2},
|
|
1785
|
+
(0, 1, 7, 9): {(0, 1, 2, 9): 2},
|
|
1786
|
+
(0, 5): {(0, 1): 1, (0, 5, 7): 2},
|
|
1787
|
+
(0, 5, 7): {(0, 5, 7, 9): 1},
|
|
1788
|
+
(0, 5, 7, 9): {(0, 1, 7, 9): 1},
|
|
1789
|
+
(0, 8): {(0, 5): 1}
|
|
1790
|
+
})
|
|
1791
|
+
|
|
1792
|
+
if not G.is_isomorphic(GT):
|
|
1793
|
+
return False
|
|
1794
|
+
else:
|
|
1795
|
+
print("G2 example passed.")
|
|
1796
|
+
|
|
1797
|
+
# Some examples from Hong--Kang:
|
|
1798
|
+
|
|
1799
|
+
# type C, ex. 8.3.5, pg. 189
|
|
1800
|
+
C = clss(['C', 3], [0, 0, 1])
|
|
1801
|
+
G = C.digraph()
|
|
1802
|
+
GT = DiGraph({
|
|
1803
|
+
(): {(0): 3},
|
|
1804
|
+
(0): {(0, 6): 2},
|
|
1805
|
+
(0, 1): {(0, 1, 3): 3, (0, 1, 7): 1},
|
|
1806
|
+
(0, 1, 2): {(0, 1, 2, 3): 3},
|
|
1807
|
+
(0, 1, 2, 3): {(0, 1, 2, 3, 8): 2},
|
|
1808
|
+
(0, 1, 2, 3, 4): {(0, 1, 2, 3, 4, 5): 3},
|
|
1809
|
+
(0, 1, 2, 3, 8): {(0, 1, 2, 3, 4): 2},
|
|
1810
|
+
(0, 1, 3): {(0, 1, 3, 7): 1},
|
|
1811
|
+
(0, 1, 3, 7): {(0, 1, 2, 3): 1, (0, 1, 3, 7, 8): 2},
|
|
1812
|
+
(0, 1, 3, 7, 8): {(0, 1, 2, 3, 8): 1},
|
|
1813
|
+
(0, 1, 7): {(0, 1, 2): 1, (0, 1, 3, 7): 3},
|
|
1814
|
+
(0, 6): {(0, 1): 2, (0, 6, 7): 1},
|
|
1815
|
+
(0, 6, 7): {(0, 1, 7): 2}
|
|
1816
|
+
})
|
|
1817
|
+
|
|
1818
|
+
if not G.is_isomorphic(GT):
|
|
1819
|
+
return False
|
|
1820
|
+
else:
|
|
1821
|
+
print("C3 example passed.")
|
|
1822
|
+
|
|
1823
|
+
# type B, fig. 8.1 pg. 172
|
|
1824
|
+
C = clss(['B', 3], [2, 0, 0])
|
|
1825
|
+
G = C.digraph()
|
|
1826
|
+
|
|
1827
|
+
GT = DiGraph({
|
|
1828
|
+
(): {(6): 1},
|
|
1829
|
+
(0): {(0, 7): 2},
|
|
1830
|
+
(0, 1): {(0, 1, 11): 3},
|
|
1831
|
+
(0, 1, 2): {(0, 1, 2, 9): 2},
|
|
1832
|
+
(0, 1, 2, 3): {(0, 1, 2, 3, 10): 1},
|
|
1833
|
+
(0, 1, 2, 3, 10): {(0, 1, 2, 3, 4): 1},
|
|
1834
|
+
(0, 1, 2, 9): {(0, 1, 2, 3): 2, (0, 1, 2, 9, 10): 1},
|
|
1835
|
+
(0, 1, 2, 9, 10): {(0, 1, 2, 3, 10): 2},
|
|
1836
|
+
(0, 1, 5): {(0, 1, 2): 3, (0, 1, 5, 9): 2},
|
|
1837
|
+
(0, 1, 5, 9): {(0, 1, 2, 9): 3, (0, 1, 5, 9, 10): 1},
|
|
1838
|
+
(0, 1, 5, 9, 10): {(0, 1, 2, 9, 10): 3},
|
|
1839
|
+
(0, 1, 8): {(0, 1, 5): 3},
|
|
1840
|
+
(0, 1, 8, 9): {(0, 1, 5, 9): 3, (0, 1, 8, 9, 10): 1},
|
|
1841
|
+
(0, 1, 8, 9, 10): {(0, 1, 5, 9, 10): 3},
|
|
1842
|
+
(0, 1, 11): {(0, 1, 8): 3},
|
|
1843
|
+
(0, 7): {(0, 1): 2, (0, 7, 11): 3},
|
|
1844
|
+
(0, 7, 8): {(0, 7, 8, 9): 2},
|
|
1845
|
+
(0, 7, 8, 9): {(0, 1, 8, 9): 2},
|
|
1846
|
+
(0, 7, 8, 9, 10): {(0, 1, 8, 9, 10): 2},
|
|
1847
|
+
(0, 7, 11): {(0, 1, 11): 2, (0, 7, 8): 3},
|
|
1848
|
+
(6): {(0): 1, (6, 7): 2},
|
|
1849
|
+
(6, 7): {(0, 7): 1, (6, 7, 11): 3},
|
|
1850
|
+
(6, 7, 8): {(0, 7, 8): 1, (6, 7, 8, 9): 2},
|
|
1851
|
+
(6, 7, 8, 9): {(6, 7, 8, 9, 10): 1},
|
|
1852
|
+
(6, 7, 8, 9, 10): {(0, 7, 8, 9, 10): 1},
|
|
1853
|
+
(6, 7, 11): {(0, 7, 11): 1, (6, 7, 8): 3}
|
|
1854
|
+
})
|
|
1855
|
+
|
|
1856
|
+
if not G.is_isomorphic(GT):
|
|
1857
|
+
return False
|
|
1858
|
+
else:
|
|
1859
|
+
print("B3 example 1 passed.")
|
|
1860
|
+
|
|
1861
|
+
C = clss(['B', 3], [0, 1, 0])
|
|
1862
|
+
G = C.digraph()
|
|
1863
|
+
|
|
1864
|
+
GT = DiGraph({
|
|
1865
|
+
(): {(0): 2},
|
|
1866
|
+
(0): {(0, 1): 1, (0, 7): 3},
|
|
1867
|
+
(0, 1): {(0, 1, 7): 3},
|
|
1868
|
+
(0, 1, 2): {(0, 1, 2, 8): 2},
|
|
1869
|
+
(0, 1, 2, 3): {(0, 1, 2, 3, 5): 1, (0, 1, 2, 3, 9): 3},
|
|
1870
|
+
(0, 1, 2, 3, 4): {(0, 1, 2, 3, 4, 5): 1},
|
|
1871
|
+
(0, 1, 2, 3, 4, 5): {(0, 1, 2, 3, 4, 5, 6): 2},
|
|
1872
|
+
(0, 1, 2, 3, 5): {(0, 1, 2, 3, 5, 9): 3},
|
|
1873
|
+
(0, 1, 2, 3, 5, 9): {(0, 1, 2, 3, 4, 5): 3},
|
|
1874
|
+
(0, 1, 2, 3, 9): {(0, 1, 2, 3, 4): 3, (0, 1, 2, 3, 5, 9): 1},
|
|
1875
|
+
(0, 1, 2, 5): {(0, 1, 2, 3, 5): 2},
|
|
1876
|
+
(0, 1, 2, 8): {(0, 1, 2, 3): 2},
|
|
1877
|
+
(0, 1, 2, 8, 9): {(0, 1, 2, 3, 9): 2},
|
|
1878
|
+
(0, 1, 7): {(0, 1, 2): 3, (0, 1, 7, 8): 2},
|
|
1879
|
+
(0, 1, 7, 8): {(0, 1, 7, 8, 9): 3},
|
|
1880
|
+
(0, 1, 7, 8, 9): {(0, 1, 2, 8, 9): 3},
|
|
1881
|
+
(0, 2): {(0, 1, 2): 1, (0, 2, 5): 2},
|
|
1882
|
+
(0, 2, 5): {(0, 2, 5, 8): 1},
|
|
1883
|
+
(0, 2, 5, 8): {(0, 1, 2, 5): 1},
|
|
1884
|
+
(0, 7): {(0, 1, 7): 1, (0, 2): 3}
|
|
1885
|
+
})
|
|
1886
|
+
|
|
1887
|
+
if not G.is_isomorphic(GT):
|
|
1888
|
+
return False
|
|
1889
|
+
else:
|
|
1890
|
+
print("B3 example 2 passed.")
|
|
1891
|
+
|
|
1892
|
+
# type B, fig. 8.3 pg. 174
|
|
1893
|
+
|
|
1894
|
+
return True
|
|
1895
|
+
|
|
1896
|
+
|
|
1897
|
+
def compare_graphs(g1, g2, node1, node2):
|
|
1898
|
+
r"""
|
|
1899
|
+
Compare two edge-labeled :class:`graphs <DiGraph>` obtained from
|
|
1900
|
+
``Crystal.digraph()``, starting from the root nodes of each graph.
|
|
1901
|
+
|
|
1902
|
+
- ``g1`` -- :class:`graphs <DiGraph>`, first digraph
|
|
1903
|
+
- ``g2`` -- :class:`graphs <DiGraph>`, second digraph
|
|
1904
|
+
- ``node1`` -- element of ``g1``
|
|
1905
|
+
- ``node2`` -- element of ``g2``
|
|
1906
|
+
|
|
1907
|
+
Traverse ``g1`` starting at ``node1`` and compare this graph with
|
|
1908
|
+
the one obtained by traversing ``g2`` starting with ``node2``.
|
|
1909
|
+
If the graphs match (including labels) then return ``True``.
|
|
1910
|
+
Return ``False`` otherwise.
|
|
1911
|
+
|
|
1912
|
+
EXAMPLES::
|
|
1913
|
+
|
|
1914
|
+
sage: from sage.combinat.crystals.alcove_path import compare_graphs
|
|
1915
|
+
sage: G1 = crystals.Tableaux(['A',3], shape=[1,1]).digraph()
|
|
1916
|
+
sage: C = crystals.AlcovePaths(['A',3],[0,1,0])
|
|
1917
|
+
sage: G2 = C.digraph()
|
|
1918
|
+
sage: compare_graphs(G1, G2, C( () ), G2.vertices(sort=True)[0])
|
|
1919
|
+
True
|
|
1920
|
+
"""
|
|
1921
|
+
for out_edge in g1.outgoing_edges(node1):
|
|
1922
|
+
matched = False
|
|
1923
|
+
for o2 in g2.outgoing_edges(node2):
|
|
1924
|
+
if o2[2] == out_edge[2]:
|
|
1925
|
+
if matched:
|
|
1926
|
+
print("ERROR: Two edges with the same label for ", out_edge, " exist.")
|
|
1927
|
+
return False
|
|
1928
|
+
matched = True
|
|
1929
|
+
result = compare_graphs(g1, g2, out_edge[1], o2[1])
|
|
1930
|
+
if not result:
|
|
1931
|
+
return False
|
|
1932
|
+
if not matched:
|
|
1933
|
+
print("ERROR: No matching edge for ", out_edge, ".")
|
|
1934
|
+
return False
|
|
1935
|
+
return True
|
|
1936
|
+
|
|
1937
|
+
|
|
1938
|
+
def _test_against_tableaux(R, N, k, clss=CrystalOfAlcovePaths):
|
|
1939
|
+
r"""
|
|
1940
|
+
Test :class:`~sage.combinat.crystals.alcove_path.CrystalOfAlcovePaths`
|
|
1941
|
+
against all of the tableaux crystals of type `R` in rank `N` with
|
|
1942
|
+
highest weight given by a partition of `k`.
|
|
1943
|
+
|
|
1944
|
+
EXAMPLES::
|
|
1945
|
+
|
|
1946
|
+
sage: from sage.combinat.crystals.alcove_path import _test_against_tableaux
|
|
1947
|
+
sage: _test_against_tableaux(['A',3], 3, 2)
|
|
1948
|
+
** Shape [2]
|
|
1949
|
+
T has 10 nodes.
|
|
1950
|
+
C weight [2, 0, 0]
|
|
1951
|
+
C has 10 nodes.
|
|
1952
|
+
Compare graphs: True
|
|
1953
|
+
** Shape [1, 1]
|
|
1954
|
+
T has 6 nodes.
|
|
1955
|
+
C weight [0, 1, 0]
|
|
1956
|
+
C has 6 nodes.
|
|
1957
|
+
Compare graphs: True
|
|
1958
|
+
"""
|
|
1959
|
+
from sage.combinat.partition import Partitions
|
|
1960
|
+
from sage.combinat.crystals.tensor_product import CrystalOfTableaux
|
|
1961
|
+
shapes = Partitions(k).list()
|
|
1962
|
+
for shape in shapes:
|
|
1963
|
+
print("** Shape ", shape)
|
|
1964
|
+
T = CrystalOfTableaux(R, shape=shape)
|
|
1965
|
+
ct = len(T.list())
|
|
1966
|
+
print(" T has ", ct, " nodes.")
|
|
1967
|
+
# T.digraph().show(edge_labels=True)
|
|
1968
|
+
H = T.digraph()
|
|
1969
|
+
weight = T.module_generators[0].weight()
|
|
1970
|
+
w = [weight.scalar(RootSystem(R).ambient_space().simple_coroot(i))
|
|
1971
|
+
for i in range(1, N + 1)]
|
|
1972
|
+
print(" C weight ", w)
|
|
1973
|
+
|
|
1974
|
+
C = clss(R, w)
|
|
1975
|
+
|
|
1976
|
+
cc = len(C.list())
|
|
1977
|
+
# C.digraph().show(edge_labels=True)
|
|
1978
|
+
G = C.digraph()
|
|
1979
|
+
print(" C has ", cc, " nodes.")
|
|
1980
|
+
if cc != ct:
|
|
1981
|
+
print("FAIL: number of nodes differ.", cc, ct)
|
|
1982
|
+
return
|
|
1983
|
+
print(" Compare graphs: ", compare_graphs(G, H, C(()), H.vertices(sort=True)[0]))
|
|
1984
|
+
|
|
1985
|
+
|
|
1986
|
+
def _test_with_lspaths_crystal(cartan_type, weight, depth=10):
|
|
1987
|
+
r"""
|
|
1988
|
+
Test if the digraphs generated are isomorphic to the ones generated by
|
|
1989
|
+
LS-path model.
|
|
1990
|
+
|
|
1991
|
+
INPUT:
|
|
1992
|
+
|
|
1993
|
+
- ``cartan_type`` -- Cartan type of a finite or affine untwisted root
|
|
1994
|
+
system
|
|
1995
|
+
- ``weight`` -- dominant weight as a list of (integral) coefficients of the
|
|
1996
|
+
fundamental weights
|
|
1997
|
+
- ``depth`` -- starting at the module generator how deep do you want to
|
|
1998
|
+
generate the crystal, useful for affine types
|
|
1999
|
+
|
|
2000
|
+
EXAMPLES::
|
|
2001
|
+
|
|
2002
|
+
sage: from sage.combinat.crystals.alcove_path import _test_with_lspaths_crystal
|
|
2003
|
+
sage: _test_with_lspaths_crystal(['A',3,1],[1,0,0,0],10) #long time
|
|
2004
|
+
True
|
|
2005
|
+
sage: _test_with_lspaths_crystal(['G',2,1],[1,0,0,0,0],10) #long time
|
|
2006
|
+
True
|
|
2007
|
+
"""
|
|
2008
|
+
from sage.combinat.crystals.littelmann_path import CrystalOfLSPaths
|
|
2009
|
+
G1 = CrystalOfAlcovePaths(cartan_type, weight).digraph(depth=depth)
|
|
2010
|
+
C = CrystalOfLSPaths(cartan_type, weight)
|
|
2011
|
+
G2 = C.digraph(subset=C.subcrystal(max_depth=depth, direction='lower'))
|
|
2012
|
+
|
|
2013
|
+
return G1.is_isomorphic(G2, edge_labels=True)
|