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,1475 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
# sage.doctest: needs sage.combinat sage.graphs sage.modules
|
|
3
|
+
r"""
|
|
4
|
+
Kleber trees
|
|
5
|
+
|
|
6
|
+
A Kleber tree is a tree of weights generated by Kleber's algorithm
|
|
7
|
+
[Kleber1]_. The nodes correspond to the weights in the positive Weyl chamber
|
|
8
|
+
obtained by subtracting a (nonzero) positive root. The edges are labeled by
|
|
9
|
+
the coefficients of the roots of the difference.
|
|
10
|
+
|
|
11
|
+
EXAMPLES::
|
|
12
|
+
|
|
13
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
14
|
+
sage: KleberTree(['A', 3, 1], [[3,2], [2,1], [1,1], [1,1]])
|
|
15
|
+
Kleber tree of Cartan type ['A', 3, 1] and B = ((3, 2), (2, 1), (1, 1), (1, 1))
|
|
16
|
+
sage: KleberTree(['D', 4, 1], [[2,2]])
|
|
17
|
+
Kleber tree of Cartan type ['D', 4, 1] and B = ((2, 2),)
|
|
18
|
+
|
|
19
|
+
TESTS::
|
|
20
|
+
|
|
21
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
22
|
+
sage: KT = KleberTree(['A', 3, 1], [[3,2], [2,1], [1,1], [1,1]])
|
|
23
|
+
sage: sorted((x.weight.to_vector(), x.up_root.to_vector()) for x in KT.list())
|
|
24
|
+
[((0, 0, 2), (1, 1, 0)),
|
|
25
|
+
((0, 0, 2), (2, 2, 1)),
|
|
26
|
+
((0, 1, 0), (0, 0, 1)),
|
|
27
|
+
((0, 1, 0), (1, 1, 1)),
|
|
28
|
+
((0, 2, 2), (1, 0, 0)),
|
|
29
|
+
((1, 0, 3), (1, 1, 0)),
|
|
30
|
+
((1, 1, 1), (1, 1, 1)),
|
|
31
|
+
((2, 0, 0), (0, 1, 1)),
|
|
32
|
+
((2, 1, 2), (0, 0, 0)),
|
|
33
|
+
((3, 0, 1), (0, 1, 1))]
|
|
34
|
+
|
|
35
|
+
sage: KT = KleberTree(['A', 7, 1], [[3,2], [2,1], [1,1]])
|
|
36
|
+
sage: KT
|
|
37
|
+
Kleber tree of Cartan type ['A', 7, 1] and B = ((3, 2), (2, 1), (1, 1))
|
|
38
|
+
sage: sorted((x.weight.to_vector(), x.up_root.to_vector()) for x in KT.list())
|
|
39
|
+
[((0, 0, 0, 1, 1, 0, 0), (1, 1, 1, 0, 0, 0, 0)),
|
|
40
|
+
((0, 0, 1, 0, 0, 1, 0), (2, 3, 3, 2, 1, 0, 0)),
|
|
41
|
+
((0, 0, 3, 0, 0, 0, 0), (1, 1, 0, 0, 0, 0, 0)),
|
|
42
|
+
((0, 1, 1, 1, 0, 0, 0), (1, 1, 1, 0, 0, 0, 0)),
|
|
43
|
+
((1, 0, 0, 2, 0, 0, 0), (0, 1, 1, 0, 0, 0, 0)),
|
|
44
|
+
((1, 0, 1, 0, 1, 0, 0), (1, 2, 2, 1, 0, 0, 0)),
|
|
45
|
+
((1, 1, 2, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0)),
|
|
46
|
+
((2, 0, 1, 1, 0, 0, 0), (0, 1, 1, 0, 0, 0, 0))]
|
|
47
|
+
|
|
48
|
+
AUTHORS:
|
|
49
|
+
|
|
50
|
+
- Travis Scrimshaw (2011-05-03): initial version
|
|
51
|
+
- Travis Scrimshaw (2013-02-13): added support for virtual trees and improved
|
|
52
|
+
`\LaTeX` output
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
# ****************************************************************************
|
|
56
|
+
# Copyright (C) 2011, 2012 Travis Scrimshaw <tscrim@ucdavis.edu>
|
|
57
|
+
#
|
|
58
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
59
|
+
#
|
|
60
|
+
# This code is distributed in the hope that it will be useful,
|
|
61
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
62
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
63
|
+
# General Public License for more details.
|
|
64
|
+
#
|
|
65
|
+
# The full text of the GPL is available at:
|
|
66
|
+
#
|
|
67
|
+
# https://www.gnu.org/licenses/
|
|
68
|
+
# ****************************************************************************
|
|
69
|
+
|
|
70
|
+
import itertools
|
|
71
|
+
|
|
72
|
+
from sage.misc.lazy_attribute import lazy_attribute
|
|
73
|
+
from sage.misc.cachefunc import cached_method
|
|
74
|
+
from sage.misc.latex import latex
|
|
75
|
+
from sage.misc.lazy_import import lazy_import
|
|
76
|
+
from sage.misc.misc_c import prod
|
|
77
|
+
from sage.arith.misc import binomial
|
|
78
|
+
from sage.features import FeatureNotPresentError
|
|
79
|
+
from sage.rings.integer import Integer
|
|
80
|
+
|
|
81
|
+
from sage.structure.parent import Parent
|
|
82
|
+
from sage.structure.element import Element
|
|
83
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
84
|
+
from sage.structure.richcmp import richcmp_not_equal, richcmp
|
|
85
|
+
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
|
|
86
|
+
|
|
87
|
+
from sage.combinat.root_system.cartan_type import CartanType
|
|
88
|
+
|
|
89
|
+
lazy_import('sage.graphs.digraph', 'DiGraph')
|
|
90
|
+
lazy_import('sage.graphs.dot2tex_utils', 'have_dot2tex')
|
|
91
|
+
|
|
92
|
+
######################################
|
|
93
|
+
# Latex method for viewing the trees #
|
|
94
|
+
######################################
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _draw_tree(tree_node, node_label=True, style_point=None, style_node='fill=white', style_line=None,
|
|
98
|
+
hspace=2.5, vspace=-2.5, start=None, rpos=None, node_id=0, node_prefix='T',
|
|
99
|
+
edge_labels=True, use_vector_notation=False):
|
|
100
|
+
r"""
|
|
101
|
+
Return the tikz latex for drawing the Kleber tree.
|
|
102
|
+
|
|
103
|
+
AUTHORS:
|
|
104
|
+
|
|
105
|
+
- Viviane Pons (2013-02-13): Initial version
|
|
106
|
+
- Travis Scrimshaw (2013-03-02): Modified to work with Kleber tree output
|
|
107
|
+
|
|
108
|
+
.. WARNING::
|
|
109
|
+
|
|
110
|
+
Internal latex function.
|
|
111
|
+
|
|
112
|
+
EXAMPLES::
|
|
113
|
+
|
|
114
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
115
|
+
sage: KT = KleberTree(['A',3,1], [[3,2],[1,1]])
|
|
116
|
+
sage: latex(KT) # indirect doctest
|
|
117
|
+
\begin{tikzpicture}
|
|
118
|
+
\node[fill=white] (T0) at (0.000, 0.000){$V_{\omega_{1}+2\omega_{3}}$};
|
|
119
|
+
\node (T00) at (0.000, -2.500){$V_{\omega_{3}}$};
|
|
120
|
+
\draw (T0) to node[sloped,above]{\tiny $\alpha_{1} + \alpha_{2} + \alpha_{3}$} (T00);
|
|
121
|
+
\end{tikzpicture}
|
|
122
|
+
"""
|
|
123
|
+
if start is None:
|
|
124
|
+
start = [0., 0.]
|
|
125
|
+
if rpos is None:
|
|
126
|
+
rpos = [0., 0.]
|
|
127
|
+
|
|
128
|
+
if not tree_node.children:
|
|
129
|
+
r = ''
|
|
130
|
+
node_name = node_prefix + str(node_id)
|
|
131
|
+
r = "\\node (%s) at (%.3f, %.3f)" % (node_name, *start)
|
|
132
|
+
if node_label:
|
|
133
|
+
r += "{$%s$};\n" % tree_node._latex_()
|
|
134
|
+
else:
|
|
135
|
+
r += "{};\n"
|
|
136
|
+
rpos[0] = start[0]
|
|
137
|
+
rpos[1] = start[1]
|
|
138
|
+
start[0] += hspace
|
|
139
|
+
return r
|
|
140
|
+
|
|
141
|
+
node_name = node_prefix + str(node_id)
|
|
142
|
+
if style_line is None:
|
|
143
|
+
style_line_str = ''
|
|
144
|
+
else:
|
|
145
|
+
style_line_str = "[%s]" % style_line
|
|
146
|
+
if node_label:
|
|
147
|
+
node_place_str = ''
|
|
148
|
+
else:
|
|
149
|
+
node_place_str = ".center"
|
|
150
|
+
|
|
151
|
+
nb_children = len(tree_node.children)
|
|
152
|
+
half = nb_children // 2
|
|
153
|
+
children_str = ''
|
|
154
|
+
pos = [start[0], start[1]]
|
|
155
|
+
start[1] += vspace
|
|
156
|
+
lines_str = ''
|
|
157
|
+
|
|
158
|
+
# Getting children string
|
|
159
|
+
for i in range(nb_children):
|
|
160
|
+
if i == half and nb_children % 2 == 0:
|
|
161
|
+
pos[0] = start[0]
|
|
162
|
+
start[0] += hspace
|
|
163
|
+
if i == half+1 and nb_children % 2 == 1:
|
|
164
|
+
pos[0] = rpos[0]
|
|
165
|
+
child = tree_node.children[i]
|
|
166
|
+
children_str += _draw_tree(child, node_label=node_label, style_node=style_node, style_point=style_point, style_line=style_line, hspace=hspace, vspace=vspace, start=start, rpos=rpos, node_id=i, node_prefix=node_name, edge_labels=edge_labels, use_vector_notation=use_vector_notation)
|
|
167
|
+
if edge_labels:
|
|
168
|
+
if use_vector_notation:
|
|
169
|
+
edge_str = latex(child.up_root.to_vector())
|
|
170
|
+
else:
|
|
171
|
+
edge_str = latex(child.up_root)
|
|
172
|
+
lines_str += "\\draw%s (%s%s) to node[sloped,above]{\\tiny $%s$} (%s%s%s);\n" % (style_line_str, node_name, node_place_str, edge_str, node_name, i, node_place_str)
|
|
173
|
+
else:
|
|
174
|
+
lines_str += "\\draw%s (%s%s) -- (%s%s%s);\n" % (style_line_str, node_name, node_place_str, node_name, i, node_place_str)
|
|
175
|
+
|
|
176
|
+
# drawing root
|
|
177
|
+
if style_node is None:
|
|
178
|
+
style_node = ''
|
|
179
|
+
else:
|
|
180
|
+
style_node = "[%s]" % style_node
|
|
181
|
+
if style_point is None:
|
|
182
|
+
style_point = ''
|
|
183
|
+
else:
|
|
184
|
+
style_point = "[%s]" % style_point
|
|
185
|
+
start[1] -= vspace
|
|
186
|
+
rpos[0] = pos[0]
|
|
187
|
+
rpos[1] = pos[1]
|
|
188
|
+
point_str = ''
|
|
189
|
+
node_str = "\\node%s (%s) at (%.3f, %.3f)" % (style_node, node_name, *pos)
|
|
190
|
+
if node_label:
|
|
191
|
+
node_str += "{$%s$};\n" % tree_node._latex_()
|
|
192
|
+
else:
|
|
193
|
+
node_str += "{};\n"
|
|
194
|
+
point_str = "\\draw%s (%s) circle;\n" % (style_point, node_name)
|
|
195
|
+
|
|
196
|
+
res = node_str
|
|
197
|
+
res += children_str
|
|
198
|
+
res += lines_str
|
|
199
|
+
res += point_str
|
|
200
|
+
return res
|
|
201
|
+
|
|
202
|
+
#####################
|
|
203
|
+
# Kleber tree nodes #
|
|
204
|
+
#####################
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class KleberTreeNode(Element):
|
|
208
|
+
r"""
|
|
209
|
+
A node in the Kleber tree.
|
|
210
|
+
|
|
211
|
+
This class is meant to be used internally by the Kleber tree class and
|
|
212
|
+
should not be created directly by the user.
|
|
213
|
+
|
|
214
|
+
For more on the Kleber tree and the nodes, see :class:`KleberTree`.
|
|
215
|
+
|
|
216
|
+
The dominating root is the ``up_root`` which is the difference
|
|
217
|
+
between the parent node's weight and this node's weight.
|
|
218
|
+
|
|
219
|
+
INPUT:
|
|
220
|
+
|
|
221
|
+
- ``parent_obj`` -- the parent object of this element
|
|
222
|
+
- ``node_weight`` -- the weight of this node
|
|
223
|
+
- ``dominant_root`` -- the dominating root
|
|
224
|
+
- ``parent_node`` -- (default: ``None``) the parent node of this node
|
|
225
|
+
"""
|
|
226
|
+
|
|
227
|
+
def __init__(self, parent_obj, node_weight, dominant_root, parent_node=None):
|
|
228
|
+
r"""
|
|
229
|
+
Initialize the tree node.
|
|
230
|
+
|
|
231
|
+
TESTS::
|
|
232
|
+
|
|
233
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
234
|
+
sage: RS = RootSystem(['A', 2])
|
|
235
|
+
sage: WS = RS.weight_lattice()
|
|
236
|
+
sage: R = RS.root_lattice()
|
|
237
|
+
sage: KT = KleberTree(['A', 2, 1], [[1,1]])
|
|
238
|
+
sage: parent = KT(WS.sum_of_terms([(1,5), (2,2)]), R.zero())
|
|
239
|
+
sage: parent
|
|
240
|
+
Kleber tree node with weight [5, 2] and upwards edge root [0, 0]
|
|
241
|
+
sage: parent.parent_node
|
|
242
|
+
sage: child = KT(WS.sum_of_terms([(1,3), (2,1)]), R.sum_of_terms([(1,1), (2,2)]), parent)
|
|
243
|
+
sage: child
|
|
244
|
+
Kleber tree node with weight [3, 1] and upwards edge root [1, 2]
|
|
245
|
+
sage: child.parent_node
|
|
246
|
+
Kleber tree node with weight [5, 2] and upwards edge root [0, 0]
|
|
247
|
+
sage: TestSuite(parent).run()
|
|
248
|
+
"""
|
|
249
|
+
self.parent_node = parent_node
|
|
250
|
+
self.children = []
|
|
251
|
+
self.weight = node_weight
|
|
252
|
+
self.up_root = dominant_root
|
|
253
|
+
Element.__init__(self, parent_obj)
|
|
254
|
+
|
|
255
|
+
@lazy_attribute
|
|
256
|
+
def depth(self):
|
|
257
|
+
"""
|
|
258
|
+
Return the depth of this node in the tree.
|
|
259
|
+
|
|
260
|
+
EXAMPLES::
|
|
261
|
+
|
|
262
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
263
|
+
sage: RS = RootSystem(['A', 2])
|
|
264
|
+
sage: WS = RS.weight_lattice()
|
|
265
|
+
sage: R = RS.root_lattice()
|
|
266
|
+
sage: KT = KleberTree(['A', 2, 1], [[1,1]])
|
|
267
|
+
sage: n = KT(WS.sum_of_terms([(1,5), (2,2)]), R.zero())
|
|
268
|
+
sage: n.depth
|
|
269
|
+
0
|
|
270
|
+
sage: n2 = KT(WS.sum_of_terms([(1,5), (2,2)]), R.zero(), n)
|
|
271
|
+
sage: n2.depth
|
|
272
|
+
1
|
|
273
|
+
"""
|
|
274
|
+
depth = -1 # Offset
|
|
275
|
+
cur = self
|
|
276
|
+
while cur is not None:
|
|
277
|
+
depth += 1
|
|
278
|
+
cur = cur.parent_node
|
|
279
|
+
|
|
280
|
+
return depth
|
|
281
|
+
|
|
282
|
+
@cached_method
|
|
283
|
+
def multiplicity(self):
|
|
284
|
+
r"""
|
|
285
|
+
Return the multiplicity of ``self``.
|
|
286
|
+
|
|
287
|
+
The multiplicity of a node `x` of depth `d` weight `\lambda` in a
|
|
288
|
+
simply-laced Kleber tree is equal to:
|
|
289
|
+
|
|
290
|
+
.. MATH::
|
|
291
|
+
|
|
292
|
+
\prod_{i > 0} \prod_{a \in \overline{I}}
|
|
293
|
+
\binom{p_i^{(a)} + m_i^{(a)}}{p_i^{(a)}}
|
|
294
|
+
|
|
295
|
+
Recall that
|
|
296
|
+
|
|
297
|
+
.. MATH::
|
|
298
|
+
|
|
299
|
+
m_i^{(a)} = \left( \lambda^{(i-1)} - 2 \lambda^{(i)} +
|
|
300
|
+
\lambda^{(i+1)} \mid \overline{\Lambda}_a \right),
|
|
301
|
+
|
|
302
|
+
p_i^{(a)} = \left( \alpha_a \mid \lambda^{(i)} \right)
|
|
303
|
+
- \sum_{j > i} (j - i) L_j^{(a)},
|
|
304
|
+
|
|
305
|
+
where `\lambda^{(i)}` is the weight node at depth `i` in the path
|
|
306
|
+
to `x` from the root and we set `\lambda^{(j)} = \lambda` for all
|
|
307
|
+
`j \geq d`.
|
|
308
|
+
|
|
309
|
+
Note that `m_i^{(a)} = 0` for all `i > d`.
|
|
310
|
+
|
|
311
|
+
EXAMPLES::
|
|
312
|
+
|
|
313
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
314
|
+
sage: KT = KleberTree(['A',3,1], [[3,2],[2,1],[1,1],[1,1]])
|
|
315
|
+
sage: for x in KT: x, x.multiplicity()
|
|
316
|
+
(Kleber tree node with weight [2, 1, 2] and upwards edge root [0, 0, 0], 1)
|
|
317
|
+
(Kleber tree node with weight [3, 0, 1] and upwards edge root [0, 1, 1], 1)
|
|
318
|
+
(Kleber tree node with weight [0, 2, 2] and upwards edge root [1, 0, 0], 1)
|
|
319
|
+
(Kleber tree node with weight [1, 0, 3] and upwards edge root [1, 1, 0], 2)
|
|
320
|
+
(Kleber tree node with weight [1, 1, 1] and upwards edge root [1, 1, 1], 4)
|
|
321
|
+
(Kleber tree node with weight [0, 0, 2] and upwards edge root [2, 2, 1], 2)
|
|
322
|
+
(Kleber tree node with weight [2, 0, 0] and upwards edge root [0, 1, 1], 2)
|
|
323
|
+
(Kleber tree node with weight [0, 0, 2] and upwards edge root [1, 1, 0], 1)
|
|
324
|
+
(Kleber tree node with weight [0, 1, 0] and upwards edge root [1, 1, 1], 2)
|
|
325
|
+
(Kleber tree node with weight [0, 1, 0] and upwards edge root [0, 0, 1], 1)
|
|
326
|
+
|
|
327
|
+
TESTS:
|
|
328
|
+
|
|
329
|
+
We check that :issue:`16057` is fixed::
|
|
330
|
+
|
|
331
|
+
sage: RC = RiggedConfigurations(['D',4,1], [[1,3],[3,3],[4,3]])
|
|
332
|
+
sage: sum(x.multiplicity() for x in RC.kleber_tree()) == len(RC.module_generators)
|
|
333
|
+
True
|
|
334
|
+
"""
|
|
335
|
+
# The multiplicity corresponding to the root is always 1
|
|
336
|
+
if self.parent_node is None:
|
|
337
|
+
return Integer(1)
|
|
338
|
+
|
|
339
|
+
mult = Integer(1)
|
|
340
|
+
for a, m in self.up_root:
|
|
341
|
+
p = self.weight[a]
|
|
342
|
+
for r, s in self.parent().B:
|
|
343
|
+
if r == a and s > self.depth:
|
|
344
|
+
p -= s - self.depth
|
|
345
|
+
mult *= binomial(m + p, m)
|
|
346
|
+
|
|
347
|
+
prev_up_root = self.up_root
|
|
348
|
+
cur = self.parent_node
|
|
349
|
+
while cur.parent_node is not None:
|
|
350
|
+
root_diff = cur.up_root - prev_up_root
|
|
351
|
+
for a, m in root_diff:
|
|
352
|
+
p = cur.weight[a]
|
|
353
|
+
for r, s in self.parent().B:
|
|
354
|
+
if r == a and s > cur.depth:
|
|
355
|
+
p -= s - cur.depth
|
|
356
|
+
mult *= binomial(m + p, m)
|
|
357
|
+
prev_up_root = cur.up_root
|
|
358
|
+
cur = cur.parent_node
|
|
359
|
+
|
|
360
|
+
return mult
|
|
361
|
+
|
|
362
|
+
def __hash__(self):
|
|
363
|
+
r"""
|
|
364
|
+
TESTS::
|
|
365
|
+
|
|
366
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
367
|
+
sage: RS = RootSystem(['A', 2])
|
|
368
|
+
sage: WS = RS.weight_lattice()
|
|
369
|
+
sage: R = RS.root_lattice()
|
|
370
|
+
sage: KT = KleberTree(['A', 2, 1], [[1,1]])
|
|
371
|
+
sage: n = KT(WS.sum_of_terms([(1,5), (2,2)]), R.zero())
|
|
372
|
+
sage: n2 = KT(WS.sum_of_terms([(2,2), (1,5)]), R.zero())
|
|
373
|
+
sage: hash(n) == hash(n2)
|
|
374
|
+
True
|
|
375
|
+
sage: hash(n) == hash(R.zero())
|
|
376
|
+
False
|
|
377
|
+
"""
|
|
378
|
+
return hash(self.depth) ^ hash(self.weight)
|
|
379
|
+
|
|
380
|
+
def _richcmp_(self, rhs, op):
|
|
381
|
+
r"""
|
|
382
|
+
Check whether two nodes are equal.
|
|
383
|
+
|
|
384
|
+
TESTS::
|
|
385
|
+
|
|
386
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
387
|
+
sage: RS = RootSystem(['A', 2])
|
|
388
|
+
sage: WS = RS.weight_lattice()
|
|
389
|
+
sage: R = RS.root_lattice()
|
|
390
|
+
sage: KT = KleberTree(['A', 2, 1], [[1,1]])
|
|
391
|
+
sage: n = KT(WS.sum_of_terms([(1,5), (2,2)]), R.zero())
|
|
392
|
+
sage: n2 = KT(WS.sum_of_terms([(1,5), (2,2)]), R.zero(), n)
|
|
393
|
+
sage: n2 > n
|
|
394
|
+
True
|
|
395
|
+
sage: n3 = KT(WS.sum_of_terms([(1,5), (2,2)]), R.zero(), n)
|
|
396
|
+
sage: n2 == n3
|
|
397
|
+
True
|
|
398
|
+
sage: n3 = KT(WS.sum_of_terms([(1,5), (2,3)]), R.zero(), n)
|
|
399
|
+
sage: n2 < n3
|
|
400
|
+
True
|
|
401
|
+
"""
|
|
402
|
+
lx = self.depth
|
|
403
|
+
rx = rhs.depth
|
|
404
|
+
if lx != rx:
|
|
405
|
+
return richcmp_not_equal(lx, rx, op)
|
|
406
|
+
|
|
407
|
+
lx = self.parent_node
|
|
408
|
+
rx = rhs.parent_node
|
|
409
|
+
if lx != rx:
|
|
410
|
+
return richcmp_not_equal(lx, rx, op)
|
|
411
|
+
|
|
412
|
+
return richcmp(self.weight, rhs.weight, op)
|
|
413
|
+
|
|
414
|
+
def _repr_(self):
|
|
415
|
+
r"""
|
|
416
|
+
Return the string representation of ``self``.
|
|
417
|
+
|
|
418
|
+
EXAMPLES::
|
|
419
|
+
|
|
420
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
421
|
+
sage: RS = RootSystem(['A', 3])
|
|
422
|
+
sage: WS = RS.weight_lattice()
|
|
423
|
+
sage: R = RS.root_lattice()
|
|
424
|
+
sage: KT = KleberTree(['A', 2, 1], [[1,1]])
|
|
425
|
+
sage: node = KT(WS.sum_of_terms([(1,2), (2,1), (3,1)]), R.sum_of_terms([(1,3), (3,3)])); node
|
|
426
|
+
Kleber tree node with weight [2, 1, 1] and upwards edge root [3, 0, 3]
|
|
427
|
+
|
|
428
|
+
With virtual nodes::
|
|
429
|
+
|
|
430
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree
|
|
431
|
+
sage: KT = VirtualKleberTree(['A',6,2], [[2,2]])
|
|
432
|
+
sage: KT.root
|
|
433
|
+
Kleber tree node with weight [0, 2, 0, 2, 0] and upwards edge root [0, 0, 0, 0, 0]
|
|
434
|
+
"""
|
|
435
|
+
return "Kleber tree node with weight %s and upwards edge root %s" % (
|
|
436
|
+
list(self.weight.to_vector()), list(self.up_root.to_vector()))
|
|
437
|
+
|
|
438
|
+
def _latex_(self):
|
|
439
|
+
r"""
|
|
440
|
+
Return latex representation of ``self``.
|
|
441
|
+
|
|
442
|
+
TESTS::
|
|
443
|
+
|
|
444
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
445
|
+
sage: RS = RootSystem(['A', 3])
|
|
446
|
+
sage: WS = RS.weight_lattice()
|
|
447
|
+
sage: R = RS.root_lattice()
|
|
448
|
+
sage: KT = KleberTree(['A', 3, 1], [[3,2], [1,1]])
|
|
449
|
+
sage: node = KT(WS.sum_of_terms([(1,4), (3,1)]), R.zero())
|
|
450
|
+
sage: latex(node)
|
|
451
|
+
V_{4\omega_{1}+\omega_{3}}
|
|
452
|
+
sage: node = KT(WS.zero(), R.zero())
|
|
453
|
+
sage: latex(node)
|
|
454
|
+
V_{0}
|
|
455
|
+
sage: node = KT(WS.sum_of_terms([(1,2)]), R.zero())
|
|
456
|
+
sage: latex(node)
|
|
457
|
+
V_{2\omega_{1}}
|
|
458
|
+
|
|
459
|
+
With virtual nodes::
|
|
460
|
+
|
|
461
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree
|
|
462
|
+
sage: KT = VirtualKleberTree(['C',3,1], [[2,2]])
|
|
463
|
+
sage: latex(KT.root)
|
|
464
|
+
[V_{2\omega_{2}+2\omega_{4}}]
|
|
465
|
+
sage: KT = VirtualKleberTree(['A',6,2], [[2,2]])
|
|
466
|
+
sage: latex(KT.root)
|
|
467
|
+
[V_{2\omega_{2}+2\omega_{4}}]
|
|
468
|
+
"""
|
|
469
|
+
ret_str = "V_{"
|
|
470
|
+
if self.multiplicity() != 1:
|
|
471
|
+
ret_str = repr(self.multiplicity()) + ret_str
|
|
472
|
+
for pair in self.weight:
|
|
473
|
+
if pair[1] > 1:
|
|
474
|
+
ret_str += repr(pair[1]) + r"\omega_{" + repr(pair[0]) + "}+"
|
|
475
|
+
elif pair[1] == 1:
|
|
476
|
+
ret_str += r"\omega_{" + repr(pair[0]) + "}+"
|
|
477
|
+
|
|
478
|
+
if ret_str[-1] == '{':
|
|
479
|
+
ret_str += "0}"
|
|
480
|
+
else:
|
|
481
|
+
ret_str = ret_str[:-1] + "}"
|
|
482
|
+
|
|
483
|
+
ct = self.parent()._cartan_type
|
|
484
|
+
if ct.type() == 'BC' or ct.dual().type() == 'BC':
|
|
485
|
+
return "[" + ret_str + "]"
|
|
486
|
+
elif not ct.is_simply_laced():
|
|
487
|
+
s_factors = self.parent()._folded_ct.scaling_factors()
|
|
488
|
+
gamma = max(s_factors)
|
|
489
|
+
# Subtract 1 for indexing
|
|
490
|
+
if gamma > 1:
|
|
491
|
+
L = [self.parent()._folded_ct.folding_orbit()[a][0] for a in
|
|
492
|
+
range(1, len(s_factors)) if s_factors[a] == gamma]
|
|
493
|
+
else:
|
|
494
|
+
L = []
|
|
495
|
+
|
|
496
|
+
if self.depth % gamma == 0 or all(self.up_root[a] == 0 for a in L):
|
|
497
|
+
return "[" + ret_str + "]"
|
|
498
|
+
return ret_str
|
|
499
|
+
|
|
500
|
+
#######################
|
|
501
|
+
# Kleber tree classes #
|
|
502
|
+
#######################
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
class KleberTree(UniqueRepresentation, Parent):
|
|
506
|
+
r"""
|
|
507
|
+
The tree that is generated by Kleber's algorithm.
|
|
508
|
+
|
|
509
|
+
A Kleber tree is a tree of weights generated by Kleber's algorithm
|
|
510
|
+
[Kleber1]_. It is used to generate the set of all admissible rigged
|
|
511
|
+
configurations for the simply-laced affine types `A_n^{(1)}`,
|
|
512
|
+
`D_n^{(1)}`, `E_6^{(1)}`, `E_7^{(1)}`, and `E_8^{(1)}`.
|
|
513
|
+
|
|
514
|
+
.. SEEALSO::
|
|
515
|
+
|
|
516
|
+
There is a modified version for non-simply-laced affine types at
|
|
517
|
+
:class:`VirtualKleberTree`.
|
|
518
|
+
|
|
519
|
+
The nodes correspond to the weights in the positive Weyl chamber obtained
|
|
520
|
+
by subtracting a (nonzero) positive root. The edges are labeled by the
|
|
521
|
+
coefficients of the roots, and `X` is a child of `Y` if `Y` is the root
|
|
522
|
+
else if the edge label of `Y` to its parent `Z` is greater (in every
|
|
523
|
+
component) than the label from `X` to `Y`.
|
|
524
|
+
|
|
525
|
+
For a Kleber tree, one needs to specify an affine (simply-laced)
|
|
526
|
+
Cartan type and a sequence of pairs `(r,s)`, where `s` is any positive
|
|
527
|
+
integer and `r` is a node in the Dynkin diagram. Each `(r,s)` can be
|
|
528
|
+
viewed as a rectangle of width `s` and height `r`.
|
|
529
|
+
|
|
530
|
+
INPUT:
|
|
531
|
+
|
|
532
|
+
- ``cartan_type`` -- an affine simply-laced Cartan type
|
|
533
|
+
|
|
534
|
+
- ``B`` -- list of dimensions of rectangles by `[r, c]`
|
|
535
|
+
where `r` is the number of rows and `c` is the number of columns
|
|
536
|
+
|
|
537
|
+
REFERENCES:
|
|
538
|
+
|
|
539
|
+
.. [Kleber1] Michael Kleber.
|
|
540
|
+
*Combinatorial structure of finite dimensional representations of
|
|
541
|
+
Yangians: the simply-laced case*.
|
|
542
|
+
Internat. Math. Res. Notices. (1997) no. 4. 187-201.
|
|
543
|
+
|
|
544
|
+
.. [Kleber2] Michael Kleber.
|
|
545
|
+
*Finite dimensional representations of quantum affine algebras*.
|
|
546
|
+
Ph.D. dissertation at University of California Berkeley. (1998).
|
|
547
|
+
:arxiv:`math.QA/9809087`.
|
|
548
|
+
|
|
549
|
+
EXAMPLES:
|
|
550
|
+
|
|
551
|
+
Simply-laced example::
|
|
552
|
+
|
|
553
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
554
|
+
sage: KT = KleberTree(['A', 3, 1], [[3,2], [1,1]])
|
|
555
|
+
sage: KT.list()
|
|
556
|
+
[Kleber tree node with weight [1, 0, 2] and upwards edge root [0, 0, 0],
|
|
557
|
+
Kleber tree node with weight [0, 0, 1] and upwards edge root [1, 1, 1]]
|
|
558
|
+
sage: KT = KleberTree(['A', 3, 1], [[3,2], [2,1], [1,1], [1,1]])
|
|
559
|
+
sage: KT.cardinality()
|
|
560
|
+
10
|
|
561
|
+
sage: KT = KleberTree(['D', 4, 1], [[2,2]])
|
|
562
|
+
sage: KT.cardinality()
|
|
563
|
+
3
|
|
564
|
+
sage: KT = KleberTree(['D', 4, 1], [[4,5]])
|
|
565
|
+
sage: KT.cardinality()
|
|
566
|
+
1
|
|
567
|
+
|
|
568
|
+
From [Kleber2]_::
|
|
569
|
+
|
|
570
|
+
sage: KT = KleberTree(['E', 6, 1], [[4, 2]]) # long time (9s on sage.math, 2012)
|
|
571
|
+
sage: KT.cardinality() # long time
|
|
572
|
+
12
|
|
573
|
+
|
|
574
|
+
We check that relabelled types work (:issue:`16876`)::
|
|
575
|
+
|
|
576
|
+
sage: ct = CartanType(['A',3,1]).relabel(lambda x: x+2)
|
|
577
|
+
sage: kt = KleberTree(ct, [[3,1],[5,1]])
|
|
578
|
+
sage: list(kt)
|
|
579
|
+
[Kleber tree node with weight [1, 0, 1] and upwards edge root [0, 0, 0],
|
|
580
|
+
Kleber tree node with weight [0, 0, 0] and upwards edge root [1, 1, 1]]
|
|
581
|
+
sage: kt = KleberTree(['A',3,1], [[1,1],[3,1]])
|
|
582
|
+
sage: list(kt)
|
|
583
|
+
[Kleber tree node with weight [1, 0, 1] and upwards edge root [0, 0, 0],
|
|
584
|
+
Kleber tree node with weight [0, 0, 0] and upwards edge root [1, 1, 1]]
|
|
585
|
+
"""
|
|
586
|
+
@staticmethod
|
|
587
|
+
def __classcall_private__(cls, cartan_type, B, classical=None):
|
|
588
|
+
"""
|
|
589
|
+
Normalize the input arguments to ensure unique representation.
|
|
590
|
+
|
|
591
|
+
EXAMPLES::
|
|
592
|
+
|
|
593
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
594
|
+
sage: KT1 = KleberTree(CartanType(['A',3,1]), [[2,2]])
|
|
595
|
+
sage: KT2 = KleberTree(['A',3,1], [(2,2)])
|
|
596
|
+
sage: KT3 = KleberTree(['A',3,1], ((2,2),))
|
|
597
|
+
sage: KT2 is KT1, KT3 is KT1
|
|
598
|
+
(True, True)
|
|
599
|
+
"""
|
|
600
|
+
cartan_type = CartanType(cartan_type)
|
|
601
|
+
if not cartan_type.is_affine():
|
|
602
|
+
raise ValueError("The Cartan type must be affine")
|
|
603
|
+
|
|
604
|
+
if not cartan_type.classical().is_simply_laced():
|
|
605
|
+
raise ValueError("use VirtualKleberTree for non-simply-laced types")
|
|
606
|
+
|
|
607
|
+
# Standardize B input into a tuple of tuples
|
|
608
|
+
B = tuple([tuple(rs) for rs in B])
|
|
609
|
+
|
|
610
|
+
if classical is None:
|
|
611
|
+
classical = cartan_type.classical()
|
|
612
|
+
else:
|
|
613
|
+
classical = CartanType(classical)
|
|
614
|
+
return super().__classcall__(cls, cartan_type, B, classical)
|
|
615
|
+
|
|
616
|
+
def __init__(self, cartan_type, B, classical_ct):
|
|
617
|
+
r"""
|
|
618
|
+
Construct a Kleber tree.
|
|
619
|
+
|
|
620
|
+
The input ``classical_ct`` is the classical Cartan type to run the
|
|
621
|
+
algorithm on and is only meant to be used internally.
|
|
622
|
+
|
|
623
|
+
EXAMPLES::
|
|
624
|
+
|
|
625
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
626
|
+
sage: KT = KleberTree(['D', 3, 1], [[1,1], [1,1]]); KT
|
|
627
|
+
Kleber tree of Cartan type ['D', 3, 1] and B = ((1, 1), (1, 1))
|
|
628
|
+
sage: TestSuite(KT).run(skip='_test_elements')
|
|
629
|
+
"""
|
|
630
|
+
Parent.__init__(self, category=FiniteEnumeratedSets())
|
|
631
|
+
|
|
632
|
+
self._cartan_type = cartan_type
|
|
633
|
+
self.B = B
|
|
634
|
+
self._classical_ct = classical_ct
|
|
635
|
+
# Our computations in _children_iter_vector use dense vectors.
|
|
636
|
+
# Moreover, ranks are relatively small, so just use the dense
|
|
637
|
+
# version of the Cartan matrix.
|
|
638
|
+
self._CM = self._classical_ct.cartan_matrix().dense_matrix()
|
|
639
|
+
self._build_tree()
|
|
640
|
+
self._latex_options = dict(edge_labels=True, use_vector_notation=False,
|
|
641
|
+
hspace=2.5,
|
|
642
|
+
vspace=min(-2.5, -0.75*self._classical_ct.rank()))
|
|
643
|
+
|
|
644
|
+
def latex_options(self, **options):
|
|
645
|
+
"""
|
|
646
|
+
Return the current latex options if no arguments are passed, otherwise
|
|
647
|
+
set the corresponding latex option.
|
|
648
|
+
|
|
649
|
+
OPTIONS:
|
|
650
|
+
|
|
651
|
+
- ``hspace`` -- (default: `2.5`) the horizontal spacing of the
|
|
652
|
+
tree nodes
|
|
653
|
+
- ``vspace`` -- (default: ``x``) the vertical spacing of the tree
|
|
654
|
+
nodes, here ``x`` is the minimum of `-2.5` or `-.75n` where `n` is
|
|
655
|
+
the rank of the classical type
|
|
656
|
+
- ``edge_labels`` -- boolean (default: ``True``); display edge labels
|
|
657
|
+
- ``use_vector_notation`` -- boolean (default: ``False``); display edge labels
|
|
658
|
+
using vector notation instead of a linear combination
|
|
659
|
+
|
|
660
|
+
EXAMPLES::
|
|
661
|
+
|
|
662
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
663
|
+
sage: KT = KleberTree(['D', 3, 1], [[2,1], [2,1]])
|
|
664
|
+
sage: KT.latex_options(vspace=-4, use_vector_notation=True)
|
|
665
|
+
sage: sorted(KT.latex_options().items())
|
|
666
|
+
[('edge_labels', True), ('hspace', 2.5), ('use_vector_notation', True), ('vspace', -4)]
|
|
667
|
+
"""
|
|
668
|
+
if not options:
|
|
669
|
+
from copy import copy
|
|
670
|
+
return copy(self._latex_options)
|
|
671
|
+
for key, value in options.items():
|
|
672
|
+
self._latex_options[key] = value
|
|
673
|
+
|
|
674
|
+
def _latex_(self):
|
|
675
|
+
r"""
|
|
676
|
+
Return a latex representation of this Kleber tree.
|
|
677
|
+
|
|
678
|
+
.. SEEALSO::
|
|
679
|
+
|
|
680
|
+
:meth:`latex_options()`
|
|
681
|
+
|
|
682
|
+
EXAMPLES::
|
|
683
|
+
|
|
684
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
685
|
+
sage: KT = KleberTree(['D', 3, 1], [[2,1], [2,1]])
|
|
686
|
+
sage: KT._latex_()
|
|
687
|
+
'\\begin{tikzpicture}...\\end{tikzpicture}'
|
|
688
|
+
"""
|
|
689
|
+
from sage.graphs.graph_latex import setup_latex_preamble
|
|
690
|
+
setup_latex_preamble()
|
|
691
|
+
|
|
692
|
+
return "\\begin{tikzpicture}\n" + \
|
|
693
|
+
_draw_tree(self.root, **self._latex_options) \
|
|
694
|
+
+ "\\end{tikzpicture}"
|
|
695
|
+
|
|
696
|
+
def _build_tree(self):
|
|
697
|
+
"""
|
|
698
|
+
Build the Kleber tree.
|
|
699
|
+
|
|
700
|
+
TESTS:
|
|
701
|
+
|
|
702
|
+
This is called from the constructor::
|
|
703
|
+
|
|
704
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
705
|
+
sage: KT = KleberTree(['A',3,1], [[2,2]]) # indirect doctest
|
|
706
|
+
"""
|
|
707
|
+
P = self._classical_ct.root_system().weight_lattice()
|
|
708
|
+
# Create an empty node at first step
|
|
709
|
+
self.root = KleberTreeNode(self, P.zero(),
|
|
710
|
+
self._classical_ct.root_system().root_lattice().zero())
|
|
711
|
+
full_list = [self.root] # The list of tree nodes
|
|
712
|
+
|
|
713
|
+
n = self._classical_ct.rank()
|
|
714
|
+
|
|
715
|
+
# Convert the B values into an L matrix
|
|
716
|
+
I = self._classical_ct.index_set()
|
|
717
|
+
L = [[0] for _ in range(n)]
|
|
718
|
+
|
|
719
|
+
for r, s in self.B:
|
|
720
|
+
while len(L[0]) < s: # Add more columns if needed
|
|
721
|
+
for row in L:
|
|
722
|
+
row.append(0)
|
|
723
|
+
L[I.index(r)][s - 1] += 1 # The -1 is for indexing
|
|
724
|
+
|
|
725
|
+
# Perform a special case of the algorithm for the root node
|
|
726
|
+
weight_basis = P.basis()
|
|
727
|
+
for a in range(n):
|
|
728
|
+
self.root.weight += sum(L[a]) * weight_basis[I[a]]
|
|
729
|
+
new_children = []
|
|
730
|
+
for new_child in self._children_iter(self.root):
|
|
731
|
+
if not self._prune(new_child, 1):
|
|
732
|
+
new_children.append(new_child)
|
|
733
|
+
self.root.children.append(new_child)
|
|
734
|
+
full_list.append(new_child)
|
|
735
|
+
|
|
736
|
+
depth = 1
|
|
737
|
+
growth = True
|
|
738
|
+
|
|
739
|
+
# self._has_normaliz is set by _children_iter
|
|
740
|
+
if self._classical_ct.rank() >= 7 or self._has_normaliz:
|
|
741
|
+
child_itr = self._children_iter
|
|
742
|
+
else:
|
|
743
|
+
child_itr = self._children_iter_vector
|
|
744
|
+
|
|
745
|
+
while growth:
|
|
746
|
+
growth = False
|
|
747
|
+
depth += 1
|
|
748
|
+
leaves = new_children
|
|
749
|
+
|
|
750
|
+
if depth <= len(L[0]):
|
|
751
|
+
new_children = []
|
|
752
|
+
for x in full_list:
|
|
753
|
+
growth = True
|
|
754
|
+
for a in range(n):
|
|
755
|
+
for i in range(depth - 1, len(L[a])): # Subtract 1 for indexing
|
|
756
|
+
x.weight += L[a][i] * weight_basis[I[a]]
|
|
757
|
+
|
|
758
|
+
new_children = [new_child
|
|
759
|
+
for x in leaves
|
|
760
|
+
for new_child in child_itr(x)
|
|
761
|
+
if not self._prune(new_child, depth)]
|
|
762
|
+
|
|
763
|
+
# Connect the new children into the tree
|
|
764
|
+
if new_children:
|
|
765
|
+
growth = True
|
|
766
|
+
for new_child in new_children:
|
|
767
|
+
new_child.parent_node.children.append(new_child)
|
|
768
|
+
full_list.append(new_child)
|
|
769
|
+
|
|
770
|
+
self._set = full_list
|
|
771
|
+
|
|
772
|
+
def _children_iter(self, node):
|
|
773
|
+
r"""
|
|
774
|
+
Iterate over the children of ``node``.
|
|
775
|
+
|
|
776
|
+
Helper iterator to iterate over all children, by generating and/or
|
|
777
|
+
computing them, of the Kleber tree node.
|
|
778
|
+
|
|
779
|
+
We compute the children by computing integral points (expressed as
|
|
780
|
+
simple roots) in the polytope given by the intersection of the
|
|
781
|
+
negative root cone and shifted positive weight cone. More precisely,
|
|
782
|
+
we rewrite the condition `\lambda - \mu \in Q^+`, for `\mu \in P^+`,
|
|
783
|
+
as `\lambda - Q^+ = \mu \in P^+`.
|
|
784
|
+
|
|
785
|
+
INPUT:
|
|
786
|
+
|
|
787
|
+
- ``node`` -- the current node in the tree whose children we want
|
|
788
|
+
to generate
|
|
789
|
+
|
|
790
|
+
TESTS::
|
|
791
|
+
|
|
792
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
793
|
+
sage: KT = KleberTree(['D', 3, 1], [[1,1], [1,1]])
|
|
794
|
+
sage: for x in KT: x # indirect doctest
|
|
795
|
+
Kleber tree node with weight [2, 0, 0] and upwards edge root [0, 0, 0]
|
|
796
|
+
Kleber tree node with weight [0, 1, 1] and upwards edge root [1, 0, 0]
|
|
797
|
+
Kleber tree node with weight [0, 0, 0] and upwards edge root [2, 1, 1]
|
|
798
|
+
|
|
799
|
+
sage: KT = KleberTree(['D', 4, 1], [[2,2]])
|
|
800
|
+
sage: KT[1]
|
|
801
|
+
Kleber tree node with weight [0, 1, 0, 0] and upwards edge root [1, 2, 1, 1]
|
|
802
|
+
sage: for x in KT: x
|
|
803
|
+
Kleber tree node with weight [0, 2, 0, 0] and upwards edge root [0, 0, 0, 0]
|
|
804
|
+
Kleber tree node with weight [0, 1, 0, 0] and upwards edge root [1, 2, 1, 1]
|
|
805
|
+
Kleber tree node with weight [0, 0, 0, 0] and upwards edge root [1, 2, 1, 1]
|
|
806
|
+
sage: for x in KT._children_iter(KT[1]): x
|
|
807
|
+
Kleber tree node with weight [0, 0, 0, 0] and upwards edge root [1, 2, 1, 1]
|
|
808
|
+
"""
|
|
809
|
+
# It is faster to just cycle through than build the polytope and its
|
|
810
|
+
# lattice points when we are sufficiently small
|
|
811
|
+
# The number 500 comes from testing on my machine about where the
|
|
812
|
+
# tradeoff occurs between the methods. However, this may grow as
|
|
813
|
+
# the _children_iter_vector is further optimized.
|
|
814
|
+
if node != self.root and prod(val+1 for val in node.up_root.coefficients()) < 1000:
|
|
815
|
+
yield from self._children_iter_vector(node)
|
|
816
|
+
return
|
|
817
|
+
|
|
818
|
+
n = self._classical_ct.rank()
|
|
819
|
+
I = self._classical_ct.index_set()
|
|
820
|
+
Q = self._classical_ct.root_system().root_lattice()
|
|
821
|
+
P = self._classical_ct.root_system().weight_lattice()
|
|
822
|
+
|
|
823
|
+
# Construct the polytope by inequalities
|
|
824
|
+
from sage.geometry.polyhedron.constructor import Polyhedron
|
|
825
|
+
# Construct the shifted weight cone
|
|
826
|
+
root_weight = node.weight.to_vector()
|
|
827
|
+
ieqs = [[root_weight[i]] + list(col)
|
|
828
|
+
for i, col in enumerate(self._CM.columns())]
|
|
829
|
+
# Construct the negative weight cone
|
|
830
|
+
for i in range(n):
|
|
831
|
+
v = [0] * (n+1)
|
|
832
|
+
v[i+1] = -1
|
|
833
|
+
ieqs.append(v)
|
|
834
|
+
ieqs.append([-1]*(n+1)) # For avoiding the origin
|
|
835
|
+
# Construct the bounds for the non-root nodes
|
|
836
|
+
if node != self.root:
|
|
837
|
+
for i, c in enumerate(node.up_root.to_vector()):
|
|
838
|
+
v = [0] * (n+1)
|
|
839
|
+
v[0] = c
|
|
840
|
+
v[i+1] = 1
|
|
841
|
+
ieqs.append(v)
|
|
842
|
+
|
|
843
|
+
try:
|
|
844
|
+
poly = Polyhedron(ieqs=ieqs, backend='normaliz')
|
|
845
|
+
self._has_normaliz = True
|
|
846
|
+
except FeatureNotPresentError:
|
|
847
|
+
poly = Polyhedron(ieqs=ieqs)
|
|
848
|
+
self._has_normaliz = False
|
|
849
|
+
|
|
850
|
+
# Build the nodes from the polytope
|
|
851
|
+
# Sort for a consistent ordering (it is typically a small list)
|
|
852
|
+
for pt in sorted(poly.integral_points(), reverse=True):
|
|
853
|
+
up_root = Q._from_dict({I[i]: -val for i, val in enumerate(pt) if val != 0},
|
|
854
|
+
remove_zeros=False)
|
|
855
|
+
wt = node.weight + sum(val * P.simple_root(I[i]) for i, val in enumerate(pt))
|
|
856
|
+
yield KleberTreeNode(self, wt, up_root, node)
|
|
857
|
+
|
|
858
|
+
def _children_iter_vector(self, node):
|
|
859
|
+
r"""
|
|
860
|
+
Iterate over the children of ``node``.
|
|
861
|
+
|
|
862
|
+
Helper iterator to iterate over all children, by generating and/or
|
|
863
|
+
computing them, of the Kleber tree node. This implementation
|
|
864
|
+
iterates over all possible uproot vectors.
|
|
865
|
+
|
|
866
|
+
.. SEEALSO::
|
|
867
|
+
|
|
868
|
+
:meth:`_children_iter`
|
|
869
|
+
|
|
870
|
+
INPUT:
|
|
871
|
+
|
|
872
|
+
- ``node`` -- the current node in the tree whose children we want
|
|
873
|
+
to generate
|
|
874
|
+
|
|
875
|
+
TESTS::
|
|
876
|
+
|
|
877
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
878
|
+
sage: KT = KleberTree(['D', 4, 1], [[2,2]])
|
|
879
|
+
sage: KT[1]
|
|
880
|
+
Kleber tree node with weight [0, 1, 0, 0] and upwards edge root [1, 2, 1, 1]
|
|
881
|
+
sage: for x in KT._children_iter(KT[1]): x
|
|
882
|
+
Kleber tree node with weight [0, 0, 0, 0] and upwards edge root [1, 2, 1, 1]
|
|
883
|
+
"""
|
|
884
|
+
Q = self._classical_ct.root_system().root_lattice()
|
|
885
|
+
P = self._classical_ct.root_system().weight_lattice()
|
|
886
|
+
I = self._classical_ct.index_set()
|
|
887
|
+
wt = node.weight.to_vector()
|
|
888
|
+
cols = self._CM.columns()
|
|
889
|
+
|
|
890
|
+
L = [range(val + 1) for val in node.up_root.to_vector()]
|
|
891
|
+
|
|
892
|
+
it = itertools.product(*L)
|
|
893
|
+
next(it) # First element is the zero element
|
|
894
|
+
for root in it:
|
|
895
|
+
# Convert the list to the weight lattice
|
|
896
|
+
converted_root = sum(cols[i] * c for i, c in enumerate(root)
|
|
897
|
+
if c != 0)
|
|
898
|
+
|
|
899
|
+
if all(wt[i] >= val for i, val in enumerate(converted_root)):
|
|
900
|
+
wd = {I[i]: wt[i] - val for i, val in enumerate(converted_root)}
|
|
901
|
+
rd = {I[i]: val for i, val in enumerate(root) if val != 0}
|
|
902
|
+
yield KleberTreeNode(self,
|
|
903
|
+
P._from_dict(wd),
|
|
904
|
+
Q._from_dict(rd, remove_zeros=False),
|
|
905
|
+
node)
|
|
906
|
+
|
|
907
|
+
def _prune(self, new_child, depth):
|
|
908
|
+
r"""
|
|
909
|
+
Return ``True`` if we are to prune the tree at ``new_child``.
|
|
910
|
+
|
|
911
|
+
This always returns ``False`` since we do not do any pruning.
|
|
912
|
+
|
|
913
|
+
EXAMPLES::
|
|
914
|
+
|
|
915
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
916
|
+
sage: KT = KleberTree(['A', 2, 1], [[1,1]])
|
|
917
|
+
sage: KT._prune(KT.root, 0)
|
|
918
|
+
False
|
|
919
|
+
"""
|
|
920
|
+
return False
|
|
921
|
+
|
|
922
|
+
def breadth_first_iter(self):
|
|
923
|
+
r"""
|
|
924
|
+
Iterate over all nodes in the tree following a breadth-first traversal.
|
|
925
|
+
|
|
926
|
+
EXAMPLES::
|
|
927
|
+
|
|
928
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
929
|
+
sage: KT = KleberTree(['A', 3, 1], [[2, 2], [2, 3]])
|
|
930
|
+
sage: for x in KT.breadth_first_iter(): x
|
|
931
|
+
Kleber tree node with weight [0, 5, 0] and upwards edge root [0, 0, 0]
|
|
932
|
+
Kleber tree node with weight [1, 3, 1] and upwards edge root [0, 1, 0]
|
|
933
|
+
Kleber tree node with weight [0, 3, 0] and upwards edge root [1, 2, 1]
|
|
934
|
+
Kleber tree node with weight [2, 1, 2] and upwards edge root [0, 1, 0]
|
|
935
|
+
Kleber tree node with weight [1, 1, 1] and upwards edge root [0, 1, 0]
|
|
936
|
+
Kleber tree node with weight [0, 1, 0] and upwards edge root [1, 2, 1]
|
|
937
|
+
"""
|
|
938
|
+
cur = []
|
|
939
|
+
next = [self.root]
|
|
940
|
+
while next:
|
|
941
|
+
cur = next
|
|
942
|
+
next = []
|
|
943
|
+
for node in cur:
|
|
944
|
+
yield node
|
|
945
|
+
next.extend(node.children)
|
|
946
|
+
|
|
947
|
+
def depth_first_iter(self):
|
|
948
|
+
r"""
|
|
949
|
+
Iterate (recursively) over the nodes in the tree following a
|
|
950
|
+
depth-first traversal.
|
|
951
|
+
|
|
952
|
+
EXAMPLES::
|
|
953
|
+
|
|
954
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
955
|
+
sage: KT = KleberTree(['A', 3, 1], [[2, 2], [2, 3]])
|
|
956
|
+
sage: for x in KT.depth_first_iter(): x
|
|
957
|
+
Kleber tree node with weight [0, 5, 0] and upwards edge root [0, 0, 0]
|
|
958
|
+
Kleber tree node with weight [1, 3, 1] and upwards edge root [0, 1, 0]
|
|
959
|
+
Kleber tree node with weight [2, 1, 2] and upwards edge root [0, 1, 0]
|
|
960
|
+
Kleber tree node with weight [0, 3, 0] and upwards edge root [1, 2, 1]
|
|
961
|
+
Kleber tree node with weight [1, 1, 1] and upwards edge root [0, 1, 0]
|
|
962
|
+
Kleber tree node with weight [0, 1, 0] and upwards edge root [1, 2, 1]
|
|
963
|
+
"""
|
|
964
|
+
return self._depth_first_iter(None)
|
|
965
|
+
|
|
966
|
+
def _depth_first_iter(self, cur):
|
|
967
|
+
r"""
|
|
968
|
+
Helper recursive function used in depth-first iteration.
|
|
969
|
+
|
|
970
|
+
EXAMPLES::
|
|
971
|
+
|
|
972
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
973
|
+
sage: KT = KleberTree(['A', 3, 1], [[2, 2], [2, 3]])
|
|
974
|
+
sage: for x in KT._depth_first_iter(None): x
|
|
975
|
+
Kleber tree node with weight [0, 5, 0] and upwards edge root [0, 0, 0]
|
|
976
|
+
Kleber tree node with weight [1, 3, 1] and upwards edge root [0, 1, 0]
|
|
977
|
+
Kleber tree node with weight [2, 1, 2] and upwards edge root [0, 1, 0]
|
|
978
|
+
Kleber tree node with weight [0, 3, 0] and upwards edge root [1, 2, 1]
|
|
979
|
+
Kleber tree node with weight [1, 1, 1] and upwards edge root [0, 1, 0]
|
|
980
|
+
Kleber tree node with weight [0, 1, 0] and upwards edge root [1, 2, 1]
|
|
981
|
+
"""
|
|
982
|
+
if cur is None:
|
|
983
|
+
cur = self.root
|
|
984
|
+
|
|
985
|
+
yield cur
|
|
986
|
+
|
|
987
|
+
for child in cur.children:
|
|
988
|
+
yield from self._depth_first_iter(child)
|
|
989
|
+
|
|
990
|
+
__iter__ = breadth_first_iter
|
|
991
|
+
|
|
992
|
+
def _repr_(self):
|
|
993
|
+
"""
|
|
994
|
+
Return a text representation of this Kleber tree.
|
|
995
|
+
|
|
996
|
+
EXAMPLES::
|
|
997
|
+
|
|
998
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
999
|
+
sage: KleberTree(['D', 4, 1], [[2, 2]]) # indirect doctest
|
|
1000
|
+
Kleber tree of Cartan type ['D', 4, 1] and B = ((2, 2),)
|
|
1001
|
+
"""
|
|
1002
|
+
return "Kleber tree of Cartan type %s and B = %s" % (repr(self._cartan_type), self.B)
|
|
1003
|
+
|
|
1004
|
+
def cartan_type(self):
|
|
1005
|
+
r"""
|
|
1006
|
+
Return the Cartan type of this Kleber tree.
|
|
1007
|
+
|
|
1008
|
+
EXAMPLES::
|
|
1009
|
+
|
|
1010
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
1011
|
+
sage: KT = KleberTree(['A', 3, 1], [[1,1]])
|
|
1012
|
+
sage: KT.cartan_type()
|
|
1013
|
+
['A', 3, 1]
|
|
1014
|
+
"""
|
|
1015
|
+
return self._cartan_type
|
|
1016
|
+
|
|
1017
|
+
def digraph(self):
|
|
1018
|
+
r"""
|
|
1019
|
+
Return a DiGraph representation of this Kleber tree.
|
|
1020
|
+
|
|
1021
|
+
EXAMPLES::
|
|
1022
|
+
|
|
1023
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
1024
|
+
sage: KT = KleberTree(['D', 4, 1], [[2, 2]])
|
|
1025
|
+
sage: KT.digraph()
|
|
1026
|
+
Digraph on 3 vertices
|
|
1027
|
+
"""
|
|
1028
|
+
d = {}
|
|
1029
|
+
for x in self.breadth_first_iter():
|
|
1030
|
+
d[x] = {}
|
|
1031
|
+
if x.parent_node is None:
|
|
1032
|
+
continue
|
|
1033
|
+
d[x][x.parent_node] = tuple(x.up_root.to_vector())
|
|
1034
|
+
G = DiGraph(d)
|
|
1035
|
+
|
|
1036
|
+
if have_dot2tex():
|
|
1037
|
+
G.set_latex_options(format='dot2tex', edge_labels=True)
|
|
1038
|
+
return G
|
|
1039
|
+
|
|
1040
|
+
def plot(self, **options):
|
|
1041
|
+
"""
|
|
1042
|
+
Return the plot of ``self`` as a directed graph.
|
|
1043
|
+
|
|
1044
|
+
EXAMPLES::
|
|
1045
|
+
|
|
1046
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
1047
|
+
sage: KT = KleberTree(['D', 4, 1], [[2, 2]])
|
|
1048
|
+
sage: print(KT.plot()) # needs sage.plot
|
|
1049
|
+
Graphics object consisting of 8 graphics primitives
|
|
1050
|
+
"""
|
|
1051
|
+
return self.digraph().plot(edge_labels=True, vertex_size=0, **options)
|
|
1052
|
+
|
|
1053
|
+
def _element_constructor_(self, node_weight, dominant_root, parent_node=None):
|
|
1054
|
+
"""
|
|
1055
|
+
Construct a Kleber tree node.
|
|
1056
|
+
|
|
1057
|
+
EXAMPLES::
|
|
1058
|
+
|
|
1059
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree
|
|
1060
|
+
sage: RS = RootSystem(['A', 2])
|
|
1061
|
+
sage: WS = RS.weight_lattice()
|
|
1062
|
+
sage: R = RS.root_lattice()
|
|
1063
|
+
sage: KT = KleberTree(['A', 2, 1], [[1,1]])
|
|
1064
|
+
sage: root = KT(WS.sum_of_terms([(1,5), (2,2)]), R.zero()); root # indirect doctest
|
|
1065
|
+
Kleber tree node with weight [5, 2] and upwards edge root [0, 0]
|
|
1066
|
+
sage: child = KT(WS.sum_of_terms([(1,5), (2,1)]), R.zero(), root); child # indirect doctest
|
|
1067
|
+
Kleber tree node with weight [5, 1] and upwards edge root [0, 0]
|
|
1068
|
+
sage: child.parent_node
|
|
1069
|
+
Kleber tree node with weight [5, 2] and upwards edge root [0, 0]
|
|
1070
|
+
"""
|
|
1071
|
+
return self.element_class(self, node_weight, dominant_root, parent_node)
|
|
1072
|
+
|
|
1073
|
+
Element = KleberTreeNode
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
class VirtualKleberTree(KleberTree):
|
|
1077
|
+
r"""
|
|
1078
|
+
A virtual Kleber tree.
|
|
1079
|
+
|
|
1080
|
+
We can use a modified version of the Kleber algorithm called the virtual
|
|
1081
|
+
Kleber algorithm [OSS03]_ to compute all admissible rigged configurations
|
|
1082
|
+
for non-simply-laced types. This uses the following embeddings
|
|
1083
|
+
into the simply-laced types:
|
|
1084
|
+
|
|
1085
|
+
.. MATH::
|
|
1086
|
+
|
|
1087
|
+
C_n^{(1)}, A_{2n}^{(2)}, A_{2n}^{(2)\dagger}, D_{n+1}^{(2)}
|
|
1088
|
+
\hookrightarrow A_{2n-1}^{(1)}
|
|
1089
|
+
|
|
1090
|
+
A_{2n-1}^{(2)}, B_n^{(1)} \hookrightarrow D_{n+1}^{(1)}
|
|
1091
|
+
|
|
1092
|
+
E_6^{(2)}, F_4^{(1)} \hookrightarrow E_6^{(1)}
|
|
1093
|
+
|
|
1094
|
+
D_4^{(3)}, G_2^{(1)} \hookrightarrow D_4^{(1)}
|
|
1095
|
+
|
|
1096
|
+
One then selects the subset of admissible nodes which are translates of
|
|
1097
|
+
the virtual requirements. In the graph, the selected nodes are indicated
|
|
1098
|
+
by brackets `[]`.
|
|
1099
|
+
|
|
1100
|
+
.. NOTE::
|
|
1101
|
+
|
|
1102
|
+
Because these are virtual nodes, all information is given
|
|
1103
|
+
in the corresponding simply-laced type.
|
|
1104
|
+
|
|
1105
|
+
.. SEEALSO::
|
|
1106
|
+
|
|
1107
|
+
For more on the Kleber algorithm, see :class:`KleberTree`.
|
|
1108
|
+
|
|
1109
|
+
REFERENCES:
|
|
1110
|
+
|
|
1111
|
+
.. [OSS03] Masato Okado, Anne Schilling, and Mark Shimozono.
|
|
1112
|
+
*Virtual crystals and Klebers algorithm*. Commun. Math. Phys. **238**
|
|
1113
|
+
(2003). 187-209. :arxiv:`math.QA/0209082`.
|
|
1114
|
+
|
|
1115
|
+
INPUT:
|
|
1116
|
+
|
|
1117
|
+
- ``cartan_type`` -- an affine non-simply-laced Cartan type
|
|
1118
|
+
|
|
1119
|
+
- ``B`` -- list of dimensions of rectangles by `[r, c]`
|
|
1120
|
+
where `r` is the number of rows and `c` is the number of columns
|
|
1121
|
+
|
|
1122
|
+
EXAMPLES::
|
|
1123
|
+
|
|
1124
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree
|
|
1125
|
+
sage: KT = VirtualKleberTree(['C', 4, 1], [[2,2]])
|
|
1126
|
+
sage: KT.cardinality()
|
|
1127
|
+
3
|
|
1128
|
+
sage: KT.base_tree().cardinality()
|
|
1129
|
+
6
|
|
1130
|
+
sage: KT = VirtualKleberTree(['C', 4, 1], [[4,5]])
|
|
1131
|
+
sage: KT.cardinality()
|
|
1132
|
+
1
|
|
1133
|
+
sage: KT = VirtualKleberTree(['D', 5, 2], [[2,1], [1,1]])
|
|
1134
|
+
sage: KT.cardinality()
|
|
1135
|
+
8
|
|
1136
|
+
sage: KT = VirtualKleberTree(CartanType(['A', 4, 2]).dual(), [[1,1], [2,2]])
|
|
1137
|
+
sage: KT.cardinality()
|
|
1138
|
+
15
|
|
1139
|
+
"""
|
|
1140
|
+
@staticmethod
|
|
1141
|
+
def __classcall_private__(cls, cartan_type, B):
|
|
1142
|
+
"""
|
|
1143
|
+
Normalize the input arguments to ensure unique representation.
|
|
1144
|
+
|
|
1145
|
+
EXAMPLES::
|
|
1146
|
+
|
|
1147
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree
|
|
1148
|
+
sage: KT1 = VirtualKleberTree(CartanType(['C',3,1]).as_folding(), [[2,2]])
|
|
1149
|
+
sage: KT2 = VirtualKleberTree(CartanType(['C',3,1]), [(2,2)])
|
|
1150
|
+
sage: KT3 = VirtualKleberTree(['C',3,1], ((2,2),))
|
|
1151
|
+
sage: KT2 is KT1, KT3 is KT1
|
|
1152
|
+
(True, True)
|
|
1153
|
+
"""
|
|
1154
|
+
cartan_type = CartanType(cartan_type)
|
|
1155
|
+
# Standardize B input into a tuple of tuples
|
|
1156
|
+
B = tuple(map(tuple, B))
|
|
1157
|
+
if cartan_type.type() == 'BC' or cartan_type.dual().type() == 'BC':
|
|
1158
|
+
# Types A_{2n}^{(2)} and its dual
|
|
1159
|
+
return KleberTreeTypeA2Even(cartan_type, B)
|
|
1160
|
+
if cartan_type.classical().is_simply_laced():
|
|
1161
|
+
raise ValueError("use KleberTree for simply-laced types")
|
|
1162
|
+
return super().__classcall__(cls, cartan_type, B)
|
|
1163
|
+
|
|
1164
|
+
def __init__(self, cartan_type, B):
|
|
1165
|
+
"""
|
|
1166
|
+
Initialize ``self``.
|
|
1167
|
+
|
|
1168
|
+
EXAMPLES::
|
|
1169
|
+
|
|
1170
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree
|
|
1171
|
+
sage: KT = VirtualKleberTree(['C',4,1], [[2,2]])
|
|
1172
|
+
sage: TestSuite(KT).run(skip='_test_elements')
|
|
1173
|
+
"""
|
|
1174
|
+
self._folded_ct = cartan_type.as_folding()
|
|
1175
|
+
self.base_dims = B
|
|
1176
|
+
sigma = self._folded_ct.folding_orbit()
|
|
1177
|
+
gamma = self._folded_ct.scaling_factors()
|
|
1178
|
+
classical_ct = self._folded_ct.folding_of().classical()
|
|
1179
|
+
virtual_dims = [[i, s * gamma[r]]
|
|
1180
|
+
for r, s in B for i in sigma[r]]
|
|
1181
|
+
|
|
1182
|
+
KleberTree.__init__(self, cartan_type, virtual_dims, classical_ct)
|
|
1183
|
+
|
|
1184
|
+
def _repr_(self):
|
|
1185
|
+
"""
|
|
1186
|
+
Return a text representation of this Kleber tree.
|
|
1187
|
+
|
|
1188
|
+
EXAMPLES::
|
|
1189
|
+
|
|
1190
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree
|
|
1191
|
+
sage: VirtualKleberTree(['C', 4, 1], [[2, 2]])
|
|
1192
|
+
Virtual Kleber tree of Cartan type ['C', 4, 1] and B = ((2, 2),)
|
|
1193
|
+
"""
|
|
1194
|
+
return "Virtual Kleber tree of Cartan type %s and B = %s" % (repr(self._cartan_type), self.base_dims)
|
|
1195
|
+
|
|
1196
|
+
def _prune(self, new_child, depth):
|
|
1197
|
+
r"""
|
|
1198
|
+
Return ``True`` if we are to prune the tree at ``new_child``.
|
|
1199
|
+
|
|
1200
|
+
Suppose `\lambda` is the weight of the child we want to add at depth
|
|
1201
|
+
`\ell`. We prune ``new_child`` if either of the following conditions
|
|
1202
|
+
are not satisfied:
|
|
1203
|
+
|
|
1204
|
+
1. `(\lambda \mid \alpha_a) = (\lambda \mid \alpha_b)` if `a` and `b`
|
|
1205
|
+
are in the same `\sigma`-orbit.
|
|
1206
|
+
2. If `\ell - 1 \notin \gamma_a \ZZ`, then the `a`-th component of
|
|
1207
|
+
``up_root`` of ``new_child`` must equal the `a`-th component of
|
|
1208
|
+
``up_root`` of its ``parent_node``. Note that from condition 1,
|
|
1209
|
+
we only need to check one such `a` from each `\sigma`-orbit.
|
|
1210
|
+
|
|
1211
|
+
These conditions are equivalent to Definition 4.1 in [OSS03]_.
|
|
1212
|
+
|
|
1213
|
+
EXAMPLES::
|
|
1214
|
+
|
|
1215
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree
|
|
1216
|
+
sage: RS = RootSystem(['A', 3])
|
|
1217
|
+
sage: WS = RS.weight_lattice()
|
|
1218
|
+
sage: R = RS.root_lattice()
|
|
1219
|
+
sage: KT = VirtualKleberTree(['C',2,1], [[1,2],[1,1],[2,1]])
|
|
1220
|
+
sage: x = KT(WS.sum_of_terms([(1,1), (2,1), (3,3)]), R.sum_of_terms([(1,2),(2,2),(3,1)]), KT.root)
|
|
1221
|
+
sage: KT._prune(x, 1)
|
|
1222
|
+
True
|
|
1223
|
+
"""
|
|
1224
|
+
sigma = self._folded_ct._orbit
|
|
1225
|
+
for orbit in sigma[1:]:
|
|
1226
|
+
start = new_child.weight[orbit[0]]
|
|
1227
|
+
if any(new_child.weight[i] != start for i in orbit[1:]):
|
|
1228
|
+
return True
|
|
1229
|
+
gamma = self._folded_ct.scaling_factors()
|
|
1230
|
+
for a in range(1, len(gamma)):
|
|
1231
|
+
s = sigma[a][0]
|
|
1232
|
+
if ((depth - 1) % gamma[a] != 0 and
|
|
1233
|
+
new_child.up_root[s] != new_child.parent_node.up_root[s]):
|
|
1234
|
+
return True
|
|
1235
|
+
return False
|
|
1236
|
+
|
|
1237
|
+
def breadth_first_iter(self, all_nodes=False):
|
|
1238
|
+
r"""
|
|
1239
|
+
Iterate over all nodes in the tree following a breadth-first traversal.
|
|
1240
|
+
|
|
1241
|
+
INPUT:
|
|
1242
|
+
|
|
1243
|
+
- ``all_nodes`` -- boolean (default: ``False``); if ``True``, output all
|
|
1244
|
+
nodes in the tree
|
|
1245
|
+
|
|
1246
|
+
EXAMPLES::
|
|
1247
|
+
|
|
1248
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree
|
|
1249
|
+
sage: KT = VirtualKleberTree(['C', 2, 1], [[1,1], [2,1]])
|
|
1250
|
+
sage: for x in KT.breadth_first_iter(): x
|
|
1251
|
+
Kleber tree node with weight [1, 2, 1] and upwards edge root [0, 0, 0]
|
|
1252
|
+
Kleber tree node with weight [1, 0, 1] and upwards edge root [0, 1, 0]
|
|
1253
|
+
sage: for x in KT.breadth_first_iter(True): x
|
|
1254
|
+
Kleber tree node with weight [1, 2, 1] and upwards edge root [0, 0, 0]
|
|
1255
|
+
Kleber tree node with weight [0, 2, 0] and upwards edge root [1, 1, 1]
|
|
1256
|
+
Kleber tree node with weight [1, 0, 1] and upwards edge root [0, 1, 0]
|
|
1257
|
+
"""
|
|
1258
|
+
s_factors = self._folded_ct.scaling_factors()
|
|
1259
|
+
gamma = max(s_factors)
|
|
1260
|
+
# Subtract 1 for indexing
|
|
1261
|
+
if gamma > 1:
|
|
1262
|
+
sigma = self._folded_ct.folding_orbit()
|
|
1263
|
+
L = [sigma[a][0] for a in range(1, len(s_factors))
|
|
1264
|
+
if s_factors[a] == gamma]
|
|
1265
|
+
else:
|
|
1266
|
+
L = []
|
|
1267
|
+
|
|
1268
|
+
for x in KleberTree.breadth_first_iter(self):
|
|
1269
|
+
if all_nodes or (x.depth) % gamma == 0 or all(x.up_root[a] == 0 for a in L):
|
|
1270
|
+
yield x
|
|
1271
|
+
|
|
1272
|
+
def depth_first_iter(self, all_nodes=False):
|
|
1273
|
+
r"""
|
|
1274
|
+
Iterate (recursively) over the nodes in the tree following a
|
|
1275
|
+
depth-first traversal.
|
|
1276
|
+
|
|
1277
|
+
INPUT:
|
|
1278
|
+
|
|
1279
|
+
- ``all_nodes`` -- boolean (default: ``False``); if ``True``, output all
|
|
1280
|
+
nodes in the tree
|
|
1281
|
+
|
|
1282
|
+
EXAMPLES::
|
|
1283
|
+
|
|
1284
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree
|
|
1285
|
+
sage: KT = VirtualKleberTree(['C', 2, 1], [[1,1], [2,1]])
|
|
1286
|
+
sage: for x in KT.depth_first_iter(): x
|
|
1287
|
+
Kleber tree node with weight [1, 2, 1] and upwards edge root [0, 0, 0]
|
|
1288
|
+
Kleber tree node with weight [1, 0, 1] and upwards edge root [0, 1, 0]
|
|
1289
|
+
sage: for x in KT.depth_first_iter(True): x
|
|
1290
|
+
Kleber tree node with weight [1, 2, 1] and upwards edge root [0, 0, 0]
|
|
1291
|
+
Kleber tree node with weight [0, 2, 0] and upwards edge root [1, 1, 1]
|
|
1292
|
+
Kleber tree node with weight [1, 0, 1] and upwards edge root [0, 1, 0]
|
|
1293
|
+
"""
|
|
1294
|
+
s_factors = self._folded_ct.scaling_factors()
|
|
1295
|
+
gamma = max(s_factors)
|
|
1296
|
+
# Subtract 1 for indexing
|
|
1297
|
+
if gamma > 1:
|
|
1298
|
+
sigma = self._folded_ct.folding_orbit()
|
|
1299
|
+
L = [sigma[a][0] for a in range(1, len(s_factors))
|
|
1300
|
+
if s_factors[a] == gamma]
|
|
1301
|
+
else:
|
|
1302
|
+
L = []
|
|
1303
|
+
|
|
1304
|
+
for x in self._depth_first_iter(None):
|
|
1305
|
+
if all_nodes or (x.depth) % gamma == 0 or all(x.up_root[a] == 0 for a in L):
|
|
1306
|
+
yield x
|
|
1307
|
+
|
|
1308
|
+
__iter__ = breadth_first_iter
|
|
1309
|
+
|
|
1310
|
+
def base_tree(self):
|
|
1311
|
+
"""
|
|
1312
|
+
Return the underlying virtual Kleber tree associated to ``self``.
|
|
1313
|
+
|
|
1314
|
+
EXAMPLES::
|
|
1315
|
+
|
|
1316
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree
|
|
1317
|
+
sage: KT = VirtualKleberTree(['C', 4, 1], [[2,2]])
|
|
1318
|
+
sage: KT.base_tree()
|
|
1319
|
+
Kleber tree of Cartan type ['A', 7, 1] and B = ((2, 2), (6, 2))
|
|
1320
|
+
"""
|
|
1321
|
+
return KleberTree(self._folded_ct.folding_of(), self.B)
|
|
1322
|
+
|
|
1323
|
+
|
|
1324
|
+
class KleberTreeTypeA2Even(VirtualKleberTree):
|
|
1325
|
+
r"""
|
|
1326
|
+
Kleber tree for types `A_{2n}^{(2)}` and `A_{2n}^{(2)\dagger}`.
|
|
1327
|
+
|
|
1328
|
+
Note that here for `A_{2n}^{(2)}` we use `\tilde{\gamma}_a` in place of
|
|
1329
|
+
`\gamma_a` in constructing the virtual Kleber tree, and so we end up
|
|
1330
|
+
selecting all nodes since `\tilde{\gamma}_a = 1` for all `a \in
|
|
1331
|
+
\overline{I}`. For type `A_{2n}^{(2)\dagger}`, we have `\gamma_a = 1`
|
|
1332
|
+
for all `a \in \overline{I}`.
|
|
1333
|
+
|
|
1334
|
+
.. SEEALSO::
|
|
1335
|
+
|
|
1336
|
+
:class:`VirtualKleberTree`
|
|
1337
|
+
"""
|
|
1338
|
+
@staticmethod
|
|
1339
|
+
def __classcall_private__(cls, cartan_type, B):
|
|
1340
|
+
"""
|
|
1341
|
+
Normalize the input arguments to ensure unique representation.
|
|
1342
|
+
|
|
1343
|
+
EXAMPLES::
|
|
1344
|
+
|
|
1345
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree
|
|
1346
|
+
sage: KT1 = VirtualKleberTree(CartanType(['A',6,2]), [[2,2]])
|
|
1347
|
+
sage: KT2 = VirtualKleberTree(['A',6,2], [(2,2)])
|
|
1348
|
+
sage: KT3 = VirtualKleberTree(['A',6,2], ((2,2),))
|
|
1349
|
+
sage: KT2 is KT1, KT3 is KT1
|
|
1350
|
+
(True, True)
|
|
1351
|
+
"""
|
|
1352
|
+
cartan_type = CartanType(cartan_type)
|
|
1353
|
+
# Standardize B input into a tuple of tuples
|
|
1354
|
+
B = tuple(map(tuple, B))
|
|
1355
|
+
return super().__classcall__(cls, cartan_type, B)
|
|
1356
|
+
|
|
1357
|
+
def __init__(self, cartan_type, B):
|
|
1358
|
+
"""
|
|
1359
|
+
Initialize ``self``.
|
|
1360
|
+
|
|
1361
|
+
EXAMPLES::
|
|
1362
|
+
|
|
1363
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree
|
|
1364
|
+
sage: KT = VirtualKleberTree(['A',6,2], [[2,2]]); KT
|
|
1365
|
+
Virtual Kleber tree of Cartan type ['BC', 3, 2] and B = ((2, 2),)
|
|
1366
|
+
sage: TestSuite(KT).run(skip='_test_elements')
|
|
1367
|
+
"""
|
|
1368
|
+
self._folded_ct = cartan_type.as_folding()
|
|
1369
|
+
virtual_dims = []
|
|
1370
|
+
n = cartan_type.classical().rank()
|
|
1371
|
+
self.base_dims = B
|
|
1372
|
+
sigma = self._folded_ct.folding_orbit()
|
|
1373
|
+
classical_ct = self._folded_ct.folding_of().classical()
|
|
1374
|
+
for r, s in B:
|
|
1375
|
+
if r == n:
|
|
1376
|
+
virtual_dims.extend([[n, s], [n, s]])
|
|
1377
|
+
else:
|
|
1378
|
+
virtual_dims.extend([i, s] for i in sigma[r])
|
|
1379
|
+
|
|
1380
|
+
KleberTree.__init__(self, cartan_type, virtual_dims, classical_ct)
|
|
1381
|
+
|
|
1382
|
+
def __iter__(self):
|
|
1383
|
+
"""
|
|
1384
|
+
Iterate over all of the nodes.
|
|
1385
|
+
|
|
1386
|
+
EXAMPLES::
|
|
1387
|
+
|
|
1388
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree
|
|
1389
|
+
sage: KT = VirtualKleberTree(['A',6,2], [[2,2]])
|
|
1390
|
+
sage: L = [x for x in KT]
|
|
1391
|
+
sage: len(L) == KT.cardinality()
|
|
1392
|
+
True
|
|
1393
|
+
"""
|
|
1394
|
+
return KleberTree.__iter__(self)
|
|
1395
|
+
|
|
1396
|
+
def _prune(self, new_child, depth):
|
|
1397
|
+
r"""
|
|
1398
|
+
Return ``True`` if we are to prune the tree at ``new_child``.
|
|
1399
|
+
|
|
1400
|
+
Suppose `\lambda` is the weight of the child we want to add at
|
|
1401
|
+
depth `\ell`. We prune ``new_child`` if `(\lambda \mid \alpha_a)
|
|
1402
|
+
\neq (\lambda \mid \alpha_b)` if `a` and `b` are in the same
|
|
1403
|
+
`\sigma`-orbit.
|
|
1404
|
+
|
|
1405
|
+
These conditions are equivalent to Definition 4.1 in [OSS03]_ by using
|
|
1406
|
+
`\tilde{\gamma}`, and since `\tilde{\gamma}_a = 1` for all `a`, the
|
|
1407
|
+
second condition becomes vacuous.
|
|
1408
|
+
|
|
1409
|
+
EXAMPLES::
|
|
1410
|
+
|
|
1411
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree
|
|
1412
|
+
sage: RS = RootSystem(['A', 5])
|
|
1413
|
+
sage: WS = RS.weight_lattice()
|
|
1414
|
+
sage: R = RS.root_lattice()
|
|
1415
|
+
sage: KT = VirtualKleberTree(['A',6,2], [[2,2]])
|
|
1416
|
+
sage: x = KT(WS.sum_of_terms([(2,1), (4,1)]), R.sum_of_terms([(1,1),(2,2),(3,2),(4,2),(5,1)]), KT.root)
|
|
1417
|
+
sage: KT._prune(x, 1)
|
|
1418
|
+
False
|
|
1419
|
+
"""
|
|
1420
|
+
sigma = self._folded_ct._orbit
|
|
1421
|
+
for orbit in sigma[1:]:
|
|
1422
|
+
start = new_child.weight[orbit[0]]
|
|
1423
|
+
for i in orbit[1:]:
|
|
1424
|
+
if new_child.weight[i] != start:
|
|
1425
|
+
return True
|
|
1426
|
+
return False
|
|
1427
|
+
|
|
1428
|
+
def breadth_first_iter(self, all_nodes=False):
|
|
1429
|
+
r"""
|
|
1430
|
+
Iterate over all nodes in the tree following a breadth-first traversal.
|
|
1431
|
+
|
|
1432
|
+
INPUT:
|
|
1433
|
+
|
|
1434
|
+
- ``all_nodes`` -- boolean (default: ``False``); if ``True``, output all
|
|
1435
|
+
nodes in the tree
|
|
1436
|
+
|
|
1437
|
+
EXAMPLES::
|
|
1438
|
+
|
|
1439
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree
|
|
1440
|
+
sage: KT = VirtualKleberTree(['A', 4, 2], [[2,1]])
|
|
1441
|
+
sage: for x in KT.breadth_first_iter(): x
|
|
1442
|
+
Kleber tree node with weight [0, 2, 0] and upwards edge root [0, 0, 0]
|
|
1443
|
+
Kleber tree node with weight [1, 0, 1] and upwards edge root [0, 1, 0]
|
|
1444
|
+
Kleber tree node with weight [0, 0, 0] and upwards edge root [1, 2, 1]
|
|
1445
|
+
sage: for x in KT.breadth_first_iter(True): x
|
|
1446
|
+
Kleber tree node with weight [0, 2, 0] and upwards edge root [0, 0, 0]
|
|
1447
|
+
Kleber tree node with weight [1, 0, 1] and upwards edge root [0, 1, 0]
|
|
1448
|
+
Kleber tree node with weight [0, 0, 0] and upwards edge root [1, 2, 1]
|
|
1449
|
+
"""
|
|
1450
|
+
return KleberTree.breadth_first_iter(self)
|
|
1451
|
+
|
|
1452
|
+
def depth_first_iter(self, all_nodes=False):
|
|
1453
|
+
r"""
|
|
1454
|
+
Iterate (recursively) over the nodes in the tree following a
|
|
1455
|
+
depth-first traversal.
|
|
1456
|
+
|
|
1457
|
+
INPUT:
|
|
1458
|
+
|
|
1459
|
+
- ``all_nodes`` -- boolean (default: ``False``); if ``True``, output all
|
|
1460
|
+
nodes in the tree
|
|
1461
|
+
|
|
1462
|
+
EXAMPLES::
|
|
1463
|
+
|
|
1464
|
+
sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree
|
|
1465
|
+
sage: KT = VirtualKleberTree(['A', 4, 2], [[2,1]])
|
|
1466
|
+
sage: for x in KT.depth_first_iter(): x
|
|
1467
|
+
Kleber tree node with weight [0, 2, 0] and upwards edge root [0, 0, 0]
|
|
1468
|
+
Kleber tree node with weight [1, 0, 1] and upwards edge root [0, 1, 0]
|
|
1469
|
+
Kleber tree node with weight [0, 0, 0] and upwards edge root [1, 2, 1]
|
|
1470
|
+
sage: for x in KT.depth_first_iter(True): x
|
|
1471
|
+
Kleber tree node with weight [0, 2, 0] and upwards edge root [0, 0, 0]
|
|
1472
|
+
Kleber tree node with weight [1, 0, 1] and upwards edge root [0, 1, 0]
|
|
1473
|
+
Kleber tree node with weight [0, 0, 0] and upwards edge root [1, 2, 1]
|
|
1474
|
+
"""
|
|
1475
|
+
return KleberTree.depth_first_iter(self)
|