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,2039 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
r"""
|
|
3
|
+
Colored permutations
|
|
4
|
+
|
|
5
|
+
.. TODO::
|
|
6
|
+
|
|
7
|
+
Much of the colored permutations (and element) class can be
|
|
8
|
+
generalized to `G \wr S_n`
|
|
9
|
+
"""
|
|
10
|
+
import itertools
|
|
11
|
+
from random import choice
|
|
12
|
+
|
|
13
|
+
from sage.structure.element import MultiplicativeGroupElement
|
|
14
|
+
from sage.structure.parent import Parent
|
|
15
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
16
|
+
from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass
|
|
17
|
+
from sage.misc.cachefunc import cached_method
|
|
18
|
+
from sage.misc.lazy_import import lazy_import
|
|
19
|
+
from sage.misc.misc_c import prod
|
|
20
|
+
from sage.arith.functions import lcm
|
|
21
|
+
|
|
22
|
+
from sage.combinat.partition_tuple import PartitionTuples, PartitionTuple
|
|
23
|
+
from sage.combinat.permutation import Permutations
|
|
24
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
|
25
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
26
|
+
from sage.rings.integer_ring import ZZ
|
|
27
|
+
|
|
28
|
+
lazy_import('sage.matrix.constructor', 'diagonal_matrix')
|
|
29
|
+
lazy_import('sage.rings.number_field.number_field', 'CyclotomicField')
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ColoredPermutation(MultiplicativeGroupElement):
|
|
33
|
+
"""
|
|
34
|
+
A colored permutation.
|
|
35
|
+
"""
|
|
36
|
+
def __init__(self, parent, colors, perm):
|
|
37
|
+
"""
|
|
38
|
+
Initialize ``self``.
|
|
39
|
+
|
|
40
|
+
TESTS::
|
|
41
|
+
|
|
42
|
+
sage: C = ColoredPermutations(4, 3)
|
|
43
|
+
sage: s1,s2,t = C.gens()
|
|
44
|
+
sage: TestSuite(s1*s2*t).run()
|
|
45
|
+
"""
|
|
46
|
+
self._colors = tuple(colors)
|
|
47
|
+
self._perm = perm
|
|
48
|
+
MultiplicativeGroupElement.__init__(self, parent=parent)
|
|
49
|
+
|
|
50
|
+
def __hash__(self):
|
|
51
|
+
r"""
|
|
52
|
+
TESTS::
|
|
53
|
+
|
|
54
|
+
sage: C = ColoredPermutations(4, 3)
|
|
55
|
+
sage: s1,s2,t = C.gens()
|
|
56
|
+
sage: for gen in s1,s2,t:
|
|
57
|
+
....: assert hash(gen) ^^ hash(gen._colors) == hash(gen._perm)
|
|
58
|
+
"""
|
|
59
|
+
return hash(self._perm) ^ hash(self._colors)
|
|
60
|
+
|
|
61
|
+
def _repr_(self):
|
|
62
|
+
"""
|
|
63
|
+
Return a string representation of ``self``.
|
|
64
|
+
|
|
65
|
+
EXAMPLES::
|
|
66
|
+
|
|
67
|
+
sage: C = ColoredPermutations(4, 3)
|
|
68
|
+
sage: s1,s2,t = C.gens()
|
|
69
|
+
sage: s1*s2*t
|
|
70
|
+
[[1, 0, 0], [3, 1, 2]]
|
|
71
|
+
"""
|
|
72
|
+
return repr([list(self._colors), self._perm])
|
|
73
|
+
|
|
74
|
+
def _latex_(self):
|
|
75
|
+
r"""
|
|
76
|
+
Return a latex representation of ``self``.
|
|
77
|
+
|
|
78
|
+
EXAMPLES::
|
|
79
|
+
|
|
80
|
+
sage: C = ColoredPermutations(4, 3)
|
|
81
|
+
sage: s1,s2,t = C.gens()
|
|
82
|
+
sage: latex(s1*s2*t)
|
|
83
|
+
[3_{1}, 1_{0}, 2_{0}]
|
|
84
|
+
"""
|
|
85
|
+
ret = "["
|
|
86
|
+
ret += ", ".join("{}_{{{}}}".format(x, c)
|
|
87
|
+
for c, x in zip(self._colors, self._perm))
|
|
88
|
+
return ret + "]"
|
|
89
|
+
|
|
90
|
+
def __len__(self):
|
|
91
|
+
"""
|
|
92
|
+
Return the length of the one line form of ``self``.
|
|
93
|
+
|
|
94
|
+
EXAMPLES::
|
|
95
|
+
|
|
96
|
+
sage: C = ColoredPermutations(2, 3)
|
|
97
|
+
sage: s1,s2,t = C.gens()
|
|
98
|
+
sage: len(s1)
|
|
99
|
+
3
|
|
100
|
+
"""
|
|
101
|
+
return len(self._perm)
|
|
102
|
+
|
|
103
|
+
def _mul_(self, other):
|
|
104
|
+
"""
|
|
105
|
+
Multiply ``self`` and ``other``.
|
|
106
|
+
|
|
107
|
+
EXAMPLES::
|
|
108
|
+
|
|
109
|
+
sage: C = ColoredPermutations(4, 3)
|
|
110
|
+
sage: s1,s2,t = C.gens()
|
|
111
|
+
sage: s1*s2*s1 == s2*s1*s2
|
|
112
|
+
True
|
|
113
|
+
"""
|
|
114
|
+
colors = tuple(c + other._colors[val - 1] # -1 for indexing
|
|
115
|
+
for c, val in zip(self._colors, self._perm))
|
|
116
|
+
p = self._perm._left_to_right_multiply_on_right(other._perm)
|
|
117
|
+
return self.__class__(self.parent(), colors, p)
|
|
118
|
+
|
|
119
|
+
def __invert__(self):
|
|
120
|
+
"""
|
|
121
|
+
Return the inverse of ``self``.
|
|
122
|
+
|
|
123
|
+
EXAMPLES::
|
|
124
|
+
|
|
125
|
+
sage: C = ColoredPermutations(4, 3)
|
|
126
|
+
sage: s1,s2,t = C.gens()
|
|
127
|
+
sage: ~t # indirect doctest
|
|
128
|
+
[[0, 0, 3], [1, 2, 3]]
|
|
129
|
+
sage: all(x * ~x == C.one() for x in C.gens())
|
|
130
|
+
True
|
|
131
|
+
"""
|
|
132
|
+
ip = ~self._perm
|
|
133
|
+
return self.__class__(self.parent(),
|
|
134
|
+
tuple(-self._colors[i - 1] for i in ip), # -1 for indexing
|
|
135
|
+
ip)
|
|
136
|
+
|
|
137
|
+
def __eq__(self, other):
|
|
138
|
+
"""
|
|
139
|
+
Check equality.
|
|
140
|
+
|
|
141
|
+
EXAMPLES::
|
|
142
|
+
|
|
143
|
+
sage: C = ColoredPermutations(4, 3)
|
|
144
|
+
sage: s1,s2,t = C.gens()
|
|
145
|
+
sage: s1*s2*s1 == s2*s1*s2
|
|
146
|
+
True
|
|
147
|
+
sage: t^4 == C.one()
|
|
148
|
+
True
|
|
149
|
+
sage: s1*s2 == s2*s1
|
|
150
|
+
False
|
|
151
|
+
"""
|
|
152
|
+
if not isinstance(other, ColoredPermutation):
|
|
153
|
+
return False
|
|
154
|
+
return (self.parent() is other.parent()
|
|
155
|
+
and self._colors == other._colors
|
|
156
|
+
and self._perm == other._perm)
|
|
157
|
+
|
|
158
|
+
def __ne__(self, other):
|
|
159
|
+
"""
|
|
160
|
+
Check inequality.
|
|
161
|
+
|
|
162
|
+
EXAMPLES::
|
|
163
|
+
|
|
164
|
+
sage: C = ColoredPermutations(4, 3)
|
|
165
|
+
sage: s1,s2,t = C.gens()
|
|
166
|
+
sage: s1*s2*s1 != s2*s1*s2
|
|
167
|
+
False
|
|
168
|
+
sage: s1*s2 != s2*s1
|
|
169
|
+
True
|
|
170
|
+
"""
|
|
171
|
+
return not self == other
|
|
172
|
+
|
|
173
|
+
def __iter__(self):
|
|
174
|
+
"""
|
|
175
|
+
Iterate over ``self``.
|
|
176
|
+
|
|
177
|
+
EXAMPLES::
|
|
178
|
+
|
|
179
|
+
sage: C = ColoredPermutations(4, 3)
|
|
180
|
+
sage: s1,s2,t = C.gens()
|
|
181
|
+
sage: x = s1*s2*t
|
|
182
|
+
sage: list(x)
|
|
183
|
+
[(1, 3), (0, 1), (0, 2)]
|
|
184
|
+
"""
|
|
185
|
+
yield from zip(self._colors, self._perm)
|
|
186
|
+
|
|
187
|
+
def one_line_form(self):
|
|
188
|
+
"""
|
|
189
|
+
Return the one line form of ``self``.
|
|
190
|
+
|
|
191
|
+
EXAMPLES::
|
|
192
|
+
|
|
193
|
+
sage: C = ColoredPermutations(4, 3)
|
|
194
|
+
sage: s1,s2,t = C.gens()
|
|
195
|
+
sage: x = s1*s2*t
|
|
196
|
+
sage: x
|
|
197
|
+
[[1, 0, 0], [3, 1, 2]]
|
|
198
|
+
sage: x.one_line_form()
|
|
199
|
+
[(1, 3), (0, 1), (0, 2)]
|
|
200
|
+
"""
|
|
201
|
+
return list(self)
|
|
202
|
+
|
|
203
|
+
def __getitem__(self, key):
|
|
204
|
+
"""
|
|
205
|
+
Return the specified element in the one line form of ``self``.
|
|
206
|
+
|
|
207
|
+
EXAMPLES::
|
|
208
|
+
|
|
209
|
+
sage: C = ColoredPermutations(4, 3)
|
|
210
|
+
sage: s1,s2,t = C.gens()
|
|
211
|
+
sage: x = s1*s2*t
|
|
212
|
+
sage: x
|
|
213
|
+
[[1, 0, 0], [3, 1, 2]]
|
|
214
|
+
sage: x[1]
|
|
215
|
+
(0, 1)
|
|
216
|
+
sage: x[1:]
|
|
217
|
+
[(0, 1), (0, 2)]
|
|
218
|
+
"""
|
|
219
|
+
if isinstance(key, slice):
|
|
220
|
+
return list(zip(self._colors[key], self._perm[key]))
|
|
221
|
+
return (self._colors[key], self._perm[key])
|
|
222
|
+
|
|
223
|
+
def colors(self):
|
|
224
|
+
"""
|
|
225
|
+
Return the colors of ``self``.
|
|
226
|
+
|
|
227
|
+
EXAMPLES::
|
|
228
|
+
|
|
229
|
+
sage: C = ColoredPermutations(4, 3)
|
|
230
|
+
sage: s1,s2,t = C.gens()
|
|
231
|
+
sage: x = s1*s2*t
|
|
232
|
+
sage: x.colors()
|
|
233
|
+
[1, 0, 0]
|
|
234
|
+
"""
|
|
235
|
+
return list(self._colors)
|
|
236
|
+
|
|
237
|
+
def permutation(self):
|
|
238
|
+
"""
|
|
239
|
+
Return the permutation of ``self``.
|
|
240
|
+
|
|
241
|
+
This is obtained by forgetting the colors.
|
|
242
|
+
|
|
243
|
+
EXAMPLES::
|
|
244
|
+
|
|
245
|
+
sage: C = ColoredPermutations(4, 3)
|
|
246
|
+
sage: s1,s2,t = C.gens()
|
|
247
|
+
sage: x = s1*s2*t
|
|
248
|
+
sage: x.permutation()
|
|
249
|
+
[3, 1, 2]
|
|
250
|
+
"""
|
|
251
|
+
return self._perm
|
|
252
|
+
|
|
253
|
+
def to_matrix(self):
|
|
254
|
+
"""
|
|
255
|
+
Return a matrix of ``self``.
|
|
256
|
+
|
|
257
|
+
The colors are mapped to roots of unity.
|
|
258
|
+
|
|
259
|
+
EXAMPLES::
|
|
260
|
+
|
|
261
|
+
sage: C = ColoredPermutations(4, 3)
|
|
262
|
+
sage: s1,s2,t = C.gens()
|
|
263
|
+
sage: x = s1*s2*t*s2; x.one_line_form()
|
|
264
|
+
[(1, 2), (0, 1), (0, 3)]
|
|
265
|
+
sage: M = x.to_matrix(); M # needs sage.rings.number_field
|
|
266
|
+
[ 0 1 0]
|
|
267
|
+
[zeta4 0 0]
|
|
268
|
+
[ 0 0 1]
|
|
269
|
+
|
|
270
|
+
The matrix multiplication is in the *opposite* order::
|
|
271
|
+
|
|
272
|
+
sage: M == s2.to_matrix()*t.to_matrix()*s2.to_matrix()*s1.to_matrix() # needs sage.rings.number_field
|
|
273
|
+
True
|
|
274
|
+
"""
|
|
275
|
+
Cp = CyclotomicField(self.parent()._m)
|
|
276
|
+
g = Cp.gen()
|
|
277
|
+
D = diagonal_matrix(Cp, [g ** i for i in self._colors])
|
|
278
|
+
return self._perm.to_matrix() * D
|
|
279
|
+
|
|
280
|
+
def has_left_descent(self, i) -> bool:
|
|
281
|
+
r"""
|
|
282
|
+
Return ``True`` if ``i`` is a left descent of ``self``.
|
|
283
|
+
|
|
284
|
+
Let `p = ((s_1, \ldots s_n), \sigma)` be a colored permutation.
|
|
285
|
+
We say `p` has a left `n`-descent if `s_n > 0`. If `i < n`, then
|
|
286
|
+
we say `p` has a left `i`-descent if either
|
|
287
|
+
|
|
288
|
+
- `s_i \neq 0, s_{i+1} = 0` and `\sigma_i < \sigma_{i+1}` or
|
|
289
|
+
- `s_i = s_{i+1}` and `\sigma_i > \sigma_{i+1}`.
|
|
290
|
+
|
|
291
|
+
This notion of a left `i`-descent is done in order to recursively
|
|
292
|
+
construct `w(p) = \sigma_i w(\sigma_i^{-1} p)`, where `w(p)`
|
|
293
|
+
denotes a reduced word of `p`.
|
|
294
|
+
|
|
295
|
+
EXAMPLES::
|
|
296
|
+
|
|
297
|
+
sage: C = ColoredPermutations(2, 4)
|
|
298
|
+
sage: s1,s2,s3,s4 = C.gens()
|
|
299
|
+
sage: x = s4*s1*s2*s3*s4
|
|
300
|
+
sage: [x.has_left_descent(i) for i in C.index_set()]
|
|
301
|
+
[True, False, False, True]
|
|
302
|
+
|
|
303
|
+
sage: C = ColoredPermutations(1, 5)
|
|
304
|
+
sage: s1,s2,s3,s4 = C.gens()
|
|
305
|
+
sage: x = s4*s1*s2*s3*s4
|
|
306
|
+
sage: [x.has_left_descent(i) for i in C.index_set()]
|
|
307
|
+
[True, False, False, True]
|
|
308
|
+
|
|
309
|
+
sage: C = ColoredPermutations(3, 3)
|
|
310
|
+
sage: x = C([[2,1,0],[3,1,2]])
|
|
311
|
+
sage: [x.has_left_descent(i) for i in C.index_set()]
|
|
312
|
+
[False, True, False]
|
|
313
|
+
|
|
314
|
+
sage: C = ColoredPermutations(4, 4)
|
|
315
|
+
sage: x = C([[2,1,0,1],[3,2,4,1]])
|
|
316
|
+
sage: [x.has_left_descent(i) for i in C.index_set()]
|
|
317
|
+
[False, True, False, True]
|
|
318
|
+
"""
|
|
319
|
+
if self.parent()._m == 1:
|
|
320
|
+
return self._perm[i - 1] > self._perm[i]
|
|
321
|
+
|
|
322
|
+
if self.parent()._p > 1:
|
|
323
|
+
raise NotImplementedError("only implemented for p = 1")
|
|
324
|
+
|
|
325
|
+
if i == self.parent()._n:
|
|
326
|
+
return self._colors[-1] != 0
|
|
327
|
+
if self._colors[i - 1] != 0:
|
|
328
|
+
return self._colors[i] == 0 or self._perm[i - 1] < self._perm[i]
|
|
329
|
+
return self._colors[i] == 0 and self._perm[i - 1] > self._perm[i]
|
|
330
|
+
|
|
331
|
+
def reduced_word(self):
|
|
332
|
+
r"""
|
|
333
|
+
Return a word in the simple reflections to obtain ``self``.
|
|
334
|
+
|
|
335
|
+
EXAMPLES::
|
|
336
|
+
|
|
337
|
+
sage: C = ColoredPermutations(3, 3)
|
|
338
|
+
sage: x = C([[2,1,0],[3,1,2]])
|
|
339
|
+
sage: x.reduced_word()
|
|
340
|
+
[2, 1, 3, 2, 1, 3, 3]
|
|
341
|
+
|
|
342
|
+
sage: C = ColoredPermutations(4, 4)
|
|
343
|
+
sage: x = C([[2,1,0,1],[3,2,4,1]])
|
|
344
|
+
sage: x.reduced_word()
|
|
345
|
+
[2, 1, 4, 3, 2, 1, 4, 3, 2, 4, 4, 3]
|
|
346
|
+
|
|
347
|
+
TESTS::
|
|
348
|
+
|
|
349
|
+
sage: C = ColoredPermutations(3, 3)
|
|
350
|
+
sage: all(C.from_reduced_word(p.reduced_word()) == p for p in C)
|
|
351
|
+
True
|
|
352
|
+
"""
|
|
353
|
+
if self == self.parent().one():
|
|
354
|
+
return []
|
|
355
|
+
I = self.parent().index_set()
|
|
356
|
+
sinv = self.parent()._inverse_simple_reflections()
|
|
357
|
+
for i in I:
|
|
358
|
+
if self.has_left_descent(i):
|
|
359
|
+
return [i] + (sinv[i] * self).reduced_word()
|
|
360
|
+
assert False, "BUG in reduced_word"
|
|
361
|
+
|
|
362
|
+
def length(self):
|
|
363
|
+
r"""
|
|
364
|
+
Return the length of ``self`` in generating reflections.
|
|
365
|
+
|
|
366
|
+
This is the minimal numbers of generating reflections needed
|
|
367
|
+
to obtain ``self``.
|
|
368
|
+
|
|
369
|
+
EXAMPLES::
|
|
370
|
+
|
|
371
|
+
sage: C = ColoredPermutations(3, 3)
|
|
372
|
+
sage: x = C([[2,1,0],[3,1,2]])
|
|
373
|
+
sage: x.length()
|
|
374
|
+
7
|
|
375
|
+
|
|
376
|
+
sage: C = ColoredPermutations(4, 4)
|
|
377
|
+
sage: x = C([[2,1,0,1],[3,2,4,1]])
|
|
378
|
+
sage: x.length()
|
|
379
|
+
12
|
|
380
|
+
|
|
381
|
+
TESTS::
|
|
382
|
+
|
|
383
|
+
sage: C = ColoredPermutations(3, 3)
|
|
384
|
+
sage: d = [p.length() for p in C]
|
|
385
|
+
sage: [d.count(i) for i in range(14)]
|
|
386
|
+
[1, 3, 6, 10, 15, 20, 23, 24, 23, 19, 12, 5, 1, 0]
|
|
387
|
+
sage: d = [p.length() for p in ReflectionGroup([3, 1, 3])] # optional - gap3
|
|
388
|
+
sage: [d.count(i) for i in range(14)] # optional - gap3
|
|
389
|
+
[1, 3, 6, 10, 15, 20, 23, 24, 23, 19, 12, 5, 1, 0]
|
|
390
|
+
|
|
391
|
+
sage: C = ColoredPermutations(4, 3)
|
|
392
|
+
sage: d = [p.length() for p in C]
|
|
393
|
+
sage: [d.count(i) for i in range(17)]
|
|
394
|
+
[1, 3, 6, 11, 18, 27, 36, 44, 50, 52, 49, 40, 27, 14, 5, 1, 0]
|
|
395
|
+
sage: d = [p.length() for p in ReflectionGroup([4, 1, 3])] # optional - gap3
|
|
396
|
+
sage: [d.count(i) for i in range(17)] # optional - gap3
|
|
397
|
+
[1, 3, 6, 11, 18, 27, 36, 44, 50, 52, 49, 40, 27, 14, 5, 1, 0]
|
|
398
|
+
|
|
399
|
+
sage: C = ColoredPermutations(3, 4)
|
|
400
|
+
sage: d = [p.length() for p in C]
|
|
401
|
+
sage: [d.count(i) for i in range(22)]
|
|
402
|
+
[1, 4, 10, 20, 35, 56, 82, 112, 144, 174, 197,
|
|
403
|
+
209, 209, 197, 173, 138, 96, 55, 24, 7, 1, 0]
|
|
404
|
+
sage: d = [p.length() for p in ReflectionGroup([3, 1, 4])] # optional - gap3
|
|
405
|
+
sage: [d.count(i) for i in range(22)] # optional - gap3
|
|
406
|
+
[1, 4, 10, 20, 35, 56, 82, 112, 144, 174, 197,
|
|
407
|
+
209, 209, 197, 173, 138, 96, 55, 24, 7, 1, 0]
|
|
408
|
+
"""
|
|
409
|
+
return ZZ(len(self.reduced_word()))
|
|
410
|
+
|
|
411
|
+
# TODO: Parts of this should be put in the category of complex
|
|
412
|
+
# reflection groups
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
class ShephardToddFamilyGroup(UniqueRepresentation, Parent):
|
|
416
|
+
r"""
|
|
417
|
+
The Shephard-Todd family complex reflection group `G(m, p, n)`
|
|
418
|
+
realized as a subgroup of :class:`colored permutations
|
|
419
|
+
<sage.combinat.colored_permutations.ColoredPermutations>`.
|
|
420
|
+
|
|
421
|
+
A general complex reflection group is a subgroup of `GL(V)`, where
|
|
422
|
+
`V` is a `\CC` vector space, that is generated by *reflections*,
|
|
423
|
+
diagonalizable matrices with at most one eigenvalue not equal to `1`.
|
|
424
|
+
The group of colored permutations `G(m, 1, n)` are the generalized
|
|
425
|
+
permutation matrices whose entries are `m`-th roots of unity.
|
|
426
|
+
For `p | m`, the group `G(m, p, n)` is the index `p` subgroup
|
|
427
|
+
such that the product of the entries is a `m/p`-th root of unity.
|
|
428
|
+
|
|
429
|
+
By the (Chevalley-)Shephard-Todd classification of irreducible
|
|
430
|
+
finite complex reflection groups, the groups `G(m, p, n)` (with
|
|
431
|
+
`G(2, 2, 2)` being exceptionally reducible since it is the Klein
|
|
432
|
+
four group) form the only infinite family with an additional 34
|
|
433
|
+
exceptional groups `G_k`, where `4 \leq k \leq 37`. To avoid
|
|
434
|
+
ambiguities, we refer to `G(m, p, n)` as the *Shephard-Todd family
|
|
435
|
+
complex reflection group*.
|
|
436
|
+
|
|
437
|
+
INPUT:
|
|
438
|
+
|
|
439
|
+
- ``m`` -- positive integer
|
|
440
|
+
- ``p`` -- positive integer dividing ``m``
|
|
441
|
+
- ``n`` -- positive integer
|
|
442
|
+
|
|
443
|
+
REFERENCES:
|
|
444
|
+
|
|
445
|
+
- :wikipedia:`Complex_reflection_group`
|
|
446
|
+
|
|
447
|
+
EXAMPLES::
|
|
448
|
+
|
|
449
|
+
sage: # needs sage.groups
|
|
450
|
+
sage: groups.misc.ShephardToddFamily(6, 1, 4)
|
|
451
|
+
6-colored permutations of size 4
|
|
452
|
+
sage: groups.misc.ShephardToddFamily(6, 2, 4)
|
|
453
|
+
Complex reflection group G(6, 2, 4)
|
|
454
|
+
sage: groups.misc.ShephardToddFamily(6, 3, 4)
|
|
455
|
+
Complex reflection group G(6, 3, 4)
|
|
456
|
+
sage: groups.misc.ShephardToddFamily(6, 6, 4)
|
|
457
|
+
Complex reflection group G(6, 6, 4)
|
|
458
|
+
"""
|
|
459
|
+
@staticmethod
|
|
460
|
+
def __classcall_private__(cls, m, p, n):
|
|
461
|
+
r"""
|
|
462
|
+
Dispatch to :class:`sage.combinat.colored_permutations.ColoredPermutations`
|
|
463
|
+
when ``p == 1``.
|
|
464
|
+
|
|
465
|
+
EXAMPLES::
|
|
466
|
+
|
|
467
|
+
sage: # needs sage.groups
|
|
468
|
+
sage: G = groups.misc.ShephardToddFamily(6, 1, 3)
|
|
469
|
+
sage: C = ColoredPermutations(6, 3)
|
|
470
|
+
sage: G is C
|
|
471
|
+
True
|
|
472
|
+
"""
|
|
473
|
+
if p == 1:
|
|
474
|
+
return ColoredPermutations(m, n)
|
|
475
|
+
return super().__classcall__(cls, m, p, n)
|
|
476
|
+
|
|
477
|
+
def __init__(self, m, p, n):
|
|
478
|
+
r"""
|
|
479
|
+
Initialize ``self``.
|
|
480
|
+
|
|
481
|
+
EXAMPLES::
|
|
482
|
+
|
|
483
|
+
sage: # needs sage.groups
|
|
484
|
+
sage: G = groups.misc.ShephardToddFamily(6, 2, 3)
|
|
485
|
+
sage: TestSuite(G).run()
|
|
486
|
+
sage: G = groups.misc.ShephardToddFamily(8, 4, 1)
|
|
487
|
+
sage: TestSuite(G).run()
|
|
488
|
+
|
|
489
|
+
We skip some of the Coxeter group tests since the left descents
|
|
490
|
+
have not been implemented::
|
|
491
|
+
|
|
492
|
+
sage: # needs sage.groups
|
|
493
|
+
sage: coxeter_tests = ["_test_descents", "_test_has_descent",
|
|
494
|
+
....: "_test_reduced_word", "_test_simple_projections"]
|
|
495
|
+
sage: G = groups.misc.ShephardToddFamily(2, 2, 3)
|
|
496
|
+
sage: TestSuite(G).run(skip=coxeter_tests)
|
|
497
|
+
sage: G = groups.misc.ShephardToddFamily(4, 4, 2)
|
|
498
|
+
sage: TestSuite(G).run(skip=coxeter_tests)
|
|
499
|
+
"""
|
|
500
|
+
if m <= 0:
|
|
501
|
+
raise ValueError("m must be a positive integer")
|
|
502
|
+
self._m = ZZ(m)
|
|
503
|
+
self._p = ZZ(p)
|
|
504
|
+
if not self._p.divides(self._m):
|
|
505
|
+
raise ValueError("{} does not divide {}".format(self._p, self._m))
|
|
506
|
+
self._n = ZZ(n)
|
|
507
|
+
self._C = IntegerModRing(self._m)
|
|
508
|
+
self._P = Permutations(self._n)
|
|
509
|
+
|
|
510
|
+
if (self._p == 1 and (self._m == 1 or self._m == 2)
|
|
511
|
+
or (self._p == 2 and self._m == 2)
|
|
512
|
+
or (self._n == 2 and self._p == self._m)):
|
|
513
|
+
from sage.categories.finite_coxeter_groups import FiniteCoxeterGroups
|
|
514
|
+
category = FiniteCoxeterGroups()
|
|
515
|
+
if not (self._n == self._m == self._p == 2): # special case of type D_2
|
|
516
|
+
category = category.Irreducible()
|
|
517
|
+
else:
|
|
518
|
+
from sage.categories.complex_reflection_groups import ComplexReflectionGroups
|
|
519
|
+
category = ComplexReflectionGroups().Finite().Irreducible()
|
|
520
|
+
if self._p in [1, self._m]:
|
|
521
|
+
category = category.WellGenerated()
|
|
522
|
+
Parent.__init__(self, category=category)
|
|
523
|
+
|
|
524
|
+
def _repr_(self):
|
|
525
|
+
"""
|
|
526
|
+
Return a string representation of ``self``.
|
|
527
|
+
|
|
528
|
+
EXAMPLES::
|
|
529
|
+
|
|
530
|
+
sage: groups.misc.ShephardToddFamily(6, 2, 3) # needs sage.groups
|
|
531
|
+
Complex reflection group G(6, 2, 3)
|
|
532
|
+
"""
|
|
533
|
+
return "Complex reflection group G({}, {}, {})".format(self._m, self._p, self._n)
|
|
534
|
+
|
|
535
|
+
@cached_method
|
|
536
|
+
def index_set(self):
|
|
537
|
+
r"""
|
|
538
|
+
Return the index set of ``self``.
|
|
539
|
+
|
|
540
|
+
EXAMPLES::
|
|
541
|
+
|
|
542
|
+
sage: C = ColoredPermutations(3, 4)
|
|
543
|
+
sage: C.index_set()
|
|
544
|
+
(1, 2, 3, 4)
|
|
545
|
+
|
|
546
|
+
sage: C = ColoredPermutations(1, 4)
|
|
547
|
+
sage: C.index_set()
|
|
548
|
+
(1, 2, 3)
|
|
549
|
+
|
|
550
|
+
sage: G = groups.misc.ShephardToddFamily(6, 6, 4) # needs sage.groups
|
|
551
|
+
sage: G.index_set() # needs sage.groups
|
|
552
|
+
(1, 2, 3, 4)
|
|
553
|
+
|
|
554
|
+
sage: G = groups.misc.ShephardToddFamily(6, 2, 4) # needs sage.groups
|
|
555
|
+
sage: G.index_set() # needs sage.groups
|
|
556
|
+
(1, 2, 3, 4, 5)
|
|
557
|
+
|
|
558
|
+
sage: G = groups.misc.ShephardToddFamily(6, 6, 1) # needs sage.groups
|
|
559
|
+
sage: G.index_set() # needs sage.groups
|
|
560
|
+
()
|
|
561
|
+
|
|
562
|
+
sage: G = groups.misc.ShephardToddFamily(6, 2, 1) # needs sage.groups
|
|
563
|
+
sage: G.index_set() # needs sage.groups
|
|
564
|
+
(1,)
|
|
565
|
+
|
|
566
|
+
TESTS::
|
|
567
|
+
|
|
568
|
+
sage: S = SignedPermutations(4)
|
|
569
|
+
sage: S.index_set()
|
|
570
|
+
(1, 2, 3, 4)
|
|
571
|
+
"""
|
|
572
|
+
n = self._n
|
|
573
|
+
if self._m != 1 and self._n > 1:
|
|
574
|
+
n += 1
|
|
575
|
+
if self._p != 1 and self._p != self._m:
|
|
576
|
+
n += 1
|
|
577
|
+
return tuple(range(1, n))
|
|
578
|
+
|
|
579
|
+
def coxeter_matrix(self):
|
|
580
|
+
r"""
|
|
581
|
+
Return the Coxeter matrix of ``self``.
|
|
582
|
+
|
|
583
|
+
When the group is imprimitive and not a Coxeter group,
|
|
584
|
+
this returns ``None``.
|
|
585
|
+
|
|
586
|
+
EXAMPLES::
|
|
587
|
+
|
|
588
|
+
sage: C = ColoredPermutations(3, 4)
|
|
589
|
+
sage: C.coxeter_matrix() # needs sage.graphs sage.modules
|
|
590
|
+
[1 3 2 2]
|
|
591
|
+
[3 1 3 2]
|
|
592
|
+
[2 3 1 4]
|
|
593
|
+
[2 2 4 1]
|
|
594
|
+
|
|
595
|
+
sage: C = ColoredPermutations(1, 4)
|
|
596
|
+
sage: C.coxeter_matrix() # needs sage.graphs sage.modules
|
|
597
|
+
[1 3 2]
|
|
598
|
+
[3 1 3]
|
|
599
|
+
[2 3 1]
|
|
600
|
+
|
|
601
|
+
sage: G = groups.misc.ShephardToddFamily(2, 2, 3) # needs sage.groups
|
|
602
|
+
sage: G.coxeter_matrix() # needs sage.groups
|
|
603
|
+
[1 3 3]
|
|
604
|
+
[3 1 2]
|
|
605
|
+
[3 2 1]
|
|
606
|
+
|
|
607
|
+
sage: G = groups.misc.ShephardToddFamily(2, 2, 2) # needs sage.groups
|
|
608
|
+
sage: G.coxeter_matrix() # needs sage.groups
|
|
609
|
+
[1 2]
|
|
610
|
+
[2 1]
|
|
611
|
+
|
|
612
|
+
sage: G = groups.misc.ShephardToddFamily(2, 2, 1) # needs sage.groups
|
|
613
|
+
sage: G.coxeter_matrix() # needs sage.groups
|
|
614
|
+
[1]
|
|
615
|
+
|
|
616
|
+
sage: G = groups.misc.ShephardToddFamily(5, 5, 1) # needs sage.groups
|
|
617
|
+
sage: G.coxeter_matrix() # needs sage.groups
|
|
618
|
+
[]
|
|
619
|
+
|
|
620
|
+
sage: G = groups.misc.ShephardToddFamily(4, 4, 2) # needs sage.groups
|
|
621
|
+
sage: G.coxeter_matrix() # needs sage.groups
|
|
622
|
+
[1 4]
|
|
623
|
+
[4 1]
|
|
624
|
+
|
|
625
|
+
sage: G = groups.misc.ShephardToddFamily(7, 7, 2) # needs sage.groups
|
|
626
|
+
sage: G.coxeter_matrix() # needs sage.groups
|
|
627
|
+
[1 7]
|
|
628
|
+
[7 1]
|
|
629
|
+
|
|
630
|
+
sage: G = groups.misc.ShephardToddFamily(6, 3, 1) # needs sage.groups
|
|
631
|
+
sage: G.coxeter_matrix() is None # needs sage.groups
|
|
632
|
+
True
|
|
633
|
+
sage: G = groups.misc.ShephardToddFamily(6, 3, 4) # needs sage.groups
|
|
634
|
+
sage: G.coxeter_matrix() is None # needs sage.groups
|
|
635
|
+
True
|
|
636
|
+
|
|
637
|
+
TESTS::
|
|
638
|
+
|
|
639
|
+
sage: S = SignedPermutations(4)
|
|
640
|
+
sage: S.coxeter_matrix() # needs sage.graphs sage.modules
|
|
641
|
+
[1 3 2 2]
|
|
642
|
+
[3 1 3 2]
|
|
643
|
+
[2 3 1 4]
|
|
644
|
+
[2 2 4 1]
|
|
645
|
+
"""
|
|
646
|
+
from sage.combinat.root_system.cartan_type import CartanType
|
|
647
|
+
if self._p == 1:
|
|
648
|
+
if self._m == 1:
|
|
649
|
+
return CartanType(['A', self._n - 1]).coxeter_matrix()
|
|
650
|
+
return CartanType(['B', self._n]).coxeter_matrix()
|
|
651
|
+
if self._p == 2 and self._m == 2:
|
|
652
|
+
if self._n == 1:
|
|
653
|
+
return CartanType(['A', self._n]).coxeter_matrix()
|
|
654
|
+
return CartanType(['D', self._n]).coxeter_matrix()
|
|
655
|
+
if self._n == 2 and self._p == self._m:
|
|
656
|
+
return CartanType(['I', self._m]).coxeter_matrix()
|
|
657
|
+
if self._p == self._m and self._n == 1:
|
|
658
|
+
return CartanType(['A', 0]).coxeter_matrix()
|
|
659
|
+
|
|
660
|
+
@cached_method
|
|
661
|
+
def one(self):
|
|
662
|
+
"""
|
|
663
|
+
Return the identity element of ``self``.
|
|
664
|
+
|
|
665
|
+
EXAMPLES::
|
|
666
|
+
|
|
667
|
+
sage: C = ColoredPermutations(4, 3)
|
|
668
|
+
sage: C.one()
|
|
669
|
+
[[0, 0, 0], [1, 2, 3]]
|
|
670
|
+
"""
|
|
671
|
+
return self.element_class(self, [self._C.zero()] * self._n,
|
|
672
|
+
self._P.identity())
|
|
673
|
+
|
|
674
|
+
def random_element(self):
|
|
675
|
+
r"""
|
|
676
|
+
Return an element of ``self`` at random.
|
|
677
|
+
|
|
678
|
+
EXAMPLES::
|
|
679
|
+
|
|
680
|
+
sage: C = ColoredPermutations(4, 3)
|
|
681
|
+
sage: s = C.random_element(); s # random
|
|
682
|
+
[[0, 2, 1], [2, 1, 3]]
|
|
683
|
+
sage: s in C
|
|
684
|
+
True
|
|
685
|
+
"""
|
|
686
|
+
colors = [self._C.random_element() for _ in range(self._n)]
|
|
687
|
+
if self._p > 1:
|
|
688
|
+
while sum(colors) % self._p:
|
|
689
|
+
colors = [self._C.random_element() for _ in range(self._n)]
|
|
690
|
+
return self.element_class(self, colors, self._P.random_element())
|
|
691
|
+
|
|
692
|
+
def simple_reflection(self, i):
|
|
693
|
+
r"""
|
|
694
|
+
Return the ``i``-th simple reflection of ``self``.
|
|
695
|
+
|
|
696
|
+
EXAMPLES::
|
|
697
|
+
|
|
698
|
+
sage: C = ColoredPermutations(4, 3)
|
|
699
|
+
sage: C.gens()
|
|
700
|
+
([[0, 0, 0], [2, 1, 3]], [[0, 0, 0], [1, 3, 2]], [[0, 0, 1], [1, 2, 3]])
|
|
701
|
+
sage: C.simple_reflection(2)
|
|
702
|
+
[[0, 0, 0], [1, 3, 2]]
|
|
703
|
+
sage: C.simple_reflection(3)
|
|
704
|
+
[[0, 0, 1], [1, 2, 3]]
|
|
705
|
+
|
|
706
|
+
sage: S = SignedPermutations(4)
|
|
707
|
+
sage: S.simple_reflection(1)
|
|
708
|
+
[2, 1, 3, 4]
|
|
709
|
+
sage: S.simple_reflection(4)
|
|
710
|
+
[1, 2, 3, -4]
|
|
711
|
+
|
|
712
|
+
sage: G = groups.misc.ShephardToddFamily(4, 2, 3) # needs sage.groups
|
|
713
|
+
sage: list(G.simple_reflections()) # needs sage.groups
|
|
714
|
+
[[[0, 0, 0], [2, 1, 3]],
|
|
715
|
+
[[0, 0, 0], [1, 3, 2]],
|
|
716
|
+
[[0, 1, 3], [1, 3, 2]],
|
|
717
|
+
[[0, 0, 2], [1, 2, 3]]]
|
|
718
|
+
|
|
719
|
+
sage: G = groups.misc.ShephardToddFamily(8, 4, 1) # needs sage.groups
|
|
720
|
+
sage: G.simple_reflections() # needs sage.groups
|
|
721
|
+
Finite family {1: [[4], [1]]}
|
|
722
|
+
|
|
723
|
+
sage: G = groups.misc.ShephardToddFamily(8, 8, 1) # needs sage.groups
|
|
724
|
+
sage: G.simple_reflections() # needs sage.groups
|
|
725
|
+
Finite family {}
|
|
726
|
+
"""
|
|
727
|
+
if i not in self.index_set():
|
|
728
|
+
raise ValueError("i must be in the index set")
|
|
729
|
+
colors = [self._C.zero()] * self._n
|
|
730
|
+
if i < self._n:
|
|
731
|
+
p = list(range(1, self._n + 1))
|
|
732
|
+
p[i - 1] = i + 1
|
|
733
|
+
p[i] = i
|
|
734
|
+
return self.element_class(self, colors, self._P(p))
|
|
735
|
+
|
|
736
|
+
colors[-1] = self._C.one()
|
|
737
|
+
sn = self.element_class(self, colors, self._P.identity())
|
|
738
|
+
if self._p == 1:
|
|
739
|
+
return sn
|
|
740
|
+
|
|
741
|
+
if i == self._n + 1 or self._n == 1:
|
|
742
|
+
return sn ** self._p
|
|
743
|
+
|
|
744
|
+
snm = self.simple_reflection(self._n-1)
|
|
745
|
+
return sn**(self._m-1) * snm * sn
|
|
746
|
+
|
|
747
|
+
@cached_method
|
|
748
|
+
def _inverse_simple_reflections(self):
|
|
749
|
+
"""
|
|
750
|
+
Return the inverse of the simple reflections of ``self``.
|
|
751
|
+
|
|
752
|
+
.. WARNING::
|
|
753
|
+
|
|
754
|
+
This returns a ``dict`` that should not be mutated since
|
|
755
|
+
the result is cached.
|
|
756
|
+
|
|
757
|
+
EXAMPLES::
|
|
758
|
+
|
|
759
|
+
sage: C = ColoredPermutations(4, 3)
|
|
760
|
+
sage: C._inverse_simple_reflections()
|
|
761
|
+
{1: [[0, 0, 0], [2, 1, 3]],
|
|
762
|
+
2: [[0, 0, 0], [1, 3, 2]],
|
|
763
|
+
3: [[0, 0, 3], [1, 2, 3]]}
|
|
764
|
+
"""
|
|
765
|
+
s = self.simple_reflections()
|
|
766
|
+
return {i: ~s[i] for i in self.index_set()}
|
|
767
|
+
|
|
768
|
+
@cached_method
|
|
769
|
+
def gens(self) -> tuple:
|
|
770
|
+
"""
|
|
771
|
+
Return the generators of ``self``.
|
|
772
|
+
|
|
773
|
+
EXAMPLES::
|
|
774
|
+
|
|
775
|
+
sage: C = ColoredPermutations(4, 3)
|
|
776
|
+
sage: C.gens()
|
|
777
|
+
([[0, 0, 0], [2, 1, 3]],
|
|
778
|
+
[[0, 0, 0], [1, 3, 2]],
|
|
779
|
+
[[0, 0, 1], [1, 2, 3]])
|
|
780
|
+
|
|
781
|
+
sage: S = SignedPermutations(4)
|
|
782
|
+
sage: S.gens()
|
|
783
|
+
([2, 1, 3, 4], [1, 3, 2, 4], [1, 2, 4, 3], [1, 2, 3, -4])
|
|
784
|
+
"""
|
|
785
|
+
return tuple(self.simple_reflection(i) for i in self.index_set())
|
|
786
|
+
|
|
787
|
+
def matrix_group(self):
|
|
788
|
+
"""
|
|
789
|
+
Return the matrix group corresponding to ``self``.
|
|
790
|
+
|
|
791
|
+
EXAMPLES::
|
|
792
|
+
|
|
793
|
+
sage: C = ColoredPermutations(4, 3)
|
|
794
|
+
sage: C.matrix_group() # needs sage.modules sage.rings.number_field
|
|
795
|
+
Matrix group over Cyclotomic Field of order 4 and degree 2 with 3 generators (
|
|
796
|
+
[0 1 0] [1 0 0] [ 1 0 0]
|
|
797
|
+
[1 0 0] [0 0 1] [ 0 1 0]
|
|
798
|
+
[0 0 1], [0 1 0], [ 0 0 zeta4]
|
|
799
|
+
)
|
|
800
|
+
"""
|
|
801
|
+
from sage.groups.matrix_gps.finitely_generated import MatrixGroup
|
|
802
|
+
return MatrixGroup([g.to_matrix() for g in self.gens()])
|
|
803
|
+
|
|
804
|
+
def as_permutation_group(self):
|
|
805
|
+
r"""
|
|
806
|
+
Return the permutation group corresponding to ``self``.
|
|
807
|
+
|
|
808
|
+
EXAMPLES::
|
|
809
|
+
|
|
810
|
+
sage: C = ColoredPermutations(4, 3)
|
|
811
|
+
sage: C.as_permutation_group() # needs sage.groups
|
|
812
|
+
Complex reflection group G(4, 1, 3) as a permutation group
|
|
813
|
+
"""
|
|
814
|
+
from sage.groups.perm_gps.permgroup_named import ComplexReflectionGroup
|
|
815
|
+
return ComplexReflectionGroup(self._m, self._p, self._n)
|
|
816
|
+
|
|
817
|
+
def _element_constructor_(self, x):
|
|
818
|
+
r"""
|
|
819
|
+
Construct an element of ``self`` from ``x``.
|
|
820
|
+
|
|
821
|
+
INPUT:
|
|
822
|
+
|
|
823
|
+
- ``x`` -- either a list of pairs ``(color, element)`` or a pair of
|
|
824
|
+
lists ``(colors, elements)``
|
|
825
|
+
|
|
826
|
+
TESTS::
|
|
827
|
+
|
|
828
|
+
sage: C = ColoredPermutations(4, 3)
|
|
829
|
+
sage: x = C([(2,1), (3,3), (3,2)]); x
|
|
830
|
+
[[2, 3, 3], [1, 3, 2]]
|
|
831
|
+
sage: x == C([[2,3,3], [1,3,2]])
|
|
832
|
+
True
|
|
833
|
+
"""
|
|
834
|
+
if isinstance(x, self.element_class) and x.parent() is self:
|
|
835
|
+
return self
|
|
836
|
+
x = list(x)
|
|
837
|
+
if isinstance(x[0], tuple):
|
|
838
|
+
c = []
|
|
839
|
+
p = []
|
|
840
|
+
for k in x:
|
|
841
|
+
if len(k) != 2:
|
|
842
|
+
raise ValueError("input must be pairs (color, element)")
|
|
843
|
+
c.append(self._C(k[0]))
|
|
844
|
+
p.append(k[1])
|
|
845
|
+
if self._p > 1 and sum(c) % self._p:
|
|
846
|
+
raise ValueError("{} is not an element".format([c, p]))
|
|
847
|
+
return self.element_class(self, c, self._P(p))
|
|
848
|
+
|
|
849
|
+
if len(x) != 2:
|
|
850
|
+
raise ValueError("input must be a pair of a list of colors and a permutation")
|
|
851
|
+
if self._p > 1 and sum(x[0]) % self._p:
|
|
852
|
+
raise ValueError("{} is not an element".format(x))
|
|
853
|
+
return self.element_class(self, [self._C(v) for v in x[0]], self._P(x[1]))
|
|
854
|
+
|
|
855
|
+
def _coerce_map_from_(self, C):
|
|
856
|
+
r"""
|
|
857
|
+
Return a coerce map from ``C`` if it exists and ``None`` otherwise.
|
|
858
|
+
|
|
859
|
+
EXAMPLES::
|
|
860
|
+
|
|
861
|
+
sage: C = ColoredPermutations(2, 3)
|
|
862
|
+
sage: S = SignedPermutations(3)
|
|
863
|
+
sage: C.has_coerce_map_from(S)
|
|
864
|
+
True
|
|
865
|
+
|
|
866
|
+
sage: C = ColoredPermutations(4, 3)
|
|
867
|
+
sage: C.has_coerce_map_from(S)
|
|
868
|
+
False
|
|
869
|
+
sage: S = SignedPermutations(4)
|
|
870
|
+
sage: C.has_coerce_map_from(S)
|
|
871
|
+
False
|
|
872
|
+
|
|
873
|
+
sage: P = Permutations(3)
|
|
874
|
+
sage: C.has_coerce_map_from(P)
|
|
875
|
+
True
|
|
876
|
+
sage: P = Permutations(4)
|
|
877
|
+
sage: C.has_coerce_map_from(P)
|
|
878
|
+
False
|
|
879
|
+
"""
|
|
880
|
+
if isinstance(C, Permutations) and C.n == self._n:
|
|
881
|
+
return lambda P, x: P.element_class(P, [P._C.zero()] * P._n, x)
|
|
882
|
+
if self._m == 2 and self._p == 1 and isinstance(C, SignedPermutations) and C._n == self._n:
|
|
883
|
+
return lambda P, x: P.element_class(P,
|
|
884
|
+
[P._C.zero() if v == 1 else P._C.one()
|
|
885
|
+
for v in x._colors],
|
|
886
|
+
x._perm)
|
|
887
|
+
return super()._coerce_map_from_(C)
|
|
888
|
+
|
|
889
|
+
def __iter__(self):
|
|
890
|
+
r"""
|
|
891
|
+
Iterate over ``self``.
|
|
892
|
+
|
|
893
|
+
EXAMPLES::
|
|
894
|
+
|
|
895
|
+
sage: G = groups.misc.ShephardToddFamily(6, 3, 2) # needs sage.groups
|
|
896
|
+
sage: [x for x in G] # needs sage.groups
|
|
897
|
+
[[[0, 0], [1, 2]],
|
|
898
|
+
[[0, 0], [2, 1]],
|
|
899
|
+
[[0, 3], [1, 2]],
|
|
900
|
+
[[0, 3], [2, 1]],
|
|
901
|
+
[[1, 2], [1, 2]],
|
|
902
|
+
[[1, 2], [2, 1]],
|
|
903
|
+
[[1, 5], [1, 2]],
|
|
904
|
+
[[1, 5], [2, 1]],
|
|
905
|
+
[[2, 1], [1, 2]],
|
|
906
|
+
[[2, 1], [2, 1]],
|
|
907
|
+
[[2, 4], [1, 2]],
|
|
908
|
+
[[2, 4], [2, 1]],
|
|
909
|
+
[[3, 0], [1, 2]],
|
|
910
|
+
[[3, 0], [2, 1]],
|
|
911
|
+
[[3, 3], [1, 2]],
|
|
912
|
+
[[3, 3], [2, 1]],
|
|
913
|
+
[[4, 2], [1, 2]],
|
|
914
|
+
[[4, 2], [2, 1]],
|
|
915
|
+
[[4, 5], [1, 2]],
|
|
916
|
+
[[4, 5], [2, 1]],
|
|
917
|
+
[[5, 1], [1, 2]],
|
|
918
|
+
[[5, 1], [2, 1]],
|
|
919
|
+
[[5, 4], [1, 2]],
|
|
920
|
+
[[5, 4], [2, 1]]]
|
|
921
|
+
"""
|
|
922
|
+
for c in itertools.product(self._C, repeat=self._n):
|
|
923
|
+
if sum(c) % self._p:
|
|
924
|
+
continue
|
|
925
|
+
for perm in self._P:
|
|
926
|
+
yield self.element_class(self, c, perm)
|
|
927
|
+
|
|
928
|
+
def cardinality(self):
|
|
929
|
+
r"""
|
|
930
|
+
Return the cardinality of ``self``.
|
|
931
|
+
|
|
932
|
+
EXAMPLES::
|
|
933
|
+
|
|
934
|
+
sage: C = ColoredPermutations(4, 3)
|
|
935
|
+
sage: C.cardinality()
|
|
936
|
+
384
|
|
937
|
+
sage: C.cardinality() == 4**3 * factorial(3)
|
|
938
|
+
True
|
|
939
|
+
"""
|
|
940
|
+
ret = self._m ** self._n * self._P.cardinality()
|
|
941
|
+
if self._p == 1:
|
|
942
|
+
return ret
|
|
943
|
+
return ret // self._p
|
|
944
|
+
|
|
945
|
+
order = cardinality
|
|
946
|
+
|
|
947
|
+
def rank(self):
|
|
948
|
+
"""
|
|
949
|
+
Return the rank of ``self``.
|
|
950
|
+
|
|
951
|
+
The rank of a complex reflection group is equal to the dimension
|
|
952
|
+
of the complex vector space the group acts on.
|
|
953
|
+
|
|
954
|
+
EXAMPLES::
|
|
955
|
+
|
|
956
|
+
sage: C = ColoredPermutations(4, 12)
|
|
957
|
+
sage: C.rank()
|
|
958
|
+
12
|
|
959
|
+
sage: C = ColoredPermutations(7, 4)
|
|
960
|
+
sage: C.rank()
|
|
961
|
+
4
|
|
962
|
+
sage: C = ColoredPermutations(1, 4)
|
|
963
|
+
sage: C.rank()
|
|
964
|
+
3
|
|
965
|
+
"""
|
|
966
|
+
if self._m == 1:
|
|
967
|
+
return self._n - 1
|
|
968
|
+
return self._n
|
|
969
|
+
|
|
970
|
+
def degrees(self) -> tuple:
|
|
971
|
+
r"""
|
|
972
|
+
Return the degrees of ``self``.
|
|
973
|
+
|
|
974
|
+
The degrees of a complex reflection group are the degrees of
|
|
975
|
+
the fundamental invariants of the ring of polynomial invariants.
|
|
976
|
+
|
|
977
|
+
If `m = 1`, then we are in the special case of the symmetric group
|
|
978
|
+
and the degrees are `(2, 3, \ldots, n, n+1)`. Otherwise the degrees
|
|
979
|
+
are `(m, 2m, \ldots, nm)`.
|
|
980
|
+
|
|
981
|
+
EXAMPLES::
|
|
982
|
+
|
|
983
|
+
sage: C = ColoredPermutations(4, 3)
|
|
984
|
+
sage: C.degrees()
|
|
985
|
+
(4, 8, 12)
|
|
986
|
+
sage: S = ColoredPermutations(1, 3)
|
|
987
|
+
sage: S.degrees()
|
|
988
|
+
(2, 3)
|
|
989
|
+
sage: G = groups.misc.ShephardToddFamily(6, 2, 3) # needs sage.groups
|
|
990
|
+
sage: G.degrees() # needs sage.groups
|
|
991
|
+
(6, 9, 12)
|
|
992
|
+
|
|
993
|
+
We now check that the product of the degrees is equal to the
|
|
994
|
+
cardinality of ``self``::
|
|
995
|
+
|
|
996
|
+
sage: prod(C.degrees()) == C.cardinality()
|
|
997
|
+
True
|
|
998
|
+
sage: prod(S.degrees()) == S.cardinality()
|
|
999
|
+
True
|
|
1000
|
+
sage: prod(G.degrees()) == G.cardinality() # needs sage.groups
|
|
1001
|
+
True
|
|
1002
|
+
"""
|
|
1003
|
+
# For the usual symmetric group (self._m=1) we need to start at 2
|
|
1004
|
+
start = 2 if self._m == 1 else 1
|
|
1005
|
+
degrees = [self._m * i for i in range(start, self._n)]
|
|
1006
|
+
degrees.append(self._m * self._n // self._p)
|
|
1007
|
+
return tuple(sorted(degrees))
|
|
1008
|
+
|
|
1009
|
+
def codegrees(self) -> tuple:
|
|
1010
|
+
r"""
|
|
1011
|
+
Return the codegrees of ``self``.
|
|
1012
|
+
|
|
1013
|
+
Let `G` be a complex reflection group. The codegrees
|
|
1014
|
+
`d_1^* \leq d_2^* \leq \cdots \leq d_{\ell}^*` of `G` can be
|
|
1015
|
+
defined by:
|
|
1016
|
+
|
|
1017
|
+
.. MATH::
|
|
1018
|
+
|
|
1019
|
+
\prod_{i=1}^{\ell} (q - d_i^* - 1)
|
|
1020
|
+
= \sum_{g \in G} \det(g) q^{\dim(V^g)},
|
|
1021
|
+
|
|
1022
|
+
where `V` is the natural complex vector space that `G` acts on
|
|
1023
|
+
and `\ell` is the :meth:`rank`.
|
|
1024
|
+
|
|
1025
|
+
If `m = 1`, then we are in the special case of the symmetric group
|
|
1026
|
+
and the codegrees are `(n-2, n-3, \ldots 1, 0)`. Otherwise the degrees
|
|
1027
|
+
are `((n-1)m, (n-2)m, \ldots, m, 0)`.
|
|
1028
|
+
|
|
1029
|
+
EXAMPLES::
|
|
1030
|
+
|
|
1031
|
+
sage: C = ColoredPermutations(4, 3)
|
|
1032
|
+
sage: C.codegrees()
|
|
1033
|
+
(8, 4, 0)
|
|
1034
|
+
sage: S = ColoredPermutations(1, 3)
|
|
1035
|
+
sage: S.codegrees()
|
|
1036
|
+
(1, 0)
|
|
1037
|
+
sage: G = groups.misc.ShephardToddFamily(6, 2, 3) # needs sage.groups
|
|
1038
|
+
sage: G.codegrees() # needs sage.groups
|
|
1039
|
+
(12, 6, 0)
|
|
1040
|
+
|
|
1041
|
+
TESTS:
|
|
1042
|
+
|
|
1043
|
+
We check the polynomial identity::
|
|
1044
|
+
|
|
1045
|
+
sage: R.<q> = ZZ[]
|
|
1046
|
+
sage: C = ColoredPermutations(3, 2)
|
|
1047
|
+
sage: f = prod(q - ds - 1 for ds in C.codegrees())
|
|
1048
|
+
sage: d = lambda x: sum(1 for e in x.to_matrix().eigenvalues() if e == 1)
|
|
1049
|
+
sage: g = sum(det(x.to_matrix()) * q**d(x) for x in C) # needs sage.modules sage.rings.number_field
|
|
1050
|
+
sage: f == g # needs sage.modules sage.rings.number_field
|
|
1051
|
+
True
|
|
1052
|
+
"""
|
|
1053
|
+
# Special case for the usual symmetric group
|
|
1054
|
+
if self._m == 1:
|
|
1055
|
+
return tuple([ZZ(v) for v in reversed(range(self._n-1))])
|
|
1056
|
+
if self._p < self._m:
|
|
1057
|
+
return tuple([self._m * i for i in reversed(range(self._n))])
|
|
1058
|
+
codegrees = [self._m * i for i in reversed(range(self._n-1))]
|
|
1059
|
+
codegrees.append((self._n-1)*self._m - self._n)
|
|
1060
|
+
return tuple(sorted(codegrees, reverse=True))
|
|
1061
|
+
|
|
1062
|
+
def number_of_reflection_hyperplanes(self):
|
|
1063
|
+
"""
|
|
1064
|
+
Return the number of reflection hyperplanes of ``self``.
|
|
1065
|
+
|
|
1066
|
+
The number of reflection hyperplanes of a complex reflection
|
|
1067
|
+
group is equal to the sum of the codegrees plus the rank.
|
|
1068
|
+
|
|
1069
|
+
EXAMPLES::
|
|
1070
|
+
|
|
1071
|
+
sage: C = ColoredPermutations(1, 2)
|
|
1072
|
+
sage: C.number_of_reflection_hyperplanes()
|
|
1073
|
+
1
|
|
1074
|
+
sage: C = ColoredPermutations(1, 3)
|
|
1075
|
+
sage: C.number_of_reflection_hyperplanes()
|
|
1076
|
+
3
|
|
1077
|
+
sage: C = ColoredPermutations(4, 12)
|
|
1078
|
+
sage: C.number_of_reflection_hyperplanes()
|
|
1079
|
+
276
|
|
1080
|
+
"""
|
|
1081
|
+
return sum(self.codegrees()) + self.rank()
|
|
1082
|
+
|
|
1083
|
+
def fixed_point_polynomial(self, q=None):
|
|
1084
|
+
r"""
|
|
1085
|
+
The fixed point polynomial of ``self``.
|
|
1086
|
+
|
|
1087
|
+
The fixed point polynomial `f_G` of a complex reflection group `G`
|
|
1088
|
+
is counting the dimensions of fixed points subspaces:
|
|
1089
|
+
|
|
1090
|
+
.. MATH::
|
|
1091
|
+
|
|
1092
|
+
f_G(q) = \sum_{w \in W} q^{\dim V^w}.
|
|
1093
|
+
|
|
1094
|
+
Furthermore, let `d_1, d_2, \ldots, d_{\ell}` be the degrees of `G`,
|
|
1095
|
+
where `\ell` is the :meth:`rank`. Then the fixed point polynomial
|
|
1096
|
+
is given by
|
|
1097
|
+
|
|
1098
|
+
.. MATH::
|
|
1099
|
+
|
|
1100
|
+
f_G(q) = \prod_{i=1}^{\ell} (q + d_i - 1).
|
|
1101
|
+
|
|
1102
|
+
INPUT:
|
|
1103
|
+
|
|
1104
|
+
- ``q`` -- (default: the generator of ``ZZ['q']``) the parameter `q`
|
|
1105
|
+
|
|
1106
|
+
EXAMPLES::
|
|
1107
|
+
|
|
1108
|
+
sage: C = ColoredPermutations(4, 3)
|
|
1109
|
+
sage: C.fixed_point_polynomial()
|
|
1110
|
+
q^3 + 21*q^2 + 131*q + 231
|
|
1111
|
+
|
|
1112
|
+
sage: S = ColoredPermutations(1, 3)
|
|
1113
|
+
sage: S.fixed_point_polynomial()
|
|
1114
|
+
q^2 + 3*q + 2
|
|
1115
|
+
|
|
1116
|
+
TESTS:
|
|
1117
|
+
|
|
1118
|
+
We check the against the degrees and codegrees::
|
|
1119
|
+
|
|
1120
|
+
sage: R.<q> = ZZ[]
|
|
1121
|
+
sage: C = ColoredPermutations(4, 3)
|
|
1122
|
+
sage: C.fixed_point_polynomial(q) == prod(q + d - 1 for d in C.degrees())
|
|
1123
|
+
True
|
|
1124
|
+
"""
|
|
1125
|
+
if q is None:
|
|
1126
|
+
q = PolynomialRing(ZZ, 'q').gen(0)
|
|
1127
|
+
return prod(q + d - 1 for d in self.degrees())
|
|
1128
|
+
|
|
1129
|
+
def is_well_generated(self):
|
|
1130
|
+
r"""
|
|
1131
|
+
Return if ``self`` is a well-generated complex reflection group.
|
|
1132
|
+
|
|
1133
|
+
A complex reflection group `G` is well-generated if it is
|
|
1134
|
+
generated by `\ell` reflections. Equivalently, `G` is well-generated
|
|
1135
|
+
if `d_i + d_i^* = d_{\ell}` for all `1 \leq i \leq \ell`.
|
|
1136
|
+
|
|
1137
|
+
EXAMPLES::
|
|
1138
|
+
|
|
1139
|
+
sage: C = ColoredPermutations(4, 3)
|
|
1140
|
+
sage: C.is_well_generated()
|
|
1141
|
+
True
|
|
1142
|
+
sage: C = ColoredPermutations(2, 8)
|
|
1143
|
+
sage: C.is_well_generated()
|
|
1144
|
+
True
|
|
1145
|
+
sage: C = ColoredPermutations(1, 4)
|
|
1146
|
+
sage: C.is_well_generated()
|
|
1147
|
+
True
|
|
1148
|
+
"""
|
|
1149
|
+
if self._p not in [1, self._m]:
|
|
1150
|
+
return False
|
|
1151
|
+
deg = self.degrees()
|
|
1152
|
+
codeg = self.codegrees()
|
|
1153
|
+
return all(deg[-1] == d + dstar for d, dstar in zip(deg, codeg))
|
|
1154
|
+
|
|
1155
|
+
Element = ColoredPermutation
|
|
1156
|
+
|
|
1157
|
+
|
|
1158
|
+
class ColoredPermutations(ShephardToddFamilyGroup):
|
|
1159
|
+
r"""
|
|
1160
|
+
The group of `m`-colored permutations on `\{1, 2, \ldots, n\}`.
|
|
1161
|
+
|
|
1162
|
+
Let `S_n` be the symmetric group on `n` letters and `C_m` be the cyclic
|
|
1163
|
+
group of order `m`. The `m`-colored permutation group on `n` letters
|
|
1164
|
+
is given by `P_n^m = C_m \wr S_n`. This is also the complex reflection
|
|
1165
|
+
group `G(m, 1, n)`.
|
|
1166
|
+
|
|
1167
|
+
We define our multiplication by
|
|
1168
|
+
|
|
1169
|
+
.. MATH::
|
|
1170
|
+
|
|
1171
|
+
((s_1, \ldots s_n), \sigma) \cdot ((t_1, \ldots, t_n), \tau)
|
|
1172
|
+
= ((s_1 t_{\sigma(1)}, \ldots, s_n t_{\sigma(n)}), \tau \sigma).
|
|
1173
|
+
|
|
1174
|
+
EXAMPLES::
|
|
1175
|
+
|
|
1176
|
+
sage: C = ColoredPermutations(4, 3); C
|
|
1177
|
+
4-colored permutations of size 3
|
|
1178
|
+
sage: s1,s2,t = C.gens()
|
|
1179
|
+
sage: (s1, s2, t)
|
|
1180
|
+
([[0, 0, 0], [2, 1, 3]], [[0, 0, 0], [1, 3, 2]], [[0, 0, 1], [1, 2, 3]])
|
|
1181
|
+
sage: s1*s2
|
|
1182
|
+
[[0, 0, 0], [3, 1, 2]]
|
|
1183
|
+
sage: s1*s2*s1 == s2*s1*s2
|
|
1184
|
+
True
|
|
1185
|
+
sage: t^4 == C.one()
|
|
1186
|
+
True
|
|
1187
|
+
sage: s2*t*s2
|
|
1188
|
+
[[0, 1, 0], [1, 2, 3]]
|
|
1189
|
+
|
|
1190
|
+
We can also create a colored permutation by passing
|
|
1191
|
+
an iterable consisting of tuples consisting of ``(color, element)``::
|
|
1192
|
+
|
|
1193
|
+
sage: x = C([(2,1), (3,3), (3,2)]); x
|
|
1194
|
+
[[2, 3, 3], [1, 3, 2]]
|
|
1195
|
+
|
|
1196
|
+
or a list of colors and a permutation::
|
|
1197
|
+
|
|
1198
|
+
sage: C([[3,3,1], [1,3,2]])
|
|
1199
|
+
[[3, 3, 1], [1, 3, 2]]
|
|
1200
|
+
sage: C(([3,3,1], [1,3,2]))
|
|
1201
|
+
[[3, 3, 1], [1, 3, 2]]
|
|
1202
|
+
|
|
1203
|
+
There is also the natural lift from permutations::
|
|
1204
|
+
|
|
1205
|
+
sage: P = Permutations(3)
|
|
1206
|
+
sage: C(P.an_element())
|
|
1207
|
+
[[0, 0, 0], [3, 1, 2]]
|
|
1208
|
+
|
|
1209
|
+
A colored permutation::
|
|
1210
|
+
|
|
1211
|
+
sage: C(C.an_element()) == C.an_element()
|
|
1212
|
+
True
|
|
1213
|
+
|
|
1214
|
+
REFERENCES:
|
|
1215
|
+
|
|
1216
|
+
- :wikipedia:`Generalized_symmetric_group`
|
|
1217
|
+
- :wikipedia:`Complex_reflection_group`
|
|
1218
|
+
"""
|
|
1219
|
+
def __init__(self, m, n):
|
|
1220
|
+
r"""
|
|
1221
|
+
Initialize ``self``.
|
|
1222
|
+
|
|
1223
|
+
EXAMPLES::
|
|
1224
|
+
|
|
1225
|
+
sage: C = ColoredPermutations(4, 3)
|
|
1226
|
+
sage: TestSuite(C).run()
|
|
1227
|
+
sage: C = ColoredPermutations(2, 3)
|
|
1228
|
+
sage: TestSuite(C).run()
|
|
1229
|
+
sage: C = ColoredPermutations(1, 3)
|
|
1230
|
+
sage: TestSuite(C).run()
|
|
1231
|
+
"""
|
|
1232
|
+
ShephardToddFamilyGroup.__init__(self, m, 1, n)
|
|
1233
|
+
|
|
1234
|
+
def _repr_(self):
|
|
1235
|
+
"""
|
|
1236
|
+
Return a string representation of ``self``.
|
|
1237
|
+
|
|
1238
|
+
EXAMPLES::
|
|
1239
|
+
|
|
1240
|
+
sage: ColoredPermutations(4, 3)
|
|
1241
|
+
4-colored permutations of size 3
|
|
1242
|
+
"""
|
|
1243
|
+
return "{}-colored permutations of size {}".format(self._m, self._n)
|
|
1244
|
+
|
|
1245
|
+
def __iter__(self):
|
|
1246
|
+
"""
|
|
1247
|
+
Iterate over ``self``.
|
|
1248
|
+
|
|
1249
|
+
EXAMPLES::
|
|
1250
|
+
|
|
1251
|
+
sage: C = ColoredPermutations(2, 2)
|
|
1252
|
+
sage: [x for x in C]
|
|
1253
|
+
[[[0, 0], [1, 2]],
|
|
1254
|
+
[[0, 1], [1, 2]],
|
|
1255
|
+
[[1, 0], [1, 2]],
|
|
1256
|
+
[[1, 1], [1, 2]],
|
|
1257
|
+
[[0, 0], [2, 1]],
|
|
1258
|
+
[[0, 1], [2, 1]],
|
|
1259
|
+
[[1, 0], [2, 1]],
|
|
1260
|
+
[[1, 1], [2, 1]]]
|
|
1261
|
+
"""
|
|
1262
|
+
for perm in self._P:
|
|
1263
|
+
for c in itertools.product(self._C, repeat=self._n):
|
|
1264
|
+
yield self.element_class(self, c, perm)
|
|
1265
|
+
|
|
1266
|
+
|
|
1267
|
+
#####################################################################
|
|
1268
|
+
# Signed permutations
|
|
1269
|
+
|
|
1270
|
+
|
|
1271
|
+
class SignedPermutation(ColoredPermutation,
|
|
1272
|
+
metaclass=InheritComparisonClasscallMetaclass):
|
|
1273
|
+
"""
|
|
1274
|
+
A signed permutation.
|
|
1275
|
+
"""
|
|
1276
|
+
@staticmethod
|
|
1277
|
+
def __classcall_private__(cls, pi):
|
|
1278
|
+
"""
|
|
1279
|
+
Create a signed permutation.
|
|
1280
|
+
|
|
1281
|
+
EXAMPLES::
|
|
1282
|
+
|
|
1283
|
+
sage: SignedPermutation([2, 1, 3])
|
|
1284
|
+
[2, 1, 3]
|
|
1285
|
+
|
|
1286
|
+
sage: SignedPermutation([2, 1, -3])
|
|
1287
|
+
[2, 1, -3]
|
|
1288
|
+
|
|
1289
|
+
sage: SignedPermutation((2,1,-3))
|
|
1290
|
+
[2, 1, -3]
|
|
1291
|
+
|
|
1292
|
+
sage: SignedPermutation(range(1,4))
|
|
1293
|
+
[1, 2, 3]
|
|
1294
|
+
"""
|
|
1295
|
+
return SignedPermutations(len(list(pi)))(pi)
|
|
1296
|
+
|
|
1297
|
+
def _repr_(self):
|
|
1298
|
+
"""
|
|
1299
|
+
Return a string representation of ``self``.
|
|
1300
|
+
|
|
1301
|
+
EXAMPLES::
|
|
1302
|
+
|
|
1303
|
+
sage: S = SignedPermutations(4)
|
|
1304
|
+
sage: s1,s2,s3,s4 = S.gens()
|
|
1305
|
+
sage: s4*s1*s2*s3*s4
|
|
1306
|
+
[-4, 1, 2, -3]
|
|
1307
|
+
"""
|
|
1308
|
+
return repr(list(self))
|
|
1309
|
+
|
|
1310
|
+
_latex_ = _repr_
|
|
1311
|
+
|
|
1312
|
+
def _mul_(self, other):
|
|
1313
|
+
"""
|
|
1314
|
+
Multiply ``self`` and ``other``.
|
|
1315
|
+
|
|
1316
|
+
EXAMPLES::
|
|
1317
|
+
|
|
1318
|
+
sage: S = SignedPermutations(4)
|
|
1319
|
+
sage: s1,s2,s3,s4 = S.gens()
|
|
1320
|
+
sage: x = s4*s1*s2*s3*s4; x
|
|
1321
|
+
[-4, 1, 2, -3]
|
|
1322
|
+
sage: x * x
|
|
1323
|
+
[3, -4, 1, -2]
|
|
1324
|
+
|
|
1325
|
+
::
|
|
1326
|
+
|
|
1327
|
+
sage: s1*s2*s1 == s1*s2*s1
|
|
1328
|
+
True
|
|
1329
|
+
sage: s3*s4*s3*s4 == s4*s3*s4*s3
|
|
1330
|
+
True
|
|
1331
|
+
"""
|
|
1332
|
+
colors = tuple(c * other._colors[val - 1] # -1 for indexing
|
|
1333
|
+
for c, val in zip(self._colors, self._perm))
|
|
1334
|
+
p = self._perm._left_to_right_multiply_on_right(other._perm)
|
|
1335
|
+
return self.__class__(self.parent(), colors, p)
|
|
1336
|
+
|
|
1337
|
+
def __invert__(self):
|
|
1338
|
+
"""
|
|
1339
|
+
Return the inverse of ``self``.
|
|
1340
|
+
|
|
1341
|
+
EXAMPLES::
|
|
1342
|
+
|
|
1343
|
+
sage: S = SignedPermutations(4)
|
|
1344
|
+
sage: s1,s2,s3,s4 = S.gens()
|
|
1345
|
+
sage: x = s4*s1*s2*s3*s4
|
|
1346
|
+
sage: ~x # indirect doctest
|
|
1347
|
+
[2, 3, -4, -1]
|
|
1348
|
+
sage: x * ~x == S.one()
|
|
1349
|
+
True
|
|
1350
|
+
"""
|
|
1351
|
+
ip = ~self._perm
|
|
1352
|
+
return self.__class__(self.parent(),
|
|
1353
|
+
tuple(self._colors[i - 1] for i in ip), # -1 for indexing
|
|
1354
|
+
ip)
|
|
1355
|
+
|
|
1356
|
+
def __iter__(self):
|
|
1357
|
+
"""
|
|
1358
|
+
Iterate over ``self``.
|
|
1359
|
+
|
|
1360
|
+
EXAMPLES::
|
|
1361
|
+
|
|
1362
|
+
sage: S = SignedPermutations(4)
|
|
1363
|
+
sage: s1,s2,s3,s4 = S.gens()
|
|
1364
|
+
sage: x = s4*s1*s2*s3*s4
|
|
1365
|
+
sage: [a for a in x]
|
|
1366
|
+
[-4, 1, 2, -3]
|
|
1367
|
+
"""
|
|
1368
|
+
for c, p in zip(self._colors, self._perm):
|
|
1369
|
+
yield c * p
|
|
1370
|
+
|
|
1371
|
+
def __getitem__(self, key):
|
|
1372
|
+
"""
|
|
1373
|
+
Return the specified element in the one line form of ``self``.
|
|
1374
|
+
|
|
1375
|
+
EXAMPLES::
|
|
1376
|
+
|
|
1377
|
+
sage: pi = SignedPermutation([-4, 5, -1, 2, -3])
|
|
1378
|
+
sage: pi[-1]
|
|
1379
|
+
-3
|
|
1380
|
+
sage: pi[1::2]
|
|
1381
|
+
[5, 2]
|
|
1382
|
+
"""
|
|
1383
|
+
if isinstance(key, slice):
|
|
1384
|
+
return [c * v for c, v in zip(self._colors[key], self._perm[key])]
|
|
1385
|
+
return self._colors[key] * self._perm[key]
|
|
1386
|
+
|
|
1387
|
+
def __call__(self, i):
|
|
1388
|
+
"""
|
|
1389
|
+
Return the image of the integer ``i`` in ``self``.
|
|
1390
|
+
|
|
1391
|
+
EXAMPLES::
|
|
1392
|
+
|
|
1393
|
+
sage: pi = SignedPermutations(7)([2,-1,4,-6,-5,-3,7])
|
|
1394
|
+
sage: pi(2)
|
|
1395
|
+
-1
|
|
1396
|
+
sage: pi(-2)
|
|
1397
|
+
1
|
|
1398
|
+
sage: pi(7)
|
|
1399
|
+
7
|
|
1400
|
+
sage: pi(-7)
|
|
1401
|
+
-7
|
|
1402
|
+
sage: [pi(i) for i in range(1,8)]
|
|
1403
|
+
[2, -1, 4, -6, -5, -3, 7]
|
|
1404
|
+
sage: [pi(-i) for i in range(1,8)]
|
|
1405
|
+
[-2, 1, -4, 6, 5, 3, -7]
|
|
1406
|
+
"""
|
|
1407
|
+
if i in ZZ and 1 <= abs(i) <= len(self):
|
|
1408
|
+
i = ZZ(i)
|
|
1409
|
+
if i < 0:
|
|
1410
|
+
return -self._colors[-i - 1] * self._perm[-i - 1]
|
|
1411
|
+
return self._colors[i - 1] * self._perm[i - 1]
|
|
1412
|
+
|
|
1413
|
+
raise TypeError("i (= %s) must equal +/- an integer between %s and %s"
|
|
1414
|
+
% (i, 1, len(self)))
|
|
1415
|
+
|
|
1416
|
+
def to_matrix(self):
|
|
1417
|
+
"""
|
|
1418
|
+
Return a matrix of ``self``.
|
|
1419
|
+
|
|
1420
|
+
EXAMPLES::
|
|
1421
|
+
|
|
1422
|
+
sage: S = SignedPermutations(4)
|
|
1423
|
+
sage: s1,s2,s3,s4 = S.gens()
|
|
1424
|
+
sage: x = s4*s1*s2*s3*s4
|
|
1425
|
+
sage: M = x.to_matrix(); M # needs sage.modules
|
|
1426
|
+
[ 0 1 0 0]
|
|
1427
|
+
[ 0 0 1 0]
|
|
1428
|
+
[ 0 0 0 -1]
|
|
1429
|
+
[-1 0 0 0]
|
|
1430
|
+
|
|
1431
|
+
The matrix multiplication is in the *opposite* order::
|
|
1432
|
+
|
|
1433
|
+
sage: m1,m2,m3,m4 = [g.to_matrix() for g in S.gens()] # needs sage.modules
|
|
1434
|
+
sage: M == m4 * m3 * m2 * m1 * m4 # needs sage.modules
|
|
1435
|
+
True
|
|
1436
|
+
"""
|
|
1437
|
+
return self._perm.to_matrix() * diagonal_matrix(self._colors)
|
|
1438
|
+
|
|
1439
|
+
def has_left_descent(self, i) -> bool:
|
|
1440
|
+
"""
|
|
1441
|
+
Return ``True`` if ``i`` is a left descent of ``self``.
|
|
1442
|
+
|
|
1443
|
+
EXAMPLES::
|
|
1444
|
+
|
|
1445
|
+
sage: S = SignedPermutations(4)
|
|
1446
|
+
sage: s1,s2,s3,s4 = S.gens()
|
|
1447
|
+
sage: x = s4*s1*s2*s3*s4
|
|
1448
|
+
sage: [x.has_left_descent(i) for i in S.index_set()]
|
|
1449
|
+
[True, False, False, True]
|
|
1450
|
+
"""
|
|
1451
|
+
n = self.parent()._n
|
|
1452
|
+
if i == n:
|
|
1453
|
+
return self._colors[-1] == -1
|
|
1454
|
+
if self._colors[i - 1] == -1:
|
|
1455
|
+
return self._colors[i] == 1 or self._perm[i - 1] < self._perm[i]
|
|
1456
|
+
return self._colors[i] == 1 and self._perm[i - 1] > self._perm[i]
|
|
1457
|
+
|
|
1458
|
+
def to_cycles(self, singletons=True, use_min=True, negative_cycles=True):
|
|
1459
|
+
r"""
|
|
1460
|
+
Return the signed permutation ``self`` as a list of disjoint cycles.
|
|
1461
|
+
|
|
1462
|
+
The cycles are returned in the order of increasing smallest
|
|
1463
|
+
elements, and each cycle is returned as a tuple which starts
|
|
1464
|
+
with its smallest positive element.
|
|
1465
|
+
|
|
1466
|
+
INPUT:
|
|
1467
|
+
|
|
1468
|
+
- ``singletons`` -- boolean (default: ``True``); whether to include
|
|
1469
|
+
singleton cycles or not
|
|
1470
|
+
- ``use_min`` -- boolean (default: ``True``); if ``False``, the cycles
|
|
1471
|
+
are returned in the order of increasing *largest* (not smallest)
|
|
1472
|
+
elements, and each cycle starts with its largest element
|
|
1473
|
+
- ``negative_cycles`` -- boolean (default: ``True``); if ``False``, for
|
|
1474
|
+
any two cycles `C^{\pm} = \{\pm c_1, \ldots, \pm c_k\}` such that
|
|
1475
|
+
`C^+ \neq C^-`, this does not include the cycle `C^-`
|
|
1476
|
+
|
|
1477
|
+
.. WARNING::
|
|
1478
|
+
|
|
1479
|
+
The argument ``negative_cycles`` does not refer to the usual
|
|
1480
|
+
definition of a negative cycle; see :meth:`cycle_type`.
|
|
1481
|
+
|
|
1482
|
+
EXAMPLES::
|
|
1483
|
+
|
|
1484
|
+
sage: pi = SignedPermutations(7)([2,-1,4,-6,-5,-3,7])
|
|
1485
|
+
sage: pi.to_cycles()
|
|
1486
|
+
[(1, 2, -1, -2), (3, 4, -6), (-3, -4, 6), (5, -5), (7,), (-7,)]
|
|
1487
|
+
sage: pi.to_cycles(singletons=False)
|
|
1488
|
+
[(1, 2, -1, -2), (3, 4, -6), (-3, -4, 6), (5, -5)]
|
|
1489
|
+
sage: pi.to_cycles(negative_cycles=False)
|
|
1490
|
+
[(1, 2, -1, -2), (3, 4, -6), (5, -5), (7,)]
|
|
1491
|
+
sage: pi.to_cycles(singletons=False, negative_cycles=False)
|
|
1492
|
+
[(1, 2, -1, -2), (3, 4, -6), (5, -5)]
|
|
1493
|
+
sage: pi.to_cycles(use_min=False)
|
|
1494
|
+
[(7,), (-7,), (6, -3, -4), (-6, 3, 4), (5, -5), (2, -1, -2, 1)]
|
|
1495
|
+
sage: pi.to_cycles(singletons=False, use_min=False)
|
|
1496
|
+
[(6, -3, -4), (-6, 3, 4), (5, -5), (2, -1, -2, 1)]
|
|
1497
|
+
"""
|
|
1498
|
+
cycles = []
|
|
1499
|
+
|
|
1500
|
+
l = self._perm[:]
|
|
1501
|
+
|
|
1502
|
+
if use_min:
|
|
1503
|
+
groundset = range(len(l))
|
|
1504
|
+
else:
|
|
1505
|
+
groundset = reversed(range(len(l)))
|
|
1506
|
+
|
|
1507
|
+
# Go through until we've considered every number between 1 and len(l)
|
|
1508
|
+
for i in groundset:
|
|
1509
|
+
if not l[i]:
|
|
1510
|
+
continue
|
|
1511
|
+
cycle_first = i + 1
|
|
1512
|
+
cycle = [cycle_first]
|
|
1513
|
+
l[i], next_val = False, l[i]
|
|
1514
|
+
s = self._colors[i]
|
|
1515
|
+
add_neg = True
|
|
1516
|
+
while next_val != cycle_first:
|
|
1517
|
+
cycle.append(s * next_val)
|
|
1518
|
+
s *= self._colors[next_val - 1]
|
|
1519
|
+
l[next_val - 1], next_val = False, l[next_val - 1]
|
|
1520
|
+
if s != 1:
|
|
1521
|
+
cycle.extend([-e for e in cycle])
|
|
1522
|
+
add_neg = False
|
|
1523
|
+
|
|
1524
|
+
# Add the cycle to the list of cycles
|
|
1525
|
+
if singletons or len(cycle) > 1:
|
|
1526
|
+
cycles.append(tuple(cycle))
|
|
1527
|
+
if negative_cycles and add_neg:
|
|
1528
|
+
cycles.append(tuple([-e for e in cycle]))
|
|
1529
|
+
|
|
1530
|
+
return cycles
|
|
1531
|
+
|
|
1532
|
+
def cycle_type(self):
|
|
1533
|
+
r"""
|
|
1534
|
+
Return a pair of partitions of ``len(self)`` corresponding to the
|
|
1535
|
+
signed cycle type of ``self``.
|
|
1536
|
+
|
|
1537
|
+
A *cycle* is a tuple `C = (c_0, \ldots, c_{k-1})` with
|
|
1538
|
+
`\pi(c_i) = c_{i+1}` for `0 \leq i < k` and `\pi(c_{k-1}) = c_0`.
|
|
1539
|
+
If `C` is a cycle, `\overline{C} = (-c_0, \ldots, -c_{k-1})` is
|
|
1540
|
+
also a cycle. A cycle is *negative*, if `C = \overline{C}` up
|
|
1541
|
+
to cyclic reordering. In this case, `k` is necessarily even
|
|
1542
|
+
and the length of `C` is `k/2`. A *positive cycle* is a pair
|
|
1543
|
+
`C \overline{C}`, its length is `k`.
|
|
1544
|
+
|
|
1545
|
+
Let `\alpha` be the partition whose parts are the lengths of the
|
|
1546
|
+
positive cycles and let `\beta` be the partition whose parts are
|
|
1547
|
+
the lengths of the negative cycles. Then `(\alpha, \beta)` is
|
|
1548
|
+
the cycle type of `\pi`.
|
|
1549
|
+
|
|
1550
|
+
EXAMPLES::
|
|
1551
|
+
|
|
1552
|
+
sage: G = SignedPermutations(7)
|
|
1553
|
+
sage: pi = G([2, -1, 4, -6, -5, -3, 7])
|
|
1554
|
+
sage: pi.cycle_type()
|
|
1555
|
+
([3, 1], [2, 1])
|
|
1556
|
+
|
|
1557
|
+
sage: G = SignedPermutations(5)
|
|
1558
|
+
sage: all(pi.cycle_type().size() == 5 for pi in G)
|
|
1559
|
+
True
|
|
1560
|
+
sage: set(pi.cycle_type() for pi in G) == set(PartitionTuples(2, 5)) # needs sage.libs.flint
|
|
1561
|
+
True
|
|
1562
|
+
"""
|
|
1563
|
+
cycles = self.to_cycles(negative_cycles=False)
|
|
1564
|
+
pos_cycles = []
|
|
1565
|
+
neg_cycles = []
|
|
1566
|
+
for C in cycles:
|
|
1567
|
+
if (not len(C) % 2) and C[0] == -C[len(C)//2]:
|
|
1568
|
+
neg_cycles.append(C)
|
|
1569
|
+
else:
|
|
1570
|
+
pos_cycles.append(C)
|
|
1571
|
+
pos_type = [len(C) for C in pos_cycles]
|
|
1572
|
+
pos_type.sort(reverse=True)
|
|
1573
|
+
neg_type = [len(C) // 2 for C in neg_cycles]
|
|
1574
|
+
neg_type.sort(reverse=True)
|
|
1575
|
+
PT = PartitionTuples(2, self.parent()._n)
|
|
1576
|
+
return PT([pos_type, neg_type])
|
|
1577
|
+
|
|
1578
|
+
def order(self):
|
|
1579
|
+
"""
|
|
1580
|
+
Return the multiplicative order of the signed permutation.
|
|
1581
|
+
|
|
1582
|
+
EXAMPLES::
|
|
1583
|
+
|
|
1584
|
+
sage: pi = SignedPermutations(7)([2,-1,4,-6,-5,-3,7])
|
|
1585
|
+
sage: pi.to_cycles(singletons=False)
|
|
1586
|
+
[(1, 2, -1, -2), (3, 4, -6), (-3, -4, 6), (5, -5)]
|
|
1587
|
+
sage: pi.order()
|
|
1588
|
+
12
|
|
1589
|
+
"""
|
|
1590
|
+
return lcm(len(c) for c in self.to_cycles(singletons=False, negative_cycles=False))
|
|
1591
|
+
|
|
1592
|
+
|
|
1593
|
+
class SignedPermutations(ColoredPermutations):
|
|
1594
|
+
r"""
|
|
1595
|
+
Group of signed permutations.
|
|
1596
|
+
|
|
1597
|
+
The group of signed permutations is also known as the hyperoctahedral
|
|
1598
|
+
group, the Coxeter group of type `B_n`, and the 2-colored permutation
|
|
1599
|
+
group. Thus it can be constructed as the wreath product `S_2 \wr S_n`.
|
|
1600
|
+
|
|
1601
|
+
EXAMPLES::
|
|
1602
|
+
|
|
1603
|
+
sage: S = SignedPermutations(4)
|
|
1604
|
+
sage: s1,s2,s3,s4 = S.group_generators()
|
|
1605
|
+
sage: x = s4*s1*s2*s3*s4; x
|
|
1606
|
+
[-4, 1, 2, -3]
|
|
1607
|
+
sage: x^4 == S.one()
|
|
1608
|
+
True
|
|
1609
|
+
|
|
1610
|
+
This is a finite Coxeter group of type `B_n`::
|
|
1611
|
+
|
|
1612
|
+
sage: S.canonical_representation() # needs sage.graphs sage.modules sage.rings.number_field
|
|
1613
|
+
Finite Coxeter group over Number Field in a with defining polynomial x^2 - 2
|
|
1614
|
+
with a = 1.414213562373095? with Coxeter matrix:
|
|
1615
|
+
[1 3 2 2]
|
|
1616
|
+
[3 1 3 2]
|
|
1617
|
+
[2 3 1 4]
|
|
1618
|
+
[2 2 4 1]
|
|
1619
|
+
sage: S.long_element()
|
|
1620
|
+
[-1, -2, -3, -4]
|
|
1621
|
+
sage: S.long_element().reduced_word()
|
|
1622
|
+
[1, 2, 1, 3, 2, 1, 4, 3, 2, 1, 4, 3, 2, 4, 3, 4]
|
|
1623
|
+
|
|
1624
|
+
We can also go between the 2-colored permutation group::
|
|
1625
|
+
|
|
1626
|
+
sage: C = ColoredPermutations(2, 3)
|
|
1627
|
+
sage: S = SignedPermutations(3)
|
|
1628
|
+
sage: S.an_element()
|
|
1629
|
+
[-3, 1, 2]
|
|
1630
|
+
sage: C(S.an_element())
|
|
1631
|
+
[[1, 0, 0], [3, 1, 2]]
|
|
1632
|
+
sage: S(C(S.an_element())) == S.an_element()
|
|
1633
|
+
True
|
|
1634
|
+
sage: S(C.an_element())
|
|
1635
|
+
[-3, 1, 2]
|
|
1636
|
+
|
|
1637
|
+
There is also the natural lift from permutations::
|
|
1638
|
+
|
|
1639
|
+
sage: P = Permutations(3)
|
|
1640
|
+
sage: x = S(P.an_element()); x
|
|
1641
|
+
[3, 1, 2]
|
|
1642
|
+
sage: x.parent()
|
|
1643
|
+
Signed permutations of 3
|
|
1644
|
+
|
|
1645
|
+
REFERENCES:
|
|
1646
|
+
|
|
1647
|
+
- :wikipedia:`Hyperoctahedral_group`
|
|
1648
|
+
"""
|
|
1649
|
+
def __init__(self, n):
|
|
1650
|
+
"""
|
|
1651
|
+
Initialize ``self``.
|
|
1652
|
+
|
|
1653
|
+
EXAMPLES::
|
|
1654
|
+
|
|
1655
|
+
sage: S = SignedPermutations(4)
|
|
1656
|
+
sage: TestSuite(S).run()
|
|
1657
|
+
"""
|
|
1658
|
+
ColoredPermutations.__init__(self, 2, n)
|
|
1659
|
+
|
|
1660
|
+
def _repr_(self):
|
|
1661
|
+
"""
|
|
1662
|
+
Return a string representation of ``self``.
|
|
1663
|
+
|
|
1664
|
+
EXAMPLES::
|
|
1665
|
+
|
|
1666
|
+
sage: SignedPermutations(4)
|
|
1667
|
+
Signed permutations of 4
|
|
1668
|
+
"""
|
|
1669
|
+
return "Signed permutations of {}".format(self._n)
|
|
1670
|
+
|
|
1671
|
+
@cached_method
|
|
1672
|
+
def one(self):
|
|
1673
|
+
"""
|
|
1674
|
+
Return the identity element of ``self``.
|
|
1675
|
+
|
|
1676
|
+
EXAMPLES::
|
|
1677
|
+
|
|
1678
|
+
sage: S = SignedPermutations(4)
|
|
1679
|
+
sage: S.one()
|
|
1680
|
+
[1, 2, 3, 4]
|
|
1681
|
+
"""
|
|
1682
|
+
return self.element_class(self, [ZZ.one()] * self._n,
|
|
1683
|
+
self._P.identity())
|
|
1684
|
+
|
|
1685
|
+
def random_element(self):
|
|
1686
|
+
"""
|
|
1687
|
+
Return an element drawn uniformly at random.
|
|
1688
|
+
|
|
1689
|
+
EXAMPLES::
|
|
1690
|
+
|
|
1691
|
+
sage: C = SignedPermutations(7)
|
|
1692
|
+
sage: s = C.random_element(); s # random
|
|
1693
|
+
[7, 6, -4, -5, 2, 3, -1]
|
|
1694
|
+
sage: s in C
|
|
1695
|
+
True
|
|
1696
|
+
"""
|
|
1697
|
+
return self.element_class(self,
|
|
1698
|
+
[choice([ZZ.one(), -ZZ.one()])
|
|
1699
|
+
for _ in range(self._n)],
|
|
1700
|
+
self._P.random_element())
|
|
1701
|
+
|
|
1702
|
+
def simple_reflection(self, i):
|
|
1703
|
+
r"""
|
|
1704
|
+
Return the ``i``-th simple reflection of ``self``.
|
|
1705
|
+
|
|
1706
|
+
EXAMPLES::
|
|
1707
|
+
|
|
1708
|
+
sage: S = SignedPermutations(4)
|
|
1709
|
+
sage: S.simple_reflection(1)
|
|
1710
|
+
[2, 1, 3, 4]
|
|
1711
|
+
sage: S.simple_reflection(4)
|
|
1712
|
+
[1, 2, 3, -4]
|
|
1713
|
+
"""
|
|
1714
|
+
if i not in self.index_set():
|
|
1715
|
+
raise ValueError("i must be in the index set")
|
|
1716
|
+
if i < self._n:
|
|
1717
|
+
p = list(range(1, self._n + 1))
|
|
1718
|
+
p[i - 1] = i + 1
|
|
1719
|
+
p[i] = i
|
|
1720
|
+
return self.element_class(self, [ZZ.one()] * self._n, self._P(p))
|
|
1721
|
+
temp = [ZZ.one()] * self._n
|
|
1722
|
+
temp[-1] = -ZZ.one()
|
|
1723
|
+
return self.element_class(self, temp, self._P.identity())
|
|
1724
|
+
|
|
1725
|
+
def _element_constructor_(self, x):
|
|
1726
|
+
"""
|
|
1727
|
+
Construct an element of ``self`` from ``x``.
|
|
1728
|
+
|
|
1729
|
+
TESTS::
|
|
1730
|
+
|
|
1731
|
+
sage: S = SignedPermutations(3)
|
|
1732
|
+
sage: x = S([(+1,1), (-1,3), (-1,2)]); x
|
|
1733
|
+
[1, -3, -2]
|
|
1734
|
+
sage: x == S([[+1,-1,-1], [1,3,2]])
|
|
1735
|
+
True
|
|
1736
|
+
sage: x == S([1, -3, -2])
|
|
1737
|
+
True
|
|
1738
|
+
|
|
1739
|
+
sage: S = SignedPermutations(0)
|
|
1740
|
+
sage: S([]) == list(S)[0]
|
|
1741
|
+
True
|
|
1742
|
+
|
|
1743
|
+
sage: T = SignedPermutation(range(1,4))
|
|
1744
|
+
sage: SignedPermutations(3)(T)
|
|
1745
|
+
[1, 2, 3]
|
|
1746
|
+
"""
|
|
1747
|
+
if isinstance(x, self.element_class) and x.parent() is self:
|
|
1748
|
+
return self
|
|
1749
|
+
x = list(x)
|
|
1750
|
+
if x and isinstance(x[0], tuple):
|
|
1751
|
+
c = []
|
|
1752
|
+
p = []
|
|
1753
|
+
for k in x:
|
|
1754
|
+
if len(k) != 2:
|
|
1755
|
+
raise ValueError("input must be pairs (sign, element)")
|
|
1756
|
+
if k[0] != 1 and k[0] != -1:
|
|
1757
|
+
raise ValueError("the sign must be +1 or -1")
|
|
1758
|
+
c.append(ZZ(k[0]))
|
|
1759
|
+
p.append(k[1])
|
|
1760
|
+
return self.element_class(self, c, self._P(p))
|
|
1761
|
+
|
|
1762
|
+
if len(x) == self._n:
|
|
1763
|
+
c = []
|
|
1764
|
+
p = []
|
|
1765
|
+
one = ZZ.one()
|
|
1766
|
+
for v in x:
|
|
1767
|
+
if v > 0:
|
|
1768
|
+
c.append(one)
|
|
1769
|
+
p.append(v)
|
|
1770
|
+
else:
|
|
1771
|
+
c.append(-one)
|
|
1772
|
+
p.append(-v)
|
|
1773
|
+
return self.element_class(self, c, self._P(p))
|
|
1774
|
+
|
|
1775
|
+
if len(x) != 2:
|
|
1776
|
+
raise ValueError("input must be a pair of a list of signs and a permutation")
|
|
1777
|
+
if any(s != 1 and s != -1 for s in x[0]):
|
|
1778
|
+
raise ValueError("the sign must be +1 or -1")
|
|
1779
|
+
return self.element_class(self, [ZZ(v) for v in x[0]], self._P(x[1]))
|
|
1780
|
+
|
|
1781
|
+
def __iter__(self):
|
|
1782
|
+
"""
|
|
1783
|
+
Iterate over ``self``.
|
|
1784
|
+
|
|
1785
|
+
EXAMPLES::
|
|
1786
|
+
|
|
1787
|
+
sage: S = SignedPermutations(2)
|
|
1788
|
+
sage: [x for x in S]
|
|
1789
|
+
[[1, 2], [1, -2], [-1, 2], [-1, -2],
|
|
1790
|
+
[2, 1], [2, -1], [-2, 1], [-2, -1]]
|
|
1791
|
+
"""
|
|
1792
|
+
pmone = [ZZ.one(), -ZZ.one()]
|
|
1793
|
+
for p in self._P:
|
|
1794
|
+
for c in itertools.product(pmone, repeat=self._n):
|
|
1795
|
+
yield self.element_class(self, c, p)
|
|
1796
|
+
|
|
1797
|
+
def _coerce_map_from_(self, C):
|
|
1798
|
+
"""
|
|
1799
|
+
Return a coerce map from ``C`` if it exists and ``None`` otherwise.
|
|
1800
|
+
|
|
1801
|
+
EXAMPLES::
|
|
1802
|
+
|
|
1803
|
+
sage: C = ColoredPermutations(2, 3)
|
|
1804
|
+
sage: S = SignedPermutations(3)
|
|
1805
|
+
sage: S.has_coerce_map_from(C)
|
|
1806
|
+
True
|
|
1807
|
+
|
|
1808
|
+
sage: C = ColoredPermutations(4, 3)
|
|
1809
|
+
sage: S.has_coerce_map_from(C)
|
|
1810
|
+
False
|
|
1811
|
+
|
|
1812
|
+
sage: P = Permutations(3)
|
|
1813
|
+
sage: C.has_coerce_map_from(P)
|
|
1814
|
+
True
|
|
1815
|
+
sage: P = Permutations(4)
|
|
1816
|
+
sage: C.has_coerce_map_from(P)
|
|
1817
|
+
False
|
|
1818
|
+
"""
|
|
1819
|
+
if isinstance(C, Permutations) and C.n == self._n:
|
|
1820
|
+
return lambda P, x: P.element_class(P, [1] * P._n, x)
|
|
1821
|
+
if isinstance(C, ColoredPermutations) and C._n == self._n and C._m == 2:
|
|
1822
|
+
return lambda P, x: P.element_class(P,
|
|
1823
|
+
[1 if v == 0 else -1
|
|
1824
|
+
for v in x._colors],
|
|
1825
|
+
x._perm)
|
|
1826
|
+
return super()._coerce_map_from_(C)
|
|
1827
|
+
|
|
1828
|
+
def tabloid_module(self, shape, base_ring):
|
|
1829
|
+
"""
|
|
1830
|
+
Return the tabloid module of ``self`` with shape ``shape``
|
|
1831
|
+
over ``base_ring``.
|
|
1832
|
+
|
|
1833
|
+
EXAMPLES::
|
|
1834
|
+
|
|
1835
|
+
sage: # needs sage.groups sage.modules
|
|
1836
|
+
sage: B4 = SignedPermutations(4)
|
|
1837
|
+
sage: TM = B4.tabloid_module([[2,1], [1]], GF(2))
|
|
1838
|
+
sage: TM.dimension()
|
|
1839
|
+
96
|
|
1840
|
+
sage: TM = B4.tabloid_module([[], [3,1]], GF(2))
|
|
1841
|
+
sage: TM.dimension()
|
|
1842
|
+
4
|
|
1843
|
+
"""
|
|
1844
|
+
from .colored_permutations_representations import TabloidModule
|
|
1845
|
+
return TabloidModule(self, base_ring, shape)
|
|
1846
|
+
|
|
1847
|
+
def specht_module(self, shape, base_ring):
|
|
1848
|
+
"""
|
|
1849
|
+
Return the Specht module of ``self`` with shape ``shape``
|
|
1850
|
+
over ``base_ring``.
|
|
1851
|
+
|
|
1852
|
+
EXAMPLES::
|
|
1853
|
+
|
|
1854
|
+
sage: # needs sage.groups sage.modules
|
|
1855
|
+
sage: B4 = SignedPermutations(4)
|
|
1856
|
+
sage: SM = B4.specht_module([[2,1], [1]], GF(2))
|
|
1857
|
+
sage: SM.dimension()
|
|
1858
|
+
8
|
|
1859
|
+
sage: SM = B4.specht_module([[], [3,1]], GF(2))
|
|
1860
|
+
sage: SM.dimension()
|
|
1861
|
+
3
|
|
1862
|
+
"""
|
|
1863
|
+
return self.tabloid_module(shape, base_ring).specht_module()
|
|
1864
|
+
|
|
1865
|
+
def simple_module(self, shape, base_ring):
|
|
1866
|
+
"""
|
|
1867
|
+
Return the simple module of ``self`` with shape ``shape``
|
|
1868
|
+
over ``base_ring``.
|
|
1869
|
+
|
|
1870
|
+
EXAMPLES::
|
|
1871
|
+
|
|
1872
|
+
sage: # needs sage.groups sage.modules
|
|
1873
|
+
sage: B4 = SignedPermutations(4)
|
|
1874
|
+
sage: L = B4.simple_module([[], [3,1]], GF(2))
|
|
1875
|
+
sage: L.dimension()
|
|
1876
|
+
2
|
|
1877
|
+
"""
|
|
1878
|
+
return self.specht_module(shape, base_ring).simple_module()
|
|
1879
|
+
|
|
1880
|
+
def long_element(self, index_set=None):
|
|
1881
|
+
"""
|
|
1882
|
+
Return the longest element of ``self``, or of the
|
|
1883
|
+
parabolic subgroup corresponding to the given ``index_set``.
|
|
1884
|
+
|
|
1885
|
+
INPUT:
|
|
1886
|
+
|
|
1887
|
+
- ``index_set`` -- (optional) a subset (as a list or iterable)
|
|
1888
|
+
of the nodes of the indexing set
|
|
1889
|
+
|
|
1890
|
+
EXAMPLES::
|
|
1891
|
+
|
|
1892
|
+
sage: S = SignedPermutations(4)
|
|
1893
|
+
sage: S.long_element()
|
|
1894
|
+
[-1, -2, -3, -4]
|
|
1895
|
+
|
|
1896
|
+
TESTS:
|
|
1897
|
+
|
|
1898
|
+
Check that this is the element of maximal length (:issue:`25200`)::
|
|
1899
|
+
|
|
1900
|
+
sage: S = SignedPermutations(4)
|
|
1901
|
+
sage: S.long_element().length() == max(x.length() for x in S)
|
|
1902
|
+
True
|
|
1903
|
+
sage: all(SignedPermutations(n).long_element().length() == n^2
|
|
1904
|
+
....: for n in range(2,10))
|
|
1905
|
+
True
|
|
1906
|
+
"""
|
|
1907
|
+
if index_set is not None:
|
|
1908
|
+
return super().long_element()
|
|
1909
|
+
return self.element_class(self, [-ZZ.one()] * self._n, self._P.one())
|
|
1910
|
+
|
|
1911
|
+
def conjugacy_class(self, g):
|
|
1912
|
+
r"""
|
|
1913
|
+
Return the conjugacy class of ``g`` in ``self``.
|
|
1914
|
+
|
|
1915
|
+
INPUT:
|
|
1916
|
+
|
|
1917
|
+
- ``g`` -- a pair of partitions or an element of ``self``
|
|
1918
|
+
|
|
1919
|
+
EXAMPLES::
|
|
1920
|
+
|
|
1921
|
+
sage: # needs sage.groups sage.modules
|
|
1922
|
+
sage: G = SignedPermutations(5)
|
|
1923
|
+
sage: g = G([1,-3,2,5,-4])
|
|
1924
|
+
sage: G.conjugacy_class(g)
|
|
1925
|
+
Conjugacy class of cycle type ([1], [2, 2]) in Signed permutations of 5
|
|
1926
|
+
sage: G.conjugacy_class([[2,1], [1,1]])
|
|
1927
|
+
Conjugacy class of cycle type ([2, 1], [1, 1]) in Signed permutations of 5
|
|
1928
|
+
"""
|
|
1929
|
+
from .colored_permutations_representations import SignedPermutationGroupConjugacyClass
|
|
1930
|
+
return SignedPermutationGroupConjugacyClass(self, g)
|
|
1931
|
+
|
|
1932
|
+
def conjugacy_classes(self):
|
|
1933
|
+
"""
|
|
1934
|
+
Return the list of conjugacy classes of ``self``.
|
|
1935
|
+
|
|
1936
|
+
EXAMPLES::
|
|
1937
|
+
|
|
1938
|
+
sage: # needs sage.libs.flint
|
|
1939
|
+
sage: G = SignedPermutations(3)
|
|
1940
|
+
sage: G.conjugacy_classes()
|
|
1941
|
+
[Conjugacy class of cycle type ([3], []) in Signed permutations of 3,
|
|
1942
|
+
Conjugacy class of cycle type ([2, 1], []) in Signed permutations of 3,
|
|
1943
|
+
Conjugacy class of cycle type ([1, 1, 1], []) in Signed permutations of 3,
|
|
1944
|
+
Conjugacy class of cycle type ([2], [1]) in Signed permutations of 3,
|
|
1945
|
+
Conjugacy class of cycle type ([1, 1], [1]) in Signed permutations of 3,
|
|
1946
|
+
Conjugacy class of cycle type ([1], [2]) in Signed permutations of 3,
|
|
1947
|
+
Conjugacy class of cycle type ([1], [1, 1]) in Signed permutations of 3,
|
|
1948
|
+
Conjugacy class of cycle type ([], [3]) in Signed permutations of 3,
|
|
1949
|
+
Conjugacy class of cycle type ([], [2, 1]) in Signed permutations of 3,
|
|
1950
|
+
Conjugacy class of cycle type ([], [1, 1, 1]) in Signed permutations of 3]
|
|
1951
|
+
"""
|
|
1952
|
+
return [self.conjugacy_class(la) for la in PartitionTuples(2, self._n)]
|
|
1953
|
+
|
|
1954
|
+
def conjugacy_class_representative(self, nu):
|
|
1955
|
+
r"""
|
|
1956
|
+
Return a permutation with (signed) cycle type ``nu``.
|
|
1957
|
+
|
|
1958
|
+
EXAMPLES::
|
|
1959
|
+
|
|
1960
|
+
sage: G = SignedPermutations(4)
|
|
1961
|
+
sage: for nu in PartitionTuples(2, 4): # needs sage.libs.flint
|
|
1962
|
+
....: print(nu, G.conjugacy_class_representative(nu))
|
|
1963
|
+
....: assert nu == G.conjugacy_class_representative(nu).cycle_type(), nu
|
|
1964
|
+
([4], []) [2, 3, 4, 1]
|
|
1965
|
+
([3, 1], []) [2, 3, 1, 4]
|
|
1966
|
+
([2, 2], []) [2, 1, 4, 3]
|
|
1967
|
+
([2, 1, 1], []) [2, 1, 3, 4]
|
|
1968
|
+
([1, 1, 1, 1], []) [1, 2, 3, 4]
|
|
1969
|
+
([3], [1]) [2, 3, 1, -4]
|
|
1970
|
+
([2, 1], [1]) [2, 1, 3, -4]
|
|
1971
|
+
([1, 1, 1], [1]) [1, 2, 3, -4]
|
|
1972
|
+
([2], [2]) [2, 1, 4, -3]
|
|
1973
|
+
([2], [1, 1]) [2, 1, -3, -4]
|
|
1974
|
+
([1, 1], [2]) [1, 2, 4, -3]
|
|
1975
|
+
([1, 1], [1, 1]) [1, 2, -3, -4]
|
|
1976
|
+
([1], [3]) [1, 3, 4, -2]
|
|
1977
|
+
([1], [2, 1]) [1, 3, -2, -4]
|
|
1978
|
+
([1], [1, 1, 1]) [1, -2, -3, -4]
|
|
1979
|
+
([], [4]) [2, 3, 4, -1]
|
|
1980
|
+
([], [3, 1]) [2, 3, -1, -4]
|
|
1981
|
+
([], [2, 2]) [2, -1, 4, -3]
|
|
1982
|
+
([], [2, 1, 1]) [2, -1, -3, -4]
|
|
1983
|
+
([], [1, 1, 1, 1]) [-1, -2, -3, -4]
|
|
1984
|
+
|
|
1985
|
+
TESTS::
|
|
1986
|
+
|
|
1987
|
+
sage: all(nu == SignedPermutations(n).conjugacy_class_representative(nu).cycle_type() # needs sage.libs.flint
|
|
1988
|
+
....: for n in range(1, 6) for nu in PartitionTuples(2, n))
|
|
1989
|
+
True
|
|
1990
|
+
"""
|
|
1991
|
+
nu = PartitionTuples(2, self._n)(nu)
|
|
1992
|
+
la, mu = nu
|
|
1993
|
+
cyc = []
|
|
1994
|
+
cnt = 0
|
|
1995
|
+
|
|
1996
|
+
for i in la:
|
|
1997
|
+
cyc += [tuple(range(cnt+1, cnt+i+1))] + [tuple(range(-cnt-1, -cnt-i-1, -1))]
|
|
1998
|
+
cnt += i
|
|
1999
|
+
for i in mu:
|
|
2000
|
+
cyc += [tuple(range(cnt+1, cnt+i+1)) + tuple(range(-cnt-1, -cnt-i-1, -1))]
|
|
2001
|
+
cnt += i
|
|
2002
|
+
|
|
2003
|
+
p = [None] * self._n
|
|
2004
|
+
for c in cyc:
|
|
2005
|
+
for i in range(len(c)-1):
|
|
2006
|
+
if c[i] > 0:
|
|
2007
|
+
p[c[i]-1] = c[i+1]
|
|
2008
|
+
if c[-1] > 0:
|
|
2009
|
+
p[c[-1]-1] = c[0]
|
|
2010
|
+
|
|
2011
|
+
return self(p)
|
|
2012
|
+
|
|
2013
|
+
Element = SignedPermutation
|
|
2014
|
+
|
|
2015
|
+
# TODO: Make this a subgroup
|
|
2016
|
+
# class EvenSignedPermutations(SignedPermutations):
|
|
2017
|
+
# """
|
|
2018
|
+
# Group of even signed permutations.
|
|
2019
|
+
# """
|
|
2020
|
+
# def _repr_(self):
|
|
2021
|
+
# """
|
|
2022
|
+
# Return a string representation of ``self``.
|
|
2023
|
+
# """
|
|
2024
|
+
# return "Even signed permutations of {}".format(self._n)
|
|
2025
|
+
#
|
|
2026
|
+
# def __iter__(self):
|
|
2027
|
+
# """
|
|
2028
|
+
# Iterate over ``self``.
|
|
2029
|
+
# """
|
|
2030
|
+
# for s in SignedPermutations.__iter__(self):
|
|
2031
|
+
# total = 0
|
|
2032
|
+
# for pm in s._colors:
|
|
2033
|
+
# if pm == -1:
|
|
2034
|
+
# total += 1
|
|
2035
|
+
#
|
|
2036
|
+
# if total % 2 == 0:
|
|
2037
|
+
# yield s
|
|
2038
|
+
|
|
2039
|
+
# Conjugacy classes, representation theory moved to colored_permutations_representations.py
|