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,1650 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
r"""
|
|
3
|
+
Enumerated set of lists of integers with constraints, in inverse lexicographic order
|
|
4
|
+
|
|
5
|
+
- :class:`IntegerListsLex`: the enumerated set of lists of nonnegative
|
|
6
|
+
integers with specified constraints, in inverse lexicographic order.
|
|
7
|
+
|
|
8
|
+
- :class:`IntegerListsBackend_invlex`: Cython back-end for
|
|
9
|
+
:class:`IntegerListsLex`.
|
|
10
|
+
|
|
11
|
+
HISTORY:
|
|
12
|
+
|
|
13
|
+
This generic tool was originally written by Hivert and Thiery in
|
|
14
|
+
MuPAD-Combinat in 2000 and ported over to Sage by Mike Hansen in
|
|
15
|
+
2007. It was then completely rewritten in 2015 by Gillespie,
|
|
16
|
+
Schilling, and Thiery, with the help of many, to deal with
|
|
17
|
+
limitations and lack of robustness w.r.t. input.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
# ****************************************************************************
|
|
21
|
+
# Copyright (C) 2015 Bryan Gillespie <Brg008@gmail.com>
|
|
22
|
+
# Nicolas M. Thiery <nthiery at users.sf.net>
|
|
23
|
+
# Anne Schilling <anne@math.ucdavis.edu>
|
|
24
|
+
#
|
|
25
|
+
# This program is free software: you can redistribute it and/or modify
|
|
26
|
+
# it under the terms of the GNU General Public License as published by
|
|
27
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
28
|
+
# (at your option) any later version.
|
|
29
|
+
# https://www.gnu.org/licenses/
|
|
30
|
+
# ****************************************************************************
|
|
31
|
+
|
|
32
|
+
import builtins
|
|
33
|
+
|
|
34
|
+
from sage.misc.classcall_metaclass import ClasscallMetaclass, typecall
|
|
35
|
+
from sage.misc.cachefunc import cached_method
|
|
36
|
+
from sage.combinat.integer_lists.base cimport IntegerListsBackend
|
|
37
|
+
from sage.combinat.integer_lists.lists import IntegerLists
|
|
38
|
+
from sage.combinat.integer_lists.base import Infinity
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class IntegerListsLex(IntegerLists, metaclass=ClasscallMetaclass):
|
|
42
|
+
r"""
|
|
43
|
+
Lists of nonnegative integers with constraints, in inverse
|
|
44
|
+
lexicographic order.
|
|
45
|
+
|
|
46
|
+
An *integer list* is a list `l` of nonnegative integers, its *parts*. The
|
|
47
|
+
slope (at position `i`) is the difference ``l[i+1]-l[i]`` between two
|
|
48
|
+
consecutive parts.
|
|
49
|
+
|
|
50
|
+
This class allows to construct the set `S` of all integer lists
|
|
51
|
+
`l` satisfying specified bounds on the sum, the length, the slope,
|
|
52
|
+
and the individual parts, enumerated in *inverse* lexicographic
|
|
53
|
+
order, that is from largest to smallest in lexicographic
|
|
54
|
+
order. Note that, to admit such an enumeration, `S` is almost
|
|
55
|
+
necessarily finite (see :ref:`IntegerListsLex_finiteness`).
|
|
56
|
+
|
|
57
|
+
The main purpose is to provide a generic iteration engine for all the
|
|
58
|
+
enumerated sets like :class:`Partitions`, :class:`Compositions`,
|
|
59
|
+
:class:`IntegerVectors`. It can also be used to generate many other
|
|
60
|
+
combinatorial objects like Dyck paths, Motzkin paths, etc. Mathematically
|
|
61
|
+
speaking, this is a special case of set of integral points of a polytope (or
|
|
62
|
+
union thereof, when the length is not fixed).
|
|
63
|
+
|
|
64
|
+
INPUT:
|
|
65
|
+
|
|
66
|
+
- ``min_sum`` -- nonnegative integer (default: 0);
|
|
67
|
+
a lower bound on ``sum(l)``
|
|
68
|
+
|
|
69
|
+
- ``max_sum`` -- nonnegative integer or `\infty` (default: `\infty`);
|
|
70
|
+
an upper bound on ``sum(l)``
|
|
71
|
+
|
|
72
|
+
- ``n`` -- nonnegative integer (optional); if specified, this
|
|
73
|
+
overrides ``min_sum`` and ``max_sum``
|
|
74
|
+
|
|
75
|
+
- ``min_length`` -- nonnegative integer (default: `0`); a lower
|
|
76
|
+
bound on ``len(l)``
|
|
77
|
+
|
|
78
|
+
- ``max_length`` -- nonnegative integer or `\infty` (default:
|
|
79
|
+
`\infty`); an upper bound on ``len(l)``
|
|
80
|
+
|
|
81
|
+
- ``length`` -- integer (optional); overrides ``min_length``
|
|
82
|
+
and ``max_length`` if specified
|
|
83
|
+
|
|
84
|
+
- ``min_part`` -- nonnegative integer; a lower bounds on all
|
|
85
|
+
parts: ``min_part <= l[i]`` for ``0 <= i < len(l)``
|
|
86
|
+
|
|
87
|
+
- ``floor`` -- list of nonnegative integers or a function; lower
|
|
88
|
+
bounds on the individual parts `l[i]`
|
|
89
|
+
|
|
90
|
+
If ``floor`` is a list of integers, then ``floor<=l[i]`` for ``0
|
|
91
|
+
<= i < min(len(l), len(floor)``. Similarly, if ``floor`` is a
|
|
92
|
+
function, then ``floor(i) <= l[i]`` for ``0 <= i < len(l)``.
|
|
93
|
+
|
|
94
|
+
- ``max_part`` -- nonnegative integer or `\infty`; an upper
|
|
95
|
+
bound on all parts: ``l[i] <= max_part`` for ``0 <= i < len(l)``
|
|
96
|
+
|
|
97
|
+
- ``ceiling`` -- upper bounds on the individual parts ``l[i]``;
|
|
98
|
+
this takes the same type of input as ``floor``, except that
|
|
99
|
+
`\infty` is allowed in addition to integers, and the default
|
|
100
|
+
value is `\infty`.
|
|
101
|
+
|
|
102
|
+
- ``min_slope`` -- integer or `-\infty` (default: `-\infty`);
|
|
103
|
+
a lower bound on the slope between consecutive parts:
|
|
104
|
+
``min_slope <= l[i+1]-l[i]`` for ``0 <= i < len(l)-1``
|
|
105
|
+
|
|
106
|
+
- ``max_slope`` -- integer or `+\infty` (defaults: `+\infty`);
|
|
107
|
+
an upper bound on the slope between consecutive parts:
|
|
108
|
+
``l[i+1]-l[i] <= max_slope`` for ``0 <= i < len(l)-1``
|
|
109
|
+
|
|
110
|
+
- ``category`` -- a category (default: :class:`FiniteEnumeratedSets`)
|
|
111
|
+
|
|
112
|
+
- ``check`` -- boolean (default: ``True``); whether to display the
|
|
113
|
+
warnings raised when functions are given as input to ``floor``
|
|
114
|
+
or ``ceiling`` and the errors raised when there is no proper
|
|
115
|
+
enumeration.
|
|
116
|
+
|
|
117
|
+
- ``name`` -- string or ``None`` (default: ``None``); if set,
|
|
118
|
+
this will be passed down to :meth:`Parent.rename` to specify the
|
|
119
|
+
name of ``self``. It is recommended to use rename method directly
|
|
120
|
+
because this feature may become deprecated.
|
|
121
|
+
|
|
122
|
+
- ``element_constructor`` -- a function (or callable) that creates
|
|
123
|
+
elements of ``self`` from a list. See also :class:`Parent`
|
|
124
|
+
|
|
125
|
+
- ``element_class`` -- a class for the elements of ``self``
|
|
126
|
+
(default: `ClonableArray`). This merely sets the attribute
|
|
127
|
+
``self.Element``. See the examples for details.
|
|
128
|
+
|
|
129
|
+
.. NOTE::
|
|
130
|
+
|
|
131
|
+
When several lists satisfying the constraints differ only by
|
|
132
|
+
trailing zeroes, only the shortest one is enumerated (and
|
|
133
|
+
therefore counted). The others are still considered valid.
|
|
134
|
+
See the examples below.
|
|
135
|
+
|
|
136
|
+
This feature is questionable. It is recommended not to rely on
|
|
137
|
+
it, as it may eventually be discontinued.
|
|
138
|
+
|
|
139
|
+
EXAMPLES:
|
|
140
|
+
|
|
141
|
+
We create the enumerated set of all lists of nonnegative integers
|
|
142
|
+
of length `3` and sum `2`::
|
|
143
|
+
|
|
144
|
+
sage: C = IntegerListsLex(2, length=3)
|
|
145
|
+
sage: C
|
|
146
|
+
Integer lists of sum 2 satisfying certain constraints
|
|
147
|
+
sage: C.cardinality()
|
|
148
|
+
6
|
|
149
|
+
sage: [p for p in C]
|
|
150
|
+
[[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]]
|
|
151
|
+
|
|
152
|
+
sage: [2, 0, 0] in C
|
|
153
|
+
True
|
|
154
|
+
sage: [2, 0, 1] in C
|
|
155
|
+
False
|
|
156
|
+
sage: "a" in C
|
|
157
|
+
False
|
|
158
|
+
sage: ["a"] in C
|
|
159
|
+
False
|
|
160
|
+
sage: C.first()
|
|
161
|
+
[2, 0, 0]
|
|
162
|
+
|
|
163
|
+
One can specify lower and upper bounds on each part::
|
|
164
|
+
|
|
165
|
+
sage: list(IntegerListsLex(5, length=3, floor=[1,2,0], ceiling=[3,2,3]))
|
|
166
|
+
[[3, 2, 0], [2, 2, 1], [1, 2, 2]]
|
|
167
|
+
|
|
168
|
+
When the length is fixed as above, one can also use
|
|
169
|
+
:class:`IntegerVectors`::
|
|
170
|
+
|
|
171
|
+
sage: IntegerVectors(2,3).list()
|
|
172
|
+
[[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]]
|
|
173
|
+
|
|
174
|
+
Using the slope condition, one can generate integer partitions
|
|
175
|
+
(but see :class:`Partitions`)::
|
|
176
|
+
|
|
177
|
+
sage: list(IntegerListsLex(4, max_slope=0))
|
|
178
|
+
[[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]]
|
|
179
|
+
|
|
180
|
+
The following is the list of all partitions of `7` with parts at least `2`::
|
|
181
|
+
|
|
182
|
+
sage: list(IntegerListsLex(7, max_slope=0, min_part=2))
|
|
183
|
+
[[7], [5, 2], [4, 3], [3, 2, 2]]
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
.. RUBRIC:: floor and ceiling conditions
|
|
187
|
+
|
|
188
|
+
Next we list all partitions of `5` of length at most `3` which are
|
|
189
|
+
bounded below by ``[2,1,1]``::
|
|
190
|
+
|
|
191
|
+
sage: list(IntegerListsLex(5, max_slope=0, max_length=3, floor=[2,1,1]))
|
|
192
|
+
[[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1]]
|
|
193
|
+
|
|
194
|
+
Note that ``[5]`` is considered valid, because the floor
|
|
195
|
+
constraints only apply to existing positions in the list. To
|
|
196
|
+
obtain instead the partitions containing ``[2,1,1]``, one needs to
|
|
197
|
+
use ``min_length`` or ``length``::
|
|
198
|
+
|
|
199
|
+
sage: list(IntegerListsLex(5, max_slope=0, length=3, floor=[2,1,1]))
|
|
200
|
+
[[3, 1, 1], [2, 2, 1]]
|
|
201
|
+
|
|
202
|
+
Here is the list of all partitions of `5` which are contained in
|
|
203
|
+
``[3,2,2]``::
|
|
204
|
+
|
|
205
|
+
sage: list(IntegerListsLex(5, max_slope=0, max_length=3, ceiling=[3,2,2]))
|
|
206
|
+
[[3, 2], [3, 1, 1], [2, 2, 1]]
|
|
207
|
+
|
|
208
|
+
This is the list of all compositions of `4` (but see :class:`Compositions`)::
|
|
209
|
+
|
|
210
|
+
sage: list(IntegerListsLex(4, min_part=1))
|
|
211
|
+
[[4], [3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
|
|
212
|
+
|
|
213
|
+
This is the list of all integer vectors of sum `4` and length `3`::
|
|
214
|
+
|
|
215
|
+
sage: list(IntegerListsLex(4, length=3))
|
|
216
|
+
[[4, 0, 0], [3, 1, 0], [3, 0, 1], [2, 2, 0], [2, 1, 1],
|
|
217
|
+
[2, 0, 2], [1, 3, 0], [1, 2, 1], [1, 1, 2], [1, 0, 3],
|
|
218
|
+
[0, 4, 0], [0, 3, 1], [0, 2, 2], [0, 1, 3], [0, 0, 4]]
|
|
219
|
+
|
|
220
|
+
For whatever it is worth, the ``floor`` and ``min_part``
|
|
221
|
+
constraints can be combined::
|
|
222
|
+
|
|
223
|
+
sage: L = IntegerListsLex(5, floor=[2,0,2], min_part=1)
|
|
224
|
+
sage: L.list()
|
|
225
|
+
[[5], [4, 1], [3, 2], [2, 3], [2, 1, 2]]
|
|
226
|
+
|
|
227
|
+
This is achieved by updating the floor upon constructing ``L``::
|
|
228
|
+
|
|
229
|
+
sage: [L.floor(i) for i in range(5)]
|
|
230
|
+
[2, 1, 2, 1, 1]
|
|
231
|
+
|
|
232
|
+
Similarly, the ``ceiling`` and ``max_part`` constraints can be
|
|
233
|
+
combined::
|
|
234
|
+
|
|
235
|
+
sage: L = IntegerListsLex(4, ceiling=[2,3,1], max_part=2, length=3)
|
|
236
|
+
sage: L.list()
|
|
237
|
+
[[2, 2, 0], [2, 1, 1], [1, 2, 1]]
|
|
238
|
+
sage: [L.ceiling(i) for i in range(5)]
|
|
239
|
+
[2, 2, 1, 2, 2]
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
This can be used to generate Motzkin words (see
|
|
243
|
+
:wikipedia:`Motzkin_number`)::
|
|
244
|
+
|
|
245
|
+
sage: def motzkin_words(n):
|
|
246
|
+
....: return IntegerListsLex(length=n+1, min_slope=-1, max_slope=1,
|
|
247
|
+
....: ceiling=[0]+[+oo for i in range(n-1)]+[0])
|
|
248
|
+
sage: motzkin_words(4).list()
|
|
249
|
+
[[0, 1, 2, 1, 0],
|
|
250
|
+
[0, 1, 1, 1, 0],
|
|
251
|
+
[0, 1, 1, 0, 0],
|
|
252
|
+
[0, 1, 0, 1, 0],
|
|
253
|
+
[0, 1, 0, 0, 0],
|
|
254
|
+
[0, 0, 1, 1, 0],
|
|
255
|
+
[0, 0, 1, 0, 0],
|
|
256
|
+
[0, 0, 0, 1, 0],
|
|
257
|
+
[0, 0, 0, 0, 0]]
|
|
258
|
+
sage: [motzkin_words(n).cardinality() for n in range(8)]
|
|
259
|
+
[1, 1, 2, 4, 9, 21, 51, 127]
|
|
260
|
+
sage: oeis(_) # optional -- internet
|
|
261
|
+
0: A001006: Motzkin numbers: number of ways of drawing any number
|
|
262
|
+
of nonintersecting chords joining n (labeled) points on a circle.
|
|
263
|
+
1: ...
|
|
264
|
+
2: ...
|
|
265
|
+
|
|
266
|
+
or Dyck words (see also :class:`DyckWords`), through the bijection
|
|
267
|
+
with paths from `(0,0)` to `(n,n)` with left and up steps that remain
|
|
268
|
+
below the diagonal::
|
|
269
|
+
|
|
270
|
+
sage: def dyck_words(n):
|
|
271
|
+
....: return IntegerListsLex(length=n, ceiling=list(range(n+1)), min_slope=0)
|
|
272
|
+
sage: [dyck_words(n).cardinality() for n in range(8)]
|
|
273
|
+
[1, 1, 2, 5, 14, 42, 132, 429]
|
|
274
|
+
sage: dyck_words(3).list()
|
|
275
|
+
[[0, 1, 2], [0, 1, 1], [0, 0, 2], [0, 0, 1], [0, 0, 0]]
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
.. _IntegerListsLex_finiteness:
|
|
279
|
+
|
|
280
|
+
.. RUBRIC:: On finiteness and inverse lexicographic enumeration
|
|
281
|
+
|
|
282
|
+
The set of all lists of integers cannot be enumerated in inverse
|
|
283
|
+
lexicographic order, since there is no largest list (take `[n]`
|
|
284
|
+
for `n` as large as desired)::
|
|
285
|
+
|
|
286
|
+
sage: IntegerListsLex().first()
|
|
287
|
+
Traceback (most recent call last):
|
|
288
|
+
...
|
|
289
|
+
ValueError: could not prove that the specified constraints yield a finite set
|
|
290
|
+
|
|
291
|
+
Here is a variant which could be enumerated in lexicographic order
|
|
292
|
+
but not in inverse lexicographic order::
|
|
293
|
+
|
|
294
|
+
sage: L = IntegerListsLex(length=2, ceiling=[Infinity, 0], floor=[0,1])
|
|
295
|
+
sage: for l in L: print(l)
|
|
296
|
+
Traceback (most recent call last):
|
|
297
|
+
...
|
|
298
|
+
ValueError: infinite upper bound for values of m
|
|
299
|
+
|
|
300
|
+
Even when the sum is specified, it is not necessarily possible to
|
|
301
|
+
enumerate *all* elements in inverse lexicographic order. In the
|
|
302
|
+
following example, the list ``[1, 1, 1]`` will never appear in the
|
|
303
|
+
enumeration::
|
|
304
|
+
|
|
305
|
+
sage: IntegerListsLex(3).first()
|
|
306
|
+
Traceback (most recent call last):
|
|
307
|
+
...
|
|
308
|
+
ValueError: could not prove that the specified constraints yield a finite set
|
|
309
|
+
|
|
310
|
+
If one wants to proceed anyway, one can sign a waiver by setting
|
|
311
|
+
``check=False`` (again, be warned that some valid lists may never appear)::
|
|
312
|
+
|
|
313
|
+
sage: L = IntegerListsLex(3, check=False)
|
|
314
|
+
sage: it = iter(L)
|
|
315
|
+
sage: [next(it) for i in range(6)]
|
|
316
|
+
[[3], [2, 1], [2, 0, 1], [2, 0, 0, 1], [2, 0, 0, 0, 1], [2, 0, 0, 0, 0, 1]]
|
|
317
|
+
|
|
318
|
+
In fact, being inverse lexicographically enumerable is almost
|
|
319
|
+
equivalent to being finite. The only infinity that can occur would
|
|
320
|
+
be from a tail of numbers `0,1` as in the previous example, where
|
|
321
|
+
the `1` moves further and further to the right. If there is any
|
|
322
|
+
list that is inverse lexicographically smaller than such a
|
|
323
|
+
configuration, the iterator would not reach it and hence would not
|
|
324
|
+
be considered iterable. Given that the infinite cases are very
|
|
325
|
+
specific, at this point only the finite cases are supported
|
|
326
|
+
(without signing the waiver).
|
|
327
|
+
|
|
328
|
+
The finiteness detection is not complete yet, so some finite cases
|
|
329
|
+
may not be supported either, at least not without disabling the
|
|
330
|
+
checks. Practical examples of such are welcome.
|
|
331
|
+
|
|
332
|
+
.. RUBRIC:: On trailing zeroes, and their caveats
|
|
333
|
+
|
|
334
|
+
As mentioned above, when several lists satisfying the constraints
|
|
335
|
+
differ only by trailing zeroes, only the shortest one is listed::
|
|
336
|
+
|
|
337
|
+
sage: L = IntegerListsLex(max_length=4, max_part=1)
|
|
338
|
+
sage: L.list()
|
|
339
|
+
[[1, 1, 1, 1],
|
|
340
|
+
[1, 1, 1],
|
|
341
|
+
[1, 1, 0, 1],
|
|
342
|
+
[1, 1],
|
|
343
|
+
[1, 0, 1, 1],
|
|
344
|
+
[1, 0, 1],
|
|
345
|
+
[1, 0, 0, 1],
|
|
346
|
+
[1],
|
|
347
|
+
[0, 1, 1, 1],
|
|
348
|
+
[0, 1, 1],
|
|
349
|
+
[0, 1, 0, 1],
|
|
350
|
+
[0, 1],
|
|
351
|
+
[0, 0, 1, 1],
|
|
352
|
+
[0, 0, 1],
|
|
353
|
+
[0, 0, 0, 1],
|
|
354
|
+
[]]
|
|
355
|
+
|
|
356
|
+
and counted::
|
|
357
|
+
|
|
358
|
+
sage: L.cardinality()
|
|
359
|
+
16
|
|
360
|
+
|
|
361
|
+
Still, the others are considered as elements of `L`::
|
|
362
|
+
|
|
363
|
+
sage: L = IntegerListsLex(4,min_length=3,max_length=4)
|
|
364
|
+
sage: L.list()
|
|
365
|
+
[..., [2, 2, 0], ...]
|
|
366
|
+
|
|
367
|
+
sage: [2, 2, 0] in L # in L.list()
|
|
368
|
+
True
|
|
369
|
+
sage: [2, 2, 0, 0] in L # not in L.list() !
|
|
370
|
+
True
|
|
371
|
+
sage: [2, 2, 0, 0, 0] in L
|
|
372
|
+
False
|
|
373
|
+
|
|
374
|
+
.. RUBRIC:: Specifying functions as input for the floor or ceiling
|
|
375
|
+
|
|
376
|
+
We construct all lists of sum `4` and length `4` such that ``l[i] <= i``::
|
|
377
|
+
|
|
378
|
+
sage: list(IntegerListsLex(4, length=4, ceiling=lambda i: i, check=False))
|
|
379
|
+
[[0, 1, 2, 1], [0, 1, 1, 2], [0, 1, 0, 3], [0, 0, 2, 2], [0, 0, 1, 3]]
|
|
380
|
+
|
|
381
|
+
.. WARNING::
|
|
382
|
+
|
|
383
|
+
When passing a function as ``floor`` or ``ceiling``, it may
|
|
384
|
+
become undecidable to detect improper inverse lexicographic
|
|
385
|
+
enumeration. For example, the following example has a finite
|
|
386
|
+
enumeration::
|
|
387
|
+
|
|
388
|
+
sage: L = IntegerListsLex(3, floor=lambda i: 1 if i>=2 else 0, check=False)
|
|
389
|
+
sage: L.list()
|
|
390
|
+
[[3],
|
|
391
|
+
[2, 1],
|
|
392
|
+
[2, 0, 1],
|
|
393
|
+
[1, 2],
|
|
394
|
+
[1, 1, 1],
|
|
395
|
+
[1, 0, 2],
|
|
396
|
+
[1, 0, 1, 1],
|
|
397
|
+
[0, 3],
|
|
398
|
+
[0, 2, 1],
|
|
399
|
+
[0, 1, 2],
|
|
400
|
+
[0, 1, 1, 1],
|
|
401
|
+
[0, 0, 3],
|
|
402
|
+
[0, 0, 2, 1],
|
|
403
|
+
[0, 0, 1, 2],
|
|
404
|
+
[0, 0, 1, 1, 1]]
|
|
405
|
+
|
|
406
|
+
but one cannot decide whether the following has an improper
|
|
407
|
+
inverse lexicographic enumeration without computing the floor
|
|
408
|
+
all the way to ``Infinity``::
|
|
409
|
+
|
|
410
|
+
sage: L = IntegerListsLex(3, floor=lambda i: 0, check=False)
|
|
411
|
+
sage: it = iter(L)
|
|
412
|
+
sage: [next(it) for i in range(6)]
|
|
413
|
+
[[3], [2, 1], [2, 0, 1], [2, 0, 0, 1], [2, 0, 0, 0, 1], [2, 0, 0, 0, 0, 1]]
|
|
414
|
+
|
|
415
|
+
Hence a warning is raised when a function is specified as
|
|
416
|
+
input, unless the waiver is signed by setting ``check=False``::
|
|
417
|
+
|
|
418
|
+
sage: L = IntegerListsLex(3, floor=lambda i: 1 if i>=2 else 0)
|
|
419
|
+
doctest:...
|
|
420
|
+
A function has been given as input of the floor=[...] or ceiling=[...]
|
|
421
|
+
arguments of IntegerListsLex. Please see the documentation for the caveats.
|
|
422
|
+
If you know what you are doing, you can set check=False to skip this warning.
|
|
423
|
+
|
|
424
|
+
Similarly, the algorithm may need to search forever for a
|
|
425
|
+
solution when the ceiling is ultimately zero::
|
|
426
|
+
|
|
427
|
+
sage: L = IntegerListsLex(2,ceiling=lambda i:0, check=False)
|
|
428
|
+
sage: L.first() # not tested: will hang forever
|
|
429
|
+
sage: L = IntegerListsLex(2,ceiling=lambda i:0 if i<20 else 1, check=False)
|
|
430
|
+
sage: it = iter(L)
|
|
431
|
+
sage: next(it)
|
|
432
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
|
|
433
|
+
sage: next(it)
|
|
434
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1]
|
|
435
|
+
sage: next(it)
|
|
436
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1]
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
.. RUBRIC:: Tip: using disjoint union enumerated sets for additional flexibility
|
|
440
|
+
|
|
441
|
+
Sometimes, specifying a range for the sum or the length may be too
|
|
442
|
+
restrictive. One would want instead to specify a list, or
|
|
443
|
+
iterable `L`, of acceptable values. This is easy to achieve using
|
|
444
|
+
a :class:`disjoint union of enumerated sets <DisjointUnionEnumeratedSets>`.
|
|
445
|
+
Here we want to accept the values `n=0,2,3`::
|
|
446
|
+
|
|
447
|
+
sage: C = DisjointUnionEnumeratedSets(Family([0,2,3],
|
|
448
|
+
....: lambda n: IntegerListsLex(n, length=2)))
|
|
449
|
+
sage: C
|
|
450
|
+
Disjoint union of Finite family
|
|
451
|
+
{0: Integer lists of sum 0 satisfying certain constraints,
|
|
452
|
+
2: Integer lists of sum 2 satisfying certain constraints,
|
|
453
|
+
3: Integer lists of sum 3 satisfying certain constraints}
|
|
454
|
+
sage: C.list()
|
|
455
|
+
[[0, 0],
|
|
456
|
+
[2, 0], [1, 1], [0, 2],
|
|
457
|
+
[3, 0], [2, 1], [1, 2], [0, 3]]
|
|
458
|
+
|
|
459
|
+
The price to pay is that the enumeration order is now *graded
|
|
460
|
+
lexicographic* instead of lexicographic: first choose the value
|
|
461
|
+
according to the order specified by `L`, and use lexicographic
|
|
462
|
+
order within each value. Here is we reverse `L`::
|
|
463
|
+
|
|
464
|
+
sage: DisjointUnionEnumeratedSets(Family([3,2,0],
|
|
465
|
+
....: lambda n: IntegerListsLex(n, length=2))).list()
|
|
466
|
+
[[3, 0], [2, 1], [1, 2], [0, 3],
|
|
467
|
+
[2, 0], [1, 1], [0, 2],
|
|
468
|
+
[0, 0]]
|
|
469
|
+
|
|
470
|
+
Note that if a given value appears several times, the
|
|
471
|
+
corresponding elements will be enumerated several times, which
|
|
472
|
+
may, or not, be what one wants::
|
|
473
|
+
|
|
474
|
+
sage: DisjointUnionEnumeratedSets(Family([2,2],
|
|
475
|
+
....: lambda n: IntegerListsLex(n, length=2))).list()
|
|
476
|
+
[[2, 0], [1, 1], [0, 2], [2, 0], [1, 1], [0, 2]]
|
|
477
|
+
|
|
478
|
+
Here is a variant where we specify acceptable values for the
|
|
479
|
+
length::
|
|
480
|
+
|
|
481
|
+
sage: DisjointUnionEnumeratedSets(Family([0,1,3],
|
|
482
|
+
....: lambda l: IntegerListsLex(2, length=l))).list()
|
|
483
|
+
[[2],
|
|
484
|
+
[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]]
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
This technique can also be useful to obtain a proper enumeration
|
|
488
|
+
on infinite sets by using a graded lexicographic enumeration::
|
|
489
|
+
|
|
490
|
+
sage: C = DisjointUnionEnumeratedSets(Family(NN,
|
|
491
|
+
....: lambda n: IntegerListsLex(n, length=2)))
|
|
492
|
+
sage: C
|
|
493
|
+
Disjoint union of Lazy family (<lambda>(i))_{i in Non negative integer semiring}
|
|
494
|
+
sage: it = iter(C)
|
|
495
|
+
sage: [next(it) for i in range(10)]
|
|
496
|
+
[[0, 0],
|
|
497
|
+
[1, 0], [0, 1],
|
|
498
|
+
[2, 0], [1, 1], [0, 2],
|
|
499
|
+
[3, 0], [2, 1], [1, 2], [0, 3]]
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
.. RUBRIC:: Specifying how to construct elements
|
|
503
|
+
|
|
504
|
+
This is the list of all monomials of degree `4` which divide the
|
|
505
|
+
monomial `x^3y^1z^2` (a monomial being identified with its
|
|
506
|
+
exponent vector)::
|
|
507
|
+
|
|
508
|
+
sage: R.<x,y,z> = QQ[]
|
|
509
|
+
sage: m = [3,1,2]
|
|
510
|
+
sage: def term(exponents):
|
|
511
|
+
....: return x^exponents[0] * y^exponents[1] * z^exponents[2]
|
|
512
|
+
sage: list( IntegerListsLex(4, length=len(m), ceiling=m, element_constructor=term) )
|
|
513
|
+
[x^3*y, x^3*z, x^2*y*z, x^2*z^2, x*y*z^2]
|
|
514
|
+
|
|
515
|
+
Note the use of the ``element_constructor`` option to specify how
|
|
516
|
+
to construct elements from a plain list.
|
|
517
|
+
|
|
518
|
+
A variant is to specify a class for the elements. With the default
|
|
519
|
+
element constructor, this class should take as input the parent
|
|
520
|
+
``self`` and a list.
|
|
521
|
+
|
|
522
|
+
.. WARNING::
|
|
523
|
+
|
|
524
|
+
The protocol for specifying the element class and constructor
|
|
525
|
+
is subject to changes.
|
|
526
|
+
|
|
527
|
+
ALGORITHM:
|
|
528
|
+
|
|
529
|
+
The iteration algorithm uses a depth first search through the
|
|
530
|
+
prefix tree of the list of integers (see also
|
|
531
|
+
:ref:`section-generic-integerlistlex`). While doing so, it does
|
|
532
|
+
some lookahead heuristics to attempt to cut dead branches.
|
|
533
|
+
|
|
534
|
+
In most practical use cases, most dead branches are cut. Then,
|
|
535
|
+
roughly speaking, the time needed to iterate through all the
|
|
536
|
+
elements of `S` is proportional to the number of elements, where
|
|
537
|
+
the proportion factor is controlled by the length `l` of the
|
|
538
|
+
longest element of `S`. In addition, the memory usage is also
|
|
539
|
+
controlled by `l`, which is to say negligible in practice.
|
|
540
|
+
|
|
541
|
+
Still, there remains much room for efficiency improvements; see
|
|
542
|
+
:issue:`18055`, :issue:`18056`.
|
|
543
|
+
|
|
544
|
+
.. NOTE::
|
|
545
|
+
|
|
546
|
+
The generation algorithm could in principle be extended to
|
|
547
|
+
deal with non-constant slope constraints and with negative
|
|
548
|
+
parts.
|
|
549
|
+
|
|
550
|
+
TESTS:
|
|
551
|
+
|
|
552
|
+
This example from the combinatorics tutorial used to fail before
|
|
553
|
+
:issue:`17979` because the floor conditions did not satisfy the
|
|
554
|
+
slope conditions::
|
|
555
|
+
|
|
556
|
+
sage: I = IntegerListsLex(16, min_length=2, max_slope=-1, floor=[5,3,3])
|
|
557
|
+
sage: I.list()
|
|
558
|
+
[[13, 3], [12, 4], [11, 5], [10, 6], [9, 7], [9, 4, 3], [8, 5, 3], [8, 4, 3, 1],
|
|
559
|
+
[7, 6, 3], [7, 5, 4], [7, 5, 3, 1], [7, 4, 3, 2], [6, 5, 4, 1], [6, 5, 3, 2],
|
|
560
|
+
[6, 4, 3, 2, 1]]
|
|
561
|
+
|
|
562
|
+
::
|
|
563
|
+
|
|
564
|
+
sage: Partitions(2, max_slope=-1, length=2).list() # needs sage.combinat
|
|
565
|
+
[]
|
|
566
|
+
sage: list(IntegerListsLex(0, floor=ConstantFunction(1), min_slope=0))
|
|
567
|
+
[[]]
|
|
568
|
+
sage: list(IntegerListsLex(0, floor=ConstantFunction(1), min_slope=0, max_slope=0))
|
|
569
|
+
[[]]
|
|
570
|
+
sage: list(IntegerListsLex(0, max_length=0, floor=ConstantFunction(1), min_slope=0, max_slope=0))
|
|
571
|
+
[[]]
|
|
572
|
+
sage: list(IntegerListsLex(0, max_length=0, floor=ConstantFunction(0), min_slope=0, max_slope=0))
|
|
573
|
+
[[]]
|
|
574
|
+
sage: list(IntegerListsLex(0, min_part=1, min_slope=0))
|
|
575
|
+
[[]]
|
|
576
|
+
sage: list(IntegerListsLex(1, min_part=1, min_slope=0))
|
|
577
|
+
[[1]]
|
|
578
|
+
sage: list(IntegerListsLex(0, min_length=1, min_part=1, min_slope=0))
|
|
579
|
+
[]
|
|
580
|
+
sage: list(IntegerListsLex(0, min_length=1, min_slope=0))
|
|
581
|
+
[[0]]
|
|
582
|
+
sage: list(IntegerListsLex(3, max_length=2))
|
|
583
|
+
[[3], [2, 1], [1, 2], [0, 3]]
|
|
584
|
+
sage: partitions = {"min_part": 1, "max_slope": 0}
|
|
585
|
+
sage: partitions_min_2 = {"floor": ConstantFunction(2), "max_slope": 0}
|
|
586
|
+
sage: compositions = {"min_part": 1}
|
|
587
|
+
sage: integer_vectors = lambda l: {"length": l}
|
|
588
|
+
sage: lower_monomials = lambda c: {"length": c, "floor": lambda i: c[i]}
|
|
589
|
+
sage: upper_monomials = lambda c: {"length": c, "ceiling": lambda i: c[i]}
|
|
590
|
+
sage: constraints = { "min_part":1, "min_slope": -1, "max_slope": 0}
|
|
591
|
+
sage: list(IntegerListsLex(6, **partitions))
|
|
592
|
+
[[6],
|
|
593
|
+
[5, 1],
|
|
594
|
+
[4, 2],
|
|
595
|
+
[4, 1, 1],
|
|
596
|
+
[3, 3],
|
|
597
|
+
[3, 2, 1],
|
|
598
|
+
[3, 1, 1, 1],
|
|
599
|
+
[2, 2, 2],
|
|
600
|
+
[2, 2, 1, 1],
|
|
601
|
+
[2, 1, 1, 1, 1],
|
|
602
|
+
[1, 1, 1, 1, 1, 1]]
|
|
603
|
+
sage: list(IntegerListsLex(6, **constraints))
|
|
604
|
+
[[6],
|
|
605
|
+
[3, 3],
|
|
606
|
+
[3, 2, 1],
|
|
607
|
+
[2, 2, 2],
|
|
608
|
+
[2, 2, 1, 1],
|
|
609
|
+
[2, 1, 1, 1, 1],
|
|
610
|
+
[1, 1, 1, 1, 1, 1]]
|
|
611
|
+
sage: list(IntegerListsLex(1, **partitions_min_2))
|
|
612
|
+
[]
|
|
613
|
+
sage: list(IntegerListsLex(2, **partitions_min_2))
|
|
614
|
+
[[2]]
|
|
615
|
+
sage: list(IntegerListsLex(3, **partitions_min_2))
|
|
616
|
+
[[3]]
|
|
617
|
+
sage: list(IntegerListsLex(4, **partitions_min_2))
|
|
618
|
+
[[4], [2, 2]]
|
|
619
|
+
sage: list(IntegerListsLex(5, **partitions_min_2))
|
|
620
|
+
[[5], [3, 2]]
|
|
621
|
+
sage: list(IntegerListsLex(6, **partitions_min_2))
|
|
622
|
+
[[6], [4, 2], [3, 3], [2, 2, 2]]
|
|
623
|
+
sage: list(IntegerListsLex(7, **partitions_min_2))
|
|
624
|
+
[[7], [5, 2], [4, 3], [3, 2, 2]]
|
|
625
|
+
sage: list(IntegerListsLex(9, **partitions_min_2))
|
|
626
|
+
[[9], [7, 2], [6, 3], [5, 4], [5, 2, 2], [4, 3, 2], [3, 3, 3], [3, 2, 2, 2]]
|
|
627
|
+
sage: list(IntegerListsLex(10, **partitions_min_2))
|
|
628
|
+
[[10],
|
|
629
|
+
[8, 2],
|
|
630
|
+
[7, 3],
|
|
631
|
+
[6, 4],
|
|
632
|
+
[6, 2, 2],
|
|
633
|
+
[5, 5],
|
|
634
|
+
[5, 3, 2],
|
|
635
|
+
[4, 4, 2],
|
|
636
|
+
[4, 3, 3],
|
|
637
|
+
[4, 2, 2, 2],
|
|
638
|
+
[3, 3, 2, 2],
|
|
639
|
+
[2, 2, 2, 2, 2]]
|
|
640
|
+
sage: list(IntegerListsLex(4, **compositions))
|
|
641
|
+
[[4], [3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
|
|
642
|
+
sage: list(IntegerListsLex(6, min_length=1, floor=[7]))
|
|
643
|
+
[]
|
|
644
|
+
sage: L = IntegerListsLex(10**100,length=1)
|
|
645
|
+
sage: L.list()
|
|
646
|
+
[[10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]]
|
|
647
|
+
|
|
648
|
+
Noted on :issue:`17898`::
|
|
649
|
+
|
|
650
|
+
sage: list(IntegerListsLex(4, min_part=1, length=3, min_slope=1))
|
|
651
|
+
[]
|
|
652
|
+
sage: IntegerListsLex(6, ceiling=[4,2], floor=[3,3]).list()
|
|
653
|
+
[]
|
|
654
|
+
sage: IntegerListsLex(6, min_part=1, max_part=3, max_slope=-4).list()
|
|
655
|
+
[]
|
|
656
|
+
|
|
657
|
+
Noted in :issue:`17548`, which are now fixed::
|
|
658
|
+
|
|
659
|
+
sage: IntegerListsLex(10, min_part=2, max_slope=-1).list()
|
|
660
|
+
[[10], [8, 2], [7, 3], [6, 4], [5, 3, 2]]
|
|
661
|
+
sage: IntegerListsLex(5, min_slope=1, floor=[2,1,1], max_part=2).list()
|
|
662
|
+
[]
|
|
663
|
+
sage: IntegerListsLex(4, min_slope=0, max_slope=0).list()
|
|
664
|
+
[[4], [2, 2], [1, 1, 1, 1]]
|
|
665
|
+
sage: IntegerListsLex(6, min_slope=-1, max_slope=-1).list()
|
|
666
|
+
[[6], [3, 2, 1]]
|
|
667
|
+
sage: IntegerListsLex(6, min_length=3, max_length=2, min_part=1).list()
|
|
668
|
+
[]
|
|
669
|
+
sage: I = IntegerListsLex(3, max_length=2, min_part=1)
|
|
670
|
+
sage: I.list()
|
|
671
|
+
[[3], [2, 1], [1, 2]]
|
|
672
|
+
sage: [1,1,1] in I
|
|
673
|
+
False
|
|
674
|
+
sage: I = IntegerListsLex(10, ceiling=[4], max_length=1, min_part=1)
|
|
675
|
+
sage: I.list()
|
|
676
|
+
[]
|
|
677
|
+
sage: [4,6] in I
|
|
678
|
+
False
|
|
679
|
+
sage: I = IntegerListsLex(4, min_slope=1, min_part=1, max_part=2)
|
|
680
|
+
sage: I.list()
|
|
681
|
+
[]
|
|
682
|
+
sage: I = IntegerListsLex(7, min_slope=1, min_part=1, max_part=4)
|
|
683
|
+
sage: I.list()
|
|
684
|
+
[[3, 4], [1, 2, 4]]
|
|
685
|
+
sage: I = IntegerListsLex(4, floor=[2,1], ceiling=[2,2], max_length=2, min_slope=0)
|
|
686
|
+
sage: I.list()
|
|
687
|
+
[[2, 2]]
|
|
688
|
+
sage: I = IntegerListsLex(10, min_part=1, max_slope=-1)
|
|
689
|
+
sage: I.list()
|
|
690
|
+
[[10], [9, 1], [8, 2], [7, 3], [7, 2, 1], [6, 4], [6, 3, 1], [5, 4, 1],
|
|
691
|
+
[5, 3, 2], [4, 3, 2, 1]]
|
|
692
|
+
|
|
693
|
+
|
|
694
|
+
.. RUBRIC:: TESTS from comments on :issue:`17979`
|
|
695
|
+
|
|
696
|
+
Comment 191::
|
|
697
|
+
|
|
698
|
+
sage: list(IntegerListsLex(1, min_length=2, min_slope=0, max_slope=0))
|
|
699
|
+
[]
|
|
700
|
+
|
|
701
|
+
Comment 240::
|
|
702
|
+
|
|
703
|
+
sage: L = IntegerListsLex(min_length=2, max_part=0)
|
|
704
|
+
sage: L.list()
|
|
705
|
+
[[0, 0]]
|
|
706
|
+
|
|
707
|
+
.. RUBRIC:: Tests on the element constructor feature and mutability
|
|
708
|
+
|
|
709
|
+
Internally, the iterator works on a single list that is mutated
|
|
710
|
+
along the way. Therefore, you need to make sure that the
|
|
711
|
+
``element_constructor`` actually **copies** its input. This example
|
|
712
|
+
shows what can go wrong::
|
|
713
|
+
|
|
714
|
+
sage: P = IntegerListsLex(n=3, max_slope=0, min_part=1, element_constructor=lambda x: x)
|
|
715
|
+
sage: list(P)
|
|
716
|
+
[[], [], []]
|
|
717
|
+
|
|
718
|
+
However, specifying ``list()`` as constructor solves this problem::
|
|
719
|
+
|
|
720
|
+
sage: P = IntegerListsLex(n=3, max_slope=0, min_part=1, element_constructor=list)
|
|
721
|
+
sage: list(P)
|
|
722
|
+
[[3], [2, 1], [1, 1, 1]]
|
|
723
|
+
|
|
724
|
+
Same, step by step::
|
|
725
|
+
|
|
726
|
+
sage: it = iter(P)
|
|
727
|
+
sage: a = next(it); a
|
|
728
|
+
[3]
|
|
729
|
+
sage: b = next(it); b
|
|
730
|
+
[2, 1]
|
|
731
|
+
sage: a
|
|
732
|
+
[3]
|
|
733
|
+
sage: a is b
|
|
734
|
+
False
|
|
735
|
+
|
|
736
|
+
Tests from `MuPAD-Combinat <http://mupad-combinat.svn.sourceforge.net/viewvc/mupad-combinat/trunk/MuPAD-Combinat/lib/COMBINAT/TEST/MachineIntegerListsLex.tst>`_::
|
|
737
|
+
|
|
738
|
+
sage: IntegerListsLex(7, min_length=2, max_length=6, floor=[0,0,2,0,0,1], ceiling=[3,2,3,2,1,2]).cardinality()
|
|
739
|
+
83
|
|
740
|
+
sage: IntegerListsLex(7, min_length=2, max_length=6, floor=[0,0,2,0,1,1], ceiling=[3,2,3,2,1,2]).cardinality()
|
|
741
|
+
53
|
|
742
|
+
sage: IntegerListsLex(5, min_length=2, max_length=6, floor=[0,0,2,0,0,0], ceiling=[2,2,2,2,2,2]).cardinality()
|
|
743
|
+
30
|
|
744
|
+
sage: IntegerListsLex(5, min_length=2, max_length=6, floor=[0,0,1,1,0,0], ceiling=[2,2,2,2,2,2]).cardinality()
|
|
745
|
+
43
|
|
746
|
+
|
|
747
|
+
sage: IntegerListsLex(0, min_length=0, max_length=7, floor=[1,1,0,0,1,0], ceiling=[4,3,2,3,2,2,1]).first()
|
|
748
|
+
[]
|
|
749
|
+
|
|
750
|
+
sage: IntegerListsLex(0, min_length=1, max_length=7, floor=[0,1,0,0,1,0], ceiling=[4,3,2,3,2,2,1]).first()
|
|
751
|
+
[0]
|
|
752
|
+
sage: IntegerListsLex(0, min_length=1, max_length=7, floor=[1,1,0,0,1,0], ceiling=[4,3,2,3,2,2,1]).cardinality()
|
|
753
|
+
0
|
|
754
|
+
|
|
755
|
+
sage: IntegerListsLex(2, min_length=0, max_length=7, floor=[1,1,0,0,0,0], ceiling=[4,3,2,3,2,2,1]).first() # Was [1,1], due to slightly different specs
|
|
756
|
+
[2]
|
|
757
|
+
sage: IntegerListsLex(1, min_length=1, max_length=7, floor=[1,1,0,0,0,0], ceiling=[4,3,2,3,2,2,1]).first()
|
|
758
|
+
[1]
|
|
759
|
+
sage: IntegerListsLex(1, min_length=2, max_length=7, floor=[1,1,0,0,0,0], ceiling=[4,3,2,3,2,2,1]).cardinality()
|
|
760
|
+
0
|
|
761
|
+
sage: IntegerListsLex(2, min_length=5, max_length=7, floor=[1,1,0,0,0,0], ceiling=[4,3,2,3,2,2,1]).first()
|
|
762
|
+
[1, 1, 0, 0, 0]
|
|
763
|
+
sage: IntegerListsLex(2, min_length=5, max_length=7, floor=[1,1,0,0,0,1], ceiling=[4,3,2,3,2,2,1]).first()
|
|
764
|
+
[1, 1, 0, 0, 0]
|
|
765
|
+
sage: IntegerListsLex(2, min_length=5, max_length=7, floor=[1,1,0,0,1,0], ceiling=[4,3,2,3,2,2,1]).cardinality()
|
|
766
|
+
0
|
|
767
|
+
|
|
768
|
+
sage: IntegerListsLex(4, min_length=3, max_length=6, floor=[2, 1, 2, 1, 1, 1], ceiling=[3, 1, 2, 3, 2, 2]).cardinality()
|
|
769
|
+
0
|
|
770
|
+
sage: IntegerListsLex(5, min_length=3, max_length=6, floor=[2, 1, 2, 1, 1, 1], ceiling=[3, 1, 2, 3, 2, 2]).first()
|
|
771
|
+
[2, 1, 2]
|
|
772
|
+
sage: IntegerListsLex(6, min_length=3, max_length=6, floor=[2, 1, 2, 1, 1, 1], ceiling=[3, 1, 2, 3, 2, 2]).first()
|
|
773
|
+
[3, 1, 2]
|
|
774
|
+
sage: IntegerListsLex(12, min_length=3, max_length=6, floor=[2, 1, 2, 1, 1, 1], ceiling=[3, 1, 2, 3, 2, 2]).first()
|
|
775
|
+
[3, 1, 2, 3, 2, 1]
|
|
776
|
+
sage: IntegerListsLex(13, min_length=3, max_length=6, floor=[2, 1, 2, 1, 1, 1], ceiling=[3, 1, 2, 3, 2, 2]).first()
|
|
777
|
+
[3, 1, 2, 3, 2, 2]
|
|
778
|
+
sage: IntegerListsLex(14, min_length=3, max_length=6, floor=[2, 1, 2, 1, 1, 1], ceiling=[3, 1, 2, 3, 2, 2]).cardinality()
|
|
779
|
+
0
|
|
780
|
+
|
|
781
|
+
This used to hang (see comment 389 and fix in :meth:`Envelope.__init__`)::
|
|
782
|
+
|
|
783
|
+
sage: IntegerListsLex(7, max_part=0, ceiling=lambda i:i, check=False).list()
|
|
784
|
+
[]
|
|
785
|
+
"""
|
|
786
|
+
backend_class = IntegerListsBackend_invlex
|
|
787
|
+
|
|
788
|
+
@staticmethod
|
|
789
|
+
def __classcall_private__(cls, n=None, **kwargs):
|
|
790
|
+
r"""
|
|
791
|
+
Specifying a list or iterable as argument was deprecated in
|
|
792
|
+
:issue:`17979`. Please use ``DisjointUnionEnumeratedSets`` or
|
|
793
|
+
the ``min_sum`` and ``max_sum`` arguments instead.
|
|
794
|
+
"""
|
|
795
|
+
return typecall(cls, n=n, **kwargs)
|
|
796
|
+
|
|
797
|
+
|
|
798
|
+
cdef class IntegerListsBackend_invlex(IntegerListsBackend):
|
|
799
|
+
"""
|
|
800
|
+
Cython back-end of a set of lists of integers with specified
|
|
801
|
+
constraints enumerated in inverse lexicographic order.
|
|
802
|
+
"""
|
|
803
|
+
def __init__(self, *args, check=True, **kwds):
|
|
804
|
+
"""
|
|
805
|
+
Initialize ``self``.
|
|
806
|
+
|
|
807
|
+
TESTS::
|
|
808
|
+
|
|
809
|
+
sage: C = IntegerListsLex(2, length=3)
|
|
810
|
+
sage: C == loads(dumps(C))
|
|
811
|
+
True
|
|
812
|
+
sage: C.cardinality().parent() is ZZ
|
|
813
|
+
True
|
|
814
|
+
sage: TestSuite(C).run()
|
|
815
|
+
sage: IntegerListsLex(min_part=-1)
|
|
816
|
+
Traceback (most recent call last):
|
|
817
|
+
...
|
|
818
|
+
NotImplementedError: strictly negative min_part
|
|
819
|
+
"""
|
|
820
|
+
IntegerListsBackend.__init__(self, *args, **kwds)
|
|
821
|
+
|
|
822
|
+
self.check = check
|
|
823
|
+
|
|
824
|
+
if self.min_part < 0:
|
|
825
|
+
raise NotImplementedError("strictly negative min_part")
|
|
826
|
+
|
|
827
|
+
if self.check and (
|
|
828
|
+
self.floor.limit_start() == Infinity or
|
|
829
|
+
self.ceiling.limit_start() == Infinity):
|
|
830
|
+
from warnings import warn
|
|
831
|
+
warn("""
|
|
832
|
+
A function has been given as input of the floor=[...] or ceiling=[...]
|
|
833
|
+
arguments of IntegerListsLex. Please see the documentation for the caveats.
|
|
834
|
+
If you know what you are doing, you can set check=False to skip this warning.""")
|
|
835
|
+
|
|
836
|
+
@cached_method
|
|
837
|
+
def _check_finiteness(self):
|
|
838
|
+
"""
|
|
839
|
+
Check that the constraints define a finite set.
|
|
840
|
+
|
|
841
|
+
As mentioned in the description of this class, being finite is
|
|
842
|
+
almost equivalent to being inverse lexicographic iterable,
|
|
843
|
+
which is what we really care about.
|
|
844
|
+
|
|
845
|
+
This set is finite if and only if:
|
|
846
|
+
|
|
847
|
+
#. For each `i` such that there exists a list of length at
|
|
848
|
+
least `i+1` satisfying the constraints, there exists a
|
|
849
|
+
direct or indirect upper bound on the `i`-th part, that
|
|
850
|
+
is ``self.ceiling(i)`` is finite.
|
|
851
|
+
|
|
852
|
+
#. There exists a global upper bound on the length.
|
|
853
|
+
|
|
854
|
+
Failures for 1. are detected and reported later, during the
|
|
855
|
+
iteration, namely the first time a prefix including the `i`-th
|
|
856
|
+
part is explored.
|
|
857
|
+
|
|
858
|
+
This method therefore focuses on 2., namely trying to prove
|
|
859
|
+
the existence of an upper bound on the length. It may fail
|
|
860
|
+
to do so even when the set is actually finite.
|
|
861
|
+
|
|
862
|
+
OUTPUT:
|
|
863
|
+
|
|
864
|
+
``True`` if this method finds a proof that there
|
|
865
|
+
exists an upper bound on the length. Otherwise a
|
|
866
|
+
:exc:`ValueError` is raised.
|
|
867
|
+
|
|
868
|
+
Note that :func:`cached_method` does not work with methods
|
|
869
|
+
returning ``None``, so ``True`` is returned instead.
|
|
870
|
+
|
|
871
|
+
EXAMPLES::
|
|
872
|
+
|
|
873
|
+
sage: L = IntegerListsLex(4, max_length=4)
|
|
874
|
+
sage: L._check_finiteness()
|
|
875
|
+
True
|
|
876
|
+
|
|
877
|
+
The following example is infinite::
|
|
878
|
+
|
|
879
|
+
sage: L = IntegerListsLex(4)
|
|
880
|
+
sage: L._check_finiteness()
|
|
881
|
+
Traceback (most recent call last):
|
|
882
|
+
...
|
|
883
|
+
ValueError: could not prove that the specified constraints yield a finite set
|
|
884
|
+
|
|
885
|
+
Indeed::
|
|
886
|
+
|
|
887
|
+
sage: it = iter(IntegerListsLex(4, check=False))
|
|
888
|
+
sage: for _ in range(10): print(next(it))
|
|
889
|
+
[4]
|
|
890
|
+
[3, 1]
|
|
891
|
+
[3, 0, 1]
|
|
892
|
+
[3, 0, 0, 1]
|
|
893
|
+
[3, 0, 0, 0, 1]
|
|
894
|
+
[3, 0, 0, 0, 0, 1]
|
|
895
|
+
[3, 0, 0, 0, 0, 0, 1]
|
|
896
|
+
[3, 0, 0, 0, 0, 0, 0, 1]
|
|
897
|
+
[3, 0, 0, 0, 0, 0, 0, 0, 1]
|
|
898
|
+
[3, 0, 0, 0, 0, 0, 0, 0, 0, 1]
|
|
899
|
+
|
|
900
|
+
Unless ``check=False``, :meth:`_check_finiteness` is called as
|
|
901
|
+
soon as an iteration is attempted::
|
|
902
|
+
|
|
903
|
+
sage: iter(L)
|
|
904
|
+
Traceback (most recent call last):
|
|
905
|
+
...
|
|
906
|
+
ValueError: could not prove that the specified constraints yield a finite set
|
|
907
|
+
|
|
908
|
+
Some other infinite examples::
|
|
909
|
+
|
|
910
|
+
sage: L = IntegerListsLex(ceiling=[0], min_slope=1, max_slope=2)
|
|
911
|
+
sage: L.list()
|
|
912
|
+
Traceback (most recent call last):
|
|
913
|
+
...
|
|
914
|
+
ValueError: could not prove that the specified constraints yield a finite set
|
|
915
|
+
|
|
916
|
+
sage: L = IntegerListsLex(ceiling=[0], min_slope=1, max_slope=1)
|
|
917
|
+
sage: L.list()
|
|
918
|
+
Traceback (most recent call last):
|
|
919
|
+
...
|
|
920
|
+
ValueError: could not prove that the specified constraints yield a finite set
|
|
921
|
+
|
|
922
|
+
sage: IntegerListsLex(ceiling=[0], min_slope=1, max_slope=1).list()
|
|
923
|
+
Traceback (most recent call last):
|
|
924
|
+
...
|
|
925
|
+
ValueError: could not prove that the specified constraints yield a finite set
|
|
926
|
+
|
|
927
|
+
The following example is actually finite, but not detected as such::
|
|
928
|
+
|
|
929
|
+
sage: IntegerListsLex(7, floor=[4], max_part=4, min_slope=-1).list()
|
|
930
|
+
Traceback (most recent call last):
|
|
931
|
+
...
|
|
932
|
+
ValueError: could not prove that the specified constraints yield a finite set
|
|
933
|
+
|
|
934
|
+
This is sad because the following equivalent example works just fine::
|
|
935
|
+
|
|
936
|
+
sage: IntegerListsLex(7, floor=[4,3], max_part=4, min_slope=-1).list()
|
|
937
|
+
[[4, 3]]
|
|
938
|
+
|
|
939
|
+
Detecting this properly would require some deeper lookahead,
|
|
940
|
+
and the difficulty is to decide how far this lookahead should
|
|
941
|
+
search. Until this is fixed, one can disable the checks::
|
|
942
|
+
|
|
943
|
+
sage: IntegerListsLex(7, floor=[4], max_part=4, min_slope=-1, check=False).list()
|
|
944
|
+
[[4, 3]]
|
|
945
|
+
|
|
946
|
+
If the ceiling or floor is a function, it is much more likely
|
|
947
|
+
that a finite set will not be detected as such::
|
|
948
|
+
|
|
949
|
+
sage: IntegerListsLex(ceiling=lambda i: max(3-i,0))._check_finiteness()
|
|
950
|
+
Traceback (most recent call last):
|
|
951
|
+
...
|
|
952
|
+
ValueError: could not prove that the specified constraints yield a finite set
|
|
953
|
+
|
|
954
|
+
sage: IntegerListsLex(7, ceiling=lambda i:0).list()
|
|
955
|
+
Traceback (most recent call last):
|
|
956
|
+
...
|
|
957
|
+
ValueError: could not prove that the specified constraints yield a finite set
|
|
958
|
+
|
|
959
|
+
The next example shows a case that is finite because we remove
|
|
960
|
+
trailing zeroes::
|
|
961
|
+
|
|
962
|
+
sage: list(IntegerListsLex(ceiling=[0], max_slope=0))
|
|
963
|
+
[[]]
|
|
964
|
+
sage: L = IntegerListsLex(ceiling=[1], min_slope=1, max_slope=1)
|
|
965
|
+
sage: L.list()
|
|
966
|
+
Traceback (most recent call last):
|
|
967
|
+
...
|
|
968
|
+
ValueError: could not prove that the specified constraints yield a finite set
|
|
969
|
+
|
|
970
|
+
In the next examples, there is either no solution, or the region
|
|
971
|
+
is bounded::
|
|
972
|
+
|
|
973
|
+
sage: IntegerListsLex(min_sum=10, max_sum=5).list()
|
|
974
|
+
[]
|
|
975
|
+
sage: IntegerListsLex(max_part=1, min_slope=10).list()
|
|
976
|
+
[[1], []]
|
|
977
|
+
sage: IntegerListsLex(max_part=100, min_slope=10).first()
|
|
978
|
+
[100]
|
|
979
|
+
sage: IntegerListsLex(ceiling=[1,Infinity], max_part=2, min_slope=1).list()
|
|
980
|
+
[[1, 2], [1], [0, 2], [0, 1, 2], [0, 1], []]
|
|
981
|
+
sage: IntegerListsLex(min_sum=1, floor=[1,2], max_part=1).list()
|
|
982
|
+
[[1]]
|
|
983
|
+
|
|
984
|
+
sage: IntegerListsLex(min_length=2, max_length=1).list()
|
|
985
|
+
[]
|
|
986
|
+
sage: IntegerListsLex(min_length=-2, max_length=-1).list()
|
|
987
|
+
[]
|
|
988
|
+
sage: IntegerListsLex(min_length=-1, max_length=-2).list()
|
|
989
|
+
[]
|
|
990
|
+
sage: IntegerListsLex(min_length=2, max_slope=0, min_slope=1).list()
|
|
991
|
+
[]
|
|
992
|
+
sage: IntegerListsLex(min_part=2, max_part=1).list()
|
|
993
|
+
[[]]
|
|
994
|
+
|
|
995
|
+
sage: IntegerListsLex(floor=[0,2], ceiling=[3,1]).list()
|
|
996
|
+
[[3], [2], [1], []]
|
|
997
|
+
sage: IntegerListsLex(7, ceiling=[2], floor=[4]).list()
|
|
998
|
+
[]
|
|
999
|
+
sage: IntegerListsLex(7, max_part=0).list()
|
|
1000
|
+
[]
|
|
1001
|
+
sage: IntegerListsLex(5, max_part=0, min_slope=0).list()
|
|
1002
|
+
[]
|
|
1003
|
+
sage: IntegerListsLex(max_part=0).list()
|
|
1004
|
+
[[]]
|
|
1005
|
+
sage: IntegerListsLex(max_sum=1, min_sum=4, min_slope=0).list()
|
|
1006
|
+
[]
|
|
1007
|
+
"""
|
|
1008
|
+
# Trivial cases
|
|
1009
|
+
if self.max_length < Infinity:
|
|
1010
|
+
return True
|
|
1011
|
+
if self.max_sum < self.min_sum:
|
|
1012
|
+
return True
|
|
1013
|
+
if self.min_slope > self.max_slope:
|
|
1014
|
+
return True
|
|
1015
|
+
if self.max_slope < 0:
|
|
1016
|
+
return True
|
|
1017
|
+
if self.ceiling.limit() < self.floor.limit():
|
|
1018
|
+
return True
|
|
1019
|
+
if self.ceiling.limit() == 0:
|
|
1020
|
+
# This assumes no trailing zeroes
|
|
1021
|
+
return True
|
|
1022
|
+
if self.min_slope > 0 and self.ceiling.limit() < Infinity:
|
|
1023
|
+
return True
|
|
1024
|
+
|
|
1025
|
+
# Compute a lower bound on the sum of floor(i) for i=1 to infinity
|
|
1026
|
+
if self.floor.limit() > 0 or self.min_slope > 0:
|
|
1027
|
+
floor_sum_lower_bound = Infinity
|
|
1028
|
+
elif self.floor.limit_start() < Infinity:
|
|
1029
|
+
floor_sum_lower_bound = sum(self.floor(i) for i in range(self.floor.limit_start()))
|
|
1030
|
+
else:
|
|
1031
|
+
floor_sum_lower_bound = 0
|
|
1032
|
+
if floor_sum_lower_bound > 0 and self.min_slope >= 0:
|
|
1033
|
+
floor_sum_lower_bound = Infinity
|
|
1034
|
+
|
|
1035
|
+
if self.max_sum < floor_sum_lower_bound:
|
|
1036
|
+
return True
|
|
1037
|
+
if self.max_sum == floor_sum_lower_bound and self.max_sum < Infinity:
|
|
1038
|
+
# This assumes no trailing zeroes
|
|
1039
|
+
return True
|
|
1040
|
+
|
|
1041
|
+
# Variant on ceiling.limit() ==0 where we actually discover that the ceiling limit is 0
|
|
1042
|
+
if ( self.max_slope == 0 and
|
|
1043
|
+
(self.max_sum < Infinity or
|
|
1044
|
+
(self.ceiling.limit_start() < Infinity and
|
|
1045
|
+
any(self.ceiling(i) == 0 for i in range(self.ceiling.limit_start()+1)))
|
|
1046
|
+
) ):
|
|
1047
|
+
return True
|
|
1048
|
+
|
|
1049
|
+
limit_start = max(self.ceiling.limit_start(), self.floor.limit_start())
|
|
1050
|
+
if limit_start < Infinity:
|
|
1051
|
+
for i in range(limit_start+1):
|
|
1052
|
+
if self.ceiling(i) < self.floor(i):
|
|
1053
|
+
return True
|
|
1054
|
+
|
|
1055
|
+
raise ValueError("could not prove that the specified constraints yield a finite set")
|
|
1056
|
+
|
|
1057
|
+
def _iter(self):
|
|
1058
|
+
"""
|
|
1059
|
+
Return an iterator for the elements of ``self``.
|
|
1060
|
+
|
|
1061
|
+
EXAMPLES::
|
|
1062
|
+
|
|
1063
|
+
sage: C = IntegerListsLex(2, length=3)
|
|
1064
|
+
sage: list(C) # indirect doctest
|
|
1065
|
+
[[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]]
|
|
1066
|
+
"""
|
|
1067
|
+
if self.check:
|
|
1068
|
+
self._check_finiteness()
|
|
1069
|
+
return IntegerListsLexIter(self)
|
|
1070
|
+
|
|
1071
|
+
|
|
1072
|
+
# Constants for IntegerListsLexIter._next_state
|
|
1073
|
+
LOOKAHEAD = 5
|
|
1074
|
+
PUSH = 4
|
|
1075
|
+
ME = 3
|
|
1076
|
+
DECREASE = 2
|
|
1077
|
+
POP = 1
|
|
1078
|
+
STOP = 0
|
|
1079
|
+
|
|
1080
|
+
|
|
1081
|
+
class IntegerListsLexIter(builtins.object):
|
|
1082
|
+
r"""
|
|
1083
|
+
Iterator class for IntegerListsLex.
|
|
1084
|
+
|
|
1085
|
+
Let ``T`` be the prefix tree of all lists of nonnegative
|
|
1086
|
+
integers that satisfy all constraints except possibly for
|
|
1087
|
+
``min_length`` and ``min_sum``; let the children of a list
|
|
1088
|
+
be sorted decreasingly according to their last part.
|
|
1089
|
+
|
|
1090
|
+
The iterator is based on a depth-first search exploration of a
|
|
1091
|
+
subtree of this tree, trying to cut branches that do not
|
|
1092
|
+
contain a valid list. Each call of ``next`` iterates through
|
|
1093
|
+
the nodes of this tree until it finds a valid list to return.
|
|
1094
|
+
|
|
1095
|
+
Here are the attributes describing the current state of the
|
|
1096
|
+
iterator, and their invariants:
|
|
1097
|
+
|
|
1098
|
+
- ``backend`` -- the :class:`IntegerListsBackend` object this is
|
|
1099
|
+
iterating on;
|
|
1100
|
+
|
|
1101
|
+
- ``_current_list`` -- the list corresponding to the current
|
|
1102
|
+
node of the tree;
|
|
1103
|
+
|
|
1104
|
+
- ``_j`` -- the index of the last element of ``_current_list``:
|
|
1105
|
+
``self._j == len(self._current_list) - 1``;
|
|
1106
|
+
|
|
1107
|
+
- ``_current_sum`` -- the sum of the parts of ``_current_list``;
|
|
1108
|
+
|
|
1109
|
+
- ``_search_ranges`` -- list of same length as
|
|
1110
|
+
``_current_list``: the range for each part
|
|
1111
|
+
|
|
1112
|
+
Furthermore, we assume that there is no obvious contradiction
|
|
1113
|
+
in the constraints:
|
|
1114
|
+
|
|
1115
|
+
- ``self.backend.min_length <= self.backend.max_length``;
|
|
1116
|
+
- ``self.backend.min_slope <= self.backend.max_slope``
|
|
1117
|
+
unless ``self.backend.min_length <= 1``.
|
|
1118
|
+
|
|
1119
|
+
Along this iteration, ``next`` switches between the following
|
|
1120
|
+
states:
|
|
1121
|
+
|
|
1122
|
+
- LOOKAHEAD: determine whether the current list could be a
|
|
1123
|
+
prefix of a valid list;
|
|
1124
|
+
- PUSH: go deeper into the prefix tree by appending the
|
|
1125
|
+
largest possible part to the current list;
|
|
1126
|
+
- ME: check whether the current list is valid and if yes return it
|
|
1127
|
+
- DECREASE: decrease the last part;
|
|
1128
|
+
- POP: pop the last part of the current list;
|
|
1129
|
+
- STOP: the iteration is finished.
|
|
1130
|
+
|
|
1131
|
+
The attribute ``_next_state`` contains the next state ``next``
|
|
1132
|
+
should enter in.
|
|
1133
|
+
"""
|
|
1134
|
+
def __init__(self, backend):
|
|
1135
|
+
"""
|
|
1136
|
+
TESTS::
|
|
1137
|
+
|
|
1138
|
+
sage: from sage.combinat.integer_lists.invlex import IntegerListsLexIter
|
|
1139
|
+
sage: C = IntegerListsLex(2, length=3)
|
|
1140
|
+
sage: I = IntegerListsLexIter(C)
|
|
1141
|
+
sage: I._search_ranges
|
|
1142
|
+
[]
|
|
1143
|
+
sage: I._current_list
|
|
1144
|
+
[]
|
|
1145
|
+
sage: I._j
|
|
1146
|
+
-1
|
|
1147
|
+
sage: I._current_sum
|
|
1148
|
+
0
|
|
1149
|
+
"""
|
|
1150
|
+
self.backend = backend
|
|
1151
|
+
|
|
1152
|
+
self._search_ranges = []
|
|
1153
|
+
self._current_list = []
|
|
1154
|
+
self._j = -1 # index of last element of _current_list
|
|
1155
|
+
self._current_sum = 0 # sum of parts in _current_list
|
|
1156
|
+
|
|
1157
|
+
# Make sure that some invariants are respected in the iterator
|
|
1158
|
+
if (backend.min_length <= backend.max_length and
|
|
1159
|
+
(backend.min_slope <= backend.max_slope or backend.min_length <= 1)):
|
|
1160
|
+
self._next_state = PUSH
|
|
1161
|
+
else:
|
|
1162
|
+
self._next_state = STOP
|
|
1163
|
+
|
|
1164
|
+
def __iter__(self):
|
|
1165
|
+
"""
|
|
1166
|
+
Return ``self`` as per the iterator protocol.
|
|
1167
|
+
|
|
1168
|
+
EXAMPLES::
|
|
1169
|
+
|
|
1170
|
+
sage: from sage.combinat.integer_lists.invlex import IntegerListsLexIter
|
|
1171
|
+
sage: C = IntegerListsLex(2, length=3)
|
|
1172
|
+
sage: it = IntegerListsLexIter(C)
|
|
1173
|
+
sage: it.__iter__() is it
|
|
1174
|
+
True
|
|
1175
|
+
"""
|
|
1176
|
+
return self
|
|
1177
|
+
|
|
1178
|
+
def _push_search(self):
|
|
1179
|
+
"""
|
|
1180
|
+
Push search forward, resetting attributes.
|
|
1181
|
+
|
|
1182
|
+
The push may fail if it is discovered that
|
|
1183
|
+
``self._current_list`` cannot be extended in a valid way.
|
|
1184
|
+
|
|
1185
|
+
OUTPUT: boolean; whether the push succeeded
|
|
1186
|
+
|
|
1187
|
+
EXAMPLES::
|
|
1188
|
+
|
|
1189
|
+
sage: C = IntegerListsLex(2, length=3)
|
|
1190
|
+
sage: I = C._iter()
|
|
1191
|
+
sage: I._j
|
|
1192
|
+
-1
|
|
1193
|
+
sage: I._search_ranges
|
|
1194
|
+
[]
|
|
1195
|
+
sage: I._current_list
|
|
1196
|
+
[]
|
|
1197
|
+
sage: I._current_sum
|
|
1198
|
+
0
|
|
1199
|
+
sage: I._push_search()
|
|
1200
|
+
True
|
|
1201
|
+
sage: I._j
|
|
1202
|
+
0
|
|
1203
|
+
sage: I._search_ranges
|
|
1204
|
+
[(0, 2)]
|
|
1205
|
+
sage: I._current_list
|
|
1206
|
+
[2]
|
|
1207
|
+
sage: I._current_sum
|
|
1208
|
+
2
|
|
1209
|
+
sage: I._push_search()
|
|
1210
|
+
True
|
|
1211
|
+
sage: I._j
|
|
1212
|
+
1
|
|
1213
|
+
sage: I._search_ranges
|
|
1214
|
+
[(0, 2), (0, 0)]
|
|
1215
|
+
sage: I._current_list
|
|
1216
|
+
[2, 0]
|
|
1217
|
+
sage: I._current_sum
|
|
1218
|
+
2
|
|
1219
|
+
"""
|
|
1220
|
+
max_sum = self.backend.max_sum
|
|
1221
|
+
min_length = self.backend.min_length
|
|
1222
|
+
max_length = self.backend.max_length
|
|
1223
|
+
if self._j + 1 >= max_length:
|
|
1224
|
+
return False
|
|
1225
|
+
if self._j + 1 >= min_length and self._current_sum == max_sum:
|
|
1226
|
+
# Cannot add trailing zeroes
|
|
1227
|
+
return False
|
|
1228
|
+
|
|
1229
|
+
if self._j >= 0:
|
|
1230
|
+
prev = self._current_list[self._j]
|
|
1231
|
+
else:
|
|
1232
|
+
prev = None
|
|
1233
|
+
interval = self._m_interval(self._j+1, self.backend.max_sum - self._current_sum, prev)
|
|
1234
|
+
if interval[0] > interval[1]:
|
|
1235
|
+
return False
|
|
1236
|
+
|
|
1237
|
+
self._j += 1
|
|
1238
|
+
m = interval[1]
|
|
1239
|
+
self._search_ranges.append(interval)
|
|
1240
|
+
self._current_list.append(m)
|
|
1241
|
+
self._current_sum += m
|
|
1242
|
+
return True
|
|
1243
|
+
|
|
1244
|
+
def _pop_search(self):
|
|
1245
|
+
"""
|
|
1246
|
+
Go back in search tree. Resetting attributes.
|
|
1247
|
+
|
|
1248
|
+
EXAMPLES::
|
|
1249
|
+
|
|
1250
|
+
sage: C = IntegerListsLex(2, length=3)
|
|
1251
|
+
sage: I = C._iter()
|
|
1252
|
+
sage: I._push_search()
|
|
1253
|
+
True
|
|
1254
|
+
sage: I._j
|
|
1255
|
+
0
|
|
1256
|
+
sage: I._search_ranges
|
|
1257
|
+
[(0, 2)]
|
|
1258
|
+
sage: I._current_sum
|
|
1259
|
+
2
|
|
1260
|
+
sage: I._current_list
|
|
1261
|
+
[2]
|
|
1262
|
+
sage: I._pop_search()
|
|
1263
|
+
sage: I._j
|
|
1264
|
+
-1
|
|
1265
|
+
sage: I._search_ranges
|
|
1266
|
+
[]
|
|
1267
|
+
sage: I._current_sum
|
|
1268
|
+
0
|
|
1269
|
+
sage: I._current_list
|
|
1270
|
+
[]
|
|
1271
|
+
"""
|
|
1272
|
+
if self._j >= 0: # TODO: get rid of this condition
|
|
1273
|
+
self._j -= 1
|
|
1274
|
+
self._search_ranges.pop()
|
|
1275
|
+
self._current_sum -= self._current_list[-1]
|
|
1276
|
+
self._current_list.pop()
|
|
1277
|
+
|
|
1278
|
+
def __next__(self):
|
|
1279
|
+
r"""
|
|
1280
|
+
Return the next element in the iteration.
|
|
1281
|
+
|
|
1282
|
+
EXAMPLES::
|
|
1283
|
+
|
|
1284
|
+
sage: from sage.combinat.integer_lists.invlex import IntegerListsLexIter
|
|
1285
|
+
sage: C = IntegerListsLex(2, length=3)
|
|
1286
|
+
sage: I = IntegerListsLexIter(C)
|
|
1287
|
+
sage: next(I)
|
|
1288
|
+
[2, 0, 0]
|
|
1289
|
+
sage: next(I)
|
|
1290
|
+
[1, 1, 0]
|
|
1291
|
+
"""
|
|
1292
|
+
p = self.backend
|
|
1293
|
+
min_sum = p.min_sum
|
|
1294
|
+
max_length = p.max_length
|
|
1295
|
+
search_ranges = self._search_ranges
|
|
1296
|
+
|
|
1297
|
+
while True:
|
|
1298
|
+
assert self._j == len(self._current_list) - 1
|
|
1299
|
+
assert self._j == len(self._search_ranges) - 1
|
|
1300
|
+
|
|
1301
|
+
# LOOK AHEAD
|
|
1302
|
+
if self._next_state == LOOKAHEAD:
|
|
1303
|
+
if self._lookahead():
|
|
1304
|
+
self._next_state = PUSH
|
|
1305
|
+
else:
|
|
1306
|
+
# We should reuse information about the
|
|
1307
|
+
# reasons for this failure, to avoid when
|
|
1308
|
+
# possible retrying with smaller values.
|
|
1309
|
+
# We just do a special case for now:
|
|
1310
|
+
if self._j + 1 == max_length and self._current_sum < min_sum:
|
|
1311
|
+
self._next_state = POP
|
|
1312
|
+
else:
|
|
1313
|
+
self._next_state = DECREASE
|
|
1314
|
+
|
|
1315
|
+
# PUSH
|
|
1316
|
+
if self._next_state == PUSH:
|
|
1317
|
+
if self._push_search():
|
|
1318
|
+
self._next_state = LOOKAHEAD
|
|
1319
|
+
continue
|
|
1320
|
+
self._next_state = ME
|
|
1321
|
+
|
|
1322
|
+
# ME
|
|
1323
|
+
if self._next_state == ME:
|
|
1324
|
+
if self._j == -1:
|
|
1325
|
+
self._next_state = STOP
|
|
1326
|
+
else:
|
|
1327
|
+
self._next_state = DECREASE
|
|
1328
|
+
if self._internal_list_valid():
|
|
1329
|
+
return self._current_list
|
|
1330
|
+
|
|
1331
|
+
# DECREASE
|
|
1332
|
+
if self._next_state == DECREASE:
|
|
1333
|
+
self._current_list[-1] -= 1
|
|
1334
|
+
self._current_sum -= 1
|
|
1335
|
+
if self._current_list[-1] >= search_ranges[self._j][0]:
|
|
1336
|
+
self._next_state = LOOKAHEAD
|
|
1337
|
+
continue
|
|
1338
|
+
self._next_state = POP
|
|
1339
|
+
|
|
1340
|
+
# POP
|
|
1341
|
+
if self._next_state == POP:
|
|
1342
|
+
self._pop_search()
|
|
1343
|
+
self._next_state = ME
|
|
1344
|
+
continue
|
|
1345
|
+
|
|
1346
|
+
# STOP
|
|
1347
|
+
if self._next_state == STOP:
|
|
1348
|
+
raise StopIteration()
|
|
1349
|
+
|
|
1350
|
+
assert False
|
|
1351
|
+
|
|
1352
|
+
def _internal_list_valid(self):
|
|
1353
|
+
"""
|
|
1354
|
+
Return whether the current list in the iteration variable
|
|
1355
|
+
``self._current_list`` is a valid list.
|
|
1356
|
+
|
|
1357
|
+
This method checks whether the sum of the parts in
|
|
1358
|
+
``self._current_list`` is in the right range, whether its
|
|
1359
|
+
length is in the required range, and whether there are trailing
|
|
1360
|
+
zeroes. It does not check all of the necessary conditions to
|
|
1361
|
+
verify that an arbitrary list satisfies the constraints from
|
|
1362
|
+
the corresponding ``IntegerListsLex`` object, and should
|
|
1363
|
+
not be used except internally in the iterator class.
|
|
1364
|
+
|
|
1365
|
+
EXAMPLES::
|
|
1366
|
+
|
|
1367
|
+
sage: from sage.combinat.integer_lists.invlex import IntegerListsLexIter
|
|
1368
|
+
sage: C = IntegerListsLex(2, length=3)
|
|
1369
|
+
sage: I = IntegerListsLexIter(C)
|
|
1370
|
+
sage: I._current_list
|
|
1371
|
+
[]
|
|
1372
|
+
sage: I._internal_list_valid()
|
|
1373
|
+
False
|
|
1374
|
+
sage: next(I)
|
|
1375
|
+
[2, 0, 0]
|
|
1376
|
+
sage: I._current_list
|
|
1377
|
+
[2, 0, 0]
|
|
1378
|
+
sage: I._internal_list_valid()
|
|
1379
|
+
True
|
|
1380
|
+
"""
|
|
1381
|
+
p = self.backend
|
|
1382
|
+
mu = self._current_list
|
|
1383
|
+
nu = self._current_sum
|
|
1384
|
+
l = self._j + 1
|
|
1385
|
+
return (nu >= p.min_sum and nu <= p.max_sum # Good sum
|
|
1386
|
+
and l >= p.min_length and l <= p.max_length # Good length
|
|
1387
|
+
and (l <= max(p.min_length,0) or mu[-1] != 0)) # No trailing zeros
|
|
1388
|
+
|
|
1389
|
+
def _m_interval(self, i, max_sum, prev=None):
|
|
1390
|
+
r"""
|
|
1391
|
+
Return coarse lower and upper bounds for the part ``m``
|
|
1392
|
+
at position ``i``.
|
|
1393
|
+
|
|
1394
|
+
INPUT:
|
|
1395
|
+
|
|
1396
|
+
- ``i`` -- nonnegative integer (position)
|
|
1397
|
+
|
|
1398
|
+
- ``max_sum`` -- nonnegative integer or ``+oo``
|
|
1399
|
+
|
|
1400
|
+
- ``prev`` -- nonnegative integer or ``None``
|
|
1401
|
+
|
|
1402
|
+
Return coarse lower and upper bounds for the value ``m``
|
|
1403
|
+
of the part at position ``i`` so that there could exists
|
|
1404
|
+
some list suffix `v_i,\ldots,v_k` of sum bounded by
|
|
1405
|
+
``max_sum`` and satisfying the floor and upper bound
|
|
1406
|
+
constraints. If ``prev`` is specified, then the slope
|
|
1407
|
+
conditions between ``v[i-1]=prev`` and ``v[i]=m`` should
|
|
1408
|
+
also be satisfied.
|
|
1409
|
+
|
|
1410
|
+
Additionally, this raises an error if it can be detected
|
|
1411
|
+
that some part is neither directly nor indirectly bounded
|
|
1412
|
+
above, which implies that the constraints possibly do not
|
|
1413
|
+
allow for an inverse lexicographic iterator.
|
|
1414
|
+
|
|
1415
|
+
OUTPUT:
|
|
1416
|
+
|
|
1417
|
+
A tuple of two integers ``(lower_bound, upper_bound)``.
|
|
1418
|
+
|
|
1419
|
+
EXAMPLES::
|
|
1420
|
+
|
|
1421
|
+
sage: from sage.combinat.integer_lists.invlex import IntegerListsLexIter
|
|
1422
|
+
sage: C = IntegerListsLex(2, length=3)
|
|
1423
|
+
sage: I = IntegerListsLexIter(C)
|
|
1424
|
+
sage: I._m_interval(1,2)
|
|
1425
|
+
(0, 2)
|
|
1426
|
+
|
|
1427
|
+
The second part is not bounded above, hence we cannot
|
|
1428
|
+
iterate lexicographically through all the elements::
|
|
1429
|
+
|
|
1430
|
+
sage: IntegerListsLex(ceiling=[2,infinity,3], max_length=3).first()
|
|
1431
|
+
Traceback (most recent call last):
|
|
1432
|
+
...
|
|
1433
|
+
ValueError: infinite upper bound for values of m
|
|
1434
|
+
|
|
1435
|
+
Same here::
|
|
1436
|
+
|
|
1437
|
+
sage: IntegerListsLex(ceiling=[2,infinity,2], max_length=3, min_slope=-1).cardinality()
|
|
1438
|
+
Traceback (most recent call last):
|
|
1439
|
+
...
|
|
1440
|
+
ValueError: infinite upper bound for values of m
|
|
1441
|
+
|
|
1442
|
+
In the following examples however, all parts are
|
|
1443
|
+
indirectly bounded above::
|
|
1444
|
+
|
|
1445
|
+
sage: IntegerListsLex(ceiling=[2,infinity,2], length=3, min_slope=-1).cardinality()
|
|
1446
|
+
24
|
|
1447
|
+
sage: IntegerListsLex(ceiling=[2,infinity,2], max_length=3, max_slope=1).cardinality()
|
|
1448
|
+
24
|
|
1449
|
+
|
|
1450
|
+
sage: IntegerListsLex(max_part=2, max_length=3).cardinality()
|
|
1451
|
+
27
|
|
1452
|
+
sage: IntegerListsLex(3, max_length=3).cardinality() # parts bounded by n
|
|
1453
|
+
10
|
|
1454
|
+
sage: IntegerListsLex(max_length=0, min_length=1).list() # no part!
|
|
1455
|
+
[]
|
|
1456
|
+
sage: IntegerListsLex(length=0).list() # no part!
|
|
1457
|
+
[[]]
|
|
1458
|
+
"""
|
|
1459
|
+
p = self.backend
|
|
1460
|
+
|
|
1461
|
+
lower_bound = max(0, p.floor(i))
|
|
1462
|
+
upper_bound = min(max_sum, p.ceiling(i))
|
|
1463
|
+
if prev is not None:
|
|
1464
|
+
lower_bound = max(lower_bound, prev + p.min_slope)
|
|
1465
|
+
upper_bound = min(upper_bound, prev + p.max_slope)
|
|
1466
|
+
|
|
1467
|
+
## check for infinite upper bound, in case max_sum is infinite
|
|
1468
|
+
if p.check and upper_bound == Infinity:
|
|
1469
|
+
# This assumes that there exists a valid list (which
|
|
1470
|
+
# is not yet always guaranteed). Then we just
|
|
1471
|
+
# discovered that part 'i' of this list can be made as
|
|
1472
|
+
# large as desired, which implies that `self.backend`
|
|
1473
|
+
# cannot be iterated in inverse lexicographic order
|
|
1474
|
+
raise ValueError("infinite upper bound for values of m")
|
|
1475
|
+
|
|
1476
|
+
return (lower_bound, upper_bound)
|
|
1477
|
+
|
|
1478
|
+
def _lookahead(self):
|
|
1479
|
+
r"""
|
|
1480
|
+
Return whether the current list can possibly be a prefix
|
|
1481
|
+
of a valid list.
|
|
1482
|
+
|
|
1483
|
+
OUTPUT:
|
|
1484
|
+
|
|
1485
|
+
``False`` if it is guaranteed that the current list
|
|
1486
|
+
cannot be a prefix of a valid list and ``True`` otherwise.
|
|
1487
|
+
|
|
1488
|
+
EXAMPLES::
|
|
1489
|
+
|
|
1490
|
+
sage: it = IntegerListsLex(length=3, min_sum=2, max_sum=2)._iter()
|
|
1491
|
+
sage: it._current_list = [0,1] # don't do this at home, kids
|
|
1492
|
+
sage: it._current_sum = 1
|
|
1493
|
+
sage: it._j = 1
|
|
1494
|
+
sage: it._lookahead()
|
|
1495
|
+
True
|
|
1496
|
+
|
|
1497
|
+
sage: it = IntegerListsLex(length=3, min_sum=3, max_sum=2)._iter()
|
|
1498
|
+
sage: it._current_list = [0,1]
|
|
1499
|
+
sage: it._current_sum = 1
|
|
1500
|
+
sage: it._j = 1
|
|
1501
|
+
sage: it._lookahead()
|
|
1502
|
+
False
|
|
1503
|
+
|
|
1504
|
+
sage: it = IntegerListsLex(min_length=2, max_part=0)._iter()
|
|
1505
|
+
sage: it._current_list = [0]
|
|
1506
|
+
sage: it._current_sum = 0
|
|
1507
|
+
sage: it._j = 0
|
|
1508
|
+
sage: it._lookahead()
|
|
1509
|
+
True
|
|
1510
|
+
sage: it._current_list = [0, 0]
|
|
1511
|
+
sage: it._j = 1
|
|
1512
|
+
sage: it._lookahead()
|
|
1513
|
+
True
|
|
1514
|
+
sage: it._current_list = [0, 0, 0]
|
|
1515
|
+
sage: it._j = 2
|
|
1516
|
+
sage: it._lookahead()
|
|
1517
|
+
False
|
|
1518
|
+
|
|
1519
|
+
sage: n = 10**100
|
|
1520
|
+
sage: it = IntegerListsLex(n, length=1)._iter()
|
|
1521
|
+
sage: it._current_list = [n-1]
|
|
1522
|
+
sage: it._current_sum = n-1
|
|
1523
|
+
sage: it._j = 0
|
|
1524
|
+
sage: it._lookahead()
|
|
1525
|
+
False
|
|
1526
|
+
|
|
1527
|
+
sage: it = IntegerListsLex(n=3, min_part=2, min_sum=3, max_sum=3)._iter()
|
|
1528
|
+
sage: it._current_list = [2]
|
|
1529
|
+
sage: it._current_sum = 2
|
|
1530
|
+
sage: it._j = 0
|
|
1531
|
+
sage: it._lookahead()
|
|
1532
|
+
False
|
|
1533
|
+
|
|
1534
|
+
ALGORITHM:
|
|
1535
|
+
|
|
1536
|
+
Let ``j = self._j`` be the position of the last part `m` of
|
|
1537
|
+
``self._current_list``. The current algorithm computes,
|
|
1538
|
+
for `k = j, j+1, \ldots`, a lower bound `l_k` and an upper
|
|
1539
|
+
bound `u_k` for `v_0+\dots+v_k`, and stops if none of the
|
|
1540
|
+
intervals `[l_k, u_k]` intersect ``[min_sum, max_sum]``.
|
|
1541
|
+
|
|
1542
|
+
The lower bound `l_k` is given by the area below
|
|
1543
|
+
`v_0,\dots,v_{j-1}` prolongated by the lower envelope
|
|
1544
|
+
between `j` and `k` and starting at `m`. The upper bound
|
|
1545
|
+
`u_k` is given similarly using the upper envelope.
|
|
1546
|
+
|
|
1547
|
+
The complexity of this algorithm is bounded above by
|
|
1548
|
+
``O(max_length)``. When ``max_length=oo``, the algorithm
|
|
1549
|
+
is guaranteed to terminate, unless ``floor`` is a function
|
|
1550
|
+
which is eventually constant with value `0`, or which
|
|
1551
|
+
reaches the value `0` while ``max_slope=0``.
|
|
1552
|
+
|
|
1553
|
+
Indeed, the lower bound `l_k` is increasing with `k`; in
|
|
1554
|
+
fact it is strictly increasing, unless the local lower bound
|
|
1555
|
+
at `k` is `0`. Furthermore as soon as ``l_k >= min_sum``,
|
|
1556
|
+
we can conclude; we can also conclude if we know that the
|
|
1557
|
+
floor is eventually constant with value `0`, or there is a
|
|
1558
|
+
local lower bound at `k` is `0` and ``max_slope=0``.
|
|
1559
|
+
|
|
1560
|
+
.. RUBRIC:: Room for improvement
|
|
1561
|
+
|
|
1562
|
+
Improved prediction: the lower bound `l_k` does not take
|
|
1563
|
+
the slope conditions into account, except for those imposed
|
|
1564
|
+
by the value `m` at `j`. Similarly for `u_k`.
|
|
1565
|
+
|
|
1566
|
+
Improved speed: given that `l_k` is increasing with `k`,
|
|
1567
|
+
possibly some dichotomy could be used to search for `k`,
|
|
1568
|
+
with appropriate caching / fast calculation of the partial
|
|
1569
|
+
sums. Also, some of the information gained at depth `j`
|
|
1570
|
+
could be reused at depth `j+1`.
|
|
1571
|
+
|
|
1572
|
+
TESTS::
|
|
1573
|
+
|
|
1574
|
+
sage: it = IntegerListsLex(1, min_length=2, min_slope=0, max_slope=0, min_sum=1, max_sum=1)._iter()
|
|
1575
|
+
sage: it._current_list = [0]
|
|
1576
|
+
sage: it._current_sum = 0
|
|
1577
|
+
sage: it._j = 0
|
|
1578
|
+
sage: it._lookahead()
|
|
1579
|
+
False
|
|
1580
|
+
"""
|
|
1581
|
+
# Check code for various termination conditions. Possible cases:
|
|
1582
|
+
# 0. interval [lower, upper] intersects interval [min_sum, max_sum] -- terminate True
|
|
1583
|
+
# 1. lower sum surpasses max_sum -- terminate False
|
|
1584
|
+
# 2. iteration surpasses max_length -- terminate False
|
|
1585
|
+
# 3. upper envelope is smaller than lower envelope -- terminate False
|
|
1586
|
+
# 4. max_slope <= 0 -- terminate False after upper passes 0
|
|
1587
|
+
# 5. ceiling_limit == 0 -- terminate False after reaching larger limit point
|
|
1588
|
+
# 6. (uncomputable) ceiling function == 0 for all but finitely many input values -- terminate False after reaching (unknown) limit point -- currently hangs
|
|
1589
|
+
|
|
1590
|
+
m = self._current_list[-1]
|
|
1591
|
+
j = self._j
|
|
1592
|
+
min_sum = self.backend.min_sum - (self._current_sum-m)
|
|
1593
|
+
max_sum = self.backend.max_sum - (self._current_sum-m)
|
|
1594
|
+
|
|
1595
|
+
if min_sum > max_sum:
|
|
1596
|
+
return False
|
|
1597
|
+
|
|
1598
|
+
p = self.backend
|
|
1599
|
+
|
|
1600
|
+
# Beware that without slope conditions, the functions below
|
|
1601
|
+
# currently forget about the value m at k!
|
|
1602
|
+
lower_envelope = self.backend.floor.adapt(m,j)
|
|
1603
|
+
upper_envelope = self.backend.ceiling.adapt(m,j)
|
|
1604
|
+
lower = 0 # The lower bound `l_k`
|
|
1605
|
+
upper = 0 # The upper bound `u_k`
|
|
1606
|
+
|
|
1607
|
+
assert j >= 0
|
|
1608
|
+
# get to smallest valid number of parts
|
|
1609
|
+
for k in range(j, p.min_length-1):
|
|
1610
|
+
# We are looking at lists `v_j,...,v_k`
|
|
1611
|
+
lo = m if k == j else lower_envelope(k)
|
|
1612
|
+
up = m if k == j else upper_envelope(k)
|
|
1613
|
+
if lo > up:
|
|
1614
|
+
return False
|
|
1615
|
+
lower += lo
|
|
1616
|
+
upper += up
|
|
1617
|
+
|
|
1618
|
+
if j < p.min_length and min_sum <= upper and lower <= max_sum:
|
|
1619
|
+
# There could exist a valid list `v_j,\dots,v_{min_length-1}`
|
|
1620
|
+
return True
|
|
1621
|
+
|
|
1622
|
+
k = max(p.min_length-1,j)
|
|
1623
|
+
# Check if any of the intervals intersect the target interval
|
|
1624
|
+
while k < p.max_length:
|
|
1625
|
+
lo = m if k == j else lower_envelope(k)
|
|
1626
|
+
up = m if k == j else upper_envelope(k)
|
|
1627
|
+
if lo > up:
|
|
1628
|
+
# There exists no valid list of length >= k
|
|
1629
|
+
return False
|
|
1630
|
+
lower += lo
|
|
1631
|
+
upper += up
|
|
1632
|
+
assert lower <= upper
|
|
1633
|
+
|
|
1634
|
+
if lower > max_sum:
|
|
1635
|
+
# There cannot exist a valid list `v_j,\dots,v_l` with l>=k
|
|
1636
|
+
return False
|
|
1637
|
+
|
|
1638
|
+
if ( (p.max_slope <= 0 and up <= 0)
|
|
1639
|
+
or (p.ceiling.limit() == 0 and k > p.ceiling.limit_start()) ):
|
|
1640
|
+
# This implies v_l=0 for l>=k: that is we would be generating
|
|
1641
|
+
# a list with trailing zeroes
|
|
1642
|
+
return False
|
|
1643
|
+
|
|
1644
|
+
if min_sum <= upper and lower <= max_sum:
|
|
1645
|
+
# There could exist a valid list `v_j,\dots,v_k`
|
|
1646
|
+
return True
|
|
1647
|
+
|
|
1648
|
+
k += 1
|
|
1649
|
+
|
|
1650
|
+
return False
|