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,3312 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
r"""
|
|
3
|
+
Mutable Poset
|
|
4
|
+
|
|
5
|
+
This module provides a class representing a finite partially ordered
|
|
6
|
+
set (poset) for the purpose of being used as a data structure. Thus
|
|
7
|
+
the posets introduced in this module are mutable, i.e., elements can
|
|
8
|
+
be added and removed from a poset at any time.
|
|
9
|
+
|
|
10
|
+
To get in touch with Sage's "usual" posets, start with the page
|
|
11
|
+
:mod:`Posets <sage.combinat.posets.__init__>` in the reference manual.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
.. _mutable_poset_examples:
|
|
15
|
+
|
|
16
|
+
Examples
|
|
17
|
+
========
|
|
18
|
+
|
|
19
|
+
First Steps
|
|
20
|
+
-----------
|
|
21
|
+
|
|
22
|
+
We start by creating an empty poset. This is simply done by
|
|
23
|
+
|
|
24
|
+
::
|
|
25
|
+
|
|
26
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
27
|
+
sage: P = MP()
|
|
28
|
+
sage: P
|
|
29
|
+
poset()
|
|
30
|
+
|
|
31
|
+
A poset should contain elements, thus let us add them with
|
|
32
|
+
|
|
33
|
+
::
|
|
34
|
+
|
|
35
|
+
sage: P.add(42)
|
|
36
|
+
sage: P.add(7)
|
|
37
|
+
sage: P.add(13)
|
|
38
|
+
sage: P.add(3)
|
|
39
|
+
|
|
40
|
+
Let us look at the poset again::
|
|
41
|
+
|
|
42
|
+
sage: P
|
|
43
|
+
poset(3, 7, 13, 42)
|
|
44
|
+
|
|
45
|
+
We see that they elements are sorted using `\leq` which exists on the
|
|
46
|
+
integers `\ZZ`. Since this is even a total order, we could have used a
|
|
47
|
+
more efficient data structure. Alternatively, we can write
|
|
48
|
+
::
|
|
49
|
+
|
|
50
|
+
sage: MP([42, 7, 13, 3])
|
|
51
|
+
poset(3, 7, 13, 42)
|
|
52
|
+
|
|
53
|
+
to add several elements at once on construction.
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
A less boring Example
|
|
57
|
+
---------------------
|
|
58
|
+
|
|
59
|
+
Let us continue with a less boring example. We define the class
|
|
60
|
+
|
|
61
|
+
::
|
|
62
|
+
|
|
63
|
+
sage: class T(tuple):
|
|
64
|
+
....: def __le__(left, right):
|
|
65
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
66
|
+
|
|
67
|
+
It is equipped with a `\leq`-operation such that `a \leq b` if all
|
|
68
|
+
entries of `a` are at most the corresponding entry of `b`. For
|
|
69
|
+
example, we have
|
|
70
|
+
|
|
71
|
+
::
|
|
72
|
+
|
|
73
|
+
sage: a = T((1,1))
|
|
74
|
+
sage: b = T((2,1))
|
|
75
|
+
sage: c = T((1,2))
|
|
76
|
+
sage: a <= b, a <= c, b <= c
|
|
77
|
+
(True, True, False)
|
|
78
|
+
|
|
79
|
+
The last comparison gives ``False``, since the comparison of the
|
|
80
|
+
first component checks whether `2 \leq 1`.
|
|
81
|
+
|
|
82
|
+
Now, let us add such elements to a poset::
|
|
83
|
+
|
|
84
|
+
sage: Q = MP([T((1, 1)), T((3, 3)), T((4, 1)),
|
|
85
|
+
....: T((3, 2)), T((2, 3)), T((2, 2))]); Q
|
|
86
|
+
poset((1, 1), (2, 2), (2, 3), (3, 2), (3, 3), (4, 1))
|
|
87
|
+
|
|
88
|
+
In the representation above, the elements are sorted topologically,
|
|
89
|
+
smallest first. This does not (directly) show more structural
|
|
90
|
+
information. We can overcome this and display a "wiring layout" by
|
|
91
|
+
typing::
|
|
92
|
+
|
|
93
|
+
sage: print(Q.repr_full(reverse=True))
|
|
94
|
+
poset((3, 3), (2, 3), (3, 2), (2, 2), (4, 1), (1, 1))
|
|
95
|
+
+-- oo
|
|
96
|
+
| +-- no successors
|
|
97
|
+
| +-- predecessors: (3, 3), (4, 1)
|
|
98
|
+
+-- (3, 3)
|
|
99
|
+
| +-- successors: oo
|
|
100
|
+
| +-- predecessors: (2, 3), (3, 2)
|
|
101
|
+
+-- (2, 3)
|
|
102
|
+
| +-- successors: (3, 3)
|
|
103
|
+
| +-- predecessors: (2, 2)
|
|
104
|
+
+-- (3, 2)
|
|
105
|
+
| +-- successors: (3, 3)
|
|
106
|
+
| +-- predecessors: (2, 2)
|
|
107
|
+
+-- (2, 2)
|
|
108
|
+
| +-- successors: (2, 3), (3, 2)
|
|
109
|
+
| +-- predecessors: (1, 1)
|
|
110
|
+
+-- (4, 1)
|
|
111
|
+
| +-- successors: oo
|
|
112
|
+
| +-- predecessors: (1, 1)
|
|
113
|
+
+-- (1, 1)
|
|
114
|
+
| +-- successors: (2, 2), (4, 1)
|
|
115
|
+
| +-- predecessors: null
|
|
116
|
+
+-- null
|
|
117
|
+
| +-- successors: (1, 1)
|
|
118
|
+
| +-- no predecessors
|
|
119
|
+
|
|
120
|
+
Note that we use ``reverse=True`` to let the elements appear from
|
|
121
|
+
largest (on the top) to smallest (on the bottom).
|
|
122
|
+
|
|
123
|
+
If you look at the output above, you'll see two additional elements,
|
|
124
|
+
namely ``oo`` (`\infty`) and ``null`` (`\emptyset`). So what are these
|
|
125
|
+
strange animals? The answer is simple and maybe you can guess it
|
|
126
|
+
already. The `\infty`-element is larger than every other element,
|
|
127
|
+
therefore a successor of the maximal elements in the poset. Similarly,
|
|
128
|
+
the `\emptyset`-element is smaller than any other element, therefore a
|
|
129
|
+
predecessor of the poset's minimal elements. Both do not have to scare
|
|
130
|
+
us; they are just there and sometimes useful.
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
AUTHORS:
|
|
134
|
+
|
|
135
|
+
- Daniel Krenn (2015)
|
|
136
|
+
|
|
137
|
+
ACKNOWLEDGEMENT:
|
|
138
|
+
|
|
139
|
+
- Daniel Krenn is supported by the Austrian Science Fund (FWF): P 24644-N26.
|
|
140
|
+
|
|
141
|
+
Classes and their Methods
|
|
142
|
+
=========================
|
|
143
|
+
"""
|
|
144
|
+
# ****************************************************************************
|
|
145
|
+
# Copyright (C) 2015 Daniel Krenn <dev@danielkrenn.at>
|
|
146
|
+
#
|
|
147
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
148
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
149
|
+
# the License, or (at your option) any later version.
|
|
150
|
+
# https://www.gnu.org/licenses/
|
|
151
|
+
# ****************************************************************************
|
|
152
|
+
|
|
153
|
+
from sage.structure.sage_object import SageObject
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class MutablePosetShell(SageObject):
|
|
157
|
+
r"""
|
|
158
|
+
A shell for an element of a :class:`mutable poset <MutablePoset>`.
|
|
159
|
+
|
|
160
|
+
INPUT:
|
|
161
|
+
|
|
162
|
+
- ``poset`` -- the poset to which this shell belongs
|
|
163
|
+
|
|
164
|
+
- ``element`` -- the element which should be
|
|
165
|
+
contained/encapsulated in this shell
|
|
166
|
+
|
|
167
|
+
OUTPUT: a shell for the given element
|
|
168
|
+
|
|
169
|
+
.. NOTE::
|
|
170
|
+
|
|
171
|
+
If the :meth:`element` of a shell is ``None``, then this
|
|
172
|
+
element is considered as "special" (see :meth:`is_special`).
|
|
173
|
+
There are two special elements, namely
|
|
174
|
+
|
|
175
|
+
- a ``'null'`` (an element smaller than each other element;
|
|
176
|
+
it has no predecessors) and
|
|
177
|
+
- an ``'oo'`` (an element larger than each other element;
|
|
178
|
+
it has no successors).
|
|
179
|
+
|
|
180
|
+
EXAMPLES::
|
|
181
|
+
|
|
182
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
183
|
+
sage: P = MP()
|
|
184
|
+
sage: P.add(66)
|
|
185
|
+
sage: P
|
|
186
|
+
poset(66)
|
|
187
|
+
sage: s = P.shell(66)
|
|
188
|
+
sage: type(s)
|
|
189
|
+
<class 'sage.data_structures.mutable_poset.MutablePosetShell'>
|
|
190
|
+
|
|
191
|
+
.. SEEALSO::
|
|
192
|
+
|
|
193
|
+
:class:`MutablePoset`
|
|
194
|
+
"""
|
|
195
|
+
def __init__(self, poset, element):
|
|
196
|
+
r"""
|
|
197
|
+
See :class:`MutablePosetShell` for details.
|
|
198
|
+
|
|
199
|
+
TESTS::
|
|
200
|
+
|
|
201
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
202
|
+
sage: P = MP()
|
|
203
|
+
sage: from sage.data_structures.mutable_poset import MutablePosetShell
|
|
204
|
+
sage: MutablePosetShell(P, (1, 2))
|
|
205
|
+
(1, 2)
|
|
206
|
+
"""
|
|
207
|
+
self._poset_ = poset
|
|
208
|
+
self._element_ = element
|
|
209
|
+
self._key_ = self.poset.get_key(element)
|
|
210
|
+
self._predecessors_ = set()
|
|
211
|
+
self._successors_ = set()
|
|
212
|
+
super().__init__()
|
|
213
|
+
|
|
214
|
+
@property
|
|
215
|
+
def poset(self):
|
|
216
|
+
r"""
|
|
217
|
+
The poset to which this shell belongs.
|
|
218
|
+
|
|
219
|
+
.. SEEALSO::
|
|
220
|
+
|
|
221
|
+
:class:`MutablePoset`
|
|
222
|
+
|
|
223
|
+
TESTS::
|
|
224
|
+
|
|
225
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
226
|
+
sage: P = MP()
|
|
227
|
+
sage: from sage.data_structures.mutable_poset import MutablePosetShell
|
|
228
|
+
sage: e = MutablePosetShell(P, (1, 2))
|
|
229
|
+
sage: e.poset is P
|
|
230
|
+
True
|
|
231
|
+
"""
|
|
232
|
+
return self._poset_
|
|
233
|
+
|
|
234
|
+
@property
|
|
235
|
+
def element(self):
|
|
236
|
+
r"""
|
|
237
|
+
The element contained in this shell.
|
|
238
|
+
|
|
239
|
+
.. SEEALSO::
|
|
240
|
+
|
|
241
|
+
:meth:`key`,
|
|
242
|
+
:class:`MutablePoset`.
|
|
243
|
+
|
|
244
|
+
TESTS::
|
|
245
|
+
|
|
246
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
247
|
+
sage: P = MP()
|
|
248
|
+
sage: from sage.data_structures.mutable_poset import MutablePosetShell
|
|
249
|
+
sage: e = MutablePosetShell(P, (1, 2))
|
|
250
|
+
sage: e.element
|
|
251
|
+
(1, 2)
|
|
252
|
+
"""
|
|
253
|
+
return self._element_
|
|
254
|
+
|
|
255
|
+
@property
|
|
256
|
+
def key(self):
|
|
257
|
+
r"""
|
|
258
|
+
The key of the element contained in this shell.
|
|
259
|
+
|
|
260
|
+
The key of an element is determined by the mutable poset (the
|
|
261
|
+
parent) via the ``key``-function (see construction of a
|
|
262
|
+
:class:`MutablePoset`).
|
|
263
|
+
|
|
264
|
+
.. SEEALSO::
|
|
265
|
+
|
|
266
|
+
:meth:`element`,
|
|
267
|
+
:class:`MutablePoset`.
|
|
268
|
+
|
|
269
|
+
TESTS::
|
|
270
|
+
|
|
271
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
272
|
+
sage: from sage.data_structures.mutable_poset import MutablePosetShell
|
|
273
|
+
sage: P = MP()
|
|
274
|
+
sage: e = MutablePosetShell(P, (1, 2))
|
|
275
|
+
sage: e.key
|
|
276
|
+
(1, 2)
|
|
277
|
+
sage: Q = MP(key=lambda k: k[0])
|
|
278
|
+
sage: f = MutablePosetShell(Q, (1, 2))
|
|
279
|
+
sage: f.key
|
|
280
|
+
1
|
|
281
|
+
|
|
282
|
+
Test the caching of the key::
|
|
283
|
+
|
|
284
|
+
sage: def k(k):
|
|
285
|
+
....: print('key %s' % (k,))
|
|
286
|
+
....: return k
|
|
287
|
+
sage: R = MP(key=k)
|
|
288
|
+
sage: h = MutablePosetShell(R, (1, 2))
|
|
289
|
+
key (1, 2)
|
|
290
|
+
sage: h.key; h.key
|
|
291
|
+
(1, 2)
|
|
292
|
+
(1, 2)
|
|
293
|
+
"""
|
|
294
|
+
return self._key_
|
|
295
|
+
|
|
296
|
+
def predecessors(self, reverse=False):
|
|
297
|
+
r"""
|
|
298
|
+
Return the predecessors of this shell.
|
|
299
|
+
|
|
300
|
+
INPUT:
|
|
301
|
+
|
|
302
|
+
- ``reverse`` -- boolean (default: ``False``); if set, then return
|
|
303
|
+
successors instead
|
|
304
|
+
|
|
305
|
+
OUTPUT: set
|
|
306
|
+
|
|
307
|
+
.. SEEALSO::
|
|
308
|
+
|
|
309
|
+
:meth:`successors`,
|
|
310
|
+
:class:`MutablePoset`.
|
|
311
|
+
|
|
312
|
+
TESTS::
|
|
313
|
+
|
|
314
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
315
|
+
sage: P = MP()
|
|
316
|
+
sage: from sage.data_structures.mutable_poset import MutablePosetShell
|
|
317
|
+
sage: e = MutablePosetShell(P, (1, 2))
|
|
318
|
+
sage: e.predecessors()
|
|
319
|
+
set()
|
|
320
|
+
"""
|
|
321
|
+
if reverse:
|
|
322
|
+
return self._successors_
|
|
323
|
+
return self._predecessors_
|
|
324
|
+
|
|
325
|
+
def successors(self, reverse=False):
|
|
326
|
+
r"""
|
|
327
|
+
Return the successors of this shell.
|
|
328
|
+
|
|
329
|
+
INPUT:
|
|
330
|
+
|
|
331
|
+
- ``reverse`` -- boolean (default: ``False``); if set, then return
|
|
332
|
+
predecessors instead
|
|
333
|
+
|
|
334
|
+
OUTPUT: set
|
|
335
|
+
|
|
336
|
+
.. SEEALSO::
|
|
337
|
+
|
|
338
|
+
:meth:`predecessors`,
|
|
339
|
+
:class:`MutablePoset`.
|
|
340
|
+
|
|
341
|
+
TESTS::
|
|
342
|
+
|
|
343
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
344
|
+
sage: P = MP()
|
|
345
|
+
sage: from sage.data_structures.mutable_poset import MutablePosetShell
|
|
346
|
+
sage: e = MutablePosetShell(P, (1, 2))
|
|
347
|
+
sage: e.successors()
|
|
348
|
+
set()
|
|
349
|
+
"""
|
|
350
|
+
if reverse:
|
|
351
|
+
return self._predecessors_
|
|
352
|
+
return self._successors_
|
|
353
|
+
|
|
354
|
+
def is_special(self):
|
|
355
|
+
r"""
|
|
356
|
+
Return whether this shell contains either the null-element, i.e., the
|
|
357
|
+
element smaller than any possible other element or the
|
|
358
|
+
infinity-element, i.e., the element larger than any possible
|
|
359
|
+
other element.
|
|
360
|
+
|
|
361
|
+
OUTPUT: boolean
|
|
362
|
+
|
|
363
|
+
.. SEEALSO::
|
|
364
|
+
|
|
365
|
+
:meth:`is_null`,
|
|
366
|
+
:meth:`is_oo`,
|
|
367
|
+
:class:`MutablePoset`.
|
|
368
|
+
|
|
369
|
+
TESTS::
|
|
370
|
+
|
|
371
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
372
|
+
sage: P = MP()
|
|
373
|
+
sage: P.null.is_special()
|
|
374
|
+
True
|
|
375
|
+
sage: P.oo.is_special()
|
|
376
|
+
True
|
|
377
|
+
"""
|
|
378
|
+
return self.element is None
|
|
379
|
+
|
|
380
|
+
def is_null(self):
|
|
381
|
+
r"""
|
|
382
|
+
Return whether this shell contains the null-element, i.e., the element
|
|
383
|
+
smaller than any possible other element.
|
|
384
|
+
|
|
385
|
+
OUTPUT: boolean
|
|
386
|
+
|
|
387
|
+
.. SEEALSO::
|
|
388
|
+
|
|
389
|
+
:meth:`is_special`,
|
|
390
|
+
:meth:`is_oo`,
|
|
391
|
+
:meth:`MutablePoset.null`,
|
|
392
|
+
:class:`MutablePoset`.
|
|
393
|
+
|
|
394
|
+
TESTS::
|
|
395
|
+
|
|
396
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
397
|
+
sage: P = MP()
|
|
398
|
+
sage: P.null.is_null()
|
|
399
|
+
True
|
|
400
|
+
sage: P.oo.is_null()
|
|
401
|
+
False
|
|
402
|
+
"""
|
|
403
|
+
return self.element is None and not self.predecessors()
|
|
404
|
+
|
|
405
|
+
def is_oo(self):
|
|
406
|
+
r"""
|
|
407
|
+
Return whether this shell contains the infinity-element, i.e., the element
|
|
408
|
+
larger than any possible other element.
|
|
409
|
+
|
|
410
|
+
OUTPUT: boolean
|
|
411
|
+
|
|
412
|
+
.. SEEALSO::
|
|
413
|
+
|
|
414
|
+
:meth:`is_null`,
|
|
415
|
+
:meth:`is_special`,
|
|
416
|
+
:meth:`MutablePoset.oo`,
|
|
417
|
+
:class:`MutablePoset`.
|
|
418
|
+
|
|
419
|
+
TESTS::
|
|
420
|
+
|
|
421
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
422
|
+
sage: P = MP()
|
|
423
|
+
sage: P.null.is_oo()
|
|
424
|
+
False
|
|
425
|
+
sage: P.oo.is_oo()
|
|
426
|
+
True
|
|
427
|
+
"""
|
|
428
|
+
return self.element is None and not self.successors()
|
|
429
|
+
|
|
430
|
+
def _repr_(self):
|
|
431
|
+
r"""
|
|
432
|
+
Return the representation of this shell.
|
|
433
|
+
|
|
434
|
+
OUTPUT: string
|
|
435
|
+
|
|
436
|
+
.. NOTE::
|
|
437
|
+
|
|
438
|
+
If the :meth:`element` of this shell is not ``None``,
|
|
439
|
+
this method returns the respective representation string.
|
|
440
|
+
Otherwise, ``'null'`` or ``'oo'`` are returned,
|
|
441
|
+
depending on the non-existence of predecessors or
|
|
442
|
+
successors, respectively.
|
|
443
|
+
|
|
444
|
+
TESTS::
|
|
445
|
+
|
|
446
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
447
|
+
sage: P = MP()
|
|
448
|
+
sage: from sage.data_structures.mutable_poset import MutablePosetShell
|
|
449
|
+
sage: repr(MutablePosetShell(P, (1, 2))) # indirect doctest
|
|
450
|
+
'(1, 2)'
|
|
451
|
+
sage: repr(P.null) # indirect doctest
|
|
452
|
+
'null'
|
|
453
|
+
sage: repr(P.oo) # indirect doctest
|
|
454
|
+
'oo'
|
|
455
|
+
"""
|
|
456
|
+
if self.is_null():
|
|
457
|
+
return 'null'
|
|
458
|
+
elif self.is_oo():
|
|
459
|
+
return 'oo'
|
|
460
|
+
else:
|
|
461
|
+
return repr(self.element)
|
|
462
|
+
|
|
463
|
+
def __hash__(self):
|
|
464
|
+
r"""
|
|
465
|
+
Return the hash of this shell.
|
|
466
|
+
|
|
467
|
+
OUTPUT: a hash value
|
|
468
|
+
|
|
469
|
+
This returns the hash value of the key of the element
|
|
470
|
+
contained in this shell.
|
|
471
|
+
|
|
472
|
+
TESTS::
|
|
473
|
+
|
|
474
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
475
|
+
sage: P = MP()
|
|
476
|
+
sage: from sage.data_structures.mutable_poset import MutablePosetShell
|
|
477
|
+
sage: hash(MutablePosetShell(P, (1, 2))) == hash((1, 2))
|
|
478
|
+
True
|
|
479
|
+
"""
|
|
480
|
+
return hash(self.key)
|
|
481
|
+
|
|
482
|
+
def le(self, other, reverse=False):
|
|
483
|
+
r"""
|
|
484
|
+
Return whether this shell is less than or equal to ``other``.
|
|
485
|
+
|
|
486
|
+
INPUT:
|
|
487
|
+
|
|
488
|
+
- ``other`` -- a shell
|
|
489
|
+
|
|
490
|
+
- ``reverse`` -- boolean (default: ``False``); if set, then return
|
|
491
|
+
whether this shell is greater than or equal to ``other``
|
|
492
|
+
|
|
493
|
+
OUTPUT: boolean
|
|
494
|
+
|
|
495
|
+
.. NOTE::
|
|
496
|
+
|
|
497
|
+
The comparison of the shells is based on the comparison
|
|
498
|
+
of the keys of the elements contained in the shells,
|
|
499
|
+
except for special shells (see :class:`MutablePosetShell`).
|
|
500
|
+
|
|
501
|
+
.. SEEALSO::
|
|
502
|
+
|
|
503
|
+
:meth:`eq`,
|
|
504
|
+
:class:`MutablePoset`.
|
|
505
|
+
|
|
506
|
+
TESTS::
|
|
507
|
+
|
|
508
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
509
|
+
sage: P = MP()
|
|
510
|
+
sage: from sage.data_structures.mutable_poset import MutablePosetShell
|
|
511
|
+
sage: e = MutablePosetShell(P, (1, 2))
|
|
512
|
+
sage: z = P.null
|
|
513
|
+
sage: oo = P.oo
|
|
514
|
+
sage: z <= e # indirect doctest
|
|
515
|
+
True
|
|
516
|
+
sage: e <= oo # indirect doctest
|
|
517
|
+
True
|
|
518
|
+
sage: z <= oo # indirect doctest
|
|
519
|
+
True
|
|
520
|
+
sage: oo <= z # indirect doctest
|
|
521
|
+
False
|
|
522
|
+
sage: oo <= e # indirect doctest
|
|
523
|
+
False
|
|
524
|
+
sage: e <= z # indirect doctest
|
|
525
|
+
False
|
|
526
|
+
sage: z <= z # indirect doctest
|
|
527
|
+
True
|
|
528
|
+
sage: oo <= oo # indirect doctest
|
|
529
|
+
True
|
|
530
|
+
sage: e <= e # indirect doctest
|
|
531
|
+
True
|
|
532
|
+
|
|
533
|
+
::
|
|
534
|
+
|
|
535
|
+
sage: z.le(e, reverse=True)
|
|
536
|
+
False
|
|
537
|
+
sage: e.le(oo, reverse=True)
|
|
538
|
+
False
|
|
539
|
+
sage: z.le(oo, reverse=True)
|
|
540
|
+
False
|
|
541
|
+
sage: oo.le(z, reverse=True)
|
|
542
|
+
True
|
|
543
|
+
sage: oo.le(e, reverse=True)
|
|
544
|
+
True
|
|
545
|
+
sage: e.le(z, reverse=True)
|
|
546
|
+
True
|
|
547
|
+
sage: z.le(z, reverse=True)
|
|
548
|
+
True
|
|
549
|
+
sage: oo.le(oo, reverse=True)
|
|
550
|
+
True
|
|
551
|
+
sage: e.le(e, reverse=True)
|
|
552
|
+
True
|
|
553
|
+
"""
|
|
554
|
+
if reverse:
|
|
555
|
+
return other.le(self, reverse=False)
|
|
556
|
+
|
|
557
|
+
if self.element is None:
|
|
558
|
+
if not self._predecessors_:
|
|
559
|
+
# null on the left
|
|
560
|
+
return True
|
|
561
|
+
else:
|
|
562
|
+
# oo on the left
|
|
563
|
+
if other.element is None:
|
|
564
|
+
# null or oo on the right
|
|
565
|
+
return not other._successors_
|
|
566
|
+
else:
|
|
567
|
+
# not null, not oo on the right
|
|
568
|
+
return False
|
|
569
|
+
elif other.element is None:
|
|
570
|
+
# null/oo on the right
|
|
571
|
+
return not other._successors_
|
|
572
|
+
|
|
573
|
+
return self.key <= other.key
|
|
574
|
+
|
|
575
|
+
__le__ = le
|
|
576
|
+
|
|
577
|
+
def eq(self, other):
|
|
578
|
+
r"""
|
|
579
|
+
Return whether this shell is equal to ``other``.
|
|
580
|
+
|
|
581
|
+
INPUT:
|
|
582
|
+
|
|
583
|
+
- ``other`` -- a shell
|
|
584
|
+
|
|
585
|
+
OUTPUT: boolean
|
|
586
|
+
|
|
587
|
+
.. NOTE::
|
|
588
|
+
|
|
589
|
+
This method compares the keys of the elements contained
|
|
590
|
+
in the (non-special) shells. In particular,
|
|
591
|
+
elements/shells with the same key are considered as equal.
|
|
592
|
+
|
|
593
|
+
.. SEEALSO::
|
|
594
|
+
|
|
595
|
+
:meth:`le`,
|
|
596
|
+
:class:`MutablePoset`.
|
|
597
|
+
|
|
598
|
+
TESTS::
|
|
599
|
+
|
|
600
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
601
|
+
sage: P = MP()
|
|
602
|
+
sage: from sage.data_structures.mutable_poset import MutablePosetShell
|
|
603
|
+
sage: e = MutablePosetShell(P, (1, 2))
|
|
604
|
+
sage: f = MutablePosetShell(P, (2, 1))
|
|
605
|
+
sage: z = P.null
|
|
606
|
+
sage: oo = P.oo
|
|
607
|
+
sage: z == z
|
|
608
|
+
True
|
|
609
|
+
sage: oo == oo
|
|
610
|
+
True
|
|
611
|
+
sage: e == e
|
|
612
|
+
True
|
|
613
|
+
sage: e == f
|
|
614
|
+
False
|
|
615
|
+
sage: z == e
|
|
616
|
+
False
|
|
617
|
+
sage: e == oo
|
|
618
|
+
False
|
|
619
|
+
sage: oo == z
|
|
620
|
+
False
|
|
621
|
+
|
|
622
|
+
Comparing elements in different mutable posets is possible; their
|
|
623
|
+
shells are equal if their elements are::
|
|
624
|
+
|
|
625
|
+
sage: S = MP([42]); s = S.shell(42)
|
|
626
|
+
sage: T = MP([42]); t = T.shell(42)
|
|
627
|
+
sage: s == t
|
|
628
|
+
True
|
|
629
|
+
sage: S.oo == T.oo
|
|
630
|
+
True
|
|
631
|
+
"""
|
|
632
|
+
if self.element is None and other.element is None:
|
|
633
|
+
return self.is_null() == other.is_null()
|
|
634
|
+
return self.key == other.key
|
|
635
|
+
|
|
636
|
+
__eq__ = eq
|
|
637
|
+
|
|
638
|
+
def _copy_all_linked_(self, memo, poset, mapping):
|
|
639
|
+
r"""
|
|
640
|
+
Return a copy of this shell. All shells linked to this shell
|
|
641
|
+
are copied as well.
|
|
642
|
+
|
|
643
|
+
This is a helper function for :meth:`MutablePoset.copy`.
|
|
644
|
+
|
|
645
|
+
INPUT:
|
|
646
|
+
|
|
647
|
+
- ``memo`` -- dictionary which assigns to the id of the
|
|
648
|
+
calling shell to a copy of it
|
|
649
|
+
|
|
650
|
+
- ``poset`` -- the poset to which the newly created shells
|
|
651
|
+
belongs. Note that the elements are not inserted into
|
|
652
|
+
``poset``; this is done in the calling method
|
|
653
|
+
:meth:`MutablePoset._copy_shells_`.
|
|
654
|
+
|
|
655
|
+
- ``mapping`` -- a function which is applied on each of the elements
|
|
656
|
+
|
|
657
|
+
OUTPUT: a new shell
|
|
658
|
+
|
|
659
|
+
.. SEEALSO::
|
|
660
|
+
|
|
661
|
+
:meth:`MutablePoset.copy`,
|
|
662
|
+
:class:`MutablePoset`.
|
|
663
|
+
|
|
664
|
+
TESTS::
|
|
665
|
+
|
|
666
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
667
|
+
sage: P = MP()
|
|
668
|
+
sage: Q = MP()
|
|
669
|
+
sage: memo = {}
|
|
670
|
+
sage: z = P.null._copy_all_linked_(memo, Q, lambda e: e)
|
|
671
|
+
sage: z.poset is Q
|
|
672
|
+
True
|
|
673
|
+
sage: oo = z.successors().pop()
|
|
674
|
+
sage: oo.is_oo()
|
|
675
|
+
True
|
|
676
|
+
|
|
677
|
+
Note that :meth:`_copy_all_linked_` does not change the mutable
|
|
678
|
+
poset ``Q`` (this is done in the calling method
|
|
679
|
+
:meth:`MutablePoset._copy_shells_`). Thus we have
|
|
680
|
+
::
|
|
681
|
+
|
|
682
|
+
sage: oo is Q.oo
|
|
683
|
+
False
|
|
684
|
+
"""
|
|
685
|
+
try:
|
|
686
|
+
return memo[id(self)]
|
|
687
|
+
except KeyError:
|
|
688
|
+
pass
|
|
689
|
+
|
|
690
|
+
new = self.__class__(poset, mapping(self.element)
|
|
691
|
+
if self.element is not None else None)
|
|
692
|
+
memo[id(self)] = new
|
|
693
|
+
|
|
694
|
+
for reverse in (False, True):
|
|
695
|
+
for e in self.successors(reverse):
|
|
696
|
+
new.successors(reverse).add(e._copy_all_linked_(memo, poset, mapping))
|
|
697
|
+
|
|
698
|
+
return new
|
|
699
|
+
|
|
700
|
+
def lower_covers(self, shell, reverse=False):
|
|
701
|
+
r"""
|
|
702
|
+
Return the lower covers of the specified ``shell``;
|
|
703
|
+
the search is started at this (``self``) shell.
|
|
704
|
+
|
|
705
|
+
A lower cover of `x` is an element `y` of the poset
|
|
706
|
+
such that `y < x` and there is no element `z` of the poset
|
|
707
|
+
so that `y < z < x`.
|
|
708
|
+
|
|
709
|
+
INPUT:
|
|
710
|
+
|
|
711
|
+
- ``shell`` -- the shell for which to find the covering shells
|
|
712
|
+
There is no restriction of ``shell`` being contained in the poset
|
|
713
|
+
If ``shell`` is contained in the poset, then use the more efficient
|
|
714
|
+
methods :meth:`predecessors` and :meth:`successors`.
|
|
715
|
+
|
|
716
|
+
- ``reverse`` -- boolean (default: ``False``); if set, then find
|
|
717
|
+
the upper covers (see also :meth:`upper_covers`)
|
|
718
|
+
instead of the lower covers
|
|
719
|
+
|
|
720
|
+
OUTPUT: a set of :class:`shells <MutablePosetShell>`
|
|
721
|
+
|
|
722
|
+
.. NOTE::
|
|
723
|
+
|
|
724
|
+
Suppose ``reverse`` is ``False``. This method starts at
|
|
725
|
+
the calling shell (``self``) and searches towards ``'oo'``.
|
|
726
|
+
Thus, only shells which are (not necessarily
|
|
727
|
+
direct) successors of this shell are considered.
|
|
728
|
+
|
|
729
|
+
If ``reverse`` is ``True``, then the reverse direction is
|
|
730
|
+
taken.
|
|
731
|
+
|
|
732
|
+
EXAMPLES::
|
|
733
|
+
|
|
734
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
735
|
+
sage: class T(tuple):
|
|
736
|
+
....: def __le__(left, right):
|
|
737
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
738
|
+
sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
|
|
739
|
+
....: T((4, 4)), T((1, 2)), T((2, 2))])
|
|
740
|
+
sage: e = P.shell(T((2, 2))); e
|
|
741
|
+
(2, 2)
|
|
742
|
+
sage: sorted(P.null.lower_covers(e),
|
|
743
|
+
....: key=lambda c: repr(c.element))
|
|
744
|
+
[(1, 2), (2, 1)]
|
|
745
|
+
sage: set(_) == e.predecessors()
|
|
746
|
+
True
|
|
747
|
+
sage: sorted(P.oo.upper_covers(e),
|
|
748
|
+
....: key=lambda c: repr(c.element))
|
|
749
|
+
[(4, 4)]
|
|
750
|
+
sage: set(_) == e.successors()
|
|
751
|
+
True
|
|
752
|
+
|
|
753
|
+
::
|
|
754
|
+
|
|
755
|
+
sage: Q = MP([T((3, 2))])
|
|
756
|
+
sage: f = next(Q.shells())
|
|
757
|
+
sage: sorted(P.null.lower_covers(f),
|
|
758
|
+
....: key=lambda c: repr(c.element))
|
|
759
|
+
[(2, 2)]
|
|
760
|
+
sage: sorted(P.oo.upper_covers(f),
|
|
761
|
+
....: key=lambda c: repr(c.element))
|
|
762
|
+
[(4, 4)]
|
|
763
|
+
|
|
764
|
+
.. SEEALSO::
|
|
765
|
+
|
|
766
|
+
:meth:`upper_covers`,
|
|
767
|
+
:meth:`predecessors`,
|
|
768
|
+
:meth:`successors`,
|
|
769
|
+
:class:`MutablePoset`.
|
|
770
|
+
"""
|
|
771
|
+
if self == shell:
|
|
772
|
+
return set()
|
|
773
|
+
covers = set().union(*(e.lower_covers(shell, reverse)
|
|
774
|
+
for e in self.successors(reverse)
|
|
775
|
+
if e.le(shell, reverse)))
|
|
776
|
+
return covers or set([self])
|
|
777
|
+
|
|
778
|
+
def upper_covers(self, shell, reverse=False):
|
|
779
|
+
r"""
|
|
780
|
+
Return the upper covers of the specified ``shell``;
|
|
781
|
+
the search is started at this (``self``) shell.
|
|
782
|
+
|
|
783
|
+
An upper cover of `x` is an element `y` of the poset
|
|
784
|
+
such that `x < y` and there is no element `z` of the poset
|
|
785
|
+
so that `x < z < y`.
|
|
786
|
+
|
|
787
|
+
INPUT:
|
|
788
|
+
|
|
789
|
+
- ``shell`` -- the shell for which to find the covering shells
|
|
790
|
+
There is no restriction of ``shell`` being contained in the poset
|
|
791
|
+
If ``shell`` is contained in the poset, then use the more efficient
|
|
792
|
+
methods :meth:`predecessors` and :meth:`successors`.
|
|
793
|
+
|
|
794
|
+
- ``reverse`` -- boolean (default: ``False``); if set, then find
|
|
795
|
+
the lower covers (see also :meth:`lower_covers`)
|
|
796
|
+
instead of the upper covers.
|
|
797
|
+
|
|
798
|
+
OUTPUT: a set of :class:`shells <MutablePosetShell>`
|
|
799
|
+
|
|
800
|
+
.. NOTE::
|
|
801
|
+
|
|
802
|
+
Suppose ``reverse`` is ``False``. This method starts at
|
|
803
|
+
the calling shell (``self``) and searches towards ``'null'``.
|
|
804
|
+
Thus, only shells which are (not necessarily
|
|
805
|
+
direct) predecessors of this shell are considered.
|
|
806
|
+
|
|
807
|
+
If ``reverse`` is ``True``, then the reverse direction is
|
|
808
|
+
taken.
|
|
809
|
+
|
|
810
|
+
EXAMPLES::
|
|
811
|
+
|
|
812
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
813
|
+
sage: class T(tuple):
|
|
814
|
+
....: def __le__(left, right):
|
|
815
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
816
|
+
sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
|
|
817
|
+
....: T((4, 4)), T((1, 2)), T((2, 2))])
|
|
818
|
+
sage: e = P.shell(T((2, 2))); e
|
|
819
|
+
(2, 2)
|
|
820
|
+
sage: sorted(P.null.lower_covers(e),
|
|
821
|
+
....: key=lambda c: repr(c.element))
|
|
822
|
+
[(1, 2), (2, 1)]
|
|
823
|
+
sage: set(_) == e.predecessors()
|
|
824
|
+
True
|
|
825
|
+
sage: sorted(P.oo.upper_covers(e),
|
|
826
|
+
....: key=lambda c: repr(c.element))
|
|
827
|
+
[(4, 4)]
|
|
828
|
+
sage: set(_) == e.successors()
|
|
829
|
+
True
|
|
830
|
+
|
|
831
|
+
::
|
|
832
|
+
|
|
833
|
+
sage: Q = MP([T((3, 2))])
|
|
834
|
+
sage: f = next(Q.shells())
|
|
835
|
+
sage: sorted(P.null.lower_covers(f),
|
|
836
|
+
....: key=lambda c: repr(c.element))
|
|
837
|
+
[(2, 2)]
|
|
838
|
+
sage: sorted(P.oo.upper_covers(f),
|
|
839
|
+
....: key=lambda c: repr(c.element))
|
|
840
|
+
[(4, 4)]
|
|
841
|
+
|
|
842
|
+
.. SEEALSO::
|
|
843
|
+
|
|
844
|
+
:meth:`predecessors`,
|
|
845
|
+
:meth:`successors`,
|
|
846
|
+
:class:`MutablePoset`.
|
|
847
|
+
"""
|
|
848
|
+
return self.lower_covers(shell, not reverse)
|
|
849
|
+
|
|
850
|
+
def _iter_depth_first_visit_(self, marked,
|
|
851
|
+
reverse=False, key=None,
|
|
852
|
+
condition=None):
|
|
853
|
+
r"""
|
|
854
|
+
Return an iterator over all shells in depth first order.
|
|
855
|
+
|
|
856
|
+
This is a helper function for :meth:`iter_depth_first`.
|
|
857
|
+
|
|
858
|
+
INPUT:
|
|
859
|
+
|
|
860
|
+
- ``marked`` -- set in which marked shells are stored
|
|
861
|
+
|
|
862
|
+
- ``reverse`` -- boolean (default: ``False``); if set, reverses the
|
|
863
|
+
order, i.e., ``False`` searches towards ``'oo'`` and
|
|
864
|
+
``True`` searches towards ``'null'``
|
|
865
|
+
|
|
866
|
+
- ``key`` -- (default: ``None``) a function used for sorting
|
|
867
|
+
the direct successors of a shell (used in case of a
|
|
868
|
+
tie). If this is ``None``, no sorting occurs.
|
|
869
|
+
|
|
870
|
+
- ``condition`` -- (default: ``None``) a function mapping a
|
|
871
|
+
shell to ``True`` (include in iteration) or ``False`` (do
|
|
872
|
+
not include). ``None`` is equivalent to a function returning
|
|
873
|
+
always ``True``. Note that the iteration does not go beyond a
|
|
874
|
+
not included shell.
|
|
875
|
+
|
|
876
|
+
.. NOTE::
|
|
877
|
+
|
|
878
|
+
The depth first search starts at this (``self``) shell. Thus
|
|
879
|
+
only this shell and shells greater than (in case of
|
|
880
|
+
``reverse=False``) this shell are visited.
|
|
881
|
+
|
|
882
|
+
.. SEEALSO::
|
|
883
|
+
|
|
884
|
+
:meth:`iter_depth_first`,
|
|
885
|
+
:meth:`iter_topological`,
|
|
886
|
+
:class:`MutablePoset`.
|
|
887
|
+
|
|
888
|
+
TESTS::
|
|
889
|
+
|
|
890
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
891
|
+
sage: P = MP()
|
|
892
|
+
sage: P.add(42)
|
|
893
|
+
sage: P.add(5)
|
|
894
|
+
sage: marked = set()
|
|
895
|
+
sage: list(P.oo._iter_depth_first_visit_(marked, reverse=True))
|
|
896
|
+
[oo, 42, 5, null]
|
|
897
|
+
"""
|
|
898
|
+
if (condition is not None and
|
|
899
|
+
not self.is_special() and not condition(self)):
|
|
900
|
+
return
|
|
901
|
+
if self in marked:
|
|
902
|
+
return
|
|
903
|
+
marked.add(self)
|
|
904
|
+
yield self
|
|
905
|
+
S = self.successors(reverse)
|
|
906
|
+
if key is not None:
|
|
907
|
+
S = sorted(S, key=key)
|
|
908
|
+
for shell in S:
|
|
909
|
+
yield from shell._iter_depth_first_visit_(marked, reverse,
|
|
910
|
+
key, condition)
|
|
911
|
+
|
|
912
|
+
def iter_depth_first(self, reverse=False, key=None, condition=None):
|
|
913
|
+
r"""
|
|
914
|
+
Iterate over all shells in depth first order.
|
|
915
|
+
|
|
916
|
+
INPUT:
|
|
917
|
+
|
|
918
|
+
- ``reverse`` -- boolean (default: ``False``); if set, reverses the
|
|
919
|
+
order, i.e., ``False`` searches towards ``'oo'`` and
|
|
920
|
+
``True`` searches towards ``'null'``
|
|
921
|
+
|
|
922
|
+
- ``key`` -- (default: ``None``) a function used for sorting
|
|
923
|
+
the direct successors of a shell (used in case of a
|
|
924
|
+
tie). If this is ``None``, no sorting occurs.
|
|
925
|
+
|
|
926
|
+
- ``condition`` -- (default: ``None``) a function mapping a
|
|
927
|
+
shell to ``True`` (include in iteration) or ``False`` (do
|
|
928
|
+
not include). ``None`` is equivalent to a function returning
|
|
929
|
+
always ``True``. Note that the iteration does not go beyond a
|
|
930
|
+
not included shell.
|
|
931
|
+
|
|
932
|
+
.. NOTE::
|
|
933
|
+
|
|
934
|
+
The depth first search starts at this (``self``) shell. Thus
|
|
935
|
+
only this shell and shells greater than (in case of
|
|
936
|
+
``reverse=False``) this shell are visited.
|
|
937
|
+
|
|
938
|
+
ALGORITHM:
|
|
939
|
+
|
|
940
|
+
See :wikipedia:`Depth-first_search`.
|
|
941
|
+
|
|
942
|
+
EXAMPLES::
|
|
943
|
+
|
|
944
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
945
|
+
sage: class T(tuple):
|
|
946
|
+
....: def __le__(left, right):
|
|
947
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
948
|
+
sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
|
|
949
|
+
....: T((4, 4)), T((1, 2)), T((2, 2))])
|
|
950
|
+
sage: list(P.null.iter_depth_first(reverse=False, key=repr))
|
|
951
|
+
[null, (1, 1), (1, 2), (1, 3), (4, 4), oo, (2, 2), (2, 1)]
|
|
952
|
+
sage: list(P.oo.iter_depth_first(reverse=True, key=repr))
|
|
953
|
+
[oo, (4, 4), (1, 3), (1, 2), (1, 1), null, (2, 2), (2, 1)]
|
|
954
|
+
sage: list(P.null.iter_depth_first(
|
|
955
|
+
....: condition=lambda s: s.element[0] == 1))
|
|
956
|
+
[null, (1, 1), (1, 2), (1, 3)]
|
|
957
|
+
|
|
958
|
+
.. SEEALSO::
|
|
959
|
+
|
|
960
|
+
:meth:`iter_topological`,
|
|
961
|
+
:class:`MutablePoset`.
|
|
962
|
+
"""
|
|
963
|
+
marked = set()
|
|
964
|
+
return self._iter_depth_first_visit_(marked, reverse, key, condition)
|
|
965
|
+
|
|
966
|
+
def _iter_topological_visit_(self, marked,
|
|
967
|
+
reverse=False, key=None,
|
|
968
|
+
condition=None):
|
|
969
|
+
r"""
|
|
970
|
+
Return an iterator over all shells in topological order.
|
|
971
|
+
|
|
972
|
+
This is a helper function for :meth:`iter_topological`.
|
|
973
|
+
|
|
974
|
+
INPUT:
|
|
975
|
+
|
|
976
|
+
- ``marked`` -- set in which marked shells are stored
|
|
977
|
+
|
|
978
|
+
- ``reverse`` -- boolean (default: ``False``); if set, reverses the
|
|
979
|
+
order, i.e., ``False`` searches towards ``'oo'`` and
|
|
980
|
+
``True`` searches towards ``'null'``
|
|
981
|
+
|
|
982
|
+
- ``key`` -- (default: ``None``) a function used for sorting
|
|
983
|
+
the direct predecessors of a shell (used in case of a
|
|
984
|
+
tie). If this is ``None``, no sorting occurs.
|
|
985
|
+
|
|
986
|
+
- ``condition`` -- (default: ``None``) a function mapping a
|
|
987
|
+
shell to ``True`` (include in iteration) or ``False`` (do
|
|
988
|
+
not include). ``None`` is equivalent to a function returning
|
|
989
|
+
always ``True``. Note that the iteration does not go beyond a
|
|
990
|
+
not included shell.
|
|
991
|
+
|
|
992
|
+
OUTPUT: an iterator
|
|
993
|
+
|
|
994
|
+
.. NOTE::
|
|
995
|
+
|
|
996
|
+
The topological search will only find shells smaller than
|
|
997
|
+
(in case of ``reverse=False``)
|
|
998
|
+
or equal to this (``self``) shell. This is in contrast to
|
|
999
|
+
:meth:`iter_depth_first`.
|
|
1000
|
+
|
|
1001
|
+
.. SEEALSO::
|
|
1002
|
+
|
|
1003
|
+
:meth:`iter_depth_first`,
|
|
1004
|
+
:meth:`iter_topological`,
|
|
1005
|
+
:class:`MutablePoset`.
|
|
1006
|
+
|
|
1007
|
+
TESTS::
|
|
1008
|
+
|
|
1009
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1010
|
+
sage: P = MP()
|
|
1011
|
+
sage: P.add(42)
|
|
1012
|
+
sage: P.add(5)
|
|
1013
|
+
sage: marked = set()
|
|
1014
|
+
sage: list(P.null._iter_topological_visit_(marked, reverse=True, key=repr))
|
|
1015
|
+
[oo, 42, 5, null]
|
|
1016
|
+
"""
|
|
1017
|
+
if (condition is not None and
|
|
1018
|
+
not self.is_special() and not condition(self)):
|
|
1019
|
+
return
|
|
1020
|
+
if self in marked:
|
|
1021
|
+
return
|
|
1022
|
+
marked.add(self)
|
|
1023
|
+
S = self.predecessors(reverse)
|
|
1024
|
+
if key is not None and len(S) > 1:
|
|
1025
|
+
S = sorted(S, key=key)
|
|
1026
|
+
for shell in S:
|
|
1027
|
+
yield from shell._iter_topological_visit_(marked, reverse,
|
|
1028
|
+
key, condition)
|
|
1029
|
+
yield self
|
|
1030
|
+
|
|
1031
|
+
def iter_topological(self, reverse=False, key=None, condition=None):
|
|
1032
|
+
r"""
|
|
1033
|
+
Iterate over all shells in topological order.
|
|
1034
|
+
|
|
1035
|
+
INPUT:
|
|
1036
|
+
|
|
1037
|
+
- ``reverse`` -- boolean (default: ``False``); if set, reverses the
|
|
1038
|
+
order, i.e., ``False`` searches towards ``'oo'`` and
|
|
1039
|
+
``True`` searches towards ``'null'``
|
|
1040
|
+
|
|
1041
|
+
- ``key`` -- (default: ``None``) a function used for sorting
|
|
1042
|
+
the direct predecessors of a shell (used in case of a
|
|
1043
|
+
tie). If this is ``None``, no sorting occurs.
|
|
1044
|
+
|
|
1045
|
+
- ``condition`` -- (default: ``None``) a function mapping a
|
|
1046
|
+
shell to ``True`` (include in iteration) or ``False`` (do
|
|
1047
|
+
not include). ``None`` is equivalent to a function returning
|
|
1048
|
+
always ``True``. Note that the iteration does not go beyond a
|
|
1049
|
+
not included shell.
|
|
1050
|
+
|
|
1051
|
+
OUTPUT: an iterator
|
|
1052
|
+
|
|
1053
|
+
.. NOTE::
|
|
1054
|
+
|
|
1055
|
+
The topological search will only find shells smaller than
|
|
1056
|
+
(in case of ``reverse=False``)
|
|
1057
|
+
or equal to this (``self``) shell. This is in contrast to
|
|
1058
|
+
:meth:`iter_depth_first`.
|
|
1059
|
+
|
|
1060
|
+
ALGORITHM:
|
|
1061
|
+
|
|
1062
|
+
Here a simplified version of the algorithm found in [Tar1976]_
|
|
1063
|
+
and [CLRS2001]_ is used. See also
|
|
1064
|
+
:wikipedia:`Topological_sorting`.
|
|
1065
|
+
|
|
1066
|
+
EXAMPLES::
|
|
1067
|
+
|
|
1068
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1069
|
+
sage: class T(tuple):
|
|
1070
|
+
....: def __le__(left, right):
|
|
1071
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
1072
|
+
sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
|
|
1073
|
+
....: T((4, 4)), T((1, 2)), T((2, 2))])
|
|
1074
|
+
|
|
1075
|
+
::
|
|
1076
|
+
|
|
1077
|
+
sage: for e in P.shells_topological(include_special=True,
|
|
1078
|
+
....: reverse=True, key=repr):
|
|
1079
|
+
....: print(e)
|
|
1080
|
+
....: print(list(e.iter_topological(reverse=True, key=repr)))
|
|
1081
|
+
oo
|
|
1082
|
+
[oo]
|
|
1083
|
+
(4, 4)
|
|
1084
|
+
[oo, (4, 4)]
|
|
1085
|
+
(1, 3)
|
|
1086
|
+
[oo, (4, 4), (1, 3)]
|
|
1087
|
+
(2, 2)
|
|
1088
|
+
[oo, (4, 4), (2, 2)]
|
|
1089
|
+
(1, 2)
|
|
1090
|
+
[oo, (4, 4), (1, 3), (2, 2), (1, 2)]
|
|
1091
|
+
(2, 1)
|
|
1092
|
+
[oo, (4, 4), (2, 2), (2, 1)]
|
|
1093
|
+
(1, 1)
|
|
1094
|
+
[oo, (4, 4), (1, 3), (2, 2), (1, 2), (2, 1), (1, 1)]
|
|
1095
|
+
null
|
|
1096
|
+
[oo, (4, 4), (1, 3), (2, 2), (1, 2), (2, 1), (1, 1), null]
|
|
1097
|
+
|
|
1098
|
+
::
|
|
1099
|
+
|
|
1100
|
+
sage: for e in P.shells_topological(include_special=True,
|
|
1101
|
+
....: reverse=True, key=repr):
|
|
1102
|
+
....: print(e)
|
|
1103
|
+
....: print(list(e.iter_topological(reverse=False, key=repr)))
|
|
1104
|
+
oo
|
|
1105
|
+
[null, (1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (4, 4), oo]
|
|
1106
|
+
(4, 4)
|
|
1107
|
+
[null, (1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (4, 4)]
|
|
1108
|
+
(1, 3)
|
|
1109
|
+
[null, (1, 1), (1, 2), (1, 3)]
|
|
1110
|
+
(2, 2)
|
|
1111
|
+
[null, (1, 1), (1, 2), (2, 1), (2, 2)]
|
|
1112
|
+
(1, 2)
|
|
1113
|
+
[null, (1, 1), (1, 2)]
|
|
1114
|
+
(2, 1)
|
|
1115
|
+
[null, (1, 1), (2, 1)]
|
|
1116
|
+
(1, 1)
|
|
1117
|
+
[null, (1, 1)]
|
|
1118
|
+
null
|
|
1119
|
+
[null]
|
|
1120
|
+
|
|
1121
|
+
::
|
|
1122
|
+
|
|
1123
|
+
sage: list(P.null.iter_topological(
|
|
1124
|
+
....: reverse=True, condition=lambda s: s.element[0] == 1,
|
|
1125
|
+
....: key=repr))
|
|
1126
|
+
[(1, 3), (1, 2), (1, 1), null]
|
|
1127
|
+
|
|
1128
|
+
.. SEEALSO::
|
|
1129
|
+
|
|
1130
|
+
:meth:`iter_depth_first`,
|
|
1131
|
+
:meth:`MutablePoset.shells_topological`,
|
|
1132
|
+
:meth:`MutablePoset.elements_topological`,
|
|
1133
|
+
:meth:`MutablePoset.keys_topological`,
|
|
1134
|
+
:class:`MutablePoset`.
|
|
1135
|
+
"""
|
|
1136
|
+
marked = set()
|
|
1137
|
+
return self._iter_topological_visit_(marked, reverse, key, condition)
|
|
1138
|
+
|
|
1139
|
+
def merge(self, element, check=True, delete=True):
|
|
1140
|
+
r"""
|
|
1141
|
+
Merge the given element with the element contained in this
|
|
1142
|
+
shell.
|
|
1143
|
+
|
|
1144
|
+
INPUT:
|
|
1145
|
+
|
|
1146
|
+
- ``element`` -- an element (of the poset)
|
|
1147
|
+
|
|
1148
|
+
- ``check`` -- boolean (default: ``True``); if set, then the
|
|
1149
|
+
``can_merge``-function of :class:`MutablePoset` determines
|
|
1150
|
+
whether the merge is possible. ``can_merge`` is ``None`` means
|
|
1151
|
+
that this check is always passed.
|
|
1152
|
+
|
|
1153
|
+
- ``delete`` -- boolean (default: ``True``); if set, then ``element``
|
|
1154
|
+
is removed from the poset after the merge
|
|
1155
|
+
|
|
1156
|
+
OUTPUT: nothing
|
|
1157
|
+
|
|
1158
|
+
.. NOTE::
|
|
1159
|
+
|
|
1160
|
+
This operation depends on the parameters ``merge`` and
|
|
1161
|
+
``can_merge`` of the :class:`MutablePoset` this shell is
|
|
1162
|
+
contained in. These parameters are defined when the poset
|
|
1163
|
+
is constructed.
|
|
1164
|
+
|
|
1165
|
+
.. NOTE::
|
|
1166
|
+
|
|
1167
|
+
If the ``merge`` function returns ``None``, then this shell
|
|
1168
|
+
is removed from the poset.
|
|
1169
|
+
|
|
1170
|
+
EXAMPLES::
|
|
1171
|
+
|
|
1172
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1173
|
+
sage: def add(left, right):
|
|
1174
|
+
....: return (left[0], ''.join(sorted(left[1] + right[1])))
|
|
1175
|
+
sage: def can_add(left, right):
|
|
1176
|
+
....: return left[0] <= right[0]
|
|
1177
|
+
sage: P = MP([(1, 'a'), (3, 'b'), (2, 'c'), (4, 'd')],
|
|
1178
|
+
....: key=lambda c: c[0], merge=add, can_merge=can_add)
|
|
1179
|
+
sage: P
|
|
1180
|
+
poset((1, 'a'), (2, 'c'), (3, 'b'), (4, 'd'))
|
|
1181
|
+
sage: P.shell(2).merge((3, 'b'))
|
|
1182
|
+
sage: P
|
|
1183
|
+
poset((1, 'a'), (2, 'bc'), (4, 'd'))
|
|
1184
|
+
|
|
1185
|
+
.. SEEALSO::
|
|
1186
|
+
|
|
1187
|
+
:meth:`MutablePoset.merge`,
|
|
1188
|
+
:class:`MutablePoset`.
|
|
1189
|
+
|
|
1190
|
+
TESTS::
|
|
1191
|
+
|
|
1192
|
+
sage: MP([2], merge=operator.add,
|
|
1193
|
+
....: can_merge=lambda _, __: False).shell(2).merge(1)
|
|
1194
|
+
Traceback (most recent call last):
|
|
1195
|
+
...
|
|
1196
|
+
RuntimeError: Cannot merge 2 with 1.
|
|
1197
|
+
"""
|
|
1198
|
+
poset = self.poset
|
|
1199
|
+
if poset._merge_ is None:
|
|
1200
|
+
# poset._merge_ is None means no merge (poset._merge_ simply
|
|
1201
|
+
# returns its first input argument).
|
|
1202
|
+
return
|
|
1203
|
+
self_element = self.element
|
|
1204
|
+
if check:
|
|
1205
|
+
if not poset._can_merge_(self_element, element):
|
|
1206
|
+
raise RuntimeError('Cannot merge %s with %s.' %
|
|
1207
|
+
(self_element, element))
|
|
1208
|
+
new = poset._merge_(self_element, element)
|
|
1209
|
+
if new is None:
|
|
1210
|
+
poset.discard(poset.get_key(self.element))
|
|
1211
|
+
else:
|
|
1212
|
+
self._element_ = new
|
|
1213
|
+
if delete:
|
|
1214
|
+
poset.remove(poset.get_key(element))
|
|
1215
|
+
|
|
1216
|
+
|
|
1217
|
+
# *****************************************************************************
|
|
1218
|
+
|
|
1219
|
+
|
|
1220
|
+
def is_MutablePoset(P):
|
|
1221
|
+
r"""
|
|
1222
|
+
Test whether ``P`` inherits from :class:`MutablePoset`.
|
|
1223
|
+
|
|
1224
|
+
.. SEEALSO::
|
|
1225
|
+
|
|
1226
|
+
:class:`MutablePoset`
|
|
1227
|
+
|
|
1228
|
+
TESTS::
|
|
1229
|
+
|
|
1230
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1231
|
+
sage: from sage.data_structures.mutable_poset import is_MutablePoset
|
|
1232
|
+
sage: P = MP()
|
|
1233
|
+
sage: is_MutablePoset(P)
|
|
1234
|
+
doctest:warning...
|
|
1235
|
+
DeprecationWarning: The function is_MutablePoset is deprecated; use 'isinstance(..., MutablePoset)' instead.
|
|
1236
|
+
See https://github.com/sagemath/sage/issues/38125 for details.
|
|
1237
|
+
True
|
|
1238
|
+
"""
|
|
1239
|
+
from sage.misc.superseded import deprecation
|
|
1240
|
+
deprecation(38125,
|
|
1241
|
+
"The function is_MutablePoset is deprecated; "
|
|
1242
|
+
"use 'isinstance(..., MutablePoset)' instead.")
|
|
1243
|
+
return isinstance(P, MutablePoset)
|
|
1244
|
+
|
|
1245
|
+
|
|
1246
|
+
class MutablePoset(SageObject):
|
|
1247
|
+
r"""
|
|
1248
|
+
A data structure that models a mutable poset (partially ordered
|
|
1249
|
+
set).
|
|
1250
|
+
|
|
1251
|
+
INPUT:
|
|
1252
|
+
|
|
1253
|
+
- ``data`` -- data from which to construct the poset. It can be
|
|
1254
|
+
any of the following:
|
|
1255
|
+
|
|
1256
|
+
#. ``None`` (default), in which case an empty poset is created,
|
|
1257
|
+
|
|
1258
|
+
#. a :class:`MutablePoset`, which will be copied during creation,
|
|
1259
|
+
|
|
1260
|
+
#. an iterable, whose elements will be in the poset.
|
|
1261
|
+
|
|
1262
|
+
- ``key`` -- a function which maps elements to keys. If ``None``
|
|
1263
|
+
(default), this is the identity, i.e., keys are equal to their
|
|
1264
|
+
elements.
|
|
1265
|
+
|
|
1266
|
+
Two elements with the same keys are considered as equal; so only
|
|
1267
|
+
one of these two elements can be in the poset.
|
|
1268
|
+
|
|
1269
|
+
This ``key`` is not used for sorting (in contrast to
|
|
1270
|
+
sorting-functions, e.g. ``sorted``).
|
|
1271
|
+
|
|
1272
|
+
- ``merge`` -- a function which merges its second argument (an
|
|
1273
|
+
element) to its first (again an element) and returns the result
|
|
1274
|
+
(as an element). If the return value is ``None``, the element is
|
|
1275
|
+
removed from the poset.
|
|
1276
|
+
|
|
1277
|
+
This hook is called by :meth:`merge`. Moreover it is used during
|
|
1278
|
+
:meth:`add` when an element (more precisely its key) is already
|
|
1279
|
+
in this poset.
|
|
1280
|
+
|
|
1281
|
+
``merge`` is ``None`` (default) is equivalent to ``merge``
|
|
1282
|
+
returning its first argument. Note that it is not allowed that the
|
|
1283
|
+
key of the returning element differs from the key of the first
|
|
1284
|
+
input parameter. This means ``merge`` must not change the
|
|
1285
|
+
position of the element in the poset.
|
|
1286
|
+
|
|
1287
|
+
- ``can_merge`` -- a function which checks whether its second argument
|
|
1288
|
+
can be merged to its first
|
|
1289
|
+
|
|
1290
|
+
This hook is called by :meth:`merge`. Moreover it is used during
|
|
1291
|
+
:meth:`add` when an element (more precisely its key) is already
|
|
1292
|
+
in this poset.
|
|
1293
|
+
|
|
1294
|
+
``can_merge`` is ``None`` (default) is equivalent to ``can_merge``
|
|
1295
|
+
returning ``True`` in all cases.
|
|
1296
|
+
|
|
1297
|
+
OUTPUT: a mutable poset
|
|
1298
|
+
|
|
1299
|
+
You can find a short introduction and examples
|
|
1300
|
+
:mod:`here <sage.data_structures.mutable_poset>`.
|
|
1301
|
+
|
|
1302
|
+
EXAMPLES::
|
|
1303
|
+
|
|
1304
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1305
|
+
|
|
1306
|
+
We illustrate the different input formats
|
|
1307
|
+
|
|
1308
|
+
#. No input::
|
|
1309
|
+
|
|
1310
|
+
sage: A = MP(); A
|
|
1311
|
+
poset()
|
|
1312
|
+
|
|
1313
|
+
#. A :class:`MutablePoset`::
|
|
1314
|
+
|
|
1315
|
+
sage: B = MP(A); B
|
|
1316
|
+
poset()
|
|
1317
|
+
sage: B.add(42)
|
|
1318
|
+
sage: C = MP(B); C
|
|
1319
|
+
poset(42)
|
|
1320
|
+
|
|
1321
|
+
#. An iterable::
|
|
1322
|
+
|
|
1323
|
+
sage: C = MP([5, 3, 11]); C
|
|
1324
|
+
poset(3, 5, 11)
|
|
1325
|
+
|
|
1326
|
+
.. SEEALSO::
|
|
1327
|
+
|
|
1328
|
+
:class:`MutablePosetShell`.
|
|
1329
|
+
"""
|
|
1330
|
+
def __init__(self, data=None, key=None, merge=None, can_merge=None):
|
|
1331
|
+
r"""
|
|
1332
|
+
See :class:`MutablePoset` for details.
|
|
1333
|
+
|
|
1334
|
+
TESTS::
|
|
1335
|
+
|
|
1336
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1337
|
+
sage: MP()
|
|
1338
|
+
poset()
|
|
1339
|
+
|
|
1340
|
+
::
|
|
1341
|
+
|
|
1342
|
+
sage: P = MP()
|
|
1343
|
+
sage: P.add(42)
|
|
1344
|
+
sage: MP(P)
|
|
1345
|
+
poset(42)
|
|
1346
|
+
|
|
1347
|
+
::
|
|
1348
|
+
|
|
1349
|
+
sage: MP([3, 5, 7])
|
|
1350
|
+
poset(3, 5, 7)
|
|
1351
|
+
|
|
1352
|
+
::
|
|
1353
|
+
|
|
1354
|
+
sage: MP(33)
|
|
1355
|
+
Traceback (most recent call last):
|
|
1356
|
+
...
|
|
1357
|
+
TypeError: 33 is not iterable; do not know what to do with it.
|
|
1358
|
+
"""
|
|
1359
|
+
if isinstance(data, MutablePoset):
|
|
1360
|
+
if key is not None:
|
|
1361
|
+
raise TypeError('Cannot use key when data is a poset.')
|
|
1362
|
+
self._copy_shells_(data, lambda e: e)
|
|
1363
|
+
|
|
1364
|
+
else:
|
|
1365
|
+
self.clear()
|
|
1366
|
+
|
|
1367
|
+
if key is None:
|
|
1368
|
+
self._key_ = lambda k: k
|
|
1369
|
+
else:
|
|
1370
|
+
self._key_ = key
|
|
1371
|
+
|
|
1372
|
+
self._merge_ = merge
|
|
1373
|
+
if can_merge is None:
|
|
1374
|
+
self._can_merge_ = lambda _, __: True
|
|
1375
|
+
else:
|
|
1376
|
+
self._can_merge_ = can_merge
|
|
1377
|
+
|
|
1378
|
+
if data is not None:
|
|
1379
|
+
try:
|
|
1380
|
+
it = iter(data)
|
|
1381
|
+
except TypeError:
|
|
1382
|
+
raise TypeError('%s is not iterable; do not know what to '
|
|
1383
|
+
'do with it.' % (data,))
|
|
1384
|
+
self.union_update(it)
|
|
1385
|
+
super().__init__()
|
|
1386
|
+
|
|
1387
|
+
def clear(self):
|
|
1388
|
+
r"""
|
|
1389
|
+
Remove all elements from this poset.
|
|
1390
|
+
|
|
1391
|
+
OUTPUT: nothing
|
|
1392
|
+
|
|
1393
|
+
.. SEEALSO::
|
|
1394
|
+
|
|
1395
|
+
:meth:`discard`,
|
|
1396
|
+
:meth:`pop`,
|
|
1397
|
+
:meth:`remove`.
|
|
1398
|
+
|
|
1399
|
+
TESTS::
|
|
1400
|
+
|
|
1401
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1402
|
+
sage: P = MP()
|
|
1403
|
+
sage: P.add(42); P
|
|
1404
|
+
poset(42)
|
|
1405
|
+
sage: P.clear()
|
|
1406
|
+
sage: print(P.repr_full())
|
|
1407
|
+
poset()
|
|
1408
|
+
+-- null
|
|
1409
|
+
| +-- no predecessors
|
|
1410
|
+
| +-- successors: oo
|
|
1411
|
+
+-- oo
|
|
1412
|
+
| +-- predecessors: null
|
|
1413
|
+
| +-- no successors
|
|
1414
|
+
"""
|
|
1415
|
+
self._null_ = MutablePosetShell(self, None)
|
|
1416
|
+
self._oo_ = MutablePosetShell(self, None)
|
|
1417
|
+
self._null_.successors().add(self._oo_)
|
|
1418
|
+
self._oo_.predecessors().add(self._null_)
|
|
1419
|
+
self._shells_ = {}
|
|
1420
|
+
|
|
1421
|
+
def __len__(self):
|
|
1422
|
+
r"""
|
|
1423
|
+
Return the number of elements contained in this poset.
|
|
1424
|
+
|
|
1425
|
+
OUTPUT: integer
|
|
1426
|
+
|
|
1427
|
+
.. NOTE::
|
|
1428
|
+
|
|
1429
|
+
The special elements ``'null'`` and ``'oo'`` are not counted.
|
|
1430
|
+
|
|
1431
|
+
TESTS::
|
|
1432
|
+
|
|
1433
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1434
|
+
sage: P = MP()
|
|
1435
|
+
sage: len(P) # indirect doctest
|
|
1436
|
+
0
|
|
1437
|
+
sage: bool(P)
|
|
1438
|
+
False
|
|
1439
|
+
sage: P.add(42)
|
|
1440
|
+
sage: len(P)
|
|
1441
|
+
1
|
|
1442
|
+
sage: bool(P)
|
|
1443
|
+
True
|
|
1444
|
+
"""
|
|
1445
|
+
return len(self._shells_)
|
|
1446
|
+
|
|
1447
|
+
@property
|
|
1448
|
+
def null(self):
|
|
1449
|
+
r"""
|
|
1450
|
+
The shell `\emptyset` whose element is smaller than any
|
|
1451
|
+
other element.
|
|
1452
|
+
|
|
1453
|
+
EXAMPLES::
|
|
1454
|
+
|
|
1455
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1456
|
+
sage: P = MP()
|
|
1457
|
+
sage: z = P.null; z
|
|
1458
|
+
null
|
|
1459
|
+
sage: z.is_null()
|
|
1460
|
+
True
|
|
1461
|
+
|
|
1462
|
+
.. SEEALSO::
|
|
1463
|
+
|
|
1464
|
+
:meth:`oo`,
|
|
1465
|
+
:meth:`MutablePosetShell.is_null`,
|
|
1466
|
+
:meth:`MutablePosetShell.is_special`.
|
|
1467
|
+
"""
|
|
1468
|
+
return self._null_
|
|
1469
|
+
|
|
1470
|
+
@property
|
|
1471
|
+
def oo(self):
|
|
1472
|
+
r"""
|
|
1473
|
+
The shell `\infty` whose element is larger than any other
|
|
1474
|
+
element.
|
|
1475
|
+
|
|
1476
|
+
EXAMPLES::
|
|
1477
|
+
|
|
1478
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1479
|
+
sage: P = MP()
|
|
1480
|
+
sage: oo = P.oo; oo
|
|
1481
|
+
oo
|
|
1482
|
+
sage: oo.is_oo()
|
|
1483
|
+
True
|
|
1484
|
+
|
|
1485
|
+
.. SEEALSO::
|
|
1486
|
+
|
|
1487
|
+
:meth:`null`,
|
|
1488
|
+
:meth:`MutablePosetShell.is_oo`,
|
|
1489
|
+
:meth:`MutablePosetShell.is_special`.
|
|
1490
|
+
"""
|
|
1491
|
+
return self._oo_
|
|
1492
|
+
|
|
1493
|
+
def shell(self, key):
|
|
1494
|
+
r"""
|
|
1495
|
+
Return the shell of the element corresponding to ``key``.
|
|
1496
|
+
|
|
1497
|
+
INPUT:
|
|
1498
|
+
|
|
1499
|
+
- ``key`` -- the key of an object
|
|
1500
|
+
|
|
1501
|
+
OUTPUT: an instance of :class:`MutablePosetShell`
|
|
1502
|
+
|
|
1503
|
+
.. NOTE::
|
|
1504
|
+
|
|
1505
|
+
Each element is contained/encapsulated in a shell inside
|
|
1506
|
+
the poset.
|
|
1507
|
+
|
|
1508
|
+
EXAMPLES::
|
|
1509
|
+
|
|
1510
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1511
|
+
sage: P = MP()
|
|
1512
|
+
sage: P.add(42)
|
|
1513
|
+
sage: e = P.shell(42); e
|
|
1514
|
+
42
|
|
1515
|
+
sage: type(e)
|
|
1516
|
+
<class 'sage.data_structures.mutable_poset.MutablePosetShell'>
|
|
1517
|
+
|
|
1518
|
+
.. SEEALSO::
|
|
1519
|
+
|
|
1520
|
+
:meth:`element`,
|
|
1521
|
+
:meth:`get_key`.
|
|
1522
|
+
"""
|
|
1523
|
+
return self._shells_[key]
|
|
1524
|
+
|
|
1525
|
+
def element(self, key):
|
|
1526
|
+
r"""
|
|
1527
|
+
Return the element corresponding to ``key``.
|
|
1528
|
+
|
|
1529
|
+
INPUT:
|
|
1530
|
+
|
|
1531
|
+
- ``key`` -- the key of an object
|
|
1532
|
+
|
|
1533
|
+
OUTPUT: an object
|
|
1534
|
+
|
|
1535
|
+
EXAMPLES::
|
|
1536
|
+
|
|
1537
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1538
|
+
sage: P = MP()
|
|
1539
|
+
sage: P.add(42)
|
|
1540
|
+
sage: e = P.element(42); e
|
|
1541
|
+
42
|
|
1542
|
+
sage: type(e)
|
|
1543
|
+
<class 'sage.rings.integer.Integer'>
|
|
1544
|
+
|
|
1545
|
+
.. SEEALSO::
|
|
1546
|
+
|
|
1547
|
+
:meth:`shell`,
|
|
1548
|
+
:meth:`get_key`.
|
|
1549
|
+
"""
|
|
1550
|
+
return self.shell(key).element
|
|
1551
|
+
|
|
1552
|
+
def get_key(self, element):
|
|
1553
|
+
r"""
|
|
1554
|
+
Return the key corresponding to the given element.
|
|
1555
|
+
|
|
1556
|
+
INPUT:
|
|
1557
|
+
|
|
1558
|
+
- ``element`` -- an object
|
|
1559
|
+
|
|
1560
|
+
OUTPUT: an object (the key of ``element``)
|
|
1561
|
+
|
|
1562
|
+
.. SEEALSO::
|
|
1563
|
+
|
|
1564
|
+
:meth:`element`,
|
|
1565
|
+
:meth:`shell`.
|
|
1566
|
+
|
|
1567
|
+
TESTS::
|
|
1568
|
+
|
|
1569
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1570
|
+
sage: P = MP()
|
|
1571
|
+
sage: P.get_key(None) is None
|
|
1572
|
+
True
|
|
1573
|
+
sage: P.get_key((1, 2))
|
|
1574
|
+
(1, 2)
|
|
1575
|
+
sage: Q = MP(key=lambda k: k[0])
|
|
1576
|
+
sage: Q.get_key((1, 2))
|
|
1577
|
+
1
|
|
1578
|
+
"""
|
|
1579
|
+
if element is None:
|
|
1580
|
+
return None
|
|
1581
|
+
return self._key_(element)
|
|
1582
|
+
|
|
1583
|
+
def _copy_shells_(self, other, mapping):
|
|
1584
|
+
r"""
|
|
1585
|
+
Copy shells from another poset.
|
|
1586
|
+
|
|
1587
|
+
INPUT:
|
|
1588
|
+
|
|
1589
|
+
- ``other`` -- the mutable poset from which the shells
|
|
1590
|
+
should be copied to this poset
|
|
1591
|
+
|
|
1592
|
+
- ``mapping`` -- a function that is applied to each element
|
|
1593
|
+
|
|
1594
|
+
OUTPUT: nothing
|
|
1595
|
+
|
|
1596
|
+
.. SEEALSO::
|
|
1597
|
+
|
|
1598
|
+
:meth:`copy`
|
|
1599
|
+
|
|
1600
|
+
TESTS::
|
|
1601
|
+
|
|
1602
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1603
|
+
sage: class T(tuple):
|
|
1604
|
+
....: def __le__(left, right):
|
|
1605
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
1606
|
+
sage: P = MP()
|
|
1607
|
+
sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
|
|
1608
|
+
....: T((4, 4)), T((1, 2))])
|
|
1609
|
+
sage: Q = MP()
|
|
1610
|
+
sage: Q._copy_shells_(P, lambda e: e)
|
|
1611
|
+
sage: P.repr_full() == Q.repr_full()
|
|
1612
|
+
True
|
|
1613
|
+
"""
|
|
1614
|
+
from copy import copy
|
|
1615
|
+
self._key_ = copy(other._key_)
|
|
1616
|
+
self._merge_ = copy(other._merge_)
|
|
1617
|
+
self._can_merge_ = copy(other._can_merge_)
|
|
1618
|
+
memo = {}
|
|
1619
|
+
self._null_ = other._null_._copy_all_linked_(memo, self, mapping)
|
|
1620
|
+
self._oo_ = memo[id(other._oo_)]
|
|
1621
|
+
self._shells_ = {f.key: f for f in iter(memo[id(e)] for e in
|
|
1622
|
+
other._shells_.values())}
|
|
1623
|
+
|
|
1624
|
+
def copy(self, mapping=None):
|
|
1625
|
+
r"""
|
|
1626
|
+
Create a shallow copy.
|
|
1627
|
+
|
|
1628
|
+
INPUT:
|
|
1629
|
+
|
|
1630
|
+
- ``mapping`` -- a function which is applied on each of the elements
|
|
1631
|
+
|
|
1632
|
+
OUTPUT: a poset with the same content as ``self``
|
|
1633
|
+
|
|
1634
|
+
.. SEEALSO::
|
|
1635
|
+
|
|
1636
|
+
:meth:`map`,
|
|
1637
|
+
:meth:`mapped`.
|
|
1638
|
+
|
|
1639
|
+
TESTS::
|
|
1640
|
+
|
|
1641
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1642
|
+
sage: class T(tuple):
|
|
1643
|
+
....: def __le__(left, right):
|
|
1644
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
1645
|
+
sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
|
|
1646
|
+
....: T((4, 4)), T((1, 2))])
|
|
1647
|
+
sage: Q = copy(P) # indirect doctest
|
|
1648
|
+
sage: P.repr_full() == Q.repr_full()
|
|
1649
|
+
True
|
|
1650
|
+
"""
|
|
1651
|
+
if mapping is None:
|
|
1652
|
+
|
|
1653
|
+
def mapping(element):
|
|
1654
|
+
return element
|
|
1655
|
+
new = self.__class__()
|
|
1656
|
+
new._copy_shells_(self, mapping)
|
|
1657
|
+
return new
|
|
1658
|
+
|
|
1659
|
+
__copy__ = copy
|
|
1660
|
+
|
|
1661
|
+
def shells(self, include_special=False):
|
|
1662
|
+
r"""
|
|
1663
|
+
Return an iterator over all shells.
|
|
1664
|
+
|
|
1665
|
+
INPUT:
|
|
1666
|
+
|
|
1667
|
+
- ``include_special`` -- boolean (default: ``False``); if set, then
|
|
1668
|
+
including shells containing a smallest element (`\emptyset`)
|
|
1669
|
+
and a largest element (`\infty`)
|
|
1670
|
+
|
|
1671
|
+
OUTPUT: an iterator
|
|
1672
|
+
|
|
1673
|
+
.. NOTE::
|
|
1674
|
+
|
|
1675
|
+
Each element is contained/encapsulated in a shell inside
|
|
1676
|
+
the poset.
|
|
1677
|
+
|
|
1678
|
+
EXAMPLES::
|
|
1679
|
+
|
|
1680
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1681
|
+
sage: P = MP()
|
|
1682
|
+
sage: tuple(P.shells())
|
|
1683
|
+
()
|
|
1684
|
+
sage: tuple(P.shells(include_special=True))
|
|
1685
|
+
(null, oo)
|
|
1686
|
+
|
|
1687
|
+
.. SEEALSO::
|
|
1688
|
+
|
|
1689
|
+
:meth:`shells_topological`,
|
|
1690
|
+
:meth:`elements`,
|
|
1691
|
+
:meth:`elements_topological`,
|
|
1692
|
+
:meth:`keys`,
|
|
1693
|
+
:meth:`keys_topological`,
|
|
1694
|
+
:meth:`MutablePosetShell.iter_depth_first`,
|
|
1695
|
+
:meth:`MutablePosetShell.iter_topological`.
|
|
1696
|
+
"""
|
|
1697
|
+
if include_special:
|
|
1698
|
+
yield self.null
|
|
1699
|
+
yield from self._shells_.values()
|
|
1700
|
+
if include_special:
|
|
1701
|
+
yield self.oo
|
|
1702
|
+
|
|
1703
|
+
def shells_topological(self, include_special=False,
|
|
1704
|
+
reverse=False, key=None):
|
|
1705
|
+
r"""
|
|
1706
|
+
Return an iterator over all shells in topological order.
|
|
1707
|
+
|
|
1708
|
+
INPUT:
|
|
1709
|
+
|
|
1710
|
+
- ``include_special`` -- boolean (default: ``False``); if set, then
|
|
1711
|
+
including shells containing a smallest element (`\emptyset`)
|
|
1712
|
+
and a largest element (`\infty`).
|
|
1713
|
+
|
|
1714
|
+
- ``reverse`` -- boolean (default: ``False``); if set, reverses the
|
|
1715
|
+
order, i.e., ``False`` gives smallest elements first,
|
|
1716
|
+
``True`` gives largest first.
|
|
1717
|
+
|
|
1718
|
+
- ``key`` -- (default: ``None``) a function used for sorting
|
|
1719
|
+
the direct successors of a shell (used in case of a tie).
|
|
1720
|
+
If this is ``None``, no sorting occurs.
|
|
1721
|
+
|
|
1722
|
+
OUTPUT: an iterator
|
|
1723
|
+
|
|
1724
|
+
.. NOTE::
|
|
1725
|
+
|
|
1726
|
+
Each element is contained/encapsulated in a shell inside
|
|
1727
|
+
the poset.
|
|
1728
|
+
|
|
1729
|
+
EXAMPLES::
|
|
1730
|
+
|
|
1731
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1732
|
+
sage: class T(tuple):
|
|
1733
|
+
....: def __le__(left, right):
|
|
1734
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
1735
|
+
sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
|
|
1736
|
+
....: T((4, 4)), T((1, 2)), T((2, 2))])
|
|
1737
|
+
sage: list(P.shells_topological(key=repr))
|
|
1738
|
+
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (4, 4)]
|
|
1739
|
+
sage: list(P.shells_topological(reverse=True, key=repr))
|
|
1740
|
+
[(4, 4), (1, 3), (2, 2), (1, 2), (2, 1), (1, 1)]
|
|
1741
|
+
sage: list(P.shells_topological(include_special=True, key=repr))
|
|
1742
|
+
[null, (1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (4, 4), oo]
|
|
1743
|
+
sage: list(P.shells_topological(
|
|
1744
|
+
....: include_special=True, reverse=True, key=repr))
|
|
1745
|
+
[oo, (4, 4), (1, 3), (2, 2), (1, 2), (2, 1), (1, 1), null]
|
|
1746
|
+
|
|
1747
|
+
.. SEEALSO::
|
|
1748
|
+
|
|
1749
|
+
:meth:`shells`,
|
|
1750
|
+
:meth:`elements`,
|
|
1751
|
+
:meth:`elements_topological`,
|
|
1752
|
+
:meth:`keys`,
|
|
1753
|
+
:meth:`keys_topological`,
|
|
1754
|
+
:meth:`MutablePosetShell.iter_depth_first`,
|
|
1755
|
+
:meth:`MutablePosetShell.iter_topological`.
|
|
1756
|
+
"""
|
|
1757
|
+
shell = self.oo if not reverse else self.null
|
|
1758
|
+
return iter(e for e in shell.iter_topological(reverse, key)
|
|
1759
|
+
if include_special or not e.is_special())
|
|
1760
|
+
|
|
1761
|
+
def elements(self, **kwargs):
|
|
1762
|
+
r"""
|
|
1763
|
+
Return an iterator over all elements.
|
|
1764
|
+
|
|
1765
|
+
INPUT:
|
|
1766
|
+
|
|
1767
|
+
- ``kwargs`` -- arguments are passed to :meth:`shells`
|
|
1768
|
+
|
|
1769
|
+
EXAMPLES::
|
|
1770
|
+
|
|
1771
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1772
|
+
sage: P = MP([3, 42, 7])
|
|
1773
|
+
sage: [(v, type(v)) for v in sorted(P.elements())]
|
|
1774
|
+
[(3, <class 'sage.rings.integer.Integer'>),
|
|
1775
|
+
(7, <class 'sage.rings.integer.Integer'>),
|
|
1776
|
+
(42, <class 'sage.rings.integer.Integer'>)]
|
|
1777
|
+
|
|
1778
|
+
Note that
|
|
1779
|
+
|
|
1780
|
+
::
|
|
1781
|
+
|
|
1782
|
+
sage: it = iter(P)
|
|
1783
|
+
sage: sorted(it)
|
|
1784
|
+
[3, 7, 42]
|
|
1785
|
+
|
|
1786
|
+
returns all elements as well.
|
|
1787
|
+
|
|
1788
|
+
.. SEEALSO::
|
|
1789
|
+
|
|
1790
|
+
:meth:`shells`,
|
|
1791
|
+
:meth:`shells_topological`,
|
|
1792
|
+
:meth:`elements_topological`,
|
|
1793
|
+
:meth:`keys`,
|
|
1794
|
+
:meth:`keys_topological`,
|
|
1795
|
+
:meth:`MutablePosetShell.iter_depth_first`,
|
|
1796
|
+
:meth:`MutablePosetShell.iter_topological`.
|
|
1797
|
+
"""
|
|
1798
|
+
for shell in self.shells(**kwargs):
|
|
1799
|
+
yield shell.element
|
|
1800
|
+
|
|
1801
|
+
__iter__ = elements
|
|
1802
|
+
|
|
1803
|
+
def elements_topological(self, **kwargs):
|
|
1804
|
+
r"""
|
|
1805
|
+
Return an iterator over all elements in topological order.
|
|
1806
|
+
|
|
1807
|
+
INPUT:
|
|
1808
|
+
|
|
1809
|
+
- ``kwargs`` -- arguments are passed to :meth:`shells_topological`
|
|
1810
|
+
|
|
1811
|
+
EXAMPLES::
|
|
1812
|
+
|
|
1813
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1814
|
+
sage: class T(tuple):
|
|
1815
|
+
....: def __le__(left, right):
|
|
1816
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
1817
|
+
sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
|
|
1818
|
+
....: T((4, 4)), T((1, 2)), T((2, 2))])
|
|
1819
|
+
sage: [(v, type(v)) for v in P.elements_topological(key=repr)]
|
|
1820
|
+
[((1, 1), <class '__main__.T'>),
|
|
1821
|
+
((1, 2), <class '__main__.T'>),
|
|
1822
|
+
((1, 3), <class '__main__.T'>),
|
|
1823
|
+
((2, 1), <class '__main__.T'>),
|
|
1824
|
+
((2, 2), <class '__main__.T'>),
|
|
1825
|
+
((4, 4), <class '__main__.T'>)]
|
|
1826
|
+
|
|
1827
|
+
.. SEEALSO::
|
|
1828
|
+
|
|
1829
|
+
:meth:`shells`,
|
|
1830
|
+
:meth:`shells_topological`,
|
|
1831
|
+
:meth:`elements`,
|
|
1832
|
+
:meth:`keys`,
|
|
1833
|
+
:meth:`keys_topological`,
|
|
1834
|
+
:meth:`MutablePosetShell.iter_depth_first`,
|
|
1835
|
+
:meth:`MutablePosetShell.iter_topological`.
|
|
1836
|
+
"""
|
|
1837
|
+
for shell in self.shells_topological(**kwargs):
|
|
1838
|
+
yield shell.element
|
|
1839
|
+
|
|
1840
|
+
def keys(self, **kwargs):
|
|
1841
|
+
r"""
|
|
1842
|
+
Return an iterator over all keys of the elements.
|
|
1843
|
+
|
|
1844
|
+
INPUT:
|
|
1845
|
+
|
|
1846
|
+
- ``kwargs`` -- arguments are passed to :meth:`shells`
|
|
1847
|
+
|
|
1848
|
+
EXAMPLES::
|
|
1849
|
+
|
|
1850
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1851
|
+
sage: P = MP([3, 42, 7], key=lambda c: -c)
|
|
1852
|
+
sage: [(v, type(v)) for v in sorted(P.keys())]
|
|
1853
|
+
[(-42, <class 'sage.rings.integer.Integer'>),
|
|
1854
|
+
(-7, <class 'sage.rings.integer.Integer'>),
|
|
1855
|
+
(-3, <class 'sage.rings.integer.Integer'>)]
|
|
1856
|
+
|
|
1857
|
+
sage: [(v, type(v)) for v in sorted(P.elements())]
|
|
1858
|
+
[(3, <class 'sage.rings.integer.Integer'>),
|
|
1859
|
+
(7, <class 'sage.rings.integer.Integer'>),
|
|
1860
|
+
(42, <class 'sage.rings.integer.Integer'>)]
|
|
1861
|
+
|
|
1862
|
+
sage: [(v, type(v)) for v in sorted(P.shells(),
|
|
1863
|
+
....: key=lambda c: c.element)]
|
|
1864
|
+
[(3, <class 'sage.data_structures.mutable_poset.MutablePosetShell'>),
|
|
1865
|
+
(7, <class 'sage.data_structures.mutable_poset.MutablePosetShell'>),
|
|
1866
|
+
(42, <class 'sage.data_structures.mutable_poset.MutablePosetShell'>)]
|
|
1867
|
+
|
|
1868
|
+
.. SEEALSO::
|
|
1869
|
+
|
|
1870
|
+
:meth:`shells`,
|
|
1871
|
+
:meth:`shells_topological`,
|
|
1872
|
+
:meth:`elements`,
|
|
1873
|
+
:meth:`elements_topological`,
|
|
1874
|
+
:meth:`keys_topological`,
|
|
1875
|
+
:meth:`MutablePosetShell.iter_depth_first`,
|
|
1876
|
+
:meth:`MutablePosetShell.iter_topological`.
|
|
1877
|
+
"""
|
|
1878
|
+
for shell in self.shells(**kwargs):
|
|
1879
|
+
yield shell.key
|
|
1880
|
+
|
|
1881
|
+
def keys_topological(self, **kwargs):
|
|
1882
|
+
r"""
|
|
1883
|
+
Return an iterator over all keys of the elements in
|
|
1884
|
+
topological order.
|
|
1885
|
+
|
|
1886
|
+
INPUT:
|
|
1887
|
+
|
|
1888
|
+
- ``kwargs`` -- arguments are passed to :meth:`shells_topological`
|
|
1889
|
+
|
|
1890
|
+
EXAMPLES::
|
|
1891
|
+
|
|
1892
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1893
|
+
sage: P = MP([(1, 1), (2, 1), (4, 4)],
|
|
1894
|
+
....: key=lambda c: c[0])
|
|
1895
|
+
sage: [(v, type(v)) for v in P.keys_topological(key=repr)]
|
|
1896
|
+
[(1, <class 'sage.rings.integer.Integer'>),
|
|
1897
|
+
(2, <class 'sage.rings.integer.Integer'>),
|
|
1898
|
+
(4, <class 'sage.rings.integer.Integer'>)]
|
|
1899
|
+
sage: [(v, type(v)) for v in P.elements_topological(key=repr)]
|
|
1900
|
+
[((1, 1), <... 'tuple'>),
|
|
1901
|
+
((2, 1), <... 'tuple'>),
|
|
1902
|
+
((4, 4), <... 'tuple'>)]
|
|
1903
|
+
sage: [(v, type(v)) for v in P.shells_topological(key=repr)]
|
|
1904
|
+
[((1, 1), <class 'sage.data_structures.mutable_poset.MutablePosetShell'>),
|
|
1905
|
+
((2, 1), <class 'sage.data_structures.mutable_poset.MutablePosetShell'>),
|
|
1906
|
+
((4, 4), <class 'sage.data_structures.mutable_poset.MutablePosetShell'>)]
|
|
1907
|
+
|
|
1908
|
+
.. SEEALSO::
|
|
1909
|
+
|
|
1910
|
+
:meth:`shells`,
|
|
1911
|
+
:meth:`shells_topological`,
|
|
1912
|
+
:meth:`elements`,
|
|
1913
|
+
:meth:`elements_topological`,
|
|
1914
|
+
:meth:`keys`,
|
|
1915
|
+
:meth:`MutablePosetShell.iter_depth_first`,
|
|
1916
|
+
:meth:`MutablePosetShell.iter_topological`.
|
|
1917
|
+
"""
|
|
1918
|
+
for shell in self.shells_topological(**kwargs):
|
|
1919
|
+
yield shell.key
|
|
1920
|
+
|
|
1921
|
+
def repr(self, include_special=False, reverse=False):
|
|
1922
|
+
r"""
|
|
1923
|
+
Return a representation of the poset.
|
|
1924
|
+
|
|
1925
|
+
INPUT:
|
|
1926
|
+
|
|
1927
|
+
- ``include_special`` -- boolean (default: ``False``); whether to
|
|
1928
|
+
include the special elements ``'null'`` and ``'oo'`` or not
|
|
1929
|
+
|
|
1930
|
+
- ``reverse`` -- boolean (default: ``False``); if set, then
|
|
1931
|
+
largest elements are displayed first
|
|
1932
|
+
|
|
1933
|
+
OUTPUT: string
|
|
1934
|
+
|
|
1935
|
+
.. SEEALSO::
|
|
1936
|
+
|
|
1937
|
+
:meth:`repr_full`
|
|
1938
|
+
|
|
1939
|
+
TESTS::
|
|
1940
|
+
|
|
1941
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1942
|
+
sage: print(MP().repr())
|
|
1943
|
+
poset()
|
|
1944
|
+
"""
|
|
1945
|
+
s = 'poset('
|
|
1946
|
+
s += ', '.join(repr(shell) for shell in
|
|
1947
|
+
self.shells_topological(include_special, reverse,
|
|
1948
|
+
key=repr))
|
|
1949
|
+
s += ')'
|
|
1950
|
+
return s
|
|
1951
|
+
|
|
1952
|
+
def repr_full(self, reverse=False):
|
|
1953
|
+
r"""
|
|
1954
|
+
Return a representation with ordering details of the poset.
|
|
1955
|
+
|
|
1956
|
+
INPUT:
|
|
1957
|
+
|
|
1958
|
+
- ``reverse`` -- boolean (default: ``False``); if set, then
|
|
1959
|
+
largest elements are displayed first
|
|
1960
|
+
|
|
1961
|
+
OUTPUT: string
|
|
1962
|
+
|
|
1963
|
+
.. SEEALSO::
|
|
1964
|
+
|
|
1965
|
+
:meth:`repr`
|
|
1966
|
+
|
|
1967
|
+
TESTS::
|
|
1968
|
+
|
|
1969
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
1970
|
+
sage: print(MP().repr_full(reverse=True))
|
|
1971
|
+
poset()
|
|
1972
|
+
+-- oo
|
|
1973
|
+
| +-- no successors
|
|
1974
|
+
| +-- predecessors: null
|
|
1975
|
+
+-- null
|
|
1976
|
+
| +-- successors: oo
|
|
1977
|
+
| +-- no predecessors
|
|
1978
|
+
"""
|
|
1979
|
+
sortedshells = tuple(
|
|
1980
|
+
self.shells_topological(include_special=True,
|
|
1981
|
+
reverse=reverse,
|
|
1982
|
+
key=repr))
|
|
1983
|
+
strings = [self.repr(include_special=False, reverse=reverse)]
|
|
1984
|
+
for shell in sortedshells:
|
|
1985
|
+
strings.append('+-- ' + repr(shell))
|
|
1986
|
+
for rev in (not reverse, reverse):
|
|
1987
|
+
what = 'successors' if not rev else 'predecessors'
|
|
1988
|
+
if shell.successors(rev):
|
|
1989
|
+
s = '| +-- ' + what + ': '
|
|
1990
|
+
s += ', '.join(repr(e) for e in
|
|
1991
|
+
sortedshells if e in shell.successors(rev))
|
|
1992
|
+
else:
|
|
1993
|
+
s = '| +-- no ' + what
|
|
1994
|
+
strings.append(s)
|
|
1995
|
+
return '\n'.join(strings)
|
|
1996
|
+
|
|
1997
|
+
_repr_ = repr
|
|
1998
|
+
|
|
1999
|
+
def contains(self, key):
|
|
2000
|
+
r"""
|
|
2001
|
+
Test whether ``key`` is encapsulated by one of the poset's elements.
|
|
2002
|
+
|
|
2003
|
+
INPUT:
|
|
2004
|
+
|
|
2005
|
+
- ``key`` -- an object
|
|
2006
|
+
|
|
2007
|
+
OUTPUT: boolean
|
|
2008
|
+
|
|
2009
|
+
.. SEEALSO::
|
|
2010
|
+
|
|
2011
|
+
:meth:`shells`,
|
|
2012
|
+
:meth:`elements`,
|
|
2013
|
+
:meth:`keys`.
|
|
2014
|
+
|
|
2015
|
+
TESTS::
|
|
2016
|
+
|
|
2017
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
2018
|
+
sage: class T(tuple):
|
|
2019
|
+
....: def __le__(left, right):
|
|
2020
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
2021
|
+
sage: P = MP()
|
|
2022
|
+
sage: P.add(T((1, 1)))
|
|
2023
|
+
sage: T((1, 1)) in P # indirect doctest
|
|
2024
|
+
True
|
|
2025
|
+
sage: T((1, 2)) in P # indirect doctest
|
|
2026
|
+
False
|
|
2027
|
+
"""
|
|
2028
|
+
return key in self._shells_
|
|
2029
|
+
|
|
2030
|
+
__contains__ = contains
|
|
2031
|
+
|
|
2032
|
+
def add(self, element):
|
|
2033
|
+
r"""
|
|
2034
|
+
Add the given object as element to the poset.
|
|
2035
|
+
|
|
2036
|
+
INPUT:
|
|
2037
|
+
|
|
2038
|
+
- ``element`` -- an object (hashable and supporting comparison
|
|
2039
|
+
with the operator ``<=``)
|
|
2040
|
+
|
|
2041
|
+
OUTPUT: nothing
|
|
2042
|
+
|
|
2043
|
+
EXAMPLES::
|
|
2044
|
+
|
|
2045
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
2046
|
+
sage: class T(tuple):
|
|
2047
|
+
....: def __le__(left, right):
|
|
2048
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
2049
|
+
sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
|
|
2050
|
+
....: T((4, 4)), T((1, 2))])
|
|
2051
|
+
sage: print(P.repr_full(reverse=True))
|
|
2052
|
+
poset((4, 4), (1, 3), (1, 2), (2, 1), (1, 1))
|
|
2053
|
+
+-- oo
|
|
2054
|
+
| +-- no successors
|
|
2055
|
+
| +-- predecessors: (4, 4)
|
|
2056
|
+
+-- (4, 4)
|
|
2057
|
+
| +-- successors: oo
|
|
2058
|
+
| +-- predecessors: (1, 3), (2, 1)
|
|
2059
|
+
+-- (1, 3)
|
|
2060
|
+
| +-- successors: (4, 4)
|
|
2061
|
+
| +-- predecessors: (1, 2)
|
|
2062
|
+
+-- (1, 2)
|
|
2063
|
+
| +-- successors: (1, 3)
|
|
2064
|
+
| +-- predecessors: (1, 1)
|
|
2065
|
+
+-- (2, 1)
|
|
2066
|
+
| +-- successors: (4, 4)
|
|
2067
|
+
| +-- predecessors: (1, 1)
|
|
2068
|
+
+-- (1, 1)
|
|
2069
|
+
| +-- successors: (1, 2), (2, 1)
|
|
2070
|
+
| +-- predecessors: null
|
|
2071
|
+
+-- null
|
|
2072
|
+
| +-- successors: (1, 1)
|
|
2073
|
+
| +-- no predecessors
|
|
2074
|
+
sage: P.add(T((2, 2)))
|
|
2075
|
+
sage: reprP = P.repr_full(reverse=True); print(reprP)
|
|
2076
|
+
poset((4, 4), (1, 3), (2, 2), (1, 2), (2, 1), (1, 1))
|
|
2077
|
+
+-- oo
|
|
2078
|
+
| +-- no successors
|
|
2079
|
+
| +-- predecessors: (4, 4)
|
|
2080
|
+
+-- (4, 4)
|
|
2081
|
+
| +-- successors: oo
|
|
2082
|
+
| +-- predecessors: (1, 3), (2, 2)
|
|
2083
|
+
+-- (1, 3)
|
|
2084
|
+
| +-- successors: (4, 4)
|
|
2085
|
+
| +-- predecessors: (1, 2)
|
|
2086
|
+
+-- (2, 2)
|
|
2087
|
+
| +-- successors: (4, 4)
|
|
2088
|
+
| +-- predecessors: (1, 2), (2, 1)
|
|
2089
|
+
+-- (1, 2)
|
|
2090
|
+
| +-- successors: (1, 3), (2, 2)
|
|
2091
|
+
| +-- predecessors: (1, 1)
|
|
2092
|
+
+-- (2, 1)
|
|
2093
|
+
| +-- successors: (2, 2)
|
|
2094
|
+
| +-- predecessors: (1, 1)
|
|
2095
|
+
+-- (1, 1)
|
|
2096
|
+
| +-- successors: (1, 2), (2, 1)
|
|
2097
|
+
| +-- predecessors: null
|
|
2098
|
+
+-- null
|
|
2099
|
+
| +-- successors: (1, 1)
|
|
2100
|
+
| +-- no predecessors
|
|
2101
|
+
|
|
2102
|
+
When adding an element which is already in the poset, nothing happens::
|
|
2103
|
+
|
|
2104
|
+
sage: e = T((2, 2))
|
|
2105
|
+
sage: P.add(e)
|
|
2106
|
+
sage: P.repr_full(reverse=True) == reprP
|
|
2107
|
+
True
|
|
2108
|
+
|
|
2109
|
+
We can influence the behavior when an element with existing key
|
|
2110
|
+
is to be inserted in the poset. For example, we can perform an
|
|
2111
|
+
addition on some argument of the elements::
|
|
2112
|
+
|
|
2113
|
+
sage: def add(left, right):
|
|
2114
|
+
....: return (left[0], ''.join(sorted(left[1] + right[1])))
|
|
2115
|
+
sage: A = MP(key=lambda k: k[0], merge=add)
|
|
2116
|
+
sage: A.add((3, 'a'))
|
|
2117
|
+
sage: A
|
|
2118
|
+
poset((3, 'a'))
|
|
2119
|
+
sage: A.add((3, 'b'))
|
|
2120
|
+
sage: A
|
|
2121
|
+
poset((3, 'ab'))
|
|
2122
|
+
|
|
2123
|
+
We can also deal with cancellations. If the return value of
|
|
2124
|
+
our hook-function is ``None``, then the element is removed out of
|
|
2125
|
+
the poset::
|
|
2126
|
+
|
|
2127
|
+
sage: def add_None(left, right):
|
|
2128
|
+
....: s = left[1] + right[1]
|
|
2129
|
+
....: if s == 0:
|
|
2130
|
+
....: return None
|
|
2131
|
+
....: return (left[0], s)
|
|
2132
|
+
sage: B = MP(key=lambda k: k[0],
|
|
2133
|
+
....: merge=add_None)
|
|
2134
|
+
sage: B.add((7, 42))
|
|
2135
|
+
sage: B.add((7, -42))
|
|
2136
|
+
sage: B
|
|
2137
|
+
poset()
|
|
2138
|
+
|
|
2139
|
+
.. SEEALSO::
|
|
2140
|
+
|
|
2141
|
+
:meth:`discard`,
|
|
2142
|
+
:meth:`pop`,
|
|
2143
|
+
:meth:`remove`.
|
|
2144
|
+
|
|
2145
|
+
TESTS::
|
|
2146
|
+
|
|
2147
|
+
sage: R = MP([(1, 1, 42), (1, 3, 42), (2, 1, 7),
|
|
2148
|
+
....: (4, 4, 42), (1, 2, 7), (2, 2, 7)],
|
|
2149
|
+
....: key=lambda k: T(k[2:3]))
|
|
2150
|
+
sage: print(R.repr_full(reverse=True))
|
|
2151
|
+
poset((1, 1, 42), (2, 1, 7))
|
|
2152
|
+
+-- oo
|
|
2153
|
+
| +-- no successors
|
|
2154
|
+
| +-- predecessors: (1, 1, 42)
|
|
2155
|
+
+-- (1, 1, 42)
|
|
2156
|
+
| +-- successors: oo
|
|
2157
|
+
| +-- predecessors: (2, 1, 7)
|
|
2158
|
+
+-- (2, 1, 7)
|
|
2159
|
+
| +-- successors: (1, 1, 42)
|
|
2160
|
+
| +-- predecessors: null
|
|
2161
|
+
+-- null
|
|
2162
|
+
| +-- successors: (2, 1, 7)
|
|
2163
|
+
| +-- no predecessors
|
|
2164
|
+
|
|
2165
|
+
::
|
|
2166
|
+
|
|
2167
|
+
sage: P = MP()
|
|
2168
|
+
sage: P.add(None)
|
|
2169
|
+
Traceback (most recent call last):
|
|
2170
|
+
...
|
|
2171
|
+
ValueError: None is not an allowed element.
|
|
2172
|
+
"""
|
|
2173
|
+
if element is None:
|
|
2174
|
+
raise ValueError('None is not an allowed element.')
|
|
2175
|
+
key = self.get_key(element)
|
|
2176
|
+
|
|
2177
|
+
if key in self._shells_:
|
|
2178
|
+
if self._merge_ is not None:
|
|
2179
|
+
self.shell(key).merge(element, delete=False)
|
|
2180
|
+
return
|
|
2181
|
+
|
|
2182
|
+
new = MutablePosetShell(self, element)
|
|
2183
|
+
new._predecessors_ = self.null.lower_covers(new)
|
|
2184
|
+
new._successors_ = self.oo.upper_covers(new)
|
|
2185
|
+
|
|
2186
|
+
for s in new.predecessors():
|
|
2187
|
+
for l in s.successors().intersection(new.successors()):
|
|
2188
|
+
l.predecessors().remove(s)
|
|
2189
|
+
s.successors().remove(l)
|
|
2190
|
+
s.successors().add(new)
|
|
2191
|
+
for l in new.successors():
|
|
2192
|
+
l.predecessors().add(new)
|
|
2193
|
+
|
|
2194
|
+
self._shells_[key] = new
|
|
2195
|
+
|
|
2196
|
+
def remove(self, key, raise_key_error=True):
|
|
2197
|
+
r"""
|
|
2198
|
+
Remove the given object from the poset.
|
|
2199
|
+
|
|
2200
|
+
INPUT:
|
|
2201
|
+
|
|
2202
|
+
- ``key`` -- the key of an object
|
|
2203
|
+
|
|
2204
|
+
- ``raise_key_error`` -- boolean (default: ``True``); switch raising
|
|
2205
|
+
:exc:`KeyError` on and off
|
|
2206
|
+
|
|
2207
|
+
OUTPUT: nothing
|
|
2208
|
+
|
|
2209
|
+
If the element is not a member and ``raise_key_error`` is set
|
|
2210
|
+
(default), raise a :exc:`KeyError`.
|
|
2211
|
+
|
|
2212
|
+
.. NOTE::
|
|
2213
|
+
|
|
2214
|
+
As with Python's ``set``, the methods :meth:`remove`
|
|
2215
|
+
and :meth:`discard` only differ in their behavior when an
|
|
2216
|
+
element is not contained in the poset: :meth:`remove`
|
|
2217
|
+
raises a :exc:`KeyError` whereas :meth:`discard` does not
|
|
2218
|
+
raise any exception.
|
|
2219
|
+
|
|
2220
|
+
This default behavior can be overridden with the
|
|
2221
|
+
``raise_key_error`` parameter.
|
|
2222
|
+
|
|
2223
|
+
EXAMPLES::
|
|
2224
|
+
|
|
2225
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
2226
|
+
sage: class T(tuple):
|
|
2227
|
+
....: def __le__(left, right):
|
|
2228
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
2229
|
+
sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
|
|
2230
|
+
....: T((4, 4)), T((1, 2)), T((2, 2))])
|
|
2231
|
+
sage: print(P.repr_full(reverse=True))
|
|
2232
|
+
poset((4, 4), (1, 3), (2, 2), (1, 2), (2, 1), (1, 1))
|
|
2233
|
+
+-- oo
|
|
2234
|
+
| +-- no successors
|
|
2235
|
+
| +-- predecessors: (4, 4)
|
|
2236
|
+
+-- (4, 4)
|
|
2237
|
+
| +-- successors: oo
|
|
2238
|
+
| +-- predecessors: (1, 3), (2, 2)
|
|
2239
|
+
+-- (1, 3)
|
|
2240
|
+
| +-- successors: (4, 4)
|
|
2241
|
+
| +-- predecessors: (1, 2)
|
|
2242
|
+
+-- (2, 2)
|
|
2243
|
+
| +-- successors: (4, 4)
|
|
2244
|
+
| +-- predecessors: (1, 2), (2, 1)
|
|
2245
|
+
+-- (1, 2)
|
|
2246
|
+
| +-- successors: (1, 3), (2, 2)
|
|
2247
|
+
| +-- predecessors: (1, 1)
|
|
2248
|
+
+-- (2, 1)
|
|
2249
|
+
| +-- successors: (2, 2)
|
|
2250
|
+
| +-- predecessors: (1, 1)
|
|
2251
|
+
+-- (1, 1)
|
|
2252
|
+
| +-- successors: (1, 2), (2, 1)
|
|
2253
|
+
| +-- predecessors: null
|
|
2254
|
+
+-- null
|
|
2255
|
+
| +-- successors: (1, 1)
|
|
2256
|
+
| +-- no predecessors
|
|
2257
|
+
sage: P.remove(T((1, 2)))
|
|
2258
|
+
sage: print(P.repr_full(reverse=True))
|
|
2259
|
+
poset((4, 4), (1, 3), (2, 2), (2, 1), (1, 1))
|
|
2260
|
+
+-- oo
|
|
2261
|
+
| +-- no successors
|
|
2262
|
+
| +-- predecessors: (4, 4)
|
|
2263
|
+
+-- (4, 4)
|
|
2264
|
+
| +-- successors: oo
|
|
2265
|
+
| +-- predecessors: (1, 3), (2, 2)
|
|
2266
|
+
+-- (1, 3)
|
|
2267
|
+
| +-- successors: (4, 4)
|
|
2268
|
+
| +-- predecessors: (1, 1)
|
|
2269
|
+
+-- (2, 2)
|
|
2270
|
+
| +-- successors: (4, 4)
|
|
2271
|
+
| +-- predecessors: (2, 1)
|
|
2272
|
+
+-- (2, 1)
|
|
2273
|
+
| +-- successors: (2, 2)
|
|
2274
|
+
| +-- predecessors: (1, 1)
|
|
2275
|
+
+-- (1, 1)
|
|
2276
|
+
| +-- successors: (1, 3), (2, 1)
|
|
2277
|
+
| +-- predecessors: null
|
|
2278
|
+
+-- null
|
|
2279
|
+
| +-- successors: (1, 1)
|
|
2280
|
+
| +-- no predecessors
|
|
2281
|
+
|
|
2282
|
+
.. SEEALSO::
|
|
2283
|
+
|
|
2284
|
+
:meth:`add`,
|
|
2285
|
+
:meth:`clear`,
|
|
2286
|
+
:meth:`discard`,
|
|
2287
|
+
:meth:`pop`.
|
|
2288
|
+
|
|
2289
|
+
TESTS::
|
|
2290
|
+
|
|
2291
|
+
sage: Q = MP([(1, 1, 42), (1, 3, 42), (2, 1, 7),
|
|
2292
|
+
....: (4, 4, 42), (1, 2, 7), (2, 2, 7)],
|
|
2293
|
+
....: key=lambda k: T(k[0:2]))
|
|
2294
|
+
sage: print(Q.repr_full(reverse=True))
|
|
2295
|
+
poset((4, 4, 42), (1, 3, 42), (2, 2, 7),
|
|
2296
|
+
(1, 2, 7), (2, 1, 7), (1, 1, 42))
|
|
2297
|
+
+-- oo
|
|
2298
|
+
| +-- no successors
|
|
2299
|
+
| +-- predecessors: (4, 4, 42)
|
|
2300
|
+
+-- (4, 4, 42)
|
|
2301
|
+
| +-- successors: oo
|
|
2302
|
+
| +-- predecessors: (1, 3, 42), (2, 2, 7)
|
|
2303
|
+
+-- (1, 3, 42)
|
|
2304
|
+
| +-- successors: (4, 4, 42)
|
|
2305
|
+
| +-- predecessors: (1, 2, 7)
|
|
2306
|
+
+-- (2, 2, 7)
|
|
2307
|
+
| +-- successors: (4, 4, 42)
|
|
2308
|
+
| +-- predecessors: (1, 2, 7), (2, 1, 7)
|
|
2309
|
+
+-- (1, 2, 7)
|
|
2310
|
+
| +-- successors: (1, 3, 42), (2, 2, 7)
|
|
2311
|
+
| +-- predecessors: (1, 1, 42)
|
|
2312
|
+
+-- (2, 1, 7)
|
|
2313
|
+
| +-- successors: (2, 2, 7)
|
|
2314
|
+
| +-- predecessors: (1, 1, 42)
|
|
2315
|
+
+-- (1, 1, 42)
|
|
2316
|
+
| +-- successors: (1, 2, 7), (2, 1, 7)
|
|
2317
|
+
| +-- predecessors: null
|
|
2318
|
+
+-- null
|
|
2319
|
+
| +-- successors: (1, 1, 42)
|
|
2320
|
+
| +-- no predecessors
|
|
2321
|
+
sage: Q.remove((1,1))
|
|
2322
|
+
sage: print(Q.repr_full(reverse=True))
|
|
2323
|
+
poset((4, 4, 42), (1, 3, 42), (2, 2, 7), (1, 2, 7), (2, 1, 7))
|
|
2324
|
+
+-- oo
|
|
2325
|
+
| +-- no successors
|
|
2326
|
+
| +-- predecessors: (4, 4, 42)
|
|
2327
|
+
+-- (4, 4, 42)
|
|
2328
|
+
| +-- successors: oo
|
|
2329
|
+
| +-- predecessors: (1, 3, 42), (2, 2, 7)
|
|
2330
|
+
+-- (1, 3, 42)
|
|
2331
|
+
| +-- successors: (4, 4, 42)
|
|
2332
|
+
| +-- predecessors: (1, 2, 7)
|
|
2333
|
+
+-- (2, 2, 7)
|
|
2334
|
+
| +-- successors: (4, 4, 42)
|
|
2335
|
+
| +-- predecessors: (1, 2, 7), (2, 1, 7)
|
|
2336
|
+
+-- (1, 2, 7)
|
|
2337
|
+
| +-- successors: (1, 3, 42), (2, 2, 7)
|
|
2338
|
+
| +-- predecessors: null
|
|
2339
|
+
+-- (2, 1, 7)
|
|
2340
|
+
| +-- successors: (2, 2, 7)
|
|
2341
|
+
| +-- predecessors: null
|
|
2342
|
+
+-- null
|
|
2343
|
+
| +-- successors: (1, 2, 7), (2, 1, 7)
|
|
2344
|
+
| +-- no predecessors
|
|
2345
|
+
|
|
2346
|
+
::
|
|
2347
|
+
|
|
2348
|
+
sage: P = MP()
|
|
2349
|
+
sage: P.remove(None)
|
|
2350
|
+
Traceback (most recent call last):
|
|
2351
|
+
...
|
|
2352
|
+
ValueError: None is not an allowed key.
|
|
2353
|
+
"""
|
|
2354
|
+
if key is None:
|
|
2355
|
+
raise ValueError('None is not an allowed key.')
|
|
2356
|
+
|
|
2357
|
+
try:
|
|
2358
|
+
shell = self._shells_[key]
|
|
2359
|
+
except KeyError:
|
|
2360
|
+
if not raise_key_error:
|
|
2361
|
+
return
|
|
2362
|
+
raise KeyError('Key %s is not contained in this poset.' % (key,))
|
|
2363
|
+
|
|
2364
|
+
for reverse in (False, True):
|
|
2365
|
+
for p in shell.predecessors(reverse):
|
|
2366
|
+
S = p.successors(reverse)
|
|
2367
|
+
S.remove(shell)
|
|
2368
|
+
D = set(s for s in p.iter_depth_first(reverse)
|
|
2369
|
+
if s in shell.successors(reverse))
|
|
2370
|
+
S.update(shell.successors(reverse))
|
|
2371
|
+
S.difference_update(D)
|
|
2372
|
+
del self._shells_[key]
|
|
2373
|
+
|
|
2374
|
+
def discard(self, key, raise_key_error=False):
|
|
2375
|
+
r"""
|
|
2376
|
+
Remove the given object from the poset.
|
|
2377
|
+
|
|
2378
|
+
INPUT:
|
|
2379
|
+
|
|
2380
|
+
- ``key`` -- the key of an object
|
|
2381
|
+
|
|
2382
|
+
- ``raise_key_error`` -- boolean (default: ``False``); switch raising
|
|
2383
|
+
:exc:`KeyError` on and off
|
|
2384
|
+
|
|
2385
|
+
OUTPUT: nothing
|
|
2386
|
+
|
|
2387
|
+
If the element is not a member and ``raise_key_error`` is set
|
|
2388
|
+
(not default), raise a :exc:`KeyError`.
|
|
2389
|
+
|
|
2390
|
+
.. NOTE::
|
|
2391
|
+
|
|
2392
|
+
As with Python's ``set``, the methods :meth:`remove`
|
|
2393
|
+
and :meth:`discard` only differ in their behavior when an
|
|
2394
|
+
element is not contained in the poset: :meth:`remove`
|
|
2395
|
+
raises a :exc:`KeyError` whereas :meth:`discard` does not
|
|
2396
|
+
raise any exception.
|
|
2397
|
+
|
|
2398
|
+
This default behavior can be overridden with the
|
|
2399
|
+
``raise_key_error`` parameter.
|
|
2400
|
+
|
|
2401
|
+
EXAMPLES::
|
|
2402
|
+
|
|
2403
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
2404
|
+
sage: class T(tuple):
|
|
2405
|
+
....: def __le__(left, right):
|
|
2406
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
2407
|
+
sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
|
|
2408
|
+
....: T((4, 4)), T((1, 2)), T((2, 2))])
|
|
2409
|
+
sage: P.discard(T((1, 2)))
|
|
2410
|
+
sage: P.remove(T((1, 2)))
|
|
2411
|
+
Traceback (most recent call last):
|
|
2412
|
+
...
|
|
2413
|
+
KeyError: 'Key (1, 2) is not contained in this poset.'
|
|
2414
|
+
sage: P.discard(T((1, 2)))
|
|
2415
|
+
|
|
2416
|
+
.. SEEALSO::
|
|
2417
|
+
|
|
2418
|
+
:meth:`add`,
|
|
2419
|
+
:meth:`clear`,
|
|
2420
|
+
:meth:`remove`,
|
|
2421
|
+
:meth:`pop`.
|
|
2422
|
+
"""
|
|
2423
|
+
return self.remove(key, raise_key_error)
|
|
2424
|
+
|
|
2425
|
+
def pop(self, **kwargs):
|
|
2426
|
+
r"""
|
|
2427
|
+
Remove and return an arbitrary poset element.
|
|
2428
|
+
|
|
2429
|
+
INPUT:
|
|
2430
|
+
|
|
2431
|
+
- ``kwargs`` -- arguments are passed to :meth:`shells_topological`
|
|
2432
|
+
|
|
2433
|
+
OUTPUT: an object
|
|
2434
|
+
|
|
2435
|
+
.. NOTE::
|
|
2436
|
+
|
|
2437
|
+
The special elements ``'null'`` and ``'oo'`` cannot be popped.
|
|
2438
|
+
|
|
2439
|
+
EXAMPLES::
|
|
2440
|
+
|
|
2441
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
2442
|
+
sage: P = MP()
|
|
2443
|
+
sage: P.add(3)
|
|
2444
|
+
sage: P
|
|
2445
|
+
poset(3)
|
|
2446
|
+
sage: P.pop()
|
|
2447
|
+
3
|
|
2448
|
+
sage: P
|
|
2449
|
+
poset()
|
|
2450
|
+
sage: P.pop()
|
|
2451
|
+
Traceback (most recent call last):
|
|
2452
|
+
...
|
|
2453
|
+
KeyError: 'pop from an empty poset'
|
|
2454
|
+
|
|
2455
|
+
.. SEEALSO::
|
|
2456
|
+
|
|
2457
|
+
:meth:`add`,
|
|
2458
|
+
:meth:`clear`,
|
|
2459
|
+
:meth:`discard`,
|
|
2460
|
+
:meth:`remove`.
|
|
2461
|
+
"""
|
|
2462
|
+
kwargs['include_special'] = False
|
|
2463
|
+
|
|
2464
|
+
try:
|
|
2465
|
+
shell = next(self.shells_topological(**kwargs))
|
|
2466
|
+
except StopIteration:
|
|
2467
|
+
raise KeyError('pop from an empty poset')
|
|
2468
|
+
self.remove(shell.key)
|
|
2469
|
+
return shell.element
|
|
2470
|
+
|
|
2471
|
+
def union(self, *other):
|
|
2472
|
+
r"""
|
|
2473
|
+
Return the union of the given posets as a new poset.
|
|
2474
|
+
|
|
2475
|
+
INPUT:
|
|
2476
|
+
|
|
2477
|
+
- ``other`` -- a poset or an iterable. In the latter case the
|
|
2478
|
+
iterated objects are seen as elements of a poset.
|
|
2479
|
+
It is possible to specify more than one ``other`` as
|
|
2480
|
+
variadic arguments (arbitrary argument lists).
|
|
2481
|
+
|
|
2482
|
+
.. NOTE::
|
|
2483
|
+
|
|
2484
|
+
The key of an element is used for comparison. Thus elements with
|
|
2485
|
+
the same key are considered as equal.
|
|
2486
|
+
|
|
2487
|
+
Due to keys and a ``merge`` function (see :class:`MutablePoset`)
|
|
2488
|
+
this operation might not be commutative.
|
|
2489
|
+
|
|
2490
|
+
.. TODO::
|
|
2491
|
+
|
|
2492
|
+
Use the already existing information in the other poset to speed
|
|
2493
|
+
up this function. (At the moment each element of the other poset
|
|
2494
|
+
is inserted one by one and without using this information.)
|
|
2495
|
+
|
|
2496
|
+
EXAMPLES::
|
|
2497
|
+
|
|
2498
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
2499
|
+
sage: P = MP([3, 42, 7]); P
|
|
2500
|
+
poset(3, 7, 42)
|
|
2501
|
+
sage: Q = MP([4, 8, 42]); Q
|
|
2502
|
+
poset(4, 8, 42)
|
|
2503
|
+
sage: P.union(Q)
|
|
2504
|
+
poset(3, 4, 7, 8, 42)
|
|
2505
|
+
|
|
2506
|
+
.. SEEALSO::
|
|
2507
|
+
|
|
2508
|
+
:meth:`union_update`,
|
|
2509
|
+
:meth:`difference`, :meth:`difference_update`,
|
|
2510
|
+
:meth:`intersection`, :meth:`intersection_update`,
|
|
2511
|
+
:meth:`symmetric_difference`, :meth:`symmetric_difference_update`,
|
|
2512
|
+
:meth:`is_disjoint`,
|
|
2513
|
+
:meth:`is_subset`,
|
|
2514
|
+
:meth:`is_superset`.
|
|
2515
|
+
|
|
2516
|
+
TESTS::
|
|
2517
|
+
|
|
2518
|
+
sage: P.union(P, Q, Q, P)
|
|
2519
|
+
poset(3, 4, 7, 8, 42)
|
|
2520
|
+
"""
|
|
2521
|
+
new = self.copy()
|
|
2522
|
+
new.update(*other)
|
|
2523
|
+
return new
|
|
2524
|
+
|
|
2525
|
+
def union_update(self, *other):
|
|
2526
|
+
r"""
|
|
2527
|
+
Update this poset with the union of itself and another poset.
|
|
2528
|
+
|
|
2529
|
+
INPUT:
|
|
2530
|
+
|
|
2531
|
+
- ``other`` -- a poset or an iterable. In the latter case the
|
|
2532
|
+
iterated objects are seen as elements of a poset.
|
|
2533
|
+
It is possible to specify more than one ``other`` as
|
|
2534
|
+
variadic arguments (arbitrary argument lists).
|
|
2535
|
+
|
|
2536
|
+
OUTPUT: nothing
|
|
2537
|
+
|
|
2538
|
+
.. NOTE::
|
|
2539
|
+
|
|
2540
|
+
The key of an element is used for comparison. Thus elements with
|
|
2541
|
+
the same key are considered as equal;
|
|
2542
|
+
``A.union_update(B)`` and ``B.union_update(A)`` might
|
|
2543
|
+
result in different posets.
|
|
2544
|
+
|
|
2545
|
+
.. TODO::
|
|
2546
|
+
|
|
2547
|
+
Use the already existing information in the other poset to speed
|
|
2548
|
+
up this function. (At the moment each element of the other poset
|
|
2549
|
+
is inserted one by one and without using this information.)
|
|
2550
|
+
|
|
2551
|
+
EXAMPLES::
|
|
2552
|
+
|
|
2553
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
2554
|
+
sage: P = MP([3, 42, 7]); P
|
|
2555
|
+
poset(3, 7, 42)
|
|
2556
|
+
sage: Q = MP([4, 8, 42]); Q
|
|
2557
|
+
poset(4, 8, 42)
|
|
2558
|
+
sage: P.union_update(Q)
|
|
2559
|
+
sage: P
|
|
2560
|
+
poset(3, 4, 7, 8, 42)
|
|
2561
|
+
|
|
2562
|
+
.. SEEALSO::
|
|
2563
|
+
|
|
2564
|
+
:meth:`union`,
|
|
2565
|
+
:meth:`difference`, :meth:`difference_update`,
|
|
2566
|
+
:meth:`intersection`, :meth:`intersection_update`,
|
|
2567
|
+
:meth:`symmetric_difference`, :meth:`symmetric_difference_update`,
|
|
2568
|
+
:meth:`is_disjoint`,
|
|
2569
|
+
:meth:`is_subset`,
|
|
2570
|
+
:meth:`is_superset`.
|
|
2571
|
+
|
|
2572
|
+
TESTS::
|
|
2573
|
+
|
|
2574
|
+
sage: Q.update(P)
|
|
2575
|
+
sage: Q
|
|
2576
|
+
poset(3, 4, 7, 8, 42)
|
|
2577
|
+
"""
|
|
2578
|
+
for o in other:
|
|
2579
|
+
try:
|
|
2580
|
+
it = o.elements()
|
|
2581
|
+
except AttributeError:
|
|
2582
|
+
it = iter(o)
|
|
2583
|
+
for element in it:
|
|
2584
|
+
self.add(element)
|
|
2585
|
+
|
|
2586
|
+
update = union_update # as in a Python set
|
|
2587
|
+
r"""
|
|
2588
|
+
Alias of :meth:`union_update`.
|
|
2589
|
+
"""
|
|
2590
|
+
|
|
2591
|
+
def difference(self, *other):
|
|
2592
|
+
r"""
|
|
2593
|
+
Return a new poset where all elements of this poset, which are
|
|
2594
|
+
contained in one of the other given posets, are removed.
|
|
2595
|
+
|
|
2596
|
+
INPUT:
|
|
2597
|
+
|
|
2598
|
+
- ``other`` -- a poset or an iterable. In the latter case the
|
|
2599
|
+
iterated objects are seen as elements of a poset.
|
|
2600
|
+
It is possible to specify more than one ``other`` as
|
|
2601
|
+
variadic arguments (arbitrary argument lists).
|
|
2602
|
+
|
|
2603
|
+
.. NOTE::
|
|
2604
|
+
|
|
2605
|
+
The key of an element is used for comparison. Thus elements with
|
|
2606
|
+
the same key are considered as equal.
|
|
2607
|
+
|
|
2608
|
+
EXAMPLES::
|
|
2609
|
+
|
|
2610
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
2611
|
+
sage: P = MP([3, 42, 7]); P
|
|
2612
|
+
poset(3, 7, 42)
|
|
2613
|
+
sage: Q = MP([4, 8, 42]); Q
|
|
2614
|
+
poset(4, 8, 42)
|
|
2615
|
+
sage: P.difference(Q)
|
|
2616
|
+
poset(3, 7)
|
|
2617
|
+
|
|
2618
|
+
.. SEEALSO::
|
|
2619
|
+
|
|
2620
|
+
:meth:`union`, :meth:`union_update`,
|
|
2621
|
+
:meth:`difference_update`,
|
|
2622
|
+
:meth:`intersection`, :meth:`intersection_update`,
|
|
2623
|
+
:meth:`symmetric_difference`, :meth:`symmetric_difference_update`,
|
|
2624
|
+
:meth:`is_disjoint`,
|
|
2625
|
+
:meth:`is_subset`,
|
|
2626
|
+
:meth:`is_superset`.
|
|
2627
|
+
|
|
2628
|
+
TESTS::
|
|
2629
|
+
|
|
2630
|
+
sage: P.difference(Q, Q)
|
|
2631
|
+
poset(3, 7)
|
|
2632
|
+
sage: P.difference(P)
|
|
2633
|
+
poset()
|
|
2634
|
+
sage: P.difference(Q, P)
|
|
2635
|
+
poset()
|
|
2636
|
+
"""
|
|
2637
|
+
new = self.copy()
|
|
2638
|
+
new.difference_update(*other)
|
|
2639
|
+
return new
|
|
2640
|
+
|
|
2641
|
+
def difference_update(self, *other):
|
|
2642
|
+
r"""
|
|
2643
|
+
Remove all elements of another poset from this poset.
|
|
2644
|
+
|
|
2645
|
+
INPUT:
|
|
2646
|
+
|
|
2647
|
+
- ``other`` -- a poset or an iterable. In the latter case the
|
|
2648
|
+
iterated objects are seen as elements of a poset.
|
|
2649
|
+
It is possible to specify more than one ``other`` as
|
|
2650
|
+
variadic arguments (arbitrary argument lists).
|
|
2651
|
+
|
|
2652
|
+
OUTPUT: nothing
|
|
2653
|
+
|
|
2654
|
+
.. NOTE::
|
|
2655
|
+
|
|
2656
|
+
The key of an element is used for comparison. Thus elements with
|
|
2657
|
+
the same key are considered as equal.
|
|
2658
|
+
|
|
2659
|
+
EXAMPLES::
|
|
2660
|
+
|
|
2661
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
2662
|
+
sage: P = MP([3, 42, 7]); P
|
|
2663
|
+
poset(3, 7, 42)
|
|
2664
|
+
sage: Q = MP([4, 8, 42]); Q
|
|
2665
|
+
poset(4, 8, 42)
|
|
2666
|
+
sage: P.difference_update(Q)
|
|
2667
|
+
sage: P
|
|
2668
|
+
poset(3, 7)
|
|
2669
|
+
|
|
2670
|
+
.. SEEALSO::
|
|
2671
|
+
|
|
2672
|
+
:meth:`union`, :meth:`union_update`,
|
|
2673
|
+
:meth:`difference`,
|
|
2674
|
+
:meth:`intersection`, :meth:`intersection_update`,
|
|
2675
|
+
:meth:`symmetric_difference`, :meth:`symmetric_difference_update`,
|
|
2676
|
+
:meth:`is_disjoint`,
|
|
2677
|
+
:meth:`is_subset`,
|
|
2678
|
+
:meth:`is_superset`.
|
|
2679
|
+
"""
|
|
2680
|
+
for o in other:
|
|
2681
|
+
try:
|
|
2682
|
+
it = o.keys()
|
|
2683
|
+
except AttributeError:
|
|
2684
|
+
it = iter(o)
|
|
2685
|
+
for key in it:
|
|
2686
|
+
self.discard(key)
|
|
2687
|
+
|
|
2688
|
+
def intersection(self, *other):
|
|
2689
|
+
r"""
|
|
2690
|
+
Return the intersection of the given posets as a new poset.
|
|
2691
|
+
|
|
2692
|
+
INPUT:
|
|
2693
|
+
|
|
2694
|
+
- ``other`` -- a poset or an iterable. In the latter case the
|
|
2695
|
+
iterated objects are seen as elements of a poset.
|
|
2696
|
+
It is possible to specify more than one ``other`` as
|
|
2697
|
+
variadic arguments (arbitrary argument lists).
|
|
2698
|
+
|
|
2699
|
+
.. NOTE::
|
|
2700
|
+
|
|
2701
|
+
The key of an element is used for comparison. Thus elements with
|
|
2702
|
+
the same key are considered as equal.
|
|
2703
|
+
|
|
2704
|
+
EXAMPLES::
|
|
2705
|
+
|
|
2706
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
2707
|
+
sage: P = MP([3, 42, 7]); P
|
|
2708
|
+
poset(3, 7, 42)
|
|
2709
|
+
sage: Q = MP([4, 8, 42]); Q
|
|
2710
|
+
poset(4, 8, 42)
|
|
2711
|
+
sage: P.intersection(Q)
|
|
2712
|
+
poset(42)
|
|
2713
|
+
|
|
2714
|
+
.. SEEALSO::
|
|
2715
|
+
|
|
2716
|
+
:meth:`union`, :meth:`union_update`,
|
|
2717
|
+
:meth:`difference`, :meth:`difference_update`,
|
|
2718
|
+
:meth:`intersection_update`,
|
|
2719
|
+
:meth:`symmetric_difference`, :meth:`symmetric_difference_update`,
|
|
2720
|
+
:meth:`is_disjoint`,
|
|
2721
|
+
:meth:`is_subset`,
|
|
2722
|
+
:meth:`is_superset`.
|
|
2723
|
+
|
|
2724
|
+
TESTS::
|
|
2725
|
+
|
|
2726
|
+
sage: P.intersection(P, Q, Q, P)
|
|
2727
|
+
poset(42)
|
|
2728
|
+
"""
|
|
2729
|
+
new = self.copy()
|
|
2730
|
+
new.intersection_update(*other)
|
|
2731
|
+
return new
|
|
2732
|
+
|
|
2733
|
+
def intersection_update(self, *other):
|
|
2734
|
+
r"""
|
|
2735
|
+
Update this poset with the intersection of itself and another poset.
|
|
2736
|
+
|
|
2737
|
+
INPUT:
|
|
2738
|
+
|
|
2739
|
+
- ``other`` -- a poset or an iterable. In the latter case the
|
|
2740
|
+
iterated objects are seen as elements of a poset.
|
|
2741
|
+
It is possible to specify more than one ``other`` as
|
|
2742
|
+
variadic arguments (arbitrary argument lists).
|
|
2743
|
+
|
|
2744
|
+
OUTPUT: nothing
|
|
2745
|
+
|
|
2746
|
+
.. NOTE::
|
|
2747
|
+
|
|
2748
|
+
The key of an element is used for comparison. Thus elements with
|
|
2749
|
+
the same key are considered as equal;
|
|
2750
|
+
``A.intersection_update(B)`` and ``B.intersection_update(A)`` might
|
|
2751
|
+
result in different posets.
|
|
2752
|
+
|
|
2753
|
+
EXAMPLES::
|
|
2754
|
+
|
|
2755
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
2756
|
+
sage: P = MP([3, 42, 7]); P
|
|
2757
|
+
poset(3, 7, 42)
|
|
2758
|
+
sage: Q = MP([4, 8, 42]); Q
|
|
2759
|
+
poset(4, 8, 42)
|
|
2760
|
+
sage: P.intersection_update(Q)
|
|
2761
|
+
sage: P
|
|
2762
|
+
poset(42)
|
|
2763
|
+
|
|
2764
|
+
.. SEEALSO::
|
|
2765
|
+
|
|
2766
|
+
:meth:`union`, :meth:`union_update`,
|
|
2767
|
+
:meth:`difference`, :meth:`difference_update`,
|
|
2768
|
+
:meth:`intersection`,
|
|
2769
|
+
:meth:`symmetric_difference`, :meth:`symmetric_difference_update`,
|
|
2770
|
+
:meth:`is_disjoint`,
|
|
2771
|
+
:meth:`is_subset`,
|
|
2772
|
+
:meth:`is_superset`.
|
|
2773
|
+
"""
|
|
2774
|
+
keys = tuple(self.keys())
|
|
2775
|
+
for key in keys:
|
|
2776
|
+
if any(key not in o for o in other):
|
|
2777
|
+
self.discard(key)
|
|
2778
|
+
|
|
2779
|
+
def symmetric_difference(self, other):
|
|
2780
|
+
r"""
|
|
2781
|
+
Return the symmetric difference of two posets as a new poset.
|
|
2782
|
+
|
|
2783
|
+
INPUT:
|
|
2784
|
+
|
|
2785
|
+
- ``other`` -- a poset
|
|
2786
|
+
|
|
2787
|
+
.. NOTE::
|
|
2788
|
+
|
|
2789
|
+
The key of an element is used for comparison. Thus elements with
|
|
2790
|
+
the same key are considered as equal.
|
|
2791
|
+
|
|
2792
|
+
EXAMPLES::
|
|
2793
|
+
|
|
2794
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
2795
|
+
sage: P = MP([3, 42, 7]); P
|
|
2796
|
+
poset(3, 7, 42)
|
|
2797
|
+
sage: Q = MP([4, 8, 42]); Q
|
|
2798
|
+
poset(4, 8, 42)
|
|
2799
|
+
sage: P.symmetric_difference(Q)
|
|
2800
|
+
poset(3, 4, 7, 8)
|
|
2801
|
+
|
|
2802
|
+
.. SEEALSO::
|
|
2803
|
+
|
|
2804
|
+
:meth:`union`, :meth:`union_update`,
|
|
2805
|
+
:meth:`difference`, :meth:`difference_update`,
|
|
2806
|
+
:meth:`intersection`, :meth:`intersection_update`,
|
|
2807
|
+
:meth:`symmetric_difference_update`,
|
|
2808
|
+
:meth:`is_disjoint`,
|
|
2809
|
+
:meth:`is_subset`,
|
|
2810
|
+
:meth:`is_superset`.
|
|
2811
|
+
"""
|
|
2812
|
+
new = self.copy()
|
|
2813
|
+
new.symmetric_difference_update(other)
|
|
2814
|
+
return new
|
|
2815
|
+
|
|
2816
|
+
def symmetric_difference_update(self, other):
|
|
2817
|
+
r"""
|
|
2818
|
+
Update this poset with the symmetric difference of itself and
|
|
2819
|
+
another poset.
|
|
2820
|
+
|
|
2821
|
+
INPUT:
|
|
2822
|
+
|
|
2823
|
+
- ``other`` -- a poset
|
|
2824
|
+
|
|
2825
|
+
OUTPUT: nothing
|
|
2826
|
+
|
|
2827
|
+
.. NOTE::
|
|
2828
|
+
|
|
2829
|
+
The key of an element is used for comparison. Thus elements with
|
|
2830
|
+
the same key are considered as equal;
|
|
2831
|
+
``A.symmetric_difference_update(B)`` and
|
|
2832
|
+
``B.symmetric_difference_update(A)`` might
|
|
2833
|
+
result in different posets.
|
|
2834
|
+
|
|
2835
|
+
EXAMPLES::
|
|
2836
|
+
|
|
2837
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
2838
|
+
sage: P = MP([3, 42, 7]); P
|
|
2839
|
+
poset(3, 7, 42)
|
|
2840
|
+
sage: Q = MP([4, 8, 42]); Q
|
|
2841
|
+
poset(4, 8, 42)
|
|
2842
|
+
sage: P.symmetric_difference_update(Q)
|
|
2843
|
+
sage: P
|
|
2844
|
+
poset(3, 4, 7, 8)
|
|
2845
|
+
|
|
2846
|
+
.. SEEALSO::
|
|
2847
|
+
|
|
2848
|
+
:meth:`union`, :meth:`union_update`,
|
|
2849
|
+
:meth:`difference`, :meth:`difference_update`,
|
|
2850
|
+
:meth:`intersection`, :meth:`intersection_update`,
|
|
2851
|
+
:meth:`symmetric_difference`,
|
|
2852
|
+
:meth:`is_disjoint`,
|
|
2853
|
+
:meth:`is_subset`,
|
|
2854
|
+
:meth:`is_superset`.
|
|
2855
|
+
"""
|
|
2856
|
+
T = other.difference(self)
|
|
2857
|
+
self.difference_update(other)
|
|
2858
|
+
self.union_update(T)
|
|
2859
|
+
|
|
2860
|
+
def is_disjoint(self, other):
|
|
2861
|
+
r"""
|
|
2862
|
+
Return whether another poset is disjoint to this poset.
|
|
2863
|
+
|
|
2864
|
+
INPUT:
|
|
2865
|
+
|
|
2866
|
+
- ``other`` -- a poset or an iterable; in the latter case the
|
|
2867
|
+
iterated objects are seen as elements of a poset
|
|
2868
|
+
|
|
2869
|
+
OUTPUT: nothing
|
|
2870
|
+
|
|
2871
|
+
.. NOTE::
|
|
2872
|
+
|
|
2873
|
+
If this poset uses a ``key``-function, then all
|
|
2874
|
+
comparisons are performed on the keys of the elements (and
|
|
2875
|
+
not on the elements themselves).
|
|
2876
|
+
|
|
2877
|
+
EXAMPLES::
|
|
2878
|
+
|
|
2879
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
2880
|
+
sage: P = MP([3, 42, 7]); P
|
|
2881
|
+
poset(3, 7, 42)
|
|
2882
|
+
sage: Q = MP([4, 8, 42]); Q
|
|
2883
|
+
poset(4, 8, 42)
|
|
2884
|
+
sage: P.is_disjoint(Q)
|
|
2885
|
+
False
|
|
2886
|
+
sage: P.is_disjoint(Q.difference(P))
|
|
2887
|
+
True
|
|
2888
|
+
|
|
2889
|
+
.. SEEALSO::
|
|
2890
|
+
|
|
2891
|
+
:meth:`is_subset`,
|
|
2892
|
+
:meth:`is_superset`,
|
|
2893
|
+
:meth:`union`, :meth:`union_update`,
|
|
2894
|
+
:meth:`difference`, :meth:`difference_update`,
|
|
2895
|
+
:meth:`intersection`, :meth:`intersection_update`,
|
|
2896
|
+
:meth:`symmetric_difference`, :meth:`symmetric_difference_update`.
|
|
2897
|
+
"""
|
|
2898
|
+
return all(key not in other for key in self.keys())
|
|
2899
|
+
|
|
2900
|
+
isdisjoint = is_disjoint # as in a Python set
|
|
2901
|
+
r"""
|
|
2902
|
+
Alias of :meth:`is_disjoint`.
|
|
2903
|
+
"""
|
|
2904
|
+
|
|
2905
|
+
def is_subset(self, other):
|
|
2906
|
+
r"""
|
|
2907
|
+
Return whether another poset contains this poset, i.e., whether this poset
|
|
2908
|
+
is a subset of the other poset.
|
|
2909
|
+
|
|
2910
|
+
INPUT:
|
|
2911
|
+
|
|
2912
|
+
- ``other`` -- a poset or an iterable; in the latter case the
|
|
2913
|
+
iterated objects are seen as elements of a poset
|
|
2914
|
+
|
|
2915
|
+
OUTPUT: nothing
|
|
2916
|
+
|
|
2917
|
+
.. NOTE::
|
|
2918
|
+
|
|
2919
|
+
If this poset uses a ``key``-function, then all
|
|
2920
|
+
comparisons are performed on the keys of the elements (and
|
|
2921
|
+
not on the elements themselves).
|
|
2922
|
+
|
|
2923
|
+
EXAMPLES::
|
|
2924
|
+
|
|
2925
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
2926
|
+
sage: P = MP([3, 42, 7]); P
|
|
2927
|
+
poset(3, 7, 42)
|
|
2928
|
+
sage: Q = MP([4, 8, 42]); Q
|
|
2929
|
+
poset(4, 8, 42)
|
|
2930
|
+
sage: P.is_subset(Q)
|
|
2931
|
+
False
|
|
2932
|
+
sage: Q.is_subset(P)
|
|
2933
|
+
False
|
|
2934
|
+
sage: P.is_subset(P)
|
|
2935
|
+
True
|
|
2936
|
+
sage: P.is_subset(P.union(Q))
|
|
2937
|
+
True
|
|
2938
|
+
|
|
2939
|
+
.. SEEALSO::
|
|
2940
|
+
|
|
2941
|
+
:meth:`is_disjoint`,
|
|
2942
|
+
:meth:`is_superset`,
|
|
2943
|
+
:meth:`union`, :meth:`union_update`,
|
|
2944
|
+
:meth:`difference`, :meth:`difference_update`,
|
|
2945
|
+
:meth:`intersection`, :meth:`intersection_update`,
|
|
2946
|
+
:meth:`symmetric_difference`, :meth:`symmetric_difference_update`.
|
|
2947
|
+
"""
|
|
2948
|
+
return all(key in other for key in self.keys())
|
|
2949
|
+
|
|
2950
|
+
issubset = is_subset # as in a Python set
|
|
2951
|
+
r"""
|
|
2952
|
+
Alias of :meth:`is_subset`.
|
|
2953
|
+
"""
|
|
2954
|
+
|
|
2955
|
+
def is_superset(self, other):
|
|
2956
|
+
r"""
|
|
2957
|
+
Return whether this poset contains another poset, i.e., whether this poset
|
|
2958
|
+
is a superset of the other poset.
|
|
2959
|
+
|
|
2960
|
+
INPUT:
|
|
2961
|
+
|
|
2962
|
+
- ``other`` -- a poset or an iterable; in the latter case the
|
|
2963
|
+
iterated objects are seen as elements of a poset
|
|
2964
|
+
|
|
2965
|
+
OUTPUT: nothing
|
|
2966
|
+
|
|
2967
|
+
.. NOTE::
|
|
2968
|
+
|
|
2969
|
+
If this poset uses a ``key``-function, then all
|
|
2970
|
+
comparisons are performed on the keys of the elements (and
|
|
2971
|
+
not on the elements themselves).
|
|
2972
|
+
|
|
2973
|
+
EXAMPLES::
|
|
2974
|
+
|
|
2975
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
2976
|
+
sage: P = MP([3, 42, 7]); P
|
|
2977
|
+
poset(3, 7, 42)
|
|
2978
|
+
sage: Q = MP([4, 8, 42]); Q
|
|
2979
|
+
poset(4, 8, 42)
|
|
2980
|
+
sage: P.is_superset(Q)
|
|
2981
|
+
False
|
|
2982
|
+
sage: Q.is_superset(P)
|
|
2983
|
+
False
|
|
2984
|
+
sage: P.is_superset(P)
|
|
2985
|
+
True
|
|
2986
|
+
sage: P.union(Q).is_superset(P)
|
|
2987
|
+
True
|
|
2988
|
+
|
|
2989
|
+
.. SEEALSO::
|
|
2990
|
+
|
|
2991
|
+
:meth:`is_disjoint`,
|
|
2992
|
+
:meth:`is_subset`,
|
|
2993
|
+
:meth:`union`, :meth:`union_update`,
|
|
2994
|
+
:meth:`difference`, :meth:`difference_update`,
|
|
2995
|
+
:meth:`intersection`, :meth:`intersection_update`,
|
|
2996
|
+
:meth:`symmetric_difference`, :meth:`symmetric_difference_update`.
|
|
2997
|
+
"""
|
|
2998
|
+
try:
|
|
2999
|
+
it = other.keys()
|
|
3000
|
+
except AttributeError:
|
|
3001
|
+
it = iter(other)
|
|
3002
|
+
return all(key in self for key in it)
|
|
3003
|
+
|
|
3004
|
+
issuperset = is_superset # as in a Python set
|
|
3005
|
+
r"""
|
|
3006
|
+
Alias of :meth:`is_superset`.
|
|
3007
|
+
"""
|
|
3008
|
+
|
|
3009
|
+
def merge(self, key=None, reverse=False):
|
|
3010
|
+
r"""
|
|
3011
|
+
Merge the given element with its successors/predecessors.
|
|
3012
|
+
|
|
3013
|
+
INPUT:
|
|
3014
|
+
|
|
3015
|
+
- ``key`` -- the key specifying an element or ``None``
|
|
3016
|
+
(default), in which case this method is called on each
|
|
3017
|
+
element in this poset
|
|
3018
|
+
|
|
3019
|
+
- ``reverse`` -- boolean (default: ``False``); specifies which
|
|
3020
|
+
direction to go first:
|
|
3021
|
+
``False`` searches towards ``'oo'`` and
|
|
3022
|
+
``True`` searches towards ``'null'``.
|
|
3023
|
+
When ``key=None``, then this also
|
|
3024
|
+
specifies which elements are merged first.
|
|
3025
|
+
|
|
3026
|
+
OUTPUT: nothing
|
|
3027
|
+
|
|
3028
|
+
This method tests all (not necessarily direct) successors and
|
|
3029
|
+
predecessors of the given element whether they can be merged with
|
|
3030
|
+
the element itself. This is done by the ``can_merge``-function
|
|
3031
|
+
of :class:`MutablePoset`. If this merge is possible, then it
|
|
3032
|
+
is performed by calling :class:`MutablePoset`'s
|
|
3033
|
+
``merge``-function and the corresponding successor/predecessor
|
|
3034
|
+
is removed from the poset.
|
|
3035
|
+
|
|
3036
|
+
.. NOTE::
|
|
3037
|
+
|
|
3038
|
+
``can_merge`` is applied in the sense of the condition of
|
|
3039
|
+
depth first iteration, i.e., once ``can_merge`` fails,
|
|
3040
|
+
the successors/predecessors are no longer tested.
|
|
3041
|
+
|
|
3042
|
+
.. NOTE::
|
|
3043
|
+
|
|
3044
|
+
The motivation for such a merge behavior comes from
|
|
3045
|
+
asymptotic expansions: `O(n^3)` merges with, for
|
|
3046
|
+
example, `3n^2` or `O(n)` to `O(n^3)` (as `n` tends to
|
|
3047
|
+
`\infty`; see :wikipedia:`Big_O_notation`).
|
|
3048
|
+
|
|
3049
|
+
EXAMPLES::
|
|
3050
|
+
|
|
3051
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
3052
|
+
sage: class T(tuple):
|
|
3053
|
+
....: def __le__(left, right):
|
|
3054
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
3055
|
+
sage: key = lambda t: T(t[0:2])
|
|
3056
|
+
sage: def add(left, right):
|
|
3057
|
+
....: return (left[0], left[1],
|
|
3058
|
+
....: ''.join(sorted(left[2] + right[2])))
|
|
3059
|
+
sage: def can_add(left, right):
|
|
3060
|
+
....: return key(left) >= key(right)
|
|
3061
|
+
sage: P = MP([(1, 1, 'a'), (1, 3, 'b'), (2, 1, 'c'),
|
|
3062
|
+
....: (4, 4, 'd'), (1, 2, 'e'), (2, 2, 'f')],
|
|
3063
|
+
....: key=key, merge=add, can_merge=can_add)
|
|
3064
|
+
sage: Q = copy(P)
|
|
3065
|
+
sage: Q.merge(T((1, 3)))
|
|
3066
|
+
sage: print(Q.repr_full(reverse=True))
|
|
3067
|
+
poset((4, 4, 'd'), (1, 3, 'abe'), (2, 2, 'f'), (2, 1, 'c'))
|
|
3068
|
+
+-- oo
|
|
3069
|
+
| +-- no successors
|
|
3070
|
+
| +-- predecessors: (4, 4, 'd')
|
|
3071
|
+
+-- (4, 4, 'd')
|
|
3072
|
+
| +-- successors: oo
|
|
3073
|
+
| +-- predecessors: (1, 3, 'abe'), (2, 2, 'f')
|
|
3074
|
+
+-- (1, 3, 'abe')
|
|
3075
|
+
| +-- successors: (4, 4, 'd')
|
|
3076
|
+
| +-- predecessors: null
|
|
3077
|
+
+-- (2, 2, 'f')
|
|
3078
|
+
| +-- successors: (4, 4, 'd')
|
|
3079
|
+
| +-- predecessors: (2, 1, 'c')
|
|
3080
|
+
+-- (2, 1, 'c')
|
|
3081
|
+
| +-- successors: (2, 2, 'f')
|
|
3082
|
+
| +-- predecessors: null
|
|
3083
|
+
+-- null
|
|
3084
|
+
| +-- successors: (1, 3, 'abe'), (2, 1, 'c')
|
|
3085
|
+
| +-- no predecessors
|
|
3086
|
+
sage: for k in sorted(P.keys()):
|
|
3087
|
+
....: Q = copy(P)
|
|
3088
|
+
....: Q.merge(k)
|
|
3089
|
+
....: print('merging %s: %s' % (k, Q))
|
|
3090
|
+
merging (1, 1): poset((1, 1, 'a'), (1, 2, 'e'), (1, 3, 'b'),
|
|
3091
|
+
(2, 1, 'c'), (2, 2, 'f'), (4, 4, 'd'))
|
|
3092
|
+
merging (1, 2): poset((1, 2, 'ae'), (1, 3, 'b'), (2, 1, 'c'),
|
|
3093
|
+
(2, 2, 'f'), (4, 4, 'd'))
|
|
3094
|
+
merging (1, 3): poset((1, 3, 'abe'), (2, 1, 'c'), (2, 2, 'f'),
|
|
3095
|
+
(4, 4, 'd'))
|
|
3096
|
+
merging (2, 1): poset((1, 2, 'e'), (1, 3, 'b'), (2, 1, 'ac'),
|
|
3097
|
+
(2, 2, 'f'), (4, 4, 'd'))
|
|
3098
|
+
merging (2, 2): poset((1, 3, 'b'), (2, 2, 'acef'), (4, 4, 'd'))
|
|
3099
|
+
merging (4, 4): poset((4, 4, 'abcdef'))
|
|
3100
|
+
|
|
3101
|
+
sage: Q = copy(P)
|
|
3102
|
+
sage: Q.merge(); Q
|
|
3103
|
+
poset((4, 4, 'abcdef'))
|
|
3104
|
+
|
|
3105
|
+
.. SEEALSO::
|
|
3106
|
+
|
|
3107
|
+
:meth:`MutablePosetShell.merge`
|
|
3108
|
+
|
|
3109
|
+
TESTS::
|
|
3110
|
+
|
|
3111
|
+
sage: copy(P).merge(reverse=False) == copy(P).merge(reverse=True)
|
|
3112
|
+
True
|
|
3113
|
+
|
|
3114
|
+
::
|
|
3115
|
+
|
|
3116
|
+
sage: P = MP(srange(4),
|
|
3117
|
+
....: merge=lambda l, r: l, can_merge=lambda l, r: l >= r); P
|
|
3118
|
+
poset(0, 1, 2, 3)
|
|
3119
|
+
sage: Q = P.copy()
|
|
3120
|
+
sage: Q.merge(reverse=True); Q
|
|
3121
|
+
poset(3)
|
|
3122
|
+
sage: R = P.mapped(lambda x: x+1)
|
|
3123
|
+
sage: R.merge(reverse=True); R
|
|
3124
|
+
poset(4)
|
|
3125
|
+
|
|
3126
|
+
::
|
|
3127
|
+
|
|
3128
|
+
sage: P = MP(srange(4),
|
|
3129
|
+
....: merge=lambda l, r: r, can_merge=lambda l, r: l < r)
|
|
3130
|
+
sage: P.merge()
|
|
3131
|
+
Traceback (most recent call last):
|
|
3132
|
+
...
|
|
3133
|
+
RuntimeError: Stopping merge before started;
|
|
3134
|
+
the can_merge-function is not reflexive.
|
|
3135
|
+
"""
|
|
3136
|
+
if key is None:
|
|
3137
|
+
for shell in tuple(self.shells_topological(reverse=reverse)):
|
|
3138
|
+
if shell.key in self._shells_:
|
|
3139
|
+
self.merge(key=shell.key)
|
|
3140
|
+
return
|
|
3141
|
+
|
|
3142
|
+
shell = self.shell(key)
|
|
3143
|
+
|
|
3144
|
+
def can_merge(other):
|
|
3145
|
+
return self._can_merge_(shell.element, other.element)
|
|
3146
|
+
for rev in (reverse, not reverse):
|
|
3147
|
+
to_merge = shell.iter_depth_first(
|
|
3148
|
+
reverse=rev, condition=can_merge)
|
|
3149
|
+
try:
|
|
3150
|
+
next(to_merge)
|
|
3151
|
+
except StopIteration:
|
|
3152
|
+
raise RuntimeError('Stopping merge before started; the '
|
|
3153
|
+
'can_merge-function is not reflexive.')
|
|
3154
|
+
for m in tuple(to_merge):
|
|
3155
|
+
if m.is_special():
|
|
3156
|
+
continue
|
|
3157
|
+
shell.merge(m.element, check=False, delete=True)
|
|
3158
|
+
|
|
3159
|
+
def maximal_elements(self):
|
|
3160
|
+
r"""
|
|
3161
|
+
Return an iterator over the maximal elements of this poset.
|
|
3162
|
+
|
|
3163
|
+
OUTPUT: an iterator
|
|
3164
|
+
|
|
3165
|
+
EXAMPLES::
|
|
3166
|
+
|
|
3167
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
3168
|
+
sage: class T(tuple):
|
|
3169
|
+
....: def __le__(left, right):
|
|
3170
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
3171
|
+
sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
|
|
3172
|
+
....: T((1, 2)), T((2, 2))])
|
|
3173
|
+
sage: sorted(P.maximal_elements())
|
|
3174
|
+
[(1, 3), (2, 2)]
|
|
3175
|
+
|
|
3176
|
+
.. SEEALSO::
|
|
3177
|
+
|
|
3178
|
+
:meth:`minimal_elements`
|
|
3179
|
+
"""
|
|
3180
|
+
return iter(shell.element
|
|
3181
|
+
for shell in self.oo.predecessors()
|
|
3182
|
+
if not shell.is_special())
|
|
3183
|
+
|
|
3184
|
+
def minimal_elements(self):
|
|
3185
|
+
r"""
|
|
3186
|
+
Return an iterator over the minimal elements of this poset.
|
|
3187
|
+
|
|
3188
|
+
OUTPUT: an iterator
|
|
3189
|
+
|
|
3190
|
+
EXAMPLES::
|
|
3191
|
+
|
|
3192
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
3193
|
+
sage: class T(tuple):
|
|
3194
|
+
....: def __le__(left, right):
|
|
3195
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
3196
|
+
sage: P = MP([T((1, 3)), T((2, 1)),
|
|
3197
|
+
....: T((4, 4)), T((1, 2)), T((2, 2))])
|
|
3198
|
+
sage: sorted(P.minimal_elements())
|
|
3199
|
+
[(1, 2), (2, 1)]
|
|
3200
|
+
|
|
3201
|
+
.. SEEALSO::
|
|
3202
|
+
|
|
3203
|
+
:meth:`maximal_elements`
|
|
3204
|
+
"""
|
|
3205
|
+
return iter(shell.element
|
|
3206
|
+
for shell in self.null.successors()
|
|
3207
|
+
if not shell.is_special())
|
|
3208
|
+
|
|
3209
|
+
def map(self, function, topological=False, reverse=False):
|
|
3210
|
+
r"""
|
|
3211
|
+
Apply the given ``function`` to each element of this poset.
|
|
3212
|
+
|
|
3213
|
+
INPUT:
|
|
3214
|
+
|
|
3215
|
+
- ``function`` -- a function mapping an existing element to
|
|
3216
|
+
a new element
|
|
3217
|
+
|
|
3218
|
+
- ``topological`` -- boolean (default: ``False``); if set, then the
|
|
3219
|
+
mapping is done in topological order, otherwise unordered
|
|
3220
|
+
|
|
3221
|
+
- ``reverse`` -- is passed on to topological ordering
|
|
3222
|
+
|
|
3223
|
+
OUTPUT: nothing
|
|
3224
|
+
|
|
3225
|
+
.. NOTE::
|
|
3226
|
+
|
|
3227
|
+
Since this method works inplace, it is not allowed that
|
|
3228
|
+
``function`` alters the key of an element.
|
|
3229
|
+
|
|
3230
|
+
.. NOTE::
|
|
3231
|
+
|
|
3232
|
+
If ``function`` returns ``None``, then the element is
|
|
3233
|
+
removed.
|
|
3234
|
+
|
|
3235
|
+
EXAMPLES::
|
|
3236
|
+
|
|
3237
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
3238
|
+
sage: class T(tuple):
|
|
3239
|
+
....: def __le__(left, right):
|
|
3240
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
3241
|
+
sage: P = MP([T((1, 3)), T((2, 1)),
|
|
3242
|
+
....: T((4, 4)), T((1, 2)), T((2, 2))],
|
|
3243
|
+
....: key=lambda e: e[:2])
|
|
3244
|
+
sage: P.map(lambda e: e + (sum(e),))
|
|
3245
|
+
sage: P
|
|
3246
|
+
poset((1, 2, 3), (1, 3, 4), (2, 1, 3), (2, 2, 4), (4, 4, 8))
|
|
3247
|
+
|
|
3248
|
+
TESTS::
|
|
3249
|
+
|
|
3250
|
+
sage: P.map(lambda e: e if e[2] != 4 else None); P
|
|
3251
|
+
poset((1, 2, 3), (2, 1, 3), (4, 4, 8))
|
|
3252
|
+
|
|
3253
|
+
.. SEEALSO::
|
|
3254
|
+
|
|
3255
|
+
:meth:`copy`,
|
|
3256
|
+
:meth:`mapped`.
|
|
3257
|
+
"""
|
|
3258
|
+
shells = self.shells_topological(reverse=reverse) \
|
|
3259
|
+
if topological else self.shells()
|
|
3260
|
+
remove = []
|
|
3261
|
+
for shell in shells:
|
|
3262
|
+
image = function(shell._element_)
|
|
3263
|
+
if image is None:
|
|
3264
|
+
remove.append(shell.key)
|
|
3265
|
+
else:
|
|
3266
|
+
shell._element_ = image
|
|
3267
|
+
for key in remove:
|
|
3268
|
+
self.remove(key)
|
|
3269
|
+
|
|
3270
|
+
def mapped(self, function):
|
|
3271
|
+
r"""
|
|
3272
|
+
Return a poset where on each element the given ``function``
|
|
3273
|
+
was applied.
|
|
3274
|
+
|
|
3275
|
+
INPUT:
|
|
3276
|
+
|
|
3277
|
+
- ``function`` -- a function mapping an existing element to
|
|
3278
|
+
a new element
|
|
3279
|
+
|
|
3280
|
+
- ``topological`` -- boolean (default: ``False``); if set, then the
|
|
3281
|
+
mapping is done in topological order, otherwise unordered
|
|
3282
|
+
|
|
3283
|
+
- ``reverse`` -- is passed on to topological ordering
|
|
3284
|
+
|
|
3285
|
+
OUTPUT: a :class:`MutablePoset`
|
|
3286
|
+
|
|
3287
|
+
.. NOTE::
|
|
3288
|
+
|
|
3289
|
+
``function`` is not allowed to change the order of the keys,
|
|
3290
|
+
but changing the keys themselves is allowed (in contrast
|
|
3291
|
+
to :meth:`map`).
|
|
3292
|
+
|
|
3293
|
+
EXAMPLES::
|
|
3294
|
+
|
|
3295
|
+
sage: from sage.data_structures.mutable_poset import MutablePoset as MP
|
|
3296
|
+
sage: class T(tuple):
|
|
3297
|
+
....: def __le__(left, right):
|
|
3298
|
+
....: return all(l <= r for l, r in zip(left, right))
|
|
3299
|
+
sage: P = MP([T((1, 3)), T((2, 1)),
|
|
3300
|
+
....: T((4, 4)), T((1, 2)), T((2, 2))])
|
|
3301
|
+
sage: P.mapped(lambda e: str(e))
|
|
3302
|
+
poset('(1, 2)', '(1, 3)', '(2, 1)', '(2, 2)', '(4, 4)')
|
|
3303
|
+
|
|
3304
|
+
.. SEEALSO::
|
|
3305
|
+
|
|
3306
|
+
:meth:`copy`,
|
|
3307
|
+
:meth:`map`.
|
|
3308
|
+
"""
|
|
3309
|
+
return self.copy(mapping=function)
|
|
3310
|
+
|
|
3311
|
+
|
|
3312
|
+
# *****************************************************************************
|