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
sage/sets/family.pyx
ADDED
|
@@ -0,0 +1,1556 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
r"""
|
|
3
|
+
Families
|
|
4
|
+
|
|
5
|
+
A Family is an associative container which models a family
|
|
6
|
+
`(f_i)_{i \in I}`. Then, ``f[i]`` returns the element of the family indexed by
|
|
7
|
+
``i``. Whenever available, set and combinatorial class operations (counting,
|
|
8
|
+
iteration, listing) on the family are induced from those of the index
|
|
9
|
+
set. Families should be created through the :func:`Family` function.
|
|
10
|
+
|
|
11
|
+
AUTHORS:
|
|
12
|
+
|
|
13
|
+
- Nicolas Thiery (2008-02): initial release
|
|
14
|
+
|
|
15
|
+
- Florent Hivert (2008-04): various fixes, cleanups and improvements.
|
|
16
|
+
|
|
17
|
+
TESTS:
|
|
18
|
+
|
|
19
|
+
Check :issue:`12482` (shall be run in a fresh session)::
|
|
20
|
+
|
|
21
|
+
sage: P = Partitions(3)
|
|
22
|
+
sage: Family(P, lambda x: x).category()
|
|
23
|
+
Category of finite enumerated sets
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
# *****************************************************************************
|
|
27
|
+
# Copyright (C) 2008-2017 Nicolas Thiery <nthiery at users.sf.net>
|
|
28
|
+
# 2008-2009 Mike Hansen <mhansen@gmail.com>
|
|
29
|
+
# 2008-2010 Florent Hivert <Florent.Hivert@univ-rouen.fr>
|
|
30
|
+
# 2013-2021 Travis Scrimshaw
|
|
31
|
+
# 2014 Nathann Cohen
|
|
32
|
+
# 2017 Erik M. Bray
|
|
33
|
+
# 2018 Frédéric Chapoton
|
|
34
|
+
# 2019 Markus Wageringel
|
|
35
|
+
# 2022-2023 Matthias Koeppe
|
|
36
|
+
#
|
|
37
|
+
# This program is free software: you can redistribute it and/or modify
|
|
38
|
+
# it under the terms of the GNU General Public License as published by
|
|
39
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
40
|
+
# (at your option) any later version.
|
|
41
|
+
# https://www.gnu.org/licenses/
|
|
42
|
+
# ****************************************************************************
|
|
43
|
+
import types
|
|
44
|
+
from copy import copy
|
|
45
|
+
from pprint import pformat, saferepr
|
|
46
|
+
from collections.abc import Iterable
|
|
47
|
+
|
|
48
|
+
from sage.categories.enumerated_sets import EnumeratedSets
|
|
49
|
+
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
|
|
50
|
+
from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
|
|
51
|
+
from sage.misc.cachefunc import cached_method
|
|
52
|
+
from sage.misc.call import AttrCallObject
|
|
53
|
+
from sage.rings.infinity import Infinity
|
|
54
|
+
from sage.rings.integer import Integer
|
|
55
|
+
from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
|
|
56
|
+
from sage.sets.non_negative_integers import NonNegativeIntegers
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def Family(indices, function=None, hidden_keys=[], hidden_function=None, lazy=False, name=None):
|
|
60
|
+
r"""
|
|
61
|
+
A Family is an associative container which models a family
|
|
62
|
+
`(f_i)_{i \in I}`. Then, ``f[i]`` returns the element of the family
|
|
63
|
+
indexed by `i`. Whenever available, set and combinatorial class
|
|
64
|
+
operations (counting, iteration, listing) on the family are induced
|
|
65
|
+
from those of the index set.
|
|
66
|
+
|
|
67
|
+
There are several available implementations (classes) for different
|
|
68
|
+
usages; Family serves as a factory, and will create instances of
|
|
69
|
+
the appropriate classes depending on its arguments.
|
|
70
|
+
|
|
71
|
+
INPUT:
|
|
72
|
+
|
|
73
|
+
- ``indices`` -- the indices for the family
|
|
74
|
+
- ``function`` -- (optional) the function `f` applied to all visible
|
|
75
|
+
indices; the default is the identity function
|
|
76
|
+
- ``hidden_keys`` -- (optional) a list of hidden indices that can be
|
|
77
|
+
accessed through ``my_family[i]``
|
|
78
|
+
- ``hidden_function`` -- (optional) a function for the hidden indices
|
|
79
|
+
- ``lazy`` -- boolean (default: ``False``); whether the family is lazily
|
|
80
|
+
created or not; if the indices are infinite, then this is automatically
|
|
81
|
+
made ``True``
|
|
82
|
+
- ``name`` -- (optional) the name of the function; only used when the
|
|
83
|
+
family is lazily created via a function
|
|
84
|
+
|
|
85
|
+
EXAMPLES:
|
|
86
|
+
|
|
87
|
+
In its simplest form, a list `l = [l_0, l_1, \ldots, l_{\ell}]` or a
|
|
88
|
+
tuple by itself is considered as the family `(l_i)_{i \in I}` where
|
|
89
|
+
`I` is the set `\{0, \ldots, \ell\}` where `\ell` is ``len(l) - 1``.
|
|
90
|
+
So ``Family(l)`` returns the corresponding family::
|
|
91
|
+
|
|
92
|
+
sage: f = Family([1,2,3])
|
|
93
|
+
sage: f
|
|
94
|
+
Family (1, 2, 3)
|
|
95
|
+
sage: f = Family((1,2,3))
|
|
96
|
+
sage: f
|
|
97
|
+
Family (1, 2, 3)
|
|
98
|
+
|
|
99
|
+
Instead of a list you can as well pass any iterable object::
|
|
100
|
+
|
|
101
|
+
sage: f = Family(2*i+1 for i in [1,2,3])
|
|
102
|
+
sage: f
|
|
103
|
+
Family (3, 5, 7)
|
|
104
|
+
|
|
105
|
+
A family can also be constructed from a dictionary ``t``. The resulting
|
|
106
|
+
family is very close to ``t``, except that the elements of the family
|
|
107
|
+
are the values of ``t``. Here, we define the family
|
|
108
|
+
`(f_i)_{i \in \{3,4,7\}}` with `f_3 = a`, `f_4 = b`, and `f_7 = d`::
|
|
109
|
+
|
|
110
|
+
sage: f = Family({3: 'a', 4: 'b', 7: 'd'})
|
|
111
|
+
sage: f
|
|
112
|
+
Finite family {3: 'a', 4: 'b', 7: 'd'}
|
|
113
|
+
sage: f[7]
|
|
114
|
+
'd'
|
|
115
|
+
sage: len(f)
|
|
116
|
+
3
|
|
117
|
+
sage: list(f)
|
|
118
|
+
['a', 'b', 'd']
|
|
119
|
+
sage: [ x for x in f ]
|
|
120
|
+
['a', 'b', 'd']
|
|
121
|
+
sage: f.keys()
|
|
122
|
+
[3, 4, 7]
|
|
123
|
+
sage: 'b' in f
|
|
124
|
+
True
|
|
125
|
+
sage: 'e' in f
|
|
126
|
+
False
|
|
127
|
+
|
|
128
|
+
A family can also be constructed by its index set `I` and
|
|
129
|
+
a function `f`, as in `(f(i))_{i \in I}`::
|
|
130
|
+
|
|
131
|
+
sage: f = Family([3,4,7], lambda i: 2*i)
|
|
132
|
+
sage: f
|
|
133
|
+
Finite family {3: 6, 4: 8, 7: 14}
|
|
134
|
+
sage: f.keys()
|
|
135
|
+
[3, 4, 7]
|
|
136
|
+
sage: f[7]
|
|
137
|
+
14
|
|
138
|
+
sage: list(f)
|
|
139
|
+
[6, 8, 14]
|
|
140
|
+
sage: [x for x in f]
|
|
141
|
+
[6, 8, 14]
|
|
142
|
+
sage: len(f)
|
|
143
|
+
3
|
|
144
|
+
|
|
145
|
+
By default, all images are computed right away, and stored in an internal
|
|
146
|
+
dictionary::
|
|
147
|
+
|
|
148
|
+
sage: f = Family((3,4,7), lambda i: 2*i)
|
|
149
|
+
sage: f
|
|
150
|
+
Finite family {3: 6, 4: 8, 7: 14}
|
|
151
|
+
|
|
152
|
+
Note that this requires all the elements of the list to be
|
|
153
|
+
hashable. One can ask instead for the images `f(i)` to be computed
|
|
154
|
+
lazily, when needed::
|
|
155
|
+
|
|
156
|
+
sage: f = Family([3,4,7], lambda i: 2*i, lazy=True)
|
|
157
|
+
sage: f
|
|
158
|
+
Lazy family (<lambda>(i))_{i in [3, 4, 7]}
|
|
159
|
+
sage: f[7]
|
|
160
|
+
14
|
|
161
|
+
sage: list(f)
|
|
162
|
+
[6, 8, 14]
|
|
163
|
+
sage: [x for x in f]
|
|
164
|
+
[6, 8, 14]
|
|
165
|
+
|
|
166
|
+
This allows in particular for modeling infinite families::
|
|
167
|
+
|
|
168
|
+
sage: f = Family(ZZ, lambda i: 2*i, lazy=True)
|
|
169
|
+
sage: f
|
|
170
|
+
Lazy family (<lambda>(i))_{i in Integer Ring}
|
|
171
|
+
sage: f.keys()
|
|
172
|
+
Integer Ring
|
|
173
|
+
sage: f[1]
|
|
174
|
+
2
|
|
175
|
+
sage: f[-5]
|
|
176
|
+
-10
|
|
177
|
+
sage: i = iter(f)
|
|
178
|
+
sage: next(i), next(i), next(i), next(i), next(i)
|
|
179
|
+
(0, 2, -2, 4, -4)
|
|
180
|
+
|
|
181
|
+
Note that the ``lazy`` keyword parameter is only needed to force
|
|
182
|
+
laziness. Usually it is automatically set to a correct default value (ie:
|
|
183
|
+
``False`` for finite data structures and ``True`` for enumerated sets::
|
|
184
|
+
|
|
185
|
+
sage: f == Family(ZZ, lambda i: 2*i)
|
|
186
|
+
True
|
|
187
|
+
|
|
188
|
+
Beware that for those kind of families len(f) is not supposed to
|
|
189
|
+
work. As a replacement, use the .cardinality() method::
|
|
190
|
+
|
|
191
|
+
sage: f = Family(Permutations(3), attrcall("to_lehmer_code"))
|
|
192
|
+
sage: list(f)
|
|
193
|
+
[[0, 0, 0], [0, 1, 0], [1, 0, 0], [1, 1, 0], [2, 0, 0], [2, 1, 0]]
|
|
194
|
+
sage: f.cardinality()
|
|
195
|
+
6
|
|
196
|
+
|
|
197
|
+
Caveat: Only certain families with lazy behavior can be pickled. In
|
|
198
|
+
particular, only functions that work with Sage's pickle_function
|
|
199
|
+
and unpickle_function (in sage.misc.fpickle) will correctly
|
|
200
|
+
unpickle. The following two work::
|
|
201
|
+
|
|
202
|
+
sage: f = Family(Permutations(3), lambda p: p.to_lehmer_code()); f
|
|
203
|
+
Lazy family (<lambda>(i))_{i in Standard permutations of 3}
|
|
204
|
+
sage: f == loads(dumps(f))
|
|
205
|
+
True
|
|
206
|
+
|
|
207
|
+
sage: f = Family(Permutations(3), attrcall("to_lehmer_code")); f
|
|
208
|
+
Lazy family (i.to_lehmer_code())_{i in Standard permutations of 3}
|
|
209
|
+
sage: f == loads(dumps(f))
|
|
210
|
+
True
|
|
211
|
+
|
|
212
|
+
But this one does not::
|
|
213
|
+
|
|
214
|
+
sage: def plus_n(n): return lambda x: x+n
|
|
215
|
+
sage: f = Family([1,2,3], plus_n(3), lazy=True); f
|
|
216
|
+
Lazy family (<lambda>(i))_{i in [1, 2, 3]}
|
|
217
|
+
sage: f == loads(dumps(f))
|
|
218
|
+
Traceback (most recent call last):
|
|
219
|
+
...
|
|
220
|
+
ValueError: Cannot pickle code objects from closures
|
|
221
|
+
|
|
222
|
+
Finally, it can occasionally be useful to add some hidden elements
|
|
223
|
+
in a family, which are accessible as ``f[i]``, but do not appear in the
|
|
224
|
+
keys or the container operations::
|
|
225
|
+
|
|
226
|
+
sage: f = Family([3,4,7], lambda i: 2*i, hidden_keys=[2])
|
|
227
|
+
sage: f
|
|
228
|
+
Finite family {3: 6, 4: 8, 7: 14}
|
|
229
|
+
sage: f.keys()
|
|
230
|
+
[3, 4, 7]
|
|
231
|
+
sage: f.hidden_keys()
|
|
232
|
+
[2]
|
|
233
|
+
sage: f[7]
|
|
234
|
+
14
|
|
235
|
+
sage: f[2]
|
|
236
|
+
4
|
|
237
|
+
sage: list(f)
|
|
238
|
+
[6, 8, 14]
|
|
239
|
+
sage: [x for x in f]
|
|
240
|
+
[6, 8, 14]
|
|
241
|
+
sage: len(f)
|
|
242
|
+
3
|
|
243
|
+
|
|
244
|
+
The following example illustrates when the function is actually
|
|
245
|
+
called::
|
|
246
|
+
|
|
247
|
+
sage: def compute_value(i):
|
|
248
|
+
....: print('computing 2*'+str(i))
|
|
249
|
+
....: return 2*i
|
|
250
|
+
sage: f = Family([3,4,7], compute_value, hidden_keys=[2])
|
|
251
|
+
computing 2*3
|
|
252
|
+
computing 2*4
|
|
253
|
+
computing 2*7
|
|
254
|
+
sage: f
|
|
255
|
+
Finite family {3: 6, 4: 8, 7: 14}
|
|
256
|
+
sage: f.keys()
|
|
257
|
+
[3, 4, 7]
|
|
258
|
+
sage: f.hidden_keys()
|
|
259
|
+
[2]
|
|
260
|
+
sage: f[7]
|
|
261
|
+
14
|
|
262
|
+
sage: f[2]
|
|
263
|
+
computing 2*2
|
|
264
|
+
4
|
|
265
|
+
sage: f[2]
|
|
266
|
+
4
|
|
267
|
+
sage: list(f)
|
|
268
|
+
[6, 8, 14]
|
|
269
|
+
sage: [x for x in f]
|
|
270
|
+
[6, 8, 14]
|
|
271
|
+
sage: len(f)
|
|
272
|
+
3
|
|
273
|
+
|
|
274
|
+
Here is a close variant where the function for the hidden keys is
|
|
275
|
+
different from that for the other keys::
|
|
276
|
+
|
|
277
|
+
sage: f = Family([3,4,7], lambda i: 2*i, hidden_keys=[2], hidden_function = lambda i: 3*i)
|
|
278
|
+
sage: f
|
|
279
|
+
Finite family {3: 6, 4: 8, 7: 14}
|
|
280
|
+
sage: f.keys()
|
|
281
|
+
[3, 4, 7]
|
|
282
|
+
sage: f.hidden_keys()
|
|
283
|
+
[2]
|
|
284
|
+
sage: f[7]
|
|
285
|
+
14
|
|
286
|
+
sage: f[2]
|
|
287
|
+
6
|
|
288
|
+
sage: list(f)
|
|
289
|
+
[6, 8, 14]
|
|
290
|
+
sage: [x for x in f]
|
|
291
|
+
[6, 8, 14]
|
|
292
|
+
sage: len(f)
|
|
293
|
+
3
|
|
294
|
+
|
|
295
|
+
Family accept finite and infinite EnumeratedSets as input::
|
|
296
|
+
|
|
297
|
+
sage: f = Family(FiniteEnumeratedSet([1,2,3]))
|
|
298
|
+
sage: f
|
|
299
|
+
Family (1, 2, 3)
|
|
300
|
+
sage: f = Family(NonNegativeIntegers())
|
|
301
|
+
sage: f
|
|
302
|
+
Family (Non negative integers)
|
|
303
|
+
|
|
304
|
+
::
|
|
305
|
+
|
|
306
|
+
sage: f = Family(FiniteEnumeratedSet([3,4,7]), lambda i: 2*i)
|
|
307
|
+
sage: f
|
|
308
|
+
Finite family {3: 6, 4: 8, 7: 14}
|
|
309
|
+
sage: f.keys()
|
|
310
|
+
{3, 4, 7}
|
|
311
|
+
sage: f[7]
|
|
312
|
+
14
|
|
313
|
+
sage: list(f)
|
|
314
|
+
[6, 8, 14]
|
|
315
|
+
sage: [x for x in f]
|
|
316
|
+
[6, 8, 14]
|
|
317
|
+
sage: len(f)
|
|
318
|
+
3
|
|
319
|
+
|
|
320
|
+
TESTS::
|
|
321
|
+
|
|
322
|
+
sage: f = Family({1:'a', 2:'b', 3:'c'})
|
|
323
|
+
sage: f
|
|
324
|
+
Finite family {1: 'a', 2: 'b', 3: 'c'}
|
|
325
|
+
sage: f[2]
|
|
326
|
+
'b'
|
|
327
|
+
sage: loads(dumps(f)) == f
|
|
328
|
+
True
|
|
329
|
+
|
|
330
|
+
::
|
|
331
|
+
|
|
332
|
+
sage: f = Family({1:'a', 2:'b', 3:'c'}, lazy=True)
|
|
333
|
+
Traceback (most recent call last):
|
|
334
|
+
...
|
|
335
|
+
ValueError: lazy keyword only makes sense together with function keyword
|
|
336
|
+
|
|
337
|
+
::
|
|
338
|
+
|
|
339
|
+
sage: f = Family(list(range(1,27)), lambda i: chr(i+96))
|
|
340
|
+
sage: f
|
|
341
|
+
Finite family {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g',
|
|
342
|
+
8: 'h', 9: 'i', 10: 'j', 11: 'k', 12: 'l', 13: 'm', 14: 'n', 15: 'o',
|
|
343
|
+
16: 'p', 17: 'q', 18: 'r', 19: 's', 20: 't', 21: 'u', 22: 'v', 23: 'w',
|
|
344
|
+
24: 'x', 25: 'y', 26: 'z'}
|
|
345
|
+
sage: f[2]
|
|
346
|
+
'b'
|
|
347
|
+
|
|
348
|
+
The factory ``Family`` is supposed to be idempotent. We test this feature here::
|
|
349
|
+
|
|
350
|
+
sage: from sage.sets.family import FiniteFamily, LazyFamily, TrivialFamily
|
|
351
|
+
sage: f = FiniteFamily({3: 'a', 4: 'b', 7: 'd'})
|
|
352
|
+
sage: g = Family(f)
|
|
353
|
+
sage: f == g
|
|
354
|
+
True
|
|
355
|
+
|
|
356
|
+
sage: f = Family([3,4,7], lambda i: 2*i, hidden_keys=[2])
|
|
357
|
+
sage: g = Family(f)
|
|
358
|
+
sage: f == g
|
|
359
|
+
True
|
|
360
|
+
|
|
361
|
+
sage: f = LazyFamily([3,4,7], lambda i: 2*i)
|
|
362
|
+
sage: g = Family(f)
|
|
363
|
+
sage: f == g
|
|
364
|
+
True
|
|
365
|
+
|
|
366
|
+
sage: f = TrivialFamily([3,4,7])
|
|
367
|
+
sage: g = Family(f)
|
|
368
|
+
sage: f == g
|
|
369
|
+
True
|
|
370
|
+
|
|
371
|
+
A family should keep the order of the keys::
|
|
372
|
+
|
|
373
|
+
sage: f = Family(["c", "a", "b"], lambda i: 2*i)
|
|
374
|
+
sage: list(f)
|
|
375
|
+
['cc', 'aa', 'bb']
|
|
376
|
+
|
|
377
|
+
Even with hidden keys (see :issue:`22955`)::
|
|
378
|
+
|
|
379
|
+
sage: f = Family(["c", "a", "b"], lambda i: 2*i,
|
|
380
|
+
....: hidden_keys=[5], hidden_function=lambda i: i%2)
|
|
381
|
+
sage: list(f)
|
|
382
|
+
['cc', 'aa', 'bb']
|
|
383
|
+
|
|
384
|
+
Only the hidden function is applied to the hidden keys::
|
|
385
|
+
|
|
386
|
+
sage: f[5]
|
|
387
|
+
1
|
|
388
|
+
"""
|
|
389
|
+
assert isinstance(hidden_keys, list)
|
|
390
|
+
assert isinstance(lazy, bool)
|
|
391
|
+
|
|
392
|
+
if not hidden_keys:
|
|
393
|
+
if hidden_function is not None:
|
|
394
|
+
raise ValueError("hidden_function keyword only makes sense "
|
|
395
|
+
"together with hidden_keys keyword !")
|
|
396
|
+
if function is None:
|
|
397
|
+
if lazy:
|
|
398
|
+
raise ValueError("lazy keyword only makes sense together with function keyword")
|
|
399
|
+
if isinstance(indices, dict):
|
|
400
|
+
return FiniteFamily(indices)
|
|
401
|
+
if isinstance(indices, (list, tuple)):
|
|
402
|
+
return TrivialFamily(indices)
|
|
403
|
+
if isinstance(indices, (FiniteFamily, LazyFamily, TrivialFamily)):
|
|
404
|
+
return indices
|
|
405
|
+
if indices in EnumeratedSets():
|
|
406
|
+
return EnumeratedFamily(indices)
|
|
407
|
+
if isinstance(indices, Iterable):
|
|
408
|
+
return TrivialFamily(indices)
|
|
409
|
+
|
|
410
|
+
raise NotImplementedError
|
|
411
|
+
if (isinstance(indices, (list, tuple, FiniteEnumeratedSet))
|
|
412
|
+
and not lazy):
|
|
413
|
+
return FiniteFamily({i: function(i) for i in indices},
|
|
414
|
+
keys=indices)
|
|
415
|
+
|
|
416
|
+
return LazyFamily(indices, function, name)
|
|
417
|
+
if lazy:
|
|
418
|
+
raise ValueError("lazy keyword is incompatible with hidden keys")
|
|
419
|
+
if hidden_function is None:
|
|
420
|
+
hidden_function = function
|
|
421
|
+
return FiniteFamilyWithHiddenKeys({i: function(i) for i in indices},
|
|
422
|
+
hidden_keys, hidden_function,
|
|
423
|
+
keys=indices)
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
cdef class AbstractFamily(Parent):
|
|
427
|
+
"""
|
|
428
|
+
The abstract class for family.
|
|
429
|
+
|
|
430
|
+
Any family belongs to a class which inherits from :class:`AbstractFamily`.
|
|
431
|
+
"""
|
|
432
|
+
def hidden_keys(self):
|
|
433
|
+
"""
|
|
434
|
+
Return the hidden keys of the family, if any.
|
|
435
|
+
|
|
436
|
+
EXAMPLES::
|
|
437
|
+
|
|
438
|
+
sage: f = Family({3: 'a', 4: 'b', 7: 'd'})
|
|
439
|
+
sage: f.hidden_keys()
|
|
440
|
+
[]
|
|
441
|
+
"""
|
|
442
|
+
return []
|
|
443
|
+
|
|
444
|
+
def keys(self):
|
|
445
|
+
"""
|
|
446
|
+
Return the keys of the family.
|
|
447
|
+
|
|
448
|
+
EXAMPLES::
|
|
449
|
+
|
|
450
|
+
sage: f = Family({3: 'a', 4: 'b', 7: 'd'})
|
|
451
|
+
sage: sorted(f.keys())
|
|
452
|
+
[3, 4, 7]
|
|
453
|
+
"""
|
|
454
|
+
raise NotImplementedError
|
|
455
|
+
|
|
456
|
+
def values(self):
|
|
457
|
+
"""
|
|
458
|
+
Return the elements (values) of this family.
|
|
459
|
+
|
|
460
|
+
EXAMPLES::
|
|
461
|
+
|
|
462
|
+
sage: f = Family(["c", "a", "b"], lambda x: x + x)
|
|
463
|
+
sage: sorted(f.values())
|
|
464
|
+
['aa', 'bb', 'cc']
|
|
465
|
+
"""
|
|
466
|
+
raise NotImplementedError
|
|
467
|
+
|
|
468
|
+
def items(self):
|
|
469
|
+
"""
|
|
470
|
+
Return an iterator for key-value pairs.
|
|
471
|
+
|
|
472
|
+
A key can only appear once, but if the function is not injective, values may
|
|
473
|
+
appear multiple times.
|
|
474
|
+
|
|
475
|
+
EXAMPLES::
|
|
476
|
+
|
|
477
|
+
sage: f = Family([-2, -1, 0, 1, 2], abs)
|
|
478
|
+
sage: list(f.items())
|
|
479
|
+
[(-2, 2), (-1, 1), (0, 0), (1, 1), (2, 2)]
|
|
480
|
+
"""
|
|
481
|
+
return zip(self.keys(), self.values())
|
|
482
|
+
|
|
483
|
+
def zip(self, f, other, name=None):
|
|
484
|
+
r"""
|
|
485
|
+
Given two families with same index set `I` (and same hidden
|
|
486
|
+
keys if relevant), returns the family
|
|
487
|
+
`( f(self[i], other[i]) )_{i \in I}`
|
|
488
|
+
|
|
489
|
+
.. TODO:: generalize to any number of families and merge with map?
|
|
490
|
+
|
|
491
|
+
EXAMPLES::
|
|
492
|
+
|
|
493
|
+
sage: f = Family({3: 'a', 4: 'b', 7: 'd'})
|
|
494
|
+
sage: g = Family({3: '1', 4: '2', 7: '3'})
|
|
495
|
+
sage: h = f.zip(lambda x,y: x+y, g)
|
|
496
|
+
sage: list(h)
|
|
497
|
+
['a1', 'b2', 'd3']
|
|
498
|
+
"""
|
|
499
|
+
assert self.keys() == other.keys()
|
|
500
|
+
assert self.hidden_keys() == other.hidden_keys()
|
|
501
|
+
return Family(self.keys(), lambda i: f(self[i], other[i]),
|
|
502
|
+
hidden_keys=self.hidden_keys(), name=name)
|
|
503
|
+
|
|
504
|
+
def map(self, f, name=None):
|
|
505
|
+
r"""
|
|
506
|
+
Return the family `( f(\mathtt{self}[i]) )_{i \in I}`, where
|
|
507
|
+
`I` is the index set of ``self``.
|
|
508
|
+
|
|
509
|
+
EXAMPLES::
|
|
510
|
+
|
|
511
|
+
sage: f = Family({3: 'a', 4: 'b', 7: 'd'})
|
|
512
|
+
sage: g = f.map(lambda x: x+'1')
|
|
513
|
+
sage: list(g)
|
|
514
|
+
['a1', 'b1', 'd1']
|
|
515
|
+
"""
|
|
516
|
+
return Family(self.keys(), lambda i: f(self[i]), hidden_keys=self.hidden_keys(), name=name)
|
|
517
|
+
|
|
518
|
+
# temporary; tested by TestSuite.
|
|
519
|
+
_an_element_ = EnumeratedSets.ParentMethods._an_element_
|
|
520
|
+
|
|
521
|
+
@cached_method
|
|
522
|
+
def inverse_family(self):
|
|
523
|
+
"""
|
|
524
|
+
Return the inverse family, with keys and values exchanged. This
|
|
525
|
+
presumes that there are no duplicate values in ``self``.
|
|
526
|
+
|
|
527
|
+
This default implementation is not lazy and therefore will
|
|
528
|
+
only work with not too big finite families. It is also cached
|
|
529
|
+
for the same reason::
|
|
530
|
+
|
|
531
|
+
sage: Family({3: 'a', 4: 'b', 7: 'd'}).inverse_family()
|
|
532
|
+
Finite family {'a': 3, 'b': 4, 'd': 7}
|
|
533
|
+
|
|
534
|
+
sage: Family((3,4,7)).inverse_family()
|
|
535
|
+
Finite family {3: 0, 4: 1, 7: 2}
|
|
536
|
+
"""
|
|
537
|
+
return Family({self[k]: k for k in self.keys()})
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
cdef class FiniteFamily(AbstractFamily):
|
|
541
|
+
r"""
|
|
542
|
+
A :class:`FiniteFamily` is an associative container which models a finite
|
|
543
|
+
family `(f_i)_{i \in I}`. Its elements `f_i` are therefore its
|
|
544
|
+
values. Instances should be created via the :func:`Family` factory. See its
|
|
545
|
+
documentation for examples and tests.
|
|
546
|
+
|
|
547
|
+
EXAMPLES:
|
|
548
|
+
|
|
549
|
+
We define the family `(f_i)_{i \in \{3,4,7\}}` with `f_3=a`,
|
|
550
|
+
`f_4=b`, and `f_7=d`::
|
|
551
|
+
|
|
552
|
+
sage: from sage.sets.family import FiniteFamily
|
|
553
|
+
sage: f = FiniteFamily({3: 'a', 4: 'b', 7: 'd'})
|
|
554
|
+
|
|
555
|
+
Individual elements are accessible as in a usual dictionary::
|
|
556
|
+
|
|
557
|
+
sage: f[7]
|
|
558
|
+
'd'
|
|
559
|
+
|
|
560
|
+
And the other usual dictionary operations are also available::
|
|
561
|
+
|
|
562
|
+
sage: len(f)
|
|
563
|
+
3
|
|
564
|
+
sage: f.keys()
|
|
565
|
+
[3, 4, 7]
|
|
566
|
+
|
|
567
|
+
However f behaves as a container for the `f_i`'s::
|
|
568
|
+
|
|
569
|
+
sage: list(f)
|
|
570
|
+
['a', 'b', 'd']
|
|
571
|
+
sage: [ x for x in f ]
|
|
572
|
+
['a', 'b', 'd']
|
|
573
|
+
|
|
574
|
+
The order of the elements can be specified using the ``keys`` optional argument::
|
|
575
|
+
|
|
576
|
+
sage: f = FiniteFamily({"a": "aa", "b": "bb", "c" : "cc" }, keys = ["c", "a", "b"])
|
|
577
|
+
sage: list(f)
|
|
578
|
+
['cc', 'aa', 'bb']
|
|
579
|
+
"""
|
|
580
|
+
|
|
581
|
+
def __init__(self, dictionary, keys=None):
|
|
582
|
+
"""
|
|
583
|
+
TESTS::
|
|
584
|
+
|
|
585
|
+
sage: from sage.sets.family import FiniteFamily
|
|
586
|
+
sage: f = FiniteFamily({3: 'a', 4: 'b', 7: 'd'})
|
|
587
|
+
sage: TestSuite(f).run()
|
|
588
|
+
|
|
589
|
+
Check for bug :issue:`5538`::
|
|
590
|
+
|
|
591
|
+
sage: d = {1:"a", 3:"b", 4:"c"}
|
|
592
|
+
sage: f = Family(d)
|
|
593
|
+
sage: d[2] = 'DD'
|
|
594
|
+
sage: f
|
|
595
|
+
Finite family {1: 'a', 3: 'b', 4: 'c'}
|
|
596
|
+
"""
|
|
597
|
+
# TODO: use keys to specify the order of the elements
|
|
598
|
+
Parent.__init__(self, category=FiniteEnumeratedSets())
|
|
599
|
+
self._dictionary = dict(dictionary)
|
|
600
|
+
self._keys = keys
|
|
601
|
+
|
|
602
|
+
@cached_method
|
|
603
|
+
def __hash__(self):
|
|
604
|
+
"""
|
|
605
|
+
Return a hash value for ``self``.
|
|
606
|
+
|
|
607
|
+
EXAMPLES::
|
|
608
|
+
|
|
609
|
+
sage: f = Family(["c", "a", "b"], lambda x: x+x)
|
|
610
|
+
sage: hash(f) == hash(f)
|
|
611
|
+
True
|
|
612
|
+
sage: f2 = Family(["a", "c", "b"], lambda x: x+x)
|
|
613
|
+
sage: hash(f) == hash(f2)
|
|
614
|
+
True
|
|
615
|
+
sage: g = Family(["b", "c", "a"], lambda x: x+x+x)
|
|
616
|
+
sage: hash(f) == hash(g)
|
|
617
|
+
False
|
|
618
|
+
|
|
619
|
+
::
|
|
620
|
+
|
|
621
|
+
sage: f = Family({1:[1,2]})
|
|
622
|
+
sage: hash(f) == hash(f)
|
|
623
|
+
True
|
|
624
|
+
"""
|
|
625
|
+
try:
|
|
626
|
+
return hash(frozenset(self._dictionary.items()))
|
|
627
|
+
except (TypeError, ValueError):
|
|
628
|
+
return hash(frozenset(self.keys() +
|
|
629
|
+
[repr(v) for v in self.values()]))
|
|
630
|
+
|
|
631
|
+
def __bool__(self):
|
|
632
|
+
r"""
|
|
633
|
+
Return if ``self`` is empty or not.
|
|
634
|
+
|
|
635
|
+
EXAMPLES::
|
|
636
|
+
|
|
637
|
+
sage: from sage.sets.family import TrivialFamily
|
|
638
|
+
sage: f = Family(["c", "a", "b"], lambda x: x+x)
|
|
639
|
+
sage: bool(f)
|
|
640
|
+
True
|
|
641
|
+
sage: g = Family({})
|
|
642
|
+
sage: bool(g)
|
|
643
|
+
False
|
|
644
|
+
sage: h = Family([], lambda x: x+x)
|
|
645
|
+
sage: bool(h)
|
|
646
|
+
False
|
|
647
|
+
"""
|
|
648
|
+
return bool(self._dictionary)
|
|
649
|
+
|
|
650
|
+
def keys(self):
|
|
651
|
+
"""
|
|
652
|
+
Return the index set of this family.
|
|
653
|
+
|
|
654
|
+
EXAMPLES::
|
|
655
|
+
|
|
656
|
+
sage: f = Family(["c", "a", "b"], lambda x: x+x)
|
|
657
|
+
sage: f.keys()
|
|
658
|
+
['c', 'a', 'b']
|
|
659
|
+
"""
|
|
660
|
+
return (self._keys if self._keys is not None
|
|
661
|
+
else list(self._dictionary))
|
|
662
|
+
|
|
663
|
+
def values(self):
|
|
664
|
+
"""
|
|
665
|
+
Return the elements of this family.
|
|
666
|
+
|
|
667
|
+
EXAMPLES::
|
|
668
|
+
|
|
669
|
+
sage: f = Family(["c", "a", "b"], lambda x: x+x)
|
|
670
|
+
sage: f.values()
|
|
671
|
+
['cc', 'aa', 'bb']
|
|
672
|
+
"""
|
|
673
|
+
if self._keys is not None:
|
|
674
|
+
return [self._dictionary[key] for key in self._keys]
|
|
675
|
+
else:
|
|
676
|
+
return list(self._dictionary.values())
|
|
677
|
+
|
|
678
|
+
def has_key(self, k) -> bool:
|
|
679
|
+
"""
|
|
680
|
+
Return whether ``k`` is a key of ``self``.
|
|
681
|
+
|
|
682
|
+
EXAMPLES::
|
|
683
|
+
|
|
684
|
+
sage: Family({"a":1, "b":2, "c":3}).has_key("a")
|
|
685
|
+
True
|
|
686
|
+
sage: Family({"a":1, "b":2, "c":3}).has_key("d")
|
|
687
|
+
False
|
|
688
|
+
"""
|
|
689
|
+
return k in self._dictionary
|
|
690
|
+
|
|
691
|
+
def __eq__(self, other) -> bool:
|
|
692
|
+
"""
|
|
693
|
+
EXAMPLES::
|
|
694
|
+
|
|
695
|
+
sage: f = Family({1:'a', 2:'b', 3:'c'})
|
|
696
|
+
sage: g = Family({1:'a', 2:'b', 3:'c'})
|
|
697
|
+
sage: f == g
|
|
698
|
+
True
|
|
699
|
+
|
|
700
|
+
TESTS::
|
|
701
|
+
|
|
702
|
+
sage: from sage.sets.family import FiniteFamily
|
|
703
|
+
|
|
704
|
+
sage: f1 = FiniteFamily({1:'a', 2:'b', 3:'c'}, keys = [1,2,3])
|
|
705
|
+
sage: g1 = FiniteFamily({1:'a', 2:'b', 3:'c'}, keys = [1,2,3])
|
|
706
|
+
sage: h1 = FiniteFamily({1:'a', 2:'b', 3:'c'}, keys = [2,1,3])
|
|
707
|
+
|
|
708
|
+
sage: f1 == g1
|
|
709
|
+
True
|
|
710
|
+
sage: f1 == h1
|
|
711
|
+
False
|
|
712
|
+
sage: f1 == f
|
|
713
|
+
False
|
|
714
|
+
"""
|
|
715
|
+
return (isinstance(other, self.__class__) and
|
|
716
|
+
self._keys == (<FiniteFamily> other)._keys and
|
|
717
|
+
self._dictionary == (<FiniteFamily> other)._dictionary)
|
|
718
|
+
|
|
719
|
+
def _repr_(self):
|
|
720
|
+
"""
|
|
721
|
+
EXAMPLES::
|
|
722
|
+
|
|
723
|
+
sage: from sage.sets.family import FiniteFamily
|
|
724
|
+
sage: FiniteFamily({3: 'a'}) # indirect doctest
|
|
725
|
+
Finite family {3: 'a'}
|
|
726
|
+
|
|
727
|
+
sage: FiniteFamily({3: 'a', 4: 'b'}) # indirect doctest
|
|
728
|
+
Finite family {3: 'a', 4: 'b'}
|
|
729
|
+
|
|
730
|
+
sage: FiniteFamily({3: 'a', 4: 'b'}, keys=[4,3]) # indirect doctest
|
|
731
|
+
Finite family {4: 'b', 3: 'a'}
|
|
732
|
+
"""
|
|
733
|
+
if self._keys is None:
|
|
734
|
+
d = ' '.join(pformat(self._dictionary)[1:-1].splitlines())
|
|
735
|
+
else:
|
|
736
|
+
d = ', '.join('{}: {}'.format(saferepr(key),
|
|
737
|
+
saferepr(self._dictionary[key]))
|
|
738
|
+
for key in self._keys)
|
|
739
|
+
return 'Finite family {{{}}}'.format(d)
|
|
740
|
+
|
|
741
|
+
def __contains__(self, x):
|
|
742
|
+
"""
|
|
743
|
+
EXAMPLES::
|
|
744
|
+
|
|
745
|
+
sage: from sage.sets.family import FiniteFamily
|
|
746
|
+
sage: f = FiniteFamily({3: 'a'})
|
|
747
|
+
sage: 'a' in f
|
|
748
|
+
True
|
|
749
|
+
sage: 'b' in f
|
|
750
|
+
False
|
|
751
|
+
"""
|
|
752
|
+
return x in self.values()
|
|
753
|
+
|
|
754
|
+
def __len__(self):
|
|
755
|
+
"""
|
|
756
|
+
Return the number of elements in ``self``.
|
|
757
|
+
|
|
758
|
+
EXAMPLES::
|
|
759
|
+
|
|
760
|
+
sage: from sage.sets.family import FiniteFamily
|
|
761
|
+
sage: f = FiniteFamily({3: 'a', 4: 'b', 7: 'd'})
|
|
762
|
+
sage: len(f)
|
|
763
|
+
3
|
|
764
|
+
"""
|
|
765
|
+
return len(self._dictionary)
|
|
766
|
+
|
|
767
|
+
def cardinality(self):
|
|
768
|
+
"""
|
|
769
|
+
Return the number of elements in ``self``.
|
|
770
|
+
|
|
771
|
+
EXAMPLES::
|
|
772
|
+
|
|
773
|
+
sage: from sage.sets.family import FiniteFamily
|
|
774
|
+
sage: f = FiniteFamily({3: 'a', 4: 'b', 7: 'd'})
|
|
775
|
+
sage: f.cardinality()
|
|
776
|
+
3
|
|
777
|
+
"""
|
|
778
|
+
return Integer(len(self._dictionary))
|
|
779
|
+
|
|
780
|
+
def __iter__(self):
|
|
781
|
+
"""
|
|
782
|
+
EXAMPLES::
|
|
783
|
+
|
|
784
|
+
sage: from sage.sets.family import FiniteFamily
|
|
785
|
+
sage: f = FiniteFamily({3: 'a'})
|
|
786
|
+
sage: i = iter(f)
|
|
787
|
+
sage: next(i)
|
|
788
|
+
'a'
|
|
789
|
+
"""
|
|
790
|
+
return iter(self.values())
|
|
791
|
+
|
|
792
|
+
def __getitem__(self, i):
|
|
793
|
+
"""
|
|
794
|
+
Note that we can't just do self.__getitem__ =
|
|
795
|
+
dictionary.__getitem__ in the __init__ method since Python
|
|
796
|
+
queries the object's type/class for the special methods rather than
|
|
797
|
+
querying the object itself.
|
|
798
|
+
|
|
799
|
+
EXAMPLES::
|
|
800
|
+
|
|
801
|
+
sage: from sage.sets.family import FiniteFamily
|
|
802
|
+
sage: f = FiniteFamily({3: 'a', 4: 'b', 7: 'd'})
|
|
803
|
+
sage: f[3]
|
|
804
|
+
'a'
|
|
805
|
+
"""
|
|
806
|
+
return self._dictionary[i]
|
|
807
|
+
|
|
808
|
+
# For the pickle and copy modules
|
|
809
|
+
def __getstate__(self):
|
|
810
|
+
"""
|
|
811
|
+
TESTS::
|
|
812
|
+
|
|
813
|
+
sage: from sage.sets.family import FiniteFamily
|
|
814
|
+
sage: f = FiniteFamily({3: 'a'})
|
|
815
|
+
sage: f.__getstate__()
|
|
816
|
+
{'dictionary': {3: 'a'}, 'keys': None}
|
|
817
|
+
"""
|
|
818
|
+
return {'dictionary': self._dictionary, 'keys': self._keys}
|
|
819
|
+
|
|
820
|
+
def __setstate__(self, state):
|
|
821
|
+
"""
|
|
822
|
+
TESTS::
|
|
823
|
+
|
|
824
|
+
sage: from sage.sets.family import FiniteFamily
|
|
825
|
+
sage: f = FiniteFamily({3: 'a'})
|
|
826
|
+
sage: f.__setstate__({'dictionary': {4:'b'}})
|
|
827
|
+
sage: f
|
|
828
|
+
Finite family {4: 'b'}
|
|
829
|
+
"""
|
|
830
|
+
self.__init__(state['dictionary'], keys=state.get("keys"))
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
class FiniteFamilyWithHiddenKeys(FiniteFamily):
|
|
834
|
+
r"""
|
|
835
|
+
A close variant of :class:`FiniteFamily` where the family contains some
|
|
836
|
+
hidden keys whose corresponding values are computed lazily (and
|
|
837
|
+
remembered). Instances should be created via the :func:`Family` factory.
|
|
838
|
+
See its documentation for examples and tests.
|
|
839
|
+
|
|
840
|
+
Caveat: Only instances of this class whose functions are compatible
|
|
841
|
+
with :mod:`sage.misc.fpickle` can be pickled.
|
|
842
|
+
"""
|
|
843
|
+
def __init__(self, dictionary, hidden_keys, hidden_function, keys=None):
|
|
844
|
+
"""
|
|
845
|
+
EXAMPLES::
|
|
846
|
+
|
|
847
|
+
sage: f = Family([3,4,7], lambda i: 2*i, hidden_keys=[2])
|
|
848
|
+
sage: TestSuite(f).run()
|
|
849
|
+
"""
|
|
850
|
+
FiniteFamily.__init__(self, dictionary, keys=keys)
|
|
851
|
+
self._hidden_keys = hidden_keys
|
|
852
|
+
self.hidden_function = hidden_function
|
|
853
|
+
self.hidden_dictionary = {}
|
|
854
|
+
|
|
855
|
+
# would be better to define as usual method
|
|
856
|
+
# any better to unset the def of __getitem__ by FiniteFamily?
|
|
857
|
+
# self.__getitem__ = lambda i: dictionary[i] if dictionary.has_key(i) else hidden_dictionary[i]
|
|
858
|
+
|
|
859
|
+
def __getitem__(self, i):
|
|
860
|
+
"""
|
|
861
|
+
EXAMPLES::
|
|
862
|
+
|
|
863
|
+
sage: f = Family([3,4,7], lambda i: 2*i, hidden_keys=[2])
|
|
864
|
+
sage: f[3]
|
|
865
|
+
6
|
|
866
|
+
sage: f[2]
|
|
867
|
+
4
|
|
868
|
+
sage: f[5]
|
|
869
|
+
Traceback (most recent call last):
|
|
870
|
+
...
|
|
871
|
+
KeyError
|
|
872
|
+
"""
|
|
873
|
+
try:
|
|
874
|
+
return FiniteFamily.__getitem__(self, i)
|
|
875
|
+
except KeyError:
|
|
876
|
+
try:
|
|
877
|
+
return self.hidden_dictionary[i]
|
|
878
|
+
except KeyError:
|
|
879
|
+
if i not in self._hidden_keys:
|
|
880
|
+
raise KeyError
|
|
881
|
+
v = self.hidden_function(i)
|
|
882
|
+
self.hidden_dictionary[i] = v
|
|
883
|
+
return v
|
|
884
|
+
|
|
885
|
+
def hidden_keys(self):
|
|
886
|
+
"""
|
|
887
|
+
Return ``self``'s hidden keys.
|
|
888
|
+
|
|
889
|
+
EXAMPLES::
|
|
890
|
+
|
|
891
|
+
sage: f = Family([3,4,7], lambda i: 2*i, hidden_keys=[2])
|
|
892
|
+
sage: f.hidden_keys()
|
|
893
|
+
[2]
|
|
894
|
+
"""
|
|
895
|
+
return self._hidden_keys
|
|
896
|
+
|
|
897
|
+
def __getstate__(self):
|
|
898
|
+
"""
|
|
899
|
+
TESTS::
|
|
900
|
+
|
|
901
|
+
sage: f = Family([3,4,7], lambda i: 2*i, hidden_keys=[2])
|
|
902
|
+
sage: d = f.__getstate__()
|
|
903
|
+
sage: d['hidden_keys']
|
|
904
|
+
[2]
|
|
905
|
+
"""
|
|
906
|
+
from sage.misc.fpickle import pickle_function
|
|
907
|
+
f = pickle_function(self.hidden_function)
|
|
908
|
+
state = super().__getstate__()
|
|
909
|
+
state.update({'hidden_keys': self._hidden_keys,
|
|
910
|
+
'hidden_dictionary': self.hidden_dictionary,
|
|
911
|
+
'hidden_function': f})
|
|
912
|
+
return state
|
|
913
|
+
|
|
914
|
+
def __setstate__(self, d):
|
|
915
|
+
"""
|
|
916
|
+
TESTS::
|
|
917
|
+
|
|
918
|
+
sage: f = Family([3,4,7], lambda i: 2*i, hidden_keys=[2])
|
|
919
|
+
sage: d = f.__getstate__()
|
|
920
|
+
sage: f = Family([4,5,6], lambda i: 2*i, hidden_keys=[2])
|
|
921
|
+
sage: f.__setstate__(d)
|
|
922
|
+
sage: f.keys()
|
|
923
|
+
[3, 4, 7]
|
|
924
|
+
sage: f[3]
|
|
925
|
+
6
|
|
926
|
+
"""
|
|
927
|
+
hidden_function = d['hidden_function']
|
|
928
|
+
if isinstance(hidden_function, (str, bytes)):
|
|
929
|
+
# Let's assume that hidden_function is an unpickled function.
|
|
930
|
+
from sage.misc.fpickle import unpickle_function
|
|
931
|
+
hidden_function = unpickle_function(hidden_function)
|
|
932
|
+
self.__init__(d['dictionary'], d['hidden_keys'], hidden_function)
|
|
933
|
+
self.hidden_dictionary = d['hidden_dictionary']
|
|
934
|
+
# Old pickles from before Issue #22955 may not have a 'keys'
|
|
935
|
+
if 'keys' in d:
|
|
936
|
+
self._keys = d['keys']
|
|
937
|
+
else:
|
|
938
|
+
self._keys = None
|
|
939
|
+
|
|
940
|
+
|
|
941
|
+
class LazyFamily(AbstractFamily):
|
|
942
|
+
r"""
|
|
943
|
+
A LazyFamily(I, f) is an associative container which models the
|
|
944
|
+
(possibly infinite) family `(f(i))_{i \in I}`.
|
|
945
|
+
|
|
946
|
+
Instances should be created via the :func:`Family` factory. See its
|
|
947
|
+
documentation for examples and tests.
|
|
948
|
+
"""
|
|
949
|
+
def __init__(self, set, function, name=None):
|
|
950
|
+
"""
|
|
951
|
+
TESTS::
|
|
952
|
+
|
|
953
|
+
sage: from sage.sets.family import LazyFamily
|
|
954
|
+
sage: f = LazyFamily([3,4,7], lambda i: 2*i); f
|
|
955
|
+
Lazy family (<lambda>(i))_{i in [3, 4, 7]}
|
|
956
|
+
sage: TestSuite(f).run()
|
|
957
|
+
|
|
958
|
+
Check for :issue:`5538`::
|
|
959
|
+
|
|
960
|
+
sage: l = [3,4,7]
|
|
961
|
+
sage: f = LazyFamily(l, lambda i: 2*i)
|
|
962
|
+
sage: l[1] = 18
|
|
963
|
+
sage: f
|
|
964
|
+
Lazy family (<lambda>(i))_{i in [3, 4, 7]}
|
|
965
|
+
"""
|
|
966
|
+
if set in FiniteEnumeratedSets():
|
|
967
|
+
category = FiniteEnumeratedSets()
|
|
968
|
+
elif set in InfiniteEnumeratedSets():
|
|
969
|
+
category = InfiniteEnumeratedSets()
|
|
970
|
+
elif isinstance(set, (list, tuple, range)):
|
|
971
|
+
category = FiniteEnumeratedSets()
|
|
972
|
+
else: # some sets such as QQ implements is_finite() but is not in InfiniteEnumeratedSets()
|
|
973
|
+
try:
|
|
974
|
+
if set.is_finite():
|
|
975
|
+
category = FiniteEnumeratedSets()
|
|
976
|
+
else:
|
|
977
|
+
category = InfiniteEnumeratedSets()
|
|
978
|
+
except (AttributeError, NotImplementedError):
|
|
979
|
+
category = EnumeratedSets()
|
|
980
|
+
|
|
981
|
+
Parent.__init__(self, category=category)
|
|
982
|
+
|
|
983
|
+
self.set = copy(set)
|
|
984
|
+
self.function = function
|
|
985
|
+
self.function_name = name
|
|
986
|
+
|
|
987
|
+
def __bool__(self):
|
|
988
|
+
r"""
|
|
989
|
+
Return if ``self`` is empty or not.
|
|
990
|
+
|
|
991
|
+
EXAMPLES::
|
|
992
|
+
|
|
993
|
+
sage: from sage.sets.family import LazyFamily
|
|
994
|
+
sage: f = LazyFamily([3,4,7], lambda i: 2*i)
|
|
995
|
+
sage: bool(f)
|
|
996
|
+
True
|
|
997
|
+
sage: g = LazyFamily([], lambda i: 2*i)
|
|
998
|
+
sage: bool(g)
|
|
999
|
+
False
|
|
1000
|
+
sage: h = Family(ZZ, lambda x: x+x)
|
|
1001
|
+
sage: bool(h)
|
|
1002
|
+
True
|
|
1003
|
+
"""
|
|
1004
|
+
return bool(self.set)
|
|
1005
|
+
|
|
1006
|
+
@cached_method
|
|
1007
|
+
def __hash__(self):
|
|
1008
|
+
"""
|
|
1009
|
+
Return a hash value for ``self``.
|
|
1010
|
+
|
|
1011
|
+
EXAMPLES::
|
|
1012
|
+
|
|
1013
|
+
sage: from sage.sets.family import LazyFamily
|
|
1014
|
+
sage: f = LazyFamily([3,4,7], lambda i: 2*i)
|
|
1015
|
+
sage: hash(f) == hash(f)
|
|
1016
|
+
True
|
|
1017
|
+
sage: g = LazyFamily(ZZ, lambda i: 2*i)
|
|
1018
|
+
sage: hash(g) == hash(g)
|
|
1019
|
+
True
|
|
1020
|
+
sage: h = LazyFamily(ZZ, lambda i: 2*i, name='foo')
|
|
1021
|
+
sage: hash(h) == hash(h)
|
|
1022
|
+
True
|
|
1023
|
+
|
|
1024
|
+
::
|
|
1025
|
+
|
|
1026
|
+
sage: class X():
|
|
1027
|
+
....: def __call__(self, x):
|
|
1028
|
+
....: return x
|
|
1029
|
+
....: __hash__ = None
|
|
1030
|
+
sage: f = Family([1,2,3], X())
|
|
1031
|
+
sage: hash(f) == hash(f)
|
|
1032
|
+
True
|
|
1033
|
+
"""
|
|
1034
|
+
try:
|
|
1035
|
+
return hash(self.keys()) + hash(self.function)
|
|
1036
|
+
except (TypeError, ValueError):
|
|
1037
|
+
return super().__hash__()
|
|
1038
|
+
|
|
1039
|
+
def __eq__(self, other):
|
|
1040
|
+
"""
|
|
1041
|
+
WARNING: Since there is no way to compare function, we only compare
|
|
1042
|
+
their name.
|
|
1043
|
+
|
|
1044
|
+
TESTS::
|
|
1045
|
+
|
|
1046
|
+
sage: from sage.sets.family import LazyFamily
|
|
1047
|
+
sage: fun = lambda i: 2*i
|
|
1048
|
+
sage: f = LazyFamily([3,4,7], fun)
|
|
1049
|
+
sage: g = LazyFamily([3,4,7], fun)
|
|
1050
|
+
sage: f == g
|
|
1051
|
+
True
|
|
1052
|
+
"""
|
|
1053
|
+
if not isinstance(other, self.__class__):
|
|
1054
|
+
return False
|
|
1055
|
+
if not self.set == other.set:
|
|
1056
|
+
return False
|
|
1057
|
+
return repr(self) == repr(other)
|
|
1058
|
+
|
|
1059
|
+
def _repr_(self):
|
|
1060
|
+
"""
|
|
1061
|
+
EXAMPLES::
|
|
1062
|
+
|
|
1063
|
+
sage: from sage.sets.family import LazyFamily
|
|
1064
|
+
sage: def fun(i): 2*i
|
|
1065
|
+
sage: f = LazyFamily([3,4,7], fun); f
|
|
1066
|
+
Lazy family (fun(i))_{i in [3, 4, 7]}
|
|
1067
|
+
|
|
1068
|
+
sage: f = Family(Permutations(3), attrcall("to_lehmer_code"), lazy=True); f
|
|
1069
|
+
Lazy family (i.to_lehmer_code())_{i in Standard permutations of 3}
|
|
1070
|
+
|
|
1071
|
+
sage: f = LazyFamily([3,4,7], lambda i: 2*i); f
|
|
1072
|
+
Lazy family (<lambda>(i))_{i in [3, 4, 7]}
|
|
1073
|
+
|
|
1074
|
+
sage: f = LazyFamily([3,4,7], lambda i: 2*i, name='foo'); f
|
|
1075
|
+
Lazy family (foo(i))_{i in [3, 4, 7]}
|
|
1076
|
+
|
|
1077
|
+
TESTS:
|
|
1078
|
+
|
|
1079
|
+
Check that using a class as the function is correctly handled::
|
|
1080
|
+
|
|
1081
|
+
sage: Family(NonNegativeIntegers(), PerfectMatchings) # needs sage.combinat
|
|
1082
|
+
Lazy family (<class 'sage.combinat.perfect_matching.PerfectMatchings'>(i))_{i in Non negative integers}
|
|
1083
|
+
"""
|
|
1084
|
+
if self.function_name is not None:
|
|
1085
|
+
name = self.function_name + "(i)"
|
|
1086
|
+
elif isinstance(self.function, types.LambdaType):
|
|
1087
|
+
name = self.function.__name__
|
|
1088
|
+
name = name + "(i)"
|
|
1089
|
+
else:
|
|
1090
|
+
name = repr(self.function)
|
|
1091
|
+
if isinstance(self.function, AttrCallObject):
|
|
1092
|
+
name = "i" + name[1:]
|
|
1093
|
+
else:
|
|
1094
|
+
name = name + "(i)"
|
|
1095
|
+
return "Lazy family ({})_{{i in {}}}".format(name, self.set)
|
|
1096
|
+
|
|
1097
|
+
def keys(self):
|
|
1098
|
+
"""
|
|
1099
|
+
Return ``self``'s keys.
|
|
1100
|
+
|
|
1101
|
+
EXAMPLES::
|
|
1102
|
+
|
|
1103
|
+
sage: from sage.sets.family import LazyFamily
|
|
1104
|
+
sage: f = LazyFamily([3,4,7], lambda i: 2*i)
|
|
1105
|
+
sage: f.keys()
|
|
1106
|
+
[3, 4, 7]
|
|
1107
|
+
"""
|
|
1108
|
+
return self.set
|
|
1109
|
+
|
|
1110
|
+
def cardinality(self):
|
|
1111
|
+
"""
|
|
1112
|
+
Return the number of elements in ``self``.
|
|
1113
|
+
|
|
1114
|
+
EXAMPLES::
|
|
1115
|
+
|
|
1116
|
+
sage: from sage.sets.family import LazyFamily
|
|
1117
|
+
sage: f = LazyFamily([3,4,7], lambda i: 2*i)
|
|
1118
|
+
sage: f.cardinality()
|
|
1119
|
+
3
|
|
1120
|
+
sage: l = LazyFamily(NonNegativeIntegers(), lambda i: 2*i)
|
|
1121
|
+
sage: l.cardinality()
|
|
1122
|
+
+Infinity
|
|
1123
|
+
|
|
1124
|
+
TESTS:
|
|
1125
|
+
|
|
1126
|
+
Check that :issue:`15195` is fixed::
|
|
1127
|
+
|
|
1128
|
+
sage: C = cartesian_product([PositiveIntegers(), [1,2,3]])
|
|
1129
|
+
sage: C.cardinality()
|
|
1130
|
+
+Infinity
|
|
1131
|
+
sage: F = Family(C, lambda x: x)
|
|
1132
|
+
sage: F.cardinality()
|
|
1133
|
+
+Infinity
|
|
1134
|
+
"""
|
|
1135
|
+
try:
|
|
1136
|
+
return Integer(len(self.set))
|
|
1137
|
+
except (AttributeError, NotImplementedError, TypeError):
|
|
1138
|
+
return self.set.cardinality()
|
|
1139
|
+
|
|
1140
|
+
def __iter__(self):
|
|
1141
|
+
"""
|
|
1142
|
+
EXAMPLES::
|
|
1143
|
+
|
|
1144
|
+
sage: from sage.sets.family import LazyFamily
|
|
1145
|
+
sage: f = LazyFamily([3,4,7], lambda i: 2*i)
|
|
1146
|
+
sage: [i for i in f]
|
|
1147
|
+
[6, 8, 14]
|
|
1148
|
+
"""
|
|
1149
|
+
for i in self.set:
|
|
1150
|
+
yield self[i]
|
|
1151
|
+
|
|
1152
|
+
def __contains__(self, x):
|
|
1153
|
+
"""
|
|
1154
|
+
EXAMPLES::
|
|
1155
|
+
|
|
1156
|
+
sage: from sage.sets.family import LazyFamily
|
|
1157
|
+
sage: f = LazyFamily([3,4,7], lambda i: 2*i)
|
|
1158
|
+
sage: 3 in f, 14 in f
|
|
1159
|
+
(False, True)
|
|
1160
|
+
|
|
1161
|
+
By default this expands the lazy family, which is only done for
|
|
1162
|
+
families known to be finite::
|
|
1163
|
+
|
|
1164
|
+
sage: 5 in LazyFamily(NonNegativeIntegers(), lambda i: 2*i)
|
|
1165
|
+
Traceback (most recent call last):
|
|
1166
|
+
...
|
|
1167
|
+
ValueError: family must be finite to check containment
|
|
1168
|
+
"""
|
|
1169
|
+
if self not in FiniteEnumeratedSets():
|
|
1170
|
+
raise ValueError('family must be finite to check containment')
|
|
1171
|
+
return x in iter(self)
|
|
1172
|
+
|
|
1173
|
+
def __getitem__(self, i):
|
|
1174
|
+
"""
|
|
1175
|
+
EXAMPLES::
|
|
1176
|
+
|
|
1177
|
+
sage: from sage.sets.family import LazyFamily
|
|
1178
|
+
sage: f = LazyFamily([3,4,7], lambda i: 2*i)
|
|
1179
|
+
sage: f[3]
|
|
1180
|
+
6
|
|
1181
|
+
|
|
1182
|
+
TESTS::
|
|
1183
|
+
|
|
1184
|
+
sage: f[5]
|
|
1185
|
+
10
|
|
1186
|
+
"""
|
|
1187
|
+
return self.function(i)
|
|
1188
|
+
|
|
1189
|
+
def __getstate__(self):
|
|
1190
|
+
"""
|
|
1191
|
+
EXAMPLES::
|
|
1192
|
+
|
|
1193
|
+
sage: from sage.sets.family import LazyFamily
|
|
1194
|
+
sage: f = LazyFamily([3,4,7], lambda i: 2*i)
|
|
1195
|
+
sage: d = f.__getstate__()
|
|
1196
|
+
sage: d['set']
|
|
1197
|
+
[3, 4, 7]
|
|
1198
|
+
|
|
1199
|
+
sage: f = LazyFamily(Permutations(3), lambda p: p.to_lehmer_code())
|
|
1200
|
+
sage: f == loads(dumps(f))
|
|
1201
|
+
True
|
|
1202
|
+
|
|
1203
|
+
sage: f = LazyFamily(Permutations(3), attrcall("to_lehmer_code"))
|
|
1204
|
+
sage: f == loads(dumps(f))
|
|
1205
|
+
True
|
|
1206
|
+
"""
|
|
1207
|
+
f = self.function
|
|
1208
|
+
# This should be done once for all by registering
|
|
1209
|
+
# sage.misc.fpickle.pickle_function to copyreg
|
|
1210
|
+
if isinstance(f, types.FunctionType):
|
|
1211
|
+
from sage.misc.fpickle import pickle_function
|
|
1212
|
+
f = pickle_function(f)
|
|
1213
|
+
|
|
1214
|
+
return {'set': self.set,
|
|
1215
|
+
'function': f}
|
|
1216
|
+
|
|
1217
|
+
def __setstate__(self, d):
|
|
1218
|
+
"""
|
|
1219
|
+
EXAMPLES::
|
|
1220
|
+
|
|
1221
|
+
sage: from sage.sets.family import LazyFamily
|
|
1222
|
+
sage: f = LazyFamily([3,4,7], lambda i: 2*i)
|
|
1223
|
+
sage: d = f.__getstate__()
|
|
1224
|
+
sage: f = LazyFamily([4,5,6], lambda i: 2*i)
|
|
1225
|
+
sage: f.__setstate__(d)
|
|
1226
|
+
sage: f.keys()
|
|
1227
|
+
[3, 4, 7]
|
|
1228
|
+
sage: f[3]
|
|
1229
|
+
6
|
|
1230
|
+
"""
|
|
1231
|
+
function = d['function']
|
|
1232
|
+
if isinstance(function, bytes):
|
|
1233
|
+
# Let's assume that function is an unpickled function.
|
|
1234
|
+
from sage.misc.fpickle import unpickle_function
|
|
1235
|
+
function = unpickle_function(function)
|
|
1236
|
+
|
|
1237
|
+
self.__init__(d['set'], function)
|
|
1238
|
+
|
|
1239
|
+
|
|
1240
|
+
class TrivialFamily(AbstractFamily):
|
|
1241
|
+
r"""
|
|
1242
|
+
:class:`TrivialFamily` turns a list/tuple `c` into a family indexed by the
|
|
1243
|
+
set `\{0, \dots, |c|-1\}`.
|
|
1244
|
+
|
|
1245
|
+
Instances should be created via the :func:`Family` factory. See its
|
|
1246
|
+
documentation for examples and tests.
|
|
1247
|
+
"""
|
|
1248
|
+
def __init__(self, enumeration):
|
|
1249
|
+
"""
|
|
1250
|
+
EXAMPLES::
|
|
1251
|
+
|
|
1252
|
+
sage: from sage.sets.family import TrivialFamily
|
|
1253
|
+
sage: f = TrivialFamily((3,4,7)); f
|
|
1254
|
+
Family (3, 4, 7)
|
|
1255
|
+
sage: f = TrivialFamily([3,4,7]); f
|
|
1256
|
+
Family (3, 4, 7)
|
|
1257
|
+
sage: TestSuite(f).run()
|
|
1258
|
+
"""
|
|
1259
|
+
Parent.__init__(self, category=FiniteEnumeratedSets())
|
|
1260
|
+
self._enumeration = tuple(enumeration)
|
|
1261
|
+
|
|
1262
|
+
def __bool__(self):
|
|
1263
|
+
r"""
|
|
1264
|
+
Return if ``self`` is empty or not.
|
|
1265
|
+
|
|
1266
|
+
EXAMPLES::
|
|
1267
|
+
|
|
1268
|
+
sage: from sage.sets.family import TrivialFamily
|
|
1269
|
+
sage: f = TrivialFamily((3,4,7))
|
|
1270
|
+
sage: bool(f)
|
|
1271
|
+
True
|
|
1272
|
+
sage: g = Family([])
|
|
1273
|
+
sage: bool(g)
|
|
1274
|
+
False
|
|
1275
|
+
"""
|
|
1276
|
+
return bool(self._enumeration)
|
|
1277
|
+
|
|
1278
|
+
def __eq__(self, other):
|
|
1279
|
+
"""
|
|
1280
|
+
TESTS::
|
|
1281
|
+
|
|
1282
|
+
sage: f = Family((3,4,7))
|
|
1283
|
+
sage: g = Family([3,4,7])
|
|
1284
|
+
sage: f == g
|
|
1285
|
+
True
|
|
1286
|
+
"""
|
|
1287
|
+
return (isinstance(other, self.__class__) and
|
|
1288
|
+
self._enumeration == other._enumeration)
|
|
1289
|
+
|
|
1290
|
+
def __hash__(self):
|
|
1291
|
+
"""
|
|
1292
|
+
Return a hash value for ``self``.
|
|
1293
|
+
|
|
1294
|
+
EXAMPLES::
|
|
1295
|
+
|
|
1296
|
+
sage: from sage.sets.family import TrivialFamily
|
|
1297
|
+
sage: f = TrivialFamily((3,4,7))
|
|
1298
|
+
sage: hash(f) == hash(f)
|
|
1299
|
+
True
|
|
1300
|
+
"""
|
|
1301
|
+
return hash(self._enumeration)
|
|
1302
|
+
|
|
1303
|
+
def _repr_(self):
|
|
1304
|
+
"""
|
|
1305
|
+
EXAMPLES::
|
|
1306
|
+
|
|
1307
|
+
sage: from sage.sets.family import TrivialFamily
|
|
1308
|
+
sage: f = TrivialFamily([3,4,7]); f # indirect doctest
|
|
1309
|
+
Family (3, 4, 7)
|
|
1310
|
+
"""
|
|
1311
|
+
return "Family %s" % ((self._enumeration),)
|
|
1312
|
+
|
|
1313
|
+
def keys(self):
|
|
1314
|
+
"""
|
|
1315
|
+
Return ``self``'s keys.
|
|
1316
|
+
|
|
1317
|
+
EXAMPLES::
|
|
1318
|
+
|
|
1319
|
+
sage: from sage.sets.family import TrivialFamily
|
|
1320
|
+
sage: f = TrivialFamily([3,4,7])
|
|
1321
|
+
sage: f.keys()
|
|
1322
|
+
[0, 1, 2]
|
|
1323
|
+
"""
|
|
1324
|
+
return list(range(len(self._enumeration)))
|
|
1325
|
+
|
|
1326
|
+
def cardinality(self):
|
|
1327
|
+
"""
|
|
1328
|
+
Return the number of elements in ``self``.
|
|
1329
|
+
|
|
1330
|
+
EXAMPLES::
|
|
1331
|
+
|
|
1332
|
+
sage: from sage.sets.family import TrivialFamily
|
|
1333
|
+
sage: f = TrivialFamily([3,4,7])
|
|
1334
|
+
sage: f.cardinality()
|
|
1335
|
+
3
|
|
1336
|
+
"""
|
|
1337
|
+
return Integer(len(self._enumeration))
|
|
1338
|
+
|
|
1339
|
+
def __iter__(self):
|
|
1340
|
+
"""
|
|
1341
|
+
EXAMPLES::
|
|
1342
|
+
|
|
1343
|
+
sage: from sage.sets.family import TrivialFamily
|
|
1344
|
+
sage: f = TrivialFamily([3,4,7])
|
|
1345
|
+
sage: [i for i in f]
|
|
1346
|
+
[3, 4, 7]
|
|
1347
|
+
"""
|
|
1348
|
+
return iter(self._enumeration)
|
|
1349
|
+
|
|
1350
|
+
def __contains__(self, x):
|
|
1351
|
+
"""
|
|
1352
|
+
EXAMPLES::
|
|
1353
|
+
|
|
1354
|
+
sage: from sage.sets.family import TrivialFamily
|
|
1355
|
+
sage: f = TrivialFamily([3,4,7])
|
|
1356
|
+
sage: 3 in f
|
|
1357
|
+
True
|
|
1358
|
+
sage: 5 in f
|
|
1359
|
+
False
|
|
1360
|
+
"""
|
|
1361
|
+
return x in self._enumeration
|
|
1362
|
+
|
|
1363
|
+
def __getitem__(self, i):
|
|
1364
|
+
"""
|
|
1365
|
+
EXAMPLES::
|
|
1366
|
+
|
|
1367
|
+
sage: from sage.sets.family import TrivialFamily
|
|
1368
|
+
sage: f = TrivialFamily([3,4,7])
|
|
1369
|
+
sage: f[1]
|
|
1370
|
+
4
|
|
1371
|
+
"""
|
|
1372
|
+
return self._enumeration[i]
|
|
1373
|
+
|
|
1374
|
+
def __getstate__(self):
|
|
1375
|
+
"""
|
|
1376
|
+
TESTS::
|
|
1377
|
+
|
|
1378
|
+
sage: from sage.sets.family import TrivialFamily
|
|
1379
|
+
sage: f = TrivialFamily([3,4,7])
|
|
1380
|
+
sage: f.__getstate__()
|
|
1381
|
+
{'_enumeration': (3, 4, 7)}
|
|
1382
|
+
"""
|
|
1383
|
+
return {'_enumeration': self._enumeration}
|
|
1384
|
+
|
|
1385
|
+
def __setstate__(self, state):
|
|
1386
|
+
"""
|
|
1387
|
+
TESTS::
|
|
1388
|
+
|
|
1389
|
+
sage: from sage.sets.family import TrivialFamily
|
|
1390
|
+
sage: f = TrivialFamily([3,4,7])
|
|
1391
|
+
sage: f.__setstate__({'_enumeration': (2, 4, 8)})
|
|
1392
|
+
sage: f
|
|
1393
|
+
Family (2, 4, 8)
|
|
1394
|
+
"""
|
|
1395
|
+
self.__init__(state['_enumeration'])
|
|
1396
|
+
|
|
1397
|
+
def map(self, f, name=None):
|
|
1398
|
+
r"""
|
|
1399
|
+
Return the family `( f(\mathtt{self}[i]) )_{i \in I}`,
|
|
1400
|
+
where `I` is the index set of ``self``.
|
|
1401
|
+
|
|
1402
|
+
The result is again a :class:`TrivialFamily`.
|
|
1403
|
+
|
|
1404
|
+
EXAMPLES::
|
|
1405
|
+
|
|
1406
|
+
sage: from sage.sets.family import TrivialFamily
|
|
1407
|
+
sage: f = TrivialFamily(['a', 'b', 'd'])
|
|
1408
|
+
sage: g = f.map(lambda x: x + '1'); g
|
|
1409
|
+
Family ('a1', 'b1', 'd1')
|
|
1410
|
+
"""
|
|
1411
|
+
# tuple([... for ...]) is faster than tuple(... for ...)
|
|
1412
|
+
return Family(tuple([f(x) for x in self._enumeration]), name=name)
|
|
1413
|
+
|
|
1414
|
+
|
|
1415
|
+
class EnumeratedFamily(LazyFamily):
|
|
1416
|
+
r"""
|
|
1417
|
+
:class:`EnumeratedFamily` turns an enumerated set ``c`` into a family
|
|
1418
|
+
indexed by the set `\{0,\dots, |c|-1\}` (or ``NN`` if `|c|` is
|
|
1419
|
+
countably infinite).
|
|
1420
|
+
|
|
1421
|
+
Instances should be created via the :func:`Family` factory. See its
|
|
1422
|
+
documentation for examples and tests.
|
|
1423
|
+
"""
|
|
1424
|
+
def __init__(self, enumset):
|
|
1425
|
+
"""
|
|
1426
|
+
EXAMPLES::
|
|
1427
|
+
|
|
1428
|
+
sage: from sage.sets.family import EnumeratedFamily
|
|
1429
|
+
sage: f = EnumeratedFamily(Permutations(3))
|
|
1430
|
+
sage: TestSuite(f).run()
|
|
1431
|
+
|
|
1432
|
+
sage: f = Family(NonNegativeIntegers())
|
|
1433
|
+
sage: TestSuite(f).run()
|
|
1434
|
+
|
|
1435
|
+
TESTS:
|
|
1436
|
+
|
|
1437
|
+
Check that category and keys are set correctly (:issue:`28274`)::
|
|
1438
|
+
|
|
1439
|
+
sage: from sage.sets.family import EnumeratedFamily
|
|
1440
|
+
sage: f = EnumeratedFamily(Permutations(4))
|
|
1441
|
+
sage: f.category()
|
|
1442
|
+
Category of finite enumerated sets
|
|
1443
|
+
sage: list(f.keys()) == list(range(f.cardinality()))
|
|
1444
|
+
True
|
|
1445
|
+
sage: Family(Permutations()).keys()
|
|
1446
|
+
Non negative integers
|
|
1447
|
+
sage: type(Family(NN))
|
|
1448
|
+
<class 'sage.sets.family.EnumeratedFamily_with_category'>
|
|
1449
|
+
"""
|
|
1450
|
+
if enumset.cardinality() == Infinity:
|
|
1451
|
+
baseset = NonNegativeIntegers()
|
|
1452
|
+
else:
|
|
1453
|
+
baseset = range(enumset.cardinality())
|
|
1454
|
+
LazyFamily.__init__(self, baseset, enumset.unrank)
|
|
1455
|
+
self.enumset = enumset
|
|
1456
|
+
|
|
1457
|
+
def __eq__(self, other):
|
|
1458
|
+
"""
|
|
1459
|
+
EXAMPLES::
|
|
1460
|
+
|
|
1461
|
+
sage: f = Family(Permutations(3))
|
|
1462
|
+
sage: g = Family(Permutations(3))
|
|
1463
|
+
sage: f == g
|
|
1464
|
+
True
|
|
1465
|
+
"""
|
|
1466
|
+
return (isinstance(other, self.__class__) and
|
|
1467
|
+
self.enumset == other.enumset)
|
|
1468
|
+
|
|
1469
|
+
def __repr__(self):
|
|
1470
|
+
"""
|
|
1471
|
+
EXAMPLES::
|
|
1472
|
+
|
|
1473
|
+
sage: f = Family(Permutations(3)); f # indirect doctest
|
|
1474
|
+
Family (Standard permutations of 3)
|
|
1475
|
+
|
|
1476
|
+
sage: f = Family(NonNegativeIntegers()); f
|
|
1477
|
+
Family (Non negative integers)
|
|
1478
|
+
"""
|
|
1479
|
+
# return "Family ((%s)[i])_(i=1...%s)"%(self.enumset, self.enumset.cardinality())
|
|
1480
|
+
if isinstance(self.enumset, FiniteEnumeratedSet):
|
|
1481
|
+
return "Family %s" % (self.enumset._elements,)
|
|
1482
|
+
return "Family (%s)" % (self.enumset)
|
|
1483
|
+
|
|
1484
|
+
def __contains__(self, x):
|
|
1485
|
+
"""
|
|
1486
|
+
EXAMPLES::
|
|
1487
|
+
|
|
1488
|
+
sage: f = Family(Permutations(3))
|
|
1489
|
+
sage: [2,1,3] in f
|
|
1490
|
+
True
|
|
1491
|
+
"""
|
|
1492
|
+
return x in self.enumset
|
|
1493
|
+
|
|
1494
|
+
def cardinality(self):
|
|
1495
|
+
"""
|
|
1496
|
+
Return the number of elements in ``self``.
|
|
1497
|
+
|
|
1498
|
+
EXAMPLES::
|
|
1499
|
+
|
|
1500
|
+
sage: from sage.sets.family import EnumeratedFamily
|
|
1501
|
+
sage: f = EnumeratedFamily(Permutations(3))
|
|
1502
|
+
sage: f.cardinality()
|
|
1503
|
+
6
|
|
1504
|
+
|
|
1505
|
+
sage: f = Family(NonNegativeIntegers())
|
|
1506
|
+
sage: f.cardinality()
|
|
1507
|
+
+Infinity
|
|
1508
|
+
"""
|
|
1509
|
+
return self.enumset.cardinality()
|
|
1510
|
+
|
|
1511
|
+
def __iter__(self):
|
|
1512
|
+
"""
|
|
1513
|
+
EXAMPLES::
|
|
1514
|
+
|
|
1515
|
+
sage: from sage.sets.family import EnumeratedFamily
|
|
1516
|
+
sage: f = EnumeratedFamily(Permutations(3))
|
|
1517
|
+
sage: [i for i in f]
|
|
1518
|
+
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
|
|
1519
|
+
"""
|
|
1520
|
+
yield from self.enumset
|
|
1521
|
+
|
|
1522
|
+
def __getitem__(self, i):
|
|
1523
|
+
"""
|
|
1524
|
+
EXAMPLES::
|
|
1525
|
+
|
|
1526
|
+
sage: from sage.sets.family import EnumeratedFamily
|
|
1527
|
+
sage: f = EnumeratedFamily(Permutations(3))
|
|
1528
|
+
sage: f[1]
|
|
1529
|
+
[1, 3, 2]
|
|
1530
|
+
"""
|
|
1531
|
+
return self.enumset.unrank(i)
|
|
1532
|
+
|
|
1533
|
+
def __getstate__(self):
|
|
1534
|
+
"""
|
|
1535
|
+
EXAMPLES::
|
|
1536
|
+
|
|
1537
|
+
sage: from sage.sets.family import EnumeratedFamily
|
|
1538
|
+
sage: f = EnumeratedFamily(Permutations(3))
|
|
1539
|
+
sage: f.__getstate__()
|
|
1540
|
+
{'enumset': Standard permutations of 3}
|
|
1541
|
+
sage: loads(dumps(f)) == f
|
|
1542
|
+
True
|
|
1543
|
+
"""
|
|
1544
|
+
return {'enumset': self.enumset}
|
|
1545
|
+
|
|
1546
|
+
def __setstate__(self, state):
|
|
1547
|
+
"""
|
|
1548
|
+
EXAMPLES::
|
|
1549
|
+
|
|
1550
|
+
sage: from sage.sets.family import EnumeratedFamily
|
|
1551
|
+
sage: f = EnumeratedFamily(Permutations(0))
|
|
1552
|
+
sage: f.__setstate__({'enumset': Permutations(3)})
|
|
1553
|
+
sage: f
|
|
1554
|
+
Family (Standard permutations of 3)
|
|
1555
|
+
"""
|
|
1556
|
+
self.__init__(state['enumset'])
|