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,3520 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
# sage.doctest: needs sage.combinat sage.groups sage.modules
|
|
3
|
+
r"""
|
|
4
|
+
Cubic Hecke Algebras
|
|
5
|
+
|
|
6
|
+
We consider the factors of the group algebra of the Artin braid groups
|
|
7
|
+
such that the images `s_i` of the braid generators satisfy a cubic equation:
|
|
8
|
+
|
|
9
|
+
.. MATH::
|
|
10
|
+
|
|
11
|
+
s_i^3 = u s_i^2 - v s_i + w.
|
|
12
|
+
|
|
13
|
+
Here `u, v, w` are elements in an arbitrary integral domain and `i` is a
|
|
14
|
+
positive integer less than `n`, the number of the braid group's strands.
|
|
15
|
+
By the analogue to the *Iwahori Hecke algebras* (see
|
|
16
|
+
:class:`~sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra`), in which the
|
|
17
|
+
braid generators satisfy a quadratic relation these algebras have been called
|
|
18
|
+
*cubic Hecke algebras*. The relations inherited from the braid group are:
|
|
19
|
+
|
|
20
|
+
.. MATH::
|
|
21
|
+
|
|
22
|
+
s_i s_{i+1} s_i = s_{i+1} s_i s_{i+1} \text{ for } 1 \leq i < n - 1
|
|
23
|
+
\mbox{ and } s_i s_j = s_j s_i \text{ for } 1 \leq i < j - 1 < n - 1.
|
|
24
|
+
|
|
25
|
+
The algebra epimorphism from the braid group algebra over the same base ring is
|
|
26
|
+
realized inside the element constructor of the present class, for example in the
|
|
27
|
+
case of the 3 strand cubic Hecke algebra::
|
|
28
|
+
|
|
29
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
30
|
+
sage: BG3 = CHA3.braid_group()
|
|
31
|
+
sage: braid = BG3((1,2,-1,2,2,-1)); braid
|
|
32
|
+
c0*c1*c0^-1*c1^2*c0^-1
|
|
33
|
+
sage: braid_image = CHA3(braid); braid_image
|
|
34
|
+
u*c1*c0^-1*c1 + u*v*c0*c1^-1*c0^-1 - u^2*c0^-1*c1
|
|
35
|
+
+ ((u^2*v-v^2)/w)*c0*c1*c0^-1 + ((u^2-v)/w)*c0*c1*c0
|
|
36
|
+
- ((u^3-u*v)/w)*c0*c1 - (u*v-w)*c1^-1
|
|
37
|
+
|
|
38
|
+
If the ring elements `u, v, w` (which will be called the *cubic equation
|
|
39
|
+
parameters* in the sequel) are taken to be `u = v = 0, w = 1` the cubic Hecke
|
|
40
|
+
algebra specializes to the group algebra of the *cubic braid group*, which is
|
|
41
|
+
the factor group of the Artin braid group under setting the generators order
|
|
42
|
+
to be three. These groups can be obtained by
|
|
43
|
+
:meth:`CubicHeckeAlgebra.cubic_braid_group`.
|
|
44
|
+
|
|
45
|
+
It is well known, that these algebras are free of finite rank as long as the
|
|
46
|
+
number of braid generators is less than six and infinite dimensional else wise.
|
|
47
|
+
In the former (non trivial) cases they are also known as *cyclotomic Hecke
|
|
48
|
+
algebras* corresponding to the complex reflection groups having Shepard-Todd
|
|
49
|
+
number `4`, `25` and `32`.
|
|
50
|
+
|
|
51
|
+
Since the *Broué, Malle, Rouquiere* conjecture has been proved (for references
|
|
52
|
+
of these cases see [Mar2012]_) there exists a finite free basis of the cubic
|
|
53
|
+
Hecke algebra which is in bijection to the cubic braid group and compatible
|
|
54
|
+
with the specialization to the cubic braid group algebra as explained above.
|
|
55
|
+
|
|
56
|
+
For the algebras corresponding to braid groups of less than five strands such
|
|
57
|
+
a basis has been calculated by Ivan Marin. This one is used here. In the case
|
|
58
|
+
of 5 strands such a basis is not available, right now. Instead the elements
|
|
59
|
+
of the cubic braid group class themselves are used as basis elements. This
|
|
60
|
+
is also the case when the cubic braid group is infinite, even though it is
|
|
61
|
+
not known if these elements span all of the cubic Hecke algebra.
|
|
62
|
+
|
|
63
|
+
Accordingly, be aware that the module embedding of the group algebra of the
|
|
64
|
+
cubicbraid groups is known to be an isomorphism of free modules only in the
|
|
65
|
+
cases of less than five strands.
|
|
66
|
+
|
|
67
|
+
EXAMPLES:
|
|
68
|
+
|
|
69
|
+
Consider the obstruction ``b`` of the *triple quadratic algebra* from Section 2.6
|
|
70
|
+
of [Mar2018]_. We verify that the third power of it is a scalar multiple
|
|
71
|
+
of itself (explicitly ``2*w^2`` times the *Schur element* of the three
|
|
72
|
+
dimensional irreducible representation)::
|
|
73
|
+
|
|
74
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
75
|
+
sage: c1, c2 = CHA3.gens()
|
|
76
|
+
sage: b = c1^2*c2 - c2*c1^2 - c1*c2^2 + c2^2*c1; b
|
|
77
|
+
w*c0^-1*c1 - w*c0*c1^-1 - w*c1*c0^-1 + w*c1^-1*c0
|
|
78
|
+
sage: b2 = b*b
|
|
79
|
+
sage: b3 = b2*b
|
|
80
|
+
sage: BR = CHA3.base_ring()
|
|
81
|
+
sage: ER = CHA3.extension_ring()
|
|
82
|
+
sage: u, v, w = BR.gens()
|
|
83
|
+
sage: f = BR(b3.coefficients()[0]/w)
|
|
84
|
+
sage: try:
|
|
85
|
+
....: sh = CHA3.schur_element(CHA3.irred_repr.W3_111)
|
|
86
|
+
....: except NotImplementedError: # for the case GAP3 / CHEVIE not available
|
|
87
|
+
....: sh = ER(f/(2*w^2))
|
|
88
|
+
sage: ER(f/(2*w^2)) == sh
|
|
89
|
+
True
|
|
90
|
+
sage: b3 == f*b
|
|
91
|
+
True
|
|
92
|
+
|
|
93
|
+
Defining the cubic Hecke algebra on 6 strands will need some seconds for
|
|
94
|
+
initializing. However, you can do calculations inside the infinite
|
|
95
|
+
algebra as well::
|
|
96
|
+
|
|
97
|
+
sage: # optional - database_cubic_hecke
|
|
98
|
+
sage: CHA6 = algebras.CubicHecke(6)
|
|
99
|
+
sage: CHA6.inject_variables()
|
|
100
|
+
Defining c0, c1, c2, c3, c4
|
|
101
|
+
sage: s = c0*c1*c2*c3*c4; s
|
|
102
|
+
c0*c1*c2*c3*c4
|
|
103
|
+
sage: s^2
|
|
104
|
+
(c0*c1*c2*c3*c4)^2
|
|
105
|
+
sage: t = CHA6.an_element() * c4; t
|
|
106
|
+
(-w)*c0*c1^-1*c4 + v*c0*c2^-1*c4 + u*c2*c1*c4 + ((-v*w+u)/w)*c4
|
|
107
|
+
|
|
108
|
+
REFERENCES:
|
|
109
|
+
|
|
110
|
+
- [Mar2012]_
|
|
111
|
+
- [Mar2018]_
|
|
112
|
+
- [CM2012]_
|
|
113
|
+
|
|
114
|
+
AUTHORS:
|
|
115
|
+
|
|
116
|
+
- Sebastian Oehms May 2020: initial version
|
|
117
|
+
"""
|
|
118
|
+
# ###########################################################################
|
|
119
|
+
# Copyright (C) 2020 Sebastian Oehms <seb.oehms@gmail.com>
|
|
120
|
+
#
|
|
121
|
+
# This program is free software: you can redistribute it and/or modify
|
|
122
|
+
# it under the terms of the GNU General Public License as published by
|
|
123
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
124
|
+
# (at your option) any later version.
|
|
125
|
+
# https://www.gnu.org/licenses/
|
|
126
|
+
# ###########################################################################
|
|
127
|
+
from warnings import warn
|
|
128
|
+
|
|
129
|
+
from sage.combinat.free_module import CombinatorialFreeModule
|
|
130
|
+
from sage.misc.cachefunc import cached_method
|
|
131
|
+
from sage.misc.verbose import verbose
|
|
132
|
+
from sage.groups.cubic_braid import CubicBraidGroup
|
|
133
|
+
from sage.rings.integer_ring import ZZ
|
|
134
|
+
from sage.algebras.splitting_algebra import solve_with_extension
|
|
135
|
+
from sage.modules.free_module_element import vector
|
|
136
|
+
from sage.matrix.matrix_space import MatrixSpace
|
|
137
|
+
from sage.algebras.hecke_algebras.cubic_hecke_base_ring import CubicHeckeRingOfDefinition
|
|
138
|
+
from sage.algebras.hecke_algebras.cubic_hecke_matrix_rep import CubicHeckeMatrixSpace, AbsIrreducibeRep, RepresentationType
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
##############################################################################
|
|
142
|
+
#
|
|
143
|
+
# Class CubicHeckeElement (for elements)
|
|
144
|
+
#
|
|
145
|
+
##############################################################################
|
|
146
|
+
class CubicHeckeElement(CombinatorialFreeModule.Element):
|
|
147
|
+
r"""
|
|
148
|
+
An element of a :class:`CubicHeckeAlgebra`.
|
|
149
|
+
|
|
150
|
+
For more information see :class:`CubicHeckeAlgebra`.
|
|
151
|
+
|
|
152
|
+
EXAMPLES::
|
|
153
|
+
|
|
154
|
+
sage: CHA3s = algebras.CubicHecke('s1, s2'); CHA3s.an_element()
|
|
155
|
+
-w*s1*s2^-1 + v*s1 + u*s2 - ((v*w-u)/w)
|
|
156
|
+
sage: CHA3.<c1, c2> = algebras.CubicHecke(3)
|
|
157
|
+
sage: c1**3*~c2
|
|
158
|
+
u*w*c1^-1*c2^-1 + (u^2-v)*c1*c2^-1 - (u*v-w)*c2^-1
|
|
159
|
+
"""
|
|
160
|
+
# --------------------------------------------------------------------------
|
|
161
|
+
# Overloading inherited methods
|
|
162
|
+
# --------------------------------------------------------------------------
|
|
163
|
+
def __invert__(self):
|
|
164
|
+
r"""
|
|
165
|
+
Return inverse of ``self`` (if possible).
|
|
166
|
+
|
|
167
|
+
EXAMPLES::
|
|
168
|
+
|
|
169
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
170
|
+
sage: ele1 = CHA3((1,-2,1)); ele1
|
|
171
|
+
c0*c1^-1*c0
|
|
172
|
+
sage: ~ele1 # indirect doctest
|
|
173
|
+
c0^-1*c1*c0^-1
|
|
174
|
+
|
|
175
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
176
|
+
sage: x = CHA2.an_element(); x
|
|
177
|
+
v*c - ((v*w-u)/w)
|
|
178
|
+
sage: ~x
|
|
179
|
+
Traceback (most recent call last):
|
|
180
|
+
...
|
|
181
|
+
ValueError: cannot invert self (= v*c - ((v*w-u)/w))
|
|
182
|
+
"""
|
|
183
|
+
self_Tietze = self.Tietze()
|
|
184
|
+
|
|
185
|
+
if self_Tietze is None:
|
|
186
|
+
return super().__invert__()
|
|
187
|
+
|
|
188
|
+
inverse_Tietze = ()
|
|
189
|
+
len_self = len(self_Tietze)
|
|
190
|
+
|
|
191
|
+
inverse_Tietze = tuple([-1 * self_Tietze[len_self - i - 1]
|
|
192
|
+
for i in range(len_self)])
|
|
193
|
+
P = self.parent()
|
|
194
|
+
return P(inverse_Tietze)
|
|
195
|
+
|
|
196
|
+
def Tietze(self):
|
|
197
|
+
r"""
|
|
198
|
+
Return the Tietze presentation of ``self`` if ``self`` belongs to the
|
|
199
|
+
basis of its parent and ``None`` otherwise.
|
|
200
|
+
|
|
201
|
+
OUTPUT:
|
|
202
|
+
|
|
203
|
+
A tuple representing the pre image braid of ``self`` if ``self`` is a
|
|
204
|
+
monomial from the basis ``None`` else-wise
|
|
205
|
+
|
|
206
|
+
EXAMPLES::
|
|
207
|
+
|
|
208
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
209
|
+
sage: ele = CHA3.an_element(); ele
|
|
210
|
+
-w*c0*c1^-1 + v*c0 + u*c1 - ((v*w-u)/w)
|
|
211
|
+
sage: ele.Tietze() is None
|
|
212
|
+
True
|
|
213
|
+
sage: [CHA3(sp).Tietze() for sp in ele.support()]
|
|
214
|
+
[(), (1,), (1, -2), (2,)]
|
|
215
|
+
"""
|
|
216
|
+
vecd = self._monomial_coefficients
|
|
217
|
+
if len(vecd) != 1:
|
|
218
|
+
return None
|
|
219
|
+
ind, coeff = next(iter(vecd.items()))
|
|
220
|
+
if coeff.is_one():
|
|
221
|
+
return ind.Tietze()
|
|
222
|
+
|
|
223
|
+
def max_len(self):
|
|
224
|
+
r"""
|
|
225
|
+
Return the maximum of the length of Tietze expressions among the
|
|
226
|
+
support of ``self``.
|
|
227
|
+
|
|
228
|
+
EXAMPLES::
|
|
229
|
+
|
|
230
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
231
|
+
sage: ele = CHA3.an_element(); ele
|
|
232
|
+
-w*c0*c1^-1 + v*c0 + u*c1 - ((v*w-u)/w)
|
|
233
|
+
sage: ele.max_len()
|
|
234
|
+
2
|
|
235
|
+
"""
|
|
236
|
+
return max(len(bas_ele.Tietze()) for bas_ele in self.support())
|
|
237
|
+
|
|
238
|
+
def braid_group_algebra_pre_image(self):
|
|
239
|
+
r"""
|
|
240
|
+
Return a pre image of ``self`` in the group algebra of the braid group
|
|
241
|
+
(with respect to the basis given by Ivan Marin).
|
|
242
|
+
|
|
243
|
+
OUTPUT:
|
|
244
|
+
|
|
245
|
+
The pre image of ``self`` as instance of the element class of the group
|
|
246
|
+
algebra of the BraidGroup
|
|
247
|
+
|
|
248
|
+
EXAMPLES::
|
|
249
|
+
|
|
250
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
251
|
+
sage: ele = CHA3.an_element(); ele
|
|
252
|
+
-w*c0*c1^-1 + v*c0 + u*c1 - ((v*w-u)/w)
|
|
253
|
+
sage: b_ele = ele.braid_group_algebra_pre_image(); b_ele
|
|
254
|
+
-((v*w-u)/w) + v*c0 + u*c1 - w*c0*c1^-1
|
|
255
|
+
sage: ele in CHA3
|
|
256
|
+
True
|
|
257
|
+
sage: b_ele in CHA3
|
|
258
|
+
False
|
|
259
|
+
sage: b_ele in CHA3.braid_group_algebra()
|
|
260
|
+
True
|
|
261
|
+
"""
|
|
262
|
+
ch_algebra = self.parent()
|
|
263
|
+
braid_group_algebra = ch_algebra.braid_group_algebra()
|
|
264
|
+
braid_group = ch_algebra.braid_group()
|
|
265
|
+
|
|
266
|
+
def phi(bas_ele):
|
|
267
|
+
return braid_group_algebra(braid_group(bas_ele))
|
|
268
|
+
return ch_algebra._apply_module_morphism(self, phi,
|
|
269
|
+
codomain=braid_group_algebra)
|
|
270
|
+
|
|
271
|
+
def cubic_braid_group_algebra_pre_image(self):
|
|
272
|
+
r"""
|
|
273
|
+
Return a pre image of ``self`` in the group algebra of the cubic braid
|
|
274
|
+
group.
|
|
275
|
+
|
|
276
|
+
OUTPUT:
|
|
277
|
+
|
|
278
|
+
The pre image of ``self`` as instance of the element class of the group
|
|
279
|
+
algebra of the :class:`CubicBraidGroup`.
|
|
280
|
+
|
|
281
|
+
EXAMPLES::
|
|
282
|
+
|
|
283
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
284
|
+
sage: ele = CHA3.an_element(); ele
|
|
285
|
+
-w*c0*c1^-1 + v*c0 + u*c1 - ((v*w-u)/w)
|
|
286
|
+
sage: cb_ele = ele.cubic_braid_group_algebra_pre_image(); cb_ele
|
|
287
|
+
-w*c0*c1^-1 + v*c0 + u*c1 - ((v*w-u)/w)
|
|
288
|
+
sage: ele in CHA3
|
|
289
|
+
True
|
|
290
|
+
sage: cb_ele in CHA3
|
|
291
|
+
False
|
|
292
|
+
sage: cb_ele in CHA3.cubic_braid_group_algebra()
|
|
293
|
+
True
|
|
294
|
+
"""
|
|
295
|
+
ch_algebra = self.parent()
|
|
296
|
+
cbraid_group_algebra = ch_algebra.cubic_braid_group_algebra()
|
|
297
|
+
cbraid_group = ch_algebra.cubic_braid_group()
|
|
298
|
+
|
|
299
|
+
def phi(bas_ele):
|
|
300
|
+
return cbraid_group_algebra(cbraid_group(bas_ele))
|
|
301
|
+
return ch_algebra._apply_module_morphism(self, phi,
|
|
302
|
+
codomain=cbraid_group_algebra)
|
|
303
|
+
|
|
304
|
+
@cached_method
|
|
305
|
+
def matrix(self, subdivide=False, representation_type=None, original=False):
|
|
306
|
+
r"""
|
|
307
|
+
Return certain types of matrix representations of ``self``.
|
|
308
|
+
|
|
309
|
+
The absolutely irreducible representations of the cubic Hecke algebra
|
|
310
|
+
are constructed using the ``GAP3`` interface and the ``CHEVIE`` package
|
|
311
|
+
if ``GAP3`` and ``CHEVIE`` are installed on the system. Furthermore,
|
|
312
|
+
the representations given on `Ivan Marin's homepage
|
|
313
|
+
<http://www.lamfa.u-picardie.fr/marin/representationH4-en.html>`__
|
|
314
|
+
are used:
|
|
315
|
+
|
|
316
|
+
INPUT:
|
|
317
|
+
|
|
318
|
+
- ``subdivide`` -- boolean (default: ``False``); this boolean is passed
|
|
319
|
+
to the block_matrix function
|
|
320
|
+
- ``representation_type`` -- instance of enum :class:`RepresentationType`;
|
|
321
|
+
this can be obtained by the attribute :attr:`CubicHeckeAlgebra.repr_type`
|
|
322
|
+
of ``self``; the following values are possible:
|
|
323
|
+
|
|
324
|
+
- ``RegularLeft`` -- (regular left repr. from the above URL)
|
|
325
|
+
- ``RegularRight`` -- (regular right repr. from the above URL)
|
|
326
|
+
- ``SplitIrredChevie`` -- (split irred. repr. via CHEVIE)
|
|
327
|
+
- ``SplitIrredMarin`` -- (split irred. repr. from the above URL)
|
|
328
|
+
- default: ``SplitIrredChevie`` taken if GAP3 and CHEVIE are installed
|
|
329
|
+
on the system, otherwise the default will be ``SplitIrredMarin``
|
|
330
|
+
|
|
331
|
+
- ``original`` -- boolean (default: ``False``); if set to ``True`` the base
|
|
332
|
+
ring of the matrix will be the generic base_ring resp. generic extension
|
|
333
|
+
ring (for the split versions) of the parent of ``self``
|
|
334
|
+
|
|
335
|
+
OUTPUT:
|
|
336
|
+
|
|
337
|
+
An instance of :class:`~sage.algebras.hecke_algebras.cubic_hecke_matrix_rep.CubicHeckeMatrixRep`,
|
|
338
|
+
which is inherited from :class:`~sage.matrix.matrix_generic_dense.Matrix_generic_dense`.
|
|
339
|
+
In the case of the irreducible representations the matrix is given as a
|
|
340
|
+
block matrix. Each single irreducible can be obtained as item indexed by
|
|
341
|
+
the members of the enum :class:`AbsIrreducibeRep` available via
|
|
342
|
+
:attr:`CubicHeckeAlgebra.irred_repr`.
|
|
343
|
+
For details type: ``CubicHeckeAlgebra.irred_repr?``.
|
|
344
|
+
|
|
345
|
+
EXAMPLES::
|
|
346
|
+
|
|
347
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
348
|
+
sage: CHA3.inject_variables()
|
|
349
|
+
Defining c0, c1
|
|
350
|
+
sage: c0m = c0.matrix()
|
|
351
|
+
sage: c0m[CHA3.irred_repr.W3_111]
|
|
352
|
+
[ -b - a + u 0 0]
|
|
353
|
+
[(-2*a + u)*b - 2*a^2 + 2*u*a - v b 0]
|
|
354
|
+
[ b 1 a]
|
|
355
|
+
|
|
356
|
+
using the ``representation_type`` option::
|
|
357
|
+
|
|
358
|
+
sage: CHA3.<c0, c1> = algebras.CubicHecke(3) # optional gap3
|
|
359
|
+
sage: chevie = CHA3.repr_type.SplitIrredChevie # optional gap3
|
|
360
|
+
sage: c0m_ch = c0.matrix(representation_type=chevie) # optional gap3
|
|
361
|
+
sage: c0m_ch[CHA3.irred_repr.W3_011] # optional gap3
|
|
362
|
+
[ b 0]
|
|
363
|
+
[ -b -b - a + u]
|
|
364
|
+
sage: c0m[CHA3.irred_repr.W3_011]
|
|
365
|
+
[ b 0]
|
|
366
|
+
[a^2 - u*a + v -b - a + u]
|
|
367
|
+
|
|
368
|
+
using the ``original`` option::
|
|
369
|
+
|
|
370
|
+
sage: c0mo = c0.matrix(original=True)
|
|
371
|
+
sage: c0mo_ch = c0.matrix(representation_type=chevie, original=True) # optional gap3
|
|
372
|
+
sage: c0mo[CHA3.irred_repr.W3_011]
|
|
373
|
+
[ b 0]
|
|
374
|
+
[b*c c]
|
|
375
|
+
sage: c0mo_ch[CHA3.irred_repr.W3_011] # optional gap3
|
|
376
|
+
[ b 0]
|
|
377
|
+
[-b c]
|
|
378
|
+
|
|
379
|
+
specialized matrices::
|
|
380
|
+
|
|
381
|
+
sage: t = (3,7,11)
|
|
382
|
+
sage: CHA4 = algebras.CubicHecke(4, cubic_equation_roots=t) # optional database_cubic_hecke
|
|
383
|
+
sage: e = CHA4.an_element(); e # optional database_cubic_hecke
|
|
384
|
+
-231*c0*c1^-1 + 131*c0*c2^-1 + 21*c2*c1 - 1440/11
|
|
385
|
+
sage: em = e.matrix() # optional database_cubic_hecke
|
|
386
|
+
sage: em.base_ring() # optional database_cubic_hecke
|
|
387
|
+
Splitting Algebra of T^2 + T + 1 with roots [E3, -E3 - 1]
|
|
388
|
+
over Integer Ring localized at (3, 7, 11)
|
|
389
|
+
sage: em.dimensions() # optional database_cubic_hecke
|
|
390
|
+
(108, 108)
|
|
391
|
+
sage: em_irr24 = em[23] # optional database_cubic_hecke
|
|
392
|
+
sage: em_irr24.dimensions() # optional database_cubic_hecke
|
|
393
|
+
(9, 9)
|
|
394
|
+
sage: em_irr24[3,2] # optional database_cubic_hecke
|
|
395
|
+
-131*E3 - 393/7
|
|
396
|
+
sage: emg = e.matrix(representation_type=chevie) # optional gap3 database_cubic_hecke
|
|
397
|
+
sage: emg_irr24 = emg[23] # optional gap3 database_cubic_hecke
|
|
398
|
+
sage: emg_irr24[3,2] # optional gap3 database_cubic_hecke
|
|
399
|
+
-131*E3 - 393/7
|
|
400
|
+
"""
|
|
401
|
+
parent = self.parent()
|
|
402
|
+
MS = CubicHeckeMatrixSpace(parent, representation_type=representation_type, subdivide=subdivide, original=original)
|
|
403
|
+
return MS(self)
|
|
404
|
+
|
|
405
|
+
def revert_garside(self):
|
|
406
|
+
r"""
|
|
407
|
+
Return the image of ``self`` under the Garside involution.
|
|
408
|
+
|
|
409
|
+
.. SEEALSO::
|
|
410
|
+
|
|
411
|
+
:meth:`CubicHeckeAlgebra.garside_involution`
|
|
412
|
+
|
|
413
|
+
EXAMPLES::
|
|
414
|
+
|
|
415
|
+
sage: roots = (E(3), ~E(3), 1)
|
|
416
|
+
sage: CHA3.<c1, c2> = algebras.CubicHecke(3, cubic_equation_roots=roots)
|
|
417
|
+
sage: e = CHA3.an_element(); e
|
|
418
|
+
-c1*c2^-1
|
|
419
|
+
sage: _.revert_garside()
|
|
420
|
+
-c2*c1^-1
|
|
421
|
+
sage: _.revert_garside()
|
|
422
|
+
-c1*c2^-1
|
|
423
|
+
"""
|
|
424
|
+
return self.parent().garside_involution(self)
|
|
425
|
+
|
|
426
|
+
def revert_mirror(self):
|
|
427
|
+
r"""
|
|
428
|
+
Return the image of ``self`` under the mirror isomorphism.
|
|
429
|
+
|
|
430
|
+
.. SEEALSO::
|
|
431
|
+
|
|
432
|
+
:meth:`CubicHeckeAlgebra.mirror_isomorphism`
|
|
433
|
+
|
|
434
|
+
EXAMPLES::
|
|
435
|
+
|
|
436
|
+
sage: CHA3.<c1, c2> = algebras.CubicHecke(3)
|
|
437
|
+
sage: e = CHA3.an_element()
|
|
438
|
+
sage: e.revert_mirror()
|
|
439
|
+
-1/w*c0^-1*c1 + u/w*c0^-1 + v/w*c1^-1 + ((v*w-u)/w)
|
|
440
|
+
sage: _.revert_mirror() == e
|
|
441
|
+
True
|
|
442
|
+
"""
|
|
443
|
+
return self.parent().mirror_isomorphism(self)
|
|
444
|
+
|
|
445
|
+
def revert_orientation(self):
|
|
446
|
+
r"""
|
|
447
|
+
Return the image of ``self`` under the anti involution reverting the
|
|
448
|
+
orientation of braids.
|
|
449
|
+
|
|
450
|
+
.. SEEALSO::
|
|
451
|
+
|
|
452
|
+
:meth:`CubicHeckeAlgebra.orientation_antiinvolution`
|
|
453
|
+
|
|
454
|
+
EXAMPLES::
|
|
455
|
+
|
|
456
|
+
sage: CHA3.<c1, c2> = algebras.CubicHecke(3)
|
|
457
|
+
sage: e = CHA3.an_element()
|
|
458
|
+
sage: e.revert_orientation()
|
|
459
|
+
-w*c2^-1*c1 + v*c1 + u*c2 - ((v*w-u)/w)
|
|
460
|
+
sage: _.revert_orientation() == e
|
|
461
|
+
True
|
|
462
|
+
"""
|
|
463
|
+
return self.parent().orientation_antiinvolution(self)
|
|
464
|
+
|
|
465
|
+
def formal_markov_trace(self, extended=False, field_embedding=False):
|
|
466
|
+
r"""
|
|
467
|
+
Return a formal expression which can be specialized to Markov traces
|
|
468
|
+
which factor through the cubic Hecke algebra.
|
|
469
|
+
|
|
470
|
+
This covers Markov traces corresponding to the
|
|
471
|
+
|
|
472
|
+
- HOMFLY-PT polynomial,
|
|
473
|
+
- Kauffman polynomial,
|
|
474
|
+
- Links-Gould polynomial.
|
|
475
|
+
|
|
476
|
+
These expressions are elements of a sub-module of the module of linear
|
|
477
|
+
forms on ``self`` the base ring of which is an extension of the
|
|
478
|
+
generic base ring of ``self`` by an additional variable ``s``
|
|
479
|
+
representing the writhe factor. All variables of this base ring
|
|
480
|
+
extension are invertible.
|
|
481
|
+
|
|
482
|
+
A Markov trace is a family of class functions `tr_n` on the family
|
|
483
|
+
of braid groups `B_n` into some commutative ring `R` depending on
|
|
484
|
+
a unit `s \in R` such that for all `b \in B_n` the following two
|
|
485
|
+
conditions are satisfied (see [Kau1991]_, section 7):
|
|
486
|
+
|
|
487
|
+
.. MATH::
|
|
488
|
+
|
|
489
|
+
\begin{array}{lll}
|
|
490
|
+
tr_{n+1}(b g_n) & = & s tr_n(b), \\
|
|
491
|
+
tr_{n+1}(b g^{-1}_n) & = & s^{-1} tr_n(b).
|
|
492
|
+
\end{array}
|
|
493
|
+
|
|
494
|
+
The unit `s` is often called the writhe factor and corresponds to the
|
|
495
|
+
additional variable mentioned above.
|
|
496
|
+
|
|
497
|
+
.. NOTE::
|
|
498
|
+
|
|
499
|
+
Currently it is not known if all linear forms of this sub-module
|
|
500
|
+
belong to a Markov trace, i.e. can be extended to the full tower
|
|
501
|
+
of cubic Hecke algebras. Anyway, at least the four basis elements
|
|
502
|
+
(``U1``, ``U2``, ``U3`` and ``K4``) can be reconstructed form
|
|
503
|
+
the HOMFLY-PT and Kauffman polynomial.
|
|
504
|
+
|
|
505
|
+
INPUT:
|
|
506
|
+
|
|
507
|
+
- ``extended`` -- boolean (default: ``False``); if set to ``True`` the
|
|
508
|
+
base ring of the Markov trace module is constructed as an extension
|
|
509
|
+
of generic extension ring of ``self``; per default it is constructed
|
|
510
|
+
upon the generic base ring
|
|
511
|
+
- ``field_embedding`` -- boolean (default: ``False``); if set to ``True``
|
|
512
|
+
the base ring of the module is the smallest field containing the
|
|
513
|
+
generic extension ring of ``self``; ignored if ``extended=False``
|
|
514
|
+
|
|
515
|
+
EXAMPLES::
|
|
516
|
+
|
|
517
|
+
sage: from sage.knots.knotinfo import KnotInfo
|
|
518
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
519
|
+
sage: K3_1 = KnotInfo.K3_1
|
|
520
|
+
sage: b3_1 = CHA2(K3_1.braid())
|
|
521
|
+
sage: mt3_1 = b3_1.formal_markov_trace(); mt3_1
|
|
522
|
+
((u^2*s^2-v*s^2+u*w)/s)*B[U1] - (u*v-w)*B[U2]
|
|
523
|
+
sage: mt3_1.parent()
|
|
524
|
+
Free module generated by {U1, U2}
|
|
525
|
+
over Multivariate Polynomial Ring in u, v, w, s
|
|
526
|
+
over Integer Ring localized at (s, w, v, u)
|
|
527
|
+
|
|
528
|
+
sage: f = b3_1.formal_markov_trace(extended=True); f
|
|
529
|
+
(a^2*b*c*s^-1+a*b^2*c*s^-1+a*b*c^2*s^-1+a^2*s+a*b*s+b^2*s+a*c*s+b*c*s+c^2*s)*B[U1]
|
|
530
|
+
+ (-a^2*b-a*b^2-a^2*c+(-2)*a*b*c-b^2*c-a*c^2-b*c^2)*B[U2]
|
|
531
|
+
sage: f.parent().base_ring()
|
|
532
|
+
Multivariate Laurent Polynomial Ring in a, b, c, s
|
|
533
|
+
over Splitting Algebra of x^2 + x + 1 with roots [e3, -e3 - 1]
|
|
534
|
+
over Integer Ring
|
|
535
|
+
|
|
536
|
+
sage: f = b3_1.formal_markov_trace(extended=True, field_embedding=True); f
|
|
537
|
+
((a^2*b*c+a*b^2*c+a*b*c^2+a^2*s^2+a*b*s^2+b^2*s^2+a*c*s^2+b*c*s^2+c^2*s^2)/s)*B[U1]
|
|
538
|
+
- (a^2*b+a*b^2+a^2*c+2*a*b*c+b^2*c+a*c^2+b*c^2)*B[U2]
|
|
539
|
+
sage: f.parent().base_ring()
|
|
540
|
+
Fraction Field of Multivariate Polynomial Ring in a, b, c, s
|
|
541
|
+
over Cyclotomic Field of order 3 and degree 2
|
|
542
|
+
|
|
543
|
+
Obtaining the well known link invariants from it::
|
|
544
|
+
|
|
545
|
+
sage: MT = mt3_1.base_ring()
|
|
546
|
+
sage: sup = mt3_1.support()
|
|
547
|
+
sage: u, v, w, s = mt3_1.base_ring().gens()
|
|
548
|
+
sage: LK3_1 = mt3_1*s**-3 # since the writhe of K3_1 is 3
|
|
549
|
+
sage: f = MT.specialize_homfly()
|
|
550
|
+
sage: g = sum(f(LK3_1.coefficient(b)) * b.regular_homfly_polynomial() for b in sup); g
|
|
551
|
+
L^-2*M^2 - 2*L^-2 - L^-4
|
|
552
|
+
sage: g == K3_1.link().homfly_polynomial()
|
|
553
|
+
True
|
|
554
|
+
|
|
555
|
+
sage: f = MT.specialize_kauffman()
|
|
556
|
+
sage: g = sum(f(LK3_1.coefficient(b)) * b.regular_kauffman_polynomial() for b in sup); g
|
|
557
|
+
a^-2*z^2 - 2*a^-2 + a^-3*z + a^-4*z^2 - a^-4 + a^-5*z
|
|
558
|
+
sage: g == K3_1.kauffman_polynomial()
|
|
559
|
+
True
|
|
560
|
+
|
|
561
|
+
sage: f = MT.specialize_links_gould()
|
|
562
|
+
sage: g = sum(f(LK3_1.coefficient(b)) * b.links_gould_polynomial() for b in sup); g
|
|
563
|
+
-t0^2*t1 - t0*t1^2 + t0^2 + 2*t0*t1 + t1^2 - t0 - t1 + 1
|
|
564
|
+
sage: g == K3_1.link().links_gould_polynomial()
|
|
565
|
+
True
|
|
566
|
+
"""
|
|
567
|
+
cha = self.parent()
|
|
568
|
+
vs = self.to_vector()
|
|
569
|
+
mtcf = cha._markov_trace_coeffs()
|
|
570
|
+
M = cha._markov_trace_module(extended=extended, field_embedding=field_embedding)
|
|
571
|
+
if M != mtcf[0].parent():
|
|
572
|
+
if field_embedding:
|
|
573
|
+
# intermediate step needed since internal coercion to the field
|
|
574
|
+
# maps (u, v, w ) -> (a, b, c)
|
|
575
|
+
MI = cha._markov_trace_module(extended=extended, field_embedding=False)
|
|
576
|
+
RI = MI.base_ring()
|
|
577
|
+
mtcf = [MI.from_vector(cf.to_vector()) for cf in mtcf]
|
|
578
|
+
vs = vs.change_ring(RI)
|
|
579
|
+
mtcf = [M.from_vector(cf.to_vector()) for cf in mtcf]
|
|
580
|
+
|
|
581
|
+
R = M.base_ring()
|
|
582
|
+
return M.linear_combination((mtcf[i], R(val)) for i, val in vs.iteritems())
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
class CubicHeckeAlgebra(CombinatorialFreeModule):
|
|
586
|
+
r"""
|
|
587
|
+
Return the Cubic-Hecke algebra with respect to the Artin braid group on
|
|
588
|
+
`n` strands.
|
|
589
|
+
|
|
590
|
+
This is a quotient of the group algebra of the Artin braid group, such that
|
|
591
|
+
the images `s_i` (`1 \leq i < n`) of the braid generators satisfy a cubic
|
|
592
|
+
equation (see :mod:`~sage.algebras.hecke_algebras.cubic_hecke_algebra`
|
|
593
|
+
for more information, in a session type
|
|
594
|
+
``sage.algebras.hecke_algebras.cubic_hecke_algebra?``):
|
|
595
|
+
|
|
596
|
+
.. MATH::
|
|
597
|
+
|
|
598
|
+
s_i^3 = u s_i^2 - v s_i + w.
|
|
599
|
+
|
|
600
|
+
The base ring of this algebra can be specified by giving optional keywords
|
|
601
|
+
described below. If no keywords are given, the base ring will be a
|
|
602
|
+
:class:`CubicHeckeRingOfDefinition`, which is constructed as the
|
|
603
|
+
polynomial ring in `u, v, w` over the integers localized at `w`.
|
|
604
|
+
This ring will be called the *ring of definition* or sometimes for short
|
|
605
|
+
*generic base ring*. However note, that in this context the word *generic*
|
|
606
|
+
should not remind in a generic point of the corresponding scheme.
|
|
607
|
+
|
|
608
|
+
In addition to the base ring, another ring containing the roots (`a`, `b`
|
|
609
|
+
and `c`) of the cubic equation will be needed to handle the split
|
|
610
|
+
irreducible representations. This ring will be called the *extension ring*.
|
|
611
|
+
Generically, the extension ring will be a
|
|
612
|
+
:class:`~sage.algebras.hecke_algebras.cubic_hecke_base_ring.CubicHeckeExtensionRing`,
|
|
613
|
+
which is constructed as the Laurent polynomial ring in `a, b` and `c` over
|
|
614
|
+
the integers adjoined with a primitive third root of unity. A special form
|
|
615
|
+
of this *generic extension ring* is constructed as a
|
|
616
|
+
:class:`~sage.algebras.splitting_algebra.SplittingAlgebra` for the roots of
|
|
617
|
+
the cubic equation and a primitive third root of unity over the ring of
|
|
618
|
+
definition. This ring will be called the *default extension ring*.
|
|
619
|
+
|
|
620
|
+
This class uses a static and a dynamic data library. The first one is defined
|
|
621
|
+
as instance of :class:`~sage.databases.cubic_hecke_db.CubicHeckeDataBase`
|
|
622
|
+
and contains the complete basis for the algebras with less than 5 strands
|
|
623
|
+
and various types of representation matrices of the generators. These data
|
|
624
|
+
have been calculated by `Ivan Marin <http://www.lamfa.u-picardie.fr/marin/anglais.html>`__
|
|
625
|
+
and have been imported from his corresponding
|
|
626
|
+
`web page <http://www.lamfa.u-picardie.fr/marin/representationH4-en.html>`__.
|
|
627
|
+
|
|
628
|
+
Note that just the data for the cubic Hecke algebras on less than four
|
|
629
|
+
strands is available in Sage by default. To deal with four strands and
|
|
630
|
+
more you need to install the optional package
|
|
631
|
+
`database_cubic_hecke <https://pypi.org/project/database-cubic-hecke/>`__
|
|
632
|
+
by typing
|
|
633
|
+
|
|
634
|
+
- ``sage -i database_cubic_hecke`` (first time installation) or
|
|
635
|
+
- ``sage -f database_cubic_hecke`` (reinstallation) respective
|
|
636
|
+
- ``sage -i -c database_cubic_hecke`` (for running all test in concern)
|
|
637
|
+
- ``sage -f -c database_cubic_hecke``
|
|
638
|
+
|
|
639
|
+
This will add a `Python wrapper <https://github.com/soehms/database_cubic_hecke#readme>`__
|
|
640
|
+
around Ivan Marin's data to the Sage library. For more installation hints
|
|
641
|
+
see the documentation of this wrapper.
|
|
642
|
+
|
|
643
|
+
Furthermore, representation matrices can be obtained from the ``CHEVIE``
|
|
644
|
+
package of ``GAP3`` via the ``GAP3`` interface if ``GAP3`` is installed
|
|
645
|
+
inside Sage. For more information on how to obtain representation matrices
|
|
646
|
+
to elements of this class, see the documentation of the element class
|
|
647
|
+
:class:`~sage.algebras.hecke_algebras.cubic_hecke_algebra.CubicHeckeElement`
|
|
648
|
+
or its method
|
|
649
|
+
:meth:`~sage.algebras.hecke_algebras.cubic_hecke_algebra.CubicHeckeElement.matrix`:
|
|
650
|
+
|
|
651
|
+
``algebras.CubicHecke.Element?`` or ``algebras.CubicHecke.Element.matrix?``
|
|
652
|
+
|
|
653
|
+
The second library is created as instance of
|
|
654
|
+
:class:`~sage.databases.cubic_hecke_db.CubicHeckeFileCache` and used while
|
|
655
|
+
working with the class to achieve a better performance. This file cache
|
|
656
|
+
contains images of braids and representation matrices of basis elements
|
|
657
|
+
from former calculations. A refresh of the file cache can be done using
|
|
658
|
+
the :meth:`reset_filecache`.
|
|
659
|
+
|
|
660
|
+
INPUT:
|
|
661
|
+
|
|
662
|
+
- ``names`` -- string containing the names of the generators as images of
|
|
663
|
+
the braid group generators
|
|
664
|
+
- ``cubic_equation_parameters`` -- tuple ``(u, v, w)`` of three elements
|
|
665
|
+
in an integral domain used as coefficients in the cubic equation. If this
|
|
666
|
+
argument is given the base ring will be set to the common parent of
|
|
667
|
+
``u, v, w``. In addition a conversion map from the generic base ring is
|
|
668
|
+
supplied. This keyword can also be used to change the variable names of
|
|
669
|
+
the generic base ring (see example 3 below)
|
|
670
|
+
- ``cubic_equation_roots`` -- tuple ``(a, b, c)`` of three elements in an
|
|
671
|
+
integral domain which stand for the roots of the cubic equation. If this
|
|
672
|
+
argument is given the extension ring will be set to the common parent of
|
|
673
|
+
``a, b, c``. In addition a conversion map from the generic extension ring
|
|
674
|
+
and the generic base ring is supplied. This keyword can also be used to
|
|
675
|
+
change the variable names of the generic extension ring (see example 3
|
|
676
|
+
below)
|
|
677
|
+
|
|
678
|
+
EXAMPLES:
|
|
679
|
+
|
|
680
|
+
Cubic Hecke algebra over the ring of definition::
|
|
681
|
+
|
|
682
|
+
sage: CHA3 = algebras.CubicHecke('s1, s2'); CHA3
|
|
683
|
+
Cubic Hecke algebra on 3 strands over Multivariate Polynomial Ring
|
|
684
|
+
in u, v, w
|
|
685
|
+
over Integer Ring localized at (w,)
|
|
686
|
+
with cubic equation: h^3 - u*h^2 + v*h - w = 0
|
|
687
|
+
sage: CHA3.gens()
|
|
688
|
+
(s1, s2)
|
|
689
|
+
sage: GER = CHA3.extension_ring(generic=True); GER
|
|
690
|
+
Multivariate Laurent Polynomial Ring in a, b, c
|
|
691
|
+
over Splitting Algebra of x^2 + x + 1
|
|
692
|
+
with roots [e3, -e3 - 1] over Integer Ring
|
|
693
|
+
sage: ER = CHA3.extension_ring(); ER
|
|
694
|
+
Splitting Algebra of T^2 + T + 1 with roots [E3, -E3 - 1]
|
|
695
|
+
over Splitting Algebra of h^3 - u*h^2 + v*h - w
|
|
696
|
+
with roots [a, b, -b - a + u]
|
|
697
|
+
over Multivariate Polynomial Ring in u, v, w
|
|
698
|
+
over Integer Ring localized at (w,)
|
|
699
|
+
|
|
700
|
+
Element construction::
|
|
701
|
+
|
|
702
|
+
sage: ele = CHA3.an_element(); ele
|
|
703
|
+
-w*s1*s2^-1 + v*s1 + u*s2 - ((v*w-u)/w)
|
|
704
|
+
sage: ele2 = ele**2; ele2
|
|
705
|
+
w^2*(s1^-1*s2)^2 - u*w^2*s1^-1*s2*s1^-1 - v*w*s2*s1^-1*s2
|
|
706
|
+
- v*w^2*s1^-1*s2^-1 + u*w*s1*s2*s1^-1*s2 - u*w*s1^-1*s2*s1
|
|
707
|
+
- (u*v*w-2*v*w+2*u)*s1*s2^-1 + u*v*w*s2*s1^-1 + u*v*s2*s1 + v^2*w*s1^-1
|
|
708
|
+
- u^2*w*s1*s2*s1^-1 + ((u*v^2*w-2*v^2*w-u*w^2+2*u*v)/w)*s1 + u*v*s1*s2
|
|
709
|
+
+ (u^2*w+v^2*w)*s2^-1 + ((u^3*w-2*u*v*w+2*u^2)/w)*s2
|
|
710
|
+
- ((u^2*v*w^2+v^3*w^2-v^2*w^2+2*u*v*w-u^2)/w^2)
|
|
711
|
+
sage: B3 = CHA3.braid_group()
|
|
712
|
+
sage: braid = B3((2,-1, 2, 1)); braid
|
|
713
|
+
s2*s1^-1*s2*s1
|
|
714
|
+
sage: ele3 = CHA3(braid); ele3
|
|
715
|
+
s1*s2*s1^-1*s2 + u*s1^-1*s2*s1 - v*s1*s2^-1 + v*s2^-1*s1 - u*s1*s2*s1^-1
|
|
716
|
+
sage: ele3t = CHA3((2,-1, 2, 1))
|
|
717
|
+
sage: ele3 == ele3t
|
|
718
|
+
True
|
|
719
|
+
sage: CHA4 = algebras.CubicHecke(4) # optional database_cubic_hecke
|
|
720
|
+
sage: ele4 = CHA4(ele3); ele4 # optional database_cubic_hecke
|
|
721
|
+
c0*c1*c0^-1*c1 + u*c0^-1*c1*c0 + (-v)*c0*c1^-1 + v*c1^-1*c0 + (-u)*c0*c1*c0^-1
|
|
722
|
+
|
|
723
|
+
Cubic Hecke algebra over the ring of definition using different variable
|
|
724
|
+
names::
|
|
725
|
+
|
|
726
|
+
sage: algebras.CubicHecke(3, cubic_equation_parameters='u, v, w', cubic_equation_roots='p, q, r')
|
|
727
|
+
Cubic Hecke algebra on 3 strands over Multivariate Polynomial Ring
|
|
728
|
+
in u, v, w
|
|
729
|
+
over Integer Ring localized at (w,)
|
|
730
|
+
with cubic equation: h^3 - u*h^2 + v*h - w = 0
|
|
731
|
+
sage: _.extension_ring()
|
|
732
|
+
Splitting Algebra of T^2 + T + 1 with roots [E3, -E3 - 1]
|
|
733
|
+
over Splitting Algebra of h^3 - u*h^2 + v*h - w
|
|
734
|
+
with roots [p, q, -q - p + u]
|
|
735
|
+
over Multivariate Polynomial Ring in u, v, w
|
|
736
|
+
over Integer Ring localized at (w,)
|
|
737
|
+
|
|
738
|
+
Cubic Hecke algebra over a special base ring with respect to a special
|
|
739
|
+
cubic equation::
|
|
740
|
+
|
|
741
|
+
sage: algebras.CubicHecke('s1, s2', cubic_equation_parameters=(QQ(1),3,1))
|
|
742
|
+
Cubic Hecke algebra on 3 strands over Rational Field
|
|
743
|
+
with cubic equation: h^3 - h^2 + 3*h - 1 = 0
|
|
744
|
+
sage: CHA3 = _
|
|
745
|
+
sage: ER = CHA3.extension_ring(); ER
|
|
746
|
+
Number Field in T with defining polynomial T^12 + 4*T^11 + 51*T^10
|
|
747
|
+
+ 154*T^9 + 855*T^8 + 1880*T^7 + 5805*T^6 + 8798*T^5 + 15312*T^4
|
|
748
|
+
+ 14212*T^3 + 13224*T^2 + 5776*T + 1444
|
|
749
|
+
sage: CHA3.cubic_equation_roots()[0]
|
|
750
|
+
-4321/1337904*T^11 - 4181/445968*T^10 - 4064/27873*T^9 - 51725/167238*T^8
|
|
751
|
+
- 2693189/1337904*T^7 - 1272907/445968*T^6 - 704251/74328*T^5
|
|
752
|
+
- 591488/83619*T^4 - 642145/83619*T^3 + 252521/111492*T^2 + 45685/5868*T
|
|
753
|
+
+ 55187/17604
|
|
754
|
+
|
|
755
|
+
sage: F = GF(25,'u')
|
|
756
|
+
sage: algebras.CubicHecke('s1, s2', cubic_equation_parameters=(F(1), F.gen(), F(3)))
|
|
757
|
+
Cubic Hecke algebra on 3 strands over Finite Field in u of size 5^2
|
|
758
|
+
with cubic equation: h^3 + 4*h^2 + u*h + 2 = 0
|
|
759
|
+
sage: CHA3 = _
|
|
760
|
+
sage: ER = CHA3.extension_ring(); ER
|
|
761
|
+
Finite Field in S of size 5^4
|
|
762
|
+
sage: CHA3.cubic_equation_roots()
|
|
763
|
+
[2*S^3 + 2*S^2 + 2*S + 1, 2*S^3 + 3*S^2 + 3*S + 2, S^3 + 3]
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
Cubic Hecke algebra over a special extension ring with respect to special
|
|
767
|
+
roots of the cubic equation::
|
|
768
|
+
|
|
769
|
+
sage: UCF = UniversalCyclotomicField()
|
|
770
|
+
sage: e3=UCF.gen(3); e5=UCF.gen(5)
|
|
771
|
+
sage: algebras.CubicHecke('s1, s2', cubic_equation_roots=(1, e5, e3))
|
|
772
|
+
Cubic Hecke algebra on 3 strands over Universal Cyclotomic Field
|
|
773
|
+
with cubic equation:
|
|
774
|
+
h^3 + (-E(15) - E(15)^4 - E(15)^7 + E(15)^8)*h^2 + (-E(15)^2 - E(15)^8
|
|
775
|
+
- E(15)^11 - E(15)^13 - E(15)^14)*h - E(15)^8 = 0
|
|
776
|
+
|
|
777
|
+
TESTS::
|
|
778
|
+
|
|
779
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
780
|
+
sage: TestSuite(CHA3).run()
|
|
781
|
+
|
|
782
|
+
Note, that the ``TestSuite`` run on the cubic Hecke algebra on four strands
|
|
783
|
+
would take up to half an hour if the file cache is empty. A repetition takes
|
|
784
|
+
less than half a minute.
|
|
785
|
+
"""
|
|
786
|
+
Element = CubicHeckeElement
|
|
787
|
+
repr_type = RepresentationType
|
|
788
|
+
irred_repr = AbsIrreducibeRep
|
|
789
|
+
|
|
790
|
+
############################################################################
|
|
791
|
+
# private methods
|
|
792
|
+
############################################################################
|
|
793
|
+
@staticmethod
|
|
794
|
+
def __classcall_private__(cls, n=None, names='c', cubic_equation_parameters=None, cubic_equation_roots=None):
|
|
795
|
+
r"""
|
|
796
|
+
Normalize input to ensure a unique representation.
|
|
797
|
+
|
|
798
|
+
EXAMPLES::
|
|
799
|
+
|
|
800
|
+
sage: CHA2 = algebras.CubicHecke(2, 'd', cubic_equation_roots=(3,5,7)); CHA2
|
|
801
|
+
Cubic Hecke algebra on 2 strands
|
|
802
|
+
over Integer Ring localized at (3, 5, 7)
|
|
803
|
+
with cubic equation:
|
|
804
|
+
h^3 - 15*h^2 + 71*h - 105 = 0
|
|
805
|
+
sage: CHA2.inject_variables()
|
|
806
|
+
Defining d
|
|
807
|
+
sage: CHA3 = algebras.CubicHecke(3, cubic_equation_parameters=(3,5,7)); CHA3
|
|
808
|
+
Cubic Hecke algebra on 3 strands
|
|
809
|
+
over Integer Ring localized at (7,)
|
|
810
|
+
with cubic equation:
|
|
811
|
+
h^3 - 3*h^2 + 5*h - 7 = 0
|
|
812
|
+
sage: CHA3.cubic_equation_roots()
|
|
813
|
+
[a, b, -b - a + 3]
|
|
814
|
+
"""
|
|
815
|
+
# Support Freegroup('a,b') syntax
|
|
816
|
+
if n is not None:
|
|
817
|
+
try:
|
|
818
|
+
n = ZZ(n) - 1
|
|
819
|
+
except TypeError:
|
|
820
|
+
names = n
|
|
821
|
+
n = None
|
|
822
|
+
|
|
823
|
+
# derive n from counting names
|
|
824
|
+
if n is None:
|
|
825
|
+
if type(names) is str:
|
|
826
|
+
n = len(names.split(','))
|
|
827
|
+
else:
|
|
828
|
+
names = list(names)
|
|
829
|
+
n = len(names)
|
|
830
|
+
|
|
831
|
+
from sage.structure.category_object import normalize_names
|
|
832
|
+
names = tuple(normalize_names(n, names))
|
|
833
|
+
return super().__classcall__(cls, names,
|
|
834
|
+
cubic_equation_parameters=cubic_equation_parameters,
|
|
835
|
+
cubic_equation_roots=cubic_equation_roots)
|
|
836
|
+
|
|
837
|
+
def __init__(self, names, cubic_equation_parameters=None, cubic_equation_roots=None):
|
|
838
|
+
r"""
|
|
839
|
+
Initialize ``self``.
|
|
840
|
+
|
|
841
|
+
TESTS::
|
|
842
|
+
|
|
843
|
+
sage: CHA2 = algebras.CubicHecke(2, 'd', cubic_equation_roots=(3,5,7))
|
|
844
|
+
sage: TestSuite(CHA2).run()
|
|
845
|
+
sage: CHA2 = algebras.CubicHecke(2, cubic_equation_parameters=(3,5,7))
|
|
846
|
+
sage: TestSuite(CHA2).run()
|
|
847
|
+
"""
|
|
848
|
+
# ----------------------------------------------------------------------
|
|
849
|
+
# Define underlying group
|
|
850
|
+
# ----------------------------------------------------------------------
|
|
851
|
+
self._cubic_braid_group = CubicBraidGroup(names)
|
|
852
|
+
self._braid_group = self._cubic_braid_group.braid_group()
|
|
853
|
+
n = len(self._cubic_braid_group.gens())
|
|
854
|
+
self._nstrands = n + 1
|
|
855
|
+
self._dim_irr_rep = sum([irr.dimension() for irr in AbsIrreducibeRep if irr.number_gens() == n])
|
|
856
|
+
|
|
857
|
+
# ----------------------------------------------------------------------
|
|
858
|
+
# preparing use of data base anf file cache
|
|
859
|
+
# ----------------------------------------------------------------------
|
|
860
|
+
from sage.databases.cubic_hecke_db import CubicHeckeDataBase, CubicHeckeFileCache
|
|
861
|
+
self._database = CubicHeckeDataBase()
|
|
862
|
+
self._filecache = CubicHeckeFileCache(self._nstrands)
|
|
863
|
+
|
|
864
|
+
# ----------------------------------------------------------------------
|
|
865
|
+
# interpretation of keywords and type verifications
|
|
866
|
+
# ----------------------------------------------------------------------
|
|
867
|
+
# cubic_equation_parameters
|
|
868
|
+
# ----------------------------------------------------------------------
|
|
869
|
+
ring_of_definition_names = ('u', 'v', 'w')
|
|
870
|
+
if cubic_equation_parameters is not None:
|
|
871
|
+
if isinstance(cubic_equation_parameters, str):
|
|
872
|
+
# --------------------------------------------------------------
|
|
873
|
+
# Input specifies names for the generic base ring
|
|
874
|
+
# --------------------------------------------------------------
|
|
875
|
+
ring_of_definition_names = tuple(cubic_equation_parameters.split(','))
|
|
876
|
+
if len(ring_of_definition_names) != 3:
|
|
877
|
+
raise ValueError('cubic_equation_parameters must consist of exactly 3 elements')
|
|
878
|
+
cubic_equation_parameters = None
|
|
879
|
+
else:
|
|
880
|
+
# --------------------------------------------------------------
|
|
881
|
+
# Input specifies a specialized base ring
|
|
882
|
+
# --------------------------------------------------------------
|
|
883
|
+
if isinstance(cubic_equation_parameters, list):
|
|
884
|
+
cubic_equation_parameters = tuple(cubic_equation_parameters)
|
|
885
|
+
if not isinstance(cubic_equation_parameters, tuple):
|
|
886
|
+
raise TypeError('cubic_equation_parameters must be a tuple or list')
|
|
887
|
+
if len(cubic_equation_parameters) != 3:
|
|
888
|
+
raise ValueError('cubic_equation_parameters must consist of exactly 3 elements')
|
|
889
|
+
|
|
890
|
+
# ----------------------------------------------------------------------
|
|
891
|
+
# cubic_equation_roots
|
|
892
|
+
# ----------------------------------------------------------------------
|
|
893
|
+
generic_extension_ring_names = ('a', 'b', 'c')
|
|
894
|
+
if cubic_equation_roots is not None:
|
|
895
|
+
if isinstance(cubic_equation_roots, str):
|
|
896
|
+
# --------------------------------------------------------------
|
|
897
|
+
# Input specifies names for the generic extension ring
|
|
898
|
+
# --------------------------------------------------------------
|
|
899
|
+
generic_extension_ring_names = tuple(cubic_equation_roots.split(','))
|
|
900
|
+
if len(generic_extension_ring_names) != 3:
|
|
901
|
+
raise ValueError('cubic_equation_roots must consist of exactly 3 elements')
|
|
902
|
+
cubic_equation_roots = None
|
|
903
|
+
else:
|
|
904
|
+
# --------------------------------------------------------------
|
|
905
|
+
# Input specifies a specialized base ring
|
|
906
|
+
# --------------------------------------------------------------
|
|
907
|
+
if isinstance(cubic_equation_roots, list):
|
|
908
|
+
cubic_equation_roots = tuple(cubic_equation_roots)
|
|
909
|
+
if not isinstance(cubic_equation_roots, tuple):
|
|
910
|
+
raise TypeError('cubic_equation_roots must be a tuple or list')
|
|
911
|
+
if len(cubic_equation_roots) != 3:
|
|
912
|
+
raise ValueError('cubic_equation_roots must consist of exactly 3 elements')
|
|
913
|
+
|
|
914
|
+
if len(set(ring_of_definition_names + generic_extension_ring_names)) < 6:
|
|
915
|
+
raise ValueError('there is an overlap of names between cubic equation '
|
|
916
|
+
'parameters (%s) and cubic equation roots (%s)'
|
|
917
|
+
% (ring_of_definition_names, generic_extension_ring_names))
|
|
918
|
+
|
|
919
|
+
# ----------------------------------------------------------------------
|
|
920
|
+
# setting the generic rings
|
|
921
|
+
# ----------------------------------------------------------------------
|
|
922
|
+
ring_of_definition = CubicHeckeRingOfDefinition(names=ring_of_definition_names)
|
|
923
|
+
u, v, w = ring_of_definition.gens()
|
|
924
|
+
|
|
925
|
+
generic_extension_ring = ring_of_definition.extension_ring(names=generic_extension_ring_names)
|
|
926
|
+
a, b, c = generic_extension_ring.gens()
|
|
927
|
+
|
|
928
|
+
# ----------------------------------------------------------------------
|
|
929
|
+
# registering generic items as variables
|
|
930
|
+
# ----------------------------------------------------------------------
|
|
931
|
+
self._ring_of_definition = ring_of_definition
|
|
932
|
+
self._generic_extension_ring = generic_extension_ring
|
|
933
|
+
self._generic_cubic_equation_parameters = [u, v, w]
|
|
934
|
+
self._generic_cubic_equation_roots = [a, b, c]
|
|
935
|
+
|
|
936
|
+
# ----------------------------------------------------------------------
|
|
937
|
+
# interpreting user given cubic equation parameters to define the
|
|
938
|
+
# corresponding specialized base ring
|
|
939
|
+
# ----------------------------------------------------------------------
|
|
940
|
+
if cubic_equation_parameters is None and cubic_equation_roots is not None:
|
|
941
|
+
pa, pb, pc = cubic_equation_roots
|
|
942
|
+
cubic_equation_parameters = [pa+pb+pc, pa*pb+pb*pc+pa*pc, pa*pb*pc]
|
|
943
|
+
verbose('cubic_equation_parameters %s set according to '
|
|
944
|
+
'cubic_equation_roots %s' % (cubic_equation_parameters,
|
|
945
|
+
cubic_equation_roots), level=2)
|
|
946
|
+
|
|
947
|
+
if cubic_equation_parameters is not None:
|
|
948
|
+
base_ring = ring_of_definition.create_specialization(cubic_equation_parameters)
|
|
949
|
+
cubic_equation_parameters = [base_ring(para) for para in cubic_equation_parameters]
|
|
950
|
+
verbose('base_ring %s set according to cubic_equation_parameters %s'
|
|
951
|
+
% (base_ring, cubic_equation_parameters), level=2)
|
|
952
|
+
else:
|
|
953
|
+
base_ring = self._ring_of_definition
|
|
954
|
+
cubic_equation_parameters = self._generic_cubic_equation_parameters
|
|
955
|
+
|
|
956
|
+
verbose('base_ring %s and cubic_equation_parameters %s defined'
|
|
957
|
+
% (base_ring, cubic_equation_parameters), level=2)
|
|
958
|
+
|
|
959
|
+
# ----------------------------------------------------------------------
|
|
960
|
+
# defining the cubic equation
|
|
961
|
+
# ----------------------------------------------------------------------
|
|
962
|
+
pu, pv, pw = cubic_equation_parameters
|
|
963
|
+
pol_bas_ring = base_ring['h']
|
|
964
|
+
cubic_equation = pol_bas_ring([-pw, pv, -pu, 1])
|
|
965
|
+
|
|
966
|
+
verbose('cubic_equation %s defined' % cubic_equation, level=2)
|
|
967
|
+
|
|
968
|
+
# ----------------------------------------------------------------------
|
|
969
|
+
# defining cubic_equation_roots if not given using the cubic_equation
|
|
970
|
+
# ----------------------------------------------------------------------
|
|
971
|
+
if base_ring != ring_of_definition:
|
|
972
|
+
if cubic_equation_roots is None:
|
|
973
|
+
# --------------------------------------------------------------
|
|
974
|
+
# No roots given
|
|
975
|
+
# --------------------------------------------------------------
|
|
976
|
+
ext_ring_names = list(generic_extension_ring_names)
|
|
977
|
+
cubic_equation_roots = solve_with_extension(cubic_equation,
|
|
978
|
+
ext_ring_names,
|
|
979
|
+
var='S', flatten=True)
|
|
980
|
+
|
|
981
|
+
# ----------------------------------------------------------------------
|
|
982
|
+
# interpreting user given cubic equation roots to define the
|
|
983
|
+
# corresponding specialized extension ring
|
|
984
|
+
# ----------------------------------------------------------------------
|
|
985
|
+
if cubic_equation_roots is not None:
|
|
986
|
+
extension_ring = generic_extension_ring.create_specialization(cubic_equation_roots)
|
|
987
|
+
cubic_equation_roots = [extension_ring(root) for root in cubic_equation_roots]
|
|
988
|
+
verbose('extension_ring %s set according to cubic_equation_roots %s'
|
|
989
|
+
% (base_ring, cubic_equation_roots), level=2)
|
|
990
|
+
|
|
991
|
+
else:
|
|
992
|
+
extension_ring = generic_extension_ring.as_splitting_algebra()
|
|
993
|
+
cubic_equation_roots = [extension_ring(a), extension_ring(b), extension_ring(c)]
|
|
994
|
+
|
|
995
|
+
verbose('cubic roots %s and extension ring %s defined'
|
|
996
|
+
% (cubic_equation_roots, extension_ring), level=2)
|
|
997
|
+
pa, pb, pc = cubic_equation_roots
|
|
998
|
+
|
|
999
|
+
# ----------------------------------------------------------------------
|
|
1000
|
+
# check keywords plausibility
|
|
1001
|
+
# ----------------------------------------------------------------------
|
|
1002
|
+
if base_ring == extension_ring:
|
|
1003
|
+
val_a = cubic_equation.substitute(h=pa)
|
|
1004
|
+
val_b = cubic_equation.substitute(h=pb)
|
|
1005
|
+
val_c = cubic_equation.substitute(h=pc)
|
|
1006
|
+
if val_a != 0 or val_b != 0 or val_c != 0:
|
|
1007
|
+
raise ValueError('cubic equation does not vanish on cubic equation roots')
|
|
1008
|
+
|
|
1009
|
+
# ----------------------------------------------------------------------
|
|
1010
|
+
# defining the base ring embedding into the extension ring
|
|
1011
|
+
# ----------------------------------------------------------------------
|
|
1012
|
+
im_base_gens = [pa+pb+pc, pa*pb+pa*pc+pb*pc, pa*pb*pc]
|
|
1013
|
+
base_ring_embedding = extension_ring.coerce_map_from(base_ring)
|
|
1014
|
+
|
|
1015
|
+
def check_base_ring_embedding(base_ring_embedding):
|
|
1016
|
+
if base_ring_embedding is None:
|
|
1017
|
+
return False
|
|
1018
|
+
try:
|
|
1019
|
+
ipu = base_ring_embedding(pu)
|
|
1020
|
+
ipv = base_ring_embedding(pv)
|
|
1021
|
+
ipw = base_ring_embedding(pw)
|
|
1022
|
+
if [ipu, ipv, ipw] != im_base_gens:
|
|
1023
|
+
return False
|
|
1024
|
+
except (TypeError, ValueError):
|
|
1025
|
+
return False
|
|
1026
|
+
return True
|
|
1027
|
+
|
|
1028
|
+
if check_base_ring_embedding(base_ring_embedding):
|
|
1029
|
+
verbose('base_ring_embedding defined via coercion', level=2)
|
|
1030
|
+
else:
|
|
1031
|
+
base_ring_embedding = extension_ring.convert_map_from(base_ring)
|
|
1032
|
+
if check_base_ring_embedding(base_ring_embedding):
|
|
1033
|
+
verbose('base_ring_embedding defined via conversion', level=2)
|
|
1034
|
+
else:
|
|
1035
|
+
try:
|
|
1036
|
+
if base_ring.gens() == cubic_equation_parameters:
|
|
1037
|
+
base_ring_embedding = base_ring.hom(im_base_gens, codomain=extension_ring)
|
|
1038
|
+
except (TypeError, ValueError):
|
|
1039
|
+
base_ring_embedding = None
|
|
1040
|
+
|
|
1041
|
+
if base_ring_embedding is None:
|
|
1042
|
+
warn('Warning: no base_ring_embedding found')
|
|
1043
|
+
|
|
1044
|
+
# ----------------------------------------------------------------------
|
|
1045
|
+
# registering variables
|
|
1046
|
+
# ----------------------------------------------------------------------
|
|
1047
|
+
self._extension_ring = extension_ring
|
|
1048
|
+
self._base_ring_embedding = base_ring_embedding
|
|
1049
|
+
self._ring_of_definition_map = base_ring.convert_map_from(ring_of_definition)
|
|
1050
|
+
self._generic_extension_ring_map = extension_ring.convert_map_from(generic_extension_ring)
|
|
1051
|
+
self._cubic_equation_parameters = cubic_equation_parameters
|
|
1052
|
+
self._cubic_equation_roots = cubic_equation_roots
|
|
1053
|
+
|
|
1054
|
+
# ----------------------------------------------------------------------
|
|
1055
|
+
# defining the associated group algebras
|
|
1056
|
+
# ----------------------------------------------------------------------
|
|
1057
|
+
from sage.algebras.group_algebra import GroupAlgebra
|
|
1058
|
+
self._cubic_braid_group_algebra = GroupAlgebra(self._cubic_braid_group, R=base_ring)
|
|
1059
|
+
self._braid_group_algebra = GroupAlgebra(self._braid_group, R=base_ring)
|
|
1060
|
+
|
|
1061
|
+
# ----------------------------------------------------------------------
|
|
1062
|
+
# Setup of Basis
|
|
1063
|
+
# ----------------------------------------------------------------------
|
|
1064
|
+
# Fetch Ivan Marin's basis for the algebras on at most 4 strands.
|
|
1065
|
+
# An explicit list of basis element which represents a flat deformation
|
|
1066
|
+
# of the cubic braid group is only available in the cases where the
|
|
1067
|
+
# number of strands is less than 5. In the case of exactly 5 strands
|
|
1068
|
+
# it is known that such a basis exist by work of Ivan Marin in
|
|
1069
|
+
# [Marin2012] but it can not be calculated, right now. In the (infinite
|
|
1070
|
+
# dimensional) cases of more than 5 strands it is even an open problem
|
|
1071
|
+
# if the cubic Hecke algebra is a flat deformation of the group algebra
|
|
1072
|
+
# of the corresponding cubic braid group.
|
|
1073
|
+
#
|
|
1074
|
+
# But anyway, we will take the elements of the cubic braid group as a
|
|
1075
|
+
# basis of the cubic Hecke algebra in all cases. Beware that this might
|
|
1076
|
+
# not cover the whole cubic Hecke algebra if the number of strands is
|
|
1077
|
+
# larger than 4
|
|
1078
|
+
#
|
|
1079
|
+
# Internally the basis is implemented using two lists one of which
|
|
1080
|
+
# consists of fixed braid pre images of the basis elements and the other
|
|
1081
|
+
# (redundant) of the corresponding Tietze expressions.
|
|
1082
|
+
#
|
|
1083
|
+
# In the case of less than 5 strands these lists are directly obtained
|
|
1084
|
+
# from the list calculated by Ivan Marin available at
|
|
1085
|
+
#
|
|
1086
|
+
# In the other cases these lists are implemented as growing list which
|
|
1087
|
+
# is initialized with Marin's list and is extended on demand.
|
|
1088
|
+
# ----------------------------------------------------------------------
|
|
1089
|
+
db = self._database
|
|
1090
|
+
ns = min(self._nstrands, 4)
|
|
1091
|
+
self._basis_static = db.read(db.section.basis, nstrands=ns)
|
|
1092
|
+
|
|
1093
|
+
# ----------------------------------------------------------------------
|
|
1094
|
+
# defining the algebra itself
|
|
1095
|
+
# ----------------------------------------------------------------------
|
|
1096
|
+
if self._cubic_braid_group.is_finite():
|
|
1097
|
+
from sage.categories.finite_dimensional_algebras_with_basis import FiniteDimensionalAlgebrasWithBasis
|
|
1098
|
+
category = FiniteDimensionalAlgebrasWithBasis(base_ring)
|
|
1099
|
+
else:
|
|
1100
|
+
from sage.categories.algebras_with_basis import AlgebrasWithBasis
|
|
1101
|
+
category = AlgebrasWithBasis(base_ring)
|
|
1102
|
+
|
|
1103
|
+
CombinatorialFreeModule.__init__(self, base_ring, self._cubic_braid_group,
|
|
1104
|
+
prefix='', names=names, bracket=False,
|
|
1105
|
+
category=category)
|
|
1106
|
+
|
|
1107
|
+
# ----------------------------------------------------------------------
|
|
1108
|
+
# init the attributes being set on demand
|
|
1109
|
+
# ----------------------------------------------------------------------
|
|
1110
|
+
self._cubic_hecke_subalgebra = None
|
|
1111
|
+
self._mirror_image = None
|
|
1112
|
+
self._is_mirror = False
|
|
1113
|
+
self._base_ring_mirror = None
|
|
1114
|
+
self._gens_reg_repres_matrix = {}
|
|
1115
|
+
|
|
1116
|
+
# ----------------------------------------------------------------------
|
|
1117
|
+
# initializing the basis extension (in case of more than 4 strands)
|
|
1118
|
+
# ----------------------------------------------------------------------
|
|
1119
|
+
self._init_basis_extension()
|
|
1120
|
+
|
|
1121
|
+
############################################################################
|
|
1122
|
+
# --------------------------------------------------------------------------
|
|
1123
|
+
# overloaded inherited methods
|
|
1124
|
+
# --------------------------------------------------------------------------
|
|
1125
|
+
############################################################################
|
|
1126
|
+
def _repr_(self):
|
|
1127
|
+
r"""
|
|
1128
|
+
Return a string representation.
|
|
1129
|
+
|
|
1130
|
+
OUTPUT: string describing ``self``
|
|
1131
|
+
|
|
1132
|
+
TESTS::
|
|
1133
|
+
|
|
1134
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
1135
|
+
sage: CHA3 # indirect doctest
|
|
1136
|
+
Cubic Hecke algebra on 3 strands
|
|
1137
|
+
over Multivariate Polynomial Ring in u, v, w
|
|
1138
|
+
over Integer Ring localized at (w,)
|
|
1139
|
+
with cubic equation: h^3 - u*h^2 + v*h - w = 0
|
|
1140
|
+
"""
|
|
1141
|
+
s = 'Cubic Hecke algebra on %s strands over %s with cubic equation: %s = 0'
|
|
1142
|
+
return s % (self._nstrands, self.base_ring(), self.cubic_equation())
|
|
1143
|
+
|
|
1144
|
+
def _element_constructor_(self, x):
|
|
1145
|
+
r"""
|
|
1146
|
+
Extensions to the element constructor of class :class:`CombinatorialFreeModule`.
|
|
1147
|
+
|
|
1148
|
+
New functionalities are:
|
|
1149
|
+
|
|
1150
|
+
- constructing element from a braid (group homomorphism)
|
|
1151
|
+
- constructing element from a braid giving in Tietze form
|
|
1152
|
+
- constructing element from an element of the braid group algebra
|
|
1153
|
+
(algebra homomorphism)
|
|
1154
|
+
- constructing element from an element of the cubic braid group
|
|
1155
|
+
algebra (module homomorphism)
|
|
1156
|
+
- constructing element from an element of an other cubic Hecke
|
|
1157
|
+
algebra over an other base ring or with less strands
|
|
1158
|
+
- constructing element from an element of the mirror image of
|
|
1159
|
+
``self`` (see method mirror_image)
|
|
1160
|
+
|
|
1161
|
+
INPUT:
|
|
1162
|
+
|
|
1163
|
+
- ``x`` -- can be one of the following:
|
|
1164
|
+
|
|
1165
|
+
* an instance of the element class of ``self`` (but possible
|
|
1166
|
+
to a different parent)
|
|
1167
|
+
* an instance of the element class of the braid group
|
|
1168
|
+
* an instance of the element class of the braid group algebra
|
|
1169
|
+
over the base ring of ``self``
|
|
1170
|
+
* an instance of the element class of the cubic braid group
|
|
1171
|
+
* an instance of the element class of the cubic braid group
|
|
1172
|
+
algebra over the base ring of ``self``
|
|
1173
|
+
* an instance of the element class of the mirror image of
|
|
1174
|
+
``self``
|
|
1175
|
+
* a tuple representing a braid in Tietze form
|
|
1176
|
+
* any other object which works for the element constructor
|
|
1177
|
+
of :class:`CombinatorialFreeModule`
|
|
1178
|
+
|
|
1179
|
+
EXAMPLES::
|
|
1180
|
+
|
|
1181
|
+
sage: B2 = BraidGroup(2)
|
|
1182
|
+
sage: b, = B2.gens()
|
|
1183
|
+
sage: b2 = b**2
|
|
1184
|
+
sage: CB2 = CubicBraidGroup(2)
|
|
1185
|
+
sage: cb, = CB2.gens()
|
|
1186
|
+
sage: cb2 = cb**2
|
|
1187
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
1188
|
+
sage: CHA2(b2)
|
|
1189
|
+
w*c^-1 + u*c - v
|
|
1190
|
+
sage: CHA2(cb2)
|
|
1191
|
+
c^-1
|
|
1192
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
1193
|
+
sage: B3 = CHA3.braid_group()
|
|
1194
|
+
sage: CB3 = CHA3.cubic_braid_group()
|
|
1195
|
+
sage: CB3GA = CHA3.cubic_braid_group_algebra()
|
|
1196
|
+
sage: braid = B3((1,2,2,-1,2,1,1,-1)); braid
|
|
1197
|
+
c0*c1^2*c0^-1*c1*c0
|
|
1198
|
+
sage: img_braid = CHA3(braid); img_braid
|
|
1199
|
+
u*w*(c0^-1*c1)^2 + u*v*c0*c1^-1*c0 - u^2*w*c0^-1*c1*c0^-1
|
|
1200
|
+
- u*v*c1*c0^-1*c1 - (u*v*w-w^2)*c0^-1*c1^-1 + u^2*c0*c1*c0^-1*c1
|
|
1201
|
+
- (u^2*v-u*w)*c0*c1^-1 + u^2*v*c1*c0^-1 + (u^2-v)*c1*c0
|
|
1202
|
+
- u^3*c0*c1*c0^-1 + (u*v^2-v*w)*c1^-1
|
|
1203
|
+
sage: cbraid = CB3(braid); cbraid
|
|
1204
|
+
c0*c1^2*c0^-1*c1*c0
|
|
1205
|
+
sage: img_cbraid = CHA3(cbraid); img_cbraid
|
|
1206
|
+
c0^-1*c1^-1
|
|
1207
|
+
sage: img_cbraid_back = img_cbraid.cubic_braid_group_algebra_pre_image()
|
|
1208
|
+
sage: img_cbraid_back in CB3GA
|
|
1209
|
+
True
|
|
1210
|
+
sage: img_cbraid_back == CB3GA(cbraid)
|
|
1211
|
+
True
|
|
1212
|
+
"""
|
|
1213
|
+
braid_grp = self.braid_group()
|
|
1214
|
+
braid_grp_alg = self.braid_group_algebra()
|
|
1215
|
+
braid_img = self._braid_image
|
|
1216
|
+
|
|
1217
|
+
cbraid_grp = self.cubic_braid_group()
|
|
1218
|
+
cbraid_grp_alg = self.cubic_braid_group_algebra()
|
|
1219
|
+
cbraid_img = self._cubic_braid_image
|
|
1220
|
+
|
|
1221
|
+
base_ring = self.base_ring()
|
|
1222
|
+
ngens = self.ngens()
|
|
1223
|
+
params = self.cubic_equation_parameters()
|
|
1224
|
+
|
|
1225
|
+
# ----------------------------------------------------------------------
|
|
1226
|
+
# if x is a tuple we may interpret it as a braid in Tietze form
|
|
1227
|
+
# ----------------------------------------------------------------------
|
|
1228
|
+
xb = x
|
|
1229
|
+
if type(x) in (tuple, list):
|
|
1230
|
+
x = tuple(x)
|
|
1231
|
+
result = self._tietze_to_finite_sub_basis_monomial(x)
|
|
1232
|
+
if result is not None:
|
|
1233
|
+
# x represents a monomial
|
|
1234
|
+
verbose('end from tuple %s: %s' % (x, result), level=2)
|
|
1235
|
+
return result
|
|
1236
|
+
|
|
1237
|
+
try:
|
|
1238
|
+
xb = braid_grp(x)
|
|
1239
|
+
except (TypeError, ValueError, NotImplementedError):
|
|
1240
|
+
pass
|
|
1241
|
+
|
|
1242
|
+
# ----------------------------------------------------------------------
|
|
1243
|
+
# embedding of an element of an other cubic Hecke algebra with lower
|
|
1244
|
+
# number of strands but same base ring
|
|
1245
|
+
# ----------------------------------------------------------------------
|
|
1246
|
+
if isinstance(xb, CubicHeckeElement):
|
|
1247
|
+
other_cha = xb.parent()
|
|
1248
|
+
other_base_ring = other_cha.base_ring()
|
|
1249
|
+
other_ngens = other_cha.ngens()
|
|
1250
|
+
other_params = other_cha.cubic_equation_parameters()
|
|
1251
|
+
if other_base_ring != base_ring:
|
|
1252
|
+
if other_ngens == ngens:
|
|
1253
|
+
xbv = xb.to_vector()
|
|
1254
|
+
img_xbv = vector([self.base_ring()(cf) for cf in xbv])
|
|
1255
|
+
return self.from_vector(img_xbv)
|
|
1256
|
+
elif other_ngens < ngens:
|
|
1257
|
+
sub_alg = self.cubic_hecke_subalgebra(other_ngens+1)
|
|
1258
|
+
return self(sub_alg(xb))
|
|
1259
|
+
|
|
1260
|
+
elif other_ngens < ngens and other_params == params:
|
|
1261
|
+
cbraid_preimg = xb.cubic_braid_group_algebra_pre_image()
|
|
1262
|
+
other_cbga = other_cha.cubic_braid_group_algebra()
|
|
1263
|
+
|
|
1264
|
+
def fc(ele):
|
|
1265
|
+
return cbraid_img(cbraid_grp(ele))
|
|
1266
|
+
result = other_cbga._apply_module_morphism(cbraid_preimg, fc, codomain=self)
|
|
1267
|
+
verbose('end from smaller cubic Hecke algebra %s: %s' % (xb, result), level=2)
|
|
1268
|
+
return result
|
|
1269
|
+
|
|
1270
|
+
elif other_cha == self._mirror_image:
|
|
1271
|
+
result = other_cha.mirror_isomorphism(xb)
|
|
1272
|
+
verbose('end from mirror image %s: %s' % (xb, result), level=2)
|
|
1273
|
+
return result
|
|
1274
|
+
|
|
1275
|
+
# ----------------------------------------------------------------------
|
|
1276
|
+
# if xb is an element of the braid group or its group algebra over the
|
|
1277
|
+
# same base ring the algebra morphism self._braid_image is applied
|
|
1278
|
+
# ----------------------------------------------------------------------
|
|
1279
|
+
if isinstance(xb, braid_grp_alg.element_class) and xb in braid_grp_alg:
|
|
1280
|
+
|
|
1281
|
+
def fb(ele):
|
|
1282
|
+
return braid_img(ele)
|
|
1283
|
+
result = braid_grp_alg._apply_module_morphism(xb, fb, codomain=self)
|
|
1284
|
+
verbose('end from braid_group algebra %s: %s' % (xb, result), level=2)
|
|
1285
|
+
return result
|
|
1286
|
+
|
|
1287
|
+
from sage.groups.braid import Braid
|
|
1288
|
+
if isinstance(xb, Braid) and xb.strands() == self._nstrands:
|
|
1289
|
+
result = braid_img(xb)
|
|
1290
|
+
verbose('end from braid_group %s: %s' % (xb, result), level=2)
|
|
1291
|
+
return result
|
|
1292
|
+
|
|
1293
|
+
# ----------------------------------------------------------------------
|
|
1294
|
+
# if xb is an element of the cubic_braid group or its group algebra over
|
|
1295
|
+
# the same base ring xb the module morphism self._braid_image is applied
|
|
1296
|
+
# ----------------------------------------------------------------------
|
|
1297
|
+
if isinstance(xb, cbraid_grp_alg.element_class) and xb in cbraid_grp_alg:
|
|
1298
|
+
result = cbraid_grp_alg._apply_module_morphism(xb, cbraid_img, codomain=self)
|
|
1299
|
+
verbose('end from cubic braid_group algebra %s: %s' % (xb, result), level=2)
|
|
1300
|
+
return result
|
|
1301
|
+
|
|
1302
|
+
from sage.groups.cubic_braid import CubicBraidElement
|
|
1303
|
+
if isinstance(xb, CubicBraidElement) and xb.parent().strands() == self._nstrands:
|
|
1304
|
+
result = cbraid_img(xb)
|
|
1305
|
+
verbose('end from cubic braid_group %s: %s' % (xb, result), level=2)
|
|
1306
|
+
return result
|
|
1307
|
+
|
|
1308
|
+
# ----------------------------------------------------------------------
|
|
1309
|
+
# doing the default construction by inheritance
|
|
1310
|
+
# ----------------------------------------------------------------------
|
|
1311
|
+
result = CombinatorialFreeModule._element_constructor_(self, x)
|
|
1312
|
+
verbose('end (default) %s: %s' % (xb, result), level=2)
|
|
1313
|
+
return result
|
|
1314
|
+
|
|
1315
|
+
def get_order(self):
|
|
1316
|
+
r"""
|
|
1317
|
+
Return an ordering of the basis of ``self``.
|
|
1318
|
+
|
|
1319
|
+
EXAMPLES::
|
|
1320
|
+
|
|
1321
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
1322
|
+
sage: len(CHA3.get_order())
|
|
1323
|
+
24
|
|
1324
|
+
"""
|
|
1325
|
+
# The reason we have overridden this is that we have to care about
|
|
1326
|
+
# the dynamical growth of thefinite sub basis used for the
|
|
1327
|
+
# calculation in case of more than 4 strands.
|
|
1328
|
+
|
|
1329
|
+
if self._nstrands < 5:
|
|
1330
|
+
return self._order
|
|
1331
|
+
|
|
1332
|
+
# detect change of _order of sub algebra
|
|
1333
|
+
sub_alg = self.cubic_hecke_subalgebra()
|
|
1334
|
+
former_len_sub = len(sub_alg._order)
|
|
1335
|
+
sub_order = sub_alg.get_order()
|
|
1336
|
+
if former_len_sub == len(sub_order):
|
|
1337
|
+
if len(self._order) == former_len_sub + len(self._basis_extension):
|
|
1338
|
+
return self._order
|
|
1339
|
+
# _order has changed! re-calculation necessary:
|
|
1340
|
+
cbg = self.cubic_braid_group()
|
|
1341
|
+
sub_order = [cbg(cb) for cb in sub_order]
|
|
1342
|
+
self._order = sub_order + [cbg(tup) for tup in self._basis_extension]
|
|
1343
|
+
return self._order
|
|
1344
|
+
|
|
1345
|
+
def _order_key(self, x):
|
|
1346
|
+
"""
|
|
1347
|
+
Return a key for `x` compatible with the term order.
|
|
1348
|
+
|
|
1349
|
+
INPUT:
|
|
1350
|
+
|
|
1351
|
+
- ``x`` -- indices of the basis of ``self``
|
|
1352
|
+
|
|
1353
|
+
EXAMPLES::
|
|
1354
|
+
|
|
1355
|
+
sage: A = CombinatorialFreeModule(QQ, ['x','y','a','b'])
|
|
1356
|
+
sage: A.set_order(['x', 'y', 'a', 'b'])
|
|
1357
|
+
sage: A._order_key('x')
|
|
1358
|
+
0
|
|
1359
|
+
sage: A._order_key('y')
|
|
1360
|
+
1
|
|
1361
|
+
sage: A._order_key('a')
|
|
1362
|
+
2
|
|
1363
|
+
"""
|
|
1364
|
+
try:
|
|
1365
|
+
return self._rank_basis(x)
|
|
1366
|
+
except AttributeError:
|
|
1367
|
+
from sage.combinat.ranker import rank_from_list
|
|
1368
|
+
self._rank_basis = rank_from_list(self._order)
|
|
1369
|
+
return self._rank_basis(x)
|
|
1370
|
+
|
|
1371
|
+
def _dense_free_module(self, base_ring=None):
|
|
1372
|
+
r"""
|
|
1373
|
+
Return a dense free module with the same dimension as ``self``.
|
|
1374
|
+
|
|
1375
|
+
This overwrites the corresponding method of :class:`CombinatorialFreeModule`.
|
|
1376
|
+
The only difference is, that the dimension is not the dimension of
|
|
1377
|
+
``self`` but the dimension of the sub-module generated by the dynamically
|
|
1378
|
+
growing basis given by the :meth:`get_order`. In particular there is
|
|
1379
|
+
no difference if the number of strands is less than 5.
|
|
1380
|
+
|
|
1381
|
+
EXAMPLES::
|
|
1382
|
+
|
|
1383
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
1384
|
+
sage: CHA2._dense_free_module()
|
|
1385
|
+
Ambient free module of rank 3
|
|
1386
|
+
over the integral domain Multivariate Polynomial Ring in u, v, w
|
|
1387
|
+
over Integer Ring localized at (w,)
|
|
1388
|
+
"""
|
|
1389
|
+
if base_ring is None:
|
|
1390
|
+
base_ring = self.base_ring()
|
|
1391
|
+
from sage.modules.free_module import FreeModule
|
|
1392
|
+
return FreeModule(base_ring, len(self.get_order()))
|
|
1393
|
+
|
|
1394
|
+
def ngens(self):
|
|
1395
|
+
r"""
|
|
1396
|
+
The number of generators of the algebra.
|
|
1397
|
+
|
|
1398
|
+
EXAMPLES::
|
|
1399
|
+
|
|
1400
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
1401
|
+
sage: CHA2.ngens()
|
|
1402
|
+
1
|
|
1403
|
+
"""
|
|
1404
|
+
return self._nstrands - 1
|
|
1405
|
+
|
|
1406
|
+
def algebra_generators(self):
|
|
1407
|
+
r"""
|
|
1408
|
+
Return the algebra generators of ``self``.
|
|
1409
|
+
|
|
1410
|
+
EXAMPLES::
|
|
1411
|
+
|
|
1412
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
1413
|
+
sage: CHA2.algebra_generators()
|
|
1414
|
+
Finite family {c: c}
|
|
1415
|
+
"""
|
|
1416
|
+
from sage.sets.family import Family
|
|
1417
|
+
return Family(self._cubic_braid_group.gens(), self.monomial)
|
|
1418
|
+
|
|
1419
|
+
def gens(self) -> tuple:
|
|
1420
|
+
r"""
|
|
1421
|
+
Return the generators of ``self``.
|
|
1422
|
+
|
|
1423
|
+
EXAMPLES::
|
|
1424
|
+
|
|
1425
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
1426
|
+
sage: CHA2.gens()
|
|
1427
|
+
(c,)
|
|
1428
|
+
"""
|
|
1429
|
+
return tuple(self.algebra_generators())
|
|
1430
|
+
|
|
1431
|
+
def gen(self, i):
|
|
1432
|
+
r"""
|
|
1433
|
+
The ``i``-th generator of the algebra.
|
|
1434
|
+
|
|
1435
|
+
EXAMPLES::
|
|
1436
|
+
|
|
1437
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
1438
|
+
sage: CHA2.gen(0)
|
|
1439
|
+
c
|
|
1440
|
+
"""
|
|
1441
|
+
return self.gens()[i]
|
|
1442
|
+
|
|
1443
|
+
def one_basis(self):
|
|
1444
|
+
r"""
|
|
1445
|
+
Return the index of the basis element for the identity element
|
|
1446
|
+
in the cubic braid group.
|
|
1447
|
+
|
|
1448
|
+
EXAMPLES::
|
|
1449
|
+
|
|
1450
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
1451
|
+
sage: CHA2.one_basis()
|
|
1452
|
+
1
|
|
1453
|
+
"""
|
|
1454
|
+
return self.cubic_braid_group().one()
|
|
1455
|
+
|
|
1456
|
+
def _an_element_(self):
|
|
1457
|
+
r"""
|
|
1458
|
+
Overwrite the original method from :mod:`~sage.combinat.free_module`
|
|
1459
|
+
to obtain a more interesting element for ``TestSuite``.
|
|
1460
|
+
|
|
1461
|
+
EXAMPLES::
|
|
1462
|
+
|
|
1463
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
1464
|
+
sage: CHA2.an_element() # indirect doctest
|
|
1465
|
+
v*c - ((v*w-u)/w)
|
|
1466
|
+
"""
|
|
1467
|
+
n = self.ngens() + 1
|
|
1468
|
+
base_ring = self.base_ring()
|
|
1469
|
+
u, v, w = (base_ring(para) for para in self._cubic_equation_parameters)
|
|
1470
|
+
const = (u*~w - v) * self.one()
|
|
1471
|
+
|
|
1472
|
+
gens = self.gens()
|
|
1473
|
+
first_gens = [gen for gen in gens if gens.index(gen) < 3]
|
|
1474
|
+
if n == 2:
|
|
1475
|
+
c1, = first_gens
|
|
1476
|
+
return const + v*c1
|
|
1477
|
+
elif n == 3:
|
|
1478
|
+
c1, c2 = first_gens
|
|
1479
|
+
return const + v*c1 - w*c1*~c2 + u*c2
|
|
1480
|
+
else:
|
|
1481
|
+
c1, c2, c3 = first_gens
|
|
1482
|
+
return const + v*c1*~c3 - w*c1*~c2 + u*c3*c2
|
|
1483
|
+
|
|
1484
|
+
@cached_method
|
|
1485
|
+
def chevie(self):
|
|
1486
|
+
r"""
|
|
1487
|
+
Return the ``GAP3``-``CHEVIE`` realization of the corresponding
|
|
1488
|
+
cyclotomic Hecke algebra in the finite-dimensional case.
|
|
1489
|
+
|
|
1490
|
+
EXAMPLES::
|
|
1491
|
+
|
|
1492
|
+
sage: CHA3 = algebras.CubicHecke(3) # optional gap3
|
|
1493
|
+
sage: CHA3.chevie() # optional gap3
|
|
1494
|
+
Hecke(G4,[[a,b,c]])
|
|
1495
|
+
"""
|
|
1496
|
+
from sage.combinat.root_system.reflection_group_real import is_chevie_available
|
|
1497
|
+
if not is_chevie_available():
|
|
1498
|
+
raise NotImplementedError('this functionality needs GAP3 with package CHEVIE')
|
|
1499
|
+
|
|
1500
|
+
n = self._nstrands
|
|
1501
|
+
if n == 3:
|
|
1502
|
+
st_number = 4
|
|
1503
|
+
elif n == 4:
|
|
1504
|
+
st_number = 25
|
|
1505
|
+
elif n == 5:
|
|
1506
|
+
st_number = 32
|
|
1507
|
+
else:
|
|
1508
|
+
raise NotImplementedError('CHEVIE version doesn\'t exist for this cubic Hecke algebra')
|
|
1509
|
+
|
|
1510
|
+
gap3_function_str = """function(st_number, na, nb,nc)
|
|
1511
|
+
local a, b, c, # embedded Indeterminates
|
|
1512
|
+
ReflGroup, # Reflection group
|
|
1513
|
+
HeckeAlg; # Hecke algebra
|
|
1514
|
+
|
|
1515
|
+
a := Mvp(na); b := Mvp(nb); c := Mvp(nc);
|
|
1516
|
+
ReflGroup := ComplexReflectionGroup(st_number);
|
|
1517
|
+
HeckeAlg := Hecke(ReflGroup, [[a, b, c]] );
|
|
1518
|
+
return HeckeAlg;
|
|
1519
|
+
end;"""
|
|
1520
|
+
|
|
1521
|
+
from sage.interfaces.gap3 import gap3
|
|
1522
|
+
gap3_function = gap3(gap3_function_str)
|
|
1523
|
+
na, nb, nc = ('\"%s\"' % indet for indet in self.extension_ring(generic=True).variable_names())
|
|
1524
|
+
return gap3_function(st_number, na, nb, nc)
|
|
1525
|
+
|
|
1526
|
+
@cached_method
|
|
1527
|
+
def product_on_basis(self, g1, g2):
|
|
1528
|
+
r"""
|
|
1529
|
+
Return product on basis elements indexed by ``g1`` and ``g2``.
|
|
1530
|
+
|
|
1531
|
+
EXAMPLES::
|
|
1532
|
+
|
|
1533
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
1534
|
+
sage: g = CHA3.basis().keys().an_element(); g
|
|
1535
|
+
c0*c1
|
|
1536
|
+
sage: CHA3.product_on_basis(g, ~g)
|
|
1537
|
+
1
|
|
1538
|
+
sage: CHA3.product_on_basis(g, g)
|
|
1539
|
+
w*c0^-1*c1*c0 - v*c1*c0 + u*c0*c1*c0
|
|
1540
|
+
"""
|
|
1541
|
+
# ----------------------------------------------------------------------
|
|
1542
|
+
# short way for multiplications with one
|
|
1543
|
+
# ----------------------------------------------------------------------
|
|
1544
|
+
if g1 == g1.parent().one():
|
|
1545
|
+
return self.monomial(g2)
|
|
1546
|
+
|
|
1547
|
+
if g2 == g2.parent().one():
|
|
1548
|
+
return self.monomial(g1)
|
|
1549
|
+
|
|
1550
|
+
# ----------------------------------------------------------------------
|
|
1551
|
+
# convert to monomials
|
|
1552
|
+
# ----------------------------------------------------------------------
|
|
1553
|
+
g1 = self.monomial(g1)
|
|
1554
|
+
g2 = self.monomial(g2)
|
|
1555
|
+
|
|
1556
|
+
result = None
|
|
1557
|
+
|
|
1558
|
+
g1_Tietze = g1.Tietze()
|
|
1559
|
+
g2_Tietze = g2.Tietze()
|
|
1560
|
+
|
|
1561
|
+
verbose('Tietze established (%s, %s)' % (g1_Tietze, g2_Tietze), level=2)
|
|
1562
|
+
|
|
1563
|
+
# ----------------------------------------------------------------------
|
|
1564
|
+
# The product is calculated from the corresponding product of the braids
|
|
1565
|
+
# ----------------------------------------------------------------------
|
|
1566
|
+
braid_group = self.braid_group()
|
|
1567
|
+
braid_product = braid_group(g1_Tietze+g2_Tietze)
|
|
1568
|
+
result = self._braid_image(braid_product)
|
|
1569
|
+
return result
|
|
1570
|
+
|
|
1571
|
+
############################################################################
|
|
1572
|
+
# --------------------------------------------------------------------------
|
|
1573
|
+
# local methods
|
|
1574
|
+
# --------------------------------------------------------------------------
|
|
1575
|
+
############################################################################
|
|
1576
|
+
def _basis_tietze(self):
|
|
1577
|
+
r"""
|
|
1578
|
+
Return the complete finite sub basis as list of Tietze tuples.
|
|
1579
|
+
|
|
1580
|
+
EXAMPLES::
|
|
1581
|
+
|
|
1582
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
1583
|
+
sage: CHA2._basis_tietze()
|
|
1584
|
+
[[], [1], [-1]]
|
|
1585
|
+
"""
|
|
1586
|
+
if self._nstrands > 4:
|
|
1587
|
+
self_sub = self.cubic_hecke_subalgebra()
|
|
1588
|
+
result_list = self_sub._basis_tietze() + self._basis_extension
|
|
1589
|
+
else:
|
|
1590
|
+
result_list = self._basis_static
|
|
1591
|
+
return result_list
|
|
1592
|
+
|
|
1593
|
+
def _tietze_to_finite_sub_basis_monomial(self, tietze_tup):
|
|
1594
|
+
r"""
|
|
1595
|
+
Return the monomial corresponding to a Tietze tuple
|
|
1596
|
+
if it is in the finite sub basis, otherwise return ``None``.
|
|
1597
|
+
|
|
1598
|
+
EXAMPLES::
|
|
1599
|
+
|
|
1600
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
1601
|
+
sage: CHA2._tietze_to_finite_sub_basis_monomial([-1])
|
|
1602
|
+
c^-1
|
|
1603
|
+
sage: CHA2._tietze_to_finite_sub_basis_monomial([-2]) is None
|
|
1604
|
+
True
|
|
1605
|
+
"""
|
|
1606
|
+
tietze_list = list(tietze_tup)
|
|
1607
|
+
in_basis = False
|
|
1608
|
+
if tietze_list in self._basis_tietze():
|
|
1609
|
+
in_basis = True
|
|
1610
|
+
elif self._nstrands > 4:
|
|
1611
|
+
fsb_dict = self._finite_sub_basis_tuples
|
|
1612
|
+
if tietze_list in list(fsb_dict.values()):
|
|
1613
|
+
in_basis = True
|
|
1614
|
+
elif self.cubic_hecke_subalgebra()._tietze_to_finite_sub_basis_monomial(tietze_tup) is not None:
|
|
1615
|
+
in_basis = True
|
|
1616
|
+
|
|
1617
|
+
if in_basis:
|
|
1618
|
+
# tietze_tup represents a monomial
|
|
1619
|
+
B = self.basis()
|
|
1620
|
+
cb = self.cubic_braid_group()(tietze_tup)
|
|
1621
|
+
return B[cb]
|
|
1622
|
+
|
|
1623
|
+
return None
|
|
1624
|
+
|
|
1625
|
+
@cached_method
|
|
1626
|
+
def _create_matrix_list_for_one(self, representation_type):
|
|
1627
|
+
r"""
|
|
1628
|
+
Return the matrix list for the given representation type
|
|
1629
|
+
for ``self.one()``.
|
|
1630
|
+
|
|
1631
|
+
EXAMPLES::
|
|
1632
|
+
|
|
1633
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
1634
|
+
sage: CHA2._create_matrix_list_for_one(CHA2.repr_type.SplitIrredMarin)
|
|
1635
|
+
[[1], [1], [1]]
|
|
1636
|
+
sage: CHA2._create_matrix_list_for_one(CHA2.repr_type.RegularLeft)
|
|
1637
|
+
[
|
|
1638
|
+
[1 0 0]
|
|
1639
|
+
[0 1 0]
|
|
1640
|
+
[0 0 1]
|
|
1641
|
+
]
|
|
1642
|
+
"""
|
|
1643
|
+
n = self._nstrands
|
|
1644
|
+
if representation_type.is_split():
|
|
1645
|
+
gen_base_ring = self.extension_ring(generic=True)
|
|
1646
|
+
rep_ind = [rep.internal_index() for rep in AbsIrreducibeRep if rep.number_gens() == n - 1]
|
|
1647
|
+
rep_dim = [rep.dimension() for rep in AbsIrreducibeRep if rep.number_gens() == n - 1]
|
|
1648
|
+
dim_sort = [rep_dim[rep_ind.index(i)] for i in range(len(rep_ind))]
|
|
1649
|
+
matrix_list = [MatrixSpace(gen_base_ring, dim_sort[i]).one() for i in range(len(rep_ind))]
|
|
1650
|
+
else:
|
|
1651
|
+
gen_base_ring = self.base_ring(generic=True)
|
|
1652
|
+
matrix_list = [MatrixSpace(gen_base_ring, self.dimension()).one()]
|
|
1653
|
+
return matrix_list
|
|
1654
|
+
|
|
1655
|
+
@cached_method
|
|
1656
|
+
def _fetch_matrix_list_from_chevie(self, number):
|
|
1657
|
+
r"""
|
|
1658
|
+
This method reads irreducible representation of the cubic Hecke algebra
|
|
1659
|
+
via the *GAP3* interface from *CHEVIE*.
|
|
1660
|
+
|
|
1661
|
+
INPUT:
|
|
1662
|
+
|
|
1663
|
+
- ``number`` -- integer; number of the representation according to
|
|
1664
|
+
*CHEVIE*
|
|
1665
|
+
|
|
1666
|
+
OUTPUT:
|
|
1667
|
+
|
|
1668
|
+
A list of representing matrices over the generic extension ring, one
|
|
1669
|
+
matrix for each generators.
|
|
1670
|
+
|
|
1671
|
+
EXAMPLES::
|
|
1672
|
+
|
|
1673
|
+
sage: CHA3 = algebras.CubicHecke(3) # optional gap3
|
|
1674
|
+
sage: CHA3._fetch_matrix_list_from_chevie(5) # optional gap3
|
|
1675
|
+
[
|
|
1676
|
+
[ a 0] [c c]
|
|
1677
|
+
[-a c], [0 a]
|
|
1678
|
+
]
|
|
1679
|
+
"""
|
|
1680
|
+
GER = self.extension_ring(generic=True)
|
|
1681
|
+
gap3_result = self.chevie().Representations(number)
|
|
1682
|
+
from sage.matrix.constructor import matrix
|
|
1683
|
+
matrix_list_gens = [matrix(GER, mat_gap) for mat_gap in gap3_result]
|
|
1684
|
+
for m in matrix_list_gens:
|
|
1685
|
+
m.set_immutable()
|
|
1686
|
+
return matrix_list_gens
|
|
1687
|
+
|
|
1688
|
+
# --------------------------------------------------------------------------
|
|
1689
|
+
# Methods for test_suite
|
|
1690
|
+
# --------------------------------------------------------------------------
|
|
1691
|
+
# _test_ring_constructions
|
|
1692
|
+
# --------------------------------------------------------------------------
|
|
1693
|
+
def _test_ring_constructions(self, **options):
|
|
1694
|
+
r"""
|
|
1695
|
+
Method called by :class:`TestSuite`.
|
|
1696
|
+
|
|
1697
|
+
The following is checked:
|
|
1698
|
+
|
|
1699
|
+
- construction of base_ring and extension ring
|
|
1700
|
+
- construction of maps between generic base and extension ring and
|
|
1701
|
+
the user defined rings
|
|
1702
|
+
- application of the ring homomorphisms
|
|
1703
|
+
|
|
1704
|
+
EXAMPLES::
|
|
1705
|
+
|
|
1706
|
+
sage: CHA2 = algebras.CubicHecke(2, cubic_equation_roots=(3,7,11))
|
|
1707
|
+
sage: CHA2._test_ring_constructions()
|
|
1708
|
+
"""
|
|
1709
|
+
# ------------------------------------------------------------------------
|
|
1710
|
+
# testing ring constructions
|
|
1711
|
+
# ------------------------------------------------------------------------
|
|
1712
|
+
br = self.base_ring()
|
|
1713
|
+
er = self.extension_ring()
|
|
1714
|
+
A, B, C = self.cubic_equation_roots()
|
|
1715
|
+
a, b, c = self.cubic_equation_roots(generic=True)
|
|
1716
|
+
U, V, W = self.cubic_equation_parameters()
|
|
1717
|
+
u, v, w = self.cubic_equation_parameters(generic=True)
|
|
1718
|
+
eleB = U*V - W**2
|
|
1719
|
+
eleBgen = u*v - w**2
|
|
1720
|
+
eleE = A*B - C**2
|
|
1721
|
+
eleEgen = a*b - c**2
|
|
1722
|
+
|
|
1723
|
+
mbr = self._ring_of_definition_map
|
|
1724
|
+
mer = self._generic_extension_ring_map
|
|
1725
|
+
bri = self._base_ring_embedding
|
|
1726
|
+
|
|
1727
|
+
eleBgenEmb = 0
|
|
1728
|
+
eleEgenEmb = 0
|
|
1729
|
+
eleBembE = 0
|
|
1730
|
+
|
|
1731
|
+
try:
|
|
1732
|
+
eleBgenEmb = br(eleBgen)
|
|
1733
|
+
except (TypeError, ValueError, NotImplementedError):
|
|
1734
|
+
verbose('generic base ring map not registered')
|
|
1735
|
+
try:
|
|
1736
|
+
eleBgenEmb = mbr(eleBgen)
|
|
1737
|
+
except (TypeError, ValueError, NotImplementedError):
|
|
1738
|
+
raise RuntimeError('fatal: generic base ring map %s does not work' % mbr)
|
|
1739
|
+
try:
|
|
1740
|
+
eleEgenEmb = er(eleEgen)
|
|
1741
|
+
except (TypeError, ValueError, NotImplementedError):
|
|
1742
|
+
verbose('generic extension ring map not registered')
|
|
1743
|
+
try:
|
|
1744
|
+
eleEgenEmb = mer(eleEgen)
|
|
1745
|
+
except (TypeError, ValueError, NotImplementedError):
|
|
1746
|
+
raise RuntimeError('fatal: generic extension ring map %s does not work' % mer)
|
|
1747
|
+
|
|
1748
|
+
try:
|
|
1749
|
+
eleBembE = er(eleB)
|
|
1750
|
+
except (TypeError, ValueError, NotImplementedError):
|
|
1751
|
+
verbose('base ring embedding map not registered')
|
|
1752
|
+
try:
|
|
1753
|
+
eleBembE = bri(eleB)
|
|
1754
|
+
except (TypeError, ValueError, NotImplementedError):
|
|
1755
|
+
raise RuntimeError('fatal: base ring embedding %s does not work' % bri)
|
|
1756
|
+
|
|
1757
|
+
test_eleBgenEmb = self._tester(**options)
|
|
1758
|
+
test_eleBgenEmb.assertEqual(eleBgenEmb, eleB)
|
|
1759
|
+
test_eleEgenEmb = self._tester(**options)
|
|
1760
|
+
test_eleEgenEmb.assertEqual(eleEgenEmb, eleE)
|
|
1761
|
+
test_eleBembE = self._tester(**options)
|
|
1762
|
+
test_eleBembE.assertEqual(eleBembE, eleB)
|
|
1763
|
+
|
|
1764
|
+
# --------------------------------------------------------------------------
|
|
1765
|
+
# _test_matrix_constructions
|
|
1766
|
+
# --------------------------------------------------------------------------
|
|
1767
|
+
def _test_matrix_constructions(self, **options):
|
|
1768
|
+
r"""
|
|
1769
|
+
Test that the matrix constructions are valid.
|
|
1770
|
+
|
|
1771
|
+
The following is checked:
|
|
1772
|
+
|
|
1773
|
+
- construction of matrices of the following types:
|
|
1774
|
+
|
|
1775
|
+
* ``RepresentationType.SplitIrredChevie``
|
|
1776
|
+
* ``RepresentationType.SplitIrredMarin``
|
|
1777
|
+
* ``RepresentationType.RegularLeft``
|
|
1778
|
+
|
|
1779
|
+
- multiplication of matrices and compare with the matrix of the
|
|
1780
|
+
corresponding product of elements
|
|
1781
|
+
- construction of maps between generic base and extension ring and
|
|
1782
|
+
the user defined rings
|
|
1783
|
+
|
|
1784
|
+
EXAMPLES::
|
|
1785
|
+
|
|
1786
|
+
sage: CHA2 = algebras.CubicHecke(2, cubic_equation_roots=(3,7,11))
|
|
1787
|
+
sage: CHA2._test_matrix_constructions()
|
|
1788
|
+
"""
|
|
1789
|
+
# ----------------------------------------------------------------------
|
|
1790
|
+
# testing matrix constructions
|
|
1791
|
+
# ----------------------------------------------------------------------
|
|
1792
|
+
if self.ngens() > 4:
|
|
1793
|
+
return
|
|
1794
|
+
|
|
1795
|
+
gens = self.gens()
|
|
1796
|
+
b1 = gens[0]
|
|
1797
|
+
b2 = self.an_element()
|
|
1798
|
+
b12 = b1*b2
|
|
1799
|
+
verbose('b12 %s' % b12)
|
|
1800
|
+
|
|
1801
|
+
def check_matrix(representation_type):
|
|
1802
|
+
m1 = b1.matrix(representation_type=representation_type)
|
|
1803
|
+
m2 = b2.matrix(representation_type=representation_type)
|
|
1804
|
+
m12mult = m1*m2
|
|
1805
|
+
m12mat = b12.matrix(representation_type=representation_type)
|
|
1806
|
+
test_matrix = self._tester(**options)
|
|
1807
|
+
test_matrix.assertEqual(m12mult, m12mat)
|
|
1808
|
+
|
|
1809
|
+
from sage.combinat.root_system.reflection_group_real import is_chevie_available
|
|
1810
|
+
|
|
1811
|
+
if is_chevie_available():
|
|
1812
|
+
check_matrix(RepresentationType.SplitIrredChevie)
|
|
1813
|
+
if self.ngens() < 3:
|
|
1814
|
+
check_matrix(RepresentationType.SplitIrredMarin)
|
|
1815
|
+
elif self.ngens() < 4:
|
|
1816
|
+
check_matrix(RepresentationType.SplitIrredMarin)
|
|
1817
|
+
|
|
1818
|
+
if self.ngens() < 3:
|
|
1819
|
+
check_matrix(RepresentationType.RegularLeft)
|
|
1820
|
+
return
|
|
1821
|
+
|
|
1822
|
+
# --------------------------------------------------------------------------
|
|
1823
|
+
# _init_basis_extension
|
|
1824
|
+
# --------------------------------------------------------------------------
|
|
1825
|
+
def _init_basis_extension(self):
|
|
1826
|
+
r"""
|
|
1827
|
+
Return the extension of the basis for more than 4 strands hold
|
|
1828
|
+
in file cache.
|
|
1829
|
+
|
|
1830
|
+
The basis elements from the file are added to the elements of
|
|
1831
|
+
the Marin basis.
|
|
1832
|
+
|
|
1833
|
+
EXAMPLES::
|
|
1834
|
+
|
|
1835
|
+
sage: # optional - database_cubic_hecke
|
|
1836
|
+
sage: CHA5 = algebras.CubicHecke(5)
|
|
1837
|
+
sage: fc = CHA5._filecache
|
|
1838
|
+
sage: be = fc.section.basis_extensions
|
|
1839
|
+
sage: CHA5.reset_filecache(be)
|
|
1840
|
+
sage: fc.read(be)
|
|
1841
|
+
[[4], [-4]]
|
|
1842
|
+
sage: ele = CHA5.an_element()
|
|
1843
|
+
sage: CHA5.inject_variables()
|
|
1844
|
+
Defining c0, c1, c2, c3
|
|
1845
|
+
sage: ele2 = ele * c3
|
|
1846
|
+
sage: bex = fc.read(be)
|
|
1847
|
+
sage: bex.sort(); bex
|
|
1848
|
+
[[-4], [1, -3, 4], [1, -2, 4], [3, 2, 4], [4]]
|
|
1849
|
+
"""
|
|
1850
|
+
self._basis_extension = []
|
|
1851
|
+
tietze_list = self._basis_tietze()
|
|
1852
|
+
cbg = self._cubic_braid_group
|
|
1853
|
+
self._finite_sub_basis_tuples = {}
|
|
1854
|
+
|
|
1855
|
+
order_list = [cbg(tup) for tup in tietze_list]
|
|
1856
|
+
# We avoid the call to set_order for speed.
|
|
1857
|
+
# This avoids hashing the keys, which can become expensive.
|
|
1858
|
+
self._order = order_list
|
|
1859
|
+
verbose('finite sub basis length: %s' % (len(order_list)), level=2)
|
|
1860
|
+
|
|
1861
|
+
if self._nstrands < 5:
|
|
1862
|
+
return
|
|
1863
|
+
|
|
1864
|
+
# ----------------------------------------------------------------------
|
|
1865
|
+
# loading the extension of the basis from data file
|
|
1866
|
+
# ----------------------------------------------------------------------
|
|
1867
|
+
fc = self._filecache
|
|
1868
|
+
former_bas_ext = fc.read(fc.section.basis_extensions)
|
|
1869
|
+
|
|
1870
|
+
# ----------------------------------------------------------------------
|
|
1871
|
+
# pre definition of additional basis elements
|
|
1872
|
+
# ----------------------------------------------------------------------
|
|
1873
|
+
cub_braid_group = self.cubic_braid_group()
|
|
1874
|
+
if not former_bas_ext:
|
|
1875
|
+
gens = cub_braid_group.gens()
|
|
1876
|
+
last_gen = gens[len(gens)-1]
|
|
1877
|
+
self._cubic_braid_image(last_gen, check=False)
|
|
1878
|
+
self._cubic_braid_image(~last_gen, check=False)
|
|
1879
|
+
self._filecache.update_basis_extensions(self._basis_extension)
|
|
1880
|
+
return
|
|
1881
|
+
|
|
1882
|
+
# ----------------------------------------------------------------------
|
|
1883
|
+
# Installing the additional basis elements from filecache via the
|
|
1884
|
+
# embedding of the corresponding cubic braid
|
|
1885
|
+
# ----------------------------------------------------------------------
|
|
1886
|
+
for bas_Tietze in former_bas_ext:
|
|
1887
|
+
cub_braid = cub_braid_group(bas_Tietze)
|
|
1888
|
+
self._cubic_braid_image(cub_braid, check=False)
|
|
1889
|
+
|
|
1890
|
+
verbose('finite sub basis (extended) length: %s' % (len(self.get_order())), level=2)
|
|
1891
|
+
self._filecache.update_basis_extensions(self._basis_extension)
|
|
1892
|
+
return
|
|
1893
|
+
|
|
1894
|
+
# --------------------------------------------------------------------------
|
|
1895
|
+
# _braid_image_from_filecache
|
|
1896
|
+
# --------------------------------------------------------------------------
|
|
1897
|
+
def _braid_image_from_filecache(self, braid):
|
|
1898
|
+
r"""
|
|
1899
|
+
Return the image of the given braid in ``self`` from file cache (if
|
|
1900
|
+
contained).
|
|
1901
|
+
|
|
1902
|
+
INPUT:
|
|
1903
|
+
|
|
1904
|
+
- ``braid`` -- braid as instance of the braid group of ``self``
|
|
1905
|
+
|
|
1906
|
+
OUTPUT:
|
|
1907
|
+
|
|
1908
|
+
Image of braid as element of ``self``. ``None`` if the product has
|
|
1909
|
+
not been stored.
|
|
1910
|
+
|
|
1911
|
+
EXAMPLES::
|
|
1912
|
+
|
|
1913
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
1914
|
+
sage: b1, b2 = CHA3.braid_group().gens(); br = ~b2*b1*~b2
|
|
1915
|
+
sage: CHA3._braid_image_from_filecache(br)
|
|
1916
|
+
1/w*c0*c1*c0^-1*c1 + v/w*c1^-1*c0 - u/w*c0*c1*c0^-1
|
|
1917
|
+
sage: F = CHA3.base_ring().fraction_field()
|
|
1918
|
+
sage: par = tuple([F(p) for p in CHA3.cubic_equation_parameters()])
|
|
1919
|
+
sage: CHA3F = algebras.CubicHecke(3, cubic_equation_parameters=par)
|
|
1920
|
+
sage: CHA3F._braid_image_from_filecache(br)
|
|
1921
|
+
1/w*c0*c1*c0^-1*c1 + v/w*c1^-1*c0 - u/w*c0*c1*c0^-1
|
|
1922
|
+
sage: section = CHA3.filecache_section().braid_images
|
|
1923
|
+
sage: CHA3.reset_filecache(section)
|
|
1924
|
+
sage: CHA3._braid_image_from_filecache(br)
|
|
1925
|
+
"""
|
|
1926
|
+
base_ring = self.base_ring()
|
|
1927
|
+
gen_base_ring = self.base_ring(generic=True)
|
|
1928
|
+
result_vect = self._filecache.read_braid_image(braid.Tietze(), gen_base_ring)
|
|
1929
|
+
if result_vect is not None:
|
|
1930
|
+
if gen_base_ring != base_ring:
|
|
1931
|
+
base_map = self._ring_of_definition_map
|
|
1932
|
+
result_vect = vector(base_ring, [base_map(cf) for cf in result_vect])
|
|
1933
|
+
return self.from_vector(result_vect)
|
|
1934
|
+
return None
|
|
1935
|
+
|
|
1936
|
+
# --------------------------------------------------------------------------
|
|
1937
|
+
# _braid_image_to_filecache
|
|
1938
|
+
# --------------------------------------------------------------------------
|
|
1939
|
+
def _braid_image_to_filecache(self, braid_tietze, braid_image_vect):
|
|
1940
|
+
r"""
|
|
1941
|
+
Write the given braid image of to file cache.
|
|
1942
|
+
|
|
1943
|
+
INPUT:
|
|
1944
|
+
|
|
1945
|
+
- ``braid_tietze`` -- braid in Tietze form
|
|
1946
|
+
- ``braid_image_vect`` -- image of the given braid in ``self`` in vector
|
|
1947
|
+
representation
|
|
1948
|
+
|
|
1949
|
+
EXAMPLES::
|
|
1950
|
+
|
|
1951
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
1952
|
+
sage: br, = CHA2.braid_group().gens(); br2 = br**2
|
|
1953
|
+
sage: section = CHA2.filecache_section().braid_images
|
|
1954
|
+
sage: CHA2.is_filecache_empty(section) # note: 2-strand images are not automatically cached in file system
|
|
1955
|
+
True
|
|
1956
|
+
sage: CHA2._braid_image_to_filecache(br2.Tietze(), CHA2(br2).to_vector())
|
|
1957
|
+
sage: CHA2._braid_image_from_filecache(br2)
|
|
1958
|
+
w*c^-1 + u*c - v
|
|
1959
|
+
sage: CHA2.reset_filecache(CHA2.filecache_section().braid_images)
|
|
1960
|
+
sage: CHA2._braid_image_from_filecache(br2) == None
|
|
1961
|
+
True
|
|
1962
|
+
"""
|
|
1963
|
+
if self.base_ring() != self.base_ring(generic=True):
|
|
1964
|
+
# this should not be done for specialized base rings
|
|
1965
|
+
return
|
|
1966
|
+
|
|
1967
|
+
self._filecache.write_braid_image(braid_tietze, braid_image_vect)
|
|
1968
|
+
return
|
|
1969
|
+
|
|
1970
|
+
# --------------------------------------------------------------------------
|
|
1971
|
+
# _braid_image
|
|
1972
|
+
# --------------------------------------------------------------------------
|
|
1973
|
+
@cached_method
|
|
1974
|
+
def _braid_image(self, braid):
|
|
1975
|
+
r"""
|
|
1976
|
+
Return the image of the given braid in ``self``.
|
|
1977
|
+
|
|
1978
|
+
INPUT:
|
|
1979
|
+
|
|
1980
|
+
- ``braid`` -- :class:`~sage.groups.braid.Braid` whose image
|
|
1981
|
+
in ``self`` should be calculated
|
|
1982
|
+
|
|
1983
|
+
OUTPUT: an instance of the element class of ``self``
|
|
1984
|
+
|
|
1985
|
+
EXAMPLES::
|
|
1986
|
+
|
|
1987
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
1988
|
+
sage: br, = CHA2.braid_group().gens(); br2 = br**2
|
|
1989
|
+
sage: CHA2._braid_image(br2)
|
|
1990
|
+
w*c^-1 + u*c - v
|
|
1991
|
+
"""
|
|
1992
|
+
# ----------------------------------------------------------------------
|
|
1993
|
+
# first use the cubic equation to express the braid as a linear
|
|
1994
|
+
# combination of braids having no other exponent as 1 and -1 in their
|
|
1995
|
+
# defining word in the braid generators
|
|
1996
|
+
# ----------------------------------------------------------------------
|
|
1997
|
+
coeffs, braids = self._reduce_all_gen_powers(braid.Tietze())
|
|
1998
|
+
|
|
1999
|
+
# ----------------------------------------------------------------------
|
|
2000
|
+
# in the second step the images of these "reduced" braids is calculated
|
|
2001
|
+
# ----------------------------------------------------------------------
|
|
2002
|
+
result = self.zero()
|
|
2003
|
+
for i in range(len(coeffs)):
|
|
2004
|
+
braid_image = self._braid_image_from_reduced_powers(braids[i])
|
|
2005
|
+
result += coeffs[i]*braid_image
|
|
2006
|
+
|
|
2007
|
+
return result
|
|
2008
|
+
|
|
2009
|
+
# --------------------------------------------------------------------------
|
|
2010
|
+
# _braid_image_from_reduced_powers
|
|
2011
|
+
# --------------------------------------------------------------------------
|
|
2012
|
+
@cached_method
|
|
2013
|
+
def _braid_image_from_reduced_powers(self, braid_tietze):
|
|
2014
|
+
r"""
|
|
2015
|
+
Return the image of a braid in ``self`` assuming that no successive
|
|
2016
|
+
repetitions occur in the Tietze form of the braid.
|
|
2017
|
+
|
|
2018
|
+
INPUT:
|
|
2019
|
+
|
|
2020
|
+
- ``braid_tietze`` -- tuple representing the Braid whose image in
|
|
2021
|
+
``self`` should be computed; it is assumed that no successive
|
|
2022
|
+
repetitions occur among the entries (i.e. ``(1, 1)`` is not allowed
|
|
2023
|
+
but ``(1, -2, 1)`` is)
|
|
2024
|
+
|
|
2025
|
+
OUTPUT: the image of the braid as an element of ``self``
|
|
2026
|
+
|
|
2027
|
+
EXAMPLES::
|
|
2028
|
+
|
|
2029
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
2030
|
+
sage: CHA3._braid_image_from_reduced_powers((1, -2, 1))
|
|
2031
|
+
c0*c1^-1*c0
|
|
2032
|
+
sage: CHA3._braid_image_from_reduced_powers((1, -2, 1, 2))
|
|
2033
|
+
w*c0^-1*c1*c0^-1 - v*c1*c0^-1 + u*c0*c1*c0^-1
|
|
2034
|
+
"""
|
|
2035
|
+
n = self.ngens()
|
|
2036
|
+
braid_list = list(braid_tietze)
|
|
2037
|
+
len_braid = len(braid_list)
|
|
2038
|
+
|
|
2039
|
+
# ----------------------------------------------------------------------
|
|
2040
|
+
# in the case of two strands we calculate the power of the generator
|
|
2041
|
+
# ----------------------------------------------------------------------
|
|
2042
|
+
if n == 1:
|
|
2043
|
+
if len_braid == 0:
|
|
2044
|
+
return self.one()
|
|
2045
|
+
k = braid_tietze[0]*len_braid
|
|
2046
|
+
result_vect = self._reduce_gen_power(k)
|
|
2047
|
+
result = self.from_vector(result_vect)
|
|
2048
|
+
return result
|
|
2049
|
+
|
|
2050
|
+
# ----------------------------------------------------------------------
|
|
2051
|
+
# Try to use former calculations (from dynamic library) to obtain the
|
|
2052
|
+
# braid image
|
|
2053
|
+
# ----------------------------------------------------------------------
|
|
2054
|
+
result, word_decomposition = self._braid_image_from_former_calculations(braid_tietze)
|
|
2055
|
+
|
|
2056
|
+
if word_decomposition is None:
|
|
2057
|
+
return result
|
|
2058
|
+
|
|
2059
|
+
# ----------------------------------------------------------------------
|
|
2060
|
+
# proceed the calculation by use of the regular representation matrices
|
|
2061
|
+
# (given by Ivan Marin) or in case of more than 4 strands by extension
|
|
2062
|
+
# of the finite sub basis
|
|
2063
|
+
# ----------------------------------------------------------------------
|
|
2064
|
+
|
|
2065
|
+
if n > 3 and (n in braid_tietze or -n in braid_tietze):
|
|
2066
|
+
# ------------------------------------------------------------------
|
|
2067
|
+
# matrices for the regular representation are at the moment just
|
|
2068
|
+
# available in the case of less than five strands. In the higher
|
|
2069
|
+
# cases the basis is realized to grow up from the basis on 4 strands
|
|
2070
|
+
# to use the recursion, only those cubic braids are stored as new
|
|
2071
|
+
# basis elements if they involve the generator with largest index
|
|
2072
|
+
# ------------------------------------------------------------------
|
|
2073
|
+
return self._braid_image_by_basis_extension(braid_tietze)
|
|
2074
|
+
|
|
2075
|
+
word_left, word_result, word_right = word_decomposition
|
|
2076
|
+
result_vect = None
|
|
2077
|
+
|
|
2078
|
+
if word_left is not None:
|
|
2079
|
+
# ------------------------------------------------------------------
|
|
2080
|
+
# Operating from the left on the pre-calculated result
|
|
2081
|
+
# ------------------------------------------------------------------
|
|
2082
|
+
vect = result.to_vector()
|
|
2083
|
+
braid_preimage = tuple(word_result)
|
|
2084
|
+
result_vect = self._mult_by_regular_rep(vect, tuple(word_left), RepresentationType.RegularLeft, braid_preimage)
|
|
2085
|
+
|
|
2086
|
+
if word_right is not None:
|
|
2087
|
+
# ------------------------------------------------------------------
|
|
2088
|
+
# Operating from the right on the pre-calculated result
|
|
2089
|
+
# ------------------------------------------------------------------
|
|
2090
|
+
if result_vect is not None:
|
|
2091
|
+
vect = result_vect
|
|
2092
|
+
braid_preimage = tuple(word_left + word_result)
|
|
2093
|
+
else:
|
|
2094
|
+
vect = result.to_vector()
|
|
2095
|
+
braid_preimage = tuple(word_result)
|
|
2096
|
+
result_vect = self._mult_by_regular_rep(vect, tuple(word_right), RepresentationType.RegularRight, braid_preimage)
|
|
2097
|
+
|
|
2098
|
+
result = self.from_vector(result_vect)
|
|
2099
|
+
return result
|
|
2100
|
+
|
|
2101
|
+
# --------------------------------------------------------------------------
|
|
2102
|
+
# _braid_image_from_former_calculations
|
|
2103
|
+
# --------------------------------------------------------------------------
|
|
2104
|
+
def _braid_image_from_former_calculations(self, braid_tietze):
|
|
2105
|
+
r"""
|
|
2106
|
+
Return the image of a braid in ``self`` as far as this can be done by
|
|
2107
|
+
use of former calculations and is sure not to go into an endless
|
|
2108
|
+
recursion, that is
|
|
2109
|
+
|
|
2110
|
+
- using the cubic Hecke sub-algebra on one strand less
|
|
2111
|
+
- using the file cache.
|
|
2112
|
+
|
|
2113
|
+
If the image can not be calculated from former registered results this
|
|
2114
|
+
method returns None. Therefore, it is just intended to be used as as
|
|
2115
|
+
step in the complete calculation.
|
|
2116
|
+
|
|
2117
|
+
INPUT:
|
|
2118
|
+
|
|
2119
|
+
- ``braid_tietze`` -- tuple representing the braid whose image in
|
|
2120
|
+
``self`` should be computed; he generator exponents in the braid
|
|
2121
|
+
word are assumed to be ``1`` or ``-1``
|
|
2122
|
+
|
|
2123
|
+
OUTPUT:
|
|
2124
|
+
|
|
2125
|
+
A pair (image, basis_factors) where result is an element of ``self``
|
|
2126
|
+
representing the image of the input if calculation was possible and
|
|
2127
|
+
``None`` else-wise. If ``image == None`` the output basis_factors is
|
|
2128
|
+
given as a list of basis element whose product equals the input.
|
|
2129
|
+
|
|
2130
|
+
EXAMPLES::
|
|
2131
|
+
|
|
2132
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
2133
|
+
sage: CHA3._braid_image_from_former_calculations((1, -2, 1))
|
|
2134
|
+
(c0*c1^-1*c0, None)
|
|
2135
|
+
sage: CHA3._braid_image_from_former_calculations((1, -2, 1, 2))
|
|
2136
|
+
(c0*c1^-1*c0, ([], [1, -2, 1], [2]))
|
|
2137
|
+
"""
|
|
2138
|
+
braid_list = list(braid_tietze)
|
|
2139
|
+
len_braid = len(braid_list)
|
|
2140
|
+
result = None
|
|
2141
|
+
n = self.ngens()
|
|
2142
|
+
|
|
2143
|
+
# ----------------------------------------------------------------------
|
|
2144
|
+
# if the braid is in the basis take its image to be the corresponding
|
|
2145
|
+
# monomial
|
|
2146
|
+
# ----------------------------------------------------------------------
|
|
2147
|
+
result = self._tietze_to_finite_sub_basis_monomial(braid_tietze)
|
|
2148
|
+
if result is not None:
|
|
2149
|
+
return result, None
|
|
2150
|
+
|
|
2151
|
+
# ----------------------------------------------------------------------
|
|
2152
|
+
# if the braid lies in a sub-algebra take its image from there.
|
|
2153
|
+
# ----------------------------------------------------------------------
|
|
2154
|
+
sub_alg = self.cubic_hecke_subalgebra()
|
|
2155
|
+
if n not in braid_list and -n not in braid_list:
|
|
2156
|
+
result = self(sub_alg(braid_tietze))
|
|
2157
|
+
verbose('end (%s): %s in smaller algebra' % (braid_list, result), level=2)
|
|
2158
|
+
return result, None
|
|
2159
|
+
|
|
2160
|
+
# ----------------------------------------------------------------------
|
|
2161
|
+
# proceed the calculation by splitting self into a product of basis
|
|
2162
|
+
# elements and try to simplify.
|
|
2163
|
+
# ----------------------------------------------------------------------
|
|
2164
|
+
braid_group = self.braid_group()
|
|
2165
|
+
braid = braid_group(braid_tietze)
|
|
2166
|
+
result = self._braid_image_from_filecache(braid)
|
|
2167
|
+
if result is not None:
|
|
2168
|
+
verbose('end from file cache (%s)' % (list(braid_tietze)), level=2)
|
|
2169
|
+
return result, None
|
|
2170
|
+
|
|
2171
|
+
# ----------------------------------------------------------------------
|
|
2172
|
+
# If we come here len_braid must be larger than 1 (otherwise we already
|
|
2173
|
+
# have found in in the basis). By recursion we check if the subwords
|
|
2174
|
+
# with one generator removed on the left (respectively on the right)
|
|
2175
|
+
# side contain a subword whose image has already been calculated. We
|
|
2176
|
+
# choose the longest such subword as our result.
|
|
2177
|
+
# ----------------------------------------------------------------------
|
|
2178
|
+
braid_list_red_left = [braid_tietze[j] for j in range(1, len_braid)]
|
|
2179
|
+
braid_list_red_right = [braid_tietze[j] for j in range(len_braid - 1)]
|
|
2180
|
+
|
|
2181
|
+
result_left, word_decomp_left = self._braid_image_from_former_calculations(tuple(braid_list_red_left))
|
|
2182
|
+
result_right, word_decomp_right = self._braid_image_from_former_calculations(tuple(braid_list_red_right))
|
|
2183
|
+
if word_decomp_left is None:
|
|
2184
|
+
return result_left, ([braid_tietze[0]], braid_list_red_left, [])
|
|
2185
|
+
|
|
2186
|
+
if word_decomp_right is None:
|
|
2187
|
+
return result_right, ([], braid_list_red_right, [braid_tietze[len_braid - 1]])
|
|
2188
|
+
|
|
2189
|
+
word_decomp_left_left, word_decomp_left_result, word_decomp_left_right = word_decomp_left
|
|
2190
|
+
word_decomp_right_left, word_decomp_right_result, word_decomp_right_right = word_decomp_right
|
|
2191
|
+
|
|
2192
|
+
if len(word_decomp_left_result) >= len(word_decomp_right_result):
|
|
2193
|
+
return result_left, ([braid_tietze[0]] + word_decomp_left_left, word_decomp_left_result, word_decomp_left_right)
|
|
2194
|
+
|
|
2195
|
+
return result_right, (word_decomp_right_left, word_decomp_right_result, word_decomp_right_right + [braid_tietze[len_braid - 1]])
|
|
2196
|
+
|
|
2197
|
+
# --------------------------------------------------------------------------
|
|
2198
|
+
# _braid_image_by_basis_expansion_
|
|
2199
|
+
# --------------------------------------------------------------------------
|
|
2200
|
+
@cached_method
|
|
2201
|
+
def _braid_image_by_basis_extension(self, braid_tietze):
|
|
2202
|
+
r"""
|
|
2203
|
+
Return the given braid as a new basis element of ``self`` expanding the
|
|
2204
|
+
incomplete order (which is just a part of the whole basis) in the case
|
|
2205
|
+
of more than 4 strands.
|
|
2206
|
+
|
|
2207
|
+
INPUT:
|
|
2208
|
+
|
|
2209
|
+
- ``braid_tietze`` -- tuple representing the braid whose image in
|
|
2210
|
+
``self`` should be computed; he generator exponents in the braid
|
|
2211
|
+
word are assumed to be ``1`` or ``-1``
|
|
2212
|
+
|
|
2213
|
+
OUTPUT: an instance of the element class of ``self``
|
|
2214
|
+
|
|
2215
|
+
EXAMPLES::
|
|
2216
|
+
|
|
2217
|
+
sage: # optional - database_cubic_hecke
|
|
2218
|
+
sage: CHA5 = algebras.CubicHecke(5)
|
|
2219
|
+
sage: be = CHA5.filecache_section().basis_extensions
|
|
2220
|
+
sage: CHA5.reset_filecache(be)
|
|
2221
|
+
sage: CHA5._basis_extension
|
|
2222
|
+
[[4], [-4]]
|
|
2223
|
+
sage: CHA5._braid_image_by_basis_extension((4,1))
|
|
2224
|
+
c3*c0
|
|
2225
|
+
sage: CHA5._basis_extension
|
|
2226
|
+
[[4], [-4], [4, 1]]
|
|
2227
|
+
|
|
2228
|
+
case where the braid already has a corresponding basis element::
|
|
2229
|
+
|
|
2230
|
+
sage: CHA5._braid_image_by_basis_extension((1,)) # optional - database_cubic_hecke
|
|
2231
|
+
c0
|
|
2232
|
+
sage: CHA5._basis_extension # optional - database_cubic_hecke
|
|
2233
|
+
[[4], [-4], [4, 1]]
|
|
2234
|
+
|
|
2235
|
+
case where the braid doesn't have corresponding basis element but depends
|
|
2236
|
+
on them::
|
|
2237
|
+
|
|
2238
|
+
sage: CHA5._braid_image_by_basis_extension((1,1)) # optional - database_cubic_hecke
|
|
2239
|
+
Traceback (most recent call last):
|
|
2240
|
+
...
|
|
2241
|
+
NotImplementedError: no algorithm available to calculate braid image of (1, 1)
|
|
2242
|
+
"""
|
|
2243
|
+
cubic_braid = self._cubic_braid_group(braid_tietze)
|
|
2244
|
+
tup = self._cubic_braid_basis_tuple(cubic_braid)
|
|
2245
|
+
if tup is not None:
|
|
2246
|
+
bgrp = self.braid_group()
|
|
2247
|
+
if bgrp(braid_tietze) != bgrp(tup):
|
|
2248
|
+
raise NotImplementedError('no algorithm available to calculate braid image of %s' % str(braid_tietze))
|
|
2249
|
+
B = self.basis()
|
|
2250
|
+
verbose('braid-image %s in Basis' % str(braid_tietze), level=2)
|
|
2251
|
+
return self.monomial(B[cubic_braid])
|
|
2252
|
+
|
|
2253
|
+
return self._cubic_braid_append_to_basis(cubic_braid)
|
|
2254
|
+
|
|
2255
|
+
# --------------------------------------------------------------------------
|
|
2256
|
+
# _reduce_all_gen_powers
|
|
2257
|
+
# --------------------------------------------------------------------------
|
|
2258
|
+
@cached_method
|
|
2259
|
+
def _reduce_all_gen_powers(self, braid_tietze):
|
|
2260
|
+
r"""
|
|
2261
|
+
Return a linear combination of braids that have no higher powers in the
|
|
2262
|
+
braid generators having the same image in ``self`` than the given braid.
|
|
2263
|
+
|
|
2264
|
+
This linear combination is returned as a pair of lists of braids and
|
|
2265
|
+
corresponding coefficients.
|
|
2266
|
+
|
|
2267
|
+
INPUT:
|
|
2268
|
+
|
|
2269
|
+
- ``braid_tietze`` -- tuple representing the braid whose powers should
|
|
2270
|
+
be reduced given in Tietze form
|
|
2271
|
+
|
|
2272
|
+
OUTPUT:
|
|
2273
|
+
|
|
2274
|
+
A pair of two lists: ``coeffs``, ``braids``. The fist one contains the
|
|
2275
|
+
coefficients corresponding to the braids in Tietze form from the second
|
|
2276
|
+
list of braids.
|
|
2277
|
+
|
|
2278
|
+
EXAMPLES::
|
|
2279
|
+
|
|
2280
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
2281
|
+
sage: CHA3._reduce_all_gen_powers((1, 1, -2, -2))
|
|
2282
|
+
([u*v/w, (-v)/w, (-v^2)/w, (-u^2)/w, u/w, u*v/w, -u, 1, v],
|
|
2283
|
+
[(), (2,), (-2,), (1,), (1, 2), (1, -2), (-1,), (-1, 2), (-1, -2)])
|
|
2284
|
+
"""
|
|
2285
|
+
braid_list = list(braid_tietze)
|
|
2286
|
+
len_braid = len(braid_list)
|
|
2287
|
+
|
|
2288
|
+
# ----------------------------------------------------------------------
|
|
2289
|
+
# find a higher power position in braid_list
|
|
2290
|
+
# ----------------------------------------------------------------------
|
|
2291
|
+
power = 0
|
|
2292
|
+
pos = 0
|
|
2293
|
+
for i in range(len_braid - 1):
|
|
2294
|
+
if braid_list[i] != braid_list[i + 1]:
|
|
2295
|
+
continue
|
|
2296
|
+
pos = i
|
|
2297
|
+
for power in range(1, len_braid - pos + 1):
|
|
2298
|
+
if pos+power == len_braid:
|
|
2299
|
+
break
|
|
2300
|
+
if braid_list[pos] != braid_list[pos+power]:
|
|
2301
|
+
break
|
|
2302
|
+
break
|
|
2303
|
+
|
|
2304
|
+
if power == 0:
|
|
2305
|
+
verbose('end (%s) no powers' % braid_list, level=2)
|
|
2306
|
+
return [self.base_ring().one()], [braid_tietze]
|
|
2307
|
+
|
|
2308
|
+
# ----------------------------------------------------------------------
|
|
2309
|
+
# eliminate this power from braid_tietze.
|
|
2310
|
+
# ----------------------------------------------------------------------
|
|
2311
|
+
val = braid_list[pos]
|
|
2312
|
+
if val > 0:
|
|
2313
|
+
gen_ind = val
|
|
2314
|
+
exp = power
|
|
2315
|
+
else:
|
|
2316
|
+
gen_ind = -val
|
|
2317
|
+
exp = -power
|
|
2318
|
+
|
|
2319
|
+
braid_list_start = [braid_list[i] for i in range(pos)]
|
|
2320
|
+
braid_list_end = [braid_list[i] for i in range(pos+power, len_braid)]
|
|
2321
|
+
|
|
2322
|
+
# ----------------------------------------------------------------------
|
|
2323
|
+
# merging the new reduced tuple. Note that all the new tuples are
|
|
2324
|
+
# smaller than the given one, which will make the recursion terminate.
|
|
2325
|
+
# ----------------------------------------------------------------------
|
|
2326
|
+
tuple_one = tuple(braid_list_start + braid_list_end)
|
|
2327
|
+
tuple_gen = tuple(braid_list_start + [gen_ind] + braid_list_end)
|
|
2328
|
+
tuple_gen_inv = tuple(braid_list_start + [-gen_ind] + braid_list_end)
|
|
2329
|
+
|
|
2330
|
+
# ----------------------------------------------------------------------
|
|
2331
|
+
# convert them to braids (to reduce cancellation of inverses and obvious
|
|
2332
|
+
# braid relations) Note that this will not increase the length of the
|
|
2333
|
+
# word. Thus the recursion still must terminate.
|
|
2334
|
+
# ----------------------------------------------------------------------
|
|
2335
|
+
braid_group = self.braid_group()
|
|
2336
|
+
braid_one = braid_group(tuple_one)
|
|
2337
|
+
braid_gen = braid_group(tuple_gen)
|
|
2338
|
+
braid_gen_inv = braid_group(tuple_gen_inv)
|
|
2339
|
+
|
|
2340
|
+
# ----------------------------------------------------------------------
|
|
2341
|
+
# eliminate all powers from braid_tietze by recursion. The recursion
|
|
2342
|
+
# will terminate by the length reduction of the Tietze tuple (but not
|
|
2343
|
+
# necessarily by the number of generators whose exponent must be reduced).
|
|
2344
|
+
# ----------------------------------------------------------------------
|
|
2345
|
+
one_coeffs, one_braids = self._reduce_all_gen_powers(braid_one.Tietze())
|
|
2346
|
+
gen_coeffs, gen_braids = self._reduce_all_gen_powers(braid_gen.Tietze())
|
|
2347
|
+
gen_inv_coeffs, gen_inv_braids = self._reduce_all_gen_powers(braid_gen_inv.Tietze())
|
|
2348
|
+
|
|
2349
|
+
cf_one, cf_gen, cf_gen_inv = self._reduce_gen_power(exp)
|
|
2350
|
+
|
|
2351
|
+
one_coeffs = [cf*cf_one for cf in one_coeffs]
|
|
2352
|
+
gen_coeffs = [cf*cf_gen for cf in gen_coeffs]
|
|
2353
|
+
gen_inv_coeffs = [cf*cf_gen_inv for cf in gen_inv_coeffs]
|
|
2354
|
+
|
|
2355
|
+
return one_coeffs + gen_coeffs + gen_inv_coeffs, one_braids + gen_braids + gen_inv_braids
|
|
2356
|
+
|
|
2357
|
+
# --------------------------------------------------------------------------
|
|
2358
|
+
# _reduce_gen_power
|
|
2359
|
+
# --------------------------------------------------------------------------
|
|
2360
|
+
@cached_method
|
|
2361
|
+
def _reduce_gen_power(self, k):
|
|
2362
|
+
r"""
|
|
2363
|
+
Return the `k`-th power on an arbitrary generator,
|
|
2364
|
+
for example `c_0^k`.
|
|
2365
|
+
|
|
2366
|
+
INPUT:
|
|
2367
|
+
|
|
2368
|
+
- ``k`` -- integer giving the power
|
|
2369
|
+
|
|
2370
|
+
OUTPUT:
|
|
2371
|
+
|
|
2372
|
+
A list ``[coeff_one, coeff_gen, coeff_gen_inverse]`` of the three
|
|
2373
|
+
coefficients of the generators power in the span of the generator.
|
|
2374
|
+
|
|
2375
|
+
EXAMPLES::
|
|
2376
|
+
|
|
2377
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
2378
|
+
sage: CHA2._reduce_gen_power(5)
|
|
2379
|
+
(-u^3*v + 2*u*v^2 + u^2*w - 2*v*w, u^4 - 3*u^2*v
|
|
2380
|
+
+ v^2 + 2*u*w, u^3*w - 2*u*v*w + w^2)
|
|
2381
|
+
"""
|
|
2382
|
+
n = self.ngens()
|
|
2383
|
+
|
|
2384
|
+
# ----------------------------------------------------------------------
|
|
2385
|
+
# take it from smaller sub-algebras if possible
|
|
2386
|
+
# ----------------------------------------------------------------------
|
|
2387
|
+
if n > 1:
|
|
2388
|
+
sub_alg = self.cubic_hecke_subalgebra()
|
|
2389
|
+
return sub_alg._reduce_gen_power(k)
|
|
2390
|
+
|
|
2391
|
+
# ----------------------------------------------------------------------
|
|
2392
|
+
# calculate it in the sub-algebra on 2 strands
|
|
2393
|
+
# ----------------------------------------------------------------------
|
|
2394
|
+
|
|
2395
|
+
if k == 0:
|
|
2396
|
+
result_ele = self.one()
|
|
2397
|
+
result = result_ele.to_vector()
|
|
2398
|
+
|
|
2399
|
+
elif abs(k) == 1:
|
|
2400
|
+
result_ele = self._tietze_to_finite_sub_basis_monomial((k,))
|
|
2401
|
+
result = result_ele.to_vector()
|
|
2402
|
+
|
|
2403
|
+
else:
|
|
2404
|
+
if k < 0:
|
|
2405
|
+
right_vect = self._reduce_gen_power(k + 1)
|
|
2406
|
+
genTietze = (-1,)
|
|
2407
|
+
else:
|
|
2408
|
+
right_vect = self._reduce_gen_power(k - 1)
|
|
2409
|
+
genTietze = (1,)
|
|
2410
|
+
result = self._mult_by_regular_rep(right_vect, genTietze, RepresentationType.RegularLeft)
|
|
2411
|
+
return result
|
|
2412
|
+
|
|
2413
|
+
# --------------------------------------------------------------------------
|
|
2414
|
+
# _mult_by_regular_rep
|
|
2415
|
+
# --------------------------------------------------------------------------
|
|
2416
|
+
@cached_method
|
|
2417
|
+
def _mult_by_regular_rep(self, vect, gen_tuple, representation_type, braid_preimage=None):
|
|
2418
|
+
r"""
|
|
2419
|
+
Return the product of an`element of ``self`` given as a coefficient
|
|
2420
|
+
vector with a sequence (tuple) of generators (that is a braid word)
|
|
2421
|
+
using regular representation matrices.
|
|
2422
|
+
|
|
2423
|
+
The multiplication will be performed form left or right according
|
|
2424
|
+
to the given ``representation_type``.
|
|
2425
|
+
|
|
2426
|
+
INPUT:
|
|
2427
|
+
|
|
2428
|
+
- ``vect`` -- element of ``self`` in vector form (obtained by
|
|
2429
|
+
:meth:`to_vector`)
|
|
2430
|
+
- ``gen_tuple`` -- list of generators (that is a braid in Tietze form)
|
|
2431
|
+
which operates on ``vect``
|
|
2432
|
+
- ``representation_type`` -- instance of :class:`RepresentationType`
|
|
2433
|
+
(one of `RegularLeft` or `RegularRight`)
|
|
2434
|
+
- ``braid_preimage`` -- (optional) a word representing a braid whose
|
|
2435
|
+
image is vect (if it exist). This is used to record intermediate
|
|
2436
|
+
results to the dynamic library
|
|
2437
|
+
|
|
2438
|
+
OUTPUT:
|
|
2439
|
+
|
|
2440
|
+
The coefficient vector resulting after applying the multiplication of all
|
|
2441
|
+
matrices corresponding to the generators from gen_tuple.
|
|
2442
|
+
|
|
2443
|
+
EXAMPLES::
|
|
2444
|
+
|
|
2445
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
2446
|
+
sage: CHA3.inject_variables()
|
|
2447
|
+
Defining c0, c1
|
|
2448
|
+
sage: repr_type = CHA3.repr_type.RegularRight
|
|
2449
|
+
sage: CHA3._mult_by_regular_rep(c0.to_vector(), (1, -2, -2), repr_type)
|
|
2450
|
+
(u*v/w, (-u^2)/w, -u, (-v)/w, (-v^2)/w, u/w, u*v/w, 1, v,
|
|
2451
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
|
2452
|
+
"""
|
|
2453
|
+
verbose('multiply %s (pre-image %s) by %s using %s'
|
|
2454
|
+
% (vect, braid_preimage, gen_tuple, representation_type), level=2)
|
|
2455
|
+
m = len(gen_tuple)
|
|
2456
|
+
braid_list = None
|
|
2457
|
+
if braid_preimage:
|
|
2458
|
+
braid_list = list(braid_preimage)
|
|
2459
|
+
|
|
2460
|
+
result = vect
|
|
2461
|
+
for i in range(m):
|
|
2462
|
+
verbose('multiply image of %s with position %s' % (braid_list, i), level=2)
|
|
2463
|
+
|
|
2464
|
+
if representation_type == RepresentationType.RegularLeft:
|
|
2465
|
+
gen_ind = gen_tuple[m - i - 1]
|
|
2466
|
+
if braid_list:
|
|
2467
|
+
braid_list = [gen_ind] + braid_list
|
|
2468
|
+
else:
|
|
2469
|
+
gen_ind = gen_tuple[i]
|
|
2470
|
+
if braid_list:
|
|
2471
|
+
braid_list = braid_list + [gen_ind]
|
|
2472
|
+
|
|
2473
|
+
if (gen_ind, representation_type) in list(self._gens_reg_repres_matrix.keys()):
|
|
2474
|
+
mat = self._gens_reg_repres_matrix[(gen_ind, representation_type)]
|
|
2475
|
+
else:
|
|
2476
|
+
if gen_ind > 0:
|
|
2477
|
+
gen = self.gen(gen_ind - 1)
|
|
2478
|
+
mat = gen.matrix(representation_type=representation_type)
|
|
2479
|
+
else:
|
|
2480
|
+
# data of inverse of generators is stored under negative strand-index
|
|
2481
|
+
gen = self.gen(-gen_ind - 1)**(-1)
|
|
2482
|
+
mat = gen.matrix(representation_type=representation_type)
|
|
2483
|
+
|
|
2484
|
+
self._gens_reg_repres_matrix[(gen_ind, representation_type)] = mat
|
|
2485
|
+
|
|
2486
|
+
result = mat * result
|
|
2487
|
+
|
|
2488
|
+
# ------------------------------------------------------------------
|
|
2489
|
+
# save this intermediate result to the dynamic library
|
|
2490
|
+
# ------------------------------------------------------------------
|
|
2491
|
+
if braid_list:
|
|
2492
|
+
verbose('save image of %s to file cache' % braid_list, level=2)
|
|
2493
|
+
self._braid_image_to_filecache(tuple(braid_list), result)
|
|
2494
|
+
|
|
2495
|
+
verbose('multiply %s by %s using %s result %s' % (vect, gen_tuple, representation_type, result), level=2)
|
|
2496
|
+
return result
|
|
2497
|
+
|
|
2498
|
+
# --------------------------------------------------------------------------
|
|
2499
|
+
# _cubic_braid_append_to_basis
|
|
2500
|
+
# --------------------------------------------------------------------------
|
|
2501
|
+
|
|
2502
|
+
def _cubic_braid_append_to_basis(self, cubic_braid):
|
|
2503
|
+
r"""
|
|
2504
|
+
Append the given cubic braid to the finite sub basis which is used for
|
|
2505
|
+
calculation of products and representation matrices.
|
|
2506
|
+
|
|
2507
|
+
This only makes sense if the ``cubic_braid`` is not in this finite
|
|
2508
|
+
sub-basis, before. This can happen if the number of strands is more
|
|
2509
|
+
than 4.
|
|
2510
|
+
|
|
2511
|
+
INPUT:
|
|
2512
|
+
|
|
2513
|
+
- ``cubic_braid`` -- :class:`~sage.groups.cubic_braid.CubicBraid`
|
|
2514
|
+
whose image in ``self`` should be appended
|
|
2515
|
+
|
|
2516
|
+
OUTPUT: the new monomial of ``self``
|
|
2517
|
+
|
|
2518
|
+
EXAMPLES::
|
|
2519
|
+
|
|
2520
|
+
sage: # optional - database_cubic_hecke
|
|
2521
|
+
sage: CHA5 = algebras.CubicHecke(5)
|
|
2522
|
+
sage: be = CHA5.filecache_section().basis_extensions
|
|
2523
|
+
sage: CHA5.reset_filecache(be)
|
|
2524
|
+
sage: CHA5._basis_extension
|
|
2525
|
+
[[4], [-4]]
|
|
2526
|
+
sage: CBG = CHA5.cubic_braid_group()
|
|
2527
|
+
sage: CHA5._cubic_braid_append_to_basis(CBG((4,1)))
|
|
2528
|
+
c3*c0
|
|
2529
|
+
sage: CHA5._basis_extension
|
|
2530
|
+
[[4], [-4], [4, 1]]
|
|
2531
|
+
"""
|
|
2532
|
+
cbTietze = list(cubic_braid.Tietze())
|
|
2533
|
+
order = self.get_order()
|
|
2534
|
+
next_index = len(order)
|
|
2535
|
+
self._basis_extension.append(cbTietze)
|
|
2536
|
+
try:
|
|
2537
|
+
self._rank_basis.update({cubic_braid: next_index}) # supporting :meth:`get_order_key`
|
|
2538
|
+
except AttributeError:
|
|
2539
|
+
pass
|
|
2540
|
+
order.append(cubic_braid)
|
|
2541
|
+
monomial = self.monomial(cubic_braid)
|
|
2542
|
+
self._finite_sub_basis_tuples.update({cubic_braid: cbTietze})
|
|
2543
|
+
|
|
2544
|
+
verbose('registering new basis element: %s (par %s ind %s)'
|
|
2545
|
+
% (cubic_braid, cubic_braid.parent(), next_index), level=2)
|
|
2546
|
+
self._filecache.update_basis_extensions(self._basis_extension)
|
|
2547
|
+
return monomial
|
|
2548
|
+
|
|
2549
|
+
# --------------------------------------------------------------------------
|
|
2550
|
+
# _cubic_braid_basis_tuple
|
|
2551
|
+
# --------------------------------------------------------------------------
|
|
2552
|
+
def _cubic_braid_basis_tuple(self, cubic_braid):
|
|
2553
|
+
r"""
|
|
2554
|
+
Return the Tietze tuple that represents the given cubic_braid in the
|
|
2555
|
+
basis of ``self``.
|
|
2556
|
+
|
|
2557
|
+
In the case ``self`` has more than 4 strands it may happen that the
|
|
2558
|
+
given cubic braid is not contained in the finite subbasis, so far.
|
|
2559
|
+
In this case it is automatically added to it.
|
|
2560
|
+
|
|
2561
|
+
INPUT:
|
|
2562
|
+
|
|
2563
|
+
- ``cubic_braid`` -- :class:`~sage.groups.cubic_braid.CubicBraid`
|
|
2564
|
+
|
|
2565
|
+
OUTPUT: a tuple from the basis representing the cubic braid
|
|
2566
|
+
|
|
2567
|
+
EXAMPLES::
|
|
2568
|
+
|
|
2569
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
2570
|
+
sage: CBG = CHA2.cubic_braid_group()
|
|
2571
|
+
sage: CHA2._cubic_braid_basis_tuple(CBG((1, 1)))
|
|
2572
|
+
(-1,)
|
|
2573
|
+
"""
|
|
2574
|
+
tietze_list = self._basis_tietze()
|
|
2575
|
+
cubic_braid_tietze = cubic_braid.Tietze()
|
|
2576
|
+
if list(cubic_braid_tietze) in tietze_list:
|
|
2577
|
+
verbose('cubic_braid_tietze: %s in basis' % str(cubic_braid_tietze), level=2)
|
|
2578
|
+
return cubic_braid_tietze
|
|
2579
|
+
else:
|
|
2580
|
+
if cubic_braid in self._finite_sub_basis_tuples.keys():
|
|
2581
|
+
verbose('cubic_braid: %s in finite_sub_basis' % cubic_braid, level=2)
|
|
2582
|
+
return self._finite_sub_basis_tuples[cubic_braid]
|
|
2583
|
+
|
|
2584
|
+
for tup in tietze_list:
|
|
2585
|
+
cb_tup = self.cubic_braid_group()(tup)
|
|
2586
|
+
if cubic_braid == cb_tup:
|
|
2587
|
+
self._finite_sub_basis_tuples.update({cb_tup: tup})
|
|
2588
|
+
verbose('cubic_braid: %s added to finite_sub_basis with tuple %s'
|
|
2589
|
+
% (cubic_braid, tup), level=2)
|
|
2590
|
+
return tuple(tup)
|
|
2591
|
+
return None
|
|
2592
|
+
|
|
2593
|
+
# --------------------------------------------------------------------------
|
|
2594
|
+
# _cubic_braid_image
|
|
2595
|
+
# --------------------------------------------------------------------------
|
|
2596
|
+
def _cubic_braid_image(self, cubic_braid, check=True):
|
|
2597
|
+
r"""
|
|
2598
|
+
Return the given cubic braid as monomial of ``self``, that is the image
|
|
2599
|
+
under the map onto the basis.
|
|
2600
|
+
|
|
2601
|
+
If the number of strands is larger than 4, the corresponding basis
|
|
2602
|
+
element may not be contained in the order of ``self``. In this
|
|
2603
|
+
case it will be appended here.
|
|
2604
|
+
|
|
2605
|
+
INPUT:
|
|
2606
|
+
|
|
2607
|
+
- ``cubic_braid`` -- :class:`~sage.groups.cubic_braid.CubicBraid`
|
|
2608
|
+
whose image in ``self`` should be returned
|
|
2609
|
+
- ``check`` -- boolean (default: ``True``); check if the given cubic
|
|
2610
|
+
braid is already registered in the finite sub basis; if set to
|
|
2611
|
+
``False`` duplicate entries can occur
|
|
2612
|
+
|
|
2613
|
+
EXAMPLES::
|
|
2614
|
+
|
|
2615
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
2616
|
+
sage: CBG = CHA2.cubic_braid_group()
|
|
2617
|
+
sage: CHA2._cubic_braid_image(CBG((1,1)))
|
|
2618
|
+
c^-1
|
|
2619
|
+
"""
|
|
2620
|
+
if check:
|
|
2621
|
+
tup = self._cubic_braid_basis_tuple(cubic_braid)
|
|
2622
|
+
if tup is not None:
|
|
2623
|
+
return self._tietze_to_finite_sub_basis_monomial(tup)
|
|
2624
|
+
return self._cubic_braid_append_to_basis(cubic_braid)
|
|
2625
|
+
|
|
2626
|
+
# --------------------------------------------------------------------------
|
|
2627
|
+
# _extend_braid_automorphism
|
|
2628
|
+
# --------------------------------------------------------------------------
|
|
2629
|
+
def _extend_braid_automorphism(self, element, braid_automorphism):
|
|
2630
|
+
r"""
|
|
2631
|
+
Return the image of element under the extension of the given braid group
|
|
2632
|
+
automorphism to ``self``. It is assumed that the given
|
|
2633
|
+
``braid_automorphism`` factors through ``self``.
|
|
2634
|
+
|
|
2635
|
+
INPUT:
|
|
2636
|
+
|
|
2637
|
+
- ``element`` -- an element class of ``self``
|
|
2638
|
+
- ``braid_automorphism`` -- braid group automorphism factoring through
|
|
2639
|
+
``self``
|
|
2640
|
+
|
|
2641
|
+
OUTPUT:
|
|
2642
|
+
|
|
2643
|
+
Element class of ``self`` representing the image of element
|
|
2644
|
+
under the extension of the given braid group automorphism.
|
|
2645
|
+
|
|
2646
|
+
EXAMPLES::
|
|
2647
|
+
|
|
2648
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
2649
|
+
sage: br, = CHA2.gens()
|
|
2650
|
+
sage: CHA2.mirror_isomorphism(br) # indirect doctest
|
|
2651
|
+
c^-1
|
|
2652
|
+
"""
|
|
2653
|
+
|
|
2654
|
+
result = self.zero()
|
|
2655
|
+
for braid in element.support():
|
|
2656
|
+
autom_braid = braid_automorphism(braid)
|
|
2657
|
+
img_braid = self._braid_image_from_reduced_powers(autom_braid.Tietze())
|
|
2658
|
+
result += element[braid] * img_braid
|
|
2659
|
+
|
|
2660
|
+
return result
|
|
2661
|
+
|
|
2662
|
+
# --------------------------------------------------------------------------
|
|
2663
|
+
# _markov_trace_module
|
|
2664
|
+
# --------------------------------------------------------------------------
|
|
2665
|
+
def _markov_trace_module(self, extended=False, field_embedding=False):
|
|
2666
|
+
r"""
|
|
2667
|
+
Return the module that contains the formal Markov trace as elements.
|
|
2668
|
+
|
|
2669
|
+
INPUT:
|
|
2670
|
+
|
|
2671
|
+
- ``extended`` -- boolean (default: ``False``); if set to ``True`` the
|
|
2672
|
+
base ring of the module is the Markov trace version of the generic
|
|
2673
|
+
extension ring of ``self``.
|
|
2674
|
+
|
|
2675
|
+
- ``field_embedding`` -- boolean (default: ``False``); if set to ``True`
|
|
2676
|
+
the base ring of the module is the smallest field containing the
|
|
2677
|
+
generic extension ring of ``self``. The keyword is meaningless if
|
|
2678
|
+
``extended=False``.
|
|
2679
|
+
|
|
2680
|
+
OUTPUT: a :class:`~sage.combinat.free_module.CombinatorialFreeModule`
|
|
2681
|
+
|
|
2682
|
+
EXAMPLES::
|
|
2683
|
+
|
|
2684
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
2685
|
+
sage: CHA2._markov_trace_module()
|
|
2686
|
+
Free module generated by {U1, U2}
|
|
2687
|
+
over Multivariate Polynomial Ring in u, v, w, s
|
|
2688
|
+
over Integer Ring localized at (s, w, v, u)
|
|
2689
|
+
|
|
2690
|
+
sage: CHA2._markov_trace_module(extended=True)
|
|
2691
|
+
Free module generated by {U1, U2}
|
|
2692
|
+
over Multivariate Laurent Polynomial Ring in a, b, c, s
|
|
2693
|
+
over Splitting Algebra of x^2 + x + 1 with roots [e3, -e3 - 1]
|
|
2694
|
+
over Integer Ring
|
|
2695
|
+
|
|
2696
|
+
sage: CHA2._markov_trace_module(extended=True, field_embedding=True)
|
|
2697
|
+
Free module generated by {U1, U2}
|
|
2698
|
+
over Fraction Field of Multivariate Polynomial Ring in a, b, c, s
|
|
2699
|
+
over Cyclotomic Field of order 3 and degree 2
|
|
2700
|
+
"""
|
|
2701
|
+
from sage.modules.free_module import FreeModule
|
|
2702
|
+
from sage.databases.cubic_hecke_db import MarkovTraceModuleBasis
|
|
2703
|
+
basis = [b for b in MarkovTraceModuleBasis if b.strands() <= self._nstrands]
|
|
2704
|
+
BRM = self.base_ring(generic=True).markov_trace_version()
|
|
2705
|
+
if extended:
|
|
2706
|
+
BRM = BRM.extension_ring()
|
|
2707
|
+
if field_embedding:
|
|
2708
|
+
emb = BRM.field_embedding()
|
|
2709
|
+
BRM = emb.codomain()
|
|
2710
|
+
return FreeModule(BRM, basis)
|
|
2711
|
+
|
|
2712
|
+
# --------------------------------------------------------------------------
|
|
2713
|
+
# _markov_trace_coeffs
|
|
2714
|
+
# --------------------------------------------------------------------------
|
|
2715
|
+
@cached_method
|
|
2716
|
+
def _markov_trace_coeffs(self):
|
|
2717
|
+
r"""
|
|
2718
|
+
Return a list of formal Markov traces of the basis elements of ``self``.
|
|
2719
|
+
|
|
2720
|
+
OUTPUT:
|
|
2721
|
+
|
|
2722
|
+
A list of elements of the Markov trace module (over the Markov trace
|
|
2723
|
+
version of the generic base ring). Each entry of the list corresponds
|
|
2724
|
+
to the according basis element of ``self``.
|
|
2725
|
+
|
|
2726
|
+
EXAMPLES::
|
|
2727
|
+
|
|
2728
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
2729
|
+
sage: CHA2._markov_trace_coeffs()
|
|
2730
|
+
[B[U2], s*B[U1], 1/s*B[U1]]
|
|
2731
|
+
sage: M = _[0].parent(); M
|
|
2732
|
+
Free module generated by {U1, U2}
|
|
2733
|
+
over Multivariate Polynomial Ring in u, v, w, s
|
|
2734
|
+
over Integer Ring localized at (s, w, v, u)
|
|
2735
|
+
"""
|
|
2736
|
+
M = self._markov_trace_module()
|
|
2737
|
+
Mbas = M.basis().keys()
|
|
2738
|
+
db = self._database
|
|
2739
|
+
sec = db.section.markov_tr_cfs
|
|
2740
|
+
cfs = db.read(sec, variables=M.base_ring().gens(), nstrands=self._nstrands)
|
|
2741
|
+
d = self.dimension()
|
|
2742
|
+
return [sum(cfs[bas_ele][i]*M(bas_ele) for bas_ele in Mbas) for i in range(d)]
|
|
2743
|
+
|
|
2744
|
+
############################################################################
|
|
2745
|
+
# --------------------------------------------------------------------------
|
|
2746
|
+
# public methods
|
|
2747
|
+
# --------------------------------------------------------------------------
|
|
2748
|
+
############################################################################
|
|
2749
|
+
def filecache_section(self):
|
|
2750
|
+
r"""
|
|
2751
|
+
Return the ``enum`` to select a section in the file cache.
|
|
2752
|
+
|
|
2753
|
+
EXAMPLES::
|
|
2754
|
+
|
|
2755
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
2756
|
+
sage: list(CHA2.filecache_section())
|
|
2757
|
+
[<section.matrix_representations: 'matrix_representations'>,
|
|
2758
|
+
<section.braid_images: 'braid_images'>,
|
|
2759
|
+
<section.basis_extensions: 'basis_extensions'>,
|
|
2760
|
+
<section.markov_trace: 'markov_trace'>]
|
|
2761
|
+
"""
|
|
2762
|
+
return self._filecache.section
|
|
2763
|
+
|
|
2764
|
+
def is_filecache_empty(self, section=None):
|
|
2765
|
+
r"""
|
|
2766
|
+
Return ``True`` if the file cache of the given ``section`` is empty.
|
|
2767
|
+
If no ``section`` is given the answer is given for the complete
|
|
2768
|
+
file cache.
|
|
2769
|
+
|
|
2770
|
+
INPUT:
|
|
2771
|
+
|
|
2772
|
+
- ``section`` -- (default: all sections) an element of enum
|
|
2773
|
+
:class:`~sage.databases.cubic_hecke_db.CubicHeckeFileCache.section`
|
|
2774
|
+
that can be selected using :meth:`filecache_section`
|
|
2775
|
+
|
|
2776
|
+
EXAMPLES::
|
|
2777
|
+
|
|
2778
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
2779
|
+
sage: CHA2.is_filecache_empty()
|
|
2780
|
+
False
|
|
2781
|
+
"""
|
|
2782
|
+
return self._filecache.is_empty(section=section)
|
|
2783
|
+
|
|
2784
|
+
def reset_filecache(self, section=None, commit=True):
|
|
2785
|
+
r"""
|
|
2786
|
+
Reset the file cache of the given ``section`` resp. the complete
|
|
2787
|
+
file cache if no ``section`` is given.
|
|
2788
|
+
|
|
2789
|
+
INPUT:
|
|
2790
|
+
|
|
2791
|
+
- ``section`` -- (default: all sections) an element of enum
|
|
2792
|
+
:class:`~sage.databases.cubic_hecke_db.CubicHeckeFileCache.section`
|
|
2793
|
+
that can be selected using :meth:`filecache_section`
|
|
2794
|
+
- ``commit`` -- boolean (default: ``True``); if set to ``False`` the
|
|
2795
|
+
reset is not written to the filesystem
|
|
2796
|
+
|
|
2797
|
+
EXAMPLES::
|
|
2798
|
+
|
|
2799
|
+
sage: # optional - database_cubic_hecke
|
|
2800
|
+
sage: CHA5 = algebras.CubicHecke(5)
|
|
2801
|
+
sage: be = CHA5.filecache_section().basis_extensions
|
|
2802
|
+
sage: CHA5.is_filecache_empty(be)
|
|
2803
|
+
False
|
|
2804
|
+
sage: CHA5.reset_filecache(be)
|
|
2805
|
+
sage: CHA5.is_filecache_empty(be)
|
|
2806
|
+
True
|
|
2807
|
+
"""
|
|
2808
|
+
fc = self._filecache
|
|
2809
|
+
if section == fc.section.basis_extensions:
|
|
2810
|
+
if self._nstrands < 5:
|
|
2811
|
+
raise ValueError('not allowed for less than 5 strand')
|
|
2812
|
+
fc.reset_library(section=section)
|
|
2813
|
+
|
|
2814
|
+
if section == fc.section.basis_extensions:
|
|
2815
|
+
self._init_basis_extension()
|
|
2816
|
+
if commit:
|
|
2817
|
+
fc.write(section=section)
|
|
2818
|
+
|
|
2819
|
+
def strands(self):
|
|
2820
|
+
r"""
|
|
2821
|
+
Return the number of strands of the braid group whose group algebra
|
|
2822
|
+
image is ``self``.
|
|
2823
|
+
|
|
2824
|
+
EXAMPLES::
|
|
2825
|
+
|
|
2826
|
+
sage: CHA4 = algebras.CubicHecke(2)
|
|
2827
|
+
sage: CHA4.strands()
|
|
2828
|
+
2
|
|
2829
|
+
"""
|
|
2830
|
+
return self._nstrands
|
|
2831
|
+
|
|
2832
|
+
# --------------------------------------------------------------------------
|
|
2833
|
+
# Garside involution
|
|
2834
|
+
# --------------------------------------------------------------------------
|
|
2835
|
+
def garside_involution(self, element):
|
|
2836
|
+
r"""
|
|
2837
|
+
Return the image of the given element of ``self`` under the extension of
|
|
2838
|
+
the Garside involution of braids to ``self``.
|
|
2839
|
+
|
|
2840
|
+
This method may be invoked by the ``revert_garside`` method of the
|
|
2841
|
+
element class of ``self``, alternatively.
|
|
2842
|
+
|
|
2843
|
+
INPUT:
|
|
2844
|
+
|
|
2845
|
+
- ``element`` -- instance of the element class of ``self``
|
|
2846
|
+
|
|
2847
|
+
OUTPUT:
|
|
2848
|
+
|
|
2849
|
+
Instance of the element class of ``self`` representing the image of
|
|
2850
|
+
``element`` under the extension of the Garside involution to ``self``.
|
|
2851
|
+
|
|
2852
|
+
EXAMPLES::
|
|
2853
|
+
|
|
2854
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
2855
|
+
sage: ele = CHA3.an_element()
|
|
2856
|
+
sage: ele_gar = CHA3.garside_involution(ele); ele_gar
|
|
2857
|
+
-w*c1*c0^-1 + u*c0 + v*c1 - ((v*w-u)/w)
|
|
2858
|
+
sage: ele == CHA3.garside_involution(ele_gar)
|
|
2859
|
+
True
|
|
2860
|
+
"""
|
|
2861
|
+
braid_group = self.braid_group()
|
|
2862
|
+
reverse_gens = list(braid_group.gens())
|
|
2863
|
+
reverse_gens.reverse()
|
|
2864
|
+
brgrp_garside_involution = braid_group.hom(reverse_gens, check=False)
|
|
2865
|
+
return self._extend_braid_automorphism(element, brgrp_garside_involution)
|
|
2866
|
+
|
|
2867
|
+
# --------------------------------------------------------------------------
|
|
2868
|
+
# orientation anti involution
|
|
2869
|
+
# --------------------------------------------------------------------------
|
|
2870
|
+
def orientation_antiinvolution(self, element):
|
|
2871
|
+
r"""
|
|
2872
|
+
Return the image of the given element of ``self`` under the extension of
|
|
2873
|
+
the orientation anti involution of braids to ``self``. The orientation
|
|
2874
|
+
anti involution of a braid is given by reversing the order of generators
|
|
2875
|
+
in the braid word.
|
|
2876
|
+
|
|
2877
|
+
This method may be invoked by the ``revert_orientation`` method of the
|
|
2878
|
+
element class of ``self``, alternatively.
|
|
2879
|
+
|
|
2880
|
+
INPUT:
|
|
2881
|
+
|
|
2882
|
+
- ``element`` -- instance of the element class of ``self``
|
|
2883
|
+
|
|
2884
|
+
OUTPUT:
|
|
2885
|
+
|
|
2886
|
+
Instance of the element class of ``self`` representing the image of
|
|
2887
|
+
``element`` under the extension of the orientation reversing braid
|
|
2888
|
+
involution to ``self``.
|
|
2889
|
+
|
|
2890
|
+
EXAMPLES::
|
|
2891
|
+
|
|
2892
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
2893
|
+
sage: ele = CHA3.an_element()
|
|
2894
|
+
sage: ele_ori = CHA3.orientation_antiinvolution(ele); ele_ori
|
|
2895
|
+
-w*c1^-1*c0 + v*c0 + u*c1 - ((v*w-u)/w)
|
|
2896
|
+
sage: ele == CHA3.orientation_antiinvolution(ele_ori)
|
|
2897
|
+
True
|
|
2898
|
+
"""
|
|
2899
|
+
braid_group = self.braid_group()
|
|
2900
|
+
|
|
2901
|
+
def brgrp_orientation_antiinvolution(braid):
|
|
2902
|
+
braid_list = list(braid.Tietze())
|
|
2903
|
+
braid_list.reverse()
|
|
2904
|
+
return braid_group(tuple(braid_list))
|
|
2905
|
+
return self._extend_braid_automorphism(element, brgrp_orientation_antiinvolution)
|
|
2906
|
+
|
|
2907
|
+
# --------------------------------------------------------------------------
|
|
2908
|
+
# mirror isomorphism
|
|
2909
|
+
# --------------------------------------------------------------------------
|
|
2910
|
+
def mirror_isomorphism(self, element):
|
|
2911
|
+
r"""
|
|
2912
|
+
Return the image of the given element of ``self`` under the extension
|
|
2913
|
+
of the mirror involution of braids to ``self``. The mirror involution
|
|
2914
|
+
of a braid is given by inverting all generators in the braid word. It
|
|
2915
|
+
does not factor through ``self`` over the base ring but it factors
|
|
2916
|
+
through ``self`` considered as a `\ZZ`-module relative to the mirror
|
|
2917
|
+
automorphism of the generic base ring. Considering ``self`` as algebra
|
|
2918
|
+
over its base ring this involution defines an isomorphism of ``self``
|
|
2919
|
+
onto a different cubic Hecke algebra with a different cubic equation.
|
|
2920
|
+
This is defined over a different base (and extension) ring than
|
|
2921
|
+
``self``. It can be obtained by the method ``mirror_image`` or as
|
|
2922
|
+
parent of the output of this method.
|
|
2923
|
+
|
|
2924
|
+
This method may be invoked by the ``CubicHeckeElelemnt.revert_mirror``
|
|
2925
|
+
method of the element class of ``self``, alternatively.
|
|
2926
|
+
|
|
2927
|
+
INPUT:
|
|
2928
|
+
|
|
2929
|
+
- ``element`` -- instance of the element class of ``self``
|
|
2930
|
+
|
|
2931
|
+
OUTPUT:
|
|
2932
|
+
|
|
2933
|
+
Instance of the element class of the mirror image of ``self``
|
|
2934
|
+
representing the image of element under the extension of the braid
|
|
2935
|
+
mirror involution to ``self``.
|
|
2936
|
+
|
|
2937
|
+
EXAMPLES::
|
|
2938
|
+
|
|
2939
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
2940
|
+
sage: ele = CHA3.an_element()
|
|
2941
|
+
sage: ele_mirr = CHA3.mirror_isomorphism(ele); ele_mirr
|
|
2942
|
+
-1/w*c0^-1*c1 + u/w*c0^-1 + v/w*c1^-1 + ((v*w-u)/w)
|
|
2943
|
+
sage: ele_mirr2 = ele.revert_mirror() # indirect doctest
|
|
2944
|
+
sage: ele_mirr == ele_mirr2
|
|
2945
|
+
True
|
|
2946
|
+
sage: par_mirr = ele_mirr.parent()
|
|
2947
|
+
sage: par_mirr == CHA3
|
|
2948
|
+
False
|
|
2949
|
+
sage: par_mirr == CHA3.mirror_image()
|
|
2950
|
+
True
|
|
2951
|
+
sage: ele == par_mirr.mirror_isomorphism(ele_mirr)
|
|
2952
|
+
True
|
|
2953
|
+
"""
|
|
2954
|
+
mirror_image = self.mirror_image()
|
|
2955
|
+
braid_group = self.braid_group()
|
|
2956
|
+
mirror_involution = braid_group.hom([~g for g in braid_group.gens()], check=False)
|
|
2957
|
+
# Todo: have mirror_involution be a method of :class:`BraidGroup_class`
|
|
2958
|
+
base_ring_mirror = self._base_ring_mirror
|
|
2959
|
+
element_vec = vector([base_ring_mirror(cf) for cf in list(element.to_vector())])
|
|
2960
|
+
element_mirr = mirror_image.from_vector(element_vec)
|
|
2961
|
+
return mirror_image._extend_braid_automorphism(element_mirr, mirror_involution)
|
|
2962
|
+
|
|
2963
|
+
# --------------------------------------------------------------------------
|
|
2964
|
+
# cubic_equation
|
|
2965
|
+
# --------------------------------------------------------------------------
|
|
2966
|
+
def cubic_equation(self, var='h', as_coefficients=False, generic=False):
|
|
2967
|
+
r"""
|
|
2968
|
+
Return the cubic equation attached to ``self``.
|
|
2969
|
+
|
|
2970
|
+
INPUT:
|
|
2971
|
+
|
|
2972
|
+
- ``var`` -- string (default: ``'h'``); setting the indeterminate of the
|
|
2973
|
+
equation
|
|
2974
|
+
- ``as_coefficients`` -- boolean (default: ``False``); if set to ``True``
|
|
2975
|
+
the list of coefficients is returned
|
|
2976
|
+
- ``generic`` -- boolean (default: ``False``); if set to ``True`` the
|
|
2977
|
+
cubic equation will be given over the generic base ring
|
|
2978
|
+
|
|
2979
|
+
OUTPUT:
|
|
2980
|
+
|
|
2981
|
+
A polynomial over the base ring (resp. generic base ring if ``generic``
|
|
2982
|
+
is set to True). In case ``as_coefficients`` is set to ``True`` a list
|
|
2983
|
+
of them is returned.
|
|
2984
|
+
|
|
2985
|
+
EXAMPLES::
|
|
2986
|
+
|
|
2987
|
+
sage: CHA2 = algebras.CubicHecke(2, cubic_equation_roots=(E(3), ~E(3), 1))
|
|
2988
|
+
sage: CHA2.cubic_equation()
|
|
2989
|
+
h^3 - 1
|
|
2990
|
+
sage: CHA2.cubic_equation(generic=True)
|
|
2991
|
+
h^3 - u*h^2 + v*h - w
|
|
2992
|
+
sage: CHA2.cubic_equation(as_coefficients=True, generic=True)
|
|
2993
|
+
[-w, v, -u, 1]
|
|
2994
|
+
sage: CHA2.cubic_equation(as_coefficients=True)
|
|
2995
|
+
[-1, 0, 0, 1]
|
|
2996
|
+
"""
|
|
2997
|
+
BaseRing = self.base_ring(generic=generic)
|
|
2998
|
+
if generic:
|
|
2999
|
+
u, v, w = BaseRing.gens()
|
|
3000
|
+
else:
|
|
3001
|
+
u, v, w = self._cubic_equation_parameters
|
|
3002
|
+
cf = [-w, v, -u, 1]
|
|
3003
|
+
if as_coefficients:
|
|
3004
|
+
return cf
|
|
3005
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
3006
|
+
P = PolynomialRing(BaseRing, var)
|
|
3007
|
+
return P(cf)
|
|
3008
|
+
|
|
3009
|
+
# --------------------------------------------------------------------------
|
|
3010
|
+
# cubic_equation_roots
|
|
3011
|
+
# --------------------------------------------------------------------------
|
|
3012
|
+
def cubic_equation_roots(self, generic=False):
|
|
3013
|
+
r"""
|
|
3014
|
+
Return the roots of the underlying cubic equation.
|
|
3015
|
+
|
|
3016
|
+
INPUT:
|
|
3017
|
+
|
|
3018
|
+
- ``generic`` -- boolean (default: ``False``); if set to ``True`` the
|
|
3019
|
+
roots are returned as elements of the generic extension ring
|
|
3020
|
+
|
|
3021
|
+
OUTPUT: a triple consisting of the roots
|
|
3022
|
+
|
|
3023
|
+
EXAMPLES::
|
|
3024
|
+
|
|
3025
|
+
sage: CHA2 = algebras.CubicHecke(2, cubic_equation_roots=(3, 4, 5))
|
|
3026
|
+
sage: CHA2.cubic_equation()
|
|
3027
|
+
h^3 - 12*h^2 + 47*h - 60
|
|
3028
|
+
sage: CHA2.cubic_equation_roots()
|
|
3029
|
+
[3, 4, 5]
|
|
3030
|
+
sage: CHA2.cubic_equation_roots(generic=True)
|
|
3031
|
+
[a, b, c]
|
|
3032
|
+
"""
|
|
3033
|
+
if generic:
|
|
3034
|
+
return self._generic_cubic_equation_roots
|
|
3035
|
+
else:
|
|
3036
|
+
return self._cubic_equation_roots
|
|
3037
|
+
|
|
3038
|
+
# --------------------------------------------------------------------------
|
|
3039
|
+
# cubic_equation_roots
|
|
3040
|
+
# --------------------------------------------------------------------------
|
|
3041
|
+
def cubic_equation_parameters(self, generic=False):
|
|
3042
|
+
r"""
|
|
3043
|
+
Return the coefficients of the underlying cubic equation.
|
|
3044
|
+
|
|
3045
|
+
INPUT:
|
|
3046
|
+
|
|
3047
|
+
- ``generic`` -- boolean (default: ``False``); if set to ``True`` the
|
|
3048
|
+
coefficients are returned as elements of the generic base ring
|
|
3049
|
+
|
|
3050
|
+
OUTPUT: a triple consisting of the coefficients
|
|
3051
|
+
|
|
3052
|
+
EXAMPLES::
|
|
3053
|
+
|
|
3054
|
+
sage: CHA2 = algebras.CubicHecke(2, cubic_equation_roots=(3, 4, 5))
|
|
3055
|
+
sage: CHA2.cubic_equation()
|
|
3056
|
+
h^3 - 12*h^2 + 47*h - 60
|
|
3057
|
+
sage: CHA2.cubic_equation_parameters()
|
|
3058
|
+
[12, 47, 60]
|
|
3059
|
+
sage: CHA2.cubic_equation_parameters(generic=True)
|
|
3060
|
+
[u, v, w]
|
|
3061
|
+
"""
|
|
3062
|
+
if generic:
|
|
3063
|
+
return self._generic_cubic_equation_parameters
|
|
3064
|
+
else:
|
|
3065
|
+
return self._cubic_equation_parameters
|
|
3066
|
+
|
|
3067
|
+
# --------------------------------------------------------------------------
|
|
3068
|
+
# base_ring
|
|
3069
|
+
# --------------------------------------------------------------------------
|
|
3070
|
+
def base_ring(self, generic=False):
|
|
3071
|
+
r"""
|
|
3072
|
+
Return the base ring of ``self``.
|
|
3073
|
+
|
|
3074
|
+
INPUT:
|
|
3075
|
+
|
|
3076
|
+
- ``generic`` -- boolean (default: ``False``); if ``True`` the ring
|
|
3077
|
+
of definition (here often called the generic base ring) is returned
|
|
3078
|
+
|
|
3079
|
+
EXAMMPLES::
|
|
3080
|
+
|
|
3081
|
+
sage: CHA2 = algebras.CubicHecke(2, cubic_equation_roots=(3, 4, 5))
|
|
3082
|
+
sage: CHA2.base_ring()
|
|
3083
|
+
Integer Ring localized at (2, 3, 5)
|
|
3084
|
+
sage: CHA2.base_ring(generic=True)
|
|
3085
|
+
Multivariate Polynomial Ring in u, v, w
|
|
3086
|
+
over Integer Ring localized at (w,)
|
|
3087
|
+
"""
|
|
3088
|
+
if generic:
|
|
3089
|
+
return self._ring_of_definition
|
|
3090
|
+
else:
|
|
3091
|
+
return super().base_ring()
|
|
3092
|
+
|
|
3093
|
+
# --------------------------------------------------------------------------
|
|
3094
|
+
# extension_ring
|
|
3095
|
+
# --------------------------------------------------------------------------
|
|
3096
|
+
def extension_ring(self, generic=False):
|
|
3097
|
+
r"""
|
|
3098
|
+
Return the extension ring of ``self``.
|
|
3099
|
+
|
|
3100
|
+
This is an extension of its base ring containing the roots
|
|
3101
|
+
of the cubic equation.
|
|
3102
|
+
|
|
3103
|
+
INPUT:
|
|
3104
|
+
|
|
3105
|
+
- ``generic`` -- boolean (default: ``False``); if ``True`` the
|
|
3106
|
+
extension ring of definition (here often called the generic
|
|
3107
|
+
extension ring) is returned
|
|
3108
|
+
|
|
3109
|
+
EXAMMPLES::
|
|
3110
|
+
|
|
3111
|
+
sage: CHA2 = algebras.CubicHecke(2, cubic_equation_roots=(3, 4, 5))
|
|
3112
|
+
sage: CHA2.extension_ring()
|
|
3113
|
+
Splitting Algebra of T^2 + T + 1 with roots [E3, -E3 - 1]
|
|
3114
|
+
over Integer Ring localized at (2, 3, 5)
|
|
3115
|
+
sage: CHA2.extension_ring(generic=True)
|
|
3116
|
+
Multivariate Laurent Polynomial Ring in a, b, c
|
|
3117
|
+
over Splitting Algebra of x^2 + x + 1
|
|
3118
|
+
with roots [e3, -e3 - 1] over Integer Ring
|
|
3119
|
+
"""
|
|
3120
|
+
if generic:
|
|
3121
|
+
return self._generic_extension_ring
|
|
3122
|
+
else:
|
|
3123
|
+
return self._extension_ring
|
|
3124
|
+
|
|
3125
|
+
# --------------------------------------------------------------------------
|
|
3126
|
+
# cyclotomic_generator
|
|
3127
|
+
# --------------------------------------------------------------------------
|
|
3128
|
+
def cyclotomic_generator(self, generic=False):
|
|
3129
|
+
r"""
|
|
3130
|
+
Return the third root of unity as element of the extension ring.
|
|
3131
|
+
|
|
3132
|
+
The only thing where this is needed is in the nine dimensional
|
|
3133
|
+
irreducible representations of the cubic Hecke algebra on four strands
|
|
3134
|
+
(see the examples of :meth:`CubicHeckeElement.matrix` for instance).
|
|
3135
|
+
|
|
3136
|
+
INPUT:
|
|
3137
|
+
|
|
3138
|
+
- ``generic`` -- boolean (default: ``False``); if ``True`` the
|
|
3139
|
+
cyclotomic generator is returned as an element extension ring of
|
|
3140
|
+
definition
|
|
3141
|
+
|
|
3142
|
+
EXAMMPLES::
|
|
3143
|
+
|
|
3144
|
+
sage: CHA2 = algebras.CubicHecke(2, cubic_equation_roots=(3, 4, 5))
|
|
3145
|
+
sage: CHA2.cyclotomic_generator()
|
|
3146
|
+
E3
|
|
3147
|
+
sage: CHA2.cyclotomic_generator(generic=True)
|
|
3148
|
+
e3
|
|
3149
|
+
"""
|
|
3150
|
+
e3gen = self.extension_ring(generic=True).cyclotomic_generator()
|
|
3151
|
+
if generic:
|
|
3152
|
+
return e3gen
|
|
3153
|
+
else:
|
|
3154
|
+
return self._generic_extension_ring_map(e3gen)
|
|
3155
|
+
|
|
3156
|
+
# --------------------------------------------------------------------------
|
|
3157
|
+
# braid_group
|
|
3158
|
+
# --------------------------------------------------------------------------
|
|
3159
|
+
def braid_group(self):
|
|
3160
|
+
r"""
|
|
3161
|
+
Return the braid group attached to ``self``.
|
|
3162
|
+
|
|
3163
|
+
EXAMPLES::
|
|
3164
|
+
|
|
3165
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
3166
|
+
sage: CHA2.braid_group()
|
|
3167
|
+
Braid group on 2 strands
|
|
3168
|
+
"""
|
|
3169
|
+
return self._braid_group
|
|
3170
|
+
|
|
3171
|
+
# --------------------------------------------------------------------------
|
|
3172
|
+
# cubic_braid_group
|
|
3173
|
+
# --------------------------------------------------------------------------
|
|
3174
|
+
def cubic_braid_group(self):
|
|
3175
|
+
r"""
|
|
3176
|
+
Return the cubic braid group attached to ``self``.
|
|
3177
|
+
|
|
3178
|
+
EXAMPLES::
|
|
3179
|
+
|
|
3180
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
3181
|
+
sage: CHA2.cubic_braid_group()
|
|
3182
|
+
Cubic Braid group on 2 strands
|
|
3183
|
+
"""
|
|
3184
|
+
return self._cubic_braid_group
|
|
3185
|
+
|
|
3186
|
+
# --------------------------------------------------------------------------
|
|
3187
|
+
# braid_group_algebra
|
|
3188
|
+
# --------------------------------------------------------------------------
|
|
3189
|
+
def braid_group_algebra(self):
|
|
3190
|
+
r"""
|
|
3191
|
+
Return the group algebra of braid group attached to ``self`` over the
|
|
3192
|
+
base ring of ``self``.
|
|
3193
|
+
|
|
3194
|
+
EXAMPLES::
|
|
3195
|
+
|
|
3196
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
3197
|
+
sage: CHA2.braid_group_algebra()
|
|
3198
|
+
Algebra of Braid group on 2 strands
|
|
3199
|
+
over Multivariate Polynomial Ring in u, v, w
|
|
3200
|
+
over Integer Ring localized at (w,)
|
|
3201
|
+
"""
|
|
3202
|
+
return self._braid_group_algebra
|
|
3203
|
+
|
|
3204
|
+
# --------------------------------------------------------------------------
|
|
3205
|
+
# cubic_braid_group_algebra
|
|
3206
|
+
# --------------------------------------------------------------------------
|
|
3207
|
+
def cubic_braid_group_algebra(self):
|
|
3208
|
+
r"""
|
|
3209
|
+
Return the group algebra of cubic braid group attached to ``self`` over
|
|
3210
|
+
the base ring of ``self``.
|
|
3211
|
+
|
|
3212
|
+
EXAMPLES::
|
|
3213
|
+
|
|
3214
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
3215
|
+
sage: CHA2.cubic_braid_group_algebra()
|
|
3216
|
+
Algebra of Cubic Braid group on 2 strands
|
|
3217
|
+
over Multivariate Polynomial Ring in u, v, w
|
|
3218
|
+
over Integer Ring localized at (w,)
|
|
3219
|
+
"""
|
|
3220
|
+
return self._cubic_braid_group_algebra
|
|
3221
|
+
|
|
3222
|
+
# --------------------------------------------------------------------------
|
|
3223
|
+
# creating a CubicHeckeAlgebra as sub-algebra of self on less strands
|
|
3224
|
+
# --------------------------------------------------------------------------
|
|
3225
|
+
def cubic_hecke_subalgebra(self, nstrands=None):
|
|
3226
|
+
r"""
|
|
3227
|
+
Return a :class:`CubicHeckeAlgebra` that realizes a sub-algebra
|
|
3228
|
+
of ``self`` on the first ``n_strands`` strands.
|
|
3229
|
+
|
|
3230
|
+
INPUT:
|
|
3231
|
+
|
|
3232
|
+
- ``nstrands`` -- integer at least 1 and at most :meth:`strands` giving
|
|
3233
|
+
the number of strands for the subgroup; the default is one strand
|
|
3234
|
+
less than ``self`` has
|
|
3235
|
+
|
|
3236
|
+
OUTPUT: an instance of this class realizing the sub-algebra
|
|
3237
|
+
|
|
3238
|
+
EXAMPLES::
|
|
3239
|
+
|
|
3240
|
+
sage: CHA3 = algebras.CubicHecke(3, cubic_equation_roots=(3, 4, 5))
|
|
3241
|
+
sage: CHA3.cubic_hecke_subalgebra()
|
|
3242
|
+
Cubic Hecke algebra on 2 strands
|
|
3243
|
+
over Integer Ring localized at (2, 3, 5)
|
|
3244
|
+
with cubic equation: h^3 - 12*h^2 + 47*h - 60 = 0
|
|
3245
|
+
"""
|
|
3246
|
+
if nstrands is None:
|
|
3247
|
+
nstrands = self._nstrands - 1
|
|
3248
|
+
n = self._nstrands
|
|
3249
|
+
nstrands = ZZ(nstrands)
|
|
3250
|
+
|
|
3251
|
+
if nstrands >= n or nstrands <= 0:
|
|
3252
|
+
raise ValueError('nstrands must be positive and less than %s' % self._nstrands)
|
|
3253
|
+
|
|
3254
|
+
names = self.variable_names()
|
|
3255
|
+
if nstrands == self._nstrands - 1 and self._cubic_hecke_subalgebra is not None:
|
|
3256
|
+
return self._cubic_hecke_subalgebra
|
|
3257
|
+
|
|
3258
|
+
names_red = names[:nstrands - 1]
|
|
3259
|
+
if self.base_ring() == self.base_ring(generic=True):
|
|
3260
|
+
SubHeckeAlg = CubicHeckeAlgebra(names=names_red)
|
|
3261
|
+
else:
|
|
3262
|
+
SubHeckeAlg = CubicHeckeAlgebra(names=names_red,
|
|
3263
|
+
cubic_equation_parameters=tuple(self._cubic_equation_parameters),
|
|
3264
|
+
cubic_equation_roots=tuple(self._cubic_equation_roots))
|
|
3265
|
+
|
|
3266
|
+
if nstrands == self._nstrands - 1:
|
|
3267
|
+
self._cubic_hecke_subalgebra = SubHeckeAlg
|
|
3268
|
+
return SubHeckeAlg
|
|
3269
|
+
|
|
3270
|
+
# --------------------------------------------------------------------------
|
|
3271
|
+
# mirror image
|
|
3272
|
+
# --------------------------------------------------------------------------
|
|
3273
|
+
def mirror_image(self):
|
|
3274
|
+
r"""
|
|
3275
|
+
Return a copy of ``self`` with the mirrored cubic equation, that is:
|
|
3276
|
+
the cubic equation has the inverse roots to the roots with respect
|
|
3277
|
+
to ``self``.
|
|
3278
|
+
|
|
3279
|
+
This is needed since the mirror involution of the braid group does
|
|
3280
|
+
not factor through ``self`` (considered as an algebra over the base
|
|
3281
|
+
ring, just considered as `\ZZ`-algebra). Therefore, the mirror
|
|
3282
|
+
involution of an element of ``self`` belongs to ``mirror_image``.
|
|
3283
|
+
|
|
3284
|
+
OUTPUT:
|
|
3285
|
+
|
|
3286
|
+
A cubic Hecke algebra over the same base and extension ring,
|
|
3287
|
+
but whose cubic equation is transformed by the mirror involution
|
|
3288
|
+
applied to its coefficients and roots.
|
|
3289
|
+
|
|
3290
|
+
EXAMPLES::
|
|
3291
|
+
|
|
3292
|
+
sage: CHA2 = algebras.CubicHecke(2)
|
|
3293
|
+
sage: ce = CHA2.cubic_equation(); ce
|
|
3294
|
+
h^3 - u*h^2 + v*h - w
|
|
3295
|
+
sage: CHA2m = CHA2.mirror_image()
|
|
3296
|
+
sage: cem = CHA2m.cubic_equation(); cem
|
|
3297
|
+
h^3 + ((-v)/w)*h^2 + u/w*h + (-1)/w
|
|
3298
|
+
sage: mi = CHA2.base_ring().mirror_involution(); mi
|
|
3299
|
+
Ring endomorphism of Multivariate Polynomial Ring in u, v, w
|
|
3300
|
+
over Integer Ring localized at (w,)
|
|
3301
|
+
Defn: u |--> v/w
|
|
3302
|
+
v |--> u/w
|
|
3303
|
+
w |--> 1/w
|
|
3304
|
+
sage: cem == cem.parent()([mi(cf) for cf in ce.coefficients()])
|
|
3305
|
+
True
|
|
3306
|
+
|
|
3307
|
+
Note that both cubic Hecke algebras have the same ring of definition
|
|
3308
|
+
and identical generic cubic equation::
|
|
3309
|
+
|
|
3310
|
+
sage: cemg = CHA2m.cubic_equation(generic=True)
|
|
3311
|
+
sage: CHA2.cubic_equation(generic=True) == cemg
|
|
3312
|
+
True
|
|
3313
|
+
sage: CHA2.cubic_equation() == cemg
|
|
3314
|
+
True
|
|
3315
|
+
sage: a, b, c = CHA2.cubic_equation_roots()
|
|
3316
|
+
sage: CHA2m.cubic_equation_roots(generic=True) == [a, b, c]
|
|
3317
|
+
True
|
|
3318
|
+
sage: CHA2m.cubic_equation_roots()
|
|
3319
|
+
[((-1)/(-w))*a^2 + (u/(-w))*a + (-v)/(-w),
|
|
3320
|
+
((1/(-w))*a)*b + (1/(-w))*a^2 + ((-u)/(-w))*a,
|
|
3321
|
+
(((-1)/(-w))*a)*b]
|
|
3322
|
+
sage: ai, bi, ci = _
|
|
3323
|
+
sage: ai == ~a, bi == ~b, ci == ~c
|
|
3324
|
+
(True, True, True)
|
|
3325
|
+
sage: CHA2.extension_ring(generic=True).mirror_involution()
|
|
3326
|
+
Ring endomorphism of Multivariate Laurent Polynomial Ring in a, b, c
|
|
3327
|
+
over Splitting Algebra of x^2 + x + 1
|
|
3328
|
+
with roots [e3, -e3 - 1] over Integer Ring
|
|
3329
|
+
Defn: a |--> a^-1
|
|
3330
|
+
b |--> b^-1
|
|
3331
|
+
c |--> c^-1
|
|
3332
|
+
with map of base ring
|
|
3333
|
+
|
|
3334
|
+
The mirror image can not be obtained for specialized cubic Hecke
|
|
3335
|
+
algebras if the specialization does not factor through the mirror
|
|
3336
|
+
involution on the ring if definition::
|
|
3337
|
+
|
|
3338
|
+
sage: CHA2s = algebras.CubicHecke(2, cubic_equation_roots=(3, 4, 5))
|
|
3339
|
+
sage: CHA2s
|
|
3340
|
+
Cubic Hecke algebra on 2 strands
|
|
3341
|
+
over Integer Ring localized at (2, 3, 5)
|
|
3342
|
+
with cubic equation: h^3 - 12*h^2 + 47*h - 60 = 0
|
|
3343
|
+
|
|
3344
|
+
In the next example it is not clear what the mirror image of ``7``
|
|
3345
|
+
should be::
|
|
3346
|
+
|
|
3347
|
+
sage: CHA2s.mirror_image()
|
|
3348
|
+
Traceback (most recent call last):
|
|
3349
|
+
...
|
|
3350
|
+
RuntimeError: base ring Integer Ring localized at (2, 3, 5)
|
|
3351
|
+
does not factor through mirror involution
|
|
3352
|
+
"""
|
|
3353
|
+
base_ring = self.base_ring()
|
|
3354
|
+
base_gen = self.base_ring(generic=True)
|
|
3355
|
+
|
|
3356
|
+
base_gen_mirror = base_gen.mirror_involution()
|
|
3357
|
+
base_ring_mirror = self._base_ring_mirror
|
|
3358
|
+
cepg = self.cubic_equation_parameters(generic=True)
|
|
3359
|
+
cerg = self.cubic_equation_roots(generic=True)
|
|
3360
|
+
if not base_ring_mirror:
|
|
3361
|
+
mirr_paras_gen = [base_gen_mirror(par) for par in cepg]
|
|
3362
|
+
mirr_paras = [base_ring(mirr_para) for mirr_para in mirr_paras_gen]
|
|
3363
|
+
try:
|
|
3364
|
+
base_ring_mirror = base_ring.hom(mirr_paras)
|
|
3365
|
+
except (TypeError, ValueError, NotImplementedError):
|
|
3366
|
+
raise RuntimeError('base ring %s does not factor through mirror involution' % base_ring)
|
|
3367
|
+
|
|
3368
|
+
# check for involution
|
|
3369
|
+
mirr_paras_back = [base_ring_mirror(mirr_para) for mirr_para in mirr_paras]
|
|
3370
|
+
if mirr_paras_back != self.cubic_equation_parameters():
|
|
3371
|
+
raise RuntimeError('base ring %s does not factor through mirror involution' % base_ring)
|
|
3372
|
+
self._base_ring_mirror = base_ring_mirror
|
|
3373
|
+
|
|
3374
|
+
mirror_image = self._mirror_image
|
|
3375
|
+
if mirror_image is None:
|
|
3376
|
+
extension_ring = self.extension_ring()
|
|
3377
|
+
extension_gen = self.extension_ring(generic=True)
|
|
3378
|
+
extension_gen_mirror = extension_gen.mirror_involution()
|
|
3379
|
+
|
|
3380
|
+
mirr_paras_gen = [base_gen_mirror(par) for par in cepg]
|
|
3381
|
+
mirr_roots_gen = [extension_gen_mirror(root) for root in cerg]
|
|
3382
|
+
|
|
3383
|
+
mirr_paras = tuple([base_ring(par) for par in mirr_paras_gen])
|
|
3384
|
+
mirr_roots = tuple([extension_ring(root) for root in mirr_roots_gen])
|
|
3385
|
+
n = self._nstrands
|
|
3386
|
+
|
|
3387
|
+
mirror_image = CubicHeckeAlgebra(n, cubic_equation_parameters=mirr_paras, cubic_equation_roots=mirr_roots)
|
|
3388
|
+
|
|
3389
|
+
# go back by involution property
|
|
3390
|
+
mirror_image._mirror_image = self
|
|
3391
|
+
mirror_image._base_ring_mirror = base_ring_mirror
|
|
3392
|
+
mirror_image._ring_of_definition._mirror_ = base_gen_mirror
|
|
3393
|
+
mirror_image._is_mirror = True
|
|
3394
|
+
|
|
3395
|
+
self._mirror_image = mirror_image
|
|
3396
|
+
|
|
3397
|
+
return mirror_image
|
|
3398
|
+
|
|
3399
|
+
# --------------------------------------------------------------------------
|
|
3400
|
+
# Schur elements
|
|
3401
|
+
# --------------------------------------------------------------------------
|
|
3402
|
+
def schur_elements(self, generic=False):
|
|
3403
|
+
r"""
|
|
3404
|
+
Return the list of Schur elements of ``self`` as elements
|
|
3405
|
+
of the extension ring of ``self``.
|
|
3406
|
+
|
|
3407
|
+
.. NOTE::
|
|
3408
|
+
|
|
3409
|
+
This method needs ``GAP3`` installed with package ``CHEVIE``.
|
|
3410
|
+
|
|
3411
|
+
INPUT:
|
|
3412
|
+
|
|
3413
|
+
- ``generic`` -- boolean (default: ``False``); if ``True``,
|
|
3414
|
+
the element is returned as element of the generic
|
|
3415
|
+
extension ring
|
|
3416
|
+
|
|
3417
|
+
EXAMPLES::
|
|
3418
|
+
|
|
3419
|
+
sage: CHA3 = algebras.CubicHecke(3) # optional gap3
|
|
3420
|
+
sage: sch_eles = CHA3.schur_elements() # optional gap3
|
|
3421
|
+
sage: sch_eles[6] # optional gap3
|
|
3422
|
+
(u^3*w + v^3 - 6*u*v*w + 8*w^2)/w^2
|
|
3423
|
+
"""
|
|
3424
|
+
gap3_result = self.chevie().SchurElements()
|
|
3425
|
+
GER = self.extension_ring(generic=True)
|
|
3426
|
+
generic_result = [GER(s) for s in gap3_result]
|
|
3427
|
+
if generic:
|
|
3428
|
+
return list(generic_result)
|
|
3429
|
+
else:
|
|
3430
|
+
ER = self.extension_ring()
|
|
3431
|
+
return [ER(s) for s in generic_result]
|
|
3432
|
+
|
|
3433
|
+
# --------------------------------------------------------------------------
|
|
3434
|
+
# Schur element
|
|
3435
|
+
# --------------------------------------------------------------------------
|
|
3436
|
+
def schur_element(self, item, generic=False):
|
|
3437
|
+
r"""
|
|
3438
|
+
Return a single Schur element of ``self`` as elements
|
|
3439
|
+
of the extension ring of ``self``.
|
|
3440
|
+
|
|
3441
|
+
.. NOTE::
|
|
3442
|
+
|
|
3443
|
+
This method needs ``GAP3`` installed with package ``CHEVIE``.
|
|
3444
|
+
|
|
3445
|
+
INPUT:
|
|
3446
|
+
|
|
3447
|
+
- ``item`` -- an element of :class:`AbsIrreducibeRep` to give
|
|
3448
|
+
the irreducible representation of ``self`` to which the Schur
|
|
3449
|
+
element should be returned
|
|
3450
|
+
- ``generic`` -- boolean (default: ``False``); if ``True``,
|
|
3451
|
+
the element is returned as element of the generic
|
|
3452
|
+
extension ring
|
|
3453
|
+
|
|
3454
|
+
EXAMPLES::
|
|
3455
|
+
|
|
3456
|
+
sage: CHA3 = algebras.CubicHecke(3) # optional gap3
|
|
3457
|
+
sage: CHA3.schur_element(CHA3.irred_repr.W3_111) # optional gap3
|
|
3458
|
+
(u^3*w + v^3 - 6*u*v*w + 8*w^2)/w^2
|
|
3459
|
+
"""
|
|
3460
|
+
if not isinstance(item, AbsIrreducibeRep):
|
|
3461
|
+
raise ValueError('item must be an instance of %s' % AbsIrreducibeRep)
|
|
3462
|
+
return self.schur_elements(generic=generic)[item.gap_index()]
|
|
3463
|
+
|
|
3464
|
+
# --------------------------------------------------------------------------
|
|
3465
|
+
# characters
|
|
3466
|
+
# --------------------------------------------------------------------------
|
|
3467
|
+
def characters(self, irr=None, original=True):
|
|
3468
|
+
r"""
|
|
3469
|
+
Return the irreducible characters of ``self``.
|
|
3470
|
+
|
|
3471
|
+
By default the values are given in the generic extension ring.
|
|
3472
|
+
Setting the keyword ``original`` to ``False`` you can obtain
|
|
3473
|
+
the values in the (non generic) extension ring (compare the
|
|
3474
|
+
same keyword for :meth:`CubicHeckeElement.matrix`).
|
|
3475
|
+
|
|
3476
|
+
INPUT:
|
|
3477
|
+
|
|
3478
|
+
- ``irr`` -- (optional) instance of :class:`AbsIrreducibeRep`
|
|
3479
|
+
selecting the irreducible representation corresponding to the
|
|
3480
|
+
character; if not given a list of all characters is returned
|
|
3481
|
+
- ``original`` -- boolean (default: ``True``); see description above
|
|
3482
|
+
|
|
3483
|
+
OUTPUT:
|
|
3484
|
+
|
|
3485
|
+
Function or list of Functions from the element class of ``self`` to
|
|
3486
|
+
the (generic or non generic) extension ring depending on the given
|
|
3487
|
+
keyword arguments.
|
|
3488
|
+
|
|
3489
|
+
EXAMPLES::
|
|
3490
|
+
|
|
3491
|
+
sage: CHA3 = algebras.CubicHecke(3)
|
|
3492
|
+
sage: ch = CHA3.characters()
|
|
3493
|
+
sage: e = CHA3.an_element()
|
|
3494
|
+
sage: ch[0](e)
|
|
3495
|
+
a^2*b + a^2*c + a^2 - b*c + b^-1*c^-1 + a^-1*c^-1 + a^-1*b^-1
|
|
3496
|
+
sage: _.parent()
|
|
3497
|
+
Multivariate Laurent Polynomial Ring in a, b, c
|
|
3498
|
+
over Splitting Algebra of x^2 + x + 1 with roots [e3, -e3 - 1]
|
|
3499
|
+
over Integer Ring
|
|
3500
|
+
sage: ch_w3_100 = CHA3.characters(irr=CHA3.irred_repr.W3_100)
|
|
3501
|
+
sage: ch_w3_100(e) == ch[0](e)
|
|
3502
|
+
True
|
|
3503
|
+
sage: ch_x = CHA3.characters(original=False)
|
|
3504
|
+
sage: ch_x[0](e)
|
|
3505
|
+
(u + v)*a + (-v*w - w^2 + u)/w
|
|
3506
|
+
sage: _.parent()
|
|
3507
|
+
Splitting Algebra of T^2 + T + 1 with roots [E3, -E3 - 1]
|
|
3508
|
+
over Splitting Algebra of h^3 - u*h^2 + v*h - w
|
|
3509
|
+
with roots [a, b, -b - a + u]
|
|
3510
|
+
over Multivariate Polynomial Ring in u, v, w
|
|
3511
|
+
over Integer Ring localized at (w,)
|
|
3512
|
+
"""
|
|
3513
|
+
def char_function(ele):
|
|
3514
|
+
if isinstance(ele, self.element_class):
|
|
3515
|
+
m = ele.matrix(original=original)
|
|
3516
|
+
return m[irr].trace()
|
|
3517
|
+
if irr:
|
|
3518
|
+
return char_function
|
|
3519
|
+
irrs = [irr for irr in self.irred_repr if irr.number_gens() == self._nstrands - 1]
|
|
3520
|
+
return [self.characters(irrs[i], original=original) for i in range(len(irrs))]
|