passagemath-categories 10.6.32__cp314-cp314t-musllinux_1_2_aarch64.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_categories-10.6.32.dist-info/METADATA +156 -0
- passagemath_categories-10.6.32.dist-info/RECORD +719 -0
- passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
- passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
- passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
- passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
- passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
- sage/all__sagemath_categories.py +28 -0
- sage/arith/all.py +38 -0
- sage/arith/constants.pxd +27 -0
- sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/functions.pxd +4 -0
- sage/arith/functions.pyx +221 -0
- sage/arith/misc.py +6552 -0
- sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/multi_modular.pxd +39 -0
- sage/arith/multi_modular.pyx +994 -0
- sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/rational_reconstruction.pxd +4 -0
- sage/arith/rational_reconstruction.pyx +115 -0
- sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/srange.pyx +571 -0
- sage/calculus/all__sagemath_categories.py +2 -0
- sage/calculus/functional.py +481 -0
- sage/calculus/functions.py +151 -0
- sage/categories/additive_groups.py +73 -0
- sage/categories/additive_magmas.py +1044 -0
- sage/categories/additive_monoids.py +114 -0
- sage/categories/additive_semigroups.py +184 -0
- sage/categories/affine_weyl_groups.py +238 -0
- sage/categories/algebra_ideals.py +95 -0
- sage/categories/algebra_modules.py +96 -0
- sage/categories/algebras.py +349 -0
- sage/categories/algebras_with_basis.py +377 -0
- sage/categories/all.py +160 -0
- sage/categories/aperiodic_semigroups.py +29 -0
- sage/categories/associative_algebras.py +47 -0
- sage/categories/bialgebras.py +101 -0
- sage/categories/bialgebras_with_basis.py +414 -0
- sage/categories/bimodules.py +206 -0
- sage/categories/chain_complexes.py +268 -0
- sage/categories/classical_crystals.py +480 -0
- sage/categories/coalgebras.py +405 -0
- sage/categories/coalgebras_with_basis.py +232 -0
- sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/coercion_methods.pyx +52 -0
- sage/categories/commutative_additive_groups.py +104 -0
- sage/categories/commutative_additive_monoids.py +45 -0
- sage/categories/commutative_additive_semigroups.py +48 -0
- sage/categories/commutative_algebra_ideals.py +87 -0
- sage/categories/commutative_algebras.py +94 -0
- sage/categories/commutative_ring_ideals.py +58 -0
- sage/categories/commutative_rings.py +736 -0
- sage/categories/complete_discrete_valuation.py +293 -0
- sage/categories/complex_reflection_groups.py +145 -0
- sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
- sage/categories/coxeter_group_algebras.py +186 -0
- sage/categories/coxeter_groups.py +3402 -0
- sage/categories/crystals.py +2628 -0
- sage/categories/cw_complexes.py +216 -0
- sage/categories/dedekind_domains.py +137 -0
- sage/categories/discrete_valuation.py +325 -0
- sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
- sage/categories/division_rings.py +114 -0
- sage/categories/domains.py +95 -0
- sage/categories/drinfeld_modules.py +789 -0
- sage/categories/dual.py +42 -0
- sage/categories/enumerated_sets.py +1146 -0
- sage/categories/euclidean_domains.py +271 -0
- sage/categories/examples/algebras_with_basis.py +102 -0
- sage/categories/examples/all.py +1 -0
- sage/categories/examples/commutative_additive_monoids.py +130 -0
- sage/categories/examples/commutative_additive_semigroups.py +199 -0
- sage/categories/examples/coxeter_groups.py +8 -0
- sage/categories/examples/crystals.py +236 -0
- sage/categories/examples/cw_complexes.py +163 -0
- sage/categories/examples/facade_sets.py +187 -0
- sage/categories/examples/filtered_algebras_with_basis.py +204 -0
- sage/categories/examples/filtered_modules_with_basis.py +154 -0
- sage/categories/examples/finite_coxeter_groups.py +252 -0
- sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
- sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
- sage/categories/examples/finite_enumerated_sets.py +208 -0
- sage/categories/examples/finite_monoids.py +150 -0
- sage/categories/examples/finite_semigroups.py +190 -0
- sage/categories/examples/finite_weyl_groups.py +191 -0
- sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
- sage/categories/examples/graded_modules_with_basis.py +168 -0
- sage/categories/examples/graphs.py +122 -0
- sage/categories/examples/hopf_algebras_with_basis.py +145 -0
- sage/categories/examples/infinite_enumerated_sets.py +190 -0
- sage/categories/examples/lie_algebras.py +352 -0
- sage/categories/examples/lie_algebras_with_basis.py +196 -0
- sage/categories/examples/magmas.py +162 -0
- sage/categories/examples/manifolds.py +94 -0
- sage/categories/examples/monoids.py +144 -0
- sage/categories/examples/posets.py +178 -0
- sage/categories/examples/semigroups.py +580 -0
- sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/examples/semigroups_cython.pyx +221 -0
- sage/categories/examples/semirings.py +249 -0
- sage/categories/examples/sets_cat.py +706 -0
- sage/categories/examples/sets_with_grading.py +101 -0
- sage/categories/examples/with_realizations.py +542 -0
- sage/categories/fields.py +991 -0
- sage/categories/filtered_algebras.py +63 -0
- sage/categories/filtered_algebras_with_basis.py +548 -0
- sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
- sage/categories/filtered_modules.py +210 -0
- sage/categories/filtered_modules_with_basis.py +1209 -0
- sage/categories/finite_complex_reflection_groups.py +1506 -0
- sage/categories/finite_coxeter_groups.py +1138 -0
- sage/categories/finite_crystals.py +103 -0
- sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
- sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
- sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
- sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
- sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
- sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
- sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
- sage/categories/finite_enumerated_sets.py +769 -0
- sage/categories/finite_fields.py +252 -0
- sage/categories/finite_groups.py +256 -0
- sage/categories/finite_lattice_posets.py +242 -0
- sage/categories/finite_monoids.py +316 -0
- sage/categories/finite_permutation_groups.py +339 -0
- sage/categories/finite_posets.py +1994 -0
- sage/categories/finite_semigroups.py +136 -0
- sage/categories/finite_sets.py +93 -0
- sage/categories/finite_weyl_groups.py +39 -0
- sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
- sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
- sage/categories/finitely_generated_magmas.py +57 -0
- sage/categories/finitely_generated_semigroups.py +214 -0
- sage/categories/function_fields.py +76 -0
- sage/categories/g_sets.py +77 -0
- sage/categories/gcd_domains.py +65 -0
- sage/categories/generalized_coxeter_groups.py +94 -0
- sage/categories/graded_algebras.py +85 -0
- sage/categories/graded_algebras_with_basis.py +258 -0
- sage/categories/graded_bialgebras.py +32 -0
- sage/categories/graded_bialgebras_with_basis.py +32 -0
- sage/categories/graded_coalgebras.py +65 -0
- sage/categories/graded_coalgebras_with_basis.py +51 -0
- sage/categories/graded_hopf_algebras.py +41 -0
- sage/categories/graded_hopf_algebras_with_basis.py +169 -0
- sage/categories/graded_lie_algebras.py +91 -0
- sage/categories/graded_lie_algebras_with_basis.py +44 -0
- sage/categories/graded_lie_conformal_algebras.py +74 -0
- sage/categories/graded_modules.py +133 -0
- sage/categories/graded_modules_with_basis.py +329 -0
- sage/categories/graphs.py +138 -0
- sage/categories/group_algebras.py +430 -0
- sage/categories/groupoid.py +94 -0
- sage/categories/groups.py +667 -0
- sage/categories/h_trivial_semigroups.py +64 -0
- sage/categories/hecke_modules.py +185 -0
- sage/categories/highest_weight_crystals.py +980 -0
- sage/categories/hopf_algebras.py +219 -0
- sage/categories/hopf_algebras_with_basis.py +309 -0
- sage/categories/infinite_enumerated_sets.py +115 -0
- sage/categories/integral_domains.py +203 -0
- sage/categories/j_trivial_semigroups.py +29 -0
- sage/categories/kac_moody_algebras.py +82 -0
- sage/categories/kahler_algebras.py +203 -0
- sage/categories/l_trivial_semigroups.py +63 -0
- sage/categories/lambda_bracket_algebras.py +280 -0
- sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
- sage/categories/lattice_posets.py +89 -0
- sage/categories/left_modules.py +49 -0
- sage/categories/lie_algebras.py +1070 -0
- sage/categories/lie_algebras_with_basis.py +261 -0
- sage/categories/lie_conformal_algebras.py +350 -0
- sage/categories/lie_conformal_algebras_with_basis.py +147 -0
- sage/categories/lie_groups.py +73 -0
- sage/categories/loop_crystals.py +1290 -0
- sage/categories/magmas.py +1189 -0
- sage/categories/magmas_and_additive_magmas.py +149 -0
- sage/categories/magmatic_algebras.py +365 -0
- sage/categories/manifolds.py +352 -0
- sage/categories/matrix_algebras.py +40 -0
- sage/categories/metric_spaces.py +387 -0
- sage/categories/modular_abelian_varieties.py +78 -0
- sage/categories/modules.py +989 -0
- sage/categories/modules_with_basis.py +2794 -0
- sage/categories/monoid_algebras.py +38 -0
- sage/categories/monoids.py +739 -0
- sage/categories/noetherian_rings.py +87 -0
- sage/categories/number_fields.py +242 -0
- sage/categories/ore_modules.py +189 -0
- sage/categories/partially_ordered_monoids.py +49 -0
- sage/categories/permutation_groups.py +63 -0
- sage/categories/pointed_sets.py +42 -0
- sage/categories/polyhedra.py +74 -0
- sage/categories/poor_man_map.py +270 -0
- sage/categories/posets.py +722 -0
- sage/categories/principal_ideal_domains.py +270 -0
- sage/categories/quantum_group_representations.py +543 -0
- sage/categories/quotient_fields.py +728 -0
- sage/categories/r_trivial_semigroups.py +45 -0
- sage/categories/regular_crystals.py +898 -0
- sage/categories/regular_supercrystals.py +170 -0
- sage/categories/right_modules.py +49 -0
- sage/categories/ring_ideals.py +74 -0
- sage/categories/rings.py +1904 -0
- sage/categories/rngs.py +175 -0
- sage/categories/schemes.py +393 -0
- sage/categories/semigroups.py +1060 -0
- sage/categories/semirings.py +71 -0
- sage/categories/semisimple_algebras.py +114 -0
- sage/categories/sets_with_grading.py +235 -0
- sage/categories/shephard_groups.py +43 -0
- sage/categories/signed_tensor.py +120 -0
- sage/categories/simplicial_complexes.py +134 -0
- sage/categories/simplicial_sets.py +1206 -0
- sage/categories/super_algebras.py +149 -0
- sage/categories/super_algebras_with_basis.py +144 -0
- sage/categories/super_hopf_algebras_with_basis.py +126 -0
- sage/categories/super_lie_conformal_algebras.py +193 -0
- sage/categories/super_modules.py +229 -0
- sage/categories/super_modules_with_basis.py +193 -0
- sage/categories/supercommutative_algebras.py +99 -0
- sage/categories/supercrystals.py +406 -0
- sage/categories/tensor.py +110 -0
- sage/categories/topological_spaces.py +170 -0
- sage/categories/triangular_kac_moody_algebras.py +439 -0
- sage/categories/tutorial.py +58 -0
- sage/categories/unique_factorization_domains.py +318 -0
- sage/categories/unital_algebras.py +426 -0
- sage/categories/vector_bundles.py +159 -0
- sage/categories/vector_spaces.py +357 -0
- sage/categories/weyl_groups.py +853 -0
- sage/combinat/all__sagemath_categories.py +34 -0
- sage/combinat/backtrack.py +180 -0
- sage/combinat/combinat.py +2269 -0
- sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/combinat_cython.pxd +6 -0
- sage/combinat/combinat_cython.pyx +390 -0
- sage/combinat/combination.py +796 -0
- sage/combinat/combinatorial_map.py +416 -0
- sage/combinat/composition.py +2192 -0
- sage/combinat/dlx.py +510 -0
- sage/combinat/integer_lists/__init__.py +7 -0
- sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/base.pxd +16 -0
- sage/combinat/integer_lists/base.pyx +713 -0
- sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/invlex.pxd +4 -0
- sage/combinat/integer_lists/invlex.pyx +1650 -0
- sage/combinat/integer_lists/lists.py +328 -0
- sage/combinat/integer_lists/nn.py +48 -0
- sage/combinat/integer_vector.py +1818 -0
- sage/combinat/integer_vector_weighted.py +413 -0
- sage/combinat/matrices/all__sagemath_categories.py +5 -0
- sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/matrices/dancing_links.pyx +1159 -0
- sage/combinat/matrices/dancing_links_c.h +380 -0
- sage/combinat/matrices/dlxcpp.py +136 -0
- sage/combinat/partition.py +10070 -0
- sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/partitions.pyx +743 -0
- sage/combinat/permutation.py +10168 -0
- sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/permutation_cython.pxd +11 -0
- sage/combinat/permutation_cython.pyx +407 -0
- sage/combinat/q_analogues.py +1090 -0
- sage/combinat/ranker.py +268 -0
- sage/combinat/subset.py +1561 -0
- sage/combinat/subsets_hereditary.py +202 -0
- sage/combinat/subsets_pairwise.py +184 -0
- sage/combinat/tools.py +63 -0
- sage/combinat/tuple.py +348 -0
- sage/data_structures/all.py +2 -0
- sage/data_structures/all__sagemath_categories.py +2 -0
- sage/data_structures/binary_matrix.pxd +138 -0
- sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/binary_search.pxd +3 -0
- sage/data_structures/binary_search.pyx +66 -0
- sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset.pxd +40 -0
- sage/data_structures/bitset.pyx +2385 -0
- sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset_base.pxd +926 -0
- sage/data_structures/bitset_base.pyx +117 -0
- sage/data_structures/bitset_intrinsics.h +487 -0
- sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/blas_dict.pxd +12 -0
- sage/data_structures/blas_dict.pyx +469 -0
- sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/list_of_pairs.pxd +16 -0
- sage/data_structures/list_of_pairs.pyx +122 -0
- sage/data_structures/mutable_poset.py +3312 -0
- sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/pairing_heap.h +346 -0
- sage/data_structures/pairing_heap.pxd +88 -0
- sage/data_structures/pairing_heap.pyx +1464 -0
- sage/data_structures/sparse_bitset.pxd +62 -0
- sage/data_structures/stream.py +5070 -0
- sage/databases/all__sagemath_categories.py +7 -0
- sage/databases/sql_db.py +2236 -0
- sage/ext/all__sagemath_categories.py +3 -0
- sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_callable.pxd +4 -0
- sage/ext/fast_callable.pyx +2746 -0
- sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_eval.pxd +1 -0
- sage/ext/fast_eval.pyx +102 -0
- sage/ext/interpreters/__init__.py +1 -0
- sage/ext/interpreters/all__sagemath_categories.py +2 -0
- sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_el.pxd +18 -0
- sage/ext/interpreters/wrapper_el.pyx +148 -0
- sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_py.pxd +17 -0
- sage/ext/interpreters/wrapper_py.pyx +133 -0
- sage/functions/airy.py +937 -0
- sage/functions/all.py +97 -0
- sage/functions/bessel.py +2102 -0
- sage/functions/error.py +784 -0
- sage/functions/exp_integral.py +1529 -0
- sage/functions/gamma.py +1087 -0
- sage/functions/generalized.py +672 -0
- sage/functions/hyperbolic.py +747 -0
- sage/functions/hypergeometric.py +1156 -0
- sage/functions/jacobi.py +1705 -0
- sage/functions/log.py +1402 -0
- sage/functions/min_max.py +338 -0
- sage/functions/orthogonal_polys.py +3106 -0
- sage/functions/other.py +2303 -0
- sage/functions/piecewise.py +1505 -0
- sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/functions/prime_pi.pyx +262 -0
- sage/functions/special.py +1212 -0
- sage/functions/spike_function.py +278 -0
- sage/functions/transcendental.py +690 -0
- sage/functions/trig.py +1062 -0
- sage/functions/wigner.py +726 -0
- sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/geometry/abc.pyx +82 -0
- sage/geometry/all__sagemath_categories.py +1 -0
- sage/groups/all__sagemath_categories.py +11 -0
- sage/groups/generic.py +1733 -0
- sage/groups/groups_catalog.py +113 -0
- sage/groups/perm_gps/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/all.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
- sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
- sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
- sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
- sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
- sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
- sage/interfaces/abc.py +140 -0
- sage/interfaces/all.py +58 -0
- sage/interfaces/all__sagemath_categories.py +1 -0
- sage/interfaces/expect.py +1643 -0
- sage/interfaces/interface.py +1682 -0
- sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/process.pxd +5 -0
- sage/interfaces/process.pyx +288 -0
- sage/interfaces/quit.py +167 -0
- sage/interfaces/sage0.py +604 -0
- sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/sagespawn.pyx +308 -0
- sage/interfaces/tab_completion.py +101 -0
- sage/misc/all__sagemath_categories.py +78 -0
- sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/allocator.pxd +6 -0
- sage/misc/allocator.pyx +47 -0
- sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/binary_tree.pxd +29 -0
- sage/misc/binary_tree.pyx +537 -0
- sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/callable_dict.pyx +89 -0
- sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/citation.pyx +159 -0
- sage/misc/converting_dict.py +293 -0
- sage/misc/defaults.py +129 -0
- sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/derivative.pyx +223 -0
- sage/misc/functional.py +2005 -0
- sage/misc/html.py +589 -0
- sage/misc/latex.py +2673 -0
- sage/misc/latex_macros.py +236 -0
- sage/misc/latex_standalone.py +1833 -0
- sage/misc/map_threaded.py +38 -0
- sage/misc/mathml.py +76 -0
- sage/misc/method_decorator.py +88 -0
- sage/misc/mrange.py +755 -0
- sage/misc/multireplace.py +41 -0
- sage/misc/object_multiplexer.py +92 -0
- sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/parser.pyx +1107 -0
- sage/misc/random_testing.py +264 -0
- sage/misc/rest_index_of_methods.py +377 -0
- sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/search.pxd +2 -0
- sage/misc/search.pyx +68 -0
- sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/stopgap.pyx +95 -0
- sage/misc/table.py +853 -0
- sage/monoids/all__sagemath_categories.py +1 -0
- sage/monoids/indexed_free_monoid.py +1071 -0
- sage/monoids/monoid.py +82 -0
- sage/numerical/all__sagemath_categories.py +1 -0
- sage/numerical/backends/all__sagemath_categories.py +1 -0
- sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_backend.pxd +61 -0
- sage/numerical/backends/generic_backend.pyx +1893 -0
- sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_sdp_backend.pxd +38 -0
- sage/numerical/backends/generic_sdp_backend.pyx +755 -0
- sage/parallel/all.py +6 -0
- sage/parallel/decorate.py +575 -0
- sage/parallel/map_reduce.py +1997 -0
- sage/parallel/multiprocessing_sage.py +76 -0
- sage/parallel/ncpus.py +35 -0
- sage/parallel/parallelism.py +364 -0
- sage/parallel/reference.py +47 -0
- sage/parallel/use_fork.py +333 -0
- sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/abc.pxd +31 -0
- sage/rings/abc.pyx +526 -0
- sage/rings/algebraic_closure_finite_field.py +1154 -0
- sage/rings/all__sagemath_categories.py +91 -0
- sage/rings/big_oh.py +227 -0
- sage/rings/continued_fraction.py +2754 -0
- sage/rings/continued_fraction_gosper.py +220 -0
- sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/factorint.pyx +295 -0
- sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fast_arith.pxd +21 -0
- sage/rings/fast_arith.pyx +535 -0
- sage/rings/finite_rings/all__sagemath_categories.py +9 -0
- sage/rings/finite_rings/conway_polynomials.py +542 -0
- sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_base.pxd +12 -0
- sage/rings/finite_rings/element_base.pyx +1176 -0
- sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/finite_field_base.pxd +7 -0
- sage/rings/finite_rings/finite_field_base.pyx +2171 -0
- sage/rings/finite_rings/finite_field_constructor.py +827 -0
- sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
- sage/rings/finite_rings/galois_group.py +154 -0
- sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_finite_field.pxd +23 -0
- sage/rings/finite_rings/hom_finite_field.pyx +856 -0
- sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
- sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
- sage/rings/finite_rings/homset.py +357 -0
- sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/integer_mod.pxd +56 -0
- sage/rings/finite_rings/integer_mod.pyx +4586 -0
- sage/rings/finite_rings/integer_mod_limits.h +11 -0
- sage/rings/finite_rings/integer_mod_ring.py +2044 -0
- sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/residue_field.pxd +30 -0
- sage/rings/finite_rings/residue_field.pyx +1811 -0
- sage/rings/finite_rings/stdint.pxd +19 -0
- sage/rings/fraction_field.py +1452 -0
- sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fraction_field_element.pyx +1357 -0
- sage/rings/function_field/all.py +7 -0
- sage/rings/function_field/all__sagemath_categories.py +2 -0
- sage/rings/function_field/constructor.py +218 -0
- sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element.pxd +11 -0
- sage/rings/function_field/element.pyx +1008 -0
- sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element_rational.pyx +513 -0
- sage/rings/function_field/extensions.py +230 -0
- sage/rings/function_field/function_field.py +1468 -0
- sage/rings/function_field/function_field_rational.py +1005 -0
- sage/rings/function_field/ideal.py +1155 -0
- sage/rings/function_field/ideal_rational.py +629 -0
- sage/rings/function_field/jacobian_base.py +826 -0
- sage/rings/function_field/jacobian_hess.py +1053 -0
- sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
- sage/rings/function_field/maps.py +1039 -0
- sage/rings/function_field/order.py +281 -0
- sage/rings/function_field/order_basis.py +586 -0
- sage/rings/function_field/order_rational.py +576 -0
- sage/rings/function_field/place.py +426 -0
- sage/rings/function_field/place_rational.py +181 -0
- sage/rings/generic.py +320 -0
- sage/rings/homset.py +332 -0
- sage/rings/ideal.py +1885 -0
- sage/rings/ideal_monoid.py +215 -0
- sage/rings/infinity.py +1890 -0
- sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer.pxd +45 -0
- sage/rings/integer.pyx +7874 -0
- sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer_ring.pxd +8 -0
- sage/rings/integer_ring.pyx +1693 -0
- sage/rings/laurent_series_ring.py +931 -0
- sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/laurent_series_ring_element.pxd +11 -0
- sage/rings/laurent_series_ring_element.pyx +1927 -0
- sage/rings/lazy_series.py +7815 -0
- sage/rings/lazy_series_ring.py +4356 -0
- sage/rings/localization.py +1043 -0
- sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/morphism.pxd +39 -0
- sage/rings/morphism.pyx +3299 -0
- sage/rings/multi_power_series_ring.py +1145 -0
- sage/rings/multi_power_series_ring_element.py +2184 -0
- sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/noncommutative_ideals.pyx +423 -0
- sage/rings/number_field/all__sagemath_categories.py +1 -0
- sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_base.pxd +8 -0
- sage/rings/number_field/number_field_base.pyx +507 -0
- sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_element_base.pxd +6 -0
- sage/rings/number_field/number_field_element_base.pyx +36 -0
- sage/rings/number_field/number_field_ideal.py +3550 -0
- sage/rings/padics/all__sagemath_categories.py +4 -0
- sage/rings/padics/local_generic.py +1670 -0
- sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/local_generic_element.pxd +5 -0
- sage/rings/padics/local_generic_element.pyx +1017 -0
- sage/rings/padics/misc.py +256 -0
- sage/rings/padics/padic_generic.py +1911 -0
- sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/pow_computer.pxd +38 -0
- sage/rings/padics/pow_computer.pyx +671 -0
- sage/rings/padics/precision_error.py +24 -0
- sage/rings/polynomial/all__sagemath_categories.py +25 -0
- sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/commutative_polynomial.pxd +6 -0
- sage/rings/polynomial/commutative_polynomial.pyx +24 -0
- sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/cyclotomic.pyx +404 -0
- sage/rings/polynomial/flatten.py +711 -0
- sage/rings/polynomial/ideal.py +102 -0
- sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
- sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
- sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/laurent_polynomial.pxd +18 -0
- sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
- sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
- sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
- sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
- sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial.pxd +12 -0
- sage/rings/polynomial/multi_polynomial.pyx +3082 -0
- sage/rings/polynomial/multi_polynomial_element.py +2570 -0
- sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
- sage/rings/polynomial/multi_polynomial_ring.py +947 -0
- sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
- sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
- sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polydict.pxd +45 -0
- sage/rings/polynomial/polydict.pyx +2701 -0
- sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_compiled.pxd +59 -0
- sage/rings/polynomial/polynomial_compiled.pyx +509 -0
- sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_element.pxd +64 -0
- sage/rings/polynomial/polynomial_element.pyx +13255 -0
- sage/rings/polynomial/polynomial_element_generic.py +1637 -0
- sage/rings/polynomial/polynomial_fateman.py +97 -0
- sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
- sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
- sage/rings/polynomial/polynomial_ring.py +3784 -0
- sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
- sage/rings/polynomial/polynomial_singular_interface.py +549 -0
- sage/rings/polynomial/symmetric_ideal.py +989 -0
- sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/symmetric_reduction.pxd +8 -0
- sage/rings/polynomial/symmetric_reduction.pyx +669 -0
- sage/rings/polynomial/term_order.py +2279 -0
- sage/rings/polynomial/toy_buchberger.py +449 -0
- sage/rings/polynomial/toy_d_basis.py +387 -0
- sage/rings/polynomial/toy_variety.py +362 -0
- sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_mpoly.pxd +9 -0
- sage/rings/power_series_mpoly.pyx +161 -0
- sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_poly.pxd +10 -0
- sage/rings/power_series_poly.pyx +1317 -0
- sage/rings/power_series_ring.py +1441 -0
- sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_ring_element.pxd +12 -0
- sage/rings/power_series_ring_element.pyx +3028 -0
- sage/rings/puiseux_series_ring.py +487 -0
- sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/puiseux_series_ring_element.pxd +7 -0
- sage/rings/puiseux_series_ring_element.pyx +1055 -0
- sage/rings/qqbar_decorators.py +167 -0
- sage/rings/quotient_ring.py +1598 -0
- sage/rings/quotient_ring_element.py +979 -0
- sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/rational.pxd +20 -0
- sage/rings/rational.pyx +4284 -0
- sage/rings/rational_field.py +1730 -0
- sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_double.pxd +16 -0
- sage/rings/real_double.pyx +2218 -0
- sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_lazy.pxd +30 -0
- sage/rings/real_lazy.pyx +1773 -0
- sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/ring.pxd +30 -0
- sage/rings/ring.pyx +850 -0
- sage/rings/semirings/all.py +3 -0
- sage/rings/semirings/non_negative_integer_semiring.py +107 -0
- sage/rings/semirings/tropical_mpolynomial.py +972 -0
- sage/rings/semirings/tropical_polynomial.py +997 -0
- sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/semirings/tropical_semiring.pyx +676 -0
- sage/rings/semirings/tropical_variety.py +1701 -0
- sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/sum_of_squares.pxd +3 -0
- sage/rings/sum_of_squares.pyx +336 -0
- sage/rings/tests.py +504 -0
- sage/schemes/affine/affine_homset.py +508 -0
- sage/schemes/affine/affine_morphism.py +1574 -0
- sage/schemes/affine/affine_point.py +460 -0
- sage/schemes/affine/affine_rational_point.py +308 -0
- sage/schemes/affine/affine_space.py +1264 -0
- sage/schemes/affine/affine_subscheme.py +592 -0
- sage/schemes/affine/all.py +25 -0
- sage/schemes/all__sagemath_categories.py +5 -0
- sage/schemes/generic/algebraic_scheme.py +2092 -0
- sage/schemes/generic/all.py +5 -0
- sage/schemes/generic/ambient_space.py +400 -0
- sage/schemes/generic/divisor.py +465 -0
- sage/schemes/generic/divisor_group.py +313 -0
- sage/schemes/generic/glue.py +84 -0
- sage/schemes/generic/homset.py +820 -0
- sage/schemes/generic/hypersurface.py +234 -0
- sage/schemes/generic/morphism.py +2107 -0
- sage/schemes/generic/point.py +237 -0
- sage/schemes/generic/scheme.py +1190 -0
- sage/schemes/generic/spec.py +199 -0
- sage/schemes/product_projective/all.py +6 -0
- sage/schemes/product_projective/homset.py +236 -0
- sage/schemes/product_projective/morphism.py +517 -0
- sage/schemes/product_projective/point.py +568 -0
- sage/schemes/product_projective/rational_point.py +550 -0
- sage/schemes/product_projective/space.py +1301 -0
- sage/schemes/product_projective/subscheme.py +466 -0
- sage/schemes/projective/all.py +24 -0
- sage/schemes/projective/proj_bdd_height.py +453 -0
- sage/schemes/projective/projective_homset.py +718 -0
- sage/schemes/projective/projective_morphism.py +2792 -0
- sage/schemes/projective/projective_point.py +1484 -0
- sage/schemes/projective/projective_rational_point.py +569 -0
- sage/schemes/projective/projective_space.py +2571 -0
- sage/schemes/projective/projective_subscheme.py +1574 -0
- sage/sets/all.py +17 -0
- sage/sets/cartesian_product.py +376 -0
- sage/sets/condition_set.py +525 -0
- sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/disjoint_set.pxd +36 -0
- sage/sets/disjoint_set.pyx +998 -0
- sage/sets/disjoint_union_enumerated_sets.py +625 -0
- sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/family.pxd +12 -0
- sage/sets/family.pyx +1556 -0
- sage/sets/finite_enumerated_set.py +406 -0
- sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/finite_set_map_cy.pxd +34 -0
- sage/sets/finite_set_map_cy.pyx +708 -0
- sage/sets/finite_set_maps.py +591 -0
- sage/sets/image_set.py +448 -0
- sage/sets/integer_range.py +829 -0
- sage/sets/non_negative_integers.py +241 -0
- sage/sets/positive_integers.py +93 -0
- sage/sets/primes.py +188 -0
- sage/sets/real_set.py +2760 -0
- sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/recursively_enumerated_set.pxd +31 -0
- sage/sets/recursively_enumerated_set.pyx +2082 -0
- sage/sets/set.py +2083 -0
- sage/sets/set_from_iterator.py +1021 -0
- sage/sets/totally_ordered_finite_set.py +329 -0
- sage/symbolic/all__sagemath_categories.py +1 -0
- sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/symbolic/function.pxd +29 -0
- sage/symbolic/function.pyx +1488 -0
- sage/symbolic/symbols.py +56 -0
- sage/tests/all__sagemath_categories.py +1 -0
- sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/cython.pyx +37 -0
- sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/stl_vector.pyx +171 -0
- sage/typeset/all.py +6 -0
- sage/typeset/ascii_art.py +295 -0
- sage/typeset/character_art.py +789 -0
- sage/typeset/character_art_factory.py +572 -0
- sage/typeset/symbols.py +334 -0
- sage/typeset/unicode_art.py +183 -0
- sage/typeset/unicode_characters.py +101 -0
|
@@ -0,0 +1,1818 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
"""
|
|
3
|
+
Nonnegative integer vectors
|
|
4
|
+
|
|
5
|
+
AUTHORS:
|
|
6
|
+
|
|
7
|
+
- Mike Hansen (2007): original module
|
|
8
|
+
- Nathann Cohen, David Joyner (2009-2010): Gale-Ryser stuff
|
|
9
|
+
- Nathann Cohen, David Joyner (2011): Gale-Ryser bugfix
|
|
10
|
+
- Travis Scrimshaw (2012-05-12): updated docstrings to tell the user of
|
|
11
|
+
that the class's name is a misnomer (that they only contains nonnegative
|
|
12
|
+
entries).
|
|
13
|
+
- Federico Poloni (2013): specialized ``rank()``
|
|
14
|
+
- Travis Scrimshaw (2013-02-04): refactored to use ``ClonableIntArray``
|
|
15
|
+
"""
|
|
16
|
+
# ****************************************************************************
|
|
17
|
+
# Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,
|
|
18
|
+
# Copyright (C) 2012 Travis Scrimshaw <tscrim@ucdavis.edu>
|
|
19
|
+
#
|
|
20
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
21
|
+
#
|
|
22
|
+
# This code is distributed in the hope that it will be useful,
|
|
23
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
24
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
25
|
+
# General Public License for more details.
|
|
26
|
+
#
|
|
27
|
+
# The full text of the GPL is available at:
|
|
28
|
+
#
|
|
29
|
+
# https://www.gnu.org/licenses/
|
|
30
|
+
# ****************************************************************************
|
|
31
|
+
|
|
32
|
+
from itertools import product
|
|
33
|
+
from collections.abc import Sequence
|
|
34
|
+
import numbers
|
|
35
|
+
|
|
36
|
+
from sage.structure.parent import Parent
|
|
37
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
38
|
+
from sage.structure.list_clone import ClonableArray
|
|
39
|
+
from sage.misc.classcall_metaclass import ClasscallMetaclass
|
|
40
|
+
|
|
41
|
+
from sage.categories.enumerated_sets import EnumeratedSets
|
|
42
|
+
from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
|
|
43
|
+
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
|
|
44
|
+
from sage.rings.infinity import PlusInfinity
|
|
45
|
+
from sage.arith.misc import binomial
|
|
46
|
+
from sage.rings.integer_ring import ZZ
|
|
47
|
+
from sage.rings.semirings.non_negative_integer_semiring import NN
|
|
48
|
+
from sage.rings.integer import Integer
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def is_gale_ryser(r, s):
|
|
52
|
+
r"""
|
|
53
|
+
Test whether the given sequences satisfy the condition
|
|
54
|
+
of the Gale-Ryser theorem.
|
|
55
|
+
|
|
56
|
+
Given a binary matrix `B` of dimension `n\times m`, the
|
|
57
|
+
vector of row sums is defined as the vector whose
|
|
58
|
+
`i^{\mbox{th}}` component is equal to the sum of the `i^{\mbox{th}}`
|
|
59
|
+
row in `A`. The vector of column sums is defined similarly.
|
|
60
|
+
|
|
61
|
+
If, given a binary matrix, these two vectors are easy to compute,
|
|
62
|
+
the Gale-Ryser theorem lets us decide whether, given two
|
|
63
|
+
nonnegative vectors `r,s`, there exists a binary matrix
|
|
64
|
+
whose row/column sums vectors are `r` and `s`.
|
|
65
|
+
|
|
66
|
+
This functions answers accordingly.
|
|
67
|
+
|
|
68
|
+
INPUT:
|
|
69
|
+
|
|
70
|
+
- ``r``, ``s`` -- lists of nonnegative integers
|
|
71
|
+
|
|
72
|
+
ALGORITHM:
|
|
73
|
+
|
|
74
|
+
Without loss of generality, we can assume that:
|
|
75
|
+
|
|
76
|
+
- The two given sequences do not contain any `0` ( which would
|
|
77
|
+
correspond to an empty column/row )
|
|
78
|
+
|
|
79
|
+
- The two given sequences are ordered in decreasing order
|
|
80
|
+
(reordering the sequence of row (resp. column) sums amounts to
|
|
81
|
+
reordering the rows (resp. columns) themselves in the matrix,
|
|
82
|
+
which does not alter the columns (resp. rows) sums.
|
|
83
|
+
|
|
84
|
+
We can then assume that `r` and `s` are partitions
|
|
85
|
+
(see the corresponding class :class:`Partition`)
|
|
86
|
+
|
|
87
|
+
If `r^*` denote the conjugate of `r`, the Gale-Ryser theorem
|
|
88
|
+
asserts that a binary Matrix satisfying the constraints exists
|
|
89
|
+
if and only if `s \preceq r^*`, where `\preceq` denotes
|
|
90
|
+
the domination order on partitions.
|
|
91
|
+
|
|
92
|
+
EXAMPLES::
|
|
93
|
+
|
|
94
|
+
sage: from sage.combinat.integer_vector import is_gale_ryser
|
|
95
|
+
sage: is_gale_ryser([4,2,2], [3,3,1,1]) # needs sage.combinat
|
|
96
|
+
True
|
|
97
|
+
sage: is_gale_ryser([4,2,1,1], [3,3,1,1]) # needs sage.combinat
|
|
98
|
+
True
|
|
99
|
+
sage: is_gale_ryser([3,2,1,1], [3,3,1,1]) # needs sage.combinat
|
|
100
|
+
False
|
|
101
|
+
|
|
102
|
+
REMARK: In the literature, what we are calling a
|
|
103
|
+
Gale-Ryser sequence sometimes goes by the (rather
|
|
104
|
+
generic-sounding) term ''realizable sequence''.
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
# The sequences only contain nonnegative integers
|
|
108
|
+
if [x for x in r if x < 0] or [x for x in s if x < 0]:
|
|
109
|
+
return False
|
|
110
|
+
|
|
111
|
+
# builds the corresponding partitions, i.e.
|
|
112
|
+
# removes the 0 and sorts the sequences
|
|
113
|
+
from sage.combinat.partition import Partition
|
|
114
|
+
r2 = Partition(sorted([x for x in r if x > 0], reverse=True))
|
|
115
|
+
s2 = Partition(sorted([x for x in s if x > 0], reverse=True))
|
|
116
|
+
|
|
117
|
+
# If the two sequences only contained zeroes
|
|
118
|
+
if len(r2) == 0 and len(s2) == 0:
|
|
119
|
+
return True
|
|
120
|
+
|
|
121
|
+
rstar = Partition(r2).conjugate()
|
|
122
|
+
|
|
123
|
+
# same number of 1s domination
|
|
124
|
+
return len(rstar) <= len(s2) and sum(r2) == sum(s2) and rstar.dominates(s)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def gale_ryser_theorem(p1, p2, algorithm='gale',
|
|
128
|
+
*, solver=None, integrality_tolerance=1e-3):
|
|
129
|
+
r"""
|
|
130
|
+
Return the binary matrix given by the Gale-Ryser theorem.
|
|
131
|
+
|
|
132
|
+
The Gale Ryser theorem asserts that if `p_1,p_2` are two
|
|
133
|
+
partitions of `n` of respective lengths `k_1,k_2`, then there is
|
|
134
|
+
a binary `k_1\times k_2` matrix `M` such that `p_1` is the vector
|
|
135
|
+
of row sums and `p_2` is the vector of column sums of `M`, if
|
|
136
|
+
and only if the conjugate of `p_2` dominates `p_1`.
|
|
137
|
+
|
|
138
|
+
INPUT:
|
|
139
|
+
|
|
140
|
+
- ``p1``, ``p2`` -- list of integers representing the vectors
|
|
141
|
+
of row/column sums
|
|
142
|
+
|
|
143
|
+
- ``algorithm`` -- two possible string values:
|
|
144
|
+
|
|
145
|
+
- ``'ryser'`` implements the construction due to Ryser [Ryser63]_.
|
|
146
|
+
- ``'gale'`` (default) implements the construction due to Gale [Gale57]_.
|
|
147
|
+
|
|
148
|
+
- ``solver`` -- (default: ``None``) specify a Mixed Integer Linear Programming
|
|
149
|
+
(MILP) solver to be used. If set to ``None``, the default one is used. For
|
|
150
|
+
more information on MILP solvers and which default solver is used, see
|
|
151
|
+
the method
|
|
152
|
+
:meth:`solve <sage.numerical.mip.MixedIntegerLinearProgram.solve>`
|
|
153
|
+
of the class
|
|
154
|
+
:class:`MixedIntegerLinearProgram <sage.numerical.mip.MixedIntegerLinearProgram>`.
|
|
155
|
+
|
|
156
|
+
- ``integrality_tolerance`` -- parameter for use with MILP solvers over an
|
|
157
|
+
inexact base ring; see :meth:`MixedIntegerLinearProgram.get_values`
|
|
158
|
+
|
|
159
|
+
OUTPUT: a binary matrix if it exists, ``None`` otherwise
|
|
160
|
+
|
|
161
|
+
Gale's Algorithm:
|
|
162
|
+
|
|
163
|
+
(Gale [Gale57]_): A matrix satisfying the constraints of its
|
|
164
|
+
sums can be defined as the solution of the following
|
|
165
|
+
Linear Program, which Sage knows how to solve.
|
|
166
|
+
|
|
167
|
+
.. MATH::
|
|
168
|
+
|
|
169
|
+
\forall i&\sum_{j=1}^{k_2} b_{i,j}=p_{1,j}\\
|
|
170
|
+
\forall i&\sum_{j=1}^{k_1} b_{j,i}=p_{2,j}\\
|
|
171
|
+
&b_{i,j}\mbox{ is a binary variable}
|
|
172
|
+
|
|
173
|
+
Ryser's Algorithm:
|
|
174
|
+
|
|
175
|
+
(Ryser [Ryser63]_): The construction of an `m \times n` matrix
|
|
176
|
+
`A=A_{r,s}`, due to Ryser, is described as follows. The
|
|
177
|
+
construction works if and only if have `s\preceq r^*`.
|
|
178
|
+
|
|
179
|
+
* Construct the `m \times n` matrix `B` from `r` by defining
|
|
180
|
+
the `i`-th row of `B` to be the vector whose first `r_i`
|
|
181
|
+
entries are `1`, and the remainder are 0s, `1 \leq i \leq m`.
|
|
182
|
+
This maximal matrix `B` with row sum `r` and ones left
|
|
183
|
+
justified has column sum `r^{*}`.
|
|
184
|
+
|
|
185
|
+
* Shift the last `1` in certain rows of `B` to column `n` in
|
|
186
|
+
order to achieve the sum `s_n`. Call this `B` again.
|
|
187
|
+
|
|
188
|
+
* The `1`'s in column `n` are to appear in those
|
|
189
|
+
rows in which `A` has the largest row sums, giving
|
|
190
|
+
preference to the bottom-most positions in case of ties.
|
|
191
|
+
* Note: When this step automatically "fixes" other columns,
|
|
192
|
+
one must skip ahead to the first column index
|
|
193
|
+
with a wrong sum in the step below.
|
|
194
|
+
|
|
195
|
+
* Proceed inductively to construct columns `n-1`, ..., `2`, `1`.
|
|
196
|
+
Note: when performing the induction on step `k`, we consider
|
|
197
|
+
the row sums of the first `k` columns.
|
|
198
|
+
|
|
199
|
+
* Set `A = B`. Return `A`.
|
|
200
|
+
|
|
201
|
+
EXAMPLES:
|
|
202
|
+
|
|
203
|
+
Computing the matrix for `p_1=p_2=2+2+1`::
|
|
204
|
+
|
|
205
|
+
sage: # needs sage.combinat sage.modules sage.numerical.mip
|
|
206
|
+
sage: from sage.combinat.integer_vector import gale_ryser_theorem
|
|
207
|
+
sage: p1 = [2,2,1]
|
|
208
|
+
sage: p2 = [2,2,1]
|
|
209
|
+
sage: print(gale_ryser_theorem(p1, p2)) # not tested
|
|
210
|
+
[1 1 0]
|
|
211
|
+
[1 0 1]
|
|
212
|
+
[0 1 0]
|
|
213
|
+
sage: A = gale_ryser_theorem(p1, p2)
|
|
214
|
+
sage: rs = [sum(x) for x in A.rows()]
|
|
215
|
+
sage: cs = [sum(x) for x in A.columns()]
|
|
216
|
+
sage: p1 == rs; p2 == cs
|
|
217
|
+
True
|
|
218
|
+
True
|
|
219
|
+
|
|
220
|
+
Or for a non-square matrix with `p_1=3+3+2+1` and `p_2=3+2+2+1+1`,
|
|
221
|
+
using Ryser's algorithm::
|
|
222
|
+
|
|
223
|
+
sage: # needs sage.combinat sage.modules
|
|
224
|
+
sage: from sage.combinat.integer_vector import gale_ryser_theorem
|
|
225
|
+
sage: p1 = [3,3,1,1]
|
|
226
|
+
sage: p2 = [3,3,1,1]
|
|
227
|
+
sage: gale_ryser_theorem(p1, p2, algorithm='ryser')
|
|
228
|
+
[1 1 1 0]
|
|
229
|
+
[1 1 0 1]
|
|
230
|
+
[1 0 0 0]
|
|
231
|
+
[0 1 0 0]
|
|
232
|
+
sage: p1 = [4,2,2]
|
|
233
|
+
sage: p2 = [3,3,1,1]
|
|
234
|
+
sage: gale_ryser_theorem(p1, p2, algorithm='ryser')
|
|
235
|
+
[1 1 1 1]
|
|
236
|
+
[1 1 0 0]
|
|
237
|
+
[1 1 0 0]
|
|
238
|
+
sage: p1 = [4,2,2,0]
|
|
239
|
+
sage: p2 = [3,3,1,1,0,0]
|
|
240
|
+
sage: gale_ryser_theorem(p1, p2, algorithm='ryser')
|
|
241
|
+
[1 1 1 1 0 0]
|
|
242
|
+
[1 1 0 0 0 0]
|
|
243
|
+
[1 1 0 0 0 0]
|
|
244
|
+
[0 0 0 0 0 0]
|
|
245
|
+
sage: p1 = [3,3,2,1]
|
|
246
|
+
sage: p2 = [3,2,2,1,1]
|
|
247
|
+
sage: print(gale_ryser_theorem(p1, p2, algorithm='gale')) # not tested
|
|
248
|
+
[1 1 1 0 0]
|
|
249
|
+
[1 1 0 0 1]
|
|
250
|
+
[1 0 1 0 0]
|
|
251
|
+
[0 0 0 1 0]
|
|
252
|
+
|
|
253
|
+
With `0` in the sequences, and with unordered inputs::
|
|
254
|
+
|
|
255
|
+
sage: from sage.combinat.integer_vector import gale_ryser_theorem
|
|
256
|
+
sage: gale_ryser_theorem([3,3,0,1,1,0], [3,1,3,1,0], algorithm='ryser') # needs sage.combinat sage.modules
|
|
257
|
+
[1 1 1 0 0]
|
|
258
|
+
[1 0 1 1 0]
|
|
259
|
+
[0 0 0 0 0]
|
|
260
|
+
[1 0 0 0 0]
|
|
261
|
+
[0 0 1 0 0]
|
|
262
|
+
[0 0 0 0 0]
|
|
263
|
+
sage: p1 = [3,1,1,1,1]; p2 = [3,2,2,0]
|
|
264
|
+
sage: gale_ryser_theorem(p1, p2, algorithm='ryser') # needs sage.combinat sage.modules
|
|
265
|
+
[1 1 1 0]
|
|
266
|
+
[1 0 0 0]
|
|
267
|
+
[1 0 0 0]
|
|
268
|
+
[0 1 0 0]
|
|
269
|
+
[0 0 1 0]
|
|
270
|
+
|
|
271
|
+
TESTS:
|
|
272
|
+
|
|
273
|
+
This test created a random bipartite graph on `n+m` vertices. Its
|
|
274
|
+
adjacency matrix is binary, and it is used to create some
|
|
275
|
+
"random-looking" sequences which correspond to an existing matrix. The
|
|
276
|
+
``gale_ryser_theorem`` is then called on these sequences, and the output
|
|
277
|
+
checked for correction.::
|
|
278
|
+
|
|
279
|
+
sage: def test_algorithm(algorithm, low=10, high=50):
|
|
280
|
+
....: n,m = randint(low,high), randint(low,high)
|
|
281
|
+
....: g = graphs.RandomBipartite(n, m, .3)
|
|
282
|
+
....: s1 = sorted(g.degree([(0,i) for i in range(n)]), reverse = True)
|
|
283
|
+
....: s2 = sorted(g.degree([(1,i) for i in range(m)]), reverse = True)
|
|
284
|
+
....: m = gale_ryser_theorem(s1, s2, algorithm = algorithm)
|
|
285
|
+
....: ss1 = sorted(map(lambda x : sum(x) , m.rows()), reverse = True)
|
|
286
|
+
....: ss2 = sorted(map(lambda x : sum(x) , m.columns()), reverse = True)
|
|
287
|
+
....: if ((ss1 != s1) or (ss2 != s2)):
|
|
288
|
+
....: print("Algorithm %s failed with this input:" % algorithm)
|
|
289
|
+
....: print(s1, s2)
|
|
290
|
+
|
|
291
|
+
sage: for algorithm in ["gale", "ryser"]: # long time # needs sage.combinat sage.modules
|
|
292
|
+
....: for i in range(50):
|
|
293
|
+
....: test_algorithm(algorithm, 3, 10)
|
|
294
|
+
|
|
295
|
+
Null matrix::
|
|
296
|
+
|
|
297
|
+
sage: gale_ryser_theorem([0,0,0],[0,0,0,0], algorithm='gale') # needs sage.combinat sage.modules
|
|
298
|
+
[0 0 0 0]
|
|
299
|
+
[0 0 0 0]
|
|
300
|
+
[0 0 0 0]
|
|
301
|
+
sage: gale_ryser_theorem([0,0,0],[0,0,0,0], algorithm='ryser') # needs sage.combinat sage.modules
|
|
302
|
+
[0 0 0 0]
|
|
303
|
+
[0 0 0 0]
|
|
304
|
+
[0 0 0 0]
|
|
305
|
+
|
|
306
|
+
REFERENCES:
|
|
307
|
+
|
|
308
|
+
.. [Ryser63] \H. J. Ryser, Combinatorial Mathematics,
|
|
309
|
+
Carus Monographs, MAA, 1963.
|
|
310
|
+
.. [Gale57] \D. Gale, A theorem on flows in networks, Pacific J. Math.
|
|
311
|
+
7(1957)1073-1082.
|
|
312
|
+
"""
|
|
313
|
+
from sage.matrix.constructor import matrix
|
|
314
|
+
|
|
315
|
+
if not is_gale_ryser(p1, p2):
|
|
316
|
+
return False
|
|
317
|
+
|
|
318
|
+
if algorithm == "ryser": # ryser's algorithm
|
|
319
|
+
from sage.combinat.permutation import Permutation
|
|
320
|
+
|
|
321
|
+
# Sorts the sequences if they are not, and remembers the permutation
|
|
322
|
+
# applied
|
|
323
|
+
tmp = sorted(enumerate(p1), reverse=True, key=lambda x: x[1])
|
|
324
|
+
r = [x[1] for x in tmp]
|
|
325
|
+
r_permutation = [x-1 for x in Permutation([x[0]+1 for x in tmp]).inverse()]
|
|
326
|
+
m = len(r)
|
|
327
|
+
|
|
328
|
+
tmp = sorted(enumerate(p2), reverse=True, key=lambda x: x[1])
|
|
329
|
+
s = [x[1] for x in tmp]
|
|
330
|
+
s_permutation = [x-1 for x in Permutation([x[0]+1 for x in tmp]).inverse()]
|
|
331
|
+
|
|
332
|
+
# This is the partition equivalent to the sliding algorithm
|
|
333
|
+
cols = []
|
|
334
|
+
for t in reversed(s):
|
|
335
|
+
c = [0] * m
|
|
336
|
+
i = 0
|
|
337
|
+
while t:
|
|
338
|
+
k = i + 1
|
|
339
|
+
while k < m and r[i] == r[k]:
|
|
340
|
+
k += 1
|
|
341
|
+
if t >= k - i: # == number rows of the same length
|
|
342
|
+
for j in range(i, k):
|
|
343
|
+
r[j] -= 1
|
|
344
|
+
c[j] = 1
|
|
345
|
+
t -= k - i
|
|
346
|
+
else: # Remove the t last rows of that length
|
|
347
|
+
for j in range(k-t, k):
|
|
348
|
+
r[j] -= 1
|
|
349
|
+
c[j] = 1
|
|
350
|
+
t = 0
|
|
351
|
+
i = k
|
|
352
|
+
cols.append(c)
|
|
353
|
+
|
|
354
|
+
# We added columns to the back instead of the front
|
|
355
|
+
A0 = matrix(list(reversed(cols))).transpose()
|
|
356
|
+
|
|
357
|
+
# Applying the permutations to get a matrix satisfying the
|
|
358
|
+
# order given by the input
|
|
359
|
+
A0 = A0.matrix_from_rows_and_columns(r_permutation, s_permutation)
|
|
360
|
+
return A0
|
|
361
|
+
|
|
362
|
+
elif algorithm == "gale":
|
|
363
|
+
from sage.numerical.mip import MixedIntegerLinearProgram
|
|
364
|
+
k1, k2 = len(p1), len(p2)
|
|
365
|
+
p = MixedIntegerLinearProgram(solver=solver)
|
|
366
|
+
b = p.new_variable(binary=True)
|
|
367
|
+
for (i, c) in enumerate(p1):
|
|
368
|
+
p.add_constraint(p.sum([b[i, j] for j in range(k2)]) == c)
|
|
369
|
+
for (i, c) in enumerate(p2):
|
|
370
|
+
p.add_constraint(p.sum([b[j, i] for j in range(k1)]) == c)
|
|
371
|
+
p.set_objective(None)
|
|
372
|
+
p.solve()
|
|
373
|
+
b = p.get_values(b, convert=ZZ, tolerance=integrality_tolerance)
|
|
374
|
+
M = [[0]*k2 for i in range(k1)]
|
|
375
|
+
for i in range(k1):
|
|
376
|
+
for j in range(k2):
|
|
377
|
+
M[i][j] = b[i, j]
|
|
378
|
+
return matrix(M)
|
|
379
|
+
|
|
380
|
+
else:
|
|
381
|
+
raise ValueError('the only two algorithms available are "gale" and "ryser"')
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
def _default_function(l, default, i):
|
|
385
|
+
"""
|
|
386
|
+
EXAMPLES::
|
|
387
|
+
|
|
388
|
+
sage: from sage.combinat.integer_vector import _default_function
|
|
389
|
+
sage: import functools
|
|
390
|
+
sage: f = functools.partial(_default_function, [1,2,3], 99)
|
|
391
|
+
sage: f(-1)
|
|
392
|
+
99
|
|
393
|
+
sage: f(0)
|
|
394
|
+
1
|
|
395
|
+
sage: f(1)
|
|
396
|
+
2
|
|
397
|
+
sage: f(2)
|
|
398
|
+
3
|
|
399
|
+
sage: f(3)
|
|
400
|
+
99
|
|
401
|
+
"""
|
|
402
|
+
try:
|
|
403
|
+
if i < 0:
|
|
404
|
+
return default
|
|
405
|
+
return l[i]
|
|
406
|
+
except IndexError:
|
|
407
|
+
return default
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
def list2func(l, default=None):
|
|
411
|
+
"""
|
|
412
|
+
Given a list ``l``, return a function that takes in a value ``i`` and
|
|
413
|
+
return ``l[i]``. If default is not ``None``, then the function will
|
|
414
|
+
return the default value for out of range ``i``'s.
|
|
415
|
+
|
|
416
|
+
EXAMPLES::
|
|
417
|
+
|
|
418
|
+
sage: f = sage.combinat.integer_vector.list2func([1,2,3])
|
|
419
|
+
sage: f(0)
|
|
420
|
+
1
|
|
421
|
+
sage: f(1)
|
|
422
|
+
2
|
|
423
|
+
sage: f(2)
|
|
424
|
+
3
|
|
425
|
+
sage: f(3)
|
|
426
|
+
Traceback (most recent call last):
|
|
427
|
+
...
|
|
428
|
+
IndexError: list index out of range
|
|
429
|
+
|
|
430
|
+
::
|
|
431
|
+
|
|
432
|
+
sage: f = sage.combinat.integer_vector.list2func([1,2,3], 0)
|
|
433
|
+
sage: f(2)
|
|
434
|
+
3
|
|
435
|
+
sage: f(3)
|
|
436
|
+
0
|
|
437
|
+
"""
|
|
438
|
+
if default is None:
|
|
439
|
+
return lambda i: l[i]
|
|
440
|
+
else:
|
|
441
|
+
from functools import partial
|
|
442
|
+
return partial(_default_function, l, default)
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
class IntegerVector(ClonableArray):
|
|
446
|
+
"""
|
|
447
|
+
An integer vector.
|
|
448
|
+
"""
|
|
449
|
+
|
|
450
|
+
def check(self):
|
|
451
|
+
"""
|
|
452
|
+
Check to make sure this is a valid integer vector by making sure
|
|
453
|
+
all entries are nonnegative.
|
|
454
|
+
|
|
455
|
+
EXAMPLES::
|
|
456
|
+
|
|
457
|
+
sage: IV = IntegerVectors()
|
|
458
|
+
sage: elt = IV([1,2,1])
|
|
459
|
+
sage: elt.check()
|
|
460
|
+
|
|
461
|
+
Check :issue:`34510`::
|
|
462
|
+
|
|
463
|
+
sage: IV3 = IntegerVectors(n=3)
|
|
464
|
+
sage: IV3([2,2])
|
|
465
|
+
Traceback (most recent call last):
|
|
466
|
+
...
|
|
467
|
+
ValueError: [2, 2] doesn't satisfy correct constraints
|
|
468
|
+
sage: IVk3 = IntegerVectors(k=3)
|
|
469
|
+
sage: IVk3([2,2])
|
|
470
|
+
Traceback (most recent call last):
|
|
471
|
+
...
|
|
472
|
+
ValueError: [2, 2] doesn't satisfy correct constraints
|
|
473
|
+
sage: IV33 = IntegerVectors(n=3, k=3)
|
|
474
|
+
sage: IV33([2,2])
|
|
475
|
+
Traceback (most recent call last):
|
|
476
|
+
...
|
|
477
|
+
ValueError: [2, 2] doesn't satisfy correct constraints
|
|
478
|
+
"""
|
|
479
|
+
if any(x < 0 for x in self):
|
|
480
|
+
raise ValueError("all entries must be nonnegative")
|
|
481
|
+
if self not in self.parent():
|
|
482
|
+
raise ValueError(f"{self} doesn't satisfy correct constraints")
|
|
483
|
+
|
|
484
|
+
def trim(self):
|
|
485
|
+
"""
|
|
486
|
+
Remove trailing zeros from the integer vector.
|
|
487
|
+
|
|
488
|
+
EXAMPLES::
|
|
489
|
+
|
|
490
|
+
sage: IV = IntegerVectors()
|
|
491
|
+
sage: IV([5,3,5,1,0,0]).trim()
|
|
492
|
+
[5, 3, 5, 1]
|
|
493
|
+
sage: IV([5,0,5,1,0]).trim()
|
|
494
|
+
[5, 0, 5, 1]
|
|
495
|
+
sage: IV([4,3,3]).trim()
|
|
496
|
+
[4, 3, 3]
|
|
497
|
+
sage: IV([0,0,0]).trim()
|
|
498
|
+
[]
|
|
499
|
+
|
|
500
|
+
sage: IV = IntegerVectors(k=4)
|
|
501
|
+
sage: v = IV([4,3,2,0]).trim(); v
|
|
502
|
+
[4, 3, 2]
|
|
503
|
+
sage: v.parent()
|
|
504
|
+
Integer vectors
|
|
505
|
+
"""
|
|
506
|
+
P = IntegerVectors()
|
|
507
|
+
v = list(self)
|
|
508
|
+
if all(i == 0 for i in v):
|
|
509
|
+
return P.element_class(P, [], check=False)
|
|
510
|
+
while not v[-1]:
|
|
511
|
+
v = v[:-1]
|
|
512
|
+
return P.element_class(P, v, check=False)
|
|
513
|
+
|
|
514
|
+
def specht_module(self, base_ring=None):
|
|
515
|
+
r"""
|
|
516
|
+
Return the Specht module corresponding to ``self``.
|
|
517
|
+
|
|
518
|
+
EXAMPLES::
|
|
519
|
+
|
|
520
|
+
sage: SM = IntegerVectors()([2,0,1,0,2]).specht_module(QQ); SM # needs sage.combinat sage.modules
|
|
521
|
+
Specht module of [(0, 0), (0, 1), (2, 0), (4, 0), (4, 1)] over Rational Field
|
|
522
|
+
sage: s = SymmetricFunctions(QQ).s() # needs sage.combinat sage.modules
|
|
523
|
+
sage: s(SM.frobenius_image()) # needs sage.combinat sage.modules
|
|
524
|
+
s[2, 2, 1]
|
|
525
|
+
"""
|
|
526
|
+
from sage.combinat.specht_module import SpechtModule
|
|
527
|
+
from sage.combinat.symmetric_group_algebra import SymmetricGroupAlgebra
|
|
528
|
+
if base_ring is None:
|
|
529
|
+
from sage.rings.rational_field import QQ
|
|
530
|
+
base_ring = QQ
|
|
531
|
+
R = SymmetricGroupAlgebra(base_ring, sum(self))
|
|
532
|
+
return SpechtModule(R, self)
|
|
533
|
+
|
|
534
|
+
def specht_module_dimension(self, base_ring=None):
|
|
535
|
+
r"""
|
|
536
|
+
Return the dimension of the Specht module corresponding to ``self``.
|
|
537
|
+
|
|
538
|
+
INPUT:
|
|
539
|
+
|
|
540
|
+
- ``BR`` -- (default: `\QQ`) the base ring
|
|
541
|
+
|
|
542
|
+
EXAMPLES::
|
|
543
|
+
|
|
544
|
+
sage: IntegerVectors()([2,0,1,0,2]).specht_module_dimension() # needs sage.combinat sage.modules
|
|
545
|
+
5
|
|
546
|
+
sage: IntegerVectors()([2,0,1,0,2]).specht_module_dimension(GF(2)) # needs sage.combinat sage.modules sage.rings.finite_rings
|
|
547
|
+
5
|
|
548
|
+
"""
|
|
549
|
+
from sage.combinat.specht_module import specht_module_rank
|
|
550
|
+
return specht_module_rank(self, base_ring)
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
class IntegerVectors(Parent, metaclass=ClasscallMetaclass):
|
|
554
|
+
"""
|
|
555
|
+
The class of (nonnegative) integer vectors.
|
|
556
|
+
|
|
557
|
+
INPUT:
|
|
558
|
+
|
|
559
|
+
- ``n`` -- if set to an integer, returns the combinatorial class
|
|
560
|
+
of integer vectors whose sum is ``n``; if set to ``None``
|
|
561
|
+
(default), no such constraint is defined
|
|
562
|
+
|
|
563
|
+
- ``k`` -- the length of the vectors; set to ``None`` (default) if
|
|
564
|
+
you do not want such a constraint
|
|
565
|
+
|
|
566
|
+
.. NOTE::
|
|
567
|
+
|
|
568
|
+
The entries are nonnegative integers.
|
|
569
|
+
|
|
570
|
+
EXAMPLES:
|
|
571
|
+
|
|
572
|
+
If ``n`` is not specified, it returns the class of all integer vectors::
|
|
573
|
+
|
|
574
|
+
sage: IntegerVectors()
|
|
575
|
+
Integer vectors
|
|
576
|
+
sage: [] in IntegerVectors()
|
|
577
|
+
True
|
|
578
|
+
sage: [1,2,1] in IntegerVectors()
|
|
579
|
+
True
|
|
580
|
+
sage: [1, 0, 0] in IntegerVectors()
|
|
581
|
+
True
|
|
582
|
+
|
|
583
|
+
Entries are nonnegative::
|
|
584
|
+
|
|
585
|
+
sage: [-1, 2] in IntegerVectors()
|
|
586
|
+
False
|
|
587
|
+
|
|
588
|
+
If ``n`` is specified, then it returns the class of all integer vectors
|
|
589
|
+
which sum to ``n``::
|
|
590
|
+
|
|
591
|
+
sage: IV3 = IntegerVectors(3); IV3
|
|
592
|
+
Integer vectors that sum to 3
|
|
593
|
+
|
|
594
|
+
Note that trailing zeros are ignored so that ``[3, 0]`` does not show
|
|
595
|
+
up in the following list (since ``[3]`` does)::
|
|
596
|
+
|
|
597
|
+
sage: IntegerVectors(3, max_length=2).list()
|
|
598
|
+
[[3], [2, 1], [1, 2], [0, 3]]
|
|
599
|
+
|
|
600
|
+
If ``n`` and ``k`` are both specified, then it returns the class
|
|
601
|
+
of integer vectors that sum to ``n`` and are of length ``k``::
|
|
602
|
+
|
|
603
|
+
sage: IV53 = IntegerVectors(5,3); IV53
|
|
604
|
+
Integer vectors of length 3 that sum to 5
|
|
605
|
+
sage: IV53.cardinality()
|
|
606
|
+
21
|
|
607
|
+
sage: IV53.first()
|
|
608
|
+
[5, 0, 0]
|
|
609
|
+
sage: IV53.last()
|
|
610
|
+
[0, 0, 5]
|
|
611
|
+
sage: IV53.random_element().parent() is IV53
|
|
612
|
+
True
|
|
613
|
+
|
|
614
|
+
Further examples::
|
|
615
|
+
|
|
616
|
+
sage: IntegerVectors(-1, 0, min_part=1).list()
|
|
617
|
+
[]
|
|
618
|
+
sage: IntegerVectors(-1, 2, min_part=1).list()
|
|
619
|
+
[]
|
|
620
|
+
sage: IntegerVectors(0, 0, min_part=1).list()
|
|
621
|
+
[[]]
|
|
622
|
+
sage: IntegerVectors(3, 0, min_part=1).list()
|
|
623
|
+
[]
|
|
624
|
+
sage: IntegerVectors(0, 1, min_part=1).list()
|
|
625
|
+
[]
|
|
626
|
+
sage: IntegerVectors(2, 2, min_part=1).list()
|
|
627
|
+
[[1, 1]]
|
|
628
|
+
sage: IntegerVectors(2, 3, min_part=1).list()
|
|
629
|
+
[]
|
|
630
|
+
sage: IntegerVectors(4, 2, min_part=1).list()
|
|
631
|
+
[[3, 1], [2, 2], [1, 3]]
|
|
632
|
+
|
|
633
|
+
::
|
|
634
|
+
|
|
635
|
+
sage: IntegerVectors(0, 3, outer=[0,0,0]).list()
|
|
636
|
+
[[0, 0, 0]]
|
|
637
|
+
sage: IntegerVectors(1, 3, outer=[0,0,0]).list()
|
|
638
|
+
[]
|
|
639
|
+
sage: IntegerVectors(2, 3, outer=[0,2,0]).list()
|
|
640
|
+
[[0, 2, 0]]
|
|
641
|
+
sage: IntegerVectors(2, 3, outer=[1,2,1]).list()
|
|
642
|
+
[[1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1]]
|
|
643
|
+
sage: IntegerVectors(2, 3, outer=[1,1,1]).list()
|
|
644
|
+
[[1, 1, 0], [1, 0, 1], [0, 1, 1]]
|
|
645
|
+
sage: IntegerVectors(2, 5, outer=[1,1,1,1,1]).list()
|
|
646
|
+
[[1, 1, 0, 0, 0],
|
|
647
|
+
[1, 0, 1, 0, 0],
|
|
648
|
+
[1, 0, 0, 1, 0],
|
|
649
|
+
[1, 0, 0, 0, 1],
|
|
650
|
+
[0, 1, 1, 0, 0],
|
|
651
|
+
[0, 1, 0, 1, 0],
|
|
652
|
+
[0, 1, 0, 0, 1],
|
|
653
|
+
[0, 0, 1, 1, 0],
|
|
654
|
+
[0, 0, 1, 0, 1],
|
|
655
|
+
[0, 0, 0, 1, 1]]
|
|
656
|
+
|
|
657
|
+
::
|
|
658
|
+
|
|
659
|
+
sage: iv = [ IntegerVectors(n,k) for n in range(-2, 7) for k in range(7) ]
|
|
660
|
+
sage: all(map(lambda x: x.cardinality() == len(x.list()), iv))
|
|
661
|
+
True
|
|
662
|
+
sage: essai = [[1,1,1], [2,5,6], [6,5,2]]
|
|
663
|
+
sage: iv = [ IntegerVectors(x[0], x[1], max_part = x[2]-1) for x in essai ]
|
|
664
|
+
sage: all(map(lambda x: x.cardinality() == len(x.list()), iv))
|
|
665
|
+
True
|
|
666
|
+
|
|
667
|
+
An example showing the same output by using IntegerListsLex::
|
|
668
|
+
|
|
669
|
+
sage: IntegerVectors(4, max_length=2).list()
|
|
670
|
+
[[4], [3, 1], [2, 2], [1, 3], [0, 4]]
|
|
671
|
+
sage: list(IntegerListsLex(4, max_length=2))
|
|
672
|
+
[[4], [3, 1], [2, 2], [1, 3], [0, 4]]
|
|
673
|
+
|
|
674
|
+
.. SEEALSO::
|
|
675
|
+
|
|
676
|
+
:class:`sage.combinat.integer_lists.invlex.IntegerListsLex`
|
|
677
|
+
"""
|
|
678
|
+
@staticmethod
|
|
679
|
+
def __classcall_private__(cls, n=None, k=None, **kwargs):
|
|
680
|
+
"""
|
|
681
|
+
Choose the correct parent based upon input.
|
|
682
|
+
|
|
683
|
+
EXAMPLES::
|
|
684
|
+
|
|
685
|
+
sage: IV1 = IntegerVectors(3, 2)
|
|
686
|
+
sage: IV2 = IntegerVectors(3, 2)
|
|
687
|
+
sage: IV1 is IV2
|
|
688
|
+
True
|
|
689
|
+
|
|
690
|
+
TESTS::
|
|
691
|
+
|
|
692
|
+
sage: IV2 = IntegerVectors(3, 2, length=2)
|
|
693
|
+
Traceback (most recent call last):
|
|
694
|
+
...
|
|
695
|
+
ValueError: k and length both specified
|
|
696
|
+
|
|
697
|
+
:issue:`29524`::
|
|
698
|
+
|
|
699
|
+
sage: IntegerVectors(3, 3/1)
|
|
700
|
+
Traceback (most recent call last):
|
|
701
|
+
...
|
|
702
|
+
TypeError: 'k' must be an integer or a tuple, got Rational
|
|
703
|
+
"""
|
|
704
|
+
if 'length' in kwargs:
|
|
705
|
+
if k is not None:
|
|
706
|
+
raise ValueError("k and length both specified")
|
|
707
|
+
k = kwargs.pop('length')
|
|
708
|
+
if kwargs:
|
|
709
|
+
return IntegerVectorsConstraints(n, k, **kwargs)
|
|
710
|
+
|
|
711
|
+
if k is None:
|
|
712
|
+
if n is None:
|
|
713
|
+
return IntegerVectors_all()
|
|
714
|
+
return IntegerVectors_n(n)
|
|
715
|
+
if n is None:
|
|
716
|
+
return IntegerVectors_k(k)
|
|
717
|
+
|
|
718
|
+
if isinstance(k, numbers.Integral):
|
|
719
|
+
return IntegerVectors_nk(n, k)
|
|
720
|
+
elif isinstance(k, (tuple, list)):
|
|
721
|
+
return IntegerVectors_nnondescents(n, tuple(k))
|
|
722
|
+
else:
|
|
723
|
+
raise TypeError("'k' must be an integer or a tuple, got {}".format(type(k).__name__))
|
|
724
|
+
|
|
725
|
+
def __init__(self, category=None):
|
|
726
|
+
"""
|
|
727
|
+
Initialize ``self``.
|
|
728
|
+
|
|
729
|
+
EXAMPLES::
|
|
730
|
+
|
|
731
|
+
sage: IV = IntegerVectors()
|
|
732
|
+
sage: TestSuite(IV).run()
|
|
733
|
+
"""
|
|
734
|
+
if category is None:
|
|
735
|
+
category = EnumeratedSets()
|
|
736
|
+
Parent.__init__(self, category=category)
|
|
737
|
+
|
|
738
|
+
def _element_constructor_(self, lst):
|
|
739
|
+
"""
|
|
740
|
+
Construct an element of ``self`` from ``lst``.
|
|
741
|
+
|
|
742
|
+
EXAMPLES::
|
|
743
|
+
|
|
744
|
+
sage: IV = IntegerVectors()
|
|
745
|
+
sage: elt = IV([3, 1, 0, 3, 2]); elt
|
|
746
|
+
[3, 1, 0, 3, 2]
|
|
747
|
+
sage: elt.parent()
|
|
748
|
+
Integer vectors
|
|
749
|
+
|
|
750
|
+
sage: IV9 = IntegerVectors(9)
|
|
751
|
+
sage: elt9 = IV9(elt)
|
|
752
|
+
sage: elt9.parent()
|
|
753
|
+
Integer vectors that sum to 9
|
|
754
|
+
"""
|
|
755
|
+
return self.element_class(self, lst)
|
|
756
|
+
|
|
757
|
+
Element = IntegerVector
|
|
758
|
+
|
|
759
|
+
def __contains__(self, x):
|
|
760
|
+
"""
|
|
761
|
+
EXAMPLES::
|
|
762
|
+
|
|
763
|
+
sage: [] in IntegerVectors()
|
|
764
|
+
True
|
|
765
|
+
sage: [3,2,2,1] in IntegerVectors()
|
|
766
|
+
True
|
|
767
|
+
"""
|
|
768
|
+
if isinstance(x, IntegerVector):
|
|
769
|
+
return True
|
|
770
|
+
|
|
771
|
+
if not isinstance(x, Sequence):
|
|
772
|
+
return False
|
|
773
|
+
|
|
774
|
+
for i in x:
|
|
775
|
+
if i not in ZZ:
|
|
776
|
+
return False
|
|
777
|
+
if i < 0:
|
|
778
|
+
return False
|
|
779
|
+
return True
|
|
780
|
+
|
|
781
|
+
def _unrank_helper(self, x, rtn):
|
|
782
|
+
"""
|
|
783
|
+
Return the element at rank ``x`` by iterating through all integer vectors beginning with ``rtn``.
|
|
784
|
+
|
|
785
|
+
INPUT:
|
|
786
|
+
|
|
787
|
+
- ``x`` -- nonnegative integer
|
|
788
|
+
- ``rtn`` -- list of nonnegative integers
|
|
789
|
+
|
|
790
|
+
EXAMPLES::
|
|
791
|
+
|
|
792
|
+
sage: IV = IntegerVectors(k=5)
|
|
793
|
+
sage: IV._unrank_helper(10, [2,0,0,0,0])
|
|
794
|
+
[1, 0, 0, 0, 1]
|
|
795
|
+
|
|
796
|
+
sage: IV = IntegerVectors(n=7)
|
|
797
|
+
sage: IV._unrank_helper(100, [7,0,0,0])
|
|
798
|
+
[2, 0, 0, 5]
|
|
799
|
+
|
|
800
|
+
sage: IV = IntegerVectors(n=12, k=7)
|
|
801
|
+
sage: IV._unrank_helper(1000, [12,0,0,0,0,0,0])
|
|
802
|
+
[5, 3, 1, 1, 1, 1, 0]
|
|
803
|
+
"""
|
|
804
|
+
ptr = 0
|
|
805
|
+
while True:
|
|
806
|
+
current_rank = self.rank(rtn)
|
|
807
|
+
if current_rank < x:
|
|
808
|
+
rtn[ptr+1] = rtn[ptr]
|
|
809
|
+
rtn[ptr] = 0
|
|
810
|
+
ptr += 1
|
|
811
|
+
elif current_rank > x:
|
|
812
|
+
rtn[ptr] -= 1
|
|
813
|
+
rtn[ptr-1] += 1
|
|
814
|
+
else:
|
|
815
|
+
return self._element_constructor_(rtn)
|
|
816
|
+
|
|
817
|
+
|
|
818
|
+
class IntegerVectors_all(UniqueRepresentation, IntegerVectors):
|
|
819
|
+
"""
|
|
820
|
+
Class of all integer vectors.
|
|
821
|
+
"""
|
|
822
|
+
|
|
823
|
+
def __init__(self):
|
|
824
|
+
"""
|
|
825
|
+
Initialize ``self``.
|
|
826
|
+
|
|
827
|
+
EXAMPLES::
|
|
828
|
+
|
|
829
|
+
sage: IV = IntegerVectors()
|
|
830
|
+
sage: TestSuite(IV).run()
|
|
831
|
+
"""
|
|
832
|
+
IntegerVectors.__init__(self, category=InfiniteEnumeratedSets())
|
|
833
|
+
|
|
834
|
+
def _repr_(self):
|
|
835
|
+
"""
|
|
836
|
+
EXAMPLES::
|
|
837
|
+
|
|
838
|
+
sage: IntegerVectors()
|
|
839
|
+
Integer vectors
|
|
840
|
+
"""
|
|
841
|
+
return "Integer vectors"
|
|
842
|
+
|
|
843
|
+
def __iter__(self):
|
|
844
|
+
"""
|
|
845
|
+
Iterate over ``self``.
|
|
846
|
+
|
|
847
|
+
EXAMPLES::
|
|
848
|
+
|
|
849
|
+
sage: IV = IntegerVectors()
|
|
850
|
+
sage: it = IV.__iter__()
|
|
851
|
+
sage: [next(it) for x in range(10)]
|
|
852
|
+
[[], [1], [2], [2, 0], [1, 1], [0, 2], [3], [3, 0], [2, 1], [1, 2]]
|
|
853
|
+
"""
|
|
854
|
+
yield self.element_class(self, [])
|
|
855
|
+
n = 1
|
|
856
|
+
while True:
|
|
857
|
+
for k in range(1, n + 1):
|
|
858
|
+
for v in integer_vectors_nk_fast_iter(n, k):
|
|
859
|
+
yield self.element_class(self, v, check=False)
|
|
860
|
+
n += 1
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
class IntegerVectors_n(UniqueRepresentation, IntegerVectors):
|
|
864
|
+
"""
|
|
865
|
+
Integer vectors that sum to `n`.
|
|
866
|
+
"""
|
|
867
|
+
|
|
868
|
+
def __init__(self, n):
|
|
869
|
+
"""
|
|
870
|
+
TESTS::
|
|
871
|
+
|
|
872
|
+
sage: IV = IntegerVectors(3)
|
|
873
|
+
sage: TestSuite(IV).run()
|
|
874
|
+
"""
|
|
875
|
+
self.n = n
|
|
876
|
+
if self.n == 0:
|
|
877
|
+
IntegerVectors.__init__(self, category=EnumeratedSets())
|
|
878
|
+
else:
|
|
879
|
+
IntegerVectors.__init__(self, category=InfiniteEnumeratedSets())
|
|
880
|
+
|
|
881
|
+
def _repr_(self):
|
|
882
|
+
"""
|
|
883
|
+
TESTS::
|
|
884
|
+
|
|
885
|
+
sage: IV = IntegerVectors(3)
|
|
886
|
+
sage: IV
|
|
887
|
+
Integer vectors that sum to 3
|
|
888
|
+
"""
|
|
889
|
+
return "Integer vectors that sum to {}".format(self.n)
|
|
890
|
+
|
|
891
|
+
def __iter__(self):
|
|
892
|
+
"""
|
|
893
|
+
Iterate over ``self``.
|
|
894
|
+
|
|
895
|
+
EXAMPLES::
|
|
896
|
+
|
|
897
|
+
sage: it = IntegerVectors(3).__iter__()
|
|
898
|
+
sage: [next(it) for x in range(10)]
|
|
899
|
+
[[3],
|
|
900
|
+
[3, 0],
|
|
901
|
+
[2, 1],
|
|
902
|
+
[1, 2],
|
|
903
|
+
[0, 3],
|
|
904
|
+
[3, 0, 0],
|
|
905
|
+
[2, 1, 0],
|
|
906
|
+
[2, 0, 1],
|
|
907
|
+
[1, 2, 0],
|
|
908
|
+
[1, 1, 1]]
|
|
909
|
+
"""
|
|
910
|
+
if not self.n:
|
|
911
|
+
yield self.element_class(self, [])
|
|
912
|
+
|
|
913
|
+
k = 1
|
|
914
|
+
while True:
|
|
915
|
+
for iv in integer_vectors_nk_fast_iter(self.n, k):
|
|
916
|
+
yield self.element_class(self, iv, check=False)
|
|
917
|
+
k += 1
|
|
918
|
+
|
|
919
|
+
def __contains__(self, x):
|
|
920
|
+
"""
|
|
921
|
+
EXAMPLES::
|
|
922
|
+
|
|
923
|
+
sage: [0] in IntegerVectors(0)
|
|
924
|
+
True
|
|
925
|
+
sage: [3] in IntegerVectors(3)
|
|
926
|
+
True
|
|
927
|
+
sage: [3] in IntegerVectors(2)
|
|
928
|
+
False
|
|
929
|
+
sage: [3,2,2,1] in IntegerVectors(9)
|
|
930
|
+
False
|
|
931
|
+
sage: [3,2,2,1] in IntegerVectors(8)
|
|
932
|
+
True
|
|
933
|
+
"""
|
|
934
|
+
if not IntegerVectors.__contains__(self, x):
|
|
935
|
+
return False
|
|
936
|
+
return sum(x) == self.n
|
|
937
|
+
|
|
938
|
+
def rank(self, x):
|
|
939
|
+
"""
|
|
940
|
+
Return the rank of a given element.
|
|
941
|
+
|
|
942
|
+
INPUT:
|
|
943
|
+
|
|
944
|
+
- ``x`` -- list with ``sum(x) == n``
|
|
945
|
+
|
|
946
|
+
EXAMPLES::
|
|
947
|
+
|
|
948
|
+
sage: IntegerVectors(n=5).rank([5,0])
|
|
949
|
+
1
|
|
950
|
+
sage: IntegerVectors(n=5).rank([3,2])
|
|
951
|
+
3
|
|
952
|
+
"""
|
|
953
|
+
if sum(x) != self.n:
|
|
954
|
+
raise ValueError("argument is not a member of IntegerVectors({},{})".format(self.n, None))
|
|
955
|
+
|
|
956
|
+
n, k, s = self.n, len(x), 0
|
|
957
|
+
r = binomial(k + n - 1, n + 1)
|
|
958
|
+
for i in range(k - 1):
|
|
959
|
+
s += x[k - 1 - i]
|
|
960
|
+
r += binomial(s + i, i + 1)
|
|
961
|
+
return r
|
|
962
|
+
|
|
963
|
+
def unrank(self, x):
|
|
964
|
+
"""
|
|
965
|
+
Return the element at given rank x.
|
|
966
|
+
|
|
967
|
+
INPUT:
|
|
968
|
+
|
|
969
|
+
- ``x`` -- integer
|
|
970
|
+
|
|
971
|
+
EXAMPLES::
|
|
972
|
+
|
|
973
|
+
sage: IntegerVectors(n=5).unrank(2)
|
|
974
|
+
[4, 1]
|
|
975
|
+
sage: IntegerVectors(n=10).unrank(10)
|
|
976
|
+
[1, 9]
|
|
977
|
+
"""
|
|
978
|
+
rtn = [self.n]
|
|
979
|
+
while self.rank(rtn) <= x:
|
|
980
|
+
rtn.append(0)
|
|
981
|
+
rtn.pop()
|
|
982
|
+
|
|
983
|
+
return IntegerVectors._unrank_helper(self, x, rtn)
|
|
984
|
+
|
|
985
|
+
def cardinality(self):
|
|
986
|
+
"""
|
|
987
|
+
Return the cardinality of ``self``.
|
|
988
|
+
|
|
989
|
+
EXAMPLES::
|
|
990
|
+
|
|
991
|
+
sage: IntegerVectors(n=0).cardinality()
|
|
992
|
+
1
|
|
993
|
+
sage: IntegerVectors(n=10).cardinality()
|
|
994
|
+
+Infinity
|
|
995
|
+
"""
|
|
996
|
+
if self.n == 0:
|
|
997
|
+
return Integer(1)
|
|
998
|
+
return PlusInfinity()
|
|
999
|
+
|
|
1000
|
+
|
|
1001
|
+
class IntegerVectors_k(UniqueRepresentation, IntegerVectors):
|
|
1002
|
+
"""
|
|
1003
|
+
Integer vectors of length `k`.
|
|
1004
|
+
"""
|
|
1005
|
+
|
|
1006
|
+
def __init__(self, k):
|
|
1007
|
+
"""
|
|
1008
|
+
TESTS::
|
|
1009
|
+
|
|
1010
|
+
sage: IV = IntegerVectors(k=2)
|
|
1011
|
+
sage: TestSuite(IV).run()
|
|
1012
|
+
"""
|
|
1013
|
+
self.k = k
|
|
1014
|
+
if self.k == 0:
|
|
1015
|
+
IntegerVectors.__init__(self, category=EnumeratedSets())
|
|
1016
|
+
else:
|
|
1017
|
+
IntegerVectors.__init__(self, category=InfiniteEnumeratedSets())
|
|
1018
|
+
|
|
1019
|
+
def _repr_(self):
|
|
1020
|
+
"""
|
|
1021
|
+
TESTS::
|
|
1022
|
+
|
|
1023
|
+
sage: IV = IntegerVectors(k=2)
|
|
1024
|
+
sage: IV
|
|
1025
|
+
Integer vectors of length 2
|
|
1026
|
+
"""
|
|
1027
|
+
return "Integer vectors of length {}".format(self.k)
|
|
1028
|
+
|
|
1029
|
+
def __iter__(self):
|
|
1030
|
+
"""
|
|
1031
|
+
Iterate over ``self``.
|
|
1032
|
+
|
|
1033
|
+
EXAMPLES::
|
|
1034
|
+
|
|
1035
|
+
sage: it = IntegerVectors(k=2).__iter__()
|
|
1036
|
+
sage: [next(it) for x in range(10)]
|
|
1037
|
+
[[0, 0],
|
|
1038
|
+
[1, 0],
|
|
1039
|
+
[0, 1],
|
|
1040
|
+
[2, 0],
|
|
1041
|
+
[1, 1],
|
|
1042
|
+
[0, 2],
|
|
1043
|
+
[3, 0],
|
|
1044
|
+
[2, 1],
|
|
1045
|
+
[1, 2],
|
|
1046
|
+
[0, 3]]
|
|
1047
|
+
|
|
1048
|
+
TESTS:
|
|
1049
|
+
|
|
1050
|
+
Check corner case::
|
|
1051
|
+
|
|
1052
|
+
sage: IV = IntegerVectors(k=0)
|
|
1053
|
+
sage: list(IV)
|
|
1054
|
+
[[]]
|
|
1055
|
+
"""
|
|
1056
|
+
n = 0
|
|
1057
|
+
if self.k == 0: # special case
|
|
1058
|
+
yield self.element_class(self, [], check=False)
|
|
1059
|
+
return
|
|
1060
|
+
while True:
|
|
1061
|
+
for iv in integer_vectors_nk_fast_iter(n, self.k):
|
|
1062
|
+
yield self.element_class(self, iv, check=False)
|
|
1063
|
+
n += 1
|
|
1064
|
+
|
|
1065
|
+
def __contains__(self, x):
|
|
1066
|
+
"""
|
|
1067
|
+
EXAMPLES::
|
|
1068
|
+
|
|
1069
|
+
sage: [] in IntegerVectors(k=0)
|
|
1070
|
+
True
|
|
1071
|
+
sage: [3] in IntegerVectors(k=1)
|
|
1072
|
+
True
|
|
1073
|
+
sage: [3] in IntegerVectors(k=2)
|
|
1074
|
+
False
|
|
1075
|
+
sage: [3,2,2,1] in IntegerVectors(k=3)
|
|
1076
|
+
False
|
|
1077
|
+
sage: [3,2,2,1] in IntegerVectors(k=4)
|
|
1078
|
+
True
|
|
1079
|
+
"""
|
|
1080
|
+
if not IntegerVectors.__contains__(self, x):
|
|
1081
|
+
return False
|
|
1082
|
+
return len(x) == self.k
|
|
1083
|
+
|
|
1084
|
+
def rank(self, x):
|
|
1085
|
+
"""
|
|
1086
|
+
Return the rank of a given element.
|
|
1087
|
+
|
|
1088
|
+
INPUT:
|
|
1089
|
+
|
|
1090
|
+
- ``x`` -- list with ``len(x) == k``
|
|
1091
|
+
|
|
1092
|
+
EXAMPLES::
|
|
1093
|
+
|
|
1094
|
+
sage: IntegerVectors(k=5).rank([0,0,0,0,0])
|
|
1095
|
+
0
|
|
1096
|
+
sage: IntegerVectors(k=5).rank([1,1,0,0,0])
|
|
1097
|
+
7
|
|
1098
|
+
"""
|
|
1099
|
+
if len(x) != self.k:
|
|
1100
|
+
raise ValueError("argument is not a member of IntegerVectors({},{})".format(None, self.k))
|
|
1101
|
+
|
|
1102
|
+
n, k, s = sum(x), self.k, 0
|
|
1103
|
+
r = binomial(n + k - 1, k)
|
|
1104
|
+
for i in range(k - 1):
|
|
1105
|
+
s += x[k - 1 - i]
|
|
1106
|
+
r += binomial(s + i, i + 1)
|
|
1107
|
+
return r
|
|
1108
|
+
|
|
1109
|
+
def unrank(self, x):
|
|
1110
|
+
"""
|
|
1111
|
+
Return the element at given rank x.
|
|
1112
|
+
|
|
1113
|
+
INPUT:
|
|
1114
|
+
|
|
1115
|
+
- ``x`` -- integer such that ``x < self.cardinality()``
|
|
1116
|
+
|
|
1117
|
+
EXAMPLES::
|
|
1118
|
+
|
|
1119
|
+
sage: IntegerVectors(k=5).unrank(10)
|
|
1120
|
+
[1, 0, 0, 0, 1]
|
|
1121
|
+
sage: IntegerVectors(k=5).unrank(15)
|
|
1122
|
+
[0, 0, 2, 0, 0]
|
|
1123
|
+
sage: IntegerVectors(k=0).unrank(0)
|
|
1124
|
+
[]
|
|
1125
|
+
"""
|
|
1126
|
+
if self.k == 0 and x != 0:
|
|
1127
|
+
raise IndexError(f"Index {x} is out of range for the IntegerVector.")
|
|
1128
|
+
rtn = [0]*self.k
|
|
1129
|
+
if self.k == 0 and x == 0:
|
|
1130
|
+
return rtn
|
|
1131
|
+
|
|
1132
|
+
while self.rank(rtn) <= x:
|
|
1133
|
+
rtn[0] += 1
|
|
1134
|
+
rtn[0] -= 1
|
|
1135
|
+
|
|
1136
|
+
return IntegerVectors._unrank_helper(self, x, rtn)
|
|
1137
|
+
|
|
1138
|
+
def cardinality(self):
|
|
1139
|
+
"""
|
|
1140
|
+
Return the cardinality of ``self``.
|
|
1141
|
+
|
|
1142
|
+
EXAMPLES::
|
|
1143
|
+
|
|
1144
|
+
sage: IntegerVectors(k=0).cardinality()
|
|
1145
|
+
1
|
|
1146
|
+
sage: IntegerVectors(k=10).cardinality()
|
|
1147
|
+
+Infinity
|
|
1148
|
+
"""
|
|
1149
|
+
if self.k == 0:
|
|
1150
|
+
return Integer(1)
|
|
1151
|
+
return PlusInfinity()
|
|
1152
|
+
|
|
1153
|
+
|
|
1154
|
+
class IntegerVectors_nk(UniqueRepresentation, IntegerVectors):
|
|
1155
|
+
"""
|
|
1156
|
+
Integer vectors of length `k` that sum to `n`.
|
|
1157
|
+
|
|
1158
|
+
AUTHORS:
|
|
1159
|
+
|
|
1160
|
+
- Martin Albrecht
|
|
1161
|
+
- Mike Hansen
|
|
1162
|
+
"""
|
|
1163
|
+
|
|
1164
|
+
def __init__(self, n, k):
|
|
1165
|
+
"""
|
|
1166
|
+
TESTS::
|
|
1167
|
+
|
|
1168
|
+
sage: IV = IntegerVectors(2, 3)
|
|
1169
|
+
sage: TestSuite(IV).run()
|
|
1170
|
+
"""
|
|
1171
|
+
self.n = n
|
|
1172
|
+
self.k = k
|
|
1173
|
+
IntegerVectors.__init__(self, category=FiniteEnumeratedSets())
|
|
1174
|
+
|
|
1175
|
+
def _list_rec(self, n, k):
|
|
1176
|
+
"""
|
|
1177
|
+
Return a list of a exponent tuples of length ``size`` such
|
|
1178
|
+
that the degree of the associated monomial is `D`.
|
|
1179
|
+
|
|
1180
|
+
INPUT:
|
|
1181
|
+
|
|
1182
|
+
- ``n`` -- degree (must be 0)
|
|
1183
|
+
|
|
1184
|
+
- ``k`` -- length of exponent tuples (must be 0)
|
|
1185
|
+
|
|
1186
|
+
EXAMPLES::
|
|
1187
|
+
|
|
1188
|
+
sage: IV = IntegerVectors(2,3)
|
|
1189
|
+
sage: list(IV._list_rec(2,3))
|
|
1190
|
+
[(2, 0, 0), (1, 1, 0), (1, 0, 1), (0, 2, 0), (0, 1, 1), (0, 0, 2)]
|
|
1191
|
+
"""
|
|
1192
|
+
if k == 1:
|
|
1193
|
+
yield (n,)
|
|
1194
|
+
return
|
|
1195
|
+
|
|
1196
|
+
for nbar in range(n + 1):
|
|
1197
|
+
n_diff = n - nbar
|
|
1198
|
+
for rest in self._list_rec(nbar, k - 1):
|
|
1199
|
+
yield (n_diff,) + rest
|
|
1200
|
+
|
|
1201
|
+
def __iter__(self):
|
|
1202
|
+
"""
|
|
1203
|
+
Iterate over ``self``.
|
|
1204
|
+
|
|
1205
|
+
EXAMPLES::
|
|
1206
|
+
|
|
1207
|
+
sage: IV = IntegerVectors(2, 3)
|
|
1208
|
+
sage: list(IV)
|
|
1209
|
+
[[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]]
|
|
1210
|
+
sage: list(IntegerVectors(3, 0))
|
|
1211
|
+
[]
|
|
1212
|
+
sage: list(IntegerVectors(3, 1))
|
|
1213
|
+
[[3]]
|
|
1214
|
+
sage: list(IntegerVectors(0, 1))
|
|
1215
|
+
[[0]]
|
|
1216
|
+
sage: list(IntegerVectors(0, 2))
|
|
1217
|
+
[[0, 0]]
|
|
1218
|
+
sage: list(IntegerVectors(2, 2))
|
|
1219
|
+
[[2, 0], [1, 1], [0, 2]]
|
|
1220
|
+
sage: IntegerVectors(0, 0).list()
|
|
1221
|
+
[[]]
|
|
1222
|
+
sage: IntegerVectors(1, 0).list()
|
|
1223
|
+
[]
|
|
1224
|
+
sage: IntegerVectors(0, 1).list()
|
|
1225
|
+
[[0]]
|
|
1226
|
+
sage: IntegerVectors(2, 2).list()
|
|
1227
|
+
[[2, 0], [1, 1], [0, 2]]
|
|
1228
|
+
sage: IntegerVectors(-1,0).list()
|
|
1229
|
+
[]
|
|
1230
|
+
sage: IntegerVectors(-1,2).list()
|
|
1231
|
+
[]
|
|
1232
|
+
"""
|
|
1233
|
+
if self.n < 0:
|
|
1234
|
+
return
|
|
1235
|
+
|
|
1236
|
+
if not self.k:
|
|
1237
|
+
if not self.n:
|
|
1238
|
+
yield self.element_class(self, [], check=False)
|
|
1239
|
+
return
|
|
1240
|
+
elif self.k == 1:
|
|
1241
|
+
yield self.element_class(self, [self.n], check=False)
|
|
1242
|
+
return
|
|
1243
|
+
|
|
1244
|
+
for nbar in range(self.n+1):
|
|
1245
|
+
n = self.n - nbar
|
|
1246
|
+
for rest in integer_vectors_nk_fast_iter(nbar, self.k - 1):
|
|
1247
|
+
yield self.element_class(self, [n] + rest, check=False)
|
|
1248
|
+
|
|
1249
|
+
def _repr_(self):
|
|
1250
|
+
"""
|
|
1251
|
+
TESTS::
|
|
1252
|
+
|
|
1253
|
+
sage: IV = IntegerVectors(2,3)
|
|
1254
|
+
sage: IV
|
|
1255
|
+
Integer vectors of length 3 that sum to 2
|
|
1256
|
+
"""
|
|
1257
|
+
return "Integer vectors of length {} that sum to {}".format(self.k,
|
|
1258
|
+
self.n)
|
|
1259
|
+
|
|
1260
|
+
def __contains__(self, x):
|
|
1261
|
+
"""
|
|
1262
|
+
TESTS::
|
|
1263
|
+
|
|
1264
|
+
sage: IV = IntegerVectors(2, 3)
|
|
1265
|
+
sage: all(i in IV for i in IV)
|
|
1266
|
+
True
|
|
1267
|
+
sage: [0,1,2] in IV
|
|
1268
|
+
False
|
|
1269
|
+
sage: [2.0, 0, 0] in IV
|
|
1270
|
+
True
|
|
1271
|
+
sage: [0,1,0,1] in IV
|
|
1272
|
+
False
|
|
1273
|
+
sage: [0,1,1] in IV
|
|
1274
|
+
True
|
|
1275
|
+
sage: [-1,2,1] in IV
|
|
1276
|
+
False
|
|
1277
|
+
|
|
1278
|
+
sage: [0] in IntegerVectors(0, 1)
|
|
1279
|
+
True
|
|
1280
|
+
sage: [] in IntegerVectors(0, 0)
|
|
1281
|
+
True
|
|
1282
|
+
sage: [] in IntegerVectors(0, 1)
|
|
1283
|
+
False
|
|
1284
|
+
sage: [] in IntegerVectors(1, 0)
|
|
1285
|
+
False
|
|
1286
|
+
sage: [3] in IntegerVectors(2, 1)
|
|
1287
|
+
False
|
|
1288
|
+
sage: [3] in IntegerVectors(3, 1)
|
|
1289
|
+
True
|
|
1290
|
+
sage: [3,2,2,1] in IntegerVectors(9, 5)
|
|
1291
|
+
False
|
|
1292
|
+
sage: [3,2,2,1] in IntegerVectors(8, 5)
|
|
1293
|
+
False
|
|
1294
|
+
sage: [3,2,2,1] in IntegerVectors(8, 4)
|
|
1295
|
+
True
|
|
1296
|
+
|
|
1297
|
+
Check :issue:`34510`::
|
|
1298
|
+
|
|
1299
|
+
sage: IV33 = IntegerVectors(n=3, k=3)
|
|
1300
|
+
sage: IV33([0])
|
|
1301
|
+
Traceback (most recent call last):
|
|
1302
|
+
...
|
|
1303
|
+
ValueError: [0] doesn't satisfy correct constraints
|
|
1304
|
+
"""
|
|
1305
|
+
if not IntegerVectors.__contains__(self, x):
|
|
1306
|
+
return False
|
|
1307
|
+
|
|
1308
|
+
if len(x) != self.k:
|
|
1309
|
+
return False
|
|
1310
|
+
|
|
1311
|
+
if sum(x) != self.n:
|
|
1312
|
+
return False
|
|
1313
|
+
|
|
1314
|
+
if len(x) > 0 and min(x) < 0:
|
|
1315
|
+
return False
|
|
1316
|
+
|
|
1317
|
+
return True
|
|
1318
|
+
|
|
1319
|
+
def rank(self, x):
|
|
1320
|
+
"""
|
|
1321
|
+
Return the rank of a given element.
|
|
1322
|
+
|
|
1323
|
+
INPUT:
|
|
1324
|
+
|
|
1325
|
+
- ``x`` -- list with ``sum(x) == n`` and ``len(x) == k``
|
|
1326
|
+
|
|
1327
|
+
TESTS::
|
|
1328
|
+
|
|
1329
|
+
sage: IV = IntegerVectors(4,5)
|
|
1330
|
+
sage: list(range(IV.cardinality())) == [IV.rank(x) for x in IV]
|
|
1331
|
+
True
|
|
1332
|
+
"""
|
|
1333
|
+
if x not in self:
|
|
1334
|
+
raise ValueError("argument is not a member of IntegerVectors({},{})".format(self.n, self.k))
|
|
1335
|
+
|
|
1336
|
+
k, s, r = self.k, 0, 0
|
|
1337
|
+
for i in range(k - 1):
|
|
1338
|
+
s += x[k - 1 - i]
|
|
1339
|
+
r += binomial(s + i, i + 1)
|
|
1340
|
+
return r
|
|
1341
|
+
|
|
1342
|
+
def unrank(self, x):
|
|
1343
|
+
"""
|
|
1344
|
+
Return the element at given rank x.
|
|
1345
|
+
|
|
1346
|
+
INPUT:
|
|
1347
|
+
|
|
1348
|
+
- ``x`` -- integer such that ``x < self.cardinality()``
|
|
1349
|
+
|
|
1350
|
+
EXAMPLES::
|
|
1351
|
+
|
|
1352
|
+
sage: IntegerVectors(4,5).unrank(30)
|
|
1353
|
+
[1, 0, 1, 0, 2]
|
|
1354
|
+
sage: IntegerVectors(2,3).unrank(5)
|
|
1355
|
+
[0, 0, 2]
|
|
1356
|
+
"""
|
|
1357
|
+
if x >= self.cardinality():
|
|
1358
|
+
raise IndexError(f"Index {x} is out of range for the IntegerVector.")
|
|
1359
|
+
rtn = [0]*self.k
|
|
1360
|
+
rtn[0] = self.n
|
|
1361
|
+
return IntegerVectors._unrank_helper(self, x, rtn)
|
|
1362
|
+
|
|
1363
|
+
def cardinality(self):
|
|
1364
|
+
"""
|
|
1365
|
+
Return the cardinality of ``self``.
|
|
1366
|
+
|
|
1367
|
+
EXAMPLES::
|
|
1368
|
+
|
|
1369
|
+
sage: IntegerVectors(3,5).cardinality()
|
|
1370
|
+
35
|
|
1371
|
+
sage: IntegerVectors(99, 3).cardinality()
|
|
1372
|
+
5050
|
|
1373
|
+
sage: IntegerVectors(10^9 - 1, 3).cardinality()
|
|
1374
|
+
500000000500000000
|
|
1375
|
+
"""
|
|
1376
|
+
n, k = self.n, self.k
|
|
1377
|
+
return Integer(binomial(n + k - 1, n))
|
|
1378
|
+
|
|
1379
|
+
|
|
1380
|
+
class IntegerVectors_nnondescents(UniqueRepresentation, IntegerVectors):
|
|
1381
|
+
r"""
|
|
1382
|
+
Integer vectors graded by two parameters.
|
|
1383
|
+
|
|
1384
|
+
The grading parameters on the integer vector `v` are:
|
|
1385
|
+
|
|
1386
|
+
- ``n`` -- the sum of the parts of `v`
|
|
1387
|
+
|
|
1388
|
+
- ``c`` -- the non descents composition of `v`
|
|
1389
|
+
|
|
1390
|
+
In other words: the length of `v` equals `c_1 + \cdots + c_k`, and `v`
|
|
1391
|
+
is decreasing in the consecutive blocs of length `c_1, \ldots, c_k`,
|
|
1392
|
+
|
|
1393
|
+
INPUT:
|
|
1394
|
+
|
|
1395
|
+
- ``n`` -- the positive integer `n`
|
|
1396
|
+
- ``comp`` -- the composition `c`
|
|
1397
|
+
|
|
1398
|
+
Those are the integer vectors of sum `n` that are lexicographically
|
|
1399
|
+
maximal (for the natural left-to-right reading) in their orbit by the
|
|
1400
|
+
Young subgroup `S_{c_1} \times \cdots \times S_{c_k}`. In particular,
|
|
1401
|
+
they form a set of orbit representative of integer vectors with
|
|
1402
|
+
respect to this Young subgroup.
|
|
1403
|
+
"""
|
|
1404
|
+
@staticmethod
|
|
1405
|
+
def __classcall_private__(cls, n, comp):
|
|
1406
|
+
"""
|
|
1407
|
+
Normalize input to ensure a unique representation.
|
|
1408
|
+
|
|
1409
|
+
EXAMPLES::
|
|
1410
|
+
|
|
1411
|
+
sage: IntegerVectors(4, [2,1]) is IntegerVectors(int(4), (2,1))
|
|
1412
|
+
True
|
|
1413
|
+
"""
|
|
1414
|
+
return super().__classcall__(cls, n, tuple(comp))
|
|
1415
|
+
|
|
1416
|
+
def __init__(self, n, comp):
|
|
1417
|
+
"""
|
|
1418
|
+
EXAMPLES::
|
|
1419
|
+
|
|
1420
|
+
sage: IV = IntegerVectors(4, [2])
|
|
1421
|
+
sage: TestSuite(IV).run()
|
|
1422
|
+
"""
|
|
1423
|
+
self.n = n
|
|
1424
|
+
self.comp = comp
|
|
1425
|
+
IntegerVectors.__init__(self, category=FiniteEnumeratedSets())
|
|
1426
|
+
|
|
1427
|
+
def _repr_(self):
|
|
1428
|
+
"""
|
|
1429
|
+
EXAMPLES::
|
|
1430
|
+
|
|
1431
|
+
sage: IntegerVectors(4, [2])
|
|
1432
|
+
Integer vectors of 4 with non-descents composition [2]
|
|
1433
|
+
"""
|
|
1434
|
+
return "Integer vectors of {} with non-descents composition {}".format(self.n, list(self.comp))
|
|
1435
|
+
|
|
1436
|
+
def __iter__(self):
|
|
1437
|
+
"""
|
|
1438
|
+
TESTS::
|
|
1439
|
+
|
|
1440
|
+
sage: IntegerVectors(0, []).list()
|
|
1441
|
+
[[]]
|
|
1442
|
+
sage: IntegerVectors(5, []).list()
|
|
1443
|
+
[]
|
|
1444
|
+
sage: IntegerVectors(0, [1]).list()
|
|
1445
|
+
[[0]]
|
|
1446
|
+
sage: IntegerVectors(4, [1]).list()
|
|
1447
|
+
[[4]]
|
|
1448
|
+
sage: IntegerVectors(4, [2]).list()
|
|
1449
|
+
[[4, 0], [3, 1], [2, 2]]
|
|
1450
|
+
sage: IntegerVectors(4, [2,2]).list()
|
|
1451
|
+
[[4, 0, 0, 0],
|
|
1452
|
+
[3, 1, 0, 0],
|
|
1453
|
+
[2, 2, 0, 0],
|
|
1454
|
+
[3, 0, 1, 0],
|
|
1455
|
+
[2, 1, 1, 0],
|
|
1456
|
+
[2, 0, 2, 0],
|
|
1457
|
+
[2, 0, 1, 1],
|
|
1458
|
+
[1, 1, 2, 0],
|
|
1459
|
+
[1, 1, 1, 1],
|
|
1460
|
+
[1, 0, 3, 0],
|
|
1461
|
+
[1, 0, 2, 1],
|
|
1462
|
+
[0, 0, 4, 0],
|
|
1463
|
+
[0, 0, 3, 1],
|
|
1464
|
+
[0, 0, 2, 2]]
|
|
1465
|
+
sage: IntegerVectors(5, [1,1,1]).list()
|
|
1466
|
+
[[5, 0, 0],
|
|
1467
|
+
[4, 1, 0],
|
|
1468
|
+
[4, 0, 1],
|
|
1469
|
+
[3, 2, 0],
|
|
1470
|
+
[3, 1, 1],
|
|
1471
|
+
[3, 0, 2],
|
|
1472
|
+
[2, 3, 0],
|
|
1473
|
+
[2, 2, 1],
|
|
1474
|
+
[2, 1, 2],
|
|
1475
|
+
[2, 0, 3],
|
|
1476
|
+
[1, 4, 0],
|
|
1477
|
+
[1, 3, 1],
|
|
1478
|
+
[1, 2, 2],
|
|
1479
|
+
[1, 1, 3],
|
|
1480
|
+
[1, 0, 4],
|
|
1481
|
+
[0, 5, 0],
|
|
1482
|
+
[0, 4, 1],
|
|
1483
|
+
[0, 3, 2],
|
|
1484
|
+
[0, 2, 3],
|
|
1485
|
+
[0, 1, 4],
|
|
1486
|
+
[0, 0, 5]]
|
|
1487
|
+
sage: IntegerVectors(0, [2,3]).list()
|
|
1488
|
+
[[0, 0, 0, 0, 0]]
|
|
1489
|
+
"""
|
|
1490
|
+
for iv in IntegerVectors(self.n, len(self.comp)):
|
|
1491
|
+
blocks = [IntegerVectors(iv[i], val, max_slope=0).list()
|
|
1492
|
+
for i, val in enumerate(self.comp)]
|
|
1493
|
+
for parts in product(*blocks):
|
|
1494
|
+
res = []
|
|
1495
|
+
for part in parts:
|
|
1496
|
+
res += part
|
|
1497
|
+
yield self.element_class(self, res, check=False)
|
|
1498
|
+
|
|
1499
|
+
|
|
1500
|
+
class IntegerVectorsConstraints(IntegerVectors):
|
|
1501
|
+
"""
|
|
1502
|
+
Class of integer vectors subject to various constraints.
|
|
1503
|
+
"""
|
|
1504
|
+
|
|
1505
|
+
def __init__(self, n=None, k=None, **constraints):
|
|
1506
|
+
"""
|
|
1507
|
+
Initialize ``self``.
|
|
1508
|
+
|
|
1509
|
+
EXAMPLES::
|
|
1510
|
+
|
|
1511
|
+
sage: TestSuite(IntegerVectors(min_slope=0)).run()
|
|
1512
|
+
sage: TestSuite(IntegerVectors(3, max_slope=0)).run()
|
|
1513
|
+
sage: TestSuite(IntegerVectors(3, max_length=4)).run()
|
|
1514
|
+
sage: TestSuite(IntegerVectors(k=2, max_part=4)).run()
|
|
1515
|
+
sage: TestSuite(IntegerVectors(k=2, min_part=2, max_part=4)).run()
|
|
1516
|
+
sage: TestSuite(IntegerVectors(3, 2, max_slope=0)).run()
|
|
1517
|
+
"""
|
|
1518
|
+
self.n = n
|
|
1519
|
+
self.k = k
|
|
1520
|
+
if k is not None and self.k >= 0:
|
|
1521
|
+
constraints['length'] = self.k
|
|
1522
|
+
if 'outer' in constraints:
|
|
1523
|
+
constraints['ceiling'] = constraints['outer']
|
|
1524
|
+
del constraints['outer']
|
|
1525
|
+
if 'inner' in constraints:
|
|
1526
|
+
constraints['floor'] = constraints['inner']
|
|
1527
|
+
del constraints['inner']
|
|
1528
|
+
self.constraints = constraints
|
|
1529
|
+
|
|
1530
|
+
if n is not None:
|
|
1531
|
+
if k is not None or 'max_length' in constraints:
|
|
1532
|
+
category = FiniteEnumeratedSets()
|
|
1533
|
+
else:
|
|
1534
|
+
category = EnumeratedSets()
|
|
1535
|
+
elif k is not None and 'max_part' in constraints: # n is None
|
|
1536
|
+
category = FiniteEnumeratedSets()
|
|
1537
|
+
else:
|
|
1538
|
+
category = EnumeratedSets()
|
|
1539
|
+
IntegerVectors.__init__(self, category=category) # placeholder category
|
|
1540
|
+
|
|
1541
|
+
def _repr_(self):
|
|
1542
|
+
"""
|
|
1543
|
+
Return a string representation of ``self``.
|
|
1544
|
+
|
|
1545
|
+
EXAMPLES::
|
|
1546
|
+
|
|
1547
|
+
sage: IntegerVectors(min_slope=0)
|
|
1548
|
+
Integer vectors with constraints: min_slope=0
|
|
1549
|
+
|
|
1550
|
+
sage: IntegerVectors(3, max_length=2)
|
|
1551
|
+
Integer vectors that sum to 3 with constraints: max_length=2
|
|
1552
|
+
|
|
1553
|
+
sage: IntegerVectors(2, 3, min_slope=0)
|
|
1554
|
+
Integer vectors that sum to 2 with constraints: length=3, min_slope=0
|
|
1555
|
+
"""
|
|
1556
|
+
if self.n is not None:
|
|
1557
|
+
base = "Integer vectors that sum to {} with constraints: ".format(self.n)
|
|
1558
|
+
else:
|
|
1559
|
+
base = "Integer vectors with constraints: "
|
|
1560
|
+
return base + ", ".join("{}={}".format(key, self.constraints[key])
|
|
1561
|
+
for key in sorted(self.constraints))
|
|
1562
|
+
|
|
1563
|
+
def __eq__(self, rhs):
|
|
1564
|
+
"""
|
|
1565
|
+
EXAMPLES::
|
|
1566
|
+
|
|
1567
|
+
sage: IntegerVectors(min_slope=0) == IntegerVectors(min_slope=0)
|
|
1568
|
+
True
|
|
1569
|
+
sage: IntegerVectors(2, min_slope=0) == IntegerVectors(2, min_slope=0)
|
|
1570
|
+
True
|
|
1571
|
+
sage: IntegerVectors(2, 3, min_slope=0) == IntegerVectors(2, 3, min_slope=0)
|
|
1572
|
+
True
|
|
1573
|
+
"""
|
|
1574
|
+
if isinstance(rhs, IntegerVectorsConstraints):
|
|
1575
|
+
return self.n == rhs.n and self.k == rhs.k and self.constraints == rhs.constraints
|
|
1576
|
+
return False
|
|
1577
|
+
|
|
1578
|
+
def __ne__(self, rhs):
|
|
1579
|
+
"""
|
|
1580
|
+
EXAMPLES::
|
|
1581
|
+
|
|
1582
|
+
sage: IntegerVectors(min_slope=0) != IntegerVectors(min_slope=3)
|
|
1583
|
+
True
|
|
1584
|
+
"""
|
|
1585
|
+
return not self.__eq__(rhs)
|
|
1586
|
+
|
|
1587
|
+
def __hash__(self):
|
|
1588
|
+
"""
|
|
1589
|
+
Return the hash of ``self``.
|
|
1590
|
+
|
|
1591
|
+
EXAMPLES::
|
|
1592
|
+
|
|
1593
|
+
sage: hash(IntegerVectors(min_slope=0)) == hash(IntegerVectors(min_slope=0))
|
|
1594
|
+
True
|
|
1595
|
+
sage: hash(IntegerVectors(2, min_slope=0)) == hash(IntegerVectors(2, min_slope=0))
|
|
1596
|
+
True
|
|
1597
|
+
sage: hash(IntegerVectors(2, 3, min_slope=0)) == hash(IntegerVectors(2, 3, min_slope=0))
|
|
1598
|
+
True
|
|
1599
|
+
sage: hash(IntegerVectors(min_slope=0)) != hash(IntegerVectors(min_slope=3))
|
|
1600
|
+
True
|
|
1601
|
+
"""
|
|
1602
|
+
return hash((self.n, self.k, tuple(self.constraints.items())))
|
|
1603
|
+
|
|
1604
|
+
def __contains__(self, x):
|
|
1605
|
+
"""
|
|
1606
|
+
TESTS::
|
|
1607
|
+
|
|
1608
|
+
sage: [3,2,2,1] in IntegerVectors(8, 4, min_part=1) # needs sage.combinat
|
|
1609
|
+
True
|
|
1610
|
+
sage: [3,2,2,1] in IntegerVectors(8, 4, min_part=2) # needs sage.combinat
|
|
1611
|
+
False
|
|
1612
|
+
|
|
1613
|
+
sage: [0,3,0,1,2] in IntegerVectors(6, max_length=3) # needs sage.combinat
|
|
1614
|
+
False
|
|
1615
|
+
"""
|
|
1616
|
+
if isinstance(x, IntegerVector) and x.parent() is self:
|
|
1617
|
+
return True
|
|
1618
|
+
|
|
1619
|
+
if not IntegerVectors.__contains__(self, x):
|
|
1620
|
+
return False
|
|
1621
|
+
|
|
1622
|
+
if self.k is not None and len(x) != self.k:
|
|
1623
|
+
return False
|
|
1624
|
+
|
|
1625
|
+
if self.n is not None and sum(x) != self.n:
|
|
1626
|
+
return False
|
|
1627
|
+
|
|
1628
|
+
from sage.combinat.misc import check_integer_list_constraints
|
|
1629
|
+
return check_integer_list_constraints(x, singleton=True, **self.constraints)
|
|
1630
|
+
|
|
1631
|
+
def cardinality(self):
|
|
1632
|
+
"""
|
|
1633
|
+
Return the cardinality of ``self``.
|
|
1634
|
+
|
|
1635
|
+
EXAMPLES::
|
|
1636
|
+
|
|
1637
|
+
sage: IntegerVectors(3, 3, min_part=1).cardinality()
|
|
1638
|
+
1
|
|
1639
|
+
sage: IntegerVectors(5, 3, min_part=1).cardinality()
|
|
1640
|
+
6
|
|
1641
|
+
sage: IntegerVectors(13, 4, max_part=4).cardinality()
|
|
1642
|
+
20
|
|
1643
|
+
sage: IntegerVectors(k=4, max_part=3).cardinality()
|
|
1644
|
+
256
|
|
1645
|
+
sage: IntegerVectors(k=3, min_part=2, max_part=4).cardinality()
|
|
1646
|
+
27
|
|
1647
|
+
sage: IntegerVectors(13, 4, min_part=2, max_part=4).cardinality()
|
|
1648
|
+
16
|
|
1649
|
+
"""
|
|
1650
|
+
if self.k is None:
|
|
1651
|
+
if self.n is None:
|
|
1652
|
+
return PlusInfinity()
|
|
1653
|
+
if ('max_length' not in self.constraints
|
|
1654
|
+
and self.constraints.get('min_part', 0) <= 0):
|
|
1655
|
+
return PlusInfinity()
|
|
1656
|
+
elif ('max_part' in self.constraints
|
|
1657
|
+
and self.constraints['max_part'] != PlusInfinity()):
|
|
1658
|
+
if (self.n is None and len(self.constraints) == 2
|
|
1659
|
+
and 'min_part' in self.constraints
|
|
1660
|
+
and self.constraints['min_part'] >= 0):
|
|
1661
|
+
num = self.constraints['max_part'] - self.constraints['min_part'] + 1
|
|
1662
|
+
return Integer(num ** self.k)
|
|
1663
|
+
if len(self.constraints) == 1:
|
|
1664
|
+
m = self.constraints['max_part']
|
|
1665
|
+
if self.n is None:
|
|
1666
|
+
return Integer((m + 1) ** self.k)
|
|
1667
|
+
if m >= self.n:
|
|
1668
|
+
return Integer(binomial(self.n + self.k - 1, self.n))
|
|
1669
|
+
# do by inclusion / exclusion on the number
|
|
1670
|
+
# i of parts greater than m
|
|
1671
|
+
n, k = self.n, self.k
|
|
1672
|
+
return Integer(sum(
|
|
1673
|
+
(-1)**i * binomial(n + k - 1 - i * (m + 1), k - 1)
|
|
1674
|
+
* binomial(k, i) for i in range(self.n // (m + 1) + 1)))
|
|
1675
|
+
return ZZ.sum(ZZ.one() for x in self)
|
|
1676
|
+
|
|
1677
|
+
def __iter__(self):
|
|
1678
|
+
"""
|
|
1679
|
+
EXAMPLES::
|
|
1680
|
+
|
|
1681
|
+
sage: IntegerVectors(-1, 0, min_part=1).list()
|
|
1682
|
+
[]
|
|
1683
|
+
sage: IntegerVectors(-1, 2, min_part=1).list()
|
|
1684
|
+
[]
|
|
1685
|
+
sage: IntegerVectors(0, 0, min_part=1).list()
|
|
1686
|
+
[[]]
|
|
1687
|
+
sage: IntegerVectors(3, 0, min_part=1).list()
|
|
1688
|
+
[]
|
|
1689
|
+
sage: IntegerVectors(0, 1, min_part=1).list()
|
|
1690
|
+
[]
|
|
1691
|
+
sage: IntegerVectors(2, 2, min_part=1).list()
|
|
1692
|
+
[[1, 1]]
|
|
1693
|
+
sage: IntegerVectors(2, 3, min_part=1).list()
|
|
1694
|
+
[]
|
|
1695
|
+
sage: IntegerVectors(4, 2, min_part=1).list()
|
|
1696
|
+
[[3, 1], [2, 2], [1, 3]]
|
|
1697
|
+
|
|
1698
|
+
::
|
|
1699
|
+
|
|
1700
|
+
sage: IntegerVectors(0, 3, outer=[0,0,0]).list()
|
|
1701
|
+
[[0, 0, 0]]
|
|
1702
|
+
sage: IntegerVectors(1, 3, outer=[0,0,0]).list()
|
|
1703
|
+
[]
|
|
1704
|
+
sage: IntegerVectors(2, 3, outer=[0,2,0]).list()
|
|
1705
|
+
[[0, 2, 0]]
|
|
1706
|
+
sage: IntegerVectors(2, 3, outer=[1,2,1]).list()
|
|
1707
|
+
[[1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1]]
|
|
1708
|
+
sage: IntegerVectors(2, 3, outer=[1,1,1]).list()
|
|
1709
|
+
[[1, 1, 0], [1, 0, 1], [0, 1, 1]]
|
|
1710
|
+
sage: IntegerVectors(2, 5, outer=[1,1,1,1,1]).list()
|
|
1711
|
+
[[1, 1, 0, 0, 0],
|
|
1712
|
+
[1, 0, 1, 0, 0],
|
|
1713
|
+
[1, 0, 0, 1, 0],
|
|
1714
|
+
[1, 0, 0, 0, 1],
|
|
1715
|
+
[0, 1, 1, 0, 0],
|
|
1716
|
+
[0, 1, 0, 1, 0],
|
|
1717
|
+
[0, 1, 0, 0, 1],
|
|
1718
|
+
[0, 0, 1, 1, 0],
|
|
1719
|
+
[0, 0, 1, 0, 1],
|
|
1720
|
+
[0, 0, 0, 1, 1]]
|
|
1721
|
+
|
|
1722
|
+
::
|
|
1723
|
+
|
|
1724
|
+
sage: iv = [ IntegerVectors(n, k) for n in range(-2, 7) for k in range(7) ]
|
|
1725
|
+
sage: all(map(lambda x: x.cardinality() == len(x.list()), iv))
|
|
1726
|
+
True
|
|
1727
|
+
sage: essai = [[1,1,1], [2,5,6], [6,5,2]]
|
|
1728
|
+
sage: iv = [ IntegerVectors(x[0], x[1], max_part=x[2]-1) for x in essai ]
|
|
1729
|
+
sage: all(map(lambda x: x.cardinality() == len(x.list()), iv))
|
|
1730
|
+
True
|
|
1731
|
+
"""
|
|
1732
|
+
from sage.combinat.integer_lists import IntegerListsLex
|
|
1733
|
+
|
|
1734
|
+
if self.n is None:
|
|
1735
|
+
if self.k is not None and 'max_part' in self.constraints:
|
|
1736
|
+
n_list = range((self.constraints['max_part'] + 1) * self.k)
|
|
1737
|
+
else:
|
|
1738
|
+
n_list = NN
|
|
1739
|
+
else:
|
|
1740
|
+
n_list = [self.n]
|
|
1741
|
+
for n in n_list:
|
|
1742
|
+
for x in IntegerListsLex(n, check=False, **self.constraints):
|
|
1743
|
+
yield self.element_class(self, x, check=False)
|
|
1744
|
+
|
|
1745
|
+
|
|
1746
|
+
def integer_vectors_nk_fast_iter(n, k):
|
|
1747
|
+
"""
|
|
1748
|
+
A fast iterator for integer vectors of ``n`` of length ``k`` which
|
|
1749
|
+
yields Python lists filled with Sage Integers.
|
|
1750
|
+
|
|
1751
|
+
EXAMPLES::
|
|
1752
|
+
|
|
1753
|
+
sage: from sage.combinat.integer_vector import integer_vectors_nk_fast_iter
|
|
1754
|
+
sage: list(integer_vectors_nk_fast_iter(3, 2))
|
|
1755
|
+
[[3, 0], [2, 1], [1, 2], [0, 3]]
|
|
1756
|
+
sage: list(integer_vectors_nk_fast_iter(2, 2))
|
|
1757
|
+
[[2, 0], [1, 1], [0, 2]]
|
|
1758
|
+
sage: list(integer_vectors_nk_fast_iter(1, 2))
|
|
1759
|
+
[[1, 0], [0, 1]]
|
|
1760
|
+
|
|
1761
|
+
We check some corner cases::
|
|
1762
|
+
|
|
1763
|
+
sage: list(integer_vectors_nk_fast_iter(5, 1))
|
|
1764
|
+
[[5]]
|
|
1765
|
+
sage: list(integer_vectors_nk_fast_iter(1, 1))
|
|
1766
|
+
[[1]]
|
|
1767
|
+
sage: list(integer_vectors_nk_fast_iter(2, 0))
|
|
1768
|
+
[]
|
|
1769
|
+
sage: list(integer_vectors_nk_fast_iter(0, 2))
|
|
1770
|
+
[[0, 0]]
|
|
1771
|
+
sage: list(integer_vectors_nk_fast_iter(0, 0))
|
|
1772
|
+
[[]]
|
|
1773
|
+
"""
|
|
1774
|
+
# "bad" input
|
|
1775
|
+
if n < 0 or k < 0:
|
|
1776
|
+
return
|
|
1777
|
+
|
|
1778
|
+
# Check some corner cases first
|
|
1779
|
+
if not k:
|
|
1780
|
+
if not n:
|
|
1781
|
+
yield []
|
|
1782
|
+
return
|
|
1783
|
+
n = Integer(n)
|
|
1784
|
+
if k == 1:
|
|
1785
|
+
yield [n]
|
|
1786
|
+
return
|
|
1787
|
+
|
|
1788
|
+
zero = ZZ.zero()
|
|
1789
|
+
one = ZZ.one()
|
|
1790
|
+
k = int(k)
|
|
1791
|
+
|
|
1792
|
+
pos = 0 # Current position
|
|
1793
|
+
rem = zero # Amount remaining
|
|
1794
|
+
cur = [n] + [zero] * (k - 1) # Current list
|
|
1795
|
+
yield list(cur)
|
|
1796
|
+
while pos >= 0:
|
|
1797
|
+
if not cur[pos]:
|
|
1798
|
+
pos -= 1
|
|
1799
|
+
continue
|
|
1800
|
+
cur[pos] -= one
|
|
1801
|
+
rem += one
|
|
1802
|
+
if not rem:
|
|
1803
|
+
yield list(cur)
|
|
1804
|
+
elif pos == k - 2:
|
|
1805
|
+
cur[pos + 1] = rem
|
|
1806
|
+
yield list(cur)
|
|
1807
|
+
cur[pos + 1] = zero
|
|
1808
|
+
else:
|
|
1809
|
+
pos += 1
|
|
1810
|
+
cur[pos] = rem # Guaranteed to be at least 1
|
|
1811
|
+
rem = zero
|
|
1812
|
+
yield list(cur)
|
|
1813
|
+
|
|
1814
|
+
|
|
1815
|
+
# October 2012: fixing outdated pickles which use classes being deprecated
|
|
1816
|
+
from sage.misc.persist import register_unpickle_override
|
|
1817
|
+
register_unpickle_override('sage.combinat.integer_vector', 'IntegerVectors_nconstraints', IntegerVectorsConstraints)
|
|
1818
|
+
register_unpickle_override('sage.combinat.integer_vector', 'IntegerVectors_nkconstraints', IntegerVectorsConstraints)
|