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,2051 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
# sage.doctest: needs sage.combinat sage.modules
|
|
3
|
+
r"""
|
|
4
|
+
Recognizable series
|
|
5
|
+
|
|
6
|
+
Let `A` be an alphabet and `K` a semiring. Then a formal series `S`
|
|
7
|
+
with coefficients in `K` and indices in the words `A^*` is called
|
|
8
|
+
recognizable if it has a linear representation, i.e., there exists
|
|
9
|
+
|
|
10
|
+
- a nonnegative integer `n`
|
|
11
|
+
|
|
12
|
+
and there exist
|
|
13
|
+
|
|
14
|
+
- two vectors `\mathit{left}` and `\mathit{right}` of dimension `n` and
|
|
15
|
+
|
|
16
|
+
- a morphism of monoids `\mu` from `A^*` to `n\times n` matrices over `K`
|
|
17
|
+
|
|
18
|
+
such that the coefficient corresponding to a word `w\in A^*` equals
|
|
19
|
+
|
|
20
|
+
.. MATH::
|
|
21
|
+
|
|
22
|
+
\mathit{left} \, \mu(w) \, \mathit{right}.
|
|
23
|
+
|
|
24
|
+
.. NOTE::
|
|
25
|
+
|
|
26
|
+
Whenever a minimization (:meth:`~RecognizableSeries.minimized`) of
|
|
27
|
+
a series needs to be computed, it is required that `K` is a field.
|
|
28
|
+
In particular, minimization is called before checking if a series is
|
|
29
|
+
nonzero.
|
|
30
|
+
|
|
31
|
+
.. SEEALSO::
|
|
32
|
+
|
|
33
|
+
:mod:`k-regular sequence <sage.combinat.regular_sequence>`,
|
|
34
|
+
:mod:`sage.rings.cfinite_sequence`,
|
|
35
|
+
:mod:`sage.combinat.binary_recurrence_sequences`.
|
|
36
|
+
|
|
37
|
+
AUTHORS:
|
|
38
|
+
|
|
39
|
+
- Daniel Krenn (2016, 2021): supported by the Austrian Science Fund (FWF): P 24644-N26
|
|
40
|
+
"""
|
|
41
|
+
# ****************************************************************************
|
|
42
|
+
# Copyright (C) 2016 Daniel Krenn <dev@danielkrenn.at>
|
|
43
|
+
#
|
|
44
|
+
# This program is free software: you can redistribute it and/or modify
|
|
45
|
+
# it under the terms of the GNU General Public License as published by
|
|
46
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
47
|
+
# (at your option) any later version.
|
|
48
|
+
# https://www.gnu.org/licenses/
|
|
49
|
+
# ****************************************************************************
|
|
50
|
+
|
|
51
|
+
from functools import wraps
|
|
52
|
+
|
|
53
|
+
from sage.misc.cachefunc import cached_method
|
|
54
|
+
from sage.structure.element import ModuleElement
|
|
55
|
+
from sage.structure.parent import Parent
|
|
56
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class PrefixClosedSet:
|
|
60
|
+
def __init__(self, words):
|
|
61
|
+
r"""
|
|
62
|
+
A prefix-closed set.
|
|
63
|
+
|
|
64
|
+
Creation of this prefix-closed set is interactive
|
|
65
|
+
iteratively.
|
|
66
|
+
|
|
67
|
+
INPUT:
|
|
68
|
+
|
|
69
|
+
- ``words`` -- a class of words
|
|
70
|
+
(instance of :class:`~sage.combinat.words.words.Words`)
|
|
71
|
+
|
|
72
|
+
EXAMPLES::
|
|
73
|
+
|
|
74
|
+
sage: from sage.combinat.recognizable_series import PrefixClosedSet
|
|
75
|
+
sage: P = PrefixClosedSet(Words([0, 1], infinite=False)); P
|
|
76
|
+
[word: ]
|
|
77
|
+
|
|
78
|
+
sage: P = PrefixClosedSet.create_by_alphabet([0, 1]); P
|
|
79
|
+
[word: ]
|
|
80
|
+
|
|
81
|
+
See :meth:`iterate_possible_additions` for further examples.
|
|
82
|
+
"""
|
|
83
|
+
self.words = words
|
|
84
|
+
self.elements = [self.words([])]
|
|
85
|
+
|
|
86
|
+
@classmethod
|
|
87
|
+
def create_by_alphabet(cls, alphabet):
|
|
88
|
+
r"""
|
|
89
|
+
A prefix-closed set.
|
|
90
|
+
|
|
91
|
+
This is a convenience method for the
|
|
92
|
+
creation of prefix-closed sets by specifying an alphabet.
|
|
93
|
+
|
|
94
|
+
INPUT:
|
|
95
|
+
|
|
96
|
+
- ``alphabet`` -- finite words over this ``alphabet``
|
|
97
|
+
will used
|
|
98
|
+
|
|
99
|
+
EXAMPLES::
|
|
100
|
+
|
|
101
|
+
sage: from sage.combinat.recognizable_series import PrefixClosedSet
|
|
102
|
+
sage: P = PrefixClosedSet.create_by_alphabet([0, 1]); P
|
|
103
|
+
[word: ]
|
|
104
|
+
"""
|
|
105
|
+
from sage.combinat.words.words import Words
|
|
106
|
+
return cls(Words(alphabet, infinite=False))
|
|
107
|
+
|
|
108
|
+
def __repr__(self):
|
|
109
|
+
r"""
|
|
110
|
+
A representation string of this prefix-closed set.
|
|
111
|
+
|
|
112
|
+
OUTPUT: string
|
|
113
|
+
|
|
114
|
+
EXAMPLES::
|
|
115
|
+
|
|
116
|
+
sage: from sage.combinat.recognizable_series import PrefixClosedSet
|
|
117
|
+
sage: P = PrefixClosedSet.create_by_alphabet([0, 1])
|
|
118
|
+
sage: repr(P) # indirect doctest
|
|
119
|
+
'[word: ]'
|
|
120
|
+
"""
|
|
121
|
+
return repr(self.elements)
|
|
122
|
+
|
|
123
|
+
def add(self, w, check=True):
|
|
124
|
+
r"""
|
|
125
|
+
Add a word to this prefix-closed set.
|
|
126
|
+
|
|
127
|
+
INPUT:
|
|
128
|
+
|
|
129
|
+
- ``w`` -- a word
|
|
130
|
+
|
|
131
|
+
- ``check`` -- boolean (default: ``True``); if set, then it is verified
|
|
132
|
+
whether all proper prefixes of ``w`` are already in this
|
|
133
|
+
prefix-closed set
|
|
134
|
+
|
|
135
|
+
OUTPUT:
|
|
136
|
+
|
|
137
|
+
Nothing, but a
|
|
138
|
+
:python:`RuntimeError<library/exceptions.html#exceptions.ValueError>`
|
|
139
|
+
is raised if the check fails.
|
|
140
|
+
|
|
141
|
+
EXAMPLES::
|
|
142
|
+
|
|
143
|
+
sage: from sage.combinat.recognizable_series import PrefixClosedSet
|
|
144
|
+
sage: P = PrefixClosedSet.create_by_alphabet([0, 1])
|
|
145
|
+
sage: W = P.words
|
|
146
|
+
sage: P.add(W([0])); P
|
|
147
|
+
[word: , word: 0]
|
|
148
|
+
sage: P.add(W([0, 1])); P
|
|
149
|
+
[word: , word: 0, word: 01]
|
|
150
|
+
sage: P.add(W([1, 1]))
|
|
151
|
+
Traceback (most recent call last):
|
|
152
|
+
...
|
|
153
|
+
ValueError: cannot add as not all prefixes of 11 are included yet
|
|
154
|
+
"""
|
|
155
|
+
if check and any(p not in self.elements
|
|
156
|
+
for p in w.prefixes_iterator()
|
|
157
|
+
if p != w):
|
|
158
|
+
raise ValueError('cannot add as not all prefixes of '
|
|
159
|
+
'{} are included yet'.format(w))
|
|
160
|
+
self.elements.append(w)
|
|
161
|
+
|
|
162
|
+
def iterate_possible_additions(self):
|
|
163
|
+
r"""
|
|
164
|
+
Return an iterator over all elements including possible new elements.
|
|
165
|
+
|
|
166
|
+
OUTPUT: an iterator
|
|
167
|
+
|
|
168
|
+
EXAMPLES::
|
|
169
|
+
|
|
170
|
+
sage: from sage.combinat.recognizable_series import PrefixClosedSet
|
|
171
|
+
sage: P = PrefixClosedSet.create_by_alphabet([0, 1]); P
|
|
172
|
+
[word: ]
|
|
173
|
+
sage: for n, p in enumerate(P.iterate_possible_additions()):
|
|
174
|
+
....: print('{}?'.format(p))
|
|
175
|
+
....: if n in (0, 2, 3, 5):
|
|
176
|
+
....: P.add(p)
|
|
177
|
+
....: print('...added')
|
|
178
|
+
0?
|
|
179
|
+
...added
|
|
180
|
+
1?
|
|
181
|
+
00?
|
|
182
|
+
...added
|
|
183
|
+
01?
|
|
184
|
+
...added
|
|
185
|
+
000?
|
|
186
|
+
001?
|
|
187
|
+
...added
|
|
188
|
+
010?
|
|
189
|
+
011?
|
|
190
|
+
0010?
|
|
191
|
+
0011?
|
|
192
|
+
sage: P.elements
|
|
193
|
+
[word: , word: 0, word: 00, word: 01, word: 001]
|
|
194
|
+
|
|
195
|
+
Calling the iterator once more, returns all elements::
|
|
196
|
+
|
|
197
|
+
sage: list(P.iterate_possible_additions())
|
|
198
|
+
[word: 0,
|
|
199
|
+
word: 1,
|
|
200
|
+
word: 00,
|
|
201
|
+
word: 01,
|
|
202
|
+
word: 000,
|
|
203
|
+
word: 001,
|
|
204
|
+
word: 010,
|
|
205
|
+
word: 011,
|
|
206
|
+
word: 0010,
|
|
207
|
+
word: 0011]
|
|
208
|
+
|
|
209
|
+
The method :meth:`iterate_possible_additions` is roughly equivalent to
|
|
210
|
+
::
|
|
211
|
+
|
|
212
|
+
sage: list(p + a
|
|
213
|
+
....: for p in P.elements
|
|
214
|
+
....: for a in P.words.iterate_by_length(1))
|
|
215
|
+
[word: 0,
|
|
216
|
+
word: 1,
|
|
217
|
+
word: 00,
|
|
218
|
+
word: 01,
|
|
219
|
+
word: 000,
|
|
220
|
+
word: 001,
|
|
221
|
+
word: 010,
|
|
222
|
+
word: 011,
|
|
223
|
+
word: 0010,
|
|
224
|
+
word: 0011]
|
|
225
|
+
|
|
226
|
+
However, the above does not allow to add elements during iteration,
|
|
227
|
+
whereas :meth:`iterate_possible_additions` does.
|
|
228
|
+
"""
|
|
229
|
+
n = 0
|
|
230
|
+
it = self.words.iterate_by_length(1)
|
|
231
|
+
while n < len(self.elements):
|
|
232
|
+
try:
|
|
233
|
+
nn = next(it)
|
|
234
|
+
yield self.elements[n] + nn # next(it)
|
|
235
|
+
except StopIteration:
|
|
236
|
+
n += 1
|
|
237
|
+
it = self.words.iterate_by_length(1)
|
|
238
|
+
|
|
239
|
+
def prefix_set(self):
|
|
240
|
+
r"""
|
|
241
|
+
Return the set of minimal (with respect to prefix ordering) elements
|
|
242
|
+
of the complement of this prefix closed set.
|
|
243
|
+
|
|
244
|
+
See also Proposition 2.3.1 of [BR2010a]_.
|
|
245
|
+
|
|
246
|
+
OUTPUT: list
|
|
247
|
+
|
|
248
|
+
EXAMPLES::
|
|
249
|
+
|
|
250
|
+
sage: from sage.combinat.recognizable_series import PrefixClosedSet
|
|
251
|
+
sage: P = PrefixClosedSet.create_by_alphabet([0, 1]); P
|
|
252
|
+
[word: ]
|
|
253
|
+
sage: for n, p in enumerate(P.iterate_possible_additions()):
|
|
254
|
+
....: if n in (0, 1, 2, 4, 6):
|
|
255
|
+
....: P.add(p)
|
|
256
|
+
sage: P
|
|
257
|
+
[word: , word: 0, word: 1, word: 00, word: 10, word: 000]
|
|
258
|
+
sage: P.prefix_set()
|
|
259
|
+
[word: 01, word: 11, word: 001, word: 100,
|
|
260
|
+
word: 101, word: 0000, word: 0001]
|
|
261
|
+
"""
|
|
262
|
+
return [p + a
|
|
263
|
+
for p in self.elements
|
|
264
|
+
for a in self.words.iterate_by_length(1)
|
|
265
|
+
if p + a not in self.elements]
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def minimize_result(operation):
|
|
269
|
+
r"""
|
|
270
|
+
A decorator for operations that enables control of
|
|
271
|
+
automatic minimization on the result.
|
|
272
|
+
|
|
273
|
+
INPUT:
|
|
274
|
+
|
|
275
|
+
- ``operation`` -- a method
|
|
276
|
+
|
|
277
|
+
OUTPUT: a method with the following additional argument:
|
|
278
|
+
|
|
279
|
+
- ``minimize`` -- (default: ``None``) a boolean or ``None``.
|
|
280
|
+
If ``True``, then :meth:`minimized` is called after the operation,
|
|
281
|
+
if ``False``, then not. If this argument is ``None``, then
|
|
282
|
+
the default specified by the parent's ``minimize_results`` is used.
|
|
283
|
+
|
|
284
|
+
.. NOTE::
|
|
285
|
+
|
|
286
|
+
If the result of ``operation`` is ``self``, then minimization is
|
|
287
|
+
not applied unless ``minimize=True`` is explicitly set,
|
|
288
|
+
in particular, independent of the parent's ``minimize_results``.
|
|
289
|
+
|
|
290
|
+
TESTS::
|
|
291
|
+
|
|
292
|
+
sage: from sage.combinat.recognizable_series import minimize_result
|
|
293
|
+
sage: class P():
|
|
294
|
+
....: pass
|
|
295
|
+
sage: p = P()
|
|
296
|
+
sage: class S():
|
|
297
|
+
....: def __init__(self, s):
|
|
298
|
+
....: self.s = s
|
|
299
|
+
....: def __repr__(self):
|
|
300
|
+
....: return self.s
|
|
301
|
+
....: def parent(self):
|
|
302
|
+
....: return p
|
|
303
|
+
....: def minimized(self):
|
|
304
|
+
....: return S(self.s + ' minimized')
|
|
305
|
+
....: @minimize_result
|
|
306
|
+
....: def operation(self):
|
|
307
|
+
....: return S(self.s + ' result')
|
|
308
|
+
|
|
309
|
+
sage: p.minimize_results = True
|
|
310
|
+
sage: S('some').operation()
|
|
311
|
+
some result minimized
|
|
312
|
+
sage: S('some').operation(minimize=True)
|
|
313
|
+
some result minimized
|
|
314
|
+
sage: S('some').operation(minimize=False)
|
|
315
|
+
some result
|
|
316
|
+
|
|
317
|
+
sage: p.minimize_results = False
|
|
318
|
+
sage: S('some').operation()
|
|
319
|
+
some result
|
|
320
|
+
sage: S('some').operation(minimize=True)
|
|
321
|
+
some result minimized
|
|
322
|
+
sage: S('some').operation(minimize=False)
|
|
323
|
+
some result
|
|
324
|
+
|
|
325
|
+
::
|
|
326
|
+
|
|
327
|
+
sage: class T(S):
|
|
328
|
+
....: @minimize_result
|
|
329
|
+
....: def nooperation(self):
|
|
330
|
+
....: return self
|
|
331
|
+
sage: t = T('some')
|
|
332
|
+
sage: p.minimize_results = True
|
|
333
|
+
sage: t.nooperation() is t
|
|
334
|
+
True
|
|
335
|
+
sage: t.nooperation(minimize=True) is t
|
|
336
|
+
False
|
|
337
|
+
sage: t.nooperation(minimize=False) is t
|
|
338
|
+
True
|
|
339
|
+
sage: p.minimize_results = False
|
|
340
|
+
sage: t.nooperation() is t
|
|
341
|
+
True
|
|
342
|
+
sage: t.nooperation(minimize=True) is t
|
|
343
|
+
False
|
|
344
|
+
sage: t.nooperation(minimize=False) is t
|
|
345
|
+
True
|
|
346
|
+
"""
|
|
347
|
+
@wraps(operation)
|
|
348
|
+
def minimized(self, *args, **kwds):
|
|
349
|
+
minimize = kwds.pop('minimize', None)
|
|
350
|
+
|
|
351
|
+
result = operation(self, *args, **kwds)
|
|
352
|
+
if minimize is not True and result is self:
|
|
353
|
+
return result
|
|
354
|
+
|
|
355
|
+
if minimize is None:
|
|
356
|
+
minimize = self.parent().minimize_results
|
|
357
|
+
|
|
358
|
+
if minimize:
|
|
359
|
+
result = result.minimized()
|
|
360
|
+
|
|
361
|
+
return result
|
|
362
|
+
|
|
363
|
+
return minimized
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
class RecognizableSeries(ModuleElement):
|
|
367
|
+
def __init__(self, parent, mu, left, right):
|
|
368
|
+
r"""
|
|
369
|
+
A recognizable series.
|
|
370
|
+
|
|
371
|
+
- ``parent`` -- an instance of :class:`RecognizableSeriesSpace`
|
|
372
|
+
|
|
373
|
+
- ``mu`` -- a family of square matrices, all of which have the
|
|
374
|
+
same dimension.
|
|
375
|
+
The indices of this family are the elements of the alphabet.
|
|
376
|
+
``mu`` may be a list or tuple of the same cardinality as the
|
|
377
|
+
alphabet as well. See also :meth:`mu <mu>`.
|
|
378
|
+
|
|
379
|
+
- ``left`` -- a vector. When evaluating a
|
|
380
|
+
coefficient, this vector is multiplied from the left to the
|
|
381
|
+
matrix obtained from :meth:`mu <mu>` applying on a word.
|
|
382
|
+
See also :meth:`left <left>`.
|
|
383
|
+
|
|
384
|
+
- ``right`` -- a vector. When evaluating a
|
|
385
|
+
coefficient, this vector is multiplied from the right to the
|
|
386
|
+
matrix obtained from :meth:`mu <mu>` applying on a word.
|
|
387
|
+
See also :meth:`right <right>`.
|
|
388
|
+
|
|
389
|
+
When created via the parent :class:`RecognizableSeriesSpace`, then
|
|
390
|
+
the following option is available.
|
|
391
|
+
|
|
392
|
+
EXAMPLES::
|
|
393
|
+
|
|
394
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
395
|
+
sage: S = Rec((Matrix([[3, 6], [0, 1]]), Matrix([[0, -6], [1, 5]])),
|
|
396
|
+
....: vector([0, 1]), vector([1, 0])).transposed(); S
|
|
397
|
+
[1] + 3*[01] + [10] + 5*[11] + 9*[001] + 3*[010] + ...
|
|
398
|
+
|
|
399
|
+
We can access coefficients by
|
|
400
|
+
::
|
|
401
|
+
|
|
402
|
+
sage: W = Rec.indices()
|
|
403
|
+
sage: S[W([0, 0, 1])]
|
|
404
|
+
9
|
|
405
|
+
|
|
406
|
+
.. SEEALSO::
|
|
407
|
+
|
|
408
|
+
:doc:`recognizable series <recognizable_series>`,
|
|
409
|
+
:class:`RecognizableSeriesSpace`.
|
|
410
|
+
|
|
411
|
+
TESTS::
|
|
412
|
+
|
|
413
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, (0,1))
|
|
414
|
+
sage: M0 = Matrix([[1, 0], [0, 1]])
|
|
415
|
+
sage: M1 = Matrix([[0, -1], [1, 2]])
|
|
416
|
+
sage: Rec((M0, M1), (0, 1), (1, 1))
|
|
417
|
+
[] + [0] + 3*[1] + [00] + 3*[01] + 3*[10] + 5*[11] + [000] + 3*[001] + 3*[010] + ...
|
|
418
|
+
|
|
419
|
+
sage: M0 = Matrix([[3, 6], [0, 1]])
|
|
420
|
+
sage: M1 = Matrix([[0, -6], [1, 5]])
|
|
421
|
+
sage: L = vector([0, 1])
|
|
422
|
+
sage: R = vector([1, 0])
|
|
423
|
+
sage: S = Rec((M0, M1), L, R)
|
|
424
|
+
sage: S.mu[0] is M0, S.mu[1] is M1, S.left is L, S.right is R
|
|
425
|
+
(False, False, False, False)
|
|
426
|
+
sage: S.mu[0].is_immutable(), S.mu[1].is_immutable(), S.left.is_immutable(), S.right.is_immutable()
|
|
427
|
+
(True, True, True, True)
|
|
428
|
+
sage: M0.set_immutable()
|
|
429
|
+
sage: M1.set_immutable()
|
|
430
|
+
sage: L.set_immutable()
|
|
431
|
+
sage: R.set_immutable()
|
|
432
|
+
sage: S = Rec((M0, M1), L, R)
|
|
433
|
+
sage: S.mu[0] is M0, S.mu[1] is M1, S.left is L, S.right is R
|
|
434
|
+
(True, True, True, True)
|
|
435
|
+
"""
|
|
436
|
+
super().__init__(parent=parent)
|
|
437
|
+
|
|
438
|
+
from copy import copy
|
|
439
|
+
from sage.matrix.constructor import Matrix
|
|
440
|
+
from sage.modules.free_module_element import vector
|
|
441
|
+
from sage.sets.family import Family
|
|
442
|
+
|
|
443
|
+
A = self.parent().alphabet()
|
|
444
|
+
if isinstance(mu, (list, tuple)):
|
|
445
|
+
mu = dict(zip(A, mu))
|
|
446
|
+
|
|
447
|
+
def immutable(m):
|
|
448
|
+
if m.is_immutable():
|
|
449
|
+
return m
|
|
450
|
+
m = copy(m)
|
|
451
|
+
m.set_immutable()
|
|
452
|
+
return m
|
|
453
|
+
|
|
454
|
+
if isinstance(mu, dict):
|
|
455
|
+
mu = {a: Matrix(M, immutable=True) for a, M in mu.items()}
|
|
456
|
+
mu = Family(mu)
|
|
457
|
+
|
|
458
|
+
if not mu.is_finite():
|
|
459
|
+
raise NotImplementedError('mu is not a finite family of matrices')
|
|
460
|
+
|
|
461
|
+
self._left_ = immutable(vector(left))
|
|
462
|
+
self._mu_ = mu
|
|
463
|
+
self._right_ = immutable(vector(right))
|
|
464
|
+
|
|
465
|
+
@property
|
|
466
|
+
def mu(self):
|
|
467
|
+
r"""
|
|
468
|
+
When evaluating a coefficient, this is applied on each letter
|
|
469
|
+
of a word; the result is a matrix.
|
|
470
|
+
This extends :meth:`mu <mu>` to words over the parent's
|
|
471
|
+
:meth:`~RecognizableSeriesSpace.alphabet`.
|
|
472
|
+
|
|
473
|
+
TESTS::
|
|
474
|
+
|
|
475
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
476
|
+
sage: M0 = Matrix([[1, 0], [0, 1]])
|
|
477
|
+
sage: M1 = Matrix([[0, -1], [1, 2]])
|
|
478
|
+
sage: S = Rec((M0, M1), vector([0, 1]), vector([1, 1]))
|
|
479
|
+
sage: S.mu[0] == M0 and S.mu[1] == M1
|
|
480
|
+
True
|
|
481
|
+
"""
|
|
482
|
+
return self._mu_
|
|
483
|
+
|
|
484
|
+
@property
|
|
485
|
+
def left(self):
|
|
486
|
+
r"""
|
|
487
|
+
When evaluating a coefficient, this vector is multiplied from
|
|
488
|
+
the left to the matrix obtained from :meth:`mu <mu>` applied on a
|
|
489
|
+
word.
|
|
490
|
+
|
|
491
|
+
TESTS::
|
|
492
|
+
|
|
493
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
494
|
+
sage: Rec((Matrix([[3, 6], [0, 1]]), Matrix([[0, -6], [1, 5]])),
|
|
495
|
+
....: vector([0, 1]), vector([1, 0])).transposed().left
|
|
496
|
+
(1, 0)
|
|
497
|
+
"""
|
|
498
|
+
return self._left_
|
|
499
|
+
|
|
500
|
+
@property
|
|
501
|
+
def right(self):
|
|
502
|
+
r"""
|
|
503
|
+
When evaluating a coefficient, this vector is multiplied from
|
|
504
|
+
the right to the matrix obtained from :meth:`mu <mu>` applied on a
|
|
505
|
+
word.
|
|
506
|
+
|
|
507
|
+
TESTS::
|
|
508
|
+
|
|
509
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
510
|
+
sage: Rec((Matrix([[3, 6], [0, 1]]), Matrix([[0, -6], [1, 5]])),
|
|
511
|
+
....: vector([0, 1]), vector([1, 0])).transposed().right
|
|
512
|
+
(0, 1)
|
|
513
|
+
"""
|
|
514
|
+
return self._right_
|
|
515
|
+
|
|
516
|
+
def linear_representation(self):
|
|
517
|
+
r"""
|
|
518
|
+
Return the linear representation of this series.
|
|
519
|
+
|
|
520
|
+
OUTPUT:
|
|
521
|
+
|
|
522
|
+
A triple ``(left, mu, right)`` containing
|
|
523
|
+
the vectors :meth:`left <left>` and :meth:`right <right>`,
|
|
524
|
+
and the family of matrices :meth:`mu <mu>`.
|
|
525
|
+
|
|
526
|
+
EXAMPLES::
|
|
527
|
+
|
|
528
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
529
|
+
sage: Rec((Matrix([[3, 6], [0, 1]]), Matrix([[0, -6], [1, 5]])),
|
|
530
|
+
....: vector([0, 1]), vector([1, 0])
|
|
531
|
+
....: ).transposed().linear_representation()
|
|
532
|
+
((1, 0),
|
|
533
|
+
Finite family {0: [3 0]
|
|
534
|
+
[6 1],
|
|
535
|
+
1: [ 0 1]
|
|
536
|
+
[-6 5]},
|
|
537
|
+
(0, 1))
|
|
538
|
+
"""
|
|
539
|
+
return (self.left, self.mu, self.right)
|
|
540
|
+
|
|
541
|
+
def _repr_(self, latex=False):
|
|
542
|
+
r"""
|
|
543
|
+
A representation string for this recognizable series.
|
|
544
|
+
|
|
545
|
+
INPUT:
|
|
546
|
+
|
|
547
|
+
- ``latex`` -- boolean (default: ``False``); if set, then LaTeX-output
|
|
548
|
+
is returned
|
|
549
|
+
|
|
550
|
+
OUTPUT: string
|
|
551
|
+
|
|
552
|
+
EXAMPLES::
|
|
553
|
+
|
|
554
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
555
|
+
sage: S = Rec((Matrix([[3, 6], [0, 1]]), Matrix([[0, -6], [1, 5]])),
|
|
556
|
+
....: vector([0, 1]), vector([1, 0])).transposed()
|
|
557
|
+
sage: repr(S) # indirect doctest
|
|
558
|
+
'[1] + 3*[01] + [10] + 5*[11] + 9*[001] + 3*[010] + ...'
|
|
559
|
+
|
|
560
|
+
TESTS::
|
|
561
|
+
|
|
562
|
+
sage: S = Rec((Matrix([[0]]), Matrix([[0]])),
|
|
563
|
+
....: vector([1]), vector([1]))
|
|
564
|
+
sage: repr(S) # indirect doctest
|
|
565
|
+
'[] + ...'
|
|
566
|
+
|
|
567
|
+
sage: S = Rec((Matrix([[0, 1], [0, 0]]), Matrix([[0, 0], [0, 0]])),
|
|
568
|
+
....: vector([0, 1]), vector([1, 0]))
|
|
569
|
+
sage: repr(S) # indirect doctest
|
|
570
|
+
'0 + ...'
|
|
571
|
+
"""
|
|
572
|
+
if self.is_trivial_zero():
|
|
573
|
+
return '0'
|
|
574
|
+
|
|
575
|
+
from itertools import islice
|
|
576
|
+
|
|
577
|
+
if latex:
|
|
578
|
+
from sage.misc.latex import latex as latex_repr
|
|
579
|
+
fr = latex_repr
|
|
580
|
+
fs = latex_repr
|
|
581
|
+
times = ' '
|
|
582
|
+
else:
|
|
583
|
+
fr = repr
|
|
584
|
+
fs = str
|
|
585
|
+
times = '*'
|
|
586
|
+
|
|
587
|
+
def summand(w, c):
|
|
588
|
+
if c == 1:
|
|
589
|
+
return '[{w}]'.format(w=fs(w))
|
|
590
|
+
return '{c}{times}[{w}]'.format(c=fr(c), times=times, w=fs(w))
|
|
591
|
+
|
|
592
|
+
def all_coefficients():
|
|
593
|
+
number_of_zeros = 0
|
|
594
|
+
for w in self.parent().indices():
|
|
595
|
+
c = self[w]
|
|
596
|
+
if c != 0:
|
|
597
|
+
number_of_zeros = 0
|
|
598
|
+
yield (w, self[w])
|
|
599
|
+
else:
|
|
600
|
+
number_of_zeros += 1
|
|
601
|
+
if number_of_zeros >= 100:
|
|
602
|
+
return
|
|
603
|
+
|
|
604
|
+
coefficients = islice(all_coefficients(), 10)
|
|
605
|
+
|
|
606
|
+
s = ' + '.join(summand(w, c)
|
|
607
|
+
for w, c in coefficients)
|
|
608
|
+
s = s.replace('+ -', '- ')
|
|
609
|
+
if not s:
|
|
610
|
+
s = '0'
|
|
611
|
+
return s + ' + ...'
|
|
612
|
+
|
|
613
|
+
def _latex_(self):
|
|
614
|
+
r"""
|
|
615
|
+
A LaTeX-representation string for this recognizable series.
|
|
616
|
+
|
|
617
|
+
OUTPUT: string
|
|
618
|
+
|
|
619
|
+
TESTS::
|
|
620
|
+
|
|
621
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
622
|
+
sage: S = Rec((Matrix([[3, 6], [0, 1]]), Matrix([[0, -6], [1, 5]])),
|
|
623
|
+
....: vector([0, 1]), vector([1, 0])).transposed()
|
|
624
|
+
sage: latex(S) # indirect doctest
|
|
625
|
+
[1] + 3 [01] + [10] + 5 [11] + 9 [001] + 3 [010]
|
|
626
|
+
+ 15 [011] + [100] + 11 [101] + 5 [110] + ...
|
|
627
|
+
"""
|
|
628
|
+
return self._repr_(latex=True)
|
|
629
|
+
|
|
630
|
+
@cached_method
|
|
631
|
+
def coefficient_of_word(self, w, multiply_left=True, multiply_right=True):
|
|
632
|
+
r"""
|
|
633
|
+
Return the coefficient to word `w` of this series.
|
|
634
|
+
|
|
635
|
+
INPUT:
|
|
636
|
+
|
|
637
|
+
- ``w`` -- a word over the parent's
|
|
638
|
+
:meth:`~RecognizableSeriesSpace.alphabet`
|
|
639
|
+
|
|
640
|
+
- ``multiply_left`` -- boolean (default: ``True``); if ``False``,
|
|
641
|
+
then multiplication by :meth:`left <left>` is skipped
|
|
642
|
+
|
|
643
|
+
- ``multiply_right`` -- boolean (default: ``True``); if ``False``,
|
|
644
|
+
then multiplication by :meth:`right <right>` is skipped
|
|
645
|
+
|
|
646
|
+
OUTPUT:
|
|
647
|
+
|
|
648
|
+
An element in the parent's
|
|
649
|
+
:meth:`~RecognizableSeriesSpace.coefficient_ring`
|
|
650
|
+
|
|
651
|
+
EXAMPLES::
|
|
652
|
+
|
|
653
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
654
|
+
sage: W = Rec.indices()
|
|
655
|
+
sage: S = Rec((Matrix([[1, 0], [0, 1]]), Matrix([[0, -1], [1, 2]])),
|
|
656
|
+
....: left=vector([0, 1]), right=vector([1, 0]))
|
|
657
|
+
sage: S[W(7.digits(2))] # indirect doctest
|
|
658
|
+
3
|
|
659
|
+
|
|
660
|
+
TESTS::
|
|
661
|
+
|
|
662
|
+
sage: w = W(6.digits(2))
|
|
663
|
+
sage: S.coefficient_of_word(w)
|
|
664
|
+
2
|
|
665
|
+
sage: S.coefficient_of_word(w, multiply_left=False)
|
|
666
|
+
(-1, 2)
|
|
667
|
+
sage: S.coefficient_of_word(w, multiply_right=False)
|
|
668
|
+
(2, 3)
|
|
669
|
+
sage: S.coefficient_of_word(w, multiply_left=False, multiply_right=False)
|
|
670
|
+
[-1 -2]
|
|
671
|
+
[ 2 3]
|
|
672
|
+
"""
|
|
673
|
+
result = self._mu_of_word_(w)
|
|
674
|
+
if multiply_left:
|
|
675
|
+
result = self.left * result
|
|
676
|
+
if multiply_right:
|
|
677
|
+
result = result * self.right
|
|
678
|
+
return result
|
|
679
|
+
|
|
680
|
+
__getitem__ = coefficient_of_word
|
|
681
|
+
|
|
682
|
+
@cached_method
|
|
683
|
+
def _mu_of_empty_word_(self):
|
|
684
|
+
r"""
|
|
685
|
+
Return :meth:`mu <mu>` applied on the empty word.
|
|
686
|
+
|
|
687
|
+
OUTPUT: a matrix
|
|
688
|
+
|
|
689
|
+
TESTS::
|
|
690
|
+
|
|
691
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
692
|
+
sage: W = Rec.indices()
|
|
693
|
+
sage: M0 = Matrix([[1, 0], [0, 1]])
|
|
694
|
+
sage: M1 = Matrix([[0, -1], [1, 2]])
|
|
695
|
+
sage: S = Rec({W([0]): M0, W([1]): M1}, vector([0, 1]), vector([1, 1]))
|
|
696
|
+
sage: S._mu_of_empty_word_()
|
|
697
|
+
[1 0]
|
|
698
|
+
[0 1]
|
|
699
|
+
sage: I = Matrix([[1, 0], [0, 1]]); I.set_immutable()
|
|
700
|
+
sage: T = Rec({W([]): I, W([0]): M0, W([1]): M1}, vector([0, 1]), vector([1, 1]))
|
|
701
|
+
sage: T._mu_of_empty_word_()
|
|
702
|
+
[1 0]
|
|
703
|
+
[0 1]
|
|
704
|
+
sage: _ is I
|
|
705
|
+
True
|
|
706
|
+
"""
|
|
707
|
+
eps = self.parent().indices()()
|
|
708
|
+
try:
|
|
709
|
+
return self.mu[eps]
|
|
710
|
+
except KeyError:
|
|
711
|
+
return next(iter(self.mu)).parent().one()
|
|
712
|
+
|
|
713
|
+
@cached_method
|
|
714
|
+
def _mu_of_word_(self, w):
|
|
715
|
+
r"""
|
|
716
|
+
Return :meth:`mu <mu>` applied on the word `w`.
|
|
717
|
+
|
|
718
|
+
INPUT:
|
|
719
|
+
|
|
720
|
+
- ``w`` -- a word over the parent's
|
|
721
|
+
:meth:`~RecognizableSeriesSpace.alphabet`
|
|
722
|
+
|
|
723
|
+
OUTPUT: a matrix
|
|
724
|
+
|
|
725
|
+
TESTS::
|
|
726
|
+
|
|
727
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
728
|
+
sage: W = Rec.indices()
|
|
729
|
+
sage: M0 = Matrix([[1, 0], [0, 1]])
|
|
730
|
+
sage: M1 = Matrix([[0, -1], [1, 2]])
|
|
731
|
+
sage: S = Rec((M0, M1), vector([0, 1]), vector([1, 1]))
|
|
732
|
+
sage: S._mu_of_word_(W([0])) == M0
|
|
733
|
+
True
|
|
734
|
+
sage: S._mu_of_word_(W([1])) == M1
|
|
735
|
+
True
|
|
736
|
+
sage: S._mu_of_word_(W(3.digits(2))) == M1^2
|
|
737
|
+
True
|
|
738
|
+
|
|
739
|
+
::
|
|
740
|
+
|
|
741
|
+
sage: S._mu_of_word_(-1)
|
|
742
|
+
Traceback (most recent call last):
|
|
743
|
+
...
|
|
744
|
+
ValueError: index -1 is not in Finite words over {0, 1}
|
|
745
|
+
"""
|
|
746
|
+
W = self.parent().indices()
|
|
747
|
+
if w not in W:
|
|
748
|
+
raise ValueError('index {} is not in {}'.format(w, W))
|
|
749
|
+
from sage.misc.misc_c import prod
|
|
750
|
+
return prod((self.mu[a] for a in w), z=self._mu_of_empty_word_())
|
|
751
|
+
|
|
752
|
+
def __iter__(self):
|
|
753
|
+
r"""
|
|
754
|
+
Return an iterator over pairs ``(index, coefficient)``.
|
|
755
|
+
|
|
756
|
+
EXAMPLES::
|
|
757
|
+
|
|
758
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
759
|
+
sage: S = Rec((Matrix([[1, 0], [0, 1]]), Matrix([[0, -1], [1, 2]])),
|
|
760
|
+
....: left=vector([0, 1]), right=vector([1, 0]))
|
|
761
|
+
sage: from itertools import islice
|
|
762
|
+
sage: list(islice(S, 10))
|
|
763
|
+
[(word: , 0),
|
|
764
|
+
(word: 0, 0),
|
|
765
|
+
(word: 1, 1),
|
|
766
|
+
(word: 00, 0),
|
|
767
|
+
(word: 01, 1),
|
|
768
|
+
(word: 10, 1),
|
|
769
|
+
(word: 11, 2),
|
|
770
|
+
(word: 000, 0),
|
|
771
|
+
(word: 001, 1),
|
|
772
|
+
(word: 010, 1)]
|
|
773
|
+
sage: list(islice((s for s in S if s[1] != 0), 10))
|
|
774
|
+
[(word: 1, 1),
|
|
775
|
+
(word: 01, 1),
|
|
776
|
+
(word: 10, 1),
|
|
777
|
+
(word: 11, 2),
|
|
778
|
+
(word: 001, 1),
|
|
779
|
+
(word: 010, 1),
|
|
780
|
+
(word: 011, 2),
|
|
781
|
+
(word: 100, 1),
|
|
782
|
+
(word: 101, 2),
|
|
783
|
+
(word: 110, 2)]
|
|
784
|
+
|
|
785
|
+
sage: S = Rec((Matrix([[1, 0], [0, 1]]), Matrix([[0, -1], [1, 2]])),
|
|
786
|
+
....: left=vector([1, 0]), right=vector([1, 0]))
|
|
787
|
+
sage: list(islice((s for s in S if s[1] != 0), 10))
|
|
788
|
+
[(word: , 1),
|
|
789
|
+
(word: 0, 1),
|
|
790
|
+
(word: 00, 1),
|
|
791
|
+
(word: 11, -1),
|
|
792
|
+
(word: 000, 1),
|
|
793
|
+
(word: 011, -1),
|
|
794
|
+
(word: 101, -1),
|
|
795
|
+
(word: 110, -1),
|
|
796
|
+
(word: 111, -2),
|
|
797
|
+
(word: 0000, 1)]
|
|
798
|
+
|
|
799
|
+
TESTS::
|
|
800
|
+
|
|
801
|
+
sage: it = iter(S)
|
|
802
|
+
sage: iter(it) is it
|
|
803
|
+
True
|
|
804
|
+
sage: iter(S) is not it
|
|
805
|
+
True
|
|
806
|
+
"""
|
|
807
|
+
return iter((w, self[w]) for w in self.parent().indices())
|
|
808
|
+
|
|
809
|
+
def is_trivial_zero(self):
|
|
810
|
+
r"""
|
|
811
|
+
Return whether this recognizable series is trivially equal to
|
|
812
|
+
zero (without any :meth:`minimization <minimized>`).
|
|
813
|
+
|
|
814
|
+
EXAMPLES::
|
|
815
|
+
|
|
816
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
817
|
+
sage: Rec((Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [0, 1]])),
|
|
818
|
+
....: left=vector([0, 1]), right=vector([1, 0])).is_trivial_zero()
|
|
819
|
+
False
|
|
820
|
+
sage: Rec((Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [0, 1]])),
|
|
821
|
+
....: left=vector([0, 0]), right=vector([1, 0])).is_trivial_zero()
|
|
822
|
+
True
|
|
823
|
+
sage: Rec((Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [0, 1]])),
|
|
824
|
+
....: left=vector([0, 1]), right=vector([0, 0])).is_trivial_zero()
|
|
825
|
+
True
|
|
826
|
+
|
|
827
|
+
The following two differ in the coefficient of the empty word::
|
|
828
|
+
|
|
829
|
+
sage: Rec((Matrix([[0, 0], [0, 0]]), Matrix([[0, 0], [0, 0]])),
|
|
830
|
+
....: left=vector([0, 1]), right=vector([1, 0])).is_trivial_zero()
|
|
831
|
+
True
|
|
832
|
+
sage: Rec((Matrix([[0, 0], [0, 0]]), Matrix([[0, 0], [0, 0]])),
|
|
833
|
+
....: left=vector([1, 1]), right=vector([1, 1])).is_trivial_zero()
|
|
834
|
+
False
|
|
835
|
+
|
|
836
|
+
TESTS::
|
|
837
|
+
|
|
838
|
+
sage: Rec.zero().is_trivial_zero()
|
|
839
|
+
True
|
|
840
|
+
|
|
841
|
+
The following is zero, but not trivially zero::
|
|
842
|
+
|
|
843
|
+
sage: S = Rec((Matrix([[1, 0], [0, 0]]), Matrix([[1, 0], [0, 0]])),
|
|
844
|
+
....: left=vector([0, 1]), right=vector([1, 0]))
|
|
845
|
+
sage: S.is_trivial_zero()
|
|
846
|
+
False
|
|
847
|
+
sage: S.is_zero()
|
|
848
|
+
True
|
|
849
|
+
"""
|
|
850
|
+
return not self.left or not self.right or \
|
|
851
|
+
(all(not self.mu[a] for a in self.parent().alphabet()) and
|
|
852
|
+
not self[self.parent().indices()()])
|
|
853
|
+
|
|
854
|
+
def __bool__(self):
|
|
855
|
+
r"""
|
|
856
|
+
Return whether this recognizable series is nonzero.
|
|
857
|
+
|
|
858
|
+
TESTS::
|
|
859
|
+
|
|
860
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
861
|
+
sage: bool(Rec((Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [0, 1]])),
|
|
862
|
+
....: left=vector([0, 1]), right=vector([1, 0])))
|
|
863
|
+
False
|
|
864
|
+
sage: bool(Rec((Matrix([[0, 0], [0, 0]]), Matrix([[0, 0], [0, 0]])),
|
|
865
|
+
....: left=vector([0, 1]), right=vector([1, 0])))
|
|
866
|
+
False
|
|
867
|
+
sage: bool(Rec((Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [0, 1]])),
|
|
868
|
+
....: left=vector([0, 0]), right=vector([1, 0])))
|
|
869
|
+
False
|
|
870
|
+
sage: bool(Rec((Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [0, 1]])),
|
|
871
|
+
....: left=vector([0, 1]), right=vector([0, 0])))
|
|
872
|
+
False
|
|
873
|
+
|
|
874
|
+
::
|
|
875
|
+
|
|
876
|
+
sage: S = Rec((Matrix([[1, 0], [0, 0]]), Matrix([[1, 0], [0, 0]])),
|
|
877
|
+
....: left=vector([0, 1]), right=vector([1, 0]))
|
|
878
|
+
sage: bool(S)
|
|
879
|
+
False
|
|
880
|
+
"""
|
|
881
|
+
if self.is_trivial_zero():
|
|
882
|
+
return False
|
|
883
|
+
try:
|
|
884
|
+
M = self.minimized()
|
|
885
|
+
except ValueError:
|
|
886
|
+
pass
|
|
887
|
+
else:
|
|
888
|
+
if M.is_trivial_zero():
|
|
889
|
+
return False
|
|
890
|
+
return True
|
|
891
|
+
|
|
892
|
+
def __hash__(self):
|
|
893
|
+
r"""
|
|
894
|
+
A hash value of this recognizable series.
|
|
895
|
+
|
|
896
|
+
TESTS::
|
|
897
|
+
|
|
898
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
899
|
+
sage: S = Rec((Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [0, 1]])),
|
|
900
|
+
....: left=vector([0, 1]), right=vector([1, 0]))
|
|
901
|
+
sage: hash(S) # random
|
|
902
|
+
42
|
|
903
|
+
"""
|
|
904
|
+
return hash((self.mu, self.left, self.right))
|
|
905
|
+
|
|
906
|
+
def __eq__(self, other):
|
|
907
|
+
r"""
|
|
908
|
+
Return whether this recognizable series is equal to ``other``.
|
|
909
|
+
|
|
910
|
+
INPUT:
|
|
911
|
+
|
|
912
|
+
- ``other`` -- an object
|
|
913
|
+
|
|
914
|
+
OUTPUT: boolean
|
|
915
|
+
|
|
916
|
+
.. NOTE::
|
|
917
|
+
|
|
918
|
+
This function uses the coercion model to find a common
|
|
919
|
+
parent for the two operands.
|
|
920
|
+
|
|
921
|
+
EXAMPLES::
|
|
922
|
+
|
|
923
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
924
|
+
sage: S = Rec((Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [0, 1]])),
|
|
925
|
+
....: left=vector([1, 1]), right=vector([1, 0]))
|
|
926
|
+
sage: S
|
|
927
|
+
[] + [0] + [1] + [00] + [01] + [10]
|
|
928
|
+
+ [11] + [000] + [001] + [010] + ...
|
|
929
|
+
sage: Z1 = Rec((Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [0, 1]])),
|
|
930
|
+
....: left=vector([0, 1]), right=vector([1, 0]))
|
|
931
|
+
sage: Z1
|
|
932
|
+
0 + ...
|
|
933
|
+
sage: Z2 = Rec((Matrix([[0, 0], [0, 0]]), Matrix([[0, 0], [0, 0]])),
|
|
934
|
+
....: left=vector([0, 1]), right=vector([1, 0]))
|
|
935
|
+
sage: Z2
|
|
936
|
+
0
|
|
937
|
+
sage: S == Z1
|
|
938
|
+
False
|
|
939
|
+
sage: S == Z2
|
|
940
|
+
False
|
|
941
|
+
sage: Z1 == Z2
|
|
942
|
+
True
|
|
943
|
+
|
|
944
|
+
TESTS::
|
|
945
|
+
|
|
946
|
+
sage: S == S
|
|
947
|
+
True
|
|
948
|
+
sage: S == None
|
|
949
|
+
False
|
|
950
|
+
"""
|
|
951
|
+
if other is None:
|
|
952
|
+
return False
|
|
953
|
+
try:
|
|
954
|
+
return not bool(self - other)
|
|
955
|
+
except (TypeError, ValueError):
|
|
956
|
+
return False
|
|
957
|
+
|
|
958
|
+
def __ne__(self, other):
|
|
959
|
+
r"""
|
|
960
|
+
Return whether this recognizable series is not equal to ``other``.
|
|
961
|
+
|
|
962
|
+
INPUT:
|
|
963
|
+
|
|
964
|
+
- ``other`` -- an object
|
|
965
|
+
|
|
966
|
+
OUTPUT: boolean
|
|
967
|
+
|
|
968
|
+
.. NOTE::
|
|
969
|
+
|
|
970
|
+
This function uses the coercion model to find a common
|
|
971
|
+
parent for the two operands.
|
|
972
|
+
|
|
973
|
+
EXAMPLES::
|
|
974
|
+
|
|
975
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
976
|
+
sage: Z1 = Rec((Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [0, 1]])),
|
|
977
|
+
....: left=vector([0, 1]), right=vector([1, 0]))
|
|
978
|
+
sage: Z2 = Rec((Matrix([[0, 0], [0, 0]]), Matrix([[0, 0], [0, 0]])),
|
|
979
|
+
....: left=vector([0, 1]), right=vector([1, 0]))
|
|
980
|
+
sage: Z1 != Z2
|
|
981
|
+
False
|
|
982
|
+
sage: Z1 != Z1
|
|
983
|
+
False
|
|
984
|
+
"""
|
|
985
|
+
return not self == other
|
|
986
|
+
|
|
987
|
+
def transposed(self):
|
|
988
|
+
r"""
|
|
989
|
+
Return the transposed series.
|
|
990
|
+
|
|
991
|
+
OUTPUT: a :class:`RecognizableSeries`
|
|
992
|
+
|
|
993
|
+
Each of the matrices in :meth:`mu <mu>` is transposed. Additionally
|
|
994
|
+
the vectors :meth:`left <left>` and :meth:`right <right>` are switched.
|
|
995
|
+
|
|
996
|
+
EXAMPLES::
|
|
997
|
+
|
|
998
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
999
|
+
sage: S = Rec((Matrix([[3, 6], [0, 1]]), Matrix([[0, -6], [1, 5]])),
|
|
1000
|
+
....: vector([0, 1]), vector([1, 0])).transposed()
|
|
1001
|
+
sage: S
|
|
1002
|
+
[1] + 3*[01] + [10] + 5*[11] + 9*[001] + 3*[010]
|
|
1003
|
+
+ 15*[011] + [100] + 11*[101] + 5*[110] + ...
|
|
1004
|
+
sage: S.mu[0], S.mu[1], S.left, S.right
|
|
1005
|
+
(
|
|
1006
|
+
[3 0] [ 0 1]
|
|
1007
|
+
[6 1], [-6 5], (1, 0), (0, 1)
|
|
1008
|
+
)
|
|
1009
|
+
sage: T = S.transposed()
|
|
1010
|
+
sage: T
|
|
1011
|
+
[1] + [01] + 3*[10] + 5*[11] + [001] + 3*[010]
|
|
1012
|
+
+ 5*[011] + 9*[100] + 11*[101] + 15*[110] + ...
|
|
1013
|
+
sage: T.mu[0], T.mu[1], T.left, T.right
|
|
1014
|
+
(
|
|
1015
|
+
[3 6] [ 0 -6]
|
|
1016
|
+
[0 1], [ 1 5], (0, 1), (1, 0)
|
|
1017
|
+
)
|
|
1018
|
+
|
|
1019
|
+
TESTS::
|
|
1020
|
+
|
|
1021
|
+
sage: T.mu[0].is_immutable(), T.mu[1].is_immutable(), T.left.is_immutable(), T.right.is_immutable()
|
|
1022
|
+
(True, True, True, True)
|
|
1023
|
+
"""
|
|
1024
|
+
def tr(M):
|
|
1025
|
+
T = M.transpose()
|
|
1026
|
+
T.set_immutable()
|
|
1027
|
+
return T
|
|
1028
|
+
|
|
1029
|
+
P = self.parent()
|
|
1030
|
+
return P.element_class(P, self.mu.map(tr),
|
|
1031
|
+
left=self.right,
|
|
1032
|
+
right=self.left)
|
|
1033
|
+
|
|
1034
|
+
@cached_method
|
|
1035
|
+
def minimized(self):
|
|
1036
|
+
r"""
|
|
1037
|
+
Return a recognizable series equivalent to this series, but
|
|
1038
|
+
with a minimized linear representation.
|
|
1039
|
+
|
|
1040
|
+
The coefficients of the involved matrices need be in a field.
|
|
1041
|
+
If this is not the case, then the coefficients are
|
|
1042
|
+
automatically coerced to their fraction field.
|
|
1043
|
+
|
|
1044
|
+
OUTPUT: a :class:`RecognizableSeries`
|
|
1045
|
+
|
|
1046
|
+
ALGORITHM:
|
|
1047
|
+
|
|
1048
|
+
This method implements the minimization algorithm presented in
|
|
1049
|
+
Chapter 2 of [BR2010a]_.
|
|
1050
|
+
|
|
1051
|
+
.. NOTE::
|
|
1052
|
+
|
|
1053
|
+
Due to the algorithm, the left vector of the result
|
|
1054
|
+
is always `(1, 0, \ldots, 0)`, i.e., the first vector of the
|
|
1055
|
+
standard basis.
|
|
1056
|
+
|
|
1057
|
+
EXAMPLES::
|
|
1058
|
+
|
|
1059
|
+
sage: from itertools import islice
|
|
1060
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
1061
|
+
|
|
1062
|
+
sage: S = Rec((Matrix([[3, 6], [0, 1]]), Matrix([[0, -6], [1, 5]])),
|
|
1063
|
+
....: vector([0, 1]), vector([1, 0])).transposed()
|
|
1064
|
+
sage: S
|
|
1065
|
+
[1] + 3*[01] + [10] + 5*[11] + 9*[001] + 3*[010]
|
|
1066
|
+
+ 15*[011] + [100] + 11*[101] + 5*[110] + ...
|
|
1067
|
+
sage: M = S.minimized()
|
|
1068
|
+
sage: M.mu[0], M.mu[1], M.left, M.right
|
|
1069
|
+
(
|
|
1070
|
+
[3 0] [ 0 1]
|
|
1071
|
+
[6 1], [-6 5], (1, 0), (0, 1)
|
|
1072
|
+
)
|
|
1073
|
+
sage: M.left == vector([1, 0])
|
|
1074
|
+
True
|
|
1075
|
+
sage: all(c == d and v == w
|
|
1076
|
+
....: for (c, v), (d, w) in islice(zip(iter(S), iter(M)), 20))
|
|
1077
|
+
True
|
|
1078
|
+
|
|
1079
|
+
sage: S = Rec((Matrix([[2, 0], [1, 1]]), Matrix([[2, 0], [2, 1]])),
|
|
1080
|
+
....: vector([1, 0]), vector([1, 1]))
|
|
1081
|
+
sage: S
|
|
1082
|
+
[] + 2*[0] + 2*[1] + 4*[00] + 4*[01] + 4*[10] + 4*[11]
|
|
1083
|
+
+ 8*[000] + 8*[001] + 8*[010] + ...
|
|
1084
|
+
sage: M = S.minimized()
|
|
1085
|
+
sage: M.mu[0], M.mu[1], M.left, M.right
|
|
1086
|
+
([2], [2], (1), (1))
|
|
1087
|
+
sage: all(c == d and v == w
|
|
1088
|
+
....: for (c, v), (d, w) in islice(zip(iter(S), iter(M)), 20))
|
|
1089
|
+
True
|
|
1090
|
+
|
|
1091
|
+
TESTS::
|
|
1092
|
+
|
|
1093
|
+
sage: Rec((Matrix([[0]]), Matrix([[0]])),
|
|
1094
|
+
....: vector([1]), vector([0])).minimized().linear_representation()
|
|
1095
|
+
((), Finite family {0: [], 1: []}, ())
|
|
1096
|
+
"""
|
|
1097
|
+
return self._minimized_right_()._minimized_left_()
|
|
1098
|
+
|
|
1099
|
+
def _minimized_right_(self):
|
|
1100
|
+
r"""
|
|
1101
|
+
Return a recognizable series equivalent to this series, but
|
|
1102
|
+
with a right minimized linear representation.
|
|
1103
|
+
|
|
1104
|
+
OUTPUT: a :class:`RecognizableSeries`
|
|
1105
|
+
|
|
1106
|
+
See :meth:`minimized` for details.
|
|
1107
|
+
|
|
1108
|
+
TESTS::
|
|
1109
|
+
|
|
1110
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
1111
|
+
sage: S = Rec((Matrix([[0, 0], [0, 0]]), Matrix([[0, 0], [0, 0]])),
|
|
1112
|
+
....: vector([1, 1]), vector([1, 1]))
|
|
1113
|
+
sage: M = S._minimized_right_()
|
|
1114
|
+
sage: M.mu[0], M.mu[1], M.left, M.right
|
|
1115
|
+
([0], [0], (2), (1))
|
|
1116
|
+
"""
|
|
1117
|
+
return self.transposed()._minimized_left_().transposed()
|
|
1118
|
+
|
|
1119
|
+
def _minimized_left_(self):
|
|
1120
|
+
r"""
|
|
1121
|
+
Return a recognizable series equivalent to this series, but
|
|
1122
|
+
with a left minimized linear representation.
|
|
1123
|
+
|
|
1124
|
+
OUTPUT: a :class:`RecognizableSeries`
|
|
1125
|
+
|
|
1126
|
+
See :meth:`minimized` for details.
|
|
1127
|
+
|
|
1128
|
+
TESTS::
|
|
1129
|
+
|
|
1130
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
1131
|
+
sage: S = Rec((Matrix([[0, 0], [0, 0]]), Matrix([[0, 0], [0, 0]])),
|
|
1132
|
+
....: vector([1, 1]), vector([1, 1]))
|
|
1133
|
+
sage: M = S._minimized_left_()
|
|
1134
|
+
sage: M.mu[0], M.mu[1], M.left, M.right
|
|
1135
|
+
([0], [0], (1), (2))
|
|
1136
|
+
sage: M = S.minimized()
|
|
1137
|
+
sage: M.mu[0], M.mu[1], M.left, M.right
|
|
1138
|
+
([0], [0], (1), (2))
|
|
1139
|
+
|
|
1140
|
+
::
|
|
1141
|
+
|
|
1142
|
+
sage: S = Rec((Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [0, 1]])),
|
|
1143
|
+
....: vector([1, -1]), vector([1, 1]))._minimized_left_()
|
|
1144
|
+
sage: S.mu[0], S.mu[1], S.left, S.right
|
|
1145
|
+
([1], [1], (1), (0))
|
|
1146
|
+
sage: M = S.minimized()
|
|
1147
|
+
sage: M.mu[0], M.mu[1], M.left, M.right
|
|
1148
|
+
([], [], (), ())
|
|
1149
|
+
|
|
1150
|
+
sage: S = Rec((Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [0, 1]])),
|
|
1151
|
+
....: vector([1, 1]), vector([1, -1]))
|
|
1152
|
+
sage: M = S._minimized_left_()
|
|
1153
|
+
sage: M.mu[0], M.mu[1], M.left, M.right
|
|
1154
|
+
([1], [1], (1), (0))
|
|
1155
|
+
sage: M = S.minimized()
|
|
1156
|
+
sage: M.mu[0], M.mu[1], M.left, M.right
|
|
1157
|
+
([], [], (), ())
|
|
1158
|
+
|
|
1159
|
+
sage: S = Rec((Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [0, 1]])),
|
|
1160
|
+
....: left=vector([0, 1]), right=vector([1, 0]))
|
|
1161
|
+
sage: M = S._minimized_left_()
|
|
1162
|
+
sage: M.mu[0], M.mu[1], M.left, M.right
|
|
1163
|
+
([1], [1], (1), (0))
|
|
1164
|
+
sage: M = S.minimized()
|
|
1165
|
+
sage: M.mu[0], M.mu[1], M.left, M.right
|
|
1166
|
+
([], [], (), ())
|
|
1167
|
+
"""
|
|
1168
|
+
from sage.matrix.constructor import Matrix
|
|
1169
|
+
from sage.modules.free_module_element import vector
|
|
1170
|
+
from sage.rings.integer_ring import ZZ
|
|
1171
|
+
|
|
1172
|
+
pcs = PrefixClosedSet(self.parent().indices())
|
|
1173
|
+
left = self.coefficient_of_word(pcs.elements[0], multiply_right=False)
|
|
1174
|
+
if left.is_zero():
|
|
1175
|
+
return self.parent().zero()
|
|
1176
|
+
Left = [left]
|
|
1177
|
+
for p in pcs.iterate_possible_additions():
|
|
1178
|
+
left = self.coefficient_of_word(p,
|
|
1179
|
+
multiply_left=True,
|
|
1180
|
+
multiply_right=False)
|
|
1181
|
+
try:
|
|
1182
|
+
Matrix(Left).solve_left(left)
|
|
1183
|
+
except ValueError:
|
|
1184
|
+
# no solution found
|
|
1185
|
+
pcs.add(p)
|
|
1186
|
+
Left.append(left)
|
|
1187
|
+
P = pcs.elements
|
|
1188
|
+
C = pcs.prefix_set()
|
|
1189
|
+
|
|
1190
|
+
ML = Matrix(Left)
|
|
1191
|
+
|
|
1192
|
+
def alpha(c):
|
|
1193
|
+
return ML.solve_left(self.coefficient_of_word(c, multiply_right=False))
|
|
1194
|
+
|
|
1195
|
+
mu_prime = []
|
|
1196
|
+
for a in self.parent().alphabet():
|
|
1197
|
+
a = self.parent().indices()([a])
|
|
1198
|
+
M = Matrix([alpha(c) if c in C else tuple(ZZ(c == q) for q in P)
|
|
1199
|
+
for c in (p + a for p in P)])
|
|
1200
|
+
mu_prime.append(M)
|
|
1201
|
+
|
|
1202
|
+
left_prime = vector([ZZ.one()] + (len(P) - 1) * [ZZ.zero()])
|
|
1203
|
+
right_prime = vector(self.coefficient_of_word(p) for p in P)
|
|
1204
|
+
|
|
1205
|
+
P = self.parent()
|
|
1206
|
+
return P.element_class(P, mu_prime, left_prime, right_prime)
|
|
1207
|
+
|
|
1208
|
+
def dimension(self):
|
|
1209
|
+
r"""
|
|
1210
|
+
Return the dimension of this recognizable series.
|
|
1211
|
+
|
|
1212
|
+
EXAMPLES::
|
|
1213
|
+
|
|
1214
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
1215
|
+
sage: Rec((Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [0, 1]])),
|
|
1216
|
+
....: left=vector([0, 1]), right=vector([1, 0])).dimension()
|
|
1217
|
+
2
|
|
1218
|
+
"""
|
|
1219
|
+
return self.mu.first().nrows()
|
|
1220
|
+
|
|
1221
|
+
@minimize_result
|
|
1222
|
+
def _add_(self, other):
|
|
1223
|
+
r"""
|
|
1224
|
+
Return the sum of this recognizable series and the ``other``
|
|
1225
|
+
recognizable series.
|
|
1226
|
+
|
|
1227
|
+
INPUT:
|
|
1228
|
+
|
|
1229
|
+
- ``other`` -- a :class:`RecognizableSeries` with the same parent
|
|
1230
|
+
as this recognizable series
|
|
1231
|
+
|
|
1232
|
+
- ``minimize`` -- (default: ``None``) a boolean or ``None``.
|
|
1233
|
+
If ``True``, then :meth:`minimized` is called after the operation,
|
|
1234
|
+
if ``False``, then not. If this argument is ``None``, then
|
|
1235
|
+
the default specified by the parent's ``minimize_results`` is used.
|
|
1236
|
+
|
|
1237
|
+
OUTPUT: a :class:`RecognizableSeries`
|
|
1238
|
+
|
|
1239
|
+
EXAMPLES::
|
|
1240
|
+
|
|
1241
|
+
sage: Seq2 = RegularSequenceRing(2, ZZ)
|
|
1242
|
+
sage: E = Seq2((Matrix([[0, 1], [0, 1]]), Matrix([[0, 0], [0, 1]])),
|
|
1243
|
+
....: vector([1, 0]), vector([1, 1]))
|
|
1244
|
+
sage: E
|
|
1245
|
+
2-regular sequence 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, ...
|
|
1246
|
+
sage: O = Seq2((Matrix([[0, 0], [0, 1]]), Matrix([[0, 1], [0, 1]])),
|
|
1247
|
+
....: vector([1, 0]), vector([0, 1]))
|
|
1248
|
+
sage: O
|
|
1249
|
+
2-regular sequence 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, ...
|
|
1250
|
+
sage: I = E + O # indirect doctest
|
|
1251
|
+
sage: I
|
|
1252
|
+
2-regular sequence 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
|
|
1253
|
+
sage: I.linear_representation()
|
|
1254
|
+
((1),
|
|
1255
|
+
Finite family {0: [1],
|
|
1256
|
+
1: [1]},
|
|
1257
|
+
(1))
|
|
1258
|
+
"""
|
|
1259
|
+
from sage.modules.free_module_element import vector
|
|
1260
|
+
P = self.parent()
|
|
1261
|
+
|
|
1262
|
+
result = P.element_class(
|
|
1263
|
+
P,
|
|
1264
|
+
{a: self.mu[a].block_sum(other.mu[a]) for a in P.alphabet()},
|
|
1265
|
+
vector(tuple(self.left) + tuple(other.left)),
|
|
1266
|
+
vector(tuple(self.right) + tuple(other.right)))
|
|
1267
|
+
|
|
1268
|
+
return result
|
|
1269
|
+
|
|
1270
|
+
def _neg_(self):
|
|
1271
|
+
r"""
|
|
1272
|
+
Return the additive inverse of this recognizable series.
|
|
1273
|
+
|
|
1274
|
+
OUTPUT: a :class:`RecognizableSeries`
|
|
1275
|
+
|
|
1276
|
+
EXAMPLES::
|
|
1277
|
+
|
|
1278
|
+
sage: Seq2 = RegularSequenceRing(2, ZZ)
|
|
1279
|
+
sage: E = Seq2((Matrix([[0, 1], [0, 1]]), Matrix([[0, 0], [0, 1]])),
|
|
1280
|
+
....: vector([1, 0]), vector([1, 1]))
|
|
1281
|
+
sage: -E
|
|
1282
|
+
2-regular sequence -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, ...
|
|
1283
|
+
sage: Z = E - E
|
|
1284
|
+
sage: Z.is_trivial_zero()
|
|
1285
|
+
True
|
|
1286
|
+
"""
|
|
1287
|
+
P = self.parent()
|
|
1288
|
+
return P.element_class(P, self.mu, -self.left, self.right)
|
|
1289
|
+
|
|
1290
|
+
def _rmul_(self, other):
|
|
1291
|
+
r"""
|
|
1292
|
+
Multiply this recognizable series from the right
|
|
1293
|
+
by an element ``other`` of its coefficient (semi-)ring.
|
|
1294
|
+
|
|
1295
|
+
INPUT:
|
|
1296
|
+
|
|
1297
|
+
- ``other`` -- an element of the coefficient (semi-)ring
|
|
1298
|
+
|
|
1299
|
+
OUTPUT: a :class:`RecognizableSeries`
|
|
1300
|
+
|
|
1301
|
+
EXAMPLES::
|
|
1302
|
+
|
|
1303
|
+
sage: Seq2 = RegularSequenceRing(2, ZZ)
|
|
1304
|
+
sage: E = Seq2((Matrix([[0, 1], [0, 1]]), Matrix([[0, 0], [0, 1]])),
|
|
1305
|
+
....: vector([1, 0]), vector([1, 1]))
|
|
1306
|
+
sage: M = 2 * E # indirect doctest
|
|
1307
|
+
sage: M
|
|
1308
|
+
2-regular sequence 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, ...
|
|
1309
|
+
sage: M.linear_representation()
|
|
1310
|
+
((2, 0),
|
|
1311
|
+
Finite family {0: [0 1]
|
|
1312
|
+
[0 1],
|
|
1313
|
+
1: [0 0]
|
|
1314
|
+
[0 1]},
|
|
1315
|
+
(1, 1))
|
|
1316
|
+
|
|
1317
|
+
TESTS::
|
|
1318
|
+
|
|
1319
|
+
sage: 1 * E is E
|
|
1320
|
+
True
|
|
1321
|
+
|
|
1322
|
+
::
|
|
1323
|
+
|
|
1324
|
+
sage: 0 * E is Seq2.zero()
|
|
1325
|
+
True
|
|
1326
|
+
|
|
1327
|
+
We test that ``_rmul_`` and ``_lmul_`` are actually called::
|
|
1328
|
+
|
|
1329
|
+
sage: def print_name(f):
|
|
1330
|
+
....: def f_with_printed_name(*args, **kwds):
|
|
1331
|
+
....: print(f.__name__)
|
|
1332
|
+
....: return f(*args, **kwds)
|
|
1333
|
+
....: return f_with_printed_name
|
|
1334
|
+
|
|
1335
|
+
sage: E._rmul_ = print_name(E._rmul_)
|
|
1336
|
+
sage: E._lmul_ = print_name(E._lmul_)
|
|
1337
|
+
sage: 2 * E
|
|
1338
|
+
_rmul_
|
|
1339
|
+
2-regular sequence 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, ...
|
|
1340
|
+
sage: E * 2
|
|
1341
|
+
_lmul_
|
|
1342
|
+
_lmul_
|
|
1343
|
+
2-regular sequence 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, ...
|
|
1344
|
+
"""
|
|
1345
|
+
P = self.parent()
|
|
1346
|
+
if other.is_zero():
|
|
1347
|
+
return P._zero_()
|
|
1348
|
+
if other.is_one():
|
|
1349
|
+
return self
|
|
1350
|
+
return P.element_class(P, self.mu, other * self.left, self.right)
|
|
1351
|
+
|
|
1352
|
+
def _lmul_(self, other):
|
|
1353
|
+
r"""
|
|
1354
|
+
Multiply this recognizable series from the left
|
|
1355
|
+
by an element ``other`` of its coefficient (semi-)ring.
|
|
1356
|
+
|
|
1357
|
+
INPUT:
|
|
1358
|
+
|
|
1359
|
+
- ``other`` -- an element of the coefficient (semi-)ring
|
|
1360
|
+
|
|
1361
|
+
OUTPUT: a :class:`RecognizableSeries`
|
|
1362
|
+
|
|
1363
|
+
EXAMPLES::
|
|
1364
|
+
|
|
1365
|
+
sage: Seq2 = RegularSequenceRing(2, ZZ)
|
|
1366
|
+
sage: E = Seq2((Matrix([[0, 1], [0, 1]]), Matrix([[0, 0], [0, 1]])),
|
|
1367
|
+
....: vector([1, 0]), vector([1, 1]))
|
|
1368
|
+
sage: M = E * 2 # indirect doctest
|
|
1369
|
+
sage: M
|
|
1370
|
+
2-regular sequence 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, ...
|
|
1371
|
+
sage: M.linear_representation()
|
|
1372
|
+
((1, 0),
|
|
1373
|
+
Finite family {0: [0 1]
|
|
1374
|
+
[0 1],
|
|
1375
|
+
1: [0 0]
|
|
1376
|
+
[0 1]},
|
|
1377
|
+
(2, 2))
|
|
1378
|
+
|
|
1379
|
+
TESTS::
|
|
1380
|
+
|
|
1381
|
+
sage: E * 1 is E
|
|
1382
|
+
True
|
|
1383
|
+
|
|
1384
|
+
::
|
|
1385
|
+
|
|
1386
|
+
sage: E * 0 is Seq2.zero()
|
|
1387
|
+
True
|
|
1388
|
+
|
|
1389
|
+
The following is not tested, as `MS^i` for integers `i` does
|
|
1390
|
+
not work, thus ``vector([m])`` fails. (See :issue:`21317` for
|
|
1391
|
+
details.)
|
|
1392
|
+
|
|
1393
|
+
::
|
|
1394
|
+
|
|
1395
|
+
sage: MS = MatrixSpace(ZZ,2,2)
|
|
1396
|
+
sage: Rec = RecognizableSeriesSpace(MS, [0, 1])
|
|
1397
|
+
sage: m = MS.an_element()
|
|
1398
|
+
sage: S = Rec((Matrix([[m]]), Matrix([[m]])), # not tested
|
|
1399
|
+
....: vector([m]), vector([m]))
|
|
1400
|
+
sage: S # not tested
|
|
1401
|
+
sage: M = m * S # not tested indirect doctest
|
|
1402
|
+
sage: M # not tested
|
|
1403
|
+
sage: M.linear_representation() # not tested
|
|
1404
|
+
"""
|
|
1405
|
+
P = self.parent()
|
|
1406
|
+
if other.is_zero():
|
|
1407
|
+
return P._zero_()
|
|
1408
|
+
if other.is_one():
|
|
1409
|
+
return self
|
|
1410
|
+
return P.element_class(P, self.mu, self.left, self.right * other)
|
|
1411
|
+
|
|
1412
|
+
@minimize_result
|
|
1413
|
+
def hadamard_product(self, other):
|
|
1414
|
+
r"""
|
|
1415
|
+
Return the Hadamard product of this recognizable series
|
|
1416
|
+
and the ``other`` recognizable series, i.e., multiply the two
|
|
1417
|
+
series coefficient-wise.
|
|
1418
|
+
|
|
1419
|
+
INPUT:
|
|
1420
|
+
|
|
1421
|
+
- ``other`` -- a :class:`RecognizableSeries` with the same parent
|
|
1422
|
+
as this recognizable series
|
|
1423
|
+
|
|
1424
|
+
- ``minimize`` -- (default: ``None``) a boolean or ``None``.
|
|
1425
|
+
If ``True``, then :meth:`minimized` is called after the operation,
|
|
1426
|
+
if ``False``, then not. If this argument is ``None``, then
|
|
1427
|
+
the default specified by the parent's ``minimize_results`` is used.
|
|
1428
|
+
|
|
1429
|
+
OUTPUT: a :class:`RecognizableSeries`
|
|
1430
|
+
|
|
1431
|
+
EXAMPLES::
|
|
1432
|
+
|
|
1433
|
+
sage: Seq2 = RegularSequenceRing(2, ZZ)
|
|
1434
|
+
|
|
1435
|
+
sage: E = Seq2((Matrix([[0, 1], [0, 1]]), Matrix([[0, 0], [0, 1]])),
|
|
1436
|
+
....: vector([1, 0]), vector([1, 1]))
|
|
1437
|
+
sage: E
|
|
1438
|
+
2-regular sequence 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, ...
|
|
1439
|
+
|
|
1440
|
+
sage: O = Seq2((Matrix([[0, 0], [0, 1]]), Matrix([[0, 1], [0, 1]])),
|
|
1441
|
+
....: vector([1, 0]), vector([0, 1]))
|
|
1442
|
+
sage: O
|
|
1443
|
+
2-regular sequence 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, ...
|
|
1444
|
+
|
|
1445
|
+
sage: C = Seq2((Matrix([[2, 0], [2, 1]]), Matrix([[0, 1], [-2, 3]])),
|
|
1446
|
+
....: vector([1, 0]), vector([0, 1]))
|
|
1447
|
+
sage: C
|
|
1448
|
+
2-regular sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...
|
|
1449
|
+
|
|
1450
|
+
::
|
|
1451
|
+
|
|
1452
|
+
sage: CE = C.hadamard_product(E)
|
|
1453
|
+
sage: CE
|
|
1454
|
+
2-regular sequence 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, ...
|
|
1455
|
+
sage: CE.linear_representation()
|
|
1456
|
+
((1, 0, 0),
|
|
1457
|
+
Finite family {0: [0 1 0]
|
|
1458
|
+
[0 2 0]
|
|
1459
|
+
[0 2 1],
|
|
1460
|
+
1: [ 0 0 0]
|
|
1461
|
+
[ 0 0 1]
|
|
1462
|
+
[ 0 -2 3]},
|
|
1463
|
+
(0, 0, 2))
|
|
1464
|
+
|
|
1465
|
+
sage: Z = E.hadamard_product(O)
|
|
1466
|
+
sage: Z
|
|
1467
|
+
2-regular sequence 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
|
|
1468
|
+
sage: Z.linear_representation()
|
|
1469
|
+
((),
|
|
1470
|
+
Finite family {0: [],
|
|
1471
|
+
1: []},
|
|
1472
|
+
())
|
|
1473
|
+
|
|
1474
|
+
TESTS::
|
|
1475
|
+
|
|
1476
|
+
sage: EC = E.hadamard_product(C, minimize=False)
|
|
1477
|
+
sage: EC
|
|
1478
|
+
2-regular sequence 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, ...
|
|
1479
|
+
sage: EC.linear_representation()
|
|
1480
|
+
((1, 0, 0, 0),
|
|
1481
|
+
Finite family {0: [0 0 2 0]
|
|
1482
|
+
[0 0 2 1]
|
|
1483
|
+
[0 0 2 0]
|
|
1484
|
+
[0 0 2 1],
|
|
1485
|
+
1: [ 0 0 0 0]
|
|
1486
|
+
[ 0 0 0 0]
|
|
1487
|
+
[ 0 0 0 1]
|
|
1488
|
+
[ 0 0 -2 3]},
|
|
1489
|
+
(0, 1, 0, 1))
|
|
1490
|
+
sage: MEC = EC.minimized()
|
|
1491
|
+
sage: MEC
|
|
1492
|
+
2-regular sequence 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, ...
|
|
1493
|
+
sage: MEC.linear_representation()
|
|
1494
|
+
((1, 0, 0),
|
|
1495
|
+
Finite family {0: [0 1 0]
|
|
1496
|
+
[0 2 0]
|
|
1497
|
+
[0 2 1],
|
|
1498
|
+
1: [ 0 0 0]
|
|
1499
|
+
[ 0 0 1]
|
|
1500
|
+
[ 0 -2 3]},
|
|
1501
|
+
(0, 0, 2))
|
|
1502
|
+
"""
|
|
1503
|
+
from sage.matrix.constructor import Matrix
|
|
1504
|
+
from sage.modules.free_module_element import vector
|
|
1505
|
+
P = self.parent()
|
|
1506
|
+
|
|
1507
|
+
def tensor_product(left, right):
|
|
1508
|
+
T = left.tensor_product(right)
|
|
1509
|
+
T.subdivide()
|
|
1510
|
+
return T
|
|
1511
|
+
result = P.element_class(
|
|
1512
|
+
P,
|
|
1513
|
+
{a: tensor_product(self.mu[a], other.mu[a]) for a in P.alphabet()},
|
|
1514
|
+
vector(tensor_product(Matrix(self.left), Matrix(other.left))),
|
|
1515
|
+
vector(tensor_product(Matrix(self.right), Matrix(other.right))))
|
|
1516
|
+
|
|
1517
|
+
return result
|
|
1518
|
+
|
|
1519
|
+
|
|
1520
|
+
def _pickle_RecognizableSeriesSpace(coefficients, indices, category):
|
|
1521
|
+
r"""
|
|
1522
|
+
Pickle helper.
|
|
1523
|
+
|
|
1524
|
+
TESTS::
|
|
1525
|
+
|
|
1526
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
1527
|
+
sage: from sage.combinat.recognizable_series import _pickle_RecognizableSeriesSpace
|
|
1528
|
+
sage: _pickle_RecognizableSeriesSpace(
|
|
1529
|
+
....: Rec.coefficient_ring(), Rec.indices(), Rec.category())
|
|
1530
|
+
Space of recognizable series on {0, 1} with coefficients in Integer Ring
|
|
1531
|
+
"""
|
|
1532
|
+
return RecognizableSeriesSpace(coefficients, indices=indices, category=category)
|
|
1533
|
+
|
|
1534
|
+
|
|
1535
|
+
class RecognizableSeriesSpace(UniqueRepresentation, Parent):
|
|
1536
|
+
r"""
|
|
1537
|
+
The space of recognizable series on the given alphabet and
|
|
1538
|
+
with the given coefficients.
|
|
1539
|
+
|
|
1540
|
+
INPUT:
|
|
1541
|
+
|
|
1542
|
+
- ``coefficient_ring`` -- a (semi-)ring
|
|
1543
|
+
|
|
1544
|
+
- ``alphabet`` -- tuple, list or
|
|
1545
|
+
:class:`~sage.sets.totally_ordered_finite_set.TotallyOrderedFiniteSet`.
|
|
1546
|
+
If specified, then the ``indices`` are the
|
|
1547
|
+
finite words over this ``alphabet``.
|
|
1548
|
+
``alphabet`` and ``indices`` cannot be specified
|
|
1549
|
+
at the same time.
|
|
1550
|
+
|
|
1551
|
+
- ``indices`` -- a SageMath-parent of finite words over an alphabet.
|
|
1552
|
+
``alphabet`` and ``indices`` cannot be specified
|
|
1553
|
+
at the same time.
|
|
1554
|
+
|
|
1555
|
+
- ``category`` -- (default: ``None``) the category of this
|
|
1556
|
+
space
|
|
1557
|
+
|
|
1558
|
+
EXAMPLES:
|
|
1559
|
+
|
|
1560
|
+
We create a recognizable series that counts the number of ones in each word::
|
|
1561
|
+
|
|
1562
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
1563
|
+
sage: Rec
|
|
1564
|
+
Space of recognizable series on {0, 1} with coefficients in Integer Ring
|
|
1565
|
+
sage: Rec((Matrix([[1, 0], [0, 1]]), Matrix([[1, 1], [0, 1]])),
|
|
1566
|
+
....: vector([1, 0]), vector([0, 1]))
|
|
1567
|
+
[1] + [01] + [10] + 2*[11] + [001] + [010] + 2*[011] + [100] + 2*[101] + 2*[110] + ...
|
|
1568
|
+
|
|
1569
|
+
All of the following examples create the same space::
|
|
1570
|
+
|
|
1571
|
+
sage: Rec1 = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
1572
|
+
sage: Rec1
|
|
1573
|
+
Space of recognizable series on {0, 1} with coefficients in Integer Ring
|
|
1574
|
+
sage: Rec2 = RecognizableSeriesSpace(coefficient_ring=ZZ, alphabet=[0, 1])
|
|
1575
|
+
sage: Rec2
|
|
1576
|
+
Space of recognizable series on {0, 1} with coefficients in Integer Ring
|
|
1577
|
+
sage: Rec3 = RecognizableSeriesSpace(ZZ, indices=Words([0, 1], infinite=False))
|
|
1578
|
+
sage: Rec3
|
|
1579
|
+
Space of recognizable series on {0, 1} with coefficients in Integer Ring
|
|
1580
|
+
|
|
1581
|
+
.. SEEALSO::
|
|
1582
|
+
|
|
1583
|
+
:doc:`recognizable series <recognizable_series>`,
|
|
1584
|
+
:class:`RecognizableSeries`.
|
|
1585
|
+
"""
|
|
1586
|
+
Element = RecognizableSeries
|
|
1587
|
+
|
|
1588
|
+
@staticmethod
|
|
1589
|
+
def __classcall__(cls, *args, **kwds):
|
|
1590
|
+
r"""
|
|
1591
|
+
Prepare normalizing the input in order to ensure a
|
|
1592
|
+
unique representation.
|
|
1593
|
+
|
|
1594
|
+
For more information see :class:`RecognizableSeriesSpace`
|
|
1595
|
+
and :meth:`__normalize__`.
|
|
1596
|
+
|
|
1597
|
+
TESTS::
|
|
1598
|
+
|
|
1599
|
+
sage: Rec1 = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
1600
|
+
sage: Rec1
|
|
1601
|
+
Space of recognizable series on {0, 1} with coefficients in Integer Ring
|
|
1602
|
+
sage: Rec2 = RecognizableSeriesSpace(coefficient_ring=ZZ, alphabet=[0, 1])
|
|
1603
|
+
sage: Rec2
|
|
1604
|
+
Space of recognizable series on {0, 1} with coefficients in Integer Ring
|
|
1605
|
+
sage: Rec3 = RecognizableSeriesSpace(ZZ, indices=Words([0, 1], infinite=False))
|
|
1606
|
+
sage: Rec3
|
|
1607
|
+
Space of recognizable series on {0, 1} with coefficients in Integer Ring
|
|
1608
|
+
sage: Rec1 is Rec2 is Rec3
|
|
1609
|
+
True
|
|
1610
|
+
"""
|
|
1611
|
+
return super().__classcall__(
|
|
1612
|
+
cls, *cls.__normalize__(*args, **kwds))
|
|
1613
|
+
|
|
1614
|
+
@classmethod
|
|
1615
|
+
def __normalize__(cls,
|
|
1616
|
+
coefficient_ring=None,
|
|
1617
|
+
alphabet=None, indices=None,
|
|
1618
|
+
category=None,
|
|
1619
|
+
minimize_results=True):
|
|
1620
|
+
r"""
|
|
1621
|
+
Normalize the input in order to ensure a unique
|
|
1622
|
+
representation.
|
|
1623
|
+
|
|
1624
|
+
For more information see :class:`RecognizableSeriesSpace`.
|
|
1625
|
+
|
|
1626
|
+
TESTS::
|
|
1627
|
+
|
|
1628
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1]) # indirect doctest
|
|
1629
|
+
sage: Rec.category()
|
|
1630
|
+
Category of modules over Integer Ring
|
|
1631
|
+
sage: RecognizableSeriesSpace([0, 1], [0, 1])
|
|
1632
|
+
Traceback (most recent call last):
|
|
1633
|
+
...
|
|
1634
|
+
ValueError: coefficient ring [0, 1] is not a semiring
|
|
1635
|
+
|
|
1636
|
+
::
|
|
1637
|
+
|
|
1638
|
+
sage: W = Words([0, 1], infinite=False)
|
|
1639
|
+
sage: RecognizableSeriesSpace(ZZ)
|
|
1640
|
+
Traceback (most recent call last):
|
|
1641
|
+
...
|
|
1642
|
+
ValueError: specify either 'alphabet' or 'indices'
|
|
1643
|
+
sage: RecognizableSeriesSpace(ZZ, alphabet=[0, 1], indices=W)
|
|
1644
|
+
Traceback (most recent call last):
|
|
1645
|
+
...
|
|
1646
|
+
ValueError: specify either 'alphabet' or 'indices'
|
|
1647
|
+
sage: RecognizableSeriesSpace(alphabet=[0, 1])
|
|
1648
|
+
Traceback (most recent call last):
|
|
1649
|
+
...
|
|
1650
|
+
ValueError: no coefficient ring specified
|
|
1651
|
+
sage: RecognizableSeriesSpace(ZZ, indices=Words(ZZ))
|
|
1652
|
+
Traceback (most recent call last):
|
|
1653
|
+
...
|
|
1654
|
+
NotImplementedError: alphabet is not finite
|
|
1655
|
+
"""
|
|
1656
|
+
if (alphabet is None) == (indices is None):
|
|
1657
|
+
raise ValueError("specify either 'alphabet' or 'indices'")
|
|
1658
|
+
|
|
1659
|
+
if indices is None:
|
|
1660
|
+
from sage.combinat.words.words import Words
|
|
1661
|
+
indices = Words(alphabet, infinite=False)
|
|
1662
|
+
if not indices.alphabet().is_finite():
|
|
1663
|
+
raise NotImplementedError('alphabet is not finite')
|
|
1664
|
+
|
|
1665
|
+
if coefficient_ring is None:
|
|
1666
|
+
raise ValueError('no coefficient ring specified')
|
|
1667
|
+
from sage.categories.semirings import Semirings
|
|
1668
|
+
if coefficient_ring not in Semirings():
|
|
1669
|
+
raise ValueError(
|
|
1670
|
+
'coefficient ring {} is not a semiring'.format(coefficient_ring))
|
|
1671
|
+
|
|
1672
|
+
from sage.categories.modules import Modules
|
|
1673
|
+
category = category or Modules(coefficient_ring)
|
|
1674
|
+
|
|
1675
|
+
return (coefficient_ring, indices, category, minimize_results)
|
|
1676
|
+
|
|
1677
|
+
def __init__(self, coefficient_ring, indices, category, minimize_results):
|
|
1678
|
+
r"""
|
|
1679
|
+
See :class:`RecognizableSeriesSpace` for details.
|
|
1680
|
+
|
|
1681
|
+
INPUT:
|
|
1682
|
+
|
|
1683
|
+
- ``coefficients`` -- a (semi-)ring
|
|
1684
|
+
|
|
1685
|
+
- ``indices`` -- a SageMath-parent of finite words over an alphabet
|
|
1686
|
+
|
|
1687
|
+
- ``category`` -- (default: ``None``) the category of this
|
|
1688
|
+
space
|
|
1689
|
+
|
|
1690
|
+
- ``minimize_results`` -- boolean (default: ``True``); if set, then
|
|
1691
|
+
:meth:`RecognizableSeries.minimized` is automatically called
|
|
1692
|
+
after performing operations.
|
|
1693
|
+
|
|
1694
|
+
TESTS::
|
|
1695
|
+
|
|
1696
|
+
sage: RecognizableSeriesSpace(ZZ, [0, 1])
|
|
1697
|
+
Space of recognizable series on {0, 1} with coefficients in Integer Ring
|
|
1698
|
+
|
|
1699
|
+
::
|
|
1700
|
+
|
|
1701
|
+
sage: from itertools import islice
|
|
1702
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
1703
|
+
sage: TestSuite(Rec).run( # long time
|
|
1704
|
+
....: verbose=True,
|
|
1705
|
+
....: elements=tuple(islice(Rec.some_elements(), 4)))
|
|
1706
|
+
running ._test_additive_associativity() . . . pass
|
|
1707
|
+
running ._test_an_element() . . . pass
|
|
1708
|
+
running ._test_cardinality() . . . pass
|
|
1709
|
+
running ._test_category() . . . pass
|
|
1710
|
+
running ._test_construction() . . . pass
|
|
1711
|
+
running ._test_elements() . . .
|
|
1712
|
+
Running the test suite of self.an_element()
|
|
1713
|
+
running ._test_category() . . . pass
|
|
1714
|
+
running ._test_eq() . . . pass
|
|
1715
|
+
running ._test_new() . . . pass
|
|
1716
|
+
running ._test_nonzero_equal() . . . pass
|
|
1717
|
+
running ._test_not_implemented_methods() . . . pass
|
|
1718
|
+
running ._test_pickling() . . . pass
|
|
1719
|
+
pass
|
|
1720
|
+
running ._test_elements_eq_reflexive() . . . pass
|
|
1721
|
+
running ._test_elements_eq_symmetric() . . . pass
|
|
1722
|
+
running ._test_elements_eq_transitive() . . . pass
|
|
1723
|
+
running ._test_elements_neq() . . . pass
|
|
1724
|
+
running ._test_eq() . . . pass
|
|
1725
|
+
running ._test_new() . . . pass
|
|
1726
|
+
running ._test_not_implemented_methods() . . . pass
|
|
1727
|
+
running ._test_pickling() . . . pass
|
|
1728
|
+
running ._test_some_elements() . . . pass
|
|
1729
|
+
running ._test_zero() . . . pass
|
|
1730
|
+
"""
|
|
1731
|
+
self._indices_ = indices
|
|
1732
|
+
self._minimize_results_ = minimize_results
|
|
1733
|
+
super().__init__(
|
|
1734
|
+
category=category, base=coefficient_ring)
|
|
1735
|
+
|
|
1736
|
+
def __reduce__(self):
|
|
1737
|
+
r"""
|
|
1738
|
+
Pickling support.
|
|
1739
|
+
|
|
1740
|
+
TESTS::
|
|
1741
|
+
|
|
1742
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
1743
|
+
sage: loads(dumps(Rec)) # indirect doctest
|
|
1744
|
+
Space of recognizable series on {0, 1} with coefficients in Integer Ring
|
|
1745
|
+
"""
|
|
1746
|
+
return _pickle_RecognizableSeriesSpace, \
|
|
1747
|
+
(self.coefficient_ring(), self.indices(), self.category())
|
|
1748
|
+
|
|
1749
|
+
def alphabet(self):
|
|
1750
|
+
r"""
|
|
1751
|
+
Return the alphabet of this recognizable series space.
|
|
1752
|
+
|
|
1753
|
+
OUTPUT: a totally ordered set
|
|
1754
|
+
|
|
1755
|
+
EXAMPLES::
|
|
1756
|
+
|
|
1757
|
+
sage: RecognizableSeriesSpace(ZZ, [0, 1]).alphabet()
|
|
1758
|
+
{0, 1}
|
|
1759
|
+
|
|
1760
|
+
TESTS::
|
|
1761
|
+
|
|
1762
|
+
sage: type(RecognizableSeriesSpace(ZZ, [0, 1]).alphabet())
|
|
1763
|
+
<class 'sage.sets.totally_ordered_finite_set.TotallyOrderedFiniteSet_with_category'>
|
|
1764
|
+
"""
|
|
1765
|
+
return self.indices().alphabet()
|
|
1766
|
+
|
|
1767
|
+
def indices(self):
|
|
1768
|
+
r"""
|
|
1769
|
+
Return the indices of the recognizable series.
|
|
1770
|
+
|
|
1771
|
+
OUTPUT: the set of finite words over the alphabet
|
|
1772
|
+
|
|
1773
|
+
EXAMPLES::
|
|
1774
|
+
|
|
1775
|
+
sage: RecognizableSeriesSpace(ZZ, [0, 1]).indices()
|
|
1776
|
+
Finite words over {0, 1}
|
|
1777
|
+
"""
|
|
1778
|
+
return self._indices_
|
|
1779
|
+
|
|
1780
|
+
def coefficient_ring(self):
|
|
1781
|
+
r"""
|
|
1782
|
+
Return the coefficients of this recognizable series space.
|
|
1783
|
+
|
|
1784
|
+
OUTPUT:
|
|
1785
|
+
|
|
1786
|
+
A (semi-)ring
|
|
1787
|
+
|
|
1788
|
+
EXAMPLES::
|
|
1789
|
+
|
|
1790
|
+
sage: RecognizableSeriesSpace(ZZ, [0, 1]).coefficient_ring()
|
|
1791
|
+
Integer Ring
|
|
1792
|
+
"""
|
|
1793
|
+
return self.base()
|
|
1794
|
+
|
|
1795
|
+
@property
|
|
1796
|
+
def minimize_results(self):
|
|
1797
|
+
r"""
|
|
1798
|
+
A boolean indicating whether
|
|
1799
|
+
:meth:`RecognizableSeries.minimized` is automatically called
|
|
1800
|
+
after performing operations.
|
|
1801
|
+
|
|
1802
|
+
TESTS::
|
|
1803
|
+
|
|
1804
|
+
sage: RecognizableSeriesSpace(ZZ, [0, 1]).minimize_results
|
|
1805
|
+
True
|
|
1806
|
+
sage: RecognizableSeriesSpace(ZZ, [0, 1], minimize_results=True).minimize_results
|
|
1807
|
+
True
|
|
1808
|
+
sage: RecognizableSeriesSpace(ZZ, [0, 1], minimize_results=False).minimize_results
|
|
1809
|
+
False
|
|
1810
|
+
"""
|
|
1811
|
+
return self._minimize_results_
|
|
1812
|
+
|
|
1813
|
+
def _repr_(self):
|
|
1814
|
+
r"""
|
|
1815
|
+
Return a representation string of this recognizable sequence
|
|
1816
|
+
space.
|
|
1817
|
+
|
|
1818
|
+
OUTPUT: string
|
|
1819
|
+
|
|
1820
|
+
TESTS::
|
|
1821
|
+
|
|
1822
|
+
sage: repr(RecognizableSeriesSpace(ZZ, [0, 1])) # indirect doctest
|
|
1823
|
+
'Space of recognizable series on {0, 1} with coefficients in Integer Ring'
|
|
1824
|
+
"""
|
|
1825
|
+
return 'Space of recognizable series on {} ' \
|
|
1826
|
+
'with coefficients in {}'.format(self.alphabet(),
|
|
1827
|
+
self.coefficient_ring())
|
|
1828
|
+
|
|
1829
|
+
def _an_element_(self):
|
|
1830
|
+
r"""
|
|
1831
|
+
Return an element of this recognizable series space.
|
|
1832
|
+
|
|
1833
|
+
OUTPUT: a :class:`RecognizableSeries`
|
|
1834
|
+
|
|
1835
|
+
EXAMPLES::
|
|
1836
|
+
|
|
1837
|
+
sage: RecognizableSeriesSpace(ZZ, [0, 1]).an_element() # indirect doctest
|
|
1838
|
+
[1] + [01] + [10] + 2*[11] + [001] + [010]
|
|
1839
|
+
+ 2*[011] + [100] + 2*[101] + 2*[110] + ...
|
|
1840
|
+
"""
|
|
1841
|
+
from sage.matrix.constructor import Matrix
|
|
1842
|
+
from sage.modules.free_module_element import vector
|
|
1843
|
+
z = self.coefficient_ring().zero()
|
|
1844
|
+
o = self.coefficient_ring().one()
|
|
1845
|
+
e = self.coefficient_ring().an_element()
|
|
1846
|
+
return self(list(Matrix([[o, z], [i * o, o]])
|
|
1847
|
+
for i, _ in enumerate(self.alphabet())),
|
|
1848
|
+
vector([z, e]), right=vector([e, z]))
|
|
1849
|
+
|
|
1850
|
+
def some_elements(self, **kwds):
|
|
1851
|
+
r"""
|
|
1852
|
+
Return some elements of this recognizable series space.
|
|
1853
|
+
|
|
1854
|
+
See :class:`TestSuite` for a typical use case.
|
|
1855
|
+
|
|
1856
|
+
INPUT:
|
|
1857
|
+
|
|
1858
|
+
- ``kwds`` are passed on to the element constructor
|
|
1859
|
+
|
|
1860
|
+
OUTPUT: an iterator
|
|
1861
|
+
|
|
1862
|
+
EXAMPLES::
|
|
1863
|
+
|
|
1864
|
+
sage: tuple(RecognizableSeriesSpace(ZZ, [0, 1]).some_elements())
|
|
1865
|
+
([1] + [01] + [10] + 2*[11] + [001] + [010]
|
|
1866
|
+
+ 2*[011] + [100] + 2*[101] + 2*[110] + ...,
|
|
1867
|
+
[] + [1] + [11] + [111] + [1111] + [11111] + [111111] + ...,
|
|
1868
|
+
[] + [0] + [1] + [00] + [10] + [11]
|
|
1869
|
+
+ [000] - 1*[001] + [100] + [110] + ...,
|
|
1870
|
+
2*[] - 1*[1] + 2*[10] - 1*[101]
|
|
1871
|
+
+ 2*[1010] - 1*[10101] + 2*[101010] + ...,
|
|
1872
|
+
[] + [1] + 6*[00] + [11] - 39*[000] + 5*[001] + 6*[100] + [111]
|
|
1873
|
+
+ 288*[0000] - 33*[0001] + ...,
|
|
1874
|
+
-5*[] + ...,
|
|
1875
|
+
...
|
|
1876
|
+
210*[] + ...,
|
|
1877
|
+
2210*[] - 170*[0] + 170*[1] + ...)
|
|
1878
|
+
"""
|
|
1879
|
+
from itertools import islice
|
|
1880
|
+
from sage.matrix.matrix_space import MatrixSpace
|
|
1881
|
+
from sage.modules.free_module import FreeModule
|
|
1882
|
+
yield self.an_element()
|
|
1883
|
+
|
|
1884
|
+
C = self.coefficient_ring()
|
|
1885
|
+
k = len(self.alphabet())
|
|
1886
|
+
for dim in range(1, 11):
|
|
1887
|
+
elements_M = MatrixSpace(C, dim).some_elements()
|
|
1888
|
+
elements_V = FreeModule(C, dim).some_elements()
|
|
1889
|
+
for _ in range(3):
|
|
1890
|
+
mu = list(islice(elements_M, k))
|
|
1891
|
+
LR = list(islice(elements_V, 2))
|
|
1892
|
+
if len(mu) != k or len(LR) != 2:
|
|
1893
|
+
break
|
|
1894
|
+
yield self(mu, *LR, **kwds)
|
|
1895
|
+
|
|
1896
|
+
@cached_method
|
|
1897
|
+
def _zero_(self):
|
|
1898
|
+
r"""
|
|
1899
|
+
Return the zero element of this :class:`RecognizableSeriesSpace`,
|
|
1900
|
+
i.e. the unique neutral element for `+`.
|
|
1901
|
+
|
|
1902
|
+
TESTS::
|
|
1903
|
+
|
|
1904
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
1905
|
+
sage: Z = Rec._zero_(); Z
|
|
1906
|
+
0
|
|
1907
|
+
sage: Z.linear_representation()
|
|
1908
|
+
((), Finite family {0: [], 1: []}, ())
|
|
1909
|
+
"""
|
|
1910
|
+
from sage.matrix.constructor import Matrix
|
|
1911
|
+
from sage.modules.free_module_element import vector
|
|
1912
|
+
from sage.sets.family import Family
|
|
1913
|
+
|
|
1914
|
+
return self.element_class(
|
|
1915
|
+
self, Family(self.alphabet(), lambda a: Matrix()),
|
|
1916
|
+
vector([]), vector([]))
|
|
1917
|
+
|
|
1918
|
+
@cached_method
|
|
1919
|
+
def one(self):
|
|
1920
|
+
r"""
|
|
1921
|
+
Return the one element of this :class:`RecognizableSeriesSpace`,
|
|
1922
|
+
i.e. the embedding of the one of the coefficient ring into
|
|
1923
|
+
this :class:`RecognizableSeriesSpace`.
|
|
1924
|
+
|
|
1925
|
+
EXAMPLES::
|
|
1926
|
+
|
|
1927
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
1928
|
+
sage: O = Rec.one(); O
|
|
1929
|
+
[] + ...
|
|
1930
|
+
sage: O.linear_representation()
|
|
1931
|
+
((1), Finite family {0: [0], 1: [0]}, (1))
|
|
1932
|
+
|
|
1933
|
+
TESTS::
|
|
1934
|
+
|
|
1935
|
+
sage: Rec.one() is Rec.one()
|
|
1936
|
+
True
|
|
1937
|
+
"""
|
|
1938
|
+
from sage.matrix.constructor import Matrix
|
|
1939
|
+
from sage.modules.free_module_element import vector
|
|
1940
|
+
|
|
1941
|
+
R = self.coefficient_ring()
|
|
1942
|
+
one = R.one()
|
|
1943
|
+
zero = R.zero()
|
|
1944
|
+
return self.element_class(self,
|
|
1945
|
+
len(self.alphabet())*[Matrix([[zero]])],
|
|
1946
|
+
vector([one]),
|
|
1947
|
+
vector([one]))
|
|
1948
|
+
|
|
1949
|
+
@cached_method
|
|
1950
|
+
def one_hadamard(self):
|
|
1951
|
+
r"""
|
|
1952
|
+
Return the identity with respect to the
|
|
1953
|
+
:meth:`~RecognizableSeries.hadamard_product`, i.e. the
|
|
1954
|
+
coefficient-wise multiplication.
|
|
1955
|
+
|
|
1956
|
+
OUTPUT: a :class:`RecognizableSeries`
|
|
1957
|
+
|
|
1958
|
+
EXAMPLES::
|
|
1959
|
+
|
|
1960
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
1961
|
+
sage: Rec.one_hadamard()
|
|
1962
|
+
[] + [0] + [1] + [00] + [01] + [10]
|
|
1963
|
+
+ [11] + [000] + [001] + [010] + ...
|
|
1964
|
+
|
|
1965
|
+
TESTS::
|
|
1966
|
+
|
|
1967
|
+
sage: Rec.one_hadamard() is Rec.one_hadamard()
|
|
1968
|
+
True
|
|
1969
|
+
"""
|
|
1970
|
+
from sage.matrix.constructor import Matrix
|
|
1971
|
+
from sage.modules.free_module_element import vector
|
|
1972
|
+
|
|
1973
|
+
one = self.coefficient_ring()(1)
|
|
1974
|
+
return self({a: Matrix([[one]]) for a in self.alphabet()},
|
|
1975
|
+
vector([one]), vector([one]))
|
|
1976
|
+
|
|
1977
|
+
def _element_constructor_(self, data,
|
|
1978
|
+
left=None, right=None):
|
|
1979
|
+
r"""
|
|
1980
|
+
Return a recognizable series.
|
|
1981
|
+
|
|
1982
|
+
See :class:`RecognizableSeriesSpace` for details.
|
|
1983
|
+
|
|
1984
|
+
TESTS::
|
|
1985
|
+
|
|
1986
|
+
sage: Rec = RecognizableSeriesSpace(ZZ, [0, 1])
|
|
1987
|
+
|
|
1988
|
+
sage: Rec.zero()
|
|
1989
|
+
0
|
|
1990
|
+
sage: type(_)
|
|
1991
|
+
<class 'sage.combinat.recognizable_series.RecognizableSeriesSpace_with_category.element_class'>
|
|
1992
|
+
|
|
1993
|
+
::
|
|
1994
|
+
|
|
1995
|
+
sage: M0 = Matrix([[1, 0], [0, 1]])
|
|
1996
|
+
sage: M1 = Matrix([[0, -1], [1, 2]])
|
|
1997
|
+
sage: S = Rec((M0, M1), vector([0, 1]), vector([1, 1]))
|
|
1998
|
+
sage: Rec(S) is S
|
|
1999
|
+
True
|
|
2000
|
+
|
|
2001
|
+
::
|
|
2002
|
+
|
|
2003
|
+
sage: A = Rec(42); A
|
|
2004
|
+
42*[] + ...
|
|
2005
|
+
sage: A.linear_representation()
|
|
2006
|
+
((42), Finite family {0: [0], 1: [0]}, (1))
|
|
2007
|
+
sage: Z = Rec(0); Z
|
|
2008
|
+
0
|
|
2009
|
+
sage: Z.linear_representation()
|
|
2010
|
+
((), Finite family {0: [], 1: []}, ())
|
|
2011
|
+
|
|
2012
|
+
::
|
|
2013
|
+
|
|
2014
|
+
sage: Rec((M0, M1))
|
|
2015
|
+
Traceback (most recent call last):
|
|
2016
|
+
...
|
|
2017
|
+
ValueError: left or right vector is None
|
|
2018
|
+
sage: Rec((M0, M1), [0, 1])
|
|
2019
|
+
Traceback (most recent call last):
|
|
2020
|
+
...
|
|
2021
|
+
ValueError: left or right vector is None
|
|
2022
|
+
sage: Rec((M0, M1), left=[0, 1])
|
|
2023
|
+
Traceback (most recent call last):
|
|
2024
|
+
...
|
|
2025
|
+
ValueError: left or right vector is None
|
|
2026
|
+
sage: Rec((M0, M1), right=[0, 1])
|
|
2027
|
+
Traceback (most recent call last):
|
|
2028
|
+
...
|
|
2029
|
+
ValueError: left or right vector is None
|
|
2030
|
+
"""
|
|
2031
|
+
if isinstance(data, int) and data == 0:
|
|
2032
|
+
return self._zero_()
|
|
2033
|
+
|
|
2034
|
+
if isinstance(data, self.element_class) and data.parent() == self:
|
|
2035
|
+
element = data
|
|
2036
|
+
|
|
2037
|
+
elif isinstance(data, RecognizableSeries):
|
|
2038
|
+
element = self.element_class(self, data.mu, data.left, data.right)
|
|
2039
|
+
|
|
2040
|
+
elif data in self.coefficient_ring():
|
|
2041
|
+
c = self.coefficient_ring()(data)
|
|
2042
|
+
return c * self.one()
|
|
2043
|
+
|
|
2044
|
+
else:
|
|
2045
|
+
mu = data
|
|
2046
|
+
if left is None or right is None:
|
|
2047
|
+
raise ValueError('left or right vector is None')
|
|
2048
|
+
|
|
2049
|
+
element = self.element_class(self, mu, left, right)
|
|
2050
|
+
|
|
2051
|
+
return element
|