passagemath-combinat 10.6.42__cp314-cp314t-win_amd64.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/DELVEWHEEL +2 -0
- passagemath_combinat-10.6.42.dist-info/METADATA +160 -0
- passagemath_combinat-10.6.42.dist-info/RECORD +401 -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-10-3a5f019e2510aeaad918cab2b57a689d.dll +0 -0
- passagemath_combinat.libs/libsymmetrica-3-7dcf900932804d0df5fd0919b4668720.dll +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 +44 -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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +0 -0
- sage/combinat/debruijn_sequence.pyx +355 -0
- sage/combinat/decorated_permutation.py +270 -0
- sage/combinat/degree_sequences.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +0 -0
- sage/combinat/expnums.pyx +148 -0
- sage/combinat/fast_vector_partitions.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +0 -0
- sage/combinat/words/word_char.pyx +847 -0
- sage/combinat/words/word_datatypes.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +0 -0
- sage/sat/solvers/satsolver.pxd +3 -0
- sage/sat/solvers/satsolver.pyx +405 -0
|
@@ -0,0 +1,1054 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
"""
|
|
3
|
+
Automatic Semigroups
|
|
4
|
+
|
|
5
|
+
Semigroups defined by generators living in an ambient semigroup and represented by an automaton.
|
|
6
|
+
|
|
7
|
+
AUTHORS:
|
|
8
|
+
|
|
9
|
+
- Nicolas M. Thiéry
|
|
10
|
+
- Aladin Virmaux
|
|
11
|
+
"""
|
|
12
|
+
# ****************************************************************************
|
|
13
|
+
# Copyright (C) 2010-2015 Nicolas M. Thiéry
|
|
14
|
+
#
|
|
15
|
+
# This program is free software: you can redistribute it and/or modify
|
|
16
|
+
# it under the terms of the GNU General Public License as published by
|
|
17
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
18
|
+
# (at your option) any later version.
|
|
19
|
+
# https://www.gnu.org/licenses/
|
|
20
|
+
# ****************************************************************************
|
|
21
|
+
|
|
22
|
+
import operator
|
|
23
|
+
from sage.misc.cachefunc import cached_method
|
|
24
|
+
from sage.categories.semigroups import Semigroups
|
|
25
|
+
from sage.categories.sets_cat import Sets
|
|
26
|
+
from sage.categories.monoids import Monoids
|
|
27
|
+
from sage.categories.groups import Groups
|
|
28
|
+
from sage.structure.parent import Parent
|
|
29
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
30
|
+
from sage.structure.element_wrapper import ElementWrapper
|
|
31
|
+
from sage.sets.family import Family
|
|
32
|
+
from sage.rings.integer import Integer
|
|
33
|
+
from sage.cpython.getattr import raw_getattr
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class AutomaticSemigroup(UniqueRepresentation, Parent):
|
|
37
|
+
r"""
|
|
38
|
+
Semigroups defined by generators living in an ambient semigroup.
|
|
39
|
+
|
|
40
|
+
This implementation lazily constructs all the elements of the
|
|
41
|
+
semigroup, and the right Cayley graph relations between them, and
|
|
42
|
+
uses the latter as an automaton.
|
|
43
|
+
|
|
44
|
+
EXAMPLES::
|
|
45
|
+
|
|
46
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
47
|
+
sage: R = IntegerModRing(12)
|
|
48
|
+
sage: M = AutomaticSemigroup(Family({1: R(3), 2: R(5)}), one=R.one())
|
|
49
|
+
sage: M in Monoids()
|
|
50
|
+
True
|
|
51
|
+
sage: M.one()
|
|
52
|
+
1
|
|
53
|
+
sage: M.one() in M
|
|
54
|
+
True
|
|
55
|
+
sage: g = M._generators; g
|
|
56
|
+
Finite family {1: 3, 2: 5}
|
|
57
|
+
sage: g[1]*g[2]
|
|
58
|
+
3
|
|
59
|
+
sage: M.some_elements()
|
|
60
|
+
[1, 3, 5, 9]
|
|
61
|
+
|
|
62
|
+
sage: M.list()
|
|
63
|
+
[1, 3, 5, 9]
|
|
64
|
+
|
|
65
|
+
sage: M.idempotents()
|
|
66
|
+
[1, 9]
|
|
67
|
+
|
|
68
|
+
As can be seen above, elements are represented by default the
|
|
69
|
+
corresponding element in the ambient monoid. One can also represent
|
|
70
|
+
the elements by their reduced word::
|
|
71
|
+
|
|
72
|
+
sage: M.repr_element_method("reduced_word")
|
|
73
|
+
sage: M.list()
|
|
74
|
+
[[], [1], [2], [1, 1]]
|
|
75
|
+
|
|
76
|
+
In case the reduced word has not yet been calculated, the element
|
|
77
|
+
will be represented by the corresponding element in the ambient
|
|
78
|
+
monoid::
|
|
79
|
+
|
|
80
|
+
sage: R = IntegerModRing(13)
|
|
81
|
+
sage: N = AutomaticSemigroup(Family({1: R(3), 2: R(5)}), one=R.one())
|
|
82
|
+
sage: N.repr_element_method("reduced_word")
|
|
83
|
+
sage: n = N.an_element()
|
|
84
|
+
sage: n
|
|
85
|
+
[1]
|
|
86
|
+
sage: n*n
|
|
87
|
+
9
|
|
88
|
+
|
|
89
|
+
Calling :meth:`construct`, :meth:`cardinality`, or :meth:`list`,
|
|
90
|
+
or iterating through the monoid will trigger its full construction
|
|
91
|
+
and, as a side effect, compute all the reduced words. The order of
|
|
92
|
+
the elements, and the induced choice of reduced word is currently
|
|
93
|
+
length-lexicographic (i.e. the chosen reduced word is of minimal
|
|
94
|
+
length, and then minimal lexicographically w.r.t. the order of the
|
|
95
|
+
indices of the generators)::
|
|
96
|
+
|
|
97
|
+
sage: M.cardinality()
|
|
98
|
+
4
|
|
99
|
+
sage: M.list()
|
|
100
|
+
[[], [1], [2], [1, 1]]
|
|
101
|
+
sage: g = M._generators
|
|
102
|
+
|
|
103
|
+
sage: g[1]*g[2]
|
|
104
|
+
[1]
|
|
105
|
+
|
|
106
|
+
sage: g[1].transition(1)
|
|
107
|
+
[1, 1]
|
|
108
|
+
sage: g[1] * g[1]
|
|
109
|
+
[1, 1]
|
|
110
|
+
sage: g[1] * g[1] * g[1]
|
|
111
|
+
[1]
|
|
112
|
+
sage: g[1].transition(2)
|
|
113
|
+
[1]
|
|
114
|
+
sage: g[1] * g[2]
|
|
115
|
+
[1]
|
|
116
|
+
|
|
117
|
+
sage: [ x.lift() for x in M.list() ]
|
|
118
|
+
[1, 3, 5, 9]
|
|
119
|
+
|
|
120
|
+
sage: # needs sage.graphs
|
|
121
|
+
sage: G = M.cayley_graph(side='twosided'); G
|
|
122
|
+
Looped multi-digraph on 4 vertices
|
|
123
|
+
sage: G.edges(sort=True, key=str)
|
|
124
|
+
[([1, 1], [1, 1], (2, 'left')),
|
|
125
|
+
([1, 1], [1, 1], (2, 'right')),
|
|
126
|
+
([1, 1], [1], (1, 'left')),
|
|
127
|
+
([1, 1], [1], (1, 'right')),
|
|
128
|
+
([1], [1, 1], (1, 'left')),
|
|
129
|
+
([1], [1, 1], (1, 'right')),
|
|
130
|
+
([1], [1], (2, 'left')),
|
|
131
|
+
([1], [1], (2, 'right')),
|
|
132
|
+
([2], [1], (1, 'left')),
|
|
133
|
+
([2], [1], (1, 'right')),
|
|
134
|
+
([2], [], (2, 'left')),
|
|
135
|
+
([2], [], (2, 'right')),
|
|
136
|
+
([], [1], (1, 'left')),
|
|
137
|
+
([], [1], (1, 'right')),
|
|
138
|
+
([], [2], (2, 'left')),
|
|
139
|
+
([], [2], (2, 'right'))]
|
|
140
|
+
sage: list(map(sorted, M.j_classes()))
|
|
141
|
+
[[[1], [1, 1]], [[], [2]]]
|
|
142
|
+
sage: M.j_classes_of_idempotents()
|
|
143
|
+
[[[1, 1]], [[]]]
|
|
144
|
+
sage: M.j_transversal_of_idempotents()
|
|
145
|
+
[[1, 1], []]
|
|
146
|
+
|
|
147
|
+
sage: list(map(attrcall('pseudo_order'), M.list())) # needs sage.graphs
|
|
148
|
+
[[1, 0], [3, 1], [2, 0], [2, 1]]
|
|
149
|
+
|
|
150
|
+
We can also use it to get submonoids from groups. We check that in the
|
|
151
|
+
symmetric group, a transposition and a long cycle generate the whole group::
|
|
152
|
+
|
|
153
|
+
sage: # needs sage.groups
|
|
154
|
+
sage: G5 = SymmetricGroup(5)
|
|
155
|
+
sage: N = AutomaticSemigroup(Family({1: G5([2,1,3,4,5]), 2: G5([2,3,4,5,1])}),
|
|
156
|
+
....: one=G5.one())
|
|
157
|
+
sage: N.repr_element_method("reduced_word")
|
|
158
|
+
sage: N.cardinality() == G5.cardinality()
|
|
159
|
+
True
|
|
160
|
+
sage: N.retract(G5((1,4,3,5,2)))
|
|
161
|
+
[1, 2, 1, 2, 2, 1, 2, 1, 2, 2]
|
|
162
|
+
sage: N.from_reduced_word([1, 2, 1, 2, 2, 1, 2, 1, 2, 2]).lift()
|
|
163
|
+
(1,4,3,5,2)
|
|
164
|
+
|
|
165
|
+
We can also create a semigroup of matrices, where we define the
|
|
166
|
+
multiplication as matrix multiplication::
|
|
167
|
+
|
|
168
|
+
sage: # needs sage.modules
|
|
169
|
+
sage: M1 = matrix([[0,0,1],[1,0,0],[0,1,0]])
|
|
170
|
+
sage: M2 = matrix([[0,0,0],[1,1,0],[0,0,1]])
|
|
171
|
+
sage: M1.set_immutable()
|
|
172
|
+
sage: M2.set_immutable()
|
|
173
|
+
sage: def prod_m(x, y):
|
|
174
|
+
....: z=x*y
|
|
175
|
+
....: z.set_immutable()
|
|
176
|
+
....: return z
|
|
177
|
+
sage: Mon = AutomaticSemigroup([M1,M2], mul=prod_m,
|
|
178
|
+
....: category=Monoids().Finite().Subobjects())
|
|
179
|
+
sage: Mon.cardinality()
|
|
180
|
+
24
|
|
181
|
+
sage: C = Mon.cayley_graph() # needs sage.graphs
|
|
182
|
+
sage: C.is_directed_acyclic() # needs sage.graphs
|
|
183
|
+
False
|
|
184
|
+
|
|
185
|
+
Let us construct and play with the 0-Hecke Monoid::
|
|
186
|
+
|
|
187
|
+
sage: # needs sage.graphs sage.modules
|
|
188
|
+
sage: W = WeylGroup(['A',4]); W.rename('W')
|
|
189
|
+
sage: ambient_monoid = FiniteSetMaps(W, action='right')
|
|
190
|
+
sage: pi = W.simple_projections(length_increasing=True).map(ambient_monoid)
|
|
191
|
+
sage: M = AutomaticSemigroup(pi, one=ambient_monoid.one()); M
|
|
192
|
+
A submonoid of (Maps from W to itself) with 4 generators
|
|
193
|
+
sage: M.repr_element_method("reduced_word")
|
|
194
|
+
sage: sorted(M._elements_set, key=str)
|
|
195
|
+
[[1], [2], [3], [4], []]
|
|
196
|
+
sage: M.construct(n=10)
|
|
197
|
+
sage: sorted(M._elements_set, key=str)
|
|
198
|
+
[[1, 2], [1, 3], [1, 4], [1], [2, 1], [2, 3], [2], [3], [4], []]
|
|
199
|
+
sage: elt = M.from_reduced_word([3,1,2,4,2])
|
|
200
|
+
sage: M.construct(up_to=elt)
|
|
201
|
+
sage: len(M._elements_set)
|
|
202
|
+
36
|
|
203
|
+
sage: M.cardinality()
|
|
204
|
+
120
|
|
205
|
+
|
|
206
|
+
We check that the 0-Hecke monoid is `J`-trivial and contains `2^4`
|
|
207
|
+
idempotents::
|
|
208
|
+
|
|
209
|
+
sage: len(M.idempotents()) # needs sage.graphs sage.modules
|
|
210
|
+
16
|
|
211
|
+
sage: all(len(j) == 1 for j in M.j_classes()) # needs sage.graphs sage.modules
|
|
212
|
+
True
|
|
213
|
+
|
|
214
|
+
TESTS::
|
|
215
|
+
|
|
216
|
+
sage: (g[1]).__hash__() == (g[1]*g[1]*g[1]).__hash__()
|
|
217
|
+
True
|
|
218
|
+
sage: g[1] == g[1]*g[1]*g[1]
|
|
219
|
+
True
|
|
220
|
+
sage: M.__class__ # needs sage.graphs sage.modules
|
|
221
|
+
<class 'sage.monoids.automatic_semigroup.AutomaticMonoid_with_category'>
|
|
222
|
+
sage: TestSuite(M).run() # needs sage.graphs sage.modules
|
|
223
|
+
|
|
224
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
225
|
+
sage: R = IntegerModRing(34)
|
|
226
|
+
sage: M = AutomaticSemigroup(Family({1: R(3), 2: R(7)}), one=R.one())
|
|
227
|
+
sage: M[3] in M
|
|
228
|
+
True
|
|
229
|
+
|
|
230
|
+
We need to pass in the ambient monoid to ``__init__`` to guarantee
|
|
231
|
+
:class:`UniqueRepresentation` works properly::
|
|
232
|
+
|
|
233
|
+
sage: R1 = IntegerModRing(12)
|
|
234
|
+
sage: R2 = IntegerModRing(16)
|
|
235
|
+
sage: M1 = AutomaticSemigroup(Family({1: R1(3), 2: R1(5)}), one=R1.one())
|
|
236
|
+
sage: M2 = AutomaticSemigroup(Family({1: R2(3), 2: R2(5)}), one=R2.one())
|
|
237
|
+
sage: M1 is M2
|
|
238
|
+
False
|
|
239
|
+
|
|
240
|
+
.. NOTE::
|
|
241
|
+
|
|
242
|
+
Unlike what the name of the class may suggest, this currently
|
|
243
|
+
implements only a subclass of automatic semigroups;
|
|
244
|
+
essentially the finite ones. See :wikipedia:`Automatic_semigroup`.
|
|
245
|
+
|
|
246
|
+
.. WARNING::
|
|
247
|
+
|
|
248
|
+
:class:`AutomaticSemigroup` is designed primarily for finite
|
|
249
|
+
semigroups. This property is not checked automatically (this
|
|
250
|
+
would be too costly, if not undecidable). Use with care for an
|
|
251
|
+
infinite semigroup, as certain features may require
|
|
252
|
+
constructing all of it::
|
|
253
|
+
|
|
254
|
+
sage: M = AutomaticSemigroup([2], category = Monoids().Subobjects()); M
|
|
255
|
+
A submonoid of (Integer Ring) with 1 generators
|
|
256
|
+
sage: M.retract(2)
|
|
257
|
+
2
|
|
258
|
+
sage: M.retract(3) # not tested: runs forever trying to find 3
|
|
259
|
+
"""
|
|
260
|
+
@staticmethod
|
|
261
|
+
def __classcall_private__(cls, generators, ambient=None, one=None, mul=operator.mul, category=None):
|
|
262
|
+
"""
|
|
263
|
+
Parse and straighten the arguments; figure out the category.
|
|
264
|
+
|
|
265
|
+
TESTS::
|
|
266
|
+
|
|
267
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
268
|
+
sage: R = IntegerModRing(9)
|
|
269
|
+
sage: M = AutomaticSemigroup((), one=R.one())
|
|
270
|
+
sage: M.ambient() == R
|
|
271
|
+
True
|
|
272
|
+
sage: AutomaticSemigroup((0,)).category()
|
|
273
|
+
Join of Category of finitely generated semigroups
|
|
274
|
+
and Category of subquotients of semigroups
|
|
275
|
+
and Category of commutative magmas
|
|
276
|
+
and Category of subobjects of sets
|
|
277
|
+
sage: AutomaticSemigroup((0,), one=1).category()
|
|
278
|
+
Join of Category of subquotients of monoids and
|
|
279
|
+
Category of commutative monoids and
|
|
280
|
+
Category of finitely generated semigroups and
|
|
281
|
+
Category of subobjects of sets
|
|
282
|
+
sage: AutomaticSemigroup((0,), one=0).category()
|
|
283
|
+
Join of Category of commutative monoids and
|
|
284
|
+
Category of finitely generated semigroups and
|
|
285
|
+
Category of subquotients of semigroups and
|
|
286
|
+
Category of subobjects of sets
|
|
287
|
+
sage: AutomaticSemigroup((0,), mul=operator.add).category()
|
|
288
|
+
Join of Category of semigroups and Category of subobjects of sets
|
|
289
|
+
sage: AutomaticSemigroup((0,), one=0, mul=operator.add).category()
|
|
290
|
+
Join of Category of monoids and Category of subobjects of sets
|
|
291
|
+
|
|
292
|
+
sage: S5 = SymmetricGroup(5) # needs sage.groups
|
|
293
|
+
sage: AutomaticSemigroup([S5((1,2))]).category() # needs sage.groups
|
|
294
|
+
Join of Category of finite groups and
|
|
295
|
+
Category of subquotients of monoids and
|
|
296
|
+
Category of finite finitely generated semigroups and
|
|
297
|
+
Category of subquotients of finite sets and
|
|
298
|
+
Category of subobjects of sets
|
|
299
|
+
|
|
300
|
+
.. TODO::
|
|
301
|
+
|
|
302
|
+
One would want a subsemigroup of a group to be
|
|
303
|
+
automatically a subgroup (in ``Groups().Subobjects()``).
|
|
304
|
+
"""
|
|
305
|
+
generators = Family(generators)
|
|
306
|
+
if ambient is None:
|
|
307
|
+
# Try to guess the ambient semigroup from the generators or the unit
|
|
308
|
+
if generators.cardinality() > 0:
|
|
309
|
+
ambient = generators.first().parent()
|
|
310
|
+
elif one is not None:
|
|
311
|
+
ambient = one.parent()
|
|
312
|
+
else:
|
|
313
|
+
raise ValueError("AutomaticSemigroup requires at least one generator or `one` to determine the ambient space")
|
|
314
|
+
elif ambient not in Sets():
|
|
315
|
+
raise ValueError("ambient (=%s) should be a set" % ambient)
|
|
316
|
+
|
|
317
|
+
# if mul is not operator.mul and category.is_subcategory(Monoids().Subobjects()) error
|
|
318
|
+
|
|
319
|
+
if one is None and category is not None:
|
|
320
|
+
if category.is_subcategory(Monoids().Subobjects()):
|
|
321
|
+
one = ambient.one()
|
|
322
|
+
elif category.is_subcategory(Monoids()):
|
|
323
|
+
raise ValueError("For a monoid which is just a subsemigroup, the unit should be specified")
|
|
324
|
+
|
|
325
|
+
# Try to determine the most specific category
|
|
326
|
+
# This logic should be in the categories
|
|
327
|
+
if mul is operator.mul:
|
|
328
|
+
default_category = Semigroups().FinitelyGenerated()
|
|
329
|
+
if one is not None and one == ambient.one():
|
|
330
|
+
default_category = default_category.Unital()
|
|
331
|
+
if ambient in Semigroups().Commutative():
|
|
332
|
+
default_category = default_category.Commutative()
|
|
333
|
+
if ambient in Groups().Finite():
|
|
334
|
+
default_category = default_category & Groups()
|
|
335
|
+
else:
|
|
336
|
+
default_category = Sets()
|
|
337
|
+
|
|
338
|
+
if ambient in Sets().Finite():
|
|
339
|
+
default_category = default_category.Finite()
|
|
340
|
+
|
|
341
|
+
default_category = default_category.Subobjects() & Semigroups()
|
|
342
|
+
if one is not None:
|
|
343
|
+
default_category = default_category.Unital()
|
|
344
|
+
cls = AutomaticMonoid
|
|
345
|
+
|
|
346
|
+
if category is None:
|
|
347
|
+
category = default_category
|
|
348
|
+
else:
|
|
349
|
+
category = default_category & category
|
|
350
|
+
return super().__classcall__(cls, generators, ambient=ambient,
|
|
351
|
+
one=one, mul=mul, category=category)
|
|
352
|
+
|
|
353
|
+
def __init__(self, generators, ambient, one, mul, category):
|
|
354
|
+
"""
|
|
355
|
+
Initialize this semigroup.
|
|
356
|
+
|
|
357
|
+
TESTS::
|
|
358
|
+
|
|
359
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
360
|
+
sage: R = IntegerModRing(21)
|
|
361
|
+
sage: M = AutomaticSemigroup(Family(()), one=R.one())
|
|
362
|
+
sage: M.ambient() == R
|
|
363
|
+
True
|
|
364
|
+
sage: M = AutomaticSemigroup(Family(()))
|
|
365
|
+
Traceback (most recent call last):
|
|
366
|
+
...
|
|
367
|
+
ValueError: AutomaticSemigroup requires at least one generator or `one` to determine the ambient space
|
|
368
|
+
"""
|
|
369
|
+
Parent.__init__(self, category=category)
|
|
370
|
+
|
|
371
|
+
# Attributes for the multiplicative structure
|
|
372
|
+
self._ambient = ambient
|
|
373
|
+
self._mul = mul
|
|
374
|
+
if one is not None:
|
|
375
|
+
self._one = self._retract(one)
|
|
376
|
+
self._one._reduced_word = []
|
|
377
|
+
self._generators_in_ambient = generators
|
|
378
|
+
self._generators = generators.map(self._retract)
|
|
379
|
+
for e in self._generators:
|
|
380
|
+
e._reduced_word = [self._generators.inverse_family()[e]]
|
|
381
|
+
|
|
382
|
+
# Attributes for the lazy construction of the elements
|
|
383
|
+
self._constructed = False
|
|
384
|
+
self._done = 0
|
|
385
|
+
if one is not None and self._one not in self._generators:
|
|
386
|
+
self._elements = [self._one] + list(self._generators)
|
|
387
|
+
else:
|
|
388
|
+
self._elements = list(self._generators)
|
|
389
|
+
self._elements_set = set(self._elements)
|
|
390
|
+
self._iter = self.__init__iter()
|
|
391
|
+
|
|
392
|
+
# Customization
|
|
393
|
+
self._repr_element_method = "ambient"
|
|
394
|
+
|
|
395
|
+
def _repr_(self):
|
|
396
|
+
"""
|
|
397
|
+
Return the string representation for ``self``.
|
|
398
|
+
|
|
399
|
+
EXAMPLES::
|
|
400
|
+
|
|
401
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
402
|
+
sage: R = IntegerModRing(12)
|
|
403
|
+
sage: AutomaticSemigroup(Family({1: R(3), 2: R(5)}), one=R.one())
|
|
404
|
+
A submonoid of (Ring of integers modulo 12) with 2 generators
|
|
405
|
+
sage: AutomaticSemigroup(Family({1: R(3), 2: R(5)}))
|
|
406
|
+
A subsemigroup of (Ring of integers modulo 12) with 2 generators
|
|
407
|
+
|
|
408
|
+
sage: AutomaticSemigroup(Family({1: R(3), 2: R(5)}), mul=operator.add)
|
|
409
|
+
A semigroup with 2 generators
|
|
410
|
+
sage: AutomaticSemigroup(Family({1: R(3), 2: R(5)}), mul=operator.add, one=R.zero())
|
|
411
|
+
A semigroup with 2 generators
|
|
412
|
+
|
|
413
|
+
sage: S5 = SymmetricGroup(5); S5.rename('S5') # needs sage.groups
|
|
414
|
+
sage: AutomaticSemigroup(Family({1: S5((1,2))}), # needs sage.groups
|
|
415
|
+
....: category=Groups().Finite().Subobjects())
|
|
416
|
+
A subgroup of (S5) with 1 generators
|
|
417
|
+
"""
|
|
418
|
+
categories = [Groups(), Monoids(), Semigroups()]
|
|
419
|
+
for category in categories:
|
|
420
|
+
if self in category:
|
|
421
|
+
typ = "A " + category._repr_object_names()[:-1]
|
|
422
|
+
for category in [Groups(), Monoids(), Semigroups()]:
|
|
423
|
+
if self.ambient() in category and self in category.Subobjects():
|
|
424
|
+
typ = "A sub" + category._repr_object_names()[:-1]
|
|
425
|
+
break
|
|
426
|
+
if self._mul is operator.mul:
|
|
427
|
+
of = " of (%s)" % self.ambient()
|
|
428
|
+
else:
|
|
429
|
+
of = ""
|
|
430
|
+
|
|
431
|
+
return f"{typ}{of} with {len(self._generators)} generators"
|
|
432
|
+
|
|
433
|
+
def repr_element_method(self, style='ambient'):
|
|
434
|
+
"""
|
|
435
|
+
Set the representation of the elements of the monoid.
|
|
436
|
+
|
|
437
|
+
INPUT:
|
|
438
|
+
|
|
439
|
+
- ``style`` -- "ambient" or "reduced_word"
|
|
440
|
+
|
|
441
|
+
EXAMPLES::
|
|
442
|
+
|
|
443
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
444
|
+
sage: R = IntegerModRing(17)
|
|
445
|
+
sage: M = AutomaticSemigroup(Family({1: R(3), 2: R(5)}), one=R.one())
|
|
446
|
+
sage: M.list()
|
|
447
|
+
[1, 3, 5, 9, 15, 8, 10, 11, 7, 6, 13, 16, 4, 14, 12, 2]
|
|
448
|
+
sage: M.repr_element_method("reduced_word")
|
|
449
|
+
sage: M.list()
|
|
450
|
+
[[], [1], [2], [1, 1], [1, 2], [2, 2], [1, 1, 1], [1, 1, 2], [1, 2, 2],
|
|
451
|
+
[2, 2, 2], [1, 1, 1, 1], [1, 1, 1, 2], [1, 1, 2, 2], [1, 1, 1, 1, 2],
|
|
452
|
+
[1, 1, 1, 2, 2], [1, 1, 1, 1, 2, 2]]
|
|
453
|
+
"""
|
|
454
|
+
self._repr_element_method = style
|
|
455
|
+
|
|
456
|
+
def an_element(self):
|
|
457
|
+
"""
|
|
458
|
+
Return the first given generator of ``self``.
|
|
459
|
+
|
|
460
|
+
EXAMPLES::
|
|
461
|
+
|
|
462
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
463
|
+
sage: R = IntegerModRing(16)
|
|
464
|
+
sage: M = AutomaticSemigroup(Family({1: R(3), 2: R(5)}), one=R.one())
|
|
465
|
+
sage: M.an_element()
|
|
466
|
+
3
|
|
467
|
+
"""
|
|
468
|
+
return self._generators.first()
|
|
469
|
+
|
|
470
|
+
def ambient(self):
|
|
471
|
+
"""
|
|
472
|
+
Return the ambient semigroup of ``self``.
|
|
473
|
+
|
|
474
|
+
EXAMPLES::
|
|
475
|
+
|
|
476
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
477
|
+
sage: R = IntegerModRing(12)
|
|
478
|
+
sage: M = AutomaticSemigroup(Family({1: R(3), 2: R(5)}), one=R.one())
|
|
479
|
+
sage: M.ambient()
|
|
480
|
+
Ring of integers modulo 12
|
|
481
|
+
|
|
482
|
+
sage: # needs sage.modules
|
|
483
|
+
sage: M1 = matrix([[0,0,1],[1,0,0],[0,1,0]])
|
|
484
|
+
sage: M2 = matrix([[0,0,0],[1,1,0],[0,0,1]])
|
|
485
|
+
sage: M1.set_immutable()
|
|
486
|
+
sage: M2.set_immutable()
|
|
487
|
+
sage: def prod_m(x, y):
|
|
488
|
+
....: z=x*y
|
|
489
|
+
....: z.set_immutable()
|
|
490
|
+
....: return z
|
|
491
|
+
sage: Mon = AutomaticSemigroup([M1,M2], mul=prod_m)
|
|
492
|
+
sage: Mon.ambient()
|
|
493
|
+
Full MatrixSpace of 3 by 3 dense matrices over Integer Ring
|
|
494
|
+
"""
|
|
495
|
+
return self._ambient
|
|
496
|
+
|
|
497
|
+
def retract(self, ambient_element, check=True):
|
|
498
|
+
"""
|
|
499
|
+
Retract an element of the ambient semigroup into ``self``.
|
|
500
|
+
|
|
501
|
+
EXAMPLES::
|
|
502
|
+
|
|
503
|
+
sage: # needs sage.groups
|
|
504
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
505
|
+
sage: S5 = SymmetricGroup(5); S5.rename('S5')
|
|
506
|
+
sage: M = AutomaticSemigroup(Family({1:S5((1,2)), 2:S5((1,2,3,4))}),
|
|
507
|
+
....: one=S5.one())
|
|
508
|
+
sage: m = M.retract(S5((3,1))); m
|
|
509
|
+
(1,3)
|
|
510
|
+
sage: m.parent() is M
|
|
511
|
+
True
|
|
512
|
+
sage: M.retract(S5((4,5)), check=False)
|
|
513
|
+
(4,5)
|
|
514
|
+
sage: M.retract(S5((4,5)))
|
|
515
|
+
Traceback (most recent call last):
|
|
516
|
+
...
|
|
517
|
+
ValueError: (4,5) not in A subgroup of (S5) with 2 generators
|
|
518
|
+
|
|
519
|
+
TESTS::
|
|
520
|
+
|
|
521
|
+
sage: len(M._retract.cache.keys()) # needs sage.groups
|
|
522
|
+
24
|
|
523
|
+
"""
|
|
524
|
+
element = self._retract(ambient_element)
|
|
525
|
+
if check:
|
|
526
|
+
self.construct(up_to=ambient_element)
|
|
527
|
+
if element not in self._elements_set:
|
|
528
|
+
cache = self._retract.cache
|
|
529
|
+
del cache[((ambient_element,), ())]
|
|
530
|
+
raise ValueError(f"{ambient_element} not in {self}")
|
|
531
|
+
return element
|
|
532
|
+
|
|
533
|
+
@cached_method
|
|
534
|
+
def _retract(self, ambient_element):
|
|
535
|
+
r"""
|
|
536
|
+
Retract an element of the ambient semigroup into ``self``.
|
|
537
|
+
|
|
538
|
+
This is an internal method which does not check that
|
|
539
|
+
``ambient_element`` is indeed in this semigroup.
|
|
540
|
+
|
|
541
|
+
EXAMPLES::
|
|
542
|
+
|
|
543
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
544
|
+
sage: S5 = SymmetricGroup(5) # needs sage.groups
|
|
545
|
+
sage: S4 = AutomaticSemigroup(Family({1:S5((1,2)), 2:S5((1,2,3,4))}), # needs sage.groups
|
|
546
|
+
....: one=S5.one())
|
|
547
|
+
sage: S4._retract(S5((3,1))) # needs sage.groups
|
|
548
|
+
(1,3)
|
|
549
|
+
|
|
550
|
+
No check is done::
|
|
551
|
+
|
|
552
|
+
sage: S4._retract(S5((4,5))) # needs sage.groups
|
|
553
|
+
(4,5)
|
|
554
|
+
"""
|
|
555
|
+
return self.element_class(self, ambient_element)
|
|
556
|
+
|
|
557
|
+
def lift(self, x):
|
|
558
|
+
"""
|
|
559
|
+
Lift an element of ``self`` into its ambient space.
|
|
560
|
+
|
|
561
|
+
EXAMPLES::
|
|
562
|
+
|
|
563
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
564
|
+
sage: R = IntegerModRing(15)
|
|
565
|
+
sage: M = AutomaticSemigroup(Family({1: R(3), 2: R(5)}), one=R.one())
|
|
566
|
+
sage: a = M.an_element()
|
|
567
|
+
sage: a.lift() in R
|
|
568
|
+
True
|
|
569
|
+
sage: a.lift()
|
|
570
|
+
3
|
|
571
|
+
sage: [m.lift() for m in M]
|
|
572
|
+
[1, 3, 5, 9, 0, 10, 12, 6]
|
|
573
|
+
"""
|
|
574
|
+
assert x in self
|
|
575
|
+
return x.lift()
|
|
576
|
+
|
|
577
|
+
def semigroup_generators(self):
|
|
578
|
+
"""
|
|
579
|
+
Return the family of generators of ``self``.
|
|
580
|
+
|
|
581
|
+
EXAMPLES::
|
|
582
|
+
|
|
583
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
584
|
+
sage: R = IntegerModRing(28)
|
|
585
|
+
sage: M = AutomaticSemigroup(Family({1: R(3), 2: R(5)}))
|
|
586
|
+
sage: M.semigroup_generators()
|
|
587
|
+
Finite family {1: 3, 2: 5}
|
|
588
|
+
"""
|
|
589
|
+
return self._generators
|
|
590
|
+
gens = semigroup_generators
|
|
591
|
+
|
|
592
|
+
def __init__iter(self):
|
|
593
|
+
"""
|
|
594
|
+
Iterator on the elements of ``self``.
|
|
595
|
+
|
|
596
|
+
EXAMPLES::
|
|
597
|
+
|
|
598
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
599
|
+
sage: R = IntegerModRing(18)
|
|
600
|
+
sage: M = AutomaticSemigroup([R(3), R(5)], one=R.one())
|
|
601
|
+
sage: M.repr_element_method("reduced_word")
|
|
602
|
+
sage: next(M.__iter__())
|
|
603
|
+
[]
|
|
604
|
+
sage: list(M)
|
|
605
|
+
[[], [0], [1], [0, 0], [0, 1], [1, 1], [1, 1, 1], [1, 1, 1, 1], [1,
|
|
606
|
+
1, 1, 1, 1]]
|
|
607
|
+
|
|
608
|
+
ALGORITHM:
|
|
609
|
+
|
|
610
|
+
Breadth first search on the elements generated by the generators.
|
|
611
|
+
The algorithm stops when all branches have been fully explored.
|
|
612
|
+
"""
|
|
613
|
+
while self._done < len(self._elements):
|
|
614
|
+
x = self._elements[self._done]
|
|
615
|
+
for i in self._generators.keys():
|
|
616
|
+
y = x.transition(i)
|
|
617
|
+
if y in self._elements_set:
|
|
618
|
+
continue
|
|
619
|
+
self._elements.append(y)
|
|
620
|
+
self._elements_set.add(y)
|
|
621
|
+
y._reduced_word = x.reduced_word() + [i]
|
|
622
|
+
yield y
|
|
623
|
+
self._done += 1
|
|
624
|
+
self._constructed = True
|
|
625
|
+
|
|
626
|
+
def __iter__(self):
|
|
627
|
+
"""
|
|
628
|
+
Return iterator over elements of the semigroup.
|
|
629
|
+
|
|
630
|
+
EXAMPLES::
|
|
631
|
+
|
|
632
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
633
|
+
sage: R = IntegerModRing(5)
|
|
634
|
+
sage: M = AutomaticSemigroup([R(3), R(4)], one=R.one())
|
|
635
|
+
sage: I = M.__iter__()
|
|
636
|
+
sage: next(I)
|
|
637
|
+
1
|
|
638
|
+
sage: M.list()
|
|
639
|
+
[1, 3, 4, 2]
|
|
640
|
+
sage: next(I)
|
|
641
|
+
3
|
|
642
|
+
"""
|
|
643
|
+
if self._constructed:
|
|
644
|
+
return iter(self._elements)
|
|
645
|
+
else:
|
|
646
|
+
return self._iter_concurrent()
|
|
647
|
+
|
|
648
|
+
def _iter_concurrent(self):
|
|
649
|
+
"""
|
|
650
|
+
We need to take special care since several iterators may run
|
|
651
|
+
concurrently.
|
|
652
|
+
|
|
653
|
+
TESTS::
|
|
654
|
+
|
|
655
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
656
|
+
sage: R = IntegerModRing(11)
|
|
657
|
+
sage: M = AutomaticSemigroup(Family({1: R(3), 2: R(5)}), one=R.one())
|
|
658
|
+
sage: f = iter(M) # indirect doctest
|
|
659
|
+
sage: g = iter(M)
|
|
660
|
+
sage: next(f), next(g)
|
|
661
|
+
(1, 1)
|
|
662
|
+
sage: next(g), next(f)
|
|
663
|
+
(3, 3)
|
|
664
|
+
sage: next(f), next(g)
|
|
665
|
+
(5, 5)
|
|
666
|
+
sage: next(f), next(g)
|
|
667
|
+
(9, 9)
|
|
668
|
+
sage: h = iter(M)
|
|
669
|
+
sage: next(h), next(h), next(h), next(h), next(h)
|
|
670
|
+
(1, 3, 5, 9, 4)
|
|
671
|
+
sage: next(f), next(g)
|
|
672
|
+
(4, 4)
|
|
673
|
+
sage: M._constructed
|
|
674
|
+
False
|
|
675
|
+
sage: next(f)
|
|
676
|
+
Traceback (most recent call last):
|
|
677
|
+
...
|
|
678
|
+
StopIteration
|
|
679
|
+
sage: next(g)
|
|
680
|
+
Traceback (most recent call last):
|
|
681
|
+
...
|
|
682
|
+
StopIteration
|
|
683
|
+
sage: next(h)
|
|
684
|
+
Traceback (most recent call last):
|
|
685
|
+
...
|
|
686
|
+
StopIteration
|
|
687
|
+
sage: M._constructed
|
|
688
|
+
True
|
|
689
|
+
"""
|
|
690
|
+
i = 0
|
|
691
|
+
# self._elements is never empty; so we are sure
|
|
692
|
+
for x in self._elements:
|
|
693
|
+
yield x
|
|
694
|
+
# some other iterator/ method of the semigroup may have
|
|
695
|
+
# been called before we move on to the next line
|
|
696
|
+
i += 1
|
|
697
|
+
if i == len(self._elements) and not self._constructed:
|
|
698
|
+
try:
|
|
699
|
+
next(self._iter)
|
|
700
|
+
except StopIteration:
|
|
701
|
+
# Don't allow StopIteration to bubble up from generator
|
|
702
|
+
# see PEP-479
|
|
703
|
+
break
|
|
704
|
+
|
|
705
|
+
def cardinality(self):
|
|
706
|
+
"""
|
|
707
|
+
Return the cardinality of ``self``.
|
|
708
|
+
|
|
709
|
+
EXAMPLES::
|
|
710
|
+
|
|
711
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
712
|
+
sage: R = IntegerModRing(12)
|
|
713
|
+
sage: M = AutomaticSemigroup(Family({1: R(3), 2: R(5)}), one=R.one())
|
|
714
|
+
sage: M.cardinality()
|
|
715
|
+
4
|
|
716
|
+
|
|
717
|
+
TESTS::
|
|
718
|
+
|
|
719
|
+
sage: assert isinstance(M.cardinality(), Integer) # This did fail at some point
|
|
720
|
+
"""
|
|
721
|
+
if not self._constructed:
|
|
722
|
+
self.construct()
|
|
723
|
+
return Integer(len(self._elements))
|
|
724
|
+
|
|
725
|
+
def list(self):
|
|
726
|
+
"""
|
|
727
|
+
Return the list of elements of ``self``.
|
|
728
|
+
|
|
729
|
+
EXAMPLES::
|
|
730
|
+
|
|
731
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
732
|
+
sage: R = IntegerModRing(12)
|
|
733
|
+
sage: M = AutomaticSemigroup(Family({1: R(3), 2: R(5)}), one=R.one())
|
|
734
|
+
sage: M.repr_element_method("reduced_word")
|
|
735
|
+
sage: M.list()
|
|
736
|
+
[[], [1], [2], [1, 1]]
|
|
737
|
+
|
|
738
|
+
TESTS::
|
|
739
|
+
|
|
740
|
+
sage: assert isinstance(M.cardinality(), Integer) # This did fail at some point
|
|
741
|
+
"""
|
|
742
|
+
if not self._constructed:
|
|
743
|
+
self.construct()
|
|
744
|
+
return list(self._elements)
|
|
745
|
+
|
|
746
|
+
def product(self, x, y):
|
|
747
|
+
"""
|
|
748
|
+
Return the product of two elements in ``self``. It is done by
|
|
749
|
+
retracting the multiplication in the ambient semigroup.
|
|
750
|
+
|
|
751
|
+
EXAMPLES::
|
|
752
|
+
|
|
753
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
754
|
+
sage: R = IntegerModRing(12)
|
|
755
|
+
sage: M = AutomaticSemigroup(Family({1: R(3), 2: R(5)}), one=R.one())
|
|
756
|
+
sage: a = M[1]
|
|
757
|
+
sage: b = M[2]
|
|
758
|
+
sage: a*b
|
|
759
|
+
[1]
|
|
760
|
+
"""
|
|
761
|
+
assert x in self
|
|
762
|
+
assert y in self
|
|
763
|
+
red = y._reduced_word
|
|
764
|
+
if red is None:
|
|
765
|
+
return self._retract(self._mul(x.lift(), y.lift()))
|
|
766
|
+
|
|
767
|
+
for i in red:
|
|
768
|
+
x = x.transition(i)
|
|
769
|
+
return x
|
|
770
|
+
|
|
771
|
+
def from_reduced_word(self, l):
|
|
772
|
+
"""
|
|
773
|
+
Return the element of ``self`` obtained from the reduced word ``l``.
|
|
774
|
+
|
|
775
|
+
INPUT:
|
|
776
|
+
|
|
777
|
+
- ``l`` -- list of indices of the generators
|
|
778
|
+
|
|
779
|
+
.. NOTE::
|
|
780
|
+
|
|
781
|
+
We do not save the given reduced word ``l`` as an attribute of the
|
|
782
|
+
element, as some elements above in the branches may have not been
|
|
783
|
+
explored by the iterator yet.
|
|
784
|
+
|
|
785
|
+
EXAMPLES::
|
|
786
|
+
|
|
787
|
+
sage: # needs sage.groups
|
|
788
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
789
|
+
sage: G4 = SymmetricGroup(4)
|
|
790
|
+
sage: M = AutomaticSemigroup(Family({1:G4((1,2)), 2:G4((1,2,3,4))}),
|
|
791
|
+
....: one=G4.one())
|
|
792
|
+
sage: M.from_reduced_word([2, 1, 2, 2, 1]).lift()
|
|
793
|
+
(1,3)
|
|
794
|
+
sage: M.from_reduced_word([2, 1, 2, 2, 1]) == M.retract(G4((3,1)))
|
|
795
|
+
True
|
|
796
|
+
"""
|
|
797
|
+
result = self.one()
|
|
798
|
+
for i in l:
|
|
799
|
+
result = result.transition(i)
|
|
800
|
+
return result
|
|
801
|
+
|
|
802
|
+
def construct(self, up_to=None, n=None):
|
|
803
|
+
"""
|
|
804
|
+
Construct the elements of ``self``.
|
|
805
|
+
|
|
806
|
+
INPUT:
|
|
807
|
+
|
|
808
|
+
- ``up_to`` -- an element of ``self`` or of the ambient semigroup
|
|
809
|
+
|
|
810
|
+
- ``n`` -- integer or ``None`` (default: ``None``)
|
|
811
|
+
|
|
812
|
+
This construct all the elements of this semigroup, their
|
|
813
|
+
reduced words, and the right Cayley graph. If `n` is
|
|
814
|
+
specified, only the `n` first elements of the semigroup are
|
|
815
|
+
constructed. If ``element`` is specified, only the elements up
|
|
816
|
+
to ``ambient_element`` are constructed.
|
|
817
|
+
|
|
818
|
+
EXAMPLES::
|
|
819
|
+
|
|
820
|
+
sage: # needs sage.groups sage.modules
|
|
821
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
822
|
+
sage: W = WeylGroup(['A',3]); W.rename('W')
|
|
823
|
+
sage: ambient_monoid = FiniteSetMaps(W, action='right')
|
|
824
|
+
sage: pi = W.simple_projections(length_increasing=True).map(ambient_monoid)
|
|
825
|
+
sage: M = AutomaticSemigroup(pi, one=ambient_monoid.one()); M
|
|
826
|
+
A submonoid of (Maps from W to itself) with 3 generators
|
|
827
|
+
sage: M.repr_element_method("reduced_word")
|
|
828
|
+
sage: sorted(M._elements_set, key=str)
|
|
829
|
+
[[1], [2], [3], []]
|
|
830
|
+
sage: elt = M.from_reduced_word([2,3,1,2])
|
|
831
|
+
sage: M.construct(up_to=elt)
|
|
832
|
+
sage: len(M._elements_set)
|
|
833
|
+
19
|
|
834
|
+
sage: M.cardinality()
|
|
835
|
+
24
|
|
836
|
+
"""
|
|
837
|
+
if self._constructed:
|
|
838
|
+
return
|
|
839
|
+
if n is not None:
|
|
840
|
+
if up_to is not None:
|
|
841
|
+
raise ValueError("Only one of the options `up_to` or `n` should be specified")
|
|
842
|
+
i = len(self._elements)
|
|
843
|
+
while i < n and not self._constructed:
|
|
844
|
+
next(self._iter)
|
|
845
|
+
i += 1
|
|
846
|
+
elif up_to is not None:
|
|
847
|
+
if up_to.parent() is self._ambient:
|
|
848
|
+
up_to = self._retract(up_to)
|
|
849
|
+
# TODO: remove up_to from the cache if not found at the end
|
|
850
|
+
if up_to in self._elements_set:
|
|
851
|
+
return
|
|
852
|
+
for x in self._iter:
|
|
853
|
+
if up_to is x:
|
|
854
|
+
return
|
|
855
|
+
else:
|
|
856
|
+
for x in self._iter:
|
|
857
|
+
pass
|
|
858
|
+
|
|
859
|
+
class Element(ElementWrapper):
|
|
860
|
+
|
|
861
|
+
def __init__(self, ambient_element, parent):
|
|
862
|
+
"""
|
|
863
|
+
TESTS::
|
|
864
|
+
|
|
865
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
866
|
+
sage: R = IntegerModRing(21)
|
|
867
|
+
sage: M = AutomaticSemigroup(Family([2]))
|
|
868
|
+
sage: m = M(2); m
|
|
869
|
+
2
|
|
870
|
+
sage: type(m)
|
|
871
|
+
<class 'sage.monoids.automatic_semigroup.AutomaticSemigroup_with_category.element_class'>
|
|
872
|
+
"""
|
|
873
|
+
ElementWrapper.__init__(self, ambient_element, parent)
|
|
874
|
+
self._reduced_word = None
|
|
875
|
+
|
|
876
|
+
def reduced_word(self):
|
|
877
|
+
r"""
|
|
878
|
+
Return the length-lexicographic shortest word of ``self``.
|
|
879
|
+
|
|
880
|
+
OUTPUT: list of indexes of the generators
|
|
881
|
+
|
|
882
|
+
Obtaining the reduced word requires having constructed the
|
|
883
|
+
Cayley graph of the semigroup up to ``self``. If this is
|
|
884
|
+
not the case, an error is raised.
|
|
885
|
+
|
|
886
|
+
EXAMPLES::
|
|
887
|
+
|
|
888
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
889
|
+
sage: R = IntegerModRing(15)
|
|
890
|
+
sage: M = AutomaticSemigroup(Family({1: R(3), 2: R(5)}), one=R.one())
|
|
891
|
+
sage: M.construct()
|
|
892
|
+
sage: for m in M: print((m, m.reduced_word()))
|
|
893
|
+
(1, [])
|
|
894
|
+
(3, [1])
|
|
895
|
+
(5, [2])
|
|
896
|
+
(9, [1, 1])
|
|
897
|
+
(0, [1, 2])
|
|
898
|
+
(10, [2, 2])
|
|
899
|
+
(12, [1, 1, 1])
|
|
900
|
+
(6, [1, 1, 1, 1])
|
|
901
|
+
|
|
902
|
+
TESTS:
|
|
903
|
+
|
|
904
|
+
We check that :issue:`19631` is fixed::
|
|
905
|
+
|
|
906
|
+
sage: R = IntegerModRing(101)
|
|
907
|
+
sage: M = AutomaticSemigroup(Family({1: R(3), 2: R(5)}), one=R.one())
|
|
908
|
+
sage: e = M.from_reduced_word([1, 1, 1, 2, 2, 2])
|
|
909
|
+
sage: e.reduced_word()
|
|
910
|
+
[1, 1, 1, 2, 2, 2]
|
|
911
|
+
"""
|
|
912
|
+
if self._reduced_word is None:
|
|
913
|
+
self.parent().construct(up_to=self)
|
|
914
|
+
return self._reduced_word
|
|
915
|
+
|
|
916
|
+
def lift(self):
|
|
917
|
+
"""
|
|
918
|
+
Lift the element ``self`` into its ambient semigroup.
|
|
919
|
+
|
|
920
|
+
EXAMPLES::
|
|
921
|
+
|
|
922
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
923
|
+
sage: R = IntegerModRing(18)
|
|
924
|
+
sage: M = AutomaticSemigroup(Family({1: R(3), 2: R(5)}))
|
|
925
|
+
sage: M.repr_element_method("reduced_word")
|
|
926
|
+
sage: m = M.an_element(); m
|
|
927
|
+
[1]
|
|
928
|
+
sage: type(m)
|
|
929
|
+
<class 'sage.monoids.automatic_semigroup.AutomaticSemigroup_with_category.element_class'>
|
|
930
|
+
sage: m.lift()
|
|
931
|
+
3
|
|
932
|
+
sage: type(m.lift())
|
|
933
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_int'>
|
|
934
|
+
"""
|
|
935
|
+
return self.value
|
|
936
|
+
|
|
937
|
+
@cached_method
|
|
938
|
+
def transition(self, i):
|
|
939
|
+
"""
|
|
940
|
+
The multiplication on the right by a generator.
|
|
941
|
+
|
|
942
|
+
INPUT:
|
|
943
|
+
|
|
944
|
+
- ``i`` -- an element from the indexing set of the generators
|
|
945
|
+
|
|
946
|
+
This method computes ``self * self._generators[i]``.
|
|
947
|
+
|
|
948
|
+
EXAMPLES::
|
|
949
|
+
|
|
950
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
951
|
+
sage: R = IntegerModRing(17)
|
|
952
|
+
sage: M = AutomaticSemigroup(Family({1: R(3), 2: R(5)}), one=R.one())
|
|
953
|
+
sage: M.repr_element_method("reduced_word")
|
|
954
|
+
sage: M.construct()
|
|
955
|
+
sage: a = M.an_element()
|
|
956
|
+
sage: a.transition(1)
|
|
957
|
+
[1, 1]
|
|
958
|
+
sage: a.transition(2)
|
|
959
|
+
[1, 2]
|
|
960
|
+
"""
|
|
961
|
+
parent = self.parent()
|
|
962
|
+
assert i in parent._generators.keys()
|
|
963
|
+
return parent._retract(parent._mul(self.lift(), parent._generators_in_ambient[i]))
|
|
964
|
+
|
|
965
|
+
def _repr_(self):
|
|
966
|
+
"""
|
|
967
|
+
EXAMPLES::
|
|
968
|
+
|
|
969
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
970
|
+
sage: R = IntegerModRing(19)
|
|
971
|
+
sage: M = AutomaticSemigroup(Family({1: R(3), 2: R(5)}), one=R.one())
|
|
972
|
+
sage: a = M.an_element(); a
|
|
973
|
+
3
|
|
974
|
+
sage: b = M.from_reduced_word([1,2,1]); b
|
|
975
|
+
7
|
|
976
|
+
sage: M.repr_element_method("reduced_word")
|
|
977
|
+
sage: a
|
|
978
|
+
[1]
|
|
979
|
+
sage: b
|
|
980
|
+
7
|
|
981
|
+
sage: M.construct(up_to=b)
|
|
982
|
+
sage: b
|
|
983
|
+
[1, 1, 2]
|
|
984
|
+
"""
|
|
985
|
+
if self.parent()._repr_element_method == "ambient" or self._reduced_word is None:
|
|
986
|
+
return ElementWrapper._repr_(self)
|
|
987
|
+
return str(self._reduced_word)
|
|
988
|
+
|
|
989
|
+
def __copy__(self, memo=None):
|
|
990
|
+
r"""
|
|
991
|
+
Return ``self`` since this has unique representation.
|
|
992
|
+
|
|
993
|
+
INPUT:
|
|
994
|
+
|
|
995
|
+
- ``memo`` -- ignored, but required by the deepcopy API
|
|
996
|
+
|
|
997
|
+
EXAMPLES::
|
|
998
|
+
|
|
999
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
1000
|
+
sage: R = IntegerModRing(12)
|
|
1001
|
+
sage: M = AutomaticSemigroup(Family({1: R(3), 2: R(5)}), one=R.one())
|
|
1002
|
+
sage: m = M.an_element()
|
|
1003
|
+
sage: copy(m) is m
|
|
1004
|
+
True
|
|
1005
|
+
sage: from copy import deepcopy
|
|
1006
|
+
sage: deepcopy(m) is m
|
|
1007
|
+
True
|
|
1008
|
+
"""
|
|
1009
|
+
return self
|
|
1010
|
+
|
|
1011
|
+
__deepcopy__ = __copy__
|
|
1012
|
+
|
|
1013
|
+
|
|
1014
|
+
class AutomaticMonoid(AutomaticSemigroup):
|
|
1015
|
+
|
|
1016
|
+
def one(self):
|
|
1017
|
+
"""
|
|
1018
|
+
Return the unit of ``self``.
|
|
1019
|
+
|
|
1020
|
+
EXAMPLES::
|
|
1021
|
+
|
|
1022
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
1023
|
+
sage: R = IntegerModRing(21)
|
|
1024
|
+
sage: M = R.submonoid(())
|
|
1025
|
+
sage: M.one()
|
|
1026
|
+
1
|
|
1027
|
+
sage: M.one().parent() is M
|
|
1028
|
+
True
|
|
1029
|
+
"""
|
|
1030
|
+
return self._one
|
|
1031
|
+
|
|
1032
|
+
# This method takes the monoid generators and adds the unit
|
|
1033
|
+
semigroup_generators = raw_getattr(Monoids.ParentMethods, "semigroup_generators")
|
|
1034
|
+
|
|
1035
|
+
def monoid_generators(self):
|
|
1036
|
+
"""
|
|
1037
|
+
Return the family of monoid generators of ``self``.
|
|
1038
|
+
|
|
1039
|
+
EXAMPLES::
|
|
1040
|
+
|
|
1041
|
+
sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
|
|
1042
|
+
sage: R = IntegerModRing(28)
|
|
1043
|
+
sage: M = R.submonoid(Family({1: R(3), 2: R(5)}))
|
|
1044
|
+
sage: M.monoid_generators()
|
|
1045
|
+
Finite family {1: 3, 2: 5}
|
|
1046
|
+
|
|
1047
|
+
Note that the monoid generators do not include the unit,
|
|
1048
|
+
unlike the semigroup generators::
|
|
1049
|
+
|
|
1050
|
+
sage: M.semigroup_generators()
|
|
1051
|
+
Family (1, 3, 5)
|
|
1052
|
+
"""
|
|
1053
|
+
return self._generators
|
|
1054
|
+
gens = monoid_generators
|