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,1994 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
# sage.doctest: needs sage.combinat sage.graphs
|
|
3
|
+
r"""
|
|
4
|
+
Finite posets
|
|
5
|
+
|
|
6
|
+
Here is some terminology used in this file:
|
|
7
|
+
|
|
8
|
+
- An *order filter* (or *upper set*) of a poset `P` is a subset `S` of `P`
|
|
9
|
+
such that if `x \leq y` and `x\in S` then `y\in S`.
|
|
10
|
+
|
|
11
|
+
- An *order ideal* (or *lower set*) of a poset `P` is a subset `S` of `P`
|
|
12
|
+
such that if `x \leq y` and `y\in S` then `x\in S`.
|
|
13
|
+
"""
|
|
14
|
+
# ****************************************************************************
|
|
15
|
+
# Copyright (C) 2011 Nicolas M. Thiery <nthiery at users.sf.net>
|
|
16
|
+
#
|
|
17
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
18
|
+
# https://www.gnu.org/licenses/
|
|
19
|
+
# *****************************************************************************
|
|
20
|
+
|
|
21
|
+
from sage.misc.abstract_method import abstract_method
|
|
22
|
+
from sage.categories.category_with_axiom import CategoryWithAxiom
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class FinitePosets(CategoryWithAxiom):
|
|
26
|
+
r"""
|
|
27
|
+
The category of finite posets i.e. finite sets with a partial
|
|
28
|
+
order structure.
|
|
29
|
+
|
|
30
|
+
EXAMPLES::
|
|
31
|
+
|
|
32
|
+
sage: FinitePosets()
|
|
33
|
+
Category of finite posets
|
|
34
|
+
sage: FinitePosets().super_categories()
|
|
35
|
+
[Category of posets, Category of finite sets]
|
|
36
|
+
sage: FinitePosets().example()
|
|
37
|
+
NotImplemented
|
|
38
|
+
|
|
39
|
+
.. SEEALSO:: :class:`~sage.categories.posets.Posets`, :func:`Poset`
|
|
40
|
+
|
|
41
|
+
TESTS::
|
|
42
|
+
|
|
43
|
+
sage: C = FinitePosets()
|
|
44
|
+
sage: C is Posets().Finite()
|
|
45
|
+
True
|
|
46
|
+
sage: TestSuite(C).run()
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
class ParentMethods:
|
|
50
|
+
|
|
51
|
+
##########################################################################
|
|
52
|
+
# Properties of this poset
|
|
53
|
+
|
|
54
|
+
def is_lattice(self):
|
|
55
|
+
r"""
|
|
56
|
+
Return whether the poset is a lattice.
|
|
57
|
+
|
|
58
|
+
A poset is a lattice if all pairs of elements have
|
|
59
|
+
both a least upper bound ("join") and a greatest lower bound
|
|
60
|
+
("meet") in the poset.
|
|
61
|
+
|
|
62
|
+
EXAMPLES::
|
|
63
|
+
|
|
64
|
+
sage: P = Poset([[1, 3, 2], [4], [4, 5, 6], [6], [7], [7], [7], []])
|
|
65
|
+
sage: P.is_lattice() # needs sage.modules
|
|
66
|
+
True
|
|
67
|
+
|
|
68
|
+
sage: P = Poset([[1, 2], [3], [3], []])
|
|
69
|
+
sage: P.is_lattice() # needs sage.modules
|
|
70
|
+
True
|
|
71
|
+
|
|
72
|
+
sage: P = Poset({0: [2, 3], 1: [2, 3]})
|
|
73
|
+
sage: P.is_lattice()
|
|
74
|
+
False
|
|
75
|
+
|
|
76
|
+
sage: P = Poset({1: [2, 3, 4], 2: [5, 6], 3: [5, 7], 4: [6, 7], 5: [8, 9],
|
|
77
|
+
....: 6: [8, 10], 7: [9, 10], 8: [11], 9: [11], 10: [11]})
|
|
78
|
+
sage: P.is_lattice() # needs sage.modules
|
|
79
|
+
False
|
|
80
|
+
|
|
81
|
+
TESTS::
|
|
82
|
+
|
|
83
|
+
sage: P = Poset()
|
|
84
|
+
sage: P.is_lattice()
|
|
85
|
+
True
|
|
86
|
+
|
|
87
|
+
.. SEEALSO::
|
|
88
|
+
|
|
89
|
+
- Weaker properties: :meth:`~sage.combinat.posets.posets.FinitePoset.is_join_semilattice`,
|
|
90
|
+
:meth:`~sage.combinat.posets.posets.FinitePoset.is_meet_semilattice`
|
|
91
|
+
"""
|
|
92
|
+
return (self.cardinality() == 0 or
|
|
93
|
+
(self.has_bottom() and self.is_join_semilattice()))
|
|
94
|
+
|
|
95
|
+
def is_self_dual(self):
|
|
96
|
+
r"""
|
|
97
|
+
Return whether the poset is *self-dual*.
|
|
98
|
+
|
|
99
|
+
A poset is self-dual if it is isomorphic to its dual poset.
|
|
100
|
+
|
|
101
|
+
EXAMPLES::
|
|
102
|
+
|
|
103
|
+
sage: P = Poset({1: [3, 4], 2: [3, 4]})
|
|
104
|
+
sage: P.is_self_dual()
|
|
105
|
+
True
|
|
106
|
+
|
|
107
|
+
sage: P = Poset({1: [2, 3]})
|
|
108
|
+
sage: P.is_self_dual()
|
|
109
|
+
False
|
|
110
|
+
|
|
111
|
+
TESTS::
|
|
112
|
+
|
|
113
|
+
sage: P = Poset()
|
|
114
|
+
sage: P.is_self_dual()
|
|
115
|
+
True
|
|
116
|
+
|
|
117
|
+
.. SEEALSO::
|
|
118
|
+
|
|
119
|
+
- Stronger properties: :meth:`~sage.combinat.posets.lattices.FiniteLatticePoset.is_orthocomplemented` (for lattices)
|
|
120
|
+
- Other: :meth:`~sage.combinat.posets.posets.FinitePoset.dual`
|
|
121
|
+
"""
|
|
122
|
+
# Two quick checks before full isomorphic test.
|
|
123
|
+
if sorted(self._hasse_diagram.in_degree()) != sorted(self._hasse_diagram.out_degree()):
|
|
124
|
+
return False
|
|
125
|
+
levels_orig = [len(x) for x in self._hasse_diagram.level_sets()]
|
|
126
|
+
dual_poset_hasse = self._hasse_diagram.reverse()
|
|
127
|
+
levels_dual = [len(x) for x in dual_poset_hasse.level_sets()]
|
|
128
|
+
if levels_orig != levels_dual:
|
|
129
|
+
return False
|
|
130
|
+
return self._hasse_diagram.is_isomorphic(dual_poset_hasse)
|
|
131
|
+
|
|
132
|
+
##########################################################################
|
|
133
|
+
# Properties of morphisms
|
|
134
|
+
|
|
135
|
+
def is_poset_isomorphism(self, f, codomain):
|
|
136
|
+
r"""
|
|
137
|
+
Return whether `f` is an isomorphism of posets from
|
|
138
|
+
``self`` to ``codomain``.
|
|
139
|
+
|
|
140
|
+
INPUT:
|
|
141
|
+
|
|
142
|
+
- ``f`` -- a function from ``self`` to ``codomain``
|
|
143
|
+
- ``codomain`` -- a poset
|
|
144
|
+
|
|
145
|
+
EXAMPLES:
|
|
146
|
+
|
|
147
|
+
We build the poset `D` of divisors of 30, and check that
|
|
148
|
+
it is isomorphic to the boolean lattice `B` of the subsets
|
|
149
|
+
of `\{2,3,5\}` ordered by inclusion, via the reverse
|
|
150
|
+
function `f: B \to D, b \mapsto \prod_{x\in b} x`::
|
|
151
|
+
|
|
152
|
+
sage: D = Poset((divisors(30), attrcall("divides")))
|
|
153
|
+
sage: B = Poset(([frozenset(s) for s in Subsets([2,3,5])],
|
|
154
|
+
....: attrcall("issubset")))
|
|
155
|
+
sage: def f(b): return D(prod(b))
|
|
156
|
+
sage: B.is_poset_isomorphism(f, D)
|
|
157
|
+
True
|
|
158
|
+
|
|
159
|
+
On the other hand, `f` is not an isomorphism to the chain
|
|
160
|
+
of divisors of 30, ordered by usual comparison::
|
|
161
|
+
|
|
162
|
+
sage: P = Poset((divisors(30), operator.le))
|
|
163
|
+
sage: def f(b): return P(prod(b))
|
|
164
|
+
sage: B.is_poset_isomorphism(f, P)
|
|
165
|
+
False
|
|
166
|
+
|
|
167
|
+
A non surjective case::
|
|
168
|
+
|
|
169
|
+
sage: B = Poset(([frozenset(s) for s in Subsets([2,3])],
|
|
170
|
+
....: attrcall("issubset")))
|
|
171
|
+
sage: def f(b): return D(prod(b))
|
|
172
|
+
sage: B.is_poset_isomorphism(f, D)
|
|
173
|
+
False
|
|
174
|
+
|
|
175
|
+
A non injective case::
|
|
176
|
+
|
|
177
|
+
sage: B = Poset(([frozenset(s) for s in Subsets([2,3,5,6])],
|
|
178
|
+
....: attrcall("issubset")))
|
|
179
|
+
sage: def f(b): return D(gcd(prod(b), 30))
|
|
180
|
+
sage: B.is_poset_isomorphism(f, D)
|
|
181
|
+
False
|
|
182
|
+
|
|
183
|
+
.. NOTE:: since ``D`` and ``B`` are not facade posets, ``f`` is
|
|
184
|
+
responsible for the conversions between integers and subsets to
|
|
185
|
+
elements of ``D`` and ``B`` and back.
|
|
186
|
+
|
|
187
|
+
.. SEEALSO:: :meth:`FiniteLatticePosets.ParentMethods.is_lattice_morphism`
|
|
188
|
+
"""
|
|
189
|
+
image = {f(x) for x in self}
|
|
190
|
+
if len(image) != self.cardinality():
|
|
191
|
+
# Not injective
|
|
192
|
+
return False
|
|
193
|
+
if len(image) != codomain.cardinality():
|
|
194
|
+
# Not surjective
|
|
195
|
+
return False
|
|
196
|
+
for x in self:
|
|
197
|
+
if {f(y) for y in self.upper_covers(x)} != set(codomain.upper_covers(f(x))):
|
|
198
|
+
return False
|
|
199
|
+
return True
|
|
200
|
+
|
|
201
|
+
def is_poset_morphism(self, f, codomain):
|
|
202
|
+
r"""
|
|
203
|
+
Return whether `f` is a morphism of posets from ``self``
|
|
204
|
+
to ``codomain``, that is
|
|
205
|
+
|
|
206
|
+
.. MATH::
|
|
207
|
+
|
|
208
|
+
x\leq y \Longrightarrow f(x) \leq f(y)
|
|
209
|
+
|
|
210
|
+
for all `x` and `y` in ``self``.
|
|
211
|
+
|
|
212
|
+
INPUT:
|
|
213
|
+
|
|
214
|
+
- ``f`` -- a function from ``self`` to ``codomain``
|
|
215
|
+
- ``codomain`` -- a poset
|
|
216
|
+
|
|
217
|
+
EXAMPLES:
|
|
218
|
+
|
|
219
|
+
We build the boolean lattice of the subsets of
|
|
220
|
+
`\{2,3,5,6\}` and the lattice of divisors of `30`, and
|
|
221
|
+
check that the map `b \mapsto \gcd(\prod_{x\in b} x, 30)`
|
|
222
|
+
is a morphism of posets::
|
|
223
|
+
|
|
224
|
+
sage: D = Poset((divisors(30), attrcall("divides")))
|
|
225
|
+
sage: B = Poset(([frozenset(s) for s in Subsets([2,3,5,6])],
|
|
226
|
+
....: attrcall("issubset")))
|
|
227
|
+
sage: def f(b): return D(gcd(prod(b), 30))
|
|
228
|
+
sage: B.is_poset_morphism(f, D)
|
|
229
|
+
True
|
|
230
|
+
|
|
231
|
+
.. NOTE:: since ``D`` and ``B`` are not facade posets, ``f`` is responsible
|
|
232
|
+
for the conversions between integers and subsets to elements of
|
|
233
|
+
``D`` and ``B`` and back.
|
|
234
|
+
|
|
235
|
+
`f` is also a morphism of posets to the chain of divisors
|
|
236
|
+
of 30, ordered by usual comparison::
|
|
237
|
+
|
|
238
|
+
sage: P = Poset((divisors(30), operator.le))
|
|
239
|
+
sage: def f(b): return P(gcd(prod(b), 30))
|
|
240
|
+
sage: B.is_poset_morphism(f, P)
|
|
241
|
+
True
|
|
242
|
+
|
|
243
|
+
FIXME: should this be ``is_order_preserving_morphism``?
|
|
244
|
+
|
|
245
|
+
.. SEEALSO:: :meth:`is_poset_isomorphism`
|
|
246
|
+
|
|
247
|
+
TESTS:
|
|
248
|
+
|
|
249
|
+
Base cases::
|
|
250
|
+
|
|
251
|
+
sage: P = posets.ChainPoset(2)
|
|
252
|
+
sage: Q = posets.AntichainPoset(2)
|
|
253
|
+
sage: f = lambda x: 1-x
|
|
254
|
+
sage: P.is_poset_morphism(f, P)
|
|
255
|
+
False
|
|
256
|
+
sage: P.is_poset_morphism(f, Q)
|
|
257
|
+
False
|
|
258
|
+
sage: Q.is_poset_morphism(f, Q)
|
|
259
|
+
True
|
|
260
|
+
sage: Q.is_poset_morphism(f, P)
|
|
261
|
+
True
|
|
262
|
+
|
|
263
|
+
sage: P = Poset(); P
|
|
264
|
+
Finite poset containing 0 elements
|
|
265
|
+
sage: P.is_poset_morphism(f, P)
|
|
266
|
+
True
|
|
267
|
+
"""
|
|
268
|
+
for x in self:
|
|
269
|
+
for y in self.upper_covers(x):
|
|
270
|
+
if not codomain.is_lequal(f(x),f(y)):
|
|
271
|
+
return False
|
|
272
|
+
return True
|
|
273
|
+
|
|
274
|
+
##########################################################################
|
|
275
|
+
# About order ideals, order filters and the like
|
|
276
|
+
|
|
277
|
+
def order_ideal_generators(self, ideal, direction='down'):
|
|
278
|
+
r"""
|
|
279
|
+
Return the antichain of (minimal) generators of the order
|
|
280
|
+
ideal (resp. order filter) ``ideal``.
|
|
281
|
+
|
|
282
|
+
INPUT:
|
|
283
|
+
|
|
284
|
+
- ``ideal`` -- an order ideal `I` (resp. order filter)
|
|
285
|
+
of ``self``, as a list (or iterable); this should be
|
|
286
|
+
an order ideal if ``direction`` is set to ``'down'``,
|
|
287
|
+
and an order filter if ``direction`` is set to
|
|
288
|
+
``'up'``
|
|
289
|
+
- ``direction`` -- ``'up'`` or ``'down'`` (default:
|
|
290
|
+
``'down'``)
|
|
291
|
+
|
|
292
|
+
The antichain of (minimal) generators of an order ideal
|
|
293
|
+
`I` in a poset `P` is the set of all minimal elements of
|
|
294
|
+
`P`. In the case of an order filter, the definition is
|
|
295
|
+
similar, but with "maximal" used instead of "minimal".
|
|
296
|
+
|
|
297
|
+
EXAMPLES:
|
|
298
|
+
|
|
299
|
+
We build the boolean lattice of all subsets of `\{1,2,3\}`
|
|
300
|
+
ordered by inclusion, and compute an order ideal there::
|
|
301
|
+
|
|
302
|
+
sage: P = Poset((Subsets([1,2,3]), attrcall("issubset")))
|
|
303
|
+
sage: I = P.order_ideal([Set([1,2]), Set([2,3]), Set([1])])
|
|
304
|
+
sage: sorted(sorted(p) for p in I)
|
|
305
|
+
[[], [1], [1, 2], [2], [2, 3], [3]]
|
|
306
|
+
|
|
307
|
+
Then, we retrieve the generators of this ideal::
|
|
308
|
+
|
|
309
|
+
sage: gen = P.order_ideal_generators(I)
|
|
310
|
+
sage: sorted(sorted(p) for p in gen)
|
|
311
|
+
[[1, 2], [2, 3]]
|
|
312
|
+
|
|
313
|
+
If ``direction`` is ``'up'``, then this instead computes
|
|
314
|
+
the minimal generators for an order filter::
|
|
315
|
+
|
|
316
|
+
sage: I = P.order_filter([Set([1,2]), Set([2,3]), Set([1])])
|
|
317
|
+
sage: sorted(sorted(p) for p in I)
|
|
318
|
+
[[1], [1, 2], [1, 2, 3], [1, 3], [2, 3]]
|
|
319
|
+
sage: gen = P.order_ideal_generators(I, direction='up')
|
|
320
|
+
sage: sorted(sorted(p) for p in gen)
|
|
321
|
+
[[1], [2, 3]]
|
|
322
|
+
|
|
323
|
+
Complexity: `O(n+m)` where `n` is the cardinality of `I`,
|
|
324
|
+
and `m` the number of upper covers of elements of `I`.
|
|
325
|
+
"""
|
|
326
|
+
if direction == 'down':
|
|
327
|
+
covers = self.upper_covers
|
|
328
|
+
else:
|
|
329
|
+
covers = self.lower_covers
|
|
330
|
+
ideal_as_set = set(ideal)
|
|
331
|
+
from sage.sets.set import Set
|
|
332
|
+
return Set(x for x in ideal if all(y not in ideal_as_set
|
|
333
|
+
for y in covers(x)))
|
|
334
|
+
|
|
335
|
+
def order_filter_generators(self, filter):
|
|
336
|
+
r"""
|
|
337
|
+
Generators for an order filter.
|
|
338
|
+
|
|
339
|
+
INPUT:
|
|
340
|
+
|
|
341
|
+
- ``filter`` -- an order filter of ``self``, as a list (or iterable)
|
|
342
|
+
|
|
343
|
+
EXAMPLES::
|
|
344
|
+
|
|
345
|
+
sage: P = Poset((Subsets([1,2,3]), attrcall("issubset")))
|
|
346
|
+
sage: I = P.order_filter([Set([1,2]), Set([2,3]), Set([1])])
|
|
347
|
+
sage: sorted(sorted(p) for p in I)
|
|
348
|
+
[[1], [1, 2], [1, 2, 3], [1, 3], [2, 3]]
|
|
349
|
+
sage: gen = P.order_filter_generators(I)
|
|
350
|
+
sage: sorted(sorted(p) for p in gen)
|
|
351
|
+
[[1], [2, 3]]
|
|
352
|
+
|
|
353
|
+
.. SEEALSO:: :meth:`order_ideal_generators`
|
|
354
|
+
"""
|
|
355
|
+
return self.order_ideal_generators(filter, direction='up')
|
|
356
|
+
|
|
357
|
+
def order_ideal_complement_generators(self, antichain, direction='up'):
|
|
358
|
+
r"""
|
|
359
|
+
Return the Panyushev complement of the antichain
|
|
360
|
+
``antichain``.
|
|
361
|
+
|
|
362
|
+
Given an antichain `A` of a poset `P`, the Panyushev
|
|
363
|
+
complement of `A` is defined to be the antichain consisting
|
|
364
|
+
of the minimal elements of the order filter `B`, where `B`
|
|
365
|
+
is the (set-theoretic) complement of the order ideal of
|
|
366
|
+
`P` generated by `A`.
|
|
367
|
+
|
|
368
|
+
Setting the optional keyword variable ``direction`` to
|
|
369
|
+
``'down'`` leads to the inverse Panyushev complement being
|
|
370
|
+
computed instead of the Panyushev complement. The inverse
|
|
371
|
+
Panyushev complement of an antichain `A` is the antichain
|
|
372
|
+
whose Panyushev complement is `A`. It can be found as the
|
|
373
|
+
antichain consisting of the maximal elements of the order
|
|
374
|
+
ideal `C`, where `C` is the (set-theoretic) complement of
|
|
375
|
+
the order filter of `P` generated by `A`.
|
|
376
|
+
|
|
377
|
+
:meth:`panyushev_complement` is an alias for this method.
|
|
378
|
+
|
|
379
|
+
Panyushev complementation is related (actually, isomorphic)
|
|
380
|
+
to rowmotion (:meth:`rowmotion`).
|
|
381
|
+
|
|
382
|
+
INPUT:
|
|
383
|
+
|
|
384
|
+
- ``antichain`` -- an antichain of ``self``, as a list (or
|
|
385
|
+
iterable), or, more generally, generators of an order ideal
|
|
386
|
+
(resp. order filter)
|
|
387
|
+
- ``direction`` -- ``'up'`` or ``'down'`` (default: ``'up'``)
|
|
388
|
+
|
|
389
|
+
OUTPUT:
|
|
390
|
+
|
|
391
|
+
- the generating antichain of the complement order filter
|
|
392
|
+
(resp. order ideal) of the order ideal (resp. order filter)
|
|
393
|
+
generated by the antichain ``antichain``
|
|
394
|
+
|
|
395
|
+
EXAMPLES::
|
|
396
|
+
|
|
397
|
+
sage: P = Poset( ( [1,2,3], [ [1,3], [2,3] ] ) )
|
|
398
|
+
sage: P.order_ideal_complement_generators([1])
|
|
399
|
+
{2}
|
|
400
|
+
sage: P.order_ideal_complement_generators([3])
|
|
401
|
+
set()
|
|
402
|
+
sage: P.order_ideal_complement_generators([1,2])
|
|
403
|
+
{3}
|
|
404
|
+
sage: P.order_ideal_complement_generators([1,2,3])
|
|
405
|
+
set()
|
|
406
|
+
|
|
407
|
+
sage: P.order_ideal_complement_generators([1], direction='down')
|
|
408
|
+
{2}
|
|
409
|
+
sage: P.order_ideal_complement_generators([3], direction='down')
|
|
410
|
+
{1, 2}
|
|
411
|
+
sage: P.order_ideal_complement_generators([1,2], direction='down')
|
|
412
|
+
set()
|
|
413
|
+
sage: P.order_ideal_complement_generators([1,2,3], direction='down')
|
|
414
|
+
set()
|
|
415
|
+
|
|
416
|
+
.. WARNING::
|
|
417
|
+
|
|
418
|
+
This is a brute force implementation, building the
|
|
419
|
+
order ideal generated by the antichain, and searching
|
|
420
|
+
for order filter generators of its complement
|
|
421
|
+
"""
|
|
422
|
+
if direction == 'up':
|
|
423
|
+
I = self.order_ideal(antichain)
|
|
424
|
+
else:
|
|
425
|
+
I = self.order_filter(antichain)
|
|
426
|
+
I_comp = set(self).difference(I)
|
|
427
|
+
return set(self.order_ideal_generators(I_comp, direction=direction))
|
|
428
|
+
|
|
429
|
+
panyushev_complement = order_ideal_complement_generators
|
|
430
|
+
|
|
431
|
+
def rowmotion(self, order_ideal):
|
|
432
|
+
r"""
|
|
433
|
+
The image of the order ideal ``order_ideal`` under rowmotion
|
|
434
|
+
in ``self``.
|
|
435
|
+
|
|
436
|
+
Rowmotion on a finite poset `P` is an automorphism of the set
|
|
437
|
+
`J(P)` of all order ideals of `P`. One way to define it is as
|
|
438
|
+
follows: Given an order ideal `I \in J(P)`, we let `F` be the
|
|
439
|
+
set-theoretic complement of `I` in `P`. Furthermore we let
|
|
440
|
+
`A` be the antichain consisting of all minimal elements of
|
|
441
|
+
`F`. Then, the rowmotion of `I` is defined to be the order
|
|
442
|
+
ideal of `P` generated by the antichain `A` (that is, the
|
|
443
|
+
order ideal consisting of each element of `P` which has some
|
|
444
|
+
element of `A` above it).
|
|
445
|
+
|
|
446
|
+
Rowmotion is related (actually, isomorphic) to Panyushev
|
|
447
|
+
complementation (:meth:`panyushev_complement`).
|
|
448
|
+
|
|
449
|
+
INPUT:
|
|
450
|
+
|
|
451
|
+
- ``order_ideal`` -- an order ideal of ``self``, as a set
|
|
452
|
+
|
|
453
|
+
OUTPUT: the image of ``order_ideal`` under rowmotion, as a set again
|
|
454
|
+
|
|
455
|
+
EXAMPLES::
|
|
456
|
+
|
|
457
|
+
sage: P = Poset( {1: [2, 3], 2: [], 3: [], 4: [8],
|
|
458
|
+
....: 5: [], 6: [5], 7: [1, 4], 8: []} )
|
|
459
|
+
sage: I = Set({2, 6, 1, 7})
|
|
460
|
+
sage: P.rowmotion(I)
|
|
461
|
+
{1, 3, 4, 5, 6, 7}
|
|
462
|
+
|
|
463
|
+
sage: P = Poset( {} )
|
|
464
|
+
sage: I = Set({})
|
|
465
|
+
sage: P.rowmotion(I)
|
|
466
|
+
{}
|
|
467
|
+
"""
|
|
468
|
+
result = order_ideal
|
|
469
|
+
for i in reversed(self.linear_extension()):
|
|
470
|
+
result = self.order_ideal_toggle(result, i)
|
|
471
|
+
return result
|
|
472
|
+
|
|
473
|
+
def birational_free_labelling(self, linear_extension=None,
|
|
474
|
+
prefix='x', base_field=None,
|
|
475
|
+
reduced=False, addvars=None,
|
|
476
|
+
labels=None,
|
|
477
|
+
min_label=None,
|
|
478
|
+
max_label=None):
|
|
479
|
+
r"""
|
|
480
|
+
Return the birational free labelling of ``self``.
|
|
481
|
+
|
|
482
|
+
Let us hold back defining this, and introduce birational
|
|
483
|
+
toggles and birational rowmotion first. These notions have
|
|
484
|
+
been introduced in [EP2013]_ as generalizations of the notions
|
|
485
|
+
of toggles (:meth:`~sage.categories.posets.Posets.ParentMethods.order_ideal_toggle`)
|
|
486
|
+
and :meth:`rowmotion <rowmotion>` on order ideals of a finite poset. They
|
|
487
|
+
have been studied further in [GR2013]_.
|
|
488
|
+
|
|
489
|
+
Let `\mathbf{K}` be a field, and `P` be a finite poset. Let
|
|
490
|
+
`\widehat{P}` denote the poset obtained from `P` by adding a
|
|
491
|
+
new element `1` which is greater than all existing elements
|
|
492
|
+
of `P`, and a new element `0` which is smaller than all
|
|
493
|
+
existing elements of `P` and `1`. Now, a `\mathbf{K}`-*labelling
|
|
494
|
+
of* `P` will mean any function from `\widehat{P}` to `\mathbf{K}`.
|
|
495
|
+
The image of an element `v` of `\widehat{P}` under this labelling
|
|
496
|
+
will be called the *label* of this labelling at `v`. The set
|
|
497
|
+
of all `\mathbf{K}`-labellings of `P` is clearly
|
|
498
|
+
`\mathbf{K}^{\widehat{P}}`.
|
|
499
|
+
|
|
500
|
+
For any `v \in P`, we now define a rational map
|
|
501
|
+
`T_v : \mathbf{K}^{\widehat{P}} \dashrightarrow
|
|
502
|
+
\mathbf{K}^{\widehat{P}}` as follows: For every `f \in
|
|
503
|
+
\mathbf{K}^{\widehat{P}}`, the image `T_v f` should send every
|
|
504
|
+
element `u \in \widehat{P}` distinct from `v` to `f(u)` (so the
|
|
505
|
+
labels at all `u \neq v` don't change), while `v` is sent to
|
|
506
|
+
|
|
507
|
+
.. MATH::
|
|
508
|
+
|
|
509
|
+
\frac{1}{f(v)} \cdot
|
|
510
|
+
\frac{\sum_{u \lessdot v} f(u)}
|
|
511
|
+
{\sum_{u \gtrdot v} \frac{1}{f(u)}}
|
|
512
|
+
|
|
513
|
+
(both sums are over all `u \in \widehat{P}` satisfying the
|
|
514
|
+
respectively given conditions). Here, `\lessdot` and `\gtrdot`
|
|
515
|
+
mean (respectively) "covered by" and "covers", interpreted with
|
|
516
|
+
respect to the poset `\widehat{P}`. This rational map `T_v`
|
|
517
|
+
is an involution and is called the *(birational)* `v`-*toggle*; see
|
|
518
|
+
:meth:`birational_toggle` for its implementation.
|
|
519
|
+
|
|
520
|
+
Now, *birational rowmotion* is defined as the composition
|
|
521
|
+
`T_{v_1} \circ T_{v_2} \circ \cdots \circ T_{v_n}`, where
|
|
522
|
+
`(v_1, v_2, \ldots, v_n)` is a linear extension of `P`
|
|
523
|
+
(written as a linear ordering of the elements of `P`). This
|
|
524
|
+
is a rational map
|
|
525
|
+
`\mathbf{K}^{\widehat{P}} \dashrightarrow \mathbf{K}^{\widehat{P}}`
|
|
526
|
+
which does not depend on the choice of the linear extension;
|
|
527
|
+
it is denoted by `R`. See :meth:`birational_rowmotion` for
|
|
528
|
+
its implementation.
|
|
529
|
+
|
|
530
|
+
The definitions of birational toggles and birational
|
|
531
|
+
rowmotion extend to the case of `\mathbf{K}` being any semifield
|
|
532
|
+
rather than necessarily a field (although it becomes less
|
|
533
|
+
clear what constitutes a rational map in this generality).
|
|
534
|
+
The most useful case is that of the :class:`tropical semiring
|
|
535
|
+
<sage.rings.semirings.tropical_semiring.TropicalSemiring>`,
|
|
536
|
+
in which case birational rowmotion relates to classical
|
|
537
|
+
constructions such as promotion of rectangular semistandard
|
|
538
|
+
Young tableaux (page 5 of [EP2013b]_ and future work, via the
|
|
539
|
+
related notion of birational *promotion*) and rowmotion on
|
|
540
|
+
order ideals of the poset ([EP2013]_).
|
|
541
|
+
|
|
542
|
+
The *birational free labelling* is a special labelling
|
|
543
|
+
defined for every finite poset `P` and every linear extension
|
|
544
|
+
`(v_1, v_2, \ldots, v_n)` of `P`. It is given by sending
|
|
545
|
+
every element `v_i` in `P` to `x_i`, sending the element `0`
|
|
546
|
+
of `\widehat{P}` to `a`, and sending the element `1` of
|
|
547
|
+
`\widehat{P}` to `b`, where the ground field `\mathbf{K}` is the
|
|
548
|
+
field of rational functions in `n+2` indeterminates
|
|
549
|
+
`a, x_1, x_2, \ldots, x_n, b` over `\mathbb Q`.
|
|
550
|
+
|
|
551
|
+
In Sage, a labelling `f` of a poset `P` is encoded as a
|
|
552
|
+
`4`-tuple `(\mathbf{K}, d, u, v)`, where `\mathbf{K}` is the
|
|
553
|
+
ground field of the labelling (i. e., its target), `d` is the
|
|
554
|
+
dictionary containing the values of `f` at the elements of
|
|
555
|
+
`P` (the keys being the respective elements of `P`), `u`
|
|
556
|
+
is the label of `f` at `0`, and `v` is the label of `f` at
|
|
557
|
+
`1`.
|
|
558
|
+
|
|
559
|
+
.. WARNING::
|
|
560
|
+
|
|
561
|
+
The dictionary `d` is labelled by the elements of `P`.
|
|
562
|
+
If `P` is a poset with ``facade`` option set to
|
|
563
|
+
``False``, these might not be what they seem to be!
|
|
564
|
+
(For instance, if
|
|
565
|
+
``P == Poset({1: [2, 3]}, facade=False)``, then the
|
|
566
|
+
value of `d` at `1` has to be accessed by ``d[P(1)]``, not
|
|
567
|
+
by ``d[1]``.)
|
|
568
|
+
|
|
569
|
+
.. WARNING::
|
|
570
|
+
|
|
571
|
+
Dictionaries are mutable. They do compare correctly,
|
|
572
|
+
but are not hashable and need to be cloned to avoid
|
|
573
|
+
spooky action at a distance. Be careful!
|
|
574
|
+
|
|
575
|
+
INPUT:
|
|
576
|
+
|
|
577
|
+
- ``linear_extension`` -- (default: the default linear
|
|
578
|
+
extension of ``self``) a linear extension of ``self``
|
|
579
|
+
(as a linear extension or as a list), or more generally
|
|
580
|
+
a list of all elements of all elements of ``self`` each
|
|
581
|
+
occurring exactly once
|
|
582
|
+
|
|
583
|
+
- ``prefix`` -- (default: ``'x'``) the prefix to name
|
|
584
|
+
the indeterminates corresponding to the elements of
|
|
585
|
+
``self`` in the labelling (so, setting it to
|
|
586
|
+
``'frog'`` will result in these indeterminates being
|
|
587
|
+
called ``frog1, frog2, ..., frogn`` rather than
|
|
588
|
+
``x1, x2, ..., xn``).
|
|
589
|
+
|
|
590
|
+
- ``base_field`` -- (default: ``QQ``) the base field to
|
|
591
|
+
be used instead of `\QQ` to define the rational
|
|
592
|
+
function field over; this is not going to be the base
|
|
593
|
+
field of the labelling, because the latter will have
|
|
594
|
+
indeterminates adjoined!
|
|
595
|
+
|
|
596
|
+
- ``reduced`` -- boolean (default: ``False``); if set to
|
|
597
|
+
``True``, the result will be the *reduced* birational
|
|
598
|
+
free labelling, which differs from the regular one by
|
|
599
|
+
having `0` and `1` both sent to `1` instead of `a` and
|
|
600
|
+
`b` (the indeterminates `a` and `b` then also won't
|
|
601
|
+
appear in the ground field)
|
|
602
|
+
|
|
603
|
+
- ``addvars`` -- (default: ``''``) a string containing
|
|
604
|
+
names of extra variables to be adjoined to the ground
|
|
605
|
+
field (these don't have an effect on the labels)
|
|
606
|
+
|
|
607
|
+
- ``labels`` -- (default: ``'x'``) either a function
|
|
608
|
+
that takes an element of the poset and returns a name
|
|
609
|
+
for the indeterminate corresponding to that element,
|
|
610
|
+
or a string containing a comma-separated list of
|
|
611
|
+
indeterminates that will be assigned to elements in
|
|
612
|
+
the order of ``linear_extension``. If the
|
|
613
|
+
list contains more indeterminates than needed, the
|
|
614
|
+
excess will be ignored. If it contains too few, then
|
|
615
|
+
the needed indeterminates will be constructed from
|
|
616
|
+
``prefix``.
|
|
617
|
+
|
|
618
|
+
- ``min_label`` -- (default: ``'a'``) a string to be
|
|
619
|
+
used as the label for the element `0` of `\widehat{P}`
|
|
620
|
+
|
|
621
|
+
- ``max_label`` -- (default: ``'b'``) a string to be
|
|
622
|
+
used as the label for the element `1` of `\widehat{P}`
|
|
623
|
+
|
|
624
|
+
OUTPUT:
|
|
625
|
+
|
|
626
|
+
The birational free labelling of the poset ``self`` and the
|
|
627
|
+
linear extension ``linear_extension``. Or, if ``reduced``
|
|
628
|
+
is set to ``True``, the reduced birational free labelling.
|
|
629
|
+
|
|
630
|
+
EXAMPLES:
|
|
631
|
+
|
|
632
|
+
We construct the birational free labelling on a simple
|
|
633
|
+
poset::
|
|
634
|
+
|
|
635
|
+
sage: P = Poset({1: [2, 3]})
|
|
636
|
+
sage: l = P.birational_free_labelling(); l
|
|
637
|
+
(Fraction Field of Multivariate Polynomial Ring
|
|
638
|
+
in a, x1, x2, x3, b over Rational Field,
|
|
639
|
+
{...},
|
|
640
|
+
a,
|
|
641
|
+
b)
|
|
642
|
+
sage: sorted(l[1].items())
|
|
643
|
+
[(1, x1), (2, x2), (3, x3)]
|
|
644
|
+
|
|
645
|
+
sage: l = P.birational_free_labelling(linear_extension=[1, 3, 2]); l
|
|
646
|
+
(Fraction Field of Multivariate Polynomial Ring
|
|
647
|
+
in a, x1, x2, x3, b over Rational Field,
|
|
648
|
+
{...},
|
|
649
|
+
a,
|
|
650
|
+
b)
|
|
651
|
+
sage: sorted(l[1].items())
|
|
652
|
+
[(1, x1), (2, x3), (3, x2)]
|
|
653
|
+
|
|
654
|
+
sage: l = P.birational_free_labelling(linear_extension=[1, 3, 2],
|
|
655
|
+
....: reduced=True, addvars="spam, eggs"); l
|
|
656
|
+
(Fraction Field of Multivariate Polynomial Ring
|
|
657
|
+
in x1, x2, x3, spam, eggs over Rational Field,
|
|
658
|
+
{...},
|
|
659
|
+
1,
|
|
660
|
+
1)
|
|
661
|
+
sage: sorted(l[1].items())
|
|
662
|
+
[(1, x1), (2, x3), (3, x2)]
|
|
663
|
+
|
|
664
|
+
sage: l = P.birational_free_labelling(linear_extension=[1, 3, 2],
|
|
665
|
+
....: prefix='wut', reduced=True,
|
|
666
|
+
....: addvars="spam, eggs"); l
|
|
667
|
+
(Fraction Field of Multivariate Polynomial Ring
|
|
668
|
+
in wut1, wut2, wut3, spam, eggs over Rational Field,
|
|
669
|
+
{...},
|
|
670
|
+
1,
|
|
671
|
+
1)
|
|
672
|
+
sage: sorted(l[1].items())
|
|
673
|
+
[(1, wut1), (2, wut3), (3, wut2)]
|
|
674
|
+
|
|
675
|
+
sage: l = P.birational_free_labelling(linear_extension=[1, 3, 2],
|
|
676
|
+
....: reduced=False, addvars="spam, eggs"); l
|
|
677
|
+
(Fraction Field of Multivariate Polynomial Ring
|
|
678
|
+
in a, x1, x2, x3, b, spam, eggs over Rational Field,
|
|
679
|
+
{...},
|
|
680
|
+
a,
|
|
681
|
+
b)
|
|
682
|
+
sage: sorted(l[1].items())
|
|
683
|
+
[(1, x1), (2, x3), (3, x2)]
|
|
684
|
+
sage: l[1][2]
|
|
685
|
+
x3
|
|
686
|
+
|
|
687
|
+
Illustrating labelling with a function::
|
|
688
|
+
|
|
689
|
+
sage: P = posets.ChainPoset(2).product(posets.ChainPoset(2)) # needs sage.modules
|
|
690
|
+
sage: def x_label(e):
|
|
691
|
+
....: return 'x_' + str(e[0]) + str(e[1])
|
|
692
|
+
sage: l = P.birational_free_labelling(labels=x_label)
|
|
693
|
+
sage: sorted(l[1].items())
|
|
694
|
+
[((0, 0), x_00), ((0, 1), x_01), ((1, 0), x_10), ((1, 1), x_11)]
|
|
695
|
+
sage: l[2]
|
|
696
|
+
a
|
|
697
|
+
|
|
698
|
+
The same, but with ``min_label`` and ``max_label`` provided::
|
|
699
|
+
|
|
700
|
+
sage: P = posets.ChainPoset(2).product(posets.ChainPoset(2)) # needs sage.modules
|
|
701
|
+
sage: l = P.birational_free_labelling(labels=x_label,
|
|
702
|
+
....: min_label='lambda', max_label='mu')
|
|
703
|
+
sage: sorted(l[1].items())
|
|
704
|
+
[((0, 0), x_00), ((0, 1), x_01), ((1, 0), x_10), ((1, 1), x_11)]
|
|
705
|
+
sage: l[2]
|
|
706
|
+
lambda
|
|
707
|
+
sage: l[3]
|
|
708
|
+
mu
|
|
709
|
+
|
|
710
|
+
Illustrating labelling with a comma separated list of labels::
|
|
711
|
+
|
|
712
|
+
sage: l = P.birational_free_labelling(labels='w,x,y,z')
|
|
713
|
+
sage: sorted(l[1].items())
|
|
714
|
+
[((0, 0), w), ((0, 1), x), ((1, 0), y), ((1, 1), z)]
|
|
715
|
+
sage: l = P.birational_free_labelling(labels='w,x,y,z,m')
|
|
716
|
+
sage: sorted(l[1].items())
|
|
717
|
+
[((0, 0), w), ((0, 1), x), ((1, 0), y), ((1, 1), z)]
|
|
718
|
+
sage: l = P.birational_free_labelling(labels='w')
|
|
719
|
+
sage: sorted(l[1].items())
|
|
720
|
+
[((0, 0), w), ((0, 1), x1), ((1, 0), x2), ((1, 1), x3)]
|
|
721
|
+
|
|
722
|
+
Illustrating the warning about facade::
|
|
723
|
+
|
|
724
|
+
sage: P = Poset({1: [2, 3]}, facade=False)
|
|
725
|
+
sage: l = P.birational_free_labelling(linear_extension=[1, 3, 2],
|
|
726
|
+
....: reduced=False,
|
|
727
|
+
....: addvars="spam, eggs"); l
|
|
728
|
+
(Fraction Field of Multivariate Polynomial Ring
|
|
729
|
+
in a, x1, x2, x3, b, spam, eggs over Rational Field,
|
|
730
|
+
{...},
|
|
731
|
+
a,
|
|
732
|
+
b)
|
|
733
|
+
sage: l[1][2]
|
|
734
|
+
Traceback (most recent call last):
|
|
735
|
+
...
|
|
736
|
+
KeyError: 2
|
|
737
|
+
sage: l[1][P(2)]
|
|
738
|
+
x3
|
|
739
|
+
|
|
740
|
+
Another poset::
|
|
741
|
+
|
|
742
|
+
sage: # needs sage.modules
|
|
743
|
+
sage: P = posets.SSTPoset([2,1])
|
|
744
|
+
sage: lext = sorted(P)
|
|
745
|
+
sage: l = P.birational_free_labelling(linear_extension=lext,
|
|
746
|
+
....: addvars='ohai'); l
|
|
747
|
+
(Fraction Field of Multivariate Polynomial Ring
|
|
748
|
+
in a, x1, x2, x3, x4, x5, x6, x7, x8, b, ohai over Rational Field,
|
|
749
|
+
{...},
|
|
750
|
+
a,
|
|
751
|
+
b)
|
|
752
|
+
sage: sorted(l[1].items())
|
|
753
|
+
[([[1, 1], [2]], x1), ([[1, 1], [3]], x2),
|
|
754
|
+
([[1, 2], [2]], x3), ([[1, 2], [3]], x4),
|
|
755
|
+
([[1, 3], [2]], x5), ([[1, 3], [3]], x6),
|
|
756
|
+
([[2, 2], [3]], x7), ([[2, 3], [3]], x8)]
|
|
757
|
+
|
|
758
|
+
See :meth:`birational_rowmotion`, :meth:`birational_toggle` and
|
|
759
|
+
:meth:`birational_toggles` for more substantial examples of what
|
|
760
|
+
one can do with the birational free labelling.
|
|
761
|
+
|
|
762
|
+
TESTS:
|
|
763
|
+
|
|
764
|
+
The ``linear_extension`` keyword does not have to be given an
|
|
765
|
+
actual linear extension::
|
|
766
|
+
|
|
767
|
+
sage: # needs sage.modules
|
|
768
|
+
sage: P = posets.ChainPoset(2).product(posets.ChainPoset(3)); P
|
|
769
|
+
Finite lattice containing 6 elements
|
|
770
|
+
sage: lex = [(1,0),(0,0),(1,1),(0,1),(1,2),(0,2)]
|
|
771
|
+
sage: l = P.birational_free_labelling(linear_extension=lex,
|
|
772
|
+
....: prefix='u', reduced=True)
|
|
773
|
+
sage: l
|
|
774
|
+
(Fraction Field of Multivariate Polynomial Ring in u1, u2, u3, u4, u5, u6 over Rational Field,
|
|
775
|
+
{...},
|
|
776
|
+
1,
|
|
777
|
+
1)
|
|
778
|
+
sage: sorted(l[1].items())
|
|
779
|
+
[((0, 0), u2),
|
|
780
|
+
((0, 1), u4),
|
|
781
|
+
((0, 2), u6),
|
|
782
|
+
((1, 0), u1),
|
|
783
|
+
((1, 1), u3),
|
|
784
|
+
((1, 2), u5)]
|
|
785
|
+
|
|
786
|
+
For comparison, the standard linear extension::
|
|
787
|
+
|
|
788
|
+
sage: # needs sage.modules
|
|
789
|
+
sage: l = P.birational_free_labelling(prefix='u', reduced=True); l
|
|
790
|
+
(Fraction Field of Multivariate Polynomial Ring in u1, u2, u3, u4, u5, u6 over Rational Field,
|
|
791
|
+
{...},
|
|
792
|
+
1,
|
|
793
|
+
1)
|
|
794
|
+
sage: sorted(l[1].items())
|
|
795
|
+
[((0, 0), u1),
|
|
796
|
+
((0, 1), u2),
|
|
797
|
+
((0, 2), u3),
|
|
798
|
+
((1, 0), u4),
|
|
799
|
+
((1, 1), u5),
|
|
800
|
+
((1, 2), u6)]
|
|
801
|
+
|
|
802
|
+
If you want your linear extension to be tested for being a
|
|
803
|
+
linear extension, just call the ``linear_extension`` method
|
|
804
|
+
on the poset::
|
|
805
|
+
|
|
806
|
+
sage: # needs sage.modules
|
|
807
|
+
sage: lex = [(0,0),(0,1),(1,0),(1,1),(0,2),(1,2)]
|
|
808
|
+
sage: l = P.birational_free_labelling(linear_extension=P.linear_extension(lex),
|
|
809
|
+
....: prefix='u', reduced=True)
|
|
810
|
+
sage: l
|
|
811
|
+
(Fraction Field of Multivariate Polynomial Ring in u1, u2, u3, u4, u5, u6 over Rational Field,
|
|
812
|
+
{...},
|
|
813
|
+
1,
|
|
814
|
+
1)
|
|
815
|
+
sage: sorted(l[1].items())
|
|
816
|
+
[((0, 0), u1),
|
|
817
|
+
((0, 1), u2),
|
|
818
|
+
((0, 2), u5),
|
|
819
|
+
((1, 0), u3),
|
|
820
|
+
((1, 1), u4),
|
|
821
|
+
((1, 2), u6)]
|
|
822
|
+
|
|
823
|
+
Nonstandard base field::
|
|
824
|
+
|
|
825
|
+
sage: P = Poset({1: [3], 2: [3,4]})
|
|
826
|
+
sage: lex = [1, 2, 4, 3]
|
|
827
|
+
sage: l = P.birational_free_labelling(linear_extension=lex,
|
|
828
|
+
....: prefix='aaa',
|
|
829
|
+
....: base_field=Zmod(13))
|
|
830
|
+
sage: l
|
|
831
|
+
(Fraction Field of Multivariate Polynomial Ring in a, aaa1, aaa2, aaa3, aaa4, b over Ring of integers modulo 13,
|
|
832
|
+
{...},
|
|
833
|
+
a,
|
|
834
|
+
b)
|
|
835
|
+
sage: l[1][4]
|
|
836
|
+
aaa3
|
|
837
|
+
|
|
838
|
+
The empty poset::
|
|
839
|
+
|
|
840
|
+
sage: P = Poset({})
|
|
841
|
+
sage: P.birational_free_labelling(reduced=False, addvars="spam, eggs")
|
|
842
|
+
(Fraction Field of Multivariate Polynomial Ring in a, b, spam, eggs over Rational Field,
|
|
843
|
+
{},
|
|
844
|
+
a,
|
|
845
|
+
b)
|
|
846
|
+
sage: P.birational_free_labelling(reduced=True, addvars="spam, eggs")
|
|
847
|
+
(Fraction Field of Multivariate Polynomial Ring in spam, eggs over Rational Field,
|
|
848
|
+
{},
|
|
849
|
+
1,
|
|
850
|
+
1)
|
|
851
|
+
sage: P.birational_free_labelling(reduced=True)
|
|
852
|
+
(Multivariate Polynomial Ring in no variables over Rational Field,
|
|
853
|
+
{},
|
|
854
|
+
1,
|
|
855
|
+
1)
|
|
856
|
+
sage: P.birational_free_labelling(prefix='zzz')
|
|
857
|
+
(Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field,
|
|
858
|
+
{},
|
|
859
|
+
a,
|
|
860
|
+
b)
|
|
861
|
+
sage: P.birational_free_labelling(labels='x,y,z', min_label='spam', max_label='eggs')
|
|
862
|
+
(Fraction Field of Multivariate Polynomial Ring in spam, eggs over Rational Field,
|
|
863
|
+
{},
|
|
864
|
+
spam,
|
|
865
|
+
eggs)
|
|
866
|
+
"""
|
|
867
|
+
if base_field is None:
|
|
868
|
+
from sage.rings.rational_field import QQ
|
|
869
|
+
base_field = QQ
|
|
870
|
+
if linear_extension is None:
|
|
871
|
+
linear_extension = self.linear_extension()
|
|
872
|
+
n = self.cardinality()
|
|
873
|
+
label_list = []
|
|
874
|
+
if labels:
|
|
875
|
+
if callable(labels):
|
|
876
|
+
label_list = [labels(e) for e in linear_extension]
|
|
877
|
+
else:
|
|
878
|
+
label_list = labels.split(',')
|
|
879
|
+
if len(label_list) > n:
|
|
880
|
+
label_list = label_list[:n]
|
|
881
|
+
elif len(label_list) < n:
|
|
882
|
+
label_list += [prefix + str(i) for i in range(1, n + 1 - len(label_list))]
|
|
883
|
+
else:
|
|
884
|
+
label_list = [prefix + str(i) for i in range(1, n + 1)]
|
|
885
|
+
if not reduced:
|
|
886
|
+
if min_label is None:
|
|
887
|
+
min_label = 'a'
|
|
888
|
+
if max_label is None:
|
|
889
|
+
max_label = 'b'
|
|
890
|
+
label_list = [min_label] + label_list + [max_label]
|
|
891
|
+
if addvars:
|
|
892
|
+
label_list += addvars.split(',')
|
|
893
|
+
varstring = ','.join(label_list)
|
|
894
|
+
varnum = len(label_list)
|
|
895
|
+
|
|
896
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
897
|
+
PR = PolynomialRing(base_field, varstring, varnum)
|
|
898
|
+
# Now, ``PR`` is the polynomial ring in `n + 2` indeterminates
|
|
899
|
+
# (or more, if ``addvars`` was set; or less, if ``reduced`` is
|
|
900
|
+
# ``True``) over ``base_field``.
|
|
901
|
+
# The first `n + 2` of these indeterminates are named
|
|
902
|
+
# ``a, x1, x2, ..., xn, b`` (if ``reduced`` is ``False``).
|
|
903
|
+
# These will label the vertices of `\widehat{P}`.
|
|
904
|
+
if reduced:
|
|
905
|
+
xs = tuple(PR.gens()[: n])
|
|
906
|
+
else:
|
|
907
|
+
xs = tuple(PR.gens()[1 : n + 1])
|
|
908
|
+
# So ``xs`` is the list ``[x1, x2, ..., xn]``.
|
|
909
|
+
if not reduced:
|
|
910
|
+
a = PR.gens()[0]
|
|
911
|
+
b = PR.gens()[n + 1]
|
|
912
|
+
else:
|
|
913
|
+
a = PR.one()
|
|
914
|
+
b = PR.one()
|
|
915
|
+
# So ``a`` and ``b`` are the labels at `0` and `1`.
|
|
916
|
+
FF = PR.fraction_field()
|
|
917
|
+
# ``FF`` is the field of rational functions.
|
|
918
|
+
dct = {self(p): xs[i] for (i, p) in enumerate(linear_extension)}
|
|
919
|
+
return (FF, dct, a, b)
|
|
920
|
+
|
|
921
|
+
def birational_toggle(self, v, labelling):
|
|
922
|
+
r"""
|
|
923
|
+
Return the result of applying the birational `v`-toggle `T_v`
|
|
924
|
+
to the `\mathbf{K}`-labelling ``labelling`` of the poset ``self``.
|
|
925
|
+
|
|
926
|
+
See the documentation of :meth:`birational_free_labelling`
|
|
927
|
+
for a definition of this toggle and of `\mathbf{K}`-labellings as
|
|
928
|
+
well as an explanation of how `\mathbf{K}`-labellings are to be
|
|
929
|
+
encoded to be understood by Sage. This implementation allows
|
|
930
|
+
`\mathbf{K}` to be a semifield, not just a field. The birational
|
|
931
|
+
`v`-toggle is only a rational map, so an exception (most
|
|
932
|
+
likely, :exc:`ZeroDivisionError`) will be thrown if the
|
|
933
|
+
denominator is zero.
|
|
934
|
+
|
|
935
|
+
INPUT:
|
|
936
|
+
|
|
937
|
+
- ``v`` -- an element of ``self`` (must have ``self`` as
|
|
938
|
+
parent if ``self`` is a ``facade=False`` poset)
|
|
939
|
+
|
|
940
|
+
- ``labelling`` -- a `\mathbf{K}`-labelling of ``self`` in the
|
|
941
|
+
sense as defined in the documentation of
|
|
942
|
+
:meth:`birational_free_labelling`
|
|
943
|
+
|
|
944
|
+
OUTPUT:
|
|
945
|
+
|
|
946
|
+
The `\mathbf{K}`-labelling `T_v f` of ``self``, where `f` is
|
|
947
|
+
``labelling``.
|
|
948
|
+
|
|
949
|
+
EXAMPLES:
|
|
950
|
+
|
|
951
|
+
Let us start with the birational free labelling of the
|
|
952
|
+
"V"-poset (the three-element poset with Hasse diagram looking
|
|
953
|
+
like a "V")::
|
|
954
|
+
|
|
955
|
+
sage: V = Poset({1: [2, 3]})
|
|
956
|
+
sage: s = V.birational_free_labelling(); s
|
|
957
|
+
(Fraction Field of Multivariate Polynomial Ring
|
|
958
|
+
in a, x1, x2, x3, b over Rational Field,
|
|
959
|
+
{...},
|
|
960
|
+
a,
|
|
961
|
+
b)
|
|
962
|
+
sage: sorted(s[1].items())
|
|
963
|
+
[(1, x1), (2, x2), (3, x3)]
|
|
964
|
+
|
|
965
|
+
The image of `s` under the `1`-toggle `T_1` is::
|
|
966
|
+
|
|
967
|
+
sage: s1 = V.birational_toggle(1, s); s1
|
|
968
|
+
(Fraction Field of Multivariate Polynomial Ring
|
|
969
|
+
in a, x1, x2, x3, b over Rational Field,
|
|
970
|
+
{...},
|
|
971
|
+
a,
|
|
972
|
+
b)
|
|
973
|
+
sage: sorted(s1[1].items())
|
|
974
|
+
[(1, a*x2*x3/(x1*x2 + x1*x3)), (2, x2), (3, x3)]
|
|
975
|
+
|
|
976
|
+
Now let us apply the `2`-toggle `T_2` (to the old ``s``)::
|
|
977
|
+
|
|
978
|
+
sage: s2 = V.birational_toggle(2, s); s2
|
|
979
|
+
(Fraction Field of Multivariate Polynomial Ring
|
|
980
|
+
in a, x1, x2, x3, b over Rational Field,
|
|
981
|
+
{...},
|
|
982
|
+
a,
|
|
983
|
+
b)
|
|
984
|
+
sage: sorted(s2[1].items())
|
|
985
|
+
[(1, x1), (2, x1*b/x2), (3, x3)]
|
|
986
|
+
|
|
987
|
+
On the other hand, we can also apply `T_2` to the image of `s`
|
|
988
|
+
under `T_1`::
|
|
989
|
+
|
|
990
|
+
sage: s12 = V.birational_toggle(2, s1); s12
|
|
991
|
+
(Fraction Field of Multivariate Polynomial Ring
|
|
992
|
+
in a, x1, x2, x3, b over Rational Field,
|
|
993
|
+
{...},
|
|
994
|
+
a,
|
|
995
|
+
b)
|
|
996
|
+
sage: sorted(s12[1].items())
|
|
997
|
+
[(1, a*x2*x3/(x1*x2 + x1*x3)), (2, a*x3*b/(x1*x2 + x1*x3)), (3, x3)]
|
|
998
|
+
|
|
999
|
+
Each toggle is an involution::
|
|
1000
|
+
|
|
1001
|
+
sage: all( V.birational_toggle(i, V.birational_toggle(i, s)) == s
|
|
1002
|
+
....: for i in V )
|
|
1003
|
+
True
|
|
1004
|
+
|
|
1005
|
+
We can also start with a less generic labelling::
|
|
1006
|
+
|
|
1007
|
+
sage: t = (QQ, {1: 3, 2: 6, 3: 7}, 2, 10)
|
|
1008
|
+
sage: t1 = V.birational_toggle(1, t); t1
|
|
1009
|
+
(Rational Field, {...}, 2, 10)
|
|
1010
|
+
sage: sorted(t1[1].items())
|
|
1011
|
+
[(1, 28/13), (2, 6), (3, 7)]
|
|
1012
|
+
sage: t13 = V.birational_toggle(3, t1); t13
|
|
1013
|
+
(Rational Field, {...}, 2, 10)
|
|
1014
|
+
sage: sorted(t13[1].items())
|
|
1015
|
+
[(1, 28/13), (2, 6), (3, 40/13)]
|
|
1016
|
+
|
|
1017
|
+
However, labellings have to be sufficiently generic, lest
|
|
1018
|
+
denominators vanish::
|
|
1019
|
+
|
|
1020
|
+
sage: t = (QQ, {1: 3, 2: 5, 3: -5}, 1, 15)
|
|
1021
|
+
sage: t1 = V.birational_toggle(1, t)
|
|
1022
|
+
Traceback (most recent call last):
|
|
1023
|
+
...
|
|
1024
|
+
ZeroDivisionError: rational division by zero
|
|
1025
|
+
|
|
1026
|
+
We don't get into zero-division issues in the tropical
|
|
1027
|
+
semiring (unless the zero of the tropical semiring appears
|
|
1028
|
+
in the labelling)::
|
|
1029
|
+
|
|
1030
|
+
sage: TT = TropicalSemiring(QQ)
|
|
1031
|
+
sage: t = (TT, {1: TT(2), 2: TT(4), 3: TT(1)}, TT(6), TT(0))
|
|
1032
|
+
sage: t1 = V.birational_toggle(1, t); t1
|
|
1033
|
+
(Tropical semiring over Rational Field, {...}, 6, 0)
|
|
1034
|
+
sage: sorted(t1[1].items())
|
|
1035
|
+
[(1, 8), (2, 4), (3, 1)]
|
|
1036
|
+
sage: t12 = V.birational_toggle(2, t1); t12
|
|
1037
|
+
(Tropical semiring over Rational Field, {...}, 6, 0)
|
|
1038
|
+
sage: sorted(t12[1].items())
|
|
1039
|
+
[(1, 8), (2, 4), (3, 1)]
|
|
1040
|
+
sage: t123 = V.birational_toggle(3, t12); t123
|
|
1041
|
+
(Tropical semiring over Rational Field, {...}, 6, 0)
|
|
1042
|
+
sage: sorted(t123[1].items())
|
|
1043
|
+
[(1, 8), (2, 4), (3, 7)]
|
|
1044
|
+
|
|
1045
|
+
We turn to more interesting posets. Here is the `6`-element
|
|
1046
|
+
poset arising from the weak order on `S_3`::
|
|
1047
|
+
|
|
1048
|
+
sage: P = posets.SymmetricGroupWeakOrderPoset(3)
|
|
1049
|
+
sage: sorted(list(P))
|
|
1050
|
+
['123', '132', '213', '231', '312', '321']
|
|
1051
|
+
sage: t = (TT, {'123': TT(4), '132': TT(2), '213': TT(3),
|
|
1052
|
+
....: '231': TT(1), '321': TT(1), '312': TT(2)}, TT(7), TT(1))
|
|
1053
|
+
sage: t1 = P.birational_toggle('123', t); t1
|
|
1054
|
+
(Tropical semiring over Rational Field, {...}, 7, 1)
|
|
1055
|
+
sage: sorted(t1[1].items())
|
|
1056
|
+
[('123', 6), ('132', 2), ('213', 3), ('231', 1), ('312', 2), ('321', 1)]
|
|
1057
|
+
sage: t13 = P.birational_toggle('213', t1); t13
|
|
1058
|
+
(Tropical semiring over Rational Field, {...}, 7, 1)
|
|
1059
|
+
sage: sorted(t13[1].items())
|
|
1060
|
+
[('123', 6), ('132', 2), ('213', 4), ('231', 1), ('312', 2), ('321', 1)]
|
|
1061
|
+
|
|
1062
|
+
Let us verify on this example some basic properties of
|
|
1063
|
+
toggles. First of all, again let us check that `T_v` is an
|
|
1064
|
+
involution for every `v`::
|
|
1065
|
+
|
|
1066
|
+
sage: all( P.birational_toggle(v, P.birational_toggle(v, t)) == t
|
|
1067
|
+
....: for v in P )
|
|
1068
|
+
True
|
|
1069
|
+
|
|
1070
|
+
Furthermore, two toggles `T_v` and `T_w` commute unless
|
|
1071
|
+
one of `v` or `w` covers the other::
|
|
1072
|
+
|
|
1073
|
+
sage: all( P.covers(v, w) or P.covers(w, v)
|
|
1074
|
+
....: or P.birational_toggle(v, P.birational_toggle(w, t))
|
|
1075
|
+
....: == P.birational_toggle(w, P.birational_toggle(v, t))
|
|
1076
|
+
....: for v in P for w in P )
|
|
1077
|
+
True
|
|
1078
|
+
|
|
1079
|
+
TESTS:
|
|
1080
|
+
|
|
1081
|
+
Setting ``facade`` to ``False`` does not break
|
|
1082
|
+
``birational_toggle``::
|
|
1083
|
+
|
|
1084
|
+
sage: P = Poset({'x': ['y', 'w'], 'y': ['z'], 'w': ['z']}, facade=False)
|
|
1085
|
+
sage: lex = ['x', 'y', 'w', 'z']
|
|
1086
|
+
sage: t = P.birational_free_labelling(linear_extension=lex)
|
|
1087
|
+
sage: all( P.birational_toggle(v, P.birational_toggle(v, t)) == t
|
|
1088
|
+
....: for v in P )
|
|
1089
|
+
True
|
|
1090
|
+
sage: t4 = P.birational_toggle(P('z'), t); t4
|
|
1091
|
+
(Fraction Field of Multivariate Polynomial Ring
|
|
1092
|
+
in a, x1, x2, x3, x4, b over Rational Field,
|
|
1093
|
+
{...},
|
|
1094
|
+
a,
|
|
1095
|
+
b)
|
|
1096
|
+
sage: t4[1][P('x')]
|
|
1097
|
+
x1
|
|
1098
|
+
sage: t4[1][P('y')]
|
|
1099
|
+
x2
|
|
1100
|
+
sage: t4[1][P('w')]
|
|
1101
|
+
x3
|
|
1102
|
+
sage: t4[1][P('z')]
|
|
1103
|
+
(x2*b + x3*b)/x4
|
|
1104
|
+
|
|
1105
|
+
The one-element poset::
|
|
1106
|
+
|
|
1107
|
+
sage: P = Poset({8: []})
|
|
1108
|
+
sage: t = P.birational_free_labelling()
|
|
1109
|
+
sage: t8 = P.birational_toggle(8, t); t8
|
|
1110
|
+
(Fraction Field of Multivariate Polynomial Ring in a, x1, b over Rational Field,
|
|
1111
|
+
{...},
|
|
1112
|
+
a,
|
|
1113
|
+
b)
|
|
1114
|
+
sage: t8[1][8]
|
|
1115
|
+
a*b/x1
|
|
1116
|
+
"""
|
|
1117
|
+
FF = labelling[0] # base field
|
|
1118
|
+
a = labelling[2] # label at `0 \in \widehat{P}`
|
|
1119
|
+
b = labelling[3]
|
|
1120
|
+
newdict = labelling[1].copy()
|
|
1121
|
+
# Construct the harmonic sum ``x`` of the labels at the
|
|
1122
|
+
# elements covering ``v``:
|
|
1123
|
+
uppers = self.upper_covers(v)
|
|
1124
|
+
if len(uppers) == 0:
|
|
1125
|
+
x = FF.one() / b
|
|
1126
|
+
else:
|
|
1127
|
+
x = FF.sum(FF.one() / newdict[j] for j in uppers)
|
|
1128
|
+
# ``FF.sum``, not ``sum``, see trac #15591.
|
|
1129
|
+
x = FF.one() / x
|
|
1130
|
+
# Construct the sum ``y`` of the labels at the elements
|
|
1131
|
+
# covered by ``v``:
|
|
1132
|
+
lowers = self.lower_covers(v)
|
|
1133
|
+
if len(lowers) == 0:
|
|
1134
|
+
y = a
|
|
1135
|
+
else:
|
|
1136
|
+
y = FF.sum(newdict[j] for j in lowers)
|
|
1137
|
+
# Now, transform the label at v:
|
|
1138
|
+
newdict[v] = x * y / newdict[v]
|
|
1139
|
+
return (FF, newdict, a, b)
|
|
1140
|
+
|
|
1141
|
+
def birational_toggles(self, vs, labelling):
|
|
1142
|
+
r"""
|
|
1143
|
+
Return the result of applying a sequence of birational
|
|
1144
|
+
toggles (specified by ``vs``) to the `\mathbf{K}`-labelling
|
|
1145
|
+
``labelling`` of the poset ``self``.
|
|
1146
|
+
|
|
1147
|
+
See the documentation of :meth:`birational_free_labelling`
|
|
1148
|
+
for a definition of birational toggles and `\mathbf{K}`-labellings
|
|
1149
|
+
and for an explanation of how `\mathbf{K}`-labellings are to be
|
|
1150
|
+
encoded to be understood by Sage. This implementation allows
|
|
1151
|
+
`\mathbf{K}` to be a semifield, not just a field. The birational
|
|
1152
|
+
`v`-toggle is only a rational map, so an exception (most
|
|
1153
|
+
likely, :exc:`ZeroDivisionError`) will be thrown if the
|
|
1154
|
+
denominator is zero.
|
|
1155
|
+
|
|
1156
|
+
INPUT:
|
|
1157
|
+
|
|
1158
|
+
- ``vs`` -- an iterable comprising elements of ``self``
|
|
1159
|
+
(which must have ``self`` as parent if ``self`` is a
|
|
1160
|
+
``facade=False`` poset)
|
|
1161
|
+
|
|
1162
|
+
- ``labelling`` -- a `\mathbf{K}`-labelling of ``self`` in the
|
|
1163
|
+
sense as defined in the documentation of
|
|
1164
|
+
:meth:`birational_free_labelling`
|
|
1165
|
+
|
|
1166
|
+
OUTPUT:
|
|
1167
|
+
|
|
1168
|
+
The `\mathbf{K}`-labelling `T_{v_n} T_{v_{n-1}} \cdots T_{v_1} f`
|
|
1169
|
+
of ``self``, where `f` is ``labelling`` and
|
|
1170
|
+
`(v_1, v_2, \ldots, v_n)` is ``vs`` (written as list).
|
|
1171
|
+
|
|
1172
|
+
EXAMPLES::
|
|
1173
|
+
|
|
1174
|
+
sage: P = posets.SymmetricGroupBruhatOrderPoset(3)
|
|
1175
|
+
sage: sorted(list(P))
|
|
1176
|
+
['123', '132', '213', '231', '312', '321']
|
|
1177
|
+
sage: TT = TropicalSemiring(ZZ)
|
|
1178
|
+
sage: t = (TT, {'123': TT(4), '132': TT(2), '213': TT(3),
|
|
1179
|
+
....: '231': TT(1), '321': TT(1), '312': TT(2)}, TT(7), TT(1))
|
|
1180
|
+
sage: tA = P.birational_toggles(['123', '231', '312'], t); tA
|
|
1181
|
+
(Tropical semiring over Integer Ring, {...}, 7, 1)
|
|
1182
|
+
sage: sorted(tA[1].items())
|
|
1183
|
+
[('123', 6), ('132', 2), ('213', 3), ('231', 2), ('312', 1), ('321', 1)]
|
|
1184
|
+
sage: tAB = P.birational_toggles(['132', '213', '321'], tA); tAB
|
|
1185
|
+
(Tropical semiring over Integer Ring, {...}, 7, 1)
|
|
1186
|
+
sage: sorted(tAB[1].items())
|
|
1187
|
+
[('123', 6), ('132', 6), ('213', 5), ('231', 2), ('312', 1), ('321', 1)]
|
|
1188
|
+
|
|
1189
|
+
sage: P = Poset({1: [2, 3], 2: [4], 3: [4]})
|
|
1190
|
+
sage: Qx = PolynomialRing(QQ, 'x').fraction_field()
|
|
1191
|
+
sage: x = Qx.gen()
|
|
1192
|
+
sage: t = (Qx, {1: 1, 2: x, 3: (x+1)/x, 4: x^2}, 1, 1)
|
|
1193
|
+
sage: t1 = P.birational_toggles((i for i in range(1, 5)), t); t1
|
|
1194
|
+
(Fraction Field of Univariate Polynomial Ring in x over Rational Field,
|
|
1195
|
+
{...},
|
|
1196
|
+
1,
|
|
1197
|
+
1)
|
|
1198
|
+
sage: sorted(t1[1].items())
|
|
1199
|
+
[(1, (x^2 + x)/(x^2 + x + 1)),
|
|
1200
|
+
(2, (x^3 + x^2)/(x^2 + x + 1)),
|
|
1201
|
+
(3, x^4/(x^2 + x + 1)), (4, 1)]
|
|
1202
|
+
sage: t2 = P.birational_toggles(reversed(range(1, 5)), t)
|
|
1203
|
+
sage: sorted(t2[1].items())
|
|
1204
|
+
[(1, 1/x^2), (2, (x^2 + x + 1)/x^4), (3, (x^2 + x + 1)/(x^3 + x^2)),
|
|
1205
|
+
(4, (x^2 + x + 1)/x^3)]
|
|
1206
|
+
|
|
1207
|
+
Facade set to ``False`` works::
|
|
1208
|
+
|
|
1209
|
+
sage: P = Poset({'x': ['y', 'w'], 'y': ['z'], 'w': ['z']}, facade=False)
|
|
1210
|
+
sage: lex = ['x', 'y', 'w', 'z']
|
|
1211
|
+
sage: t = P.birational_free_labelling(linear_extension=lex)
|
|
1212
|
+
sage: sorted(P.birational_toggles([P('x'), P('y')], t)[1].items())
|
|
1213
|
+
[(x, a*x2*x3/(x1*x2 + x1*x3)), (y, a*x3*x4/(x1*x2 + x1*x3)), (w, x3), (z, x4)]
|
|
1214
|
+
"""
|
|
1215
|
+
l = labelling
|
|
1216
|
+
for v in vs:
|
|
1217
|
+
l = self.birational_toggle(v, l)
|
|
1218
|
+
return l
|
|
1219
|
+
|
|
1220
|
+
def birational_rowmotion(self, labelling):
|
|
1221
|
+
r"""
|
|
1222
|
+
Return the result of applying birational rowmotion to the
|
|
1223
|
+
`\mathbf{K}`-labelling ``labelling`` of the poset ``self``.
|
|
1224
|
+
|
|
1225
|
+
See the documentation of :meth:`birational_free_labelling`
|
|
1226
|
+
for a definition of birational rowmotion and
|
|
1227
|
+
`\mathbf{K}`-labellings and for an explanation of how
|
|
1228
|
+
`\mathbf{K}`-labellings are to be encoded to be understood
|
|
1229
|
+
by Sage. This implementation allows `\mathbf{K}` to be a
|
|
1230
|
+
semifield, not just a field. Birational rowmotion is only
|
|
1231
|
+
a rational map, so an exception (most likely,
|
|
1232
|
+
:exc:`ZeroDivisionError`) will be thrown if the
|
|
1233
|
+
denominator is zero.
|
|
1234
|
+
|
|
1235
|
+
INPUT:
|
|
1236
|
+
|
|
1237
|
+
- ``labelling`` -- a `\mathbf{K}`-labelling of ``self`` in the
|
|
1238
|
+
sense as defined in the documentation of
|
|
1239
|
+
:meth:`birational_free_labelling`
|
|
1240
|
+
|
|
1241
|
+
OUTPUT:
|
|
1242
|
+
|
|
1243
|
+
The image of the `\mathbf{K}`-labelling `f` under birational
|
|
1244
|
+
rowmotion.
|
|
1245
|
+
|
|
1246
|
+
EXAMPLES::
|
|
1247
|
+
|
|
1248
|
+
sage: P = Poset({1: [2, 3], 2: [4], 3: [4]})
|
|
1249
|
+
sage: lex = [1, 2, 3, 4]
|
|
1250
|
+
sage: t = P.birational_free_labelling(linear_extension=lex); t
|
|
1251
|
+
(Fraction Field of Multivariate Polynomial Ring in a, x1, x2, x3, x4, b over Rational Field,
|
|
1252
|
+
{...},
|
|
1253
|
+
a,
|
|
1254
|
+
b)
|
|
1255
|
+
sage: sorted(t[1].items())
|
|
1256
|
+
[(1, x1), (2, x2), (3, x3), (4, x4)]
|
|
1257
|
+
sage: t = P.birational_rowmotion(t); t
|
|
1258
|
+
(Fraction Field of Multivariate Polynomial Ring in a, x1, x2, x3, x4, b over Rational Field,
|
|
1259
|
+
{...},
|
|
1260
|
+
a,
|
|
1261
|
+
b)
|
|
1262
|
+
sage: sorted(t[1].items())
|
|
1263
|
+
[(1, a*b/x4), (2, (x1*x2*b + x1*x3*b)/(x2*x4)),
|
|
1264
|
+
(3, (x1*x2*b + x1*x3*b)/(x3*x4)), (4, (x2*b + x3*b)/x4)]
|
|
1265
|
+
|
|
1266
|
+
A result of [GR2013]_ states that applying birational rowmotion
|
|
1267
|
+
`n+m` times to a `\mathbf{K}`-labelling `f` of the poset
|
|
1268
|
+
`[n] \times [m]` gives back `f`. Let us check this::
|
|
1269
|
+
|
|
1270
|
+
sage: def test_rectangle_periodicity(n, m, k):
|
|
1271
|
+
....: P = posets.ChainPoset(n).product(posets.ChainPoset(m))
|
|
1272
|
+
....: t0 = P.birational_free_labelling(P)
|
|
1273
|
+
....: t = t0
|
|
1274
|
+
....: for i in range(k):
|
|
1275
|
+
....: t = P.birational_rowmotion(t)
|
|
1276
|
+
....: return t == t0
|
|
1277
|
+
sage: test_rectangle_periodicity(2, 2, 4) # needs sage.modules
|
|
1278
|
+
True
|
|
1279
|
+
sage: test_rectangle_periodicity(2, 2, 2) # needs sage.modules
|
|
1280
|
+
False
|
|
1281
|
+
sage: test_rectangle_periodicity(2, 3, 5) # long time # needs sage.modules
|
|
1282
|
+
True
|
|
1283
|
+
|
|
1284
|
+
While computations with the birational free labelling quickly
|
|
1285
|
+
run out of memory due to the complexity of the rational
|
|
1286
|
+
functions involved, it is computationally cheap to check
|
|
1287
|
+
properties of birational rowmotion on examples in the tropical
|
|
1288
|
+
semiring::
|
|
1289
|
+
|
|
1290
|
+
sage: def test_rectangle_periodicity_tropical(n, m, k):
|
|
1291
|
+
....: P = posets.ChainPoset(n).product(posets.ChainPoset(m))
|
|
1292
|
+
....: TT = TropicalSemiring(ZZ)
|
|
1293
|
+
....: t0 = (TT, {v: TT(randint(0, 99)) for v in P}, TT(0), TT(124))
|
|
1294
|
+
....: t = t0
|
|
1295
|
+
....: for i in range(k):
|
|
1296
|
+
....: t = P.birational_rowmotion(t)
|
|
1297
|
+
....: return t == t0
|
|
1298
|
+
sage: test_rectangle_periodicity_tropical(7, 6, 13) # needs sage.modules
|
|
1299
|
+
True
|
|
1300
|
+
|
|
1301
|
+
Tropicalization is also what relates birational rowmotion to
|
|
1302
|
+
classical rowmotion on order ideals. In fact, if `T` denotes
|
|
1303
|
+
the :class:`tropical semiring
|
|
1304
|
+
<sage.rings.semirings.tropical_semiring.TropicalSemiring>` of
|
|
1305
|
+
`\ZZ` and `P` is a finite poset, then we can define an embedding
|
|
1306
|
+
`\phi` from the set `J(P)` of all order ideals of `P` into the
|
|
1307
|
+
set `T^{\widehat{P}}` of all `T`-labellings of `P` by sending
|
|
1308
|
+
every `I \in J(P)` to the indicator function of `I` extended by
|
|
1309
|
+
the value `1` at the element `0` and the value `0` at the
|
|
1310
|
+
element `1`. This map `\phi` has the property that
|
|
1311
|
+
`R \circ \phi = \phi \circ r`, where `R` denotes birational
|
|
1312
|
+
rowmotion, and `r` denotes :meth:`classical rowmotion <rowmotion>`
|
|
1313
|
+
on `J(P)`. An example::
|
|
1314
|
+
|
|
1315
|
+
sage: P = posets.IntegerPartitions(5)
|
|
1316
|
+
sage: TT = TropicalSemiring(ZZ)
|
|
1317
|
+
sage: def indicator_labelling(I):
|
|
1318
|
+
....: # send order ideal `I` to a `T`-labelling of `P`.
|
|
1319
|
+
....: dct = {v: TT(v in I) for v in P}
|
|
1320
|
+
....: return (TT, dct, TT(1), TT(0))
|
|
1321
|
+
sage: all(indicator_labelling(P.rowmotion(I)) # needs sage.modules
|
|
1322
|
+
....: == P.birational_rowmotion(indicator_labelling(I))
|
|
1323
|
+
....: for I in P.order_ideals_lattice(facade=True))
|
|
1324
|
+
True
|
|
1325
|
+
|
|
1326
|
+
TESTS:
|
|
1327
|
+
|
|
1328
|
+
Facade set to false works::
|
|
1329
|
+
|
|
1330
|
+
sage: P = Poset({1: [2, 3], 2: [4], 3: [4]}, facade=False)
|
|
1331
|
+
sage: lex = [1, 2, 3, 4]
|
|
1332
|
+
sage: t = P.birational_free_labelling(linear_extension=lex); t
|
|
1333
|
+
(Fraction Field of Multivariate Polynomial Ring in a, x1, x2, x3, x4, b over Rational Field,
|
|
1334
|
+
{...},
|
|
1335
|
+
a,
|
|
1336
|
+
b)
|
|
1337
|
+
sage: t = P.birational_rowmotion(t); t
|
|
1338
|
+
(Fraction Field of Multivariate Polynomial Ring in a, x1, x2, x3, x4, b over Rational Field,
|
|
1339
|
+
{...},
|
|
1340
|
+
a,
|
|
1341
|
+
b)
|
|
1342
|
+
sage: t[1][P(2)]
|
|
1343
|
+
(x1*x2*b + x1*x3*b)/(x2*x4)
|
|
1344
|
+
sage: t = P.birational_rowmotion(t)
|
|
1345
|
+
sage: t[1][P(2)]
|
|
1346
|
+
a*b/x3
|
|
1347
|
+
"""
|
|
1348
|
+
l = labelling
|
|
1349
|
+
for v in reversed(self.linear_extension()):
|
|
1350
|
+
l = self.birational_toggle(v, l)
|
|
1351
|
+
return l
|
|
1352
|
+
|
|
1353
|
+
def panyushev_orbits(self, element_constructor=set):
|
|
1354
|
+
r"""
|
|
1355
|
+
Return the Panyushev orbits of antichains in ``self``.
|
|
1356
|
+
|
|
1357
|
+
The Panyushev orbit of an antichain is its orbit under
|
|
1358
|
+
Panyushev complementation (see
|
|
1359
|
+
:meth:`panyushev_complement`).
|
|
1360
|
+
|
|
1361
|
+
INPUT:
|
|
1362
|
+
|
|
1363
|
+
- ``element_constructor`` -- (default: ``set``) a type
|
|
1364
|
+
constructor (``set``, ``tuple``, ``list``, ``frozenset``,
|
|
1365
|
+
``iter``, etc.) which is to be applied to the antichains
|
|
1366
|
+
before they are returned
|
|
1367
|
+
|
|
1368
|
+
OUTPUT:
|
|
1369
|
+
|
|
1370
|
+
- the partition of the set of all antichains of ``self`` into
|
|
1371
|
+
orbits under Panyushev complementation. This is returned as
|
|
1372
|
+
a list of lists ``L`` such that for each ``L`` and ``i``,
|
|
1373
|
+
cyclically:
|
|
1374
|
+
``self.order_ideal_complement_generators(L[i]) == L[i+1]``.
|
|
1375
|
+
The entries ``L[i]`` are sets by default, but depending on
|
|
1376
|
+
the optional keyword variable ``element_constructors``
|
|
1377
|
+
they can also be tuples, lists etc.
|
|
1378
|
+
|
|
1379
|
+
EXAMPLES::
|
|
1380
|
+
|
|
1381
|
+
sage: # needs sage.modules
|
|
1382
|
+
sage: P = Poset( ( [1,2,3], [ [1,3], [2,3] ] ) )
|
|
1383
|
+
sage: orb = P.panyushev_orbits()
|
|
1384
|
+
sage: sorted(sorted(o) for o in orb)
|
|
1385
|
+
[[set(), {1, 2}, {3}], [{2}, {1}]]
|
|
1386
|
+
sage: orb = P.panyushev_orbits(element_constructor=list)
|
|
1387
|
+
sage: sorted(sorted(o) for o in orb)
|
|
1388
|
+
[[[], [1, 2], [3]], [[1], [2]]]
|
|
1389
|
+
sage: orb = P.panyushev_orbits(element_constructor=frozenset)
|
|
1390
|
+
sage: sorted(sorted(o) for o in orb)
|
|
1391
|
+
[[frozenset(), frozenset({1, 2}), frozenset({3})],
|
|
1392
|
+
[frozenset({2}), frozenset({1})]]
|
|
1393
|
+
sage: orb = P.panyushev_orbits(element_constructor=tuple)
|
|
1394
|
+
sage: sorted(sorted(o) for o in orb)
|
|
1395
|
+
[[(), (1, 2), (3,)], [(1,), (2,)]]
|
|
1396
|
+
sage: P = Poset( {} )
|
|
1397
|
+
sage: P.panyushev_orbits()
|
|
1398
|
+
[[set()]]
|
|
1399
|
+
"""
|
|
1400
|
+
# TODO: implement a generic function taking a set and
|
|
1401
|
+
# bijections on this set, and returning the orbits.
|
|
1402
|
+
AC = set(self.antichains(element_constructor=frozenset))
|
|
1403
|
+
orbits = []
|
|
1404
|
+
while AC:
|
|
1405
|
+
A = AC.pop()
|
|
1406
|
+
orbit = [A]
|
|
1407
|
+
while True:
|
|
1408
|
+
A = frozenset(self.order_ideal_complement_generators(A))
|
|
1409
|
+
if A not in AC:
|
|
1410
|
+
break
|
|
1411
|
+
orbit.append(A)
|
|
1412
|
+
AC.remove(A)
|
|
1413
|
+
orbits.append([element_constructor(elt) for elt in orbit])
|
|
1414
|
+
return orbits
|
|
1415
|
+
|
|
1416
|
+
def rowmotion_orbits(self, element_constructor=set):
|
|
1417
|
+
r"""
|
|
1418
|
+
Return the rowmotion orbits of order ideals in ``self``.
|
|
1419
|
+
|
|
1420
|
+
The rowmotion orbit of an order ideal is its orbit under
|
|
1421
|
+
rowmotion (see :meth:`rowmotion`).
|
|
1422
|
+
|
|
1423
|
+
INPUT:
|
|
1424
|
+
|
|
1425
|
+
- ``element_constructor`` -- (default: ``set``) a type
|
|
1426
|
+
constructor (``set``, ``tuple``, ``list``, ``frozenset``,
|
|
1427
|
+
``iter``, etc.) which is to be applied to the antichains
|
|
1428
|
+
before they are returned
|
|
1429
|
+
|
|
1430
|
+
OUTPUT:
|
|
1431
|
+
|
|
1432
|
+
- the partition of the set of all order ideals of ``self``
|
|
1433
|
+
into orbits under rowmotion. This is returned as
|
|
1434
|
+
a list of lists ``L`` such that for each ``L`` and ``i``,
|
|
1435
|
+
cyclically: ``self.rowmotion(L[i]) == L[i+1]``.
|
|
1436
|
+
The entries ``L[i]`` are sets by default, but depending on
|
|
1437
|
+
the optional keyword variable ``element_constructors``
|
|
1438
|
+
they can also be tuples, lists etc.
|
|
1439
|
+
|
|
1440
|
+
EXAMPLES::
|
|
1441
|
+
|
|
1442
|
+
sage: # needs sage.modules
|
|
1443
|
+
sage: P = Poset( {1: [2, 3], 2: [], 3: [], 4: [2]} )
|
|
1444
|
+
sage: sorted(len(o) for o in P.rowmotion_orbits())
|
|
1445
|
+
[3, 5]
|
|
1446
|
+
sage: orb = P.rowmotion_orbits(element_constructor=list)
|
|
1447
|
+
sage: sorted(sorted(e) for e in orb)
|
|
1448
|
+
[[[], [4, 1], [4, 1, 2, 3]], [[1], [1, 3], [4], [4, 1, 2], [4, 1, 3]]]
|
|
1449
|
+
sage: orb = P.rowmotion_orbits(element_constructor=tuple)
|
|
1450
|
+
sage: sorted(sorted(e) for e in orb)
|
|
1451
|
+
[[(), (4, 1), (4, 1, 2, 3)], [(1,), (1, 3), (4,), (4, 1, 2), (4, 1, 3)]]
|
|
1452
|
+
sage: P = Poset({})
|
|
1453
|
+
sage: P.rowmotion_orbits(element_constructor=tuple)
|
|
1454
|
+
[[()]]
|
|
1455
|
+
"""
|
|
1456
|
+
pan_orbits = self.panyushev_orbits(element_constructor=list)
|
|
1457
|
+
return [[element_constructor(self.order_ideal(oideal))
|
|
1458
|
+
for oideal in orbit] for orbit in pan_orbits]
|
|
1459
|
+
|
|
1460
|
+
def rowmotion_orbits_plots(self):
|
|
1461
|
+
r"""
|
|
1462
|
+
Return plots of the rowmotion orbits of order ideals in ``self``.
|
|
1463
|
+
|
|
1464
|
+
The rowmotion orbit of an order ideal is its orbit under
|
|
1465
|
+
rowmotion (see :meth:`rowmotion`).
|
|
1466
|
+
|
|
1467
|
+
EXAMPLES::
|
|
1468
|
+
|
|
1469
|
+
sage: # needs sage.modules sage.plot
|
|
1470
|
+
sage: P = Poset( {1: [2, 3], 2: [], 3: [], 4: [2]} )
|
|
1471
|
+
sage: P.rowmotion_orbits_plots()
|
|
1472
|
+
Graphics Array of size 2 x 5
|
|
1473
|
+
sage: P = Poset({})
|
|
1474
|
+
sage: P.rowmotion_orbits_plots()
|
|
1475
|
+
Graphics Array of size 1 x 1
|
|
1476
|
+
"""
|
|
1477
|
+
from sage.plot.plot import graphics_array
|
|
1478
|
+
plot_of_orb_plots = []
|
|
1479
|
+
max_orbit_size = 0
|
|
1480
|
+
for orb in self.rowmotion_orbits():
|
|
1481
|
+
orb_plots = []
|
|
1482
|
+
max_orbit_size = max(len(orb), max_orbit_size)
|
|
1483
|
+
for oi in orb:
|
|
1484
|
+
oiplot = self.order_ideal_plot(oi)
|
|
1485
|
+
orb_plots.append(oiplot)
|
|
1486
|
+
plot_of_orb_plots.append(orb_plots)
|
|
1487
|
+
return graphics_array(plot_of_orb_plots, ncols=max_orbit_size)
|
|
1488
|
+
|
|
1489
|
+
def toggling_orbits(self, vs, element_constructor=set):
|
|
1490
|
+
r"""
|
|
1491
|
+
Return the orbits of order ideals in ``self`` under the
|
|
1492
|
+
operation of toggling the vertices ``vs[0], vs[1], ...``
|
|
1493
|
+
in this order.
|
|
1494
|
+
|
|
1495
|
+
See :meth:`~sage.categories.posets.Posets.ParentMethods.order_ideal_toggle` for a definition of toggling.
|
|
1496
|
+
|
|
1497
|
+
.. WARNING::
|
|
1498
|
+
|
|
1499
|
+
The orbits are those under the composition of toggles,
|
|
1500
|
+
*not* under the single toggles themselves. Thus, for
|
|
1501
|
+
example, if ``vs == [1,2]``, then the orbits have the
|
|
1502
|
+
form `(I, T_2 T_1 I, T_2 T_1 T_2 T_1 I, \ldots)`
|
|
1503
|
+
(where `I` denotes an order ideal and `T_i` means
|
|
1504
|
+
toggling at `i`) rather than
|
|
1505
|
+
`(I, T_1 I, T_2 T_1 I, T_1 T_2 T_1 I, \ldots)`.
|
|
1506
|
+
|
|
1507
|
+
INPUT:
|
|
1508
|
+
|
|
1509
|
+
- ``vs`` -- a list (or other iterable) of elements of ``self``
|
|
1510
|
+
(but since the output depends on the order, sets should
|
|
1511
|
+
not be used as ``vs``).
|
|
1512
|
+
|
|
1513
|
+
OUTPUT:
|
|
1514
|
+
|
|
1515
|
+
A partition of the order ideals of ``self``, as a list of
|
|
1516
|
+
sets ``L`` such that for each ``L`` and ``i``, cyclically:
|
|
1517
|
+
``self.order_ideal_toggles(L[i], vs) == L[i+1]``.
|
|
1518
|
+
|
|
1519
|
+
EXAMPLES::
|
|
1520
|
+
|
|
1521
|
+
sage: P = Poset( {1: [2, 4], 2: [], 3: [4], 4: []} )
|
|
1522
|
+
sage: sorted(len(o) for o in P.toggling_orbits([1, 2])) # needs sage.modules
|
|
1523
|
+
[2, 3, 3]
|
|
1524
|
+
sage: P = Poset( {1: [3], 2: [1, 4], 3: [], 4: [3]} )
|
|
1525
|
+
sage: sorted(len(o) for o in P.toggling_orbits((1, 2, 4, 3))) # needs sage.modules
|
|
1526
|
+
[3, 3]
|
|
1527
|
+
"""
|
|
1528
|
+
# TODO: implement a generic function taking a set and
|
|
1529
|
+
# bijections on this set, and returning the orbits.
|
|
1530
|
+
OI = set(self.order_ideals_lattice(facade=True))
|
|
1531
|
+
orbits = []
|
|
1532
|
+
while OI:
|
|
1533
|
+
A = OI.pop()
|
|
1534
|
+
orbit = [ A ]
|
|
1535
|
+
while True:
|
|
1536
|
+
A = self.order_ideal_toggles(A, vs)
|
|
1537
|
+
if A not in OI:
|
|
1538
|
+
break
|
|
1539
|
+
orbit.append( A )
|
|
1540
|
+
OI.remove( A )
|
|
1541
|
+
orbits.append([element_constructor(_) for _ in orbit])
|
|
1542
|
+
return orbits
|
|
1543
|
+
|
|
1544
|
+
def toggling_orbits_plots(self, vs):
|
|
1545
|
+
r"""
|
|
1546
|
+
Return plots of the orbits of order ideals in ``self`` under the
|
|
1547
|
+
operation of toggling the vertices ``vs[0], vs[1], ...``
|
|
1548
|
+
in this order.
|
|
1549
|
+
|
|
1550
|
+
See :meth:`toggling_orbits` for more information.
|
|
1551
|
+
|
|
1552
|
+
EXAMPLES::
|
|
1553
|
+
|
|
1554
|
+
sage: # needs sage.modules sage.plot
|
|
1555
|
+
sage: P = Poset( {1: [2, 3], 2: [], 3: [], 4: [2]} )
|
|
1556
|
+
sage: P.toggling_orbits_plots([1,2,3,4])
|
|
1557
|
+
Graphics Array of size 2 x 5
|
|
1558
|
+
sage: P = Poset({})
|
|
1559
|
+
sage: P.toggling_orbits_plots([])
|
|
1560
|
+
Graphics Array of size 1 x 1
|
|
1561
|
+
"""
|
|
1562
|
+
from sage.plot.plot import graphics_array
|
|
1563
|
+
plot_of_orb_plots = []
|
|
1564
|
+
max_orbit_size = 0
|
|
1565
|
+
for orb in self.toggling_orbits(vs):
|
|
1566
|
+
orb_plots = []
|
|
1567
|
+
max_orbit_size = max(len(orb), max_orbit_size)
|
|
1568
|
+
for oi in orb:
|
|
1569
|
+
oiplot = self.order_ideal_plot(oi)
|
|
1570
|
+
orb_plots.append(oiplot)
|
|
1571
|
+
plot_of_orb_plots.append(orb_plots)
|
|
1572
|
+
return graphics_array(plot_of_orb_plots, ncols=max_orbit_size)
|
|
1573
|
+
|
|
1574
|
+
def panyushev_orbit_iter(self, antichain, element_constructor=set,
|
|
1575
|
+
stop=True, check=True):
|
|
1576
|
+
r"""
|
|
1577
|
+
Iterate over the Panyushev orbit of an antichain
|
|
1578
|
+
``antichain`` of ``self``.
|
|
1579
|
+
|
|
1580
|
+
The Panyushev orbit of an antichain is its orbit under
|
|
1581
|
+
Panyushev complementation (see
|
|
1582
|
+
:meth:`panyushev_complement`).
|
|
1583
|
+
|
|
1584
|
+
INPUT:
|
|
1585
|
+
|
|
1586
|
+
- ``antichain`` -- an antichain of ``self``, given as an
|
|
1587
|
+
iterable
|
|
1588
|
+
|
|
1589
|
+
- ``element_constructor`` -- a type constructor (default: ``set``).
|
|
1590
|
+
Can be ``set``, ``tuple``, ``list``, ``frozenset``, ``iter``,
|
|
1591
|
+
etc. To be applied to the antichains before they are yielded.
|
|
1592
|
+
|
|
1593
|
+
- ``stop`` -- boolean (default: ``True``); whether the iterator
|
|
1594
|
+
should stop once it completes its cycle (this happens when it is
|
|
1595
|
+
set to ``True``) or go on forever (this happens when it is set to
|
|
1596
|
+
``False``).
|
|
1597
|
+
|
|
1598
|
+
- ``check`` -- boolean (default: ``True``); whether to check
|
|
1599
|
+
``antichain`` for being an antichain
|
|
1600
|
+
|
|
1601
|
+
OUTPUT:
|
|
1602
|
+
|
|
1603
|
+
- an iterator over the orbit of the antichain ``antichain``
|
|
1604
|
+
under Panyushev complementation. This iterator `I` has the
|
|
1605
|
+
property that ``I[0] == antichain`` and each `i` satisfies
|
|
1606
|
+
``self.order_ideal_complement_generators(I[i]) == I[i+1]``,
|
|
1607
|
+
where ``I[i+1]`` has to be understood as ``I[0]`` if it is
|
|
1608
|
+
undefined.
|
|
1609
|
+
The entries ``I[i]`` are sets by default, but depending on
|
|
1610
|
+
the optional keyword variable ``element_constructors``
|
|
1611
|
+
they can also be tuples, lists etc.
|
|
1612
|
+
|
|
1613
|
+
EXAMPLES::
|
|
1614
|
+
|
|
1615
|
+
sage: P = Poset( ( [1,2,3], [ [1,3], [2,3] ] ) )
|
|
1616
|
+
sage: list(P.panyushev_orbit_iter(set([1, 2])))
|
|
1617
|
+
[{1, 2}, {3}, set()]
|
|
1618
|
+
sage: list(P.panyushev_orbit_iter([1, 2]))
|
|
1619
|
+
[{1, 2}, {3}, set()]
|
|
1620
|
+
sage: list(P.panyushev_orbit_iter([2, 1]))
|
|
1621
|
+
[{1, 2}, {3}, set()]
|
|
1622
|
+
sage: list(P.panyushev_orbit_iter(set([1, 2]), element_constructor=list))
|
|
1623
|
+
[[1, 2], [3], []]
|
|
1624
|
+
sage: list(P.panyushev_orbit_iter(set([1, 2]), element_constructor=frozenset))
|
|
1625
|
+
[frozenset({1, 2}), frozenset({3}), frozenset()]
|
|
1626
|
+
sage: list(P.panyushev_orbit_iter(set([1, 2]), element_constructor=tuple))
|
|
1627
|
+
[(1, 2), (3,), ()]
|
|
1628
|
+
|
|
1629
|
+
sage: P = Poset( {} )
|
|
1630
|
+
sage: list(P.panyushev_orbit_iter([]))
|
|
1631
|
+
[set()]
|
|
1632
|
+
|
|
1633
|
+
sage: P = Poset({ 1: [2, 3], 2: [4], 3: [4], 4: [] })
|
|
1634
|
+
sage: Piter = P.panyushev_orbit_iter([2], stop=False)
|
|
1635
|
+
sage: next(Piter)
|
|
1636
|
+
{2}
|
|
1637
|
+
sage: next(Piter)
|
|
1638
|
+
{3}
|
|
1639
|
+
sage: next(Piter)
|
|
1640
|
+
{2}
|
|
1641
|
+
sage: next(Piter)
|
|
1642
|
+
{3}
|
|
1643
|
+
"""
|
|
1644
|
+
# TODO: implement a generic function taking a set and
|
|
1645
|
+
# bijections on this set, and returning an orbit of a given
|
|
1646
|
+
# element.
|
|
1647
|
+
if check:
|
|
1648
|
+
if not self.is_antichain_of_poset(antichain):
|
|
1649
|
+
raise ValueError("the given antichain is not an antichain")
|
|
1650
|
+
starter = set(antichain) # sanitize input
|
|
1651
|
+
yield element_constructor(starter)
|
|
1652
|
+
next = starter
|
|
1653
|
+
if stop:
|
|
1654
|
+
while True:
|
|
1655
|
+
next = self.order_ideal_complement_generators(next)
|
|
1656
|
+
if next == starter:
|
|
1657
|
+
break
|
|
1658
|
+
yield element_constructor(next)
|
|
1659
|
+
else:
|
|
1660
|
+
while True:
|
|
1661
|
+
next = self.order_ideal_complement_generators(next)
|
|
1662
|
+
yield element_constructor(next)
|
|
1663
|
+
|
|
1664
|
+
def rowmotion_orbit_iter(self, oideal, element_constructor=set, stop=True, check=True):
|
|
1665
|
+
r"""
|
|
1666
|
+
Iterate over the rowmotion orbit of an order ideal
|
|
1667
|
+
``oideal`` of ``self``.
|
|
1668
|
+
|
|
1669
|
+
The rowmotion orbit of an order ideal is its orbit under
|
|
1670
|
+
rowmotion (see :meth:`rowmotion`).
|
|
1671
|
+
|
|
1672
|
+
INPUT:
|
|
1673
|
+
|
|
1674
|
+
- ``oideal`` -- an order ideal of ``self``, given as an
|
|
1675
|
+
iterable
|
|
1676
|
+
|
|
1677
|
+
- ``element_constructor`` -- (defaults to ``set``) a type
|
|
1678
|
+
constructor (``set``, ``tuple``, ``list``, ``frozenset``,
|
|
1679
|
+
``iter``, etc.) which is to be applied to the order
|
|
1680
|
+
ideals before they are yielded
|
|
1681
|
+
|
|
1682
|
+
- ``stop`` -- boolean (default: ``True``);
|
|
1683
|
+
whether the iterator should stop once it completes its
|
|
1684
|
+
cycle (this happens when it is set to ``True``) or go on
|
|
1685
|
+
forever (this happens when it is set to ``False``)
|
|
1686
|
+
|
|
1687
|
+
- ``check`` -- boolean (default: ``True``);
|
|
1688
|
+
whether ``oideal`` should be checked for being an
|
|
1689
|
+
order ideal
|
|
1690
|
+
|
|
1691
|
+
OUTPUT:
|
|
1692
|
+
|
|
1693
|
+
- an iterator over the orbit of the order ideal ``oideal``
|
|
1694
|
+
under rowmotion. This iterator `I` has the property that
|
|
1695
|
+
``I[0] == oideal`` and that every `i` satisfies
|
|
1696
|
+
``self.rowmotion(I[i]) == I[i+1]``, where ``I[i+1]`` has
|
|
1697
|
+
to be understood as ``I[0]`` if it is undefined.
|
|
1698
|
+
The entries ``I[i]`` are sets by default, but depending on
|
|
1699
|
+
the optional keyword variable ``element_constructors``
|
|
1700
|
+
they can also be tuples, lists etc.
|
|
1701
|
+
|
|
1702
|
+
EXAMPLES::
|
|
1703
|
+
|
|
1704
|
+
sage: P = Poset( ( [1,2,3], [ [1,3], [2,3] ] ) )
|
|
1705
|
+
sage: list(P.rowmotion_orbit_iter(set([1, 2])))
|
|
1706
|
+
[{1, 2}, {1, 2, 3}, set()]
|
|
1707
|
+
sage: list(P.rowmotion_orbit_iter([1, 2]))
|
|
1708
|
+
[{1, 2}, {1, 2, 3}, set()]
|
|
1709
|
+
sage: list(P.rowmotion_orbit_iter([2, 1]))
|
|
1710
|
+
[{1, 2}, {1, 2, 3}, set()]
|
|
1711
|
+
sage: list(P.rowmotion_orbit_iter(set([1, 2]), element_constructor=list))
|
|
1712
|
+
[[1, 2], [1, 2, 3], []]
|
|
1713
|
+
sage: list(P.rowmotion_orbit_iter(set([1, 2]), element_constructor=frozenset))
|
|
1714
|
+
[frozenset({1, 2}), frozenset({1, 2, 3}), frozenset()]
|
|
1715
|
+
sage: list(P.rowmotion_orbit_iter(set([1, 2]), element_constructor=tuple))
|
|
1716
|
+
[(1, 2), (1, 2, 3), ()]
|
|
1717
|
+
|
|
1718
|
+
sage: P = Poset( {} )
|
|
1719
|
+
sage: list(P.rowmotion_orbit_iter([]))
|
|
1720
|
+
[set()]
|
|
1721
|
+
|
|
1722
|
+
sage: P = Poset({ 1: [2, 3], 2: [4], 3: [4], 4: [] })
|
|
1723
|
+
sage: Piter = P.rowmotion_orbit_iter([1, 2, 3], stop=False)
|
|
1724
|
+
sage: next(Piter)
|
|
1725
|
+
{1, 2, 3}
|
|
1726
|
+
sage: next(Piter)
|
|
1727
|
+
{1, 2, 3, 4}
|
|
1728
|
+
sage: next(Piter)
|
|
1729
|
+
set()
|
|
1730
|
+
sage: next(Piter)
|
|
1731
|
+
{1}
|
|
1732
|
+
sage: next(Piter)
|
|
1733
|
+
{1, 2, 3}
|
|
1734
|
+
|
|
1735
|
+
sage: P = Poset({ 1: [4], 2: [4, 5], 3: [5] })
|
|
1736
|
+
sage: list(P.rowmotion_orbit_iter([1, 2], element_constructor=list))
|
|
1737
|
+
[[1, 2], [1, 2, 3, 4], [2, 3, 5], [1], [2, 3], [1, 2, 3, 5], [1, 2, 4], [3]]
|
|
1738
|
+
"""
|
|
1739
|
+
# TODO: implement a generic function taking a set and
|
|
1740
|
+
# bijections on this set, and returning an orbit of a given
|
|
1741
|
+
# element.
|
|
1742
|
+
if check:
|
|
1743
|
+
if not self.is_order_ideal(oideal):
|
|
1744
|
+
raise ValueError("the given order ideal is not an order ideal")
|
|
1745
|
+
starter = set(oideal) # sanitize input
|
|
1746
|
+
yield element_constructor(starter)
|
|
1747
|
+
next = starter
|
|
1748
|
+
if stop:
|
|
1749
|
+
while True:
|
|
1750
|
+
next = self.rowmotion(next)
|
|
1751
|
+
if next == starter:
|
|
1752
|
+
break
|
|
1753
|
+
yield element_constructor(next)
|
|
1754
|
+
else:
|
|
1755
|
+
while True:
|
|
1756
|
+
next = self.rowmotion(next)
|
|
1757
|
+
yield element_constructor(next)
|
|
1758
|
+
|
|
1759
|
+
def toggling_orbit_iter(self, vs, oideal, element_constructor=set, stop=True, check=True):
|
|
1760
|
+
r"""
|
|
1761
|
+
Iterate over the orbit of an order ideal ``oideal`` of
|
|
1762
|
+
``self`` under the operation of toggling the vertices
|
|
1763
|
+
``vs[0], vs[1], ...`` in this order.
|
|
1764
|
+
|
|
1765
|
+
See :meth:`~sage.categories.posets.Posets.ParentMethods.order_ideal_toggle` for a definition of toggling.
|
|
1766
|
+
|
|
1767
|
+
.. WARNING::
|
|
1768
|
+
|
|
1769
|
+
The orbit is that under the composition of toggles,
|
|
1770
|
+
*not* under the single toggles themselves. Thus, for
|
|
1771
|
+
example, if ``vs == [1,2]``, then the orbit has the
|
|
1772
|
+
form `(I, T_2 T_1 I, T_2 T_1 T_2 T_1 I, \ldots)`
|
|
1773
|
+
(where `I` denotes ``oideal`` and `T_i` means
|
|
1774
|
+
toggling at `i`) rather than
|
|
1775
|
+
`(I, T_1 I, T_2 T_1 I, T_1 T_2 T_1 I, \ldots)`.
|
|
1776
|
+
|
|
1777
|
+
INPUT:
|
|
1778
|
+
|
|
1779
|
+
- ``vs`` -- list (or other iterable) of elements of ``self``
|
|
1780
|
+
(but since the output depends on the order, sets should
|
|
1781
|
+
not be used as ``vs``).
|
|
1782
|
+
|
|
1783
|
+
- ``oideal`` -- an order ideal of ``self``, given as an
|
|
1784
|
+
iterable
|
|
1785
|
+
|
|
1786
|
+
- ``element_constructor`` -- (default: ``set``) a type
|
|
1787
|
+
constructor (``set``, ``tuple``, ``list``, ``frozenset``,
|
|
1788
|
+
``iter``, etc.) which is to be applied to the order
|
|
1789
|
+
ideals before they are yielded.
|
|
1790
|
+
|
|
1791
|
+
- ``stop`` -- boolean (default: ``True``);
|
|
1792
|
+
whether the iterator should stop once it completes its
|
|
1793
|
+
cycle (this happens when it is set to ``True``) or go on
|
|
1794
|
+
forever (this happens when it is set to ``False``).
|
|
1795
|
+
|
|
1796
|
+
- ``check`` -- boolean (default: ``True``);
|
|
1797
|
+
whether ``oideal`` should be checked for being an
|
|
1798
|
+
order ideal.
|
|
1799
|
+
|
|
1800
|
+
OUTPUT:
|
|
1801
|
+
|
|
1802
|
+
- an iterator over the orbit of the order ideal ``oideal``
|
|
1803
|
+
under toggling the vertices in the list ``vs`` in this
|
|
1804
|
+
order. This iterator `I` has the property that
|
|
1805
|
+
``I[0] == oideal`` and that every `i` satisfies
|
|
1806
|
+
``self.order_ideal_toggles(I[i], vs) == I[i+1]``, where
|
|
1807
|
+
``I[i+1]`` has to be understood as ``I[0]`` if it is
|
|
1808
|
+
undefined.
|
|
1809
|
+
The entries ``I[i]`` are sets by default, but depending on
|
|
1810
|
+
the optional keyword variable ``element_constructors``
|
|
1811
|
+
they can also be tuples, lists etc.
|
|
1812
|
+
|
|
1813
|
+
EXAMPLES::
|
|
1814
|
+
|
|
1815
|
+
sage: P = Poset( ( [1,2,3], [ [1,3], [2,3] ] ) )
|
|
1816
|
+
sage: list(P.toggling_orbit_iter([1, 3, 1], set([1, 2])))
|
|
1817
|
+
[{1, 2}]
|
|
1818
|
+
sage: list(P.toggling_orbit_iter([1, 2, 3], set([1, 2])))
|
|
1819
|
+
[{1, 2}, set(), {1, 2, 3}]
|
|
1820
|
+
sage: list(P.toggling_orbit_iter([3, 2, 1], set([1, 2])))
|
|
1821
|
+
[{1, 2}, {1, 2, 3}, set()]
|
|
1822
|
+
sage: list(P.toggling_orbit_iter([3, 2, 1], set([1, 2]),
|
|
1823
|
+
....: element_constructor=list))
|
|
1824
|
+
[[1, 2], [1, 2, 3], []]
|
|
1825
|
+
sage: list(P.toggling_orbit_iter([3, 2, 1], set([1, 2]),
|
|
1826
|
+
....: element_constructor=frozenset))
|
|
1827
|
+
[frozenset({1, 2}), frozenset({1, 2, 3}), frozenset()]
|
|
1828
|
+
sage: list(P.toggling_orbit_iter([3, 2, 1], set([1, 2]),
|
|
1829
|
+
....: element_constructor=tuple))
|
|
1830
|
+
[(1, 2), (1, 2, 3), ()]
|
|
1831
|
+
sage: list(P.toggling_orbit_iter([3, 2, 1], [2, 1],
|
|
1832
|
+
....: element_constructor=tuple))
|
|
1833
|
+
[(1, 2), (1, 2, 3), ()]
|
|
1834
|
+
|
|
1835
|
+
sage: P = Poset( {} )
|
|
1836
|
+
sage: list(P.toggling_orbit_iter([], []))
|
|
1837
|
+
[set()]
|
|
1838
|
+
|
|
1839
|
+
sage: P = Poset({ 1: [2, 3], 2: [4], 3: [4], 4: [] })
|
|
1840
|
+
sage: Piter = P.toggling_orbit_iter([1, 2, 4, 3], [1, 2, 3], stop=False)
|
|
1841
|
+
sage: next(Piter)
|
|
1842
|
+
{1, 2, 3}
|
|
1843
|
+
sage: next(Piter)
|
|
1844
|
+
{1}
|
|
1845
|
+
sage: next(Piter)
|
|
1846
|
+
set()
|
|
1847
|
+
sage: next(Piter)
|
|
1848
|
+
{1, 2, 3}
|
|
1849
|
+
sage: next(Piter)
|
|
1850
|
+
{1}
|
|
1851
|
+
"""
|
|
1852
|
+
# TODO: implement a generic function taking a set and
|
|
1853
|
+
# bijections on this set, and returning an orbit of a given
|
|
1854
|
+
# element.
|
|
1855
|
+
if check:
|
|
1856
|
+
if not self.is_order_ideal(oideal):
|
|
1857
|
+
raise ValueError("the given order ideal is not an order ideal")
|
|
1858
|
+
starter = set(oideal) # sanitize input
|
|
1859
|
+
yield element_constructor(starter)
|
|
1860
|
+
next = starter
|
|
1861
|
+
if stop:
|
|
1862
|
+
while True:
|
|
1863
|
+
next = self.order_ideal_toggles(next, vs)
|
|
1864
|
+
if next == starter:
|
|
1865
|
+
break
|
|
1866
|
+
yield element_constructor(next)
|
|
1867
|
+
else:
|
|
1868
|
+
while True:
|
|
1869
|
+
next = self.order_ideal_toggles(next, vs)
|
|
1870
|
+
yield element_constructor(next)
|
|
1871
|
+
|
|
1872
|
+
def order_ideals_lattice(self, as_ideals=True, facade=None):
|
|
1873
|
+
r"""
|
|
1874
|
+
Return the lattice of order ideals of a poset ``self``,
|
|
1875
|
+
ordered by inclusion.
|
|
1876
|
+
|
|
1877
|
+
The lattice of order ideals of a poset `P` is usually
|
|
1878
|
+
denoted by `J(P)`. Its underlying set is the set of order
|
|
1879
|
+
ideals of `P`, and its partial order is given by
|
|
1880
|
+
inclusion.
|
|
1881
|
+
|
|
1882
|
+
The order ideals of `P` are in a canonical bijection
|
|
1883
|
+
with the antichains of `P`. The bijection maps every
|
|
1884
|
+
order ideal to the antichain formed by its maximal
|
|
1885
|
+
elements. By setting the ``as_ideals`` keyword variable to
|
|
1886
|
+
``False``, one can make this method apply this bijection
|
|
1887
|
+
before returning the lattice.
|
|
1888
|
+
|
|
1889
|
+
INPUT:
|
|
1890
|
+
|
|
1891
|
+
- ``as_ideals`` -- boolean (default: ``True``); if ``True`` returns
|
|
1892
|
+
a poset on the set of order ideals, otherwise on the set
|
|
1893
|
+
of antichains
|
|
1894
|
+
- ``facade`` -- boolean or ``None`` (default); whether to
|
|
1895
|
+
return a facade lattice or not. By default return facade
|
|
1896
|
+
lattice if the poset is a facade poset.
|
|
1897
|
+
|
|
1898
|
+
EXAMPLES::
|
|
1899
|
+
|
|
1900
|
+
sage: # needs sage.modules
|
|
1901
|
+
sage: P = posets.PentagonPoset()
|
|
1902
|
+
sage: P.cover_relations()
|
|
1903
|
+
[[0, 1], [0, 2], [1, 4], [2, 3], [3, 4]]
|
|
1904
|
+
sage: J = P.order_ideals_lattice(); J
|
|
1905
|
+
Finite lattice containing 8 elements
|
|
1906
|
+
sage: sorted(sorted(e) for e in J)
|
|
1907
|
+
[[], [0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4], [0, 2], [0, 2, 3]]
|
|
1908
|
+
|
|
1909
|
+
As a lattice on antichains::
|
|
1910
|
+
|
|
1911
|
+
sage: J2 = P.order_ideals_lattice(False); J2 # needs sage.modules
|
|
1912
|
+
Finite lattice containing 8 elements
|
|
1913
|
+
sage: sorted(J2) # needs sage.modules
|
|
1914
|
+
[(), (0,), (1,), (1, 2), (1, 3), (2,), (3,), (4,)]
|
|
1915
|
+
|
|
1916
|
+
TESTS::
|
|
1917
|
+
|
|
1918
|
+
sage: # needs sage.modules
|
|
1919
|
+
sage: J = posets.DiamondPoset(4, facade=True).order_ideals_lattice(); J
|
|
1920
|
+
Finite lattice containing 6 elements
|
|
1921
|
+
sage: sorted(sorted(e) for e in J)
|
|
1922
|
+
[[], [0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 2]]
|
|
1923
|
+
sage: sorted(sorted(sorted(e) for e in c) for c in J.cover_relations())
|
|
1924
|
+
[[[], [0]], [[0], [0, 1]], [[0], [0, 2]], [[0, 1], [0, 1, 2]], [[0, 1, 2], [0, 1, 2, 3]], [[0, 1, 2], [0, 2]]]
|
|
1925
|
+
|
|
1926
|
+
sage: P = Poset({1: [2]})
|
|
1927
|
+
sage: J_facade = P.order_ideals_lattice() # needs sage.modules
|
|
1928
|
+
sage: J_nonfacade = P.order_ideals_lattice(facade=False) # needs sage.modules
|
|
1929
|
+
sage: type(J_facade[0]) == type(J_nonfacade[0]) # needs sage.modules
|
|
1930
|
+
False
|
|
1931
|
+
"""
|
|
1932
|
+
from sage.combinat.posets.lattices import LatticePoset
|
|
1933
|
+
if facade is None:
|
|
1934
|
+
facade = self._is_facade
|
|
1935
|
+
if as_ideals:
|
|
1936
|
+
from sage.misc.call import attrcall
|
|
1937
|
+
from sage.sets.set import Set
|
|
1938
|
+
ideals = [Set(self.order_ideal(antichain))
|
|
1939
|
+
for antichain in self.antichains()]
|
|
1940
|
+
return LatticePoset((ideals, attrcall("issubset")),
|
|
1941
|
+
facade=facade)
|
|
1942
|
+
else:
|
|
1943
|
+
from sage.misc.cachefunc import cached_function
|
|
1944
|
+
antichains = [tuple(a) for a in self.antichains()]
|
|
1945
|
+
|
|
1946
|
+
@cached_function
|
|
1947
|
+
def is_above(a, xb):
|
|
1948
|
+
return any(self.is_lequal(xa, xb) for xa in a)
|
|
1949
|
+
|
|
1950
|
+
def compare(a, b):
|
|
1951
|
+
return all(is_above(a, xb) for xb in b)
|
|
1952
|
+
return LatticePoset((antichains, compare), facade=facade)
|
|
1953
|
+
|
|
1954
|
+
@abstract_method(optional=True)
|
|
1955
|
+
def antichains(self):
|
|
1956
|
+
r"""
|
|
1957
|
+
Return all antichains of ``self``.
|
|
1958
|
+
|
|
1959
|
+
EXAMPLES::
|
|
1960
|
+
|
|
1961
|
+
sage: A = posets.PentagonPoset().antichains(); A # needs sage.modules
|
|
1962
|
+
Set of antichains of Finite lattice containing 5 elements
|
|
1963
|
+
sage: list(A) # needs sage.modules
|
|
1964
|
+
[[], [0], [1], [1, 2], [1, 3], [2], [3], [4]]
|
|
1965
|
+
"""
|
|
1966
|
+
|
|
1967
|
+
def directed_subsets(self, direction):
|
|
1968
|
+
r"""
|
|
1969
|
+
Return the order filters (resp. order ideals) of ``self``, as lists.
|
|
1970
|
+
|
|
1971
|
+
If ``direction`` is ``'up'``, returns the order filters (upper sets).
|
|
1972
|
+
|
|
1973
|
+
If ``direction`` is ``'down'``, returns the order ideals (lower sets).
|
|
1974
|
+
|
|
1975
|
+
INPUT:
|
|
1976
|
+
|
|
1977
|
+
- ``direction`` -- ``'up'`` or ``'down'``
|
|
1978
|
+
|
|
1979
|
+
EXAMPLES::
|
|
1980
|
+
|
|
1981
|
+
sage: P = Poset((divisors(12), attrcall("divides")), facade=True)
|
|
1982
|
+
sage: A = P.directed_subsets('up')
|
|
1983
|
+
sage: sorted(list(A)) # needs sage.modules
|
|
1984
|
+
[[], [1, 2, 4, 3, 6, 12], [2, 4, 3, 6, 12], [2, 4, 6, 12], [3, 6, 12],
|
|
1985
|
+
[4, 3, 6, 12], [4, 6, 12], [4, 12], [6, 12], [12]]
|
|
1986
|
+
|
|
1987
|
+
TESTS::
|
|
1988
|
+
|
|
1989
|
+
sage: list(Poset().directed_subsets('up'))
|
|
1990
|
+
[[]]
|
|
1991
|
+
"""
|
|
1992
|
+
if direction != 'up' and direction != 'down':
|
|
1993
|
+
raise ValueError("direction must be either 'up' or 'down'")
|
|
1994
|
+
return self.antichains().map(lambda elements: self.directed_subset(elements, direction))
|