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,1238 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
# sage.doctest: needs sage.combinat sage.groups
|
|
3
|
+
r"""
|
|
4
|
+
Integer vectors modulo the action of a permutation group
|
|
5
|
+
|
|
6
|
+
AUTHORS:
|
|
7
|
+
|
|
8
|
+
* Nicolas Borie (2010-2012) - original module
|
|
9
|
+
* Jukka Kohonen (2023) - fast cardinality method, :issue:`36787`, :issue:`36681`
|
|
10
|
+
"""
|
|
11
|
+
# ****************************************************************************
|
|
12
|
+
# Copyright (C) 2010-12 Nicolas Borie <nicolas.borie at math dot u-psud.fr>
|
|
13
|
+
#
|
|
14
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
15
|
+
#
|
|
16
|
+
# The full text of the GPL is available at:
|
|
17
|
+
# https://www.gnu.org/licenses/
|
|
18
|
+
# ****************************************************************************
|
|
19
|
+
|
|
20
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
21
|
+
from sage.rings.semirings.non_negative_integer_semiring import NN
|
|
22
|
+
|
|
23
|
+
from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
|
|
24
|
+
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
|
|
25
|
+
|
|
26
|
+
from sage.structure.list_clone import ClonableIntArray
|
|
27
|
+
from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
|
|
28
|
+
|
|
29
|
+
from sage.combinat.enumeration_mod_permgroup import is_canonical, orbit, canonical_children, canonical_representative_of_orbit_of
|
|
30
|
+
|
|
31
|
+
from sage.combinat.integer_vector import IntegerVectors
|
|
32
|
+
|
|
33
|
+
from sage.rings.power_series_ring import PowerSeriesRing
|
|
34
|
+
from sage.rings.rational_field import QQ
|
|
35
|
+
from sage.rings.integer import Integer
|
|
36
|
+
from sage.misc.misc_c import prod
|
|
37
|
+
from sage.arith.misc import binomial
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class IntegerVectorsModPermutationGroup(UniqueRepresentation):
|
|
41
|
+
r"""
|
|
42
|
+
Return an enumerated set containing integer vectors which are
|
|
43
|
+
maximal in their orbit under the action of the permutation group
|
|
44
|
+
``G`` for the lexicographic order.
|
|
45
|
+
|
|
46
|
+
In Sage, a permutation group `G` is viewed as a subgroup of the
|
|
47
|
+
symmetric group `S_n` of degree `n` and `n` is said to be the degree
|
|
48
|
+
of `G`. Any integer vector `v` is said to be canonical if it
|
|
49
|
+
is maximal in its orbit under the action of `G`. `v` is
|
|
50
|
+
canonical if and only if
|
|
51
|
+
|
|
52
|
+
.. MATH::
|
|
53
|
+
|
|
54
|
+
v = \max_{\text{lex order}} \{g \cdot v | g \in G \}
|
|
55
|
+
|
|
56
|
+
The action of `G` is on position. This means for example that the
|
|
57
|
+
simple transposition `s_1 = (1, 2)` swaps the first and the second
|
|
58
|
+
entries of any integer vector `v = [a_1, a_2, a_3, \dots , a_n]`
|
|
59
|
+
|
|
60
|
+
.. MATH::
|
|
61
|
+
|
|
62
|
+
s_1 \cdot v = [a_2, a_1, a_3, \dots , a_n]
|
|
63
|
+
|
|
64
|
+
This function returns a parent which contains, from each orbit
|
|
65
|
+
orbit under the action of the permutation group `G`, a single
|
|
66
|
+
canonical vector. The canonical vector is the one that is maximal
|
|
67
|
+
within the orbit according to lexicographic order.
|
|
68
|
+
|
|
69
|
+
INPUT:
|
|
70
|
+
|
|
71
|
+
- ``G`` -- a permutation group
|
|
72
|
+
- ``sum`` -- (default: ``None``) - a nonnegative integer
|
|
73
|
+
- ``max_part`` -- (default: ``None``) - a nonnegative integer setting the
|
|
74
|
+
maximum value for every element
|
|
75
|
+
- ``sgs`` -- (default: ``None``) - a strong generating system of the
|
|
76
|
+
group `G`. If you do not provide it, it will be calculated at the
|
|
77
|
+
creation of the parent
|
|
78
|
+
|
|
79
|
+
OUTPUT:
|
|
80
|
+
|
|
81
|
+
- If ``sum`` and ``max_part`` are None, it returns the infinite
|
|
82
|
+
enumerated set of all integer vectors (lists of integers) maximal
|
|
83
|
+
in their orbit for the lexicographic order. Exceptionally, if
|
|
84
|
+
the domain of ``G`` is empty, the result is a finite enumerated
|
|
85
|
+
set that contains one element, namely the empty vector.
|
|
86
|
+
|
|
87
|
+
- If ``sum`` is an integer, it returns a finite enumerated set
|
|
88
|
+
containing all integer vectors maximal in their orbit for the
|
|
89
|
+
lexicographic order and whose entries sum to ``sum``.
|
|
90
|
+
|
|
91
|
+
EXAMPLES:
|
|
92
|
+
|
|
93
|
+
Here is the set enumerating integer vectors modulo the action of the cyclic
|
|
94
|
+
group of `3` elements::
|
|
95
|
+
|
|
96
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3)]]))
|
|
97
|
+
sage: I.category()
|
|
98
|
+
Category of infinite enumerated quotients of sets
|
|
99
|
+
sage: I.cardinality()
|
|
100
|
+
+Infinity
|
|
101
|
+
sage: I.list()
|
|
102
|
+
Traceback (most recent call last):
|
|
103
|
+
...
|
|
104
|
+
NotImplementedError: cannot list an infinite set
|
|
105
|
+
sage: p = iter(I)
|
|
106
|
+
sage: for i in range(10): next(p)
|
|
107
|
+
[0, 0, 0]
|
|
108
|
+
[1, 0, 0]
|
|
109
|
+
[2, 0, 0]
|
|
110
|
+
[1, 1, 0]
|
|
111
|
+
[3, 0, 0]
|
|
112
|
+
[2, 1, 0]
|
|
113
|
+
[2, 0, 1]
|
|
114
|
+
[1, 1, 1]
|
|
115
|
+
[4, 0, 0]
|
|
116
|
+
[3, 1, 0]
|
|
117
|
+
|
|
118
|
+
The method
|
|
119
|
+
:meth:`~sage.combinat.integer_vectors_mod_permgroup.IntegerVectorsModPermutationGroup_All.is_canonical`
|
|
120
|
+
tests if an integer vector is maximal in its orbit. This method
|
|
121
|
+
is also used in the containment test::
|
|
122
|
+
|
|
123
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
|
|
124
|
+
sage: I.is_canonical([5,2,0,4])
|
|
125
|
+
True
|
|
126
|
+
sage: I.is_canonical([5,0,6,4])
|
|
127
|
+
False
|
|
128
|
+
sage: I.is_canonical([1,1,1,1])
|
|
129
|
+
True
|
|
130
|
+
sage: [2,3,1,0] in I
|
|
131
|
+
False
|
|
132
|
+
sage: [5,0,5,0] in I
|
|
133
|
+
True
|
|
134
|
+
sage: 'Bla' in I
|
|
135
|
+
False
|
|
136
|
+
sage: I.is_canonical('bla')
|
|
137
|
+
Traceback (most recent call last):
|
|
138
|
+
...
|
|
139
|
+
AssertionError: bla should be a list or an integer vector
|
|
140
|
+
|
|
141
|
+
If you give a value to the extra argument ``sum``, the set returned
|
|
142
|
+
will be a finite set containing only canonical vectors whose entries
|
|
143
|
+
sum to ``sum``.::
|
|
144
|
+
|
|
145
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3)]]), sum=6)
|
|
146
|
+
sage: I.cardinality()
|
|
147
|
+
10
|
|
148
|
+
sage: I.list()
|
|
149
|
+
[[6, 0, 0], [5, 1, 0], [5, 0, 1], [4, 2, 0], [4, 1, 1],
|
|
150
|
+
[4, 0, 2], [3, 3, 0], [3, 2, 1], [3, 1, 2], [2, 2, 2]]
|
|
151
|
+
sage: I.category()
|
|
152
|
+
Join of Category of finite enumerated sets
|
|
153
|
+
and Category of subquotients of finite sets
|
|
154
|
+
and Category of quotients of sets
|
|
155
|
+
|
|
156
|
+
To get the orbit of any integer vector `v` under the action of the group,
|
|
157
|
+
use the method :meth:`~sage.combinat.integer_vectors_mod_permgroup.IntegerVectorsModPermutationGroup_All.orbit`;
|
|
158
|
+
we convert the returned set of vectors into a list in increasing lexicographic order,
|
|
159
|
+
to get a reproducible test::
|
|
160
|
+
|
|
161
|
+
sage: sorted(I.orbit([6,0,0]))
|
|
162
|
+
[[0, 0, 6], [0, 6, 0], [6, 0, 0]]
|
|
163
|
+
sage: sorted(I.orbit([5,1,0]))
|
|
164
|
+
[[0, 5, 1], [1, 0, 5], [5, 1, 0]]
|
|
165
|
+
sage: I.orbit([2,2,2])
|
|
166
|
+
{[2, 2, 2]}
|
|
167
|
+
|
|
168
|
+
Even without constraints, for an empty domain the result is
|
|
169
|
+
a singleton set::
|
|
170
|
+
|
|
171
|
+
sage: G = PermutationGroup([], domain=[])
|
|
172
|
+
sage: sgs = tuple(tuple(s) for s in G.strong_generating_system())
|
|
173
|
+
sage: list(IntegerVectorsModPermutationGroup(G, sgs=sgs))
|
|
174
|
+
[[]]
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
.. WARNING::
|
|
178
|
+
|
|
179
|
+
Because of :issue:`36527`, permutation groups that have
|
|
180
|
+
different domains but similar generators can be erroneously
|
|
181
|
+
treated as the same group. This will silently produce
|
|
182
|
+
erroneous results. To avoid this issue, compute a strong
|
|
183
|
+
generating system for the group as::
|
|
184
|
+
|
|
185
|
+
sgs = tuple(tuple(s) for s in G.strong_generating_system())
|
|
186
|
+
|
|
187
|
+
and provide it as the optional ``sgs`` argument to the
|
|
188
|
+
constructor.
|
|
189
|
+
|
|
190
|
+
TESTS:
|
|
191
|
+
|
|
192
|
+
Let us check that canonical integer vectors of the symmetric group
|
|
193
|
+
are just nonincreasing lists of integers::
|
|
194
|
+
|
|
195
|
+
sage: I = IntegerVectorsModPermutationGroup(SymmetricGroup(5)) # long time
|
|
196
|
+
sage: p = iter(I) # long time
|
|
197
|
+
sage: for i in range(100): # long time
|
|
198
|
+
....: v = list(next(p))
|
|
199
|
+
....: assert sorted(v, reverse=True) == v
|
|
200
|
+
|
|
201
|
+
We now check that there are as many canonical vectors under the
|
|
202
|
+
symmetric group `S_n` whose entries sum to `d` as there are
|
|
203
|
+
partitions of `d` of at most `n` parts::
|
|
204
|
+
|
|
205
|
+
sage: I = IntegerVectorsModPermutationGroup(SymmetricGroup(5)) # long time
|
|
206
|
+
sage: for i in range(10): # long time
|
|
207
|
+
....: d1 = I.subset(i).cardinality()
|
|
208
|
+
....: d2 = Partitions(i, max_length=5).cardinality()
|
|
209
|
+
....: print(d1)
|
|
210
|
+
....: assert d1 == d2
|
|
211
|
+
1
|
|
212
|
+
1
|
|
213
|
+
2
|
|
214
|
+
3
|
|
215
|
+
5
|
|
216
|
+
7
|
|
217
|
+
10
|
|
218
|
+
13
|
|
219
|
+
18
|
|
220
|
+
23
|
|
221
|
+
|
|
222
|
+
Another corner case is trivial groups. For the trivial group ``G``
|
|
223
|
+
acting on a list of length `n`, all integer vectors of length `n`
|
|
224
|
+
are canonical::
|
|
225
|
+
|
|
226
|
+
sage: # long time
|
|
227
|
+
sage: G = PermutationGroup([[(6,)]])
|
|
228
|
+
sage: G.cardinality()
|
|
229
|
+
1
|
|
230
|
+
sage: sgs = tuple(tuple(s) for s in G.strong_generating_system())
|
|
231
|
+
sage: I = IntegerVectorsModPermutationGroup(G, sgs=sgs)
|
|
232
|
+
sage: for i in range(10):
|
|
233
|
+
....: d1 = I.subset(i).cardinality()
|
|
234
|
+
....: d2 = IntegerVectors(i,6).cardinality()
|
|
235
|
+
....: print(d1)
|
|
236
|
+
....: assert d1 == d2
|
|
237
|
+
1
|
|
238
|
+
6
|
|
239
|
+
21
|
|
240
|
+
56
|
|
241
|
+
126
|
|
242
|
+
252
|
|
243
|
+
462
|
|
244
|
+
792
|
|
245
|
+
1287
|
|
246
|
+
2002
|
|
247
|
+
"""
|
|
248
|
+
@staticmethod
|
|
249
|
+
def __classcall__(cls, G, sum=None, max_part=None, sgs=None):
|
|
250
|
+
r"""
|
|
251
|
+
TESTS::
|
|
252
|
+
|
|
253
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3)]]))
|
|
254
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3)]]), None)
|
|
255
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3)]]), 2)
|
|
256
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3)]]), -2)
|
|
257
|
+
Traceback (most recent call last):
|
|
258
|
+
...
|
|
259
|
+
ValueError: Value -2 in not in Non negative integer semiring.
|
|
260
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3)]]), 8, max_part=5)
|
|
261
|
+
"""
|
|
262
|
+
if sum is None and max_part is None:
|
|
263
|
+
# No constraints.
|
|
264
|
+
if G.domain():
|
|
265
|
+
# Nonempty domain, infinite set.
|
|
266
|
+
return IntegerVectorsModPermutationGroup_All(G, sgs=sgs)
|
|
267
|
+
else:
|
|
268
|
+
# Empty domain, singleton set.
|
|
269
|
+
return IntegerVectorsModPermutationGroup_with_constraints(
|
|
270
|
+
G, 0, max_part=-1, sgs=sgs)
|
|
271
|
+
else:
|
|
272
|
+
# Some constraints, either sum or max_part or both.
|
|
273
|
+
if sum is not None:
|
|
274
|
+
assert sum == NN(sum)
|
|
275
|
+
if max_part is not None:
|
|
276
|
+
assert max_part == NN(max_part)
|
|
277
|
+
return IntegerVectorsModPermutationGroup_with_constraints(
|
|
278
|
+
G, sum, max_part, sgs=sgs)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
class IntegerVectorsModPermutationGroup_All(UniqueRepresentation, RecursivelyEnumeratedSet_forest):
|
|
282
|
+
r"""
|
|
283
|
+
A class for integer vectors enumerated up to the action of a
|
|
284
|
+
permutation group.
|
|
285
|
+
|
|
286
|
+
A Sage permutation group is viewed as a subgroup of the symmetric
|
|
287
|
+
group `S_n` for a certain `n`. This group has a natural action by
|
|
288
|
+
position on vectors of length `n`. This class implements a set
|
|
289
|
+
which keeps a single vector for each orbit. We say that a vector
|
|
290
|
+
is canonical if it is the maximum in its orbit under the action of
|
|
291
|
+
the permutation group for the lexicographic order.
|
|
292
|
+
|
|
293
|
+
EXAMPLES::
|
|
294
|
+
|
|
295
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]])); I
|
|
296
|
+
Integer vectors of length 4 enumerated up to the action of
|
|
297
|
+
Permutation Group with generators [(1,2,3,4)]
|
|
298
|
+
sage: I.cardinality()
|
|
299
|
+
+Infinity
|
|
300
|
+
sage: TestSuite(I).run()
|
|
301
|
+
sage: it = iter(I)
|
|
302
|
+
sage: [next(it), next(it), next(it), next(it), next(it)]
|
|
303
|
+
[[0, 0, 0, 0],
|
|
304
|
+
[1, 0, 0, 0],
|
|
305
|
+
[2, 0, 0, 0],
|
|
306
|
+
[1, 1, 0, 0],
|
|
307
|
+
[1, 0, 1, 0]]
|
|
308
|
+
sage: x = next(it); x
|
|
309
|
+
[3, 0, 0, 0]
|
|
310
|
+
sage: I.first()
|
|
311
|
+
[0, 0, 0, 0]
|
|
312
|
+
|
|
313
|
+
TESTS::
|
|
314
|
+
|
|
315
|
+
sage: TestSuite(I).run()
|
|
316
|
+
"""
|
|
317
|
+
|
|
318
|
+
def __init__(self, G, sgs=None):
|
|
319
|
+
"""
|
|
320
|
+
TESTS::
|
|
321
|
+
|
|
322
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
|
|
323
|
+
sage: I
|
|
324
|
+
Integer vectors of length 4 enumerated up to the action of
|
|
325
|
+
Permutation Group with generators [(1,2,3,4)]
|
|
326
|
+
sage: I.category()
|
|
327
|
+
Category of infinite enumerated quotients of sets
|
|
328
|
+
sage: TestSuite(I).run()
|
|
329
|
+
"""
|
|
330
|
+
RecursivelyEnumeratedSet_forest.__init__(self, algorithm='breadth', category=InfiniteEnumeratedSets().Quotients())
|
|
331
|
+
self._permgroup = G
|
|
332
|
+
self.n = G.degree()
|
|
333
|
+
|
|
334
|
+
# self.sgs: strong_generating_system
|
|
335
|
+
if sgs is None:
|
|
336
|
+
self._sgs = G.strong_generating_system()
|
|
337
|
+
else:
|
|
338
|
+
self._sgs = [list(x) for x in list(sgs)]
|
|
339
|
+
|
|
340
|
+
def _repr_(self):
|
|
341
|
+
"""
|
|
342
|
+
TESTS::
|
|
343
|
+
|
|
344
|
+
sage: IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3)]]))
|
|
345
|
+
Integer vectors of length 3 enumerated up to the action of Permutation Group with generators [(1,2,3)]
|
|
346
|
+
"""
|
|
347
|
+
return "Integer vectors of length %s enumerated up to the action of %r" % (self.n, self._permgroup)
|
|
348
|
+
|
|
349
|
+
def ambient(self):
|
|
350
|
+
r"""
|
|
351
|
+
Return the ambient space from which ``self`` is a quotient.
|
|
352
|
+
|
|
353
|
+
EXAMPLES::
|
|
354
|
+
|
|
355
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
|
|
356
|
+
sage: S.ambient()
|
|
357
|
+
Integer vectors of length 4
|
|
358
|
+
"""
|
|
359
|
+
return IntegerVectors(length=self.n)
|
|
360
|
+
|
|
361
|
+
def lift(self, elt):
|
|
362
|
+
r"""
|
|
363
|
+
Lift the element ``elt`` inside the ambient space from which ``self`` is a quotient.
|
|
364
|
+
|
|
365
|
+
EXAMPLES::
|
|
366
|
+
|
|
367
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
|
|
368
|
+
sage: v = S.lift(S([4,3,0,1])); v
|
|
369
|
+
[4, 3, 0, 1]
|
|
370
|
+
sage: type(v)
|
|
371
|
+
<class 'list'>
|
|
372
|
+
"""
|
|
373
|
+
# TODO: For now, Sage integer vectors are just python list.
|
|
374
|
+
# Once Integer vectors will have an element class, update this
|
|
375
|
+
# code properly
|
|
376
|
+
return list(elt)
|
|
377
|
+
|
|
378
|
+
def retract(self, elt):
|
|
379
|
+
r"""
|
|
380
|
+
Return the canonical representative of the orbit of the
|
|
381
|
+
integer ``elt`` under the action of the permutation group
|
|
382
|
+
defining ``self``.
|
|
383
|
+
|
|
384
|
+
If the element ``elt`` is already maximal in its orbit for
|
|
385
|
+
the lexicographic order, ``elt`` is thus the good
|
|
386
|
+
representative for its orbit.
|
|
387
|
+
|
|
388
|
+
EXAMPLES::
|
|
389
|
+
|
|
390
|
+
sage: [0,0,0,0] in IntegerVectors(0,4)
|
|
391
|
+
True
|
|
392
|
+
sage: [1,0,0,0] in IntegerVectors(1,4)
|
|
393
|
+
True
|
|
394
|
+
sage: [0,1,0,0] in IntegerVectors(1,4)
|
|
395
|
+
True
|
|
396
|
+
sage: [1,0,1,0] in IntegerVectors(2,4)
|
|
397
|
+
True
|
|
398
|
+
sage: [0,1,0,1] in IntegerVectors(2,4)
|
|
399
|
+
True
|
|
400
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
|
|
401
|
+
sage: S.retract([0,0,0,0])
|
|
402
|
+
[0, 0, 0, 0]
|
|
403
|
+
sage: S.retract([1,0,0,0])
|
|
404
|
+
[1, 0, 0, 0]
|
|
405
|
+
sage: S.retract([0,1,0,0])
|
|
406
|
+
[1, 0, 0, 0]
|
|
407
|
+
sage: S.retract([1,0,1,0])
|
|
408
|
+
[1, 0, 1, 0]
|
|
409
|
+
sage: S.retract([0,1,0,1])
|
|
410
|
+
[1, 0, 1, 0]
|
|
411
|
+
"""
|
|
412
|
+
# TODO: Once Sage integer vector will have a data structure
|
|
413
|
+
# based on ClonableIntArray, remove the conversion intarray
|
|
414
|
+
assert len(elt) == self.n, "%s is a quotient set of %s" % (self, self.ambient())
|
|
415
|
+
intarray = self.element_class(self, elt, check=False)
|
|
416
|
+
return self.element_class(self, canonical_representative_of_orbit_of(self._sgs, intarray), check=False)
|
|
417
|
+
|
|
418
|
+
def roots(self):
|
|
419
|
+
r"""
|
|
420
|
+
Return the root of generation of ``self``. This method is
|
|
421
|
+
required to build the tree structure of ``self`` which
|
|
422
|
+
inherits from the class :class:`~sage.sets.recursively_enumerated_set.RecursivelyEnumeratedSet_forest`.
|
|
423
|
+
|
|
424
|
+
EXAMPLES::
|
|
425
|
+
|
|
426
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
|
|
427
|
+
sage: I.roots()
|
|
428
|
+
[[0, 0, 0, 0]]
|
|
429
|
+
"""
|
|
430
|
+
return [self.element_class(self, self.n*[0,], check=False)]
|
|
431
|
+
|
|
432
|
+
def children(self, x):
|
|
433
|
+
r"""
|
|
434
|
+
Return the list of children of the element ``x``. This method
|
|
435
|
+
is required to build the tree structure of ``self`` which
|
|
436
|
+
inherits from the class :class:`~sage.sets.recursively_enumerated_set.RecursivelyEnumeratedSet_forest`.
|
|
437
|
+
|
|
438
|
+
EXAMPLES::
|
|
439
|
+
|
|
440
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
|
|
441
|
+
sage: I.children(I([2,1,0,0], check=False))
|
|
442
|
+
[[2, 2, 0, 0], [2, 1, 1, 0], [2, 1, 0, 1]]
|
|
443
|
+
"""
|
|
444
|
+
return canonical_children(self._sgs, x, -1)
|
|
445
|
+
|
|
446
|
+
def permutation_group(self):
|
|
447
|
+
r"""
|
|
448
|
+
Return the permutation group given to define ``self``.
|
|
449
|
+
|
|
450
|
+
EXAMPLES::
|
|
451
|
+
|
|
452
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
|
|
453
|
+
sage: I.permutation_group()
|
|
454
|
+
Permutation Group with generators [(1,2,3,4)]
|
|
455
|
+
"""
|
|
456
|
+
return self._permgroup
|
|
457
|
+
|
|
458
|
+
def is_canonical(self, v, check=True):
|
|
459
|
+
r"""
|
|
460
|
+
Return ``True`` if the integer list ``v`` is maximal in its
|
|
461
|
+
orbit under the action of the permutation group given to
|
|
462
|
+
define ``self``. Such integer vectors are said to be
|
|
463
|
+
canonical. A vector `v` is canonical if and only if
|
|
464
|
+
|
|
465
|
+
.. MATH::
|
|
466
|
+
|
|
467
|
+
v = \max_{\text{lex order}} \{g \cdot v | g \in G \}
|
|
468
|
+
|
|
469
|
+
EXAMPLES::
|
|
470
|
+
|
|
471
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
|
|
472
|
+
sage: I.is_canonical([4,3,2,1])
|
|
473
|
+
True
|
|
474
|
+
sage: I.is_canonical([4,0,0,1])
|
|
475
|
+
True
|
|
476
|
+
sage: I.is_canonical([4,0,3,3])
|
|
477
|
+
True
|
|
478
|
+
sage: I.is_canonical([4,0,4,4])
|
|
479
|
+
False
|
|
480
|
+
"""
|
|
481
|
+
if check:
|
|
482
|
+
assert isinstance(v, (ClonableIntArray, list)), '%s should be a list or an integer vector' % v
|
|
483
|
+
assert (self.n == len(v)), '%s should be of length %s' % (v, self.n)
|
|
484
|
+
for p in v:
|
|
485
|
+
assert (p == NN(p)), 'Elements of %s should be integers' % v
|
|
486
|
+
return is_canonical(self._sgs, self.element_class(self, list(v), check=False))
|
|
487
|
+
|
|
488
|
+
def __contains__(self, v):
|
|
489
|
+
"""
|
|
490
|
+
EXAMPLES::
|
|
491
|
+
|
|
492
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
|
|
493
|
+
sage: [2,2,0,0] in I
|
|
494
|
+
True
|
|
495
|
+
sage: [2,0,1,0] in I
|
|
496
|
+
True
|
|
497
|
+
sage: [2,0,0,1] in I
|
|
498
|
+
True
|
|
499
|
+
sage: [2,0,0,2] in I
|
|
500
|
+
False
|
|
501
|
+
sage: [2,0,0,2,12] in I
|
|
502
|
+
False
|
|
503
|
+
"""
|
|
504
|
+
try:
|
|
505
|
+
return self.is_canonical(self.element_class(self, list(v), check=False), check=False)
|
|
506
|
+
except Exception:
|
|
507
|
+
return False
|
|
508
|
+
|
|
509
|
+
def __call__(self, v, check=True):
|
|
510
|
+
r"""
|
|
511
|
+
Return an element of ``self`` constructed from ``v`` if
|
|
512
|
+
possible.
|
|
513
|
+
|
|
514
|
+
TESTS::
|
|
515
|
+
|
|
516
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
|
|
517
|
+
sage: I([3,2,1,0])
|
|
518
|
+
[3, 2, 1, 0]
|
|
519
|
+
"""
|
|
520
|
+
try:
|
|
521
|
+
if v.parent() is self:
|
|
522
|
+
return v
|
|
523
|
+
else:
|
|
524
|
+
raise ValueError('%s should be a Python list of integer' % (v))
|
|
525
|
+
except Exception:
|
|
526
|
+
return self.element_class(self, list(v), check=check)
|
|
527
|
+
|
|
528
|
+
def orbit(self, v):
|
|
529
|
+
r"""
|
|
530
|
+
Return the orbit of the integer vector ``v`` under the action of the
|
|
531
|
+
permutation group defining ``self``. The result is a set.
|
|
532
|
+
|
|
533
|
+
EXAMPLES:
|
|
534
|
+
|
|
535
|
+
In order to get reproducible doctests, we convert the returned sets
|
|
536
|
+
into lists in increasing lexicographic order::
|
|
537
|
+
|
|
538
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
|
|
539
|
+
sage: sorted(I.orbit([2,2,0,0]))
|
|
540
|
+
[[0, 0, 2, 2], [0, 2, 2, 0], [2, 0, 0, 2], [2, 2, 0, 0]]
|
|
541
|
+
sage: sorted(I.orbit([2,1,0,0]))
|
|
542
|
+
[[0, 0, 2, 1], [0, 2, 1, 0], [1, 0, 0, 2], [2, 1, 0, 0]]
|
|
543
|
+
sage: sorted(I.orbit([2,0,1,0]))
|
|
544
|
+
[[0, 1, 0, 2], [0, 2, 0, 1], [1, 0, 2, 0], [2, 0, 1, 0]]
|
|
545
|
+
sage: sorted(I.orbit([2,0,2,0]))
|
|
546
|
+
[[0, 2, 0, 2], [2, 0, 2, 0]]
|
|
547
|
+
sage: I.orbit([1,1,1,1])
|
|
548
|
+
{[1, 1, 1, 1]}
|
|
549
|
+
"""
|
|
550
|
+
assert isinstance(v, (list, ClonableIntArray)), '%s should be a Python list or an element of %s' % (v, self)
|
|
551
|
+
try:
|
|
552
|
+
if v.parent() is self:
|
|
553
|
+
return orbit(self._sgs, v)
|
|
554
|
+
raise TypeError
|
|
555
|
+
except Exception:
|
|
556
|
+
return orbit(self._sgs, self.element_class(self, v, check=False))
|
|
557
|
+
|
|
558
|
+
def subset(self, sum=None, max_part=None):
|
|
559
|
+
r"""
|
|
560
|
+
Return the subset of ``self`` containing integer vectors
|
|
561
|
+
whose entries sum to ``sum``.
|
|
562
|
+
|
|
563
|
+
EXAMPLES::
|
|
564
|
+
|
|
565
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
|
|
566
|
+
sage: S.subset(4)
|
|
567
|
+
Integer vectors of length 4 and of sum 4 enumerated up to
|
|
568
|
+
the action of Permutation Group with generators
|
|
569
|
+
[(1,2,3,4)]
|
|
570
|
+
"""
|
|
571
|
+
return IntegerVectorsModPermutationGroup_with_constraints(self.permutation_group(), sum, max_part)
|
|
572
|
+
|
|
573
|
+
class Element(ClonableIntArray):
|
|
574
|
+
r"""
|
|
575
|
+
Element class for the set of integer vectors of given sum enumerated modulo
|
|
576
|
+
the action of a permutation group. These vectors are clonable lists of integers
|
|
577
|
+
which must satisfy conditions coming from the parent appearing in the method
|
|
578
|
+
:meth:`~sage.structure.list_clone.ClonableIntArray.check`.
|
|
579
|
+
|
|
580
|
+
TESTS::
|
|
581
|
+
|
|
582
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
|
|
583
|
+
sage: v = I.element_class(I, [4,3,2,1]); v
|
|
584
|
+
[4, 3, 2, 1]
|
|
585
|
+
sage: TestSuite(v).run()
|
|
586
|
+
sage: I.element_class(I, [4,3,2,5])
|
|
587
|
+
Traceback (most recent call last):
|
|
588
|
+
...
|
|
589
|
+
AssertionError
|
|
590
|
+
"""
|
|
591
|
+
|
|
592
|
+
def check(self):
|
|
593
|
+
r"""
|
|
594
|
+
Check that ``self`` verify the invariants needed for
|
|
595
|
+
living in ``self.parent()``.
|
|
596
|
+
|
|
597
|
+
EXAMPLES::
|
|
598
|
+
|
|
599
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
|
|
600
|
+
sage: v = I.an_element()
|
|
601
|
+
sage: v.check()
|
|
602
|
+
sage: w = I([0,4,0,0], check=False); w
|
|
603
|
+
[0, 4, 0, 0]
|
|
604
|
+
sage: w.check()
|
|
605
|
+
Traceback (most recent call last):
|
|
606
|
+
...
|
|
607
|
+
AssertionError
|
|
608
|
+
"""
|
|
609
|
+
assert self.parent().is_canonical(self)
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
class IntegerVectorsModPermutationGroup_with_constraints(UniqueRepresentation, RecursivelyEnumeratedSet_forest):
|
|
613
|
+
r"""
|
|
614
|
+
This class models finite enumerated sets of integer vectors with
|
|
615
|
+
constraint enumerated up to the action of a permutation group.
|
|
616
|
+
Integer vectors are enumerated modulo the action of the
|
|
617
|
+
permutation group. To implement that, we keep a single integer
|
|
618
|
+
vector by orbit under the action of the permutation
|
|
619
|
+
group. Elements chosen are vectors maximal in their orbit for the
|
|
620
|
+
lexicographic order.
|
|
621
|
+
|
|
622
|
+
For more information see :class:`IntegerVectorsModPermutationGroup`.
|
|
623
|
+
|
|
624
|
+
EXAMPLES::
|
|
625
|
+
|
|
626
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),
|
|
627
|
+
....: max_part=1)
|
|
628
|
+
sage: I.list()
|
|
629
|
+
[[0, 0, 0, 0], [1, 0, 0, 0], [1, 1, 0, 0], [1, 0, 1, 0], [1, 1, 1, 0],
|
|
630
|
+
[1, 1, 1, 1]]
|
|
631
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),
|
|
632
|
+
....: sum=6, max_part=4)
|
|
633
|
+
sage: I.list()
|
|
634
|
+
[[4, 2, 0, 0], [4, 1, 1, 0], [4, 1, 0, 1], [4, 0, 2, 0], [4, 0, 1, 1],
|
|
635
|
+
[4, 0, 0, 2], [3, 3, 0, 0], [3, 2, 1, 0], [3, 2, 0, 1], [3, 1, 2, 0],
|
|
636
|
+
[3, 1, 1, 1], [3, 1, 0, 2], [3, 0, 3, 0], [3, 0, 2, 1], [3, 0, 1, 2],
|
|
637
|
+
[2, 2, 2, 0], [2, 2, 1, 1], [2, 1, 2, 1]]
|
|
638
|
+
|
|
639
|
+
Here is the enumeration of unlabeled graphs over 5 vertices::
|
|
640
|
+
|
|
641
|
+
sage: G = IntegerVectorsModPermutationGroup(TransitiveGroup(10,12), max_part=1)
|
|
642
|
+
sage: G.cardinality()
|
|
643
|
+
34
|
|
644
|
+
|
|
645
|
+
TESTS::
|
|
646
|
+
|
|
647
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),4)
|
|
648
|
+
sage: TestSuite(I).run()
|
|
649
|
+
"""
|
|
650
|
+
|
|
651
|
+
def __init__(self, G, d, max_part, sgs=None):
|
|
652
|
+
r"""
|
|
653
|
+
TESTS::
|
|
654
|
+
|
|
655
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 6, max_part=4)
|
|
656
|
+
"""
|
|
657
|
+
RecursivelyEnumeratedSet_forest.__init__(self, algorithm='breadth', category=(FiniteEnumeratedSets(), FiniteEnumeratedSets().Quotients()))
|
|
658
|
+
self._permgroup = G
|
|
659
|
+
self.n = G.degree()
|
|
660
|
+
self._sum = d
|
|
661
|
+
if max_part is None:
|
|
662
|
+
self._max_part = -1
|
|
663
|
+
else:
|
|
664
|
+
self._max_part = max_part
|
|
665
|
+
|
|
666
|
+
# self.sgs: strong_generating_system
|
|
667
|
+
if sgs is None:
|
|
668
|
+
self._sgs = G.strong_generating_system()
|
|
669
|
+
else:
|
|
670
|
+
self._sgs = [list(x) for x in list(sgs)]
|
|
671
|
+
|
|
672
|
+
def _repr_(self):
|
|
673
|
+
r"""
|
|
674
|
+
TESTS::
|
|
675
|
+
|
|
676
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]])); S
|
|
677
|
+
Integer vectors of length 4 enumerated up to the action of Permutation Group with generators [(1,2,3,4)]
|
|
678
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 6); S
|
|
679
|
+
Integer vectors of length 4 and of sum 6 enumerated up to the action of Permutation Group with generators [(1,2,3,4)]
|
|
680
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 6, max_part=4); S
|
|
681
|
+
Vectors of length 4 and of sum 6 whose entries are in {0, ..., 4} enumerated up to the action of Permutation Group with generators [(1,2,3,4)]
|
|
682
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), max_part=4); S
|
|
683
|
+
Integer vectors of length 4 whose entries are in {0, ..., 4} enumerated up to the action of Permutation Group with generators [(1,2,3,4)]
|
|
684
|
+
"""
|
|
685
|
+
if self._sum is not None:
|
|
686
|
+
if self._max_part >= 0:
|
|
687
|
+
return ("Vectors of length %s and of sum %s"
|
|
688
|
+
" whose entries are in {0, ..., %s}"
|
|
689
|
+
" enumerated up to the action of %s"
|
|
690
|
+
% (self.n, self._sum, self._max_part,
|
|
691
|
+
self.permutation_group()))
|
|
692
|
+
else:
|
|
693
|
+
return ("Integer vectors of length %s"
|
|
694
|
+
" and of sum %s"
|
|
695
|
+
" enumerated up to the action of %s"
|
|
696
|
+
% (self.n, self._sum, self.permutation_group()))
|
|
697
|
+
else:
|
|
698
|
+
return ("Integer vectors of length %s"
|
|
699
|
+
" whose entries are in {0, ..., %s}"
|
|
700
|
+
" enumerated up to the action of %s"
|
|
701
|
+
% (self.n, self._max_part, self.permutation_group()))
|
|
702
|
+
|
|
703
|
+
def roots(self):
|
|
704
|
+
r"""
|
|
705
|
+
Return the root of generation of ``self``.
|
|
706
|
+
|
|
707
|
+
This method is
|
|
708
|
+
required to build the tree structure of ``self`` which
|
|
709
|
+
inherits from the class
|
|
710
|
+
:class:`~sage.sets.recursively_enumerated_set.RecursivelyEnumeratedSet_forest`.
|
|
711
|
+
|
|
712
|
+
EXAMPLES::
|
|
713
|
+
|
|
714
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
|
|
715
|
+
sage: I.roots()
|
|
716
|
+
[[0, 0, 0, 0]]
|
|
717
|
+
"""
|
|
718
|
+
return [self.element_class(self, self.n*[0,], check=False)]
|
|
719
|
+
|
|
720
|
+
def children(self, x):
|
|
721
|
+
r"""
|
|
722
|
+
Return the list of children of the element ``x``.
|
|
723
|
+
|
|
724
|
+
This method
|
|
725
|
+
is required to build the tree structure of ``self`` which
|
|
726
|
+
inherits from the class
|
|
727
|
+
:class:`~sage.sets.recursively_enumerated_set.RecursivelyEnumeratedSet_forest`.
|
|
728
|
+
|
|
729
|
+
EXAMPLES::
|
|
730
|
+
|
|
731
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
|
|
732
|
+
sage: I.children(I([2,1,0,0], check=False))
|
|
733
|
+
[[2, 2, 0, 0], [2, 1, 1, 0], [2, 1, 0, 1]]
|
|
734
|
+
"""
|
|
735
|
+
return canonical_children(self._sgs, x, -1)
|
|
736
|
+
|
|
737
|
+
def permutation_group(self):
|
|
738
|
+
r"""
|
|
739
|
+
Return the permutation group given to define ``self``.
|
|
740
|
+
|
|
741
|
+
EXAMPLES::
|
|
742
|
+
|
|
743
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3)]]), 5)
|
|
744
|
+
sage: I.permutation_group()
|
|
745
|
+
Permutation Group with generators [(1,2,3)]
|
|
746
|
+
"""
|
|
747
|
+
return self._permgroup
|
|
748
|
+
|
|
749
|
+
def __contains__(self, v):
|
|
750
|
+
r"""
|
|
751
|
+
TESTS::
|
|
752
|
+
|
|
753
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),6)
|
|
754
|
+
sage: [6,0,0,0] in I
|
|
755
|
+
True
|
|
756
|
+
sage: [5,0,1,0] in I
|
|
757
|
+
True
|
|
758
|
+
sage: [0,5,1,0] in I
|
|
759
|
+
False
|
|
760
|
+
sage: [3,0,1,3] in I
|
|
761
|
+
False
|
|
762
|
+
sage: [3,3,1,0] in I
|
|
763
|
+
False
|
|
764
|
+
"""
|
|
765
|
+
try:
|
|
766
|
+
return (self(v)).parent() is self
|
|
767
|
+
except Exception:
|
|
768
|
+
return False
|
|
769
|
+
|
|
770
|
+
def __call__(self, v, check=True):
|
|
771
|
+
r"""
|
|
772
|
+
Make `v` an element living in ``self``.
|
|
773
|
+
|
|
774
|
+
TESTS::
|
|
775
|
+
|
|
776
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 4)
|
|
777
|
+
sage: v = I([2,1,0,1]); v
|
|
778
|
+
[2, 1, 0, 1]
|
|
779
|
+
sage: v.parent()
|
|
780
|
+
Integer vectors of length 4 and of sum 4 enumerated up to
|
|
781
|
+
the action of Permutation Group with generators
|
|
782
|
+
[(1,2,3,4)]
|
|
783
|
+
"""
|
|
784
|
+
try:
|
|
785
|
+
if v.parent() is self:
|
|
786
|
+
return v
|
|
787
|
+
else:
|
|
788
|
+
raise ValueError('%s should be a Python list of integer' % (v))
|
|
789
|
+
except Exception:
|
|
790
|
+
return self.element_class(self, list(v), check=check)
|
|
791
|
+
|
|
792
|
+
def __iter__(self):
|
|
793
|
+
r"""
|
|
794
|
+
TESTS::
|
|
795
|
+
|
|
796
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),4)
|
|
797
|
+
sage: for i in I: i
|
|
798
|
+
[4, 0, 0, 0]
|
|
799
|
+
[3, 1, 0, 0]
|
|
800
|
+
[3, 0, 1, 0]
|
|
801
|
+
[3, 0, 0, 1]
|
|
802
|
+
[2, 2, 0, 0]
|
|
803
|
+
[2, 1, 1, 0]
|
|
804
|
+
[2, 1, 0, 1]
|
|
805
|
+
[2, 0, 2, 0]
|
|
806
|
+
[2, 0, 1, 1]
|
|
807
|
+
[1, 1, 1, 1]
|
|
808
|
+
|
|
809
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=7, max_part=3)
|
|
810
|
+
sage: for i in I: i
|
|
811
|
+
[3, 3, 1, 0]
|
|
812
|
+
[3, 3, 0, 1]
|
|
813
|
+
[3, 2, 2, 0]
|
|
814
|
+
[3, 2, 1, 1]
|
|
815
|
+
[3, 2, 0, 2]
|
|
816
|
+
[3, 1, 3, 0]
|
|
817
|
+
[3, 1, 2, 1]
|
|
818
|
+
[3, 1, 1, 2]
|
|
819
|
+
[3, 0, 2, 2]
|
|
820
|
+
[2, 2, 2, 1]
|
|
821
|
+
|
|
822
|
+
Check that :issue:`36681` is fixed::
|
|
823
|
+
|
|
824
|
+
sage: G = PermutationGroup([], domain=[])
|
|
825
|
+
sage: I = IntegerVectorsModPermutationGroup(G, sum=0)
|
|
826
|
+
sage: list(iter(I))
|
|
827
|
+
[[]]
|
|
828
|
+
|
|
829
|
+
Check that :issue:`36681` is fixed::
|
|
830
|
+
|
|
831
|
+
sage: G = PermutationGroup([], domain=[])
|
|
832
|
+
sage: I = IntegerVectorsModPermutationGroup(G, sum=3)
|
|
833
|
+
sage: list(iter(I))
|
|
834
|
+
[]
|
|
835
|
+
"""
|
|
836
|
+
# Special cases when domain is empty.
|
|
837
|
+
if self.n == 0:
|
|
838
|
+
if self._sum is not None and self._sum > 0:
|
|
839
|
+
# No empty vector can have positive sum.
|
|
840
|
+
return iter(())
|
|
841
|
+
else:
|
|
842
|
+
# Sum is allowed to be zero. It does not matter what
|
|
843
|
+
# the maxpart is, the empty vector is a solution.
|
|
844
|
+
return iter([self([])])
|
|
845
|
+
|
|
846
|
+
# General case, nonempty domain.
|
|
847
|
+
if self._max_part < 0:
|
|
848
|
+
return self.elements_of_depth_iterator(self._sum)
|
|
849
|
+
else:
|
|
850
|
+
SF = RecursivelyEnumeratedSet_forest(
|
|
851
|
+
(self([0]*(self.n), check=False),),
|
|
852
|
+
lambda x: [self(y, check=False)
|
|
853
|
+
for y in canonical_children(
|
|
854
|
+
self._sgs, x, self._max_part)],
|
|
855
|
+
algorithm='breadth')
|
|
856
|
+
if self._sum is None:
|
|
857
|
+
return iter(SF)
|
|
858
|
+
else:
|
|
859
|
+
return SF.elements_of_depth_iterator(self._sum)
|
|
860
|
+
|
|
861
|
+
def cardinality(self):
|
|
862
|
+
r"""
|
|
863
|
+
Return the number of integer vectors in the set.
|
|
864
|
+
|
|
865
|
+
The algorithm utilises :wikipedia:`Cycle Index Theorem <Cycle_index>`, allowing
|
|
866
|
+
for a faster than a plain enumeration computation.
|
|
867
|
+
|
|
868
|
+
EXAMPLES:
|
|
869
|
+
|
|
870
|
+
With a trivial group all vectors are canonical::
|
|
871
|
+
|
|
872
|
+
sage: G = PermutationGroup([], domain=[1,2,3])
|
|
873
|
+
sage: IntegerVectorsModPermutationGroup(G, 5).cardinality()
|
|
874
|
+
21
|
|
875
|
+
sage: IntegerVectors(5, 3).cardinality()
|
|
876
|
+
21
|
|
877
|
+
|
|
878
|
+
With two interchangeable elements, the smaller one
|
|
879
|
+
ranges from zero to ``sum//2``::
|
|
880
|
+
|
|
881
|
+
sage: G = PermutationGroup([(1,2)])
|
|
882
|
+
sage: IntegerVectorsModPermutationGroup(G, 1000).cardinality()
|
|
883
|
+
501
|
|
884
|
+
|
|
885
|
+
Binary vectors up to full symmetry are first some ones and
|
|
886
|
+
then some zeros::
|
|
887
|
+
|
|
888
|
+
sage: G = SymmetricGroup(10)
|
|
889
|
+
sage: I = IntegerVectorsModPermutationGroup(G, max_part=1)
|
|
890
|
+
sage: I.cardinality()
|
|
891
|
+
11
|
|
892
|
+
|
|
893
|
+
Binary vectors of constant weight, up to PGL(2,17), which
|
|
894
|
+
is 3-transitive, but not 4-transitive::
|
|
895
|
+
|
|
896
|
+
sage: G=PGL(2,17)
|
|
897
|
+
sage: I = IntegerVectorsModPermutationGroup(G, sum=3, max_part=1)
|
|
898
|
+
sage: I.cardinality()
|
|
899
|
+
1
|
|
900
|
+
sage: I = IntegerVectorsModPermutationGroup(G, sum=4, max_part=1)
|
|
901
|
+
sage: I.cardinality()
|
|
902
|
+
3
|
|
903
|
+
|
|
904
|
+
TESTS:
|
|
905
|
+
|
|
906
|
+
Check that :issue:`36681` is fixed::
|
|
907
|
+
|
|
908
|
+
sage: G = PermutationGroup([], domain=[])
|
|
909
|
+
sage: sgs = tuple(tuple(t) for t in G.strong_generating_system())
|
|
910
|
+
sage: V = IntegerVectorsModPermutationGroup(G, sum=1, sgs=sgs)
|
|
911
|
+
sage: V.cardinality()
|
|
912
|
+
0
|
|
913
|
+
|
|
914
|
+
The case when both ``sum`` and ``max_part`` are specified::
|
|
915
|
+
|
|
916
|
+
sage: G = PermutationGroup([(1,2,3)])
|
|
917
|
+
sage: I = IntegerVectorsModPermutationGroup(G, sum=10, max_part=5)
|
|
918
|
+
sage: I.cardinality()
|
|
919
|
+
7
|
|
920
|
+
|
|
921
|
+
All permutation groups of degree 4::
|
|
922
|
+
|
|
923
|
+
sage: for G in SymmetricGroup(4).subgroups():
|
|
924
|
+
....: sgs = tuple(tuple(t) for t in G.strong_generating_system())
|
|
925
|
+
....: I1 = IntegerVectorsModPermutationGroup(G, sum=10, sgs=sgs)
|
|
926
|
+
....: assert I1.cardinality() == len(list(I1))
|
|
927
|
+
....: I2 = IntegerVectorsModPermutationGroup(G, max_part=3, sgs=sgs)
|
|
928
|
+
....: assert I2.cardinality() == len(list(I2))
|
|
929
|
+
....: I3 = IntegerVectorsModPermutationGroup(G, sum=10, max_part=3, sgs=sgs)
|
|
930
|
+
....: assert I3.cardinality() == len(list(I3))
|
|
931
|
+
|
|
932
|
+
Symmetric group with sums 0 and 1::
|
|
933
|
+
|
|
934
|
+
sage: S10 = SymmetricGroup(10)
|
|
935
|
+
sage: IntegerVectorsModPermutationGroup(S10, 0).cardinality()
|
|
936
|
+
1
|
|
937
|
+
sage: IntegerVectorsModPermutationGroup(S10, 1).cardinality()
|
|
938
|
+
1
|
|
939
|
+
|
|
940
|
+
Trivial group with sums 1 and 100::
|
|
941
|
+
|
|
942
|
+
sage: T10 = PermutationGroup([], domain=range(1, 11))
|
|
943
|
+
sage: IntegerVectorsModPermutationGroup(T10, 1).cardinality()
|
|
944
|
+
10
|
|
945
|
+
sage: IntegerVectorsModPermutationGroup(T10, 100).cardinality()
|
|
946
|
+
4263421511271
|
|
947
|
+
"""
|
|
948
|
+
G = self._permgroup
|
|
949
|
+
k = G.degree() # Vector length
|
|
950
|
+
d = self._sum # Required sum
|
|
951
|
+
m = self._max_part # Max of one entry, -1 for no limit
|
|
952
|
+
if m == -1:
|
|
953
|
+
m = d # Any entry cannot exceed total
|
|
954
|
+
|
|
955
|
+
# Some easy special cases.
|
|
956
|
+
if k == 0:
|
|
957
|
+
# Empty vectors. There is only one, and it has zero sum.
|
|
958
|
+
# Here _max_part does not matter because any _max_part
|
|
959
|
+
# condition is vacuously true (with no parts).
|
|
960
|
+
if d == 0 or d is None:
|
|
961
|
+
return Integer(1)
|
|
962
|
+
else:
|
|
963
|
+
return Integer(0)
|
|
964
|
+
if d == 0 or m == 0:
|
|
965
|
+
# All-zero vectors. There is only one of them.
|
|
966
|
+
return Integer(1)
|
|
967
|
+
if d == 1:
|
|
968
|
+
# Vectors with one 1 and all other elements zero.
|
|
969
|
+
# The 1 can be placed in any orbit, and by symmetry
|
|
970
|
+
# it will be on the first element of the orbit.
|
|
971
|
+
return Integer(len(G.orbits()))
|
|
972
|
+
if d is not None and m >= d and G.is_trivial():
|
|
973
|
+
# Simple calculation with stars and bars.
|
|
974
|
+
return Integer(binomial(d + k - 1, k - 1))
|
|
975
|
+
|
|
976
|
+
# General case.
|
|
977
|
+
#
|
|
978
|
+
# Cardinality is computed using the Cycle Index Theorem. We
|
|
979
|
+
# have two cases. With a fixed sum d we work with power
|
|
980
|
+
# series and extract the x^d coefficient. Without a fixed sum
|
|
981
|
+
# we can do with integer arithmetic.
|
|
982
|
+
Z = G.cycle_index()
|
|
983
|
+
|
|
984
|
+
if d is None:
|
|
985
|
+
# Case 1. Without a fixed sum, the sum can be up to k*m.
|
|
986
|
+
result = sum(coeff * (m+1)**len(cycle_type)
|
|
987
|
+
for cycle_type, coeff in Z)
|
|
988
|
+
# Computed as Rational, but should have an integer value
|
|
989
|
+
# by now.
|
|
990
|
+
return Integer(result)
|
|
991
|
+
|
|
992
|
+
# Case 2. Fixed sum d. Work with power series with enough
|
|
993
|
+
# precision that x^d is valid.
|
|
994
|
+
R = PowerSeriesRing(QQ, 'x', default_prec=d+1)
|
|
995
|
+
x = R.gen()
|
|
996
|
+
|
|
997
|
+
# The figure-counting series, for max_part==m, is (1-t**(m+1))
|
|
998
|
+
# / (1-t) = 1+t+...+t**m. For the function-counting series,
|
|
999
|
+
# we substitute x**cycle_length for t.
|
|
1000
|
+
#
|
|
1001
|
+
funcount = sum(
|
|
1002
|
+
coeff * prod((1 - x**((m+1)*cycle_len)) / (1 - x**cycle_len)
|
|
1003
|
+
for cycle_len in cycle_type)
|
|
1004
|
+
for cycle_type, coeff in Z)
|
|
1005
|
+
|
|
1006
|
+
# Extract the d'th degree coefficient. Computed as Rational,
|
|
1007
|
+
# but should have an integer value by now.
|
|
1008
|
+
return Integer(funcount[d])
|
|
1009
|
+
|
|
1010
|
+
def is_canonical(self, v, check=True):
|
|
1011
|
+
r"""
|
|
1012
|
+
Return ``True`` if the integer list ``v`` is maximal in its
|
|
1013
|
+
orbit under the action of the permutation group given to
|
|
1014
|
+
define ``self``. Such integer vectors are said to be
|
|
1015
|
+
canonical. A vector `v` is canonical if and only if
|
|
1016
|
+
|
|
1017
|
+
.. MATH::
|
|
1018
|
+
|
|
1019
|
+
v = \max_{\text{lex order}} \{g \cdot v | g \in G \}
|
|
1020
|
+
|
|
1021
|
+
EXAMPLES::
|
|
1022
|
+
|
|
1023
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),
|
|
1024
|
+
....: max_part=3)
|
|
1025
|
+
sage: I.is_canonical([3,0,0,0])
|
|
1026
|
+
True
|
|
1027
|
+
sage: I.is_canonical([1,0,2,0])
|
|
1028
|
+
False
|
|
1029
|
+
sage: I.is_canonical([2,0,1,0])
|
|
1030
|
+
True
|
|
1031
|
+
"""
|
|
1032
|
+
if check:
|
|
1033
|
+
assert isinstance(v, (ClonableIntArray, list)), '%s should be a list or an integer vector' % v
|
|
1034
|
+
assert (self.n == len(v)), '%s should be of length %s' % (v, self.n)
|
|
1035
|
+
for p in v:
|
|
1036
|
+
assert (p == NN(p)), 'Elements of %s should be integers' % v
|
|
1037
|
+
return is_canonical(self._sgs, self.element_class(self, list(v), check=False))
|
|
1038
|
+
|
|
1039
|
+
def ambient(self):
|
|
1040
|
+
r"""
|
|
1041
|
+
Return the ambient space from which ``self`` is a quotient.
|
|
1042
|
+
|
|
1043
|
+
EXAMPLES::
|
|
1044
|
+
|
|
1045
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 6)
|
|
1046
|
+
sage: S.ambient()
|
|
1047
|
+
Integer vectors that sum to 6
|
|
1048
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),
|
|
1049
|
+
....: 6, max_part=12)
|
|
1050
|
+
sage: S.ambient()
|
|
1051
|
+
Integer vectors that sum to 6 with constraints: max_part=12
|
|
1052
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),
|
|
1053
|
+
....: max_part=12)
|
|
1054
|
+
sage: S.ambient()
|
|
1055
|
+
Integer vectors with constraints: max_part=12
|
|
1056
|
+
"""
|
|
1057
|
+
if self._sum is not None:
|
|
1058
|
+
if self._max_part <= -1:
|
|
1059
|
+
return IntegerVectors(n=self._sum)
|
|
1060
|
+
else:
|
|
1061
|
+
return IntegerVectors(n=self._sum, max_part=self._max_part)
|
|
1062
|
+
else:
|
|
1063
|
+
return IntegerVectors(max_part=self._max_part)
|
|
1064
|
+
|
|
1065
|
+
def lift(self, elt):
|
|
1066
|
+
r"""
|
|
1067
|
+
Lift the element ``elt`` inside the ambient space from which ``self`` is a quotient.
|
|
1068
|
+
|
|
1069
|
+
EXAMPLES::
|
|
1070
|
+
|
|
1071
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),
|
|
1072
|
+
....: max_part=1)
|
|
1073
|
+
sage: v = S.lift([1,0,1,0]); v
|
|
1074
|
+
[1, 0, 1, 0]
|
|
1075
|
+
sage: v in IntegerVectors(2,4,max_part=1)
|
|
1076
|
+
True
|
|
1077
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),
|
|
1078
|
+
....: sum=6)
|
|
1079
|
+
sage: v = S.lift(S.list()[5]); v
|
|
1080
|
+
[4, 1, 1, 0]
|
|
1081
|
+
sage: v in IntegerVectors(n=6)
|
|
1082
|
+
True
|
|
1083
|
+
"""
|
|
1084
|
+
# TODO: For now, Sage integer vectors are just python list.
|
|
1085
|
+
# Once Integer vectors will have an element class, update this
|
|
1086
|
+
# code properly
|
|
1087
|
+
return list(elt)
|
|
1088
|
+
|
|
1089
|
+
def retract(self, elt):
|
|
1090
|
+
r"""
|
|
1091
|
+
Return the canonical representative of the orbit of the
|
|
1092
|
+
integer ``elt`` under the action of the permutation group
|
|
1093
|
+
defining ``self``.
|
|
1094
|
+
|
|
1095
|
+
If the element ``elt`` is already maximal in its orbits for
|
|
1096
|
+
the lexicographic order, ``elt`` is thus the good
|
|
1097
|
+
representative for its orbit.
|
|
1098
|
+
|
|
1099
|
+
EXAMPLES::
|
|
1100
|
+
|
|
1101
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),
|
|
1102
|
+
....: sum=2, max_part=1)
|
|
1103
|
+
sage: S.retract([1,1,0,0])
|
|
1104
|
+
[1, 1, 0, 0]
|
|
1105
|
+
sage: S.retract([1,0,1,0])
|
|
1106
|
+
[1, 0, 1, 0]
|
|
1107
|
+
sage: S.retract([1,0,0,1])
|
|
1108
|
+
[1, 1, 0, 0]
|
|
1109
|
+
sage: S.retract([0,1,1,0])
|
|
1110
|
+
[1, 1, 0, 0]
|
|
1111
|
+
sage: S.retract([0,1,0,1])
|
|
1112
|
+
[1, 0, 1, 0]
|
|
1113
|
+
sage: S.retract([0,0,1,1])
|
|
1114
|
+
[1, 1, 0, 0]
|
|
1115
|
+
"""
|
|
1116
|
+
# TODO: Once Sage integer vector will have a data structure
|
|
1117
|
+
# based on ClonableIntArray, remove the conversion intarray
|
|
1118
|
+
assert len(elt) == self.n, "%s is a quotient set of %s" % (self, self.ambient())
|
|
1119
|
+
if self._sum is not None:
|
|
1120
|
+
assert sum(elt) == self._sum, "%s is a quotient set of %s" % (self, self.ambient())
|
|
1121
|
+
if self._max_part >= 0:
|
|
1122
|
+
assert max(elt) <= self._max_part, "%s is a quotient set of %s" % (self, self.ambient())
|
|
1123
|
+
intarray = self.element_class(self, elt, check=False)
|
|
1124
|
+
return self.element_class(self, canonical_representative_of_orbit_of(self._sgs, intarray), check=False)
|
|
1125
|
+
|
|
1126
|
+
def _an_element_(self):
|
|
1127
|
+
r"""
|
|
1128
|
+
Return an element of ``self``.
|
|
1129
|
+
|
|
1130
|
+
This raises an :exc:`EmptySetError` when ``self`` is empty.
|
|
1131
|
+
|
|
1132
|
+
EXAMPLES::
|
|
1133
|
+
|
|
1134
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),
|
|
1135
|
+
....: sum=0, max_part=1)
|
|
1136
|
+
sage: S.an_element()
|
|
1137
|
+
[0, 0, 0, 0]
|
|
1138
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),
|
|
1139
|
+
....: sum=1, max_part=1)
|
|
1140
|
+
sage: S.an_element()
|
|
1141
|
+
[1, 0, 0, 0]
|
|
1142
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),
|
|
1143
|
+
....: sum=2, max_part=1)
|
|
1144
|
+
sage: S.an_element()
|
|
1145
|
+
[1, 1, 0, 0]
|
|
1146
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),
|
|
1147
|
+
....: sum=3, max_part=1)
|
|
1148
|
+
sage: S.an_element()
|
|
1149
|
+
[1, 1, 1, 0]
|
|
1150
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),
|
|
1151
|
+
....: sum=4, max_part=1)
|
|
1152
|
+
sage: S.an_element()
|
|
1153
|
+
[1, 1, 1, 1]
|
|
1154
|
+
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),
|
|
1155
|
+
....: sum=5, max_part=1)
|
|
1156
|
+
sage: S.an_element()
|
|
1157
|
+
Traceback (most recent call last):
|
|
1158
|
+
...
|
|
1159
|
+
EmptySetError
|
|
1160
|
+
"""
|
|
1161
|
+
if self._max_part < 0:
|
|
1162
|
+
return self([self._sum]+(self.n-1)*[0], check=False)
|
|
1163
|
+
else:
|
|
1164
|
+
try:
|
|
1165
|
+
v = iter(self)
|
|
1166
|
+
return next(v)
|
|
1167
|
+
except StopIteration:
|
|
1168
|
+
from sage.categories.sets_cat import EmptySetError
|
|
1169
|
+
raise EmptySetError
|
|
1170
|
+
|
|
1171
|
+
def orbit(self, v):
|
|
1172
|
+
r"""
|
|
1173
|
+
Return the orbit of the vector ``v`` under the action of the
|
|
1174
|
+
permutation group defining ``self``. The result is a set.
|
|
1175
|
+
|
|
1176
|
+
INPUT:
|
|
1177
|
+
|
|
1178
|
+
- ``v`` -- an element of ``self`` or any list of length the
|
|
1179
|
+
degree of the permutation group
|
|
1180
|
+
|
|
1181
|
+
EXAMPLES:
|
|
1182
|
+
|
|
1183
|
+
We convert the result in a list in increasing lexicographic
|
|
1184
|
+
order, to get a reproducible doctest::
|
|
1185
|
+
|
|
1186
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 4)
|
|
1187
|
+
sage: I.orbit([1,1,1,1])
|
|
1188
|
+
{[1, 1, 1, 1]}
|
|
1189
|
+
sage: sorted(I.orbit([3,0,0,1]))
|
|
1190
|
+
[[0, 0, 1, 3], [0, 1, 3, 0], [1, 3, 0, 0], [3, 0, 0, 1]]
|
|
1191
|
+
"""
|
|
1192
|
+
assert isinstance(v, (list, ClonableIntArray)), '%s should be a Python list or an element of %s' % (v, self)
|
|
1193
|
+
try:
|
|
1194
|
+
if v.parent() is self:
|
|
1195
|
+
return orbit(self._sgs, v)
|
|
1196
|
+
except Exception:
|
|
1197
|
+
return orbit(self._sgs, self.element_class(self, v, check=False))
|
|
1198
|
+
|
|
1199
|
+
class Element(ClonableIntArray):
|
|
1200
|
+
r"""
|
|
1201
|
+
Element class for the set of integer vectors with constraints enumerated
|
|
1202
|
+
modulo the action of a permutation group. These vectors are clonable lists
|
|
1203
|
+
of integers which must satisfy conditions coming from the parent as in
|
|
1204
|
+
the method :meth:`~sage.combinat.integer_vectors_mod_permgroup.IntegerVectorsModPermutationGroup_with_constraints.Element.check`.
|
|
1205
|
+
|
|
1206
|
+
TESTS::
|
|
1207
|
+
|
|
1208
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 4)
|
|
1209
|
+
sage: v = I.element_class(I, [3,1,0,0]); v
|
|
1210
|
+
[3, 1, 0, 0]
|
|
1211
|
+
sage: TestSuite(v).run()
|
|
1212
|
+
sage: v = I.element_class(I, [3,2,0,0])
|
|
1213
|
+
Traceback (most recent call last):
|
|
1214
|
+
...
|
|
1215
|
+
AssertionError: [3, 2, 0, 0] should be an integer vector of sum 4
|
|
1216
|
+
"""
|
|
1217
|
+
|
|
1218
|
+
def check(self):
|
|
1219
|
+
r"""
|
|
1220
|
+
Check that ``self`` meets the constraints of being an element of ``self.parent()``.
|
|
1221
|
+
|
|
1222
|
+
EXAMPLES::
|
|
1223
|
+
|
|
1224
|
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 4)
|
|
1225
|
+
sage: v = I.an_element()
|
|
1226
|
+
sage: v.check()
|
|
1227
|
+
sage: w = I([0,4,0,0], check=False); w
|
|
1228
|
+
[0, 4, 0, 0]
|
|
1229
|
+
sage: w.check()
|
|
1230
|
+
Traceback (most recent call last):
|
|
1231
|
+
...
|
|
1232
|
+
AssertionError
|
|
1233
|
+
"""
|
|
1234
|
+
if self.parent()._sum is not None:
|
|
1235
|
+
assert sum(self) == self.parent()._sum, '%s should be an integer vector of sum %s' % (self, self.parent()._sum)
|
|
1236
|
+
if self.parent()._max_part >= 0:
|
|
1237
|
+
assert max(self) <= self.parent()._max_part, 'Entries of %s must be inferior to %s' % (self, self.parent()._max_part)
|
|
1238
|
+
assert self.parent().is_canonical(self)
|