passagemath-categories 10.6.32__cp314-cp314t-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_categories-10.6.32.dist-info/METADATA +156 -0
- passagemath_categories-10.6.32.dist-info/RECORD +719 -0
- passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
- passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
- passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
- passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
- passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
- sage/all__sagemath_categories.py +28 -0
- sage/arith/all.py +38 -0
- sage/arith/constants.pxd +27 -0
- sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/functions.pxd +4 -0
- sage/arith/functions.pyx +221 -0
- sage/arith/misc.py +6552 -0
- sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/multi_modular.pxd +39 -0
- sage/arith/multi_modular.pyx +994 -0
- sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/rational_reconstruction.pxd +4 -0
- sage/arith/rational_reconstruction.pyx +115 -0
- sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/srange.pyx +571 -0
- sage/calculus/all__sagemath_categories.py +2 -0
- sage/calculus/functional.py +481 -0
- sage/calculus/functions.py +151 -0
- sage/categories/additive_groups.py +73 -0
- sage/categories/additive_magmas.py +1044 -0
- sage/categories/additive_monoids.py +114 -0
- sage/categories/additive_semigroups.py +184 -0
- sage/categories/affine_weyl_groups.py +238 -0
- sage/categories/algebra_ideals.py +95 -0
- sage/categories/algebra_modules.py +96 -0
- sage/categories/algebras.py +349 -0
- sage/categories/algebras_with_basis.py +377 -0
- sage/categories/all.py +160 -0
- sage/categories/aperiodic_semigroups.py +29 -0
- sage/categories/associative_algebras.py +47 -0
- sage/categories/bialgebras.py +101 -0
- sage/categories/bialgebras_with_basis.py +414 -0
- sage/categories/bimodules.py +206 -0
- sage/categories/chain_complexes.py +268 -0
- sage/categories/classical_crystals.py +480 -0
- sage/categories/coalgebras.py +405 -0
- sage/categories/coalgebras_with_basis.py +232 -0
- sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/coercion_methods.pyx +52 -0
- sage/categories/commutative_additive_groups.py +104 -0
- sage/categories/commutative_additive_monoids.py +45 -0
- sage/categories/commutative_additive_semigroups.py +48 -0
- sage/categories/commutative_algebra_ideals.py +87 -0
- sage/categories/commutative_algebras.py +94 -0
- sage/categories/commutative_ring_ideals.py +58 -0
- sage/categories/commutative_rings.py +736 -0
- sage/categories/complete_discrete_valuation.py +293 -0
- sage/categories/complex_reflection_groups.py +145 -0
- sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
- sage/categories/coxeter_group_algebras.py +186 -0
- sage/categories/coxeter_groups.py +3402 -0
- sage/categories/crystals.py +2628 -0
- sage/categories/cw_complexes.py +216 -0
- sage/categories/dedekind_domains.py +137 -0
- sage/categories/discrete_valuation.py +325 -0
- sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
- sage/categories/division_rings.py +114 -0
- sage/categories/domains.py +95 -0
- sage/categories/drinfeld_modules.py +789 -0
- sage/categories/dual.py +42 -0
- sage/categories/enumerated_sets.py +1146 -0
- sage/categories/euclidean_domains.py +271 -0
- sage/categories/examples/algebras_with_basis.py +102 -0
- sage/categories/examples/all.py +1 -0
- sage/categories/examples/commutative_additive_monoids.py +130 -0
- sage/categories/examples/commutative_additive_semigroups.py +199 -0
- sage/categories/examples/coxeter_groups.py +8 -0
- sage/categories/examples/crystals.py +236 -0
- sage/categories/examples/cw_complexes.py +163 -0
- sage/categories/examples/facade_sets.py +187 -0
- sage/categories/examples/filtered_algebras_with_basis.py +204 -0
- sage/categories/examples/filtered_modules_with_basis.py +154 -0
- sage/categories/examples/finite_coxeter_groups.py +252 -0
- sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
- sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
- sage/categories/examples/finite_enumerated_sets.py +208 -0
- sage/categories/examples/finite_monoids.py +150 -0
- sage/categories/examples/finite_semigroups.py +190 -0
- sage/categories/examples/finite_weyl_groups.py +191 -0
- sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
- sage/categories/examples/graded_modules_with_basis.py +168 -0
- sage/categories/examples/graphs.py +122 -0
- sage/categories/examples/hopf_algebras_with_basis.py +145 -0
- sage/categories/examples/infinite_enumerated_sets.py +190 -0
- sage/categories/examples/lie_algebras.py +352 -0
- sage/categories/examples/lie_algebras_with_basis.py +196 -0
- sage/categories/examples/magmas.py +162 -0
- sage/categories/examples/manifolds.py +94 -0
- sage/categories/examples/monoids.py +144 -0
- sage/categories/examples/posets.py +178 -0
- sage/categories/examples/semigroups.py +580 -0
- sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/examples/semigroups_cython.pyx +221 -0
- sage/categories/examples/semirings.py +249 -0
- sage/categories/examples/sets_cat.py +706 -0
- sage/categories/examples/sets_with_grading.py +101 -0
- sage/categories/examples/with_realizations.py +542 -0
- sage/categories/fields.py +991 -0
- sage/categories/filtered_algebras.py +63 -0
- sage/categories/filtered_algebras_with_basis.py +548 -0
- sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
- sage/categories/filtered_modules.py +210 -0
- sage/categories/filtered_modules_with_basis.py +1209 -0
- sage/categories/finite_complex_reflection_groups.py +1506 -0
- sage/categories/finite_coxeter_groups.py +1138 -0
- sage/categories/finite_crystals.py +103 -0
- sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
- sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
- sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
- sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
- sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
- sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
- sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
- sage/categories/finite_enumerated_sets.py +769 -0
- sage/categories/finite_fields.py +252 -0
- sage/categories/finite_groups.py +256 -0
- sage/categories/finite_lattice_posets.py +242 -0
- sage/categories/finite_monoids.py +316 -0
- sage/categories/finite_permutation_groups.py +339 -0
- sage/categories/finite_posets.py +1994 -0
- sage/categories/finite_semigroups.py +136 -0
- sage/categories/finite_sets.py +93 -0
- sage/categories/finite_weyl_groups.py +39 -0
- sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
- sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
- sage/categories/finitely_generated_magmas.py +57 -0
- sage/categories/finitely_generated_semigroups.py +214 -0
- sage/categories/function_fields.py +76 -0
- sage/categories/g_sets.py +77 -0
- sage/categories/gcd_domains.py +65 -0
- sage/categories/generalized_coxeter_groups.py +94 -0
- sage/categories/graded_algebras.py +85 -0
- sage/categories/graded_algebras_with_basis.py +258 -0
- sage/categories/graded_bialgebras.py +32 -0
- sage/categories/graded_bialgebras_with_basis.py +32 -0
- sage/categories/graded_coalgebras.py +65 -0
- sage/categories/graded_coalgebras_with_basis.py +51 -0
- sage/categories/graded_hopf_algebras.py +41 -0
- sage/categories/graded_hopf_algebras_with_basis.py +169 -0
- sage/categories/graded_lie_algebras.py +91 -0
- sage/categories/graded_lie_algebras_with_basis.py +44 -0
- sage/categories/graded_lie_conformal_algebras.py +74 -0
- sage/categories/graded_modules.py +133 -0
- sage/categories/graded_modules_with_basis.py +329 -0
- sage/categories/graphs.py +138 -0
- sage/categories/group_algebras.py +430 -0
- sage/categories/groupoid.py +94 -0
- sage/categories/groups.py +667 -0
- sage/categories/h_trivial_semigroups.py +64 -0
- sage/categories/hecke_modules.py +185 -0
- sage/categories/highest_weight_crystals.py +980 -0
- sage/categories/hopf_algebras.py +219 -0
- sage/categories/hopf_algebras_with_basis.py +309 -0
- sage/categories/infinite_enumerated_sets.py +115 -0
- sage/categories/integral_domains.py +203 -0
- sage/categories/j_trivial_semigroups.py +29 -0
- sage/categories/kac_moody_algebras.py +82 -0
- sage/categories/kahler_algebras.py +203 -0
- sage/categories/l_trivial_semigroups.py +63 -0
- sage/categories/lambda_bracket_algebras.py +280 -0
- sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
- sage/categories/lattice_posets.py +89 -0
- sage/categories/left_modules.py +49 -0
- sage/categories/lie_algebras.py +1070 -0
- sage/categories/lie_algebras_with_basis.py +261 -0
- sage/categories/lie_conformal_algebras.py +350 -0
- sage/categories/lie_conformal_algebras_with_basis.py +147 -0
- sage/categories/lie_groups.py +73 -0
- sage/categories/loop_crystals.py +1290 -0
- sage/categories/magmas.py +1189 -0
- sage/categories/magmas_and_additive_magmas.py +149 -0
- sage/categories/magmatic_algebras.py +365 -0
- sage/categories/manifolds.py +352 -0
- sage/categories/matrix_algebras.py +40 -0
- sage/categories/metric_spaces.py +387 -0
- sage/categories/modular_abelian_varieties.py +78 -0
- sage/categories/modules.py +989 -0
- sage/categories/modules_with_basis.py +2794 -0
- sage/categories/monoid_algebras.py +38 -0
- sage/categories/monoids.py +739 -0
- sage/categories/noetherian_rings.py +87 -0
- sage/categories/number_fields.py +242 -0
- sage/categories/ore_modules.py +189 -0
- sage/categories/partially_ordered_monoids.py +49 -0
- sage/categories/permutation_groups.py +63 -0
- sage/categories/pointed_sets.py +42 -0
- sage/categories/polyhedra.py +74 -0
- sage/categories/poor_man_map.py +270 -0
- sage/categories/posets.py +722 -0
- sage/categories/principal_ideal_domains.py +270 -0
- sage/categories/quantum_group_representations.py +543 -0
- sage/categories/quotient_fields.py +728 -0
- sage/categories/r_trivial_semigroups.py +45 -0
- sage/categories/regular_crystals.py +898 -0
- sage/categories/regular_supercrystals.py +170 -0
- sage/categories/right_modules.py +49 -0
- sage/categories/ring_ideals.py +74 -0
- sage/categories/rings.py +1904 -0
- sage/categories/rngs.py +175 -0
- sage/categories/schemes.py +393 -0
- sage/categories/semigroups.py +1060 -0
- sage/categories/semirings.py +71 -0
- sage/categories/semisimple_algebras.py +114 -0
- sage/categories/sets_with_grading.py +235 -0
- sage/categories/shephard_groups.py +43 -0
- sage/categories/signed_tensor.py +120 -0
- sage/categories/simplicial_complexes.py +134 -0
- sage/categories/simplicial_sets.py +1206 -0
- sage/categories/super_algebras.py +149 -0
- sage/categories/super_algebras_with_basis.py +144 -0
- sage/categories/super_hopf_algebras_with_basis.py +126 -0
- sage/categories/super_lie_conformal_algebras.py +193 -0
- sage/categories/super_modules.py +229 -0
- sage/categories/super_modules_with_basis.py +193 -0
- sage/categories/supercommutative_algebras.py +99 -0
- sage/categories/supercrystals.py +406 -0
- sage/categories/tensor.py +110 -0
- sage/categories/topological_spaces.py +170 -0
- sage/categories/triangular_kac_moody_algebras.py +439 -0
- sage/categories/tutorial.py +58 -0
- sage/categories/unique_factorization_domains.py +318 -0
- sage/categories/unital_algebras.py +426 -0
- sage/categories/vector_bundles.py +159 -0
- sage/categories/vector_spaces.py +357 -0
- sage/categories/weyl_groups.py +853 -0
- sage/combinat/all__sagemath_categories.py +34 -0
- sage/combinat/backtrack.py +180 -0
- sage/combinat/combinat.py +2269 -0
- sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/combinat_cython.pxd +6 -0
- sage/combinat/combinat_cython.pyx +390 -0
- sage/combinat/combination.py +796 -0
- sage/combinat/combinatorial_map.py +416 -0
- sage/combinat/composition.py +2192 -0
- sage/combinat/dlx.py +510 -0
- sage/combinat/integer_lists/__init__.py +7 -0
- sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/base.pxd +16 -0
- sage/combinat/integer_lists/base.pyx +713 -0
- sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/invlex.pxd +4 -0
- sage/combinat/integer_lists/invlex.pyx +1650 -0
- sage/combinat/integer_lists/lists.py +328 -0
- sage/combinat/integer_lists/nn.py +48 -0
- sage/combinat/integer_vector.py +1818 -0
- sage/combinat/integer_vector_weighted.py +413 -0
- sage/combinat/matrices/all__sagemath_categories.py +5 -0
- sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/matrices/dancing_links.pyx +1159 -0
- sage/combinat/matrices/dancing_links_c.h +380 -0
- sage/combinat/matrices/dlxcpp.py +136 -0
- sage/combinat/partition.py +10070 -0
- sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/partitions.pyx +743 -0
- sage/combinat/permutation.py +10168 -0
- sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/permutation_cython.pxd +11 -0
- sage/combinat/permutation_cython.pyx +407 -0
- sage/combinat/q_analogues.py +1090 -0
- sage/combinat/ranker.py +268 -0
- sage/combinat/subset.py +1561 -0
- sage/combinat/subsets_hereditary.py +202 -0
- sage/combinat/subsets_pairwise.py +184 -0
- sage/combinat/tools.py +63 -0
- sage/combinat/tuple.py +348 -0
- sage/data_structures/all.py +2 -0
- sage/data_structures/all__sagemath_categories.py +2 -0
- sage/data_structures/binary_matrix.pxd +138 -0
- sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/binary_search.pxd +3 -0
- sage/data_structures/binary_search.pyx +66 -0
- sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset.pxd +40 -0
- sage/data_structures/bitset.pyx +2385 -0
- sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset_base.pxd +926 -0
- sage/data_structures/bitset_base.pyx +117 -0
- sage/data_structures/bitset_intrinsics.h +487 -0
- sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/blas_dict.pxd +12 -0
- sage/data_structures/blas_dict.pyx +469 -0
- sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/list_of_pairs.pxd +16 -0
- sage/data_structures/list_of_pairs.pyx +122 -0
- sage/data_structures/mutable_poset.py +3312 -0
- sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/pairing_heap.h +346 -0
- sage/data_structures/pairing_heap.pxd +88 -0
- sage/data_structures/pairing_heap.pyx +1464 -0
- sage/data_structures/sparse_bitset.pxd +62 -0
- sage/data_structures/stream.py +5070 -0
- sage/databases/all__sagemath_categories.py +7 -0
- sage/databases/sql_db.py +2236 -0
- sage/ext/all__sagemath_categories.py +3 -0
- sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_callable.pxd +4 -0
- sage/ext/fast_callable.pyx +2746 -0
- sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_eval.pxd +1 -0
- sage/ext/fast_eval.pyx +102 -0
- sage/ext/interpreters/__init__.py +1 -0
- sage/ext/interpreters/all__sagemath_categories.py +2 -0
- sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_el.pxd +18 -0
- sage/ext/interpreters/wrapper_el.pyx +148 -0
- sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_py.pxd +17 -0
- sage/ext/interpreters/wrapper_py.pyx +133 -0
- sage/functions/airy.py +937 -0
- sage/functions/all.py +97 -0
- sage/functions/bessel.py +2102 -0
- sage/functions/error.py +784 -0
- sage/functions/exp_integral.py +1529 -0
- sage/functions/gamma.py +1087 -0
- sage/functions/generalized.py +672 -0
- sage/functions/hyperbolic.py +747 -0
- sage/functions/hypergeometric.py +1156 -0
- sage/functions/jacobi.py +1705 -0
- sage/functions/log.py +1402 -0
- sage/functions/min_max.py +338 -0
- sage/functions/orthogonal_polys.py +3106 -0
- sage/functions/other.py +2303 -0
- sage/functions/piecewise.py +1505 -0
- sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/functions/prime_pi.pyx +262 -0
- sage/functions/special.py +1212 -0
- sage/functions/spike_function.py +278 -0
- sage/functions/transcendental.py +690 -0
- sage/functions/trig.py +1062 -0
- sage/functions/wigner.py +726 -0
- sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/geometry/abc.pyx +82 -0
- sage/geometry/all__sagemath_categories.py +1 -0
- sage/groups/all__sagemath_categories.py +11 -0
- sage/groups/generic.py +1733 -0
- sage/groups/groups_catalog.py +113 -0
- sage/groups/perm_gps/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/all.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
- sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
- sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
- sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
- sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
- sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
- sage/interfaces/abc.py +140 -0
- sage/interfaces/all.py +58 -0
- sage/interfaces/all__sagemath_categories.py +1 -0
- sage/interfaces/expect.py +1643 -0
- sage/interfaces/interface.py +1682 -0
- sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/process.pxd +5 -0
- sage/interfaces/process.pyx +288 -0
- sage/interfaces/quit.py +167 -0
- sage/interfaces/sage0.py +604 -0
- sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/sagespawn.pyx +308 -0
- sage/interfaces/tab_completion.py +101 -0
- sage/misc/all__sagemath_categories.py +78 -0
- sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/allocator.pxd +6 -0
- sage/misc/allocator.pyx +47 -0
- sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/binary_tree.pxd +29 -0
- sage/misc/binary_tree.pyx +537 -0
- sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/callable_dict.pyx +89 -0
- sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/citation.pyx +159 -0
- sage/misc/converting_dict.py +293 -0
- sage/misc/defaults.py +129 -0
- sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/derivative.pyx +223 -0
- sage/misc/functional.py +2005 -0
- sage/misc/html.py +589 -0
- sage/misc/latex.py +2673 -0
- sage/misc/latex_macros.py +236 -0
- sage/misc/latex_standalone.py +1833 -0
- sage/misc/map_threaded.py +38 -0
- sage/misc/mathml.py +76 -0
- sage/misc/method_decorator.py +88 -0
- sage/misc/mrange.py +755 -0
- sage/misc/multireplace.py +41 -0
- sage/misc/object_multiplexer.py +92 -0
- sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/parser.pyx +1107 -0
- sage/misc/random_testing.py +264 -0
- sage/misc/rest_index_of_methods.py +377 -0
- sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/search.pxd +2 -0
- sage/misc/search.pyx +68 -0
- sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/stopgap.pyx +95 -0
- sage/misc/table.py +853 -0
- sage/monoids/all__sagemath_categories.py +1 -0
- sage/monoids/indexed_free_monoid.py +1071 -0
- sage/monoids/monoid.py +82 -0
- sage/numerical/all__sagemath_categories.py +1 -0
- sage/numerical/backends/all__sagemath_categories.py +1 -0
- sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_backend.pxd +61 -0
- sage/numerical/backends/generic_backend.pyx +1893 -0
- sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_sdp_backend.pxd +38 -0
- sage/numerical/backends/generic_sdp_backend.pyx +755 -0
- sage/parallel/all.py +6 -0
- sage/parallel/decorate.py +575 -0
- sage/parallel/map_reduce.py +1997 -0
- sage/parallel/multiprocessing_sage.py +76 -0
- sage/parallel/ncpus.py +35 -0
- sage/parallel/parallelism.py +364 -0
- sage/parallel/reference.py +47 -0
- sage/parallel/use_fork.py +333 -0
- sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/abc.pxd +31 -0
- sage/rings/abc.pyx +526 -0
- sage/rings/algebraic_closure_finite_field.py +1154 -0
- sage/rings/all__sagemath_categories.py +91 -0
- sage/rings/big_oh.py +227 -0
- sage/rings/continued_fraction.py +2754 -0
- sage/rings/continued_fraction_gosper.py +220 -0
- sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/factorint.pyx +295 -0
- sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fast_arith.pxd +21 -0
- sage/rings/fast_arith.pyx +535 -0
- sage/rings/finite_rings/all__sagemath_categories.py +9 -0
- sage/rings/finite_rings/conway_polynomials.py +542 -0
- sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_base.pxd +12 -0
- sage/rings/finite_rings/element_base.pyx +1176 -0
- sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/finite_field_base.pxd +7 -0
- sage/rings/finite_rings/finite_field_base.pyx +2171 -0
- sage/rings/finite_rings/finite_field_constructor.py +827 -0
- sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
- sage/rings/finite_rings/galois_group.py +154 -0
- sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_finite_field.pxd +23 -0
- sage/rings/finite_rings/hom_finite_field.pyx +856 -0
- sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
- sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
- sage/rings/finite_rings/homset.py +357 -0
- sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/integer_mod.pxd +56 -0
- sage/rings/finite_rings/integer_mod.pyx +4586 -0
- sage/rings/finite_rings/integer_mod_limits.h +11 -0
- sage/rings/finite_rings/integer_mod_ring.py +2044 -0
- sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/residue_field.pxd +30 -0
- sage/rings/finite_rings/residue_field.pyx +1811 -0
- sage/rings/finite_rings/stdint.pxd +19 -0
- sage/rings/fraction_field.py +1452 -0
- sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fraction_field_element.pyx +1357 -0
- sage/rings/function_field/all.py +7 -0
- sage/rings/function_field/all__sagemath_categories.py +2 -0
- sage/rings/function_field/constructor.py +218 -0
- sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element.pxd +11 -0
- sage/rings/function_field/element.pyx +1008 -0
- sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element_rational.pyx +513 -0
- sage/rings/function_field/extensions.py +230 -0
- sage/rings/function_field/function_field.py +1468 -0
- sage/rings/function_field/function_field_rational.py +1005 -0
- sage/rings/function_field/ideal.py +1155 -0
- sage/rings/function_field/ideal_rational.py +629 -0
- sage/rings/function_field/jacobian_base.py +826 -0
- sage/rings/function_field/jacobian_hess.py +1053 -0
- sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
- sage/rings/function_field/maps.py +1039 -0
- sage/rings/function_field/order.py +281 -0
- sage/rings/function_field/order_basis.py +586 -0
- sage/rings/function_field/order_rational.py +576 -0
- sage/rings/function_field/place.py +426 -0
- sage/rings/function_field/place_rational.py +181 -0
- sage/rings/generic.py +320 -0
- sage/rings/homset.py +332 -0
- sage/rings/ideal.py +1885 -0
- sage/rings/ideal_monoid.py +215 -0
- sage/rings/infinity.py +1890 -0
- sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer.pxd +45 -0
- sage/rings/integer.pyx +7874 -0
- sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer_ring.pxd +8 -0
- sage/rings/integer_ring.pyx +1693 -0
- sage/rings/laurent_series_ring.py +931 -0
- sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/laurent_series_ring_element.pxd +11 -0
- sage/rings/laurent_series_ring_element.pyx +1927 -0
- sage/rings/lazy_series.py +7815 -0
- sage/rings/lazy_series_ring.py +4356 -0
- sage/rings/localization.py +1043 -0
- sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/morphism.pxd +39 -0
- sage/rings/morphism.pyx +3299 -0
- sage/rings/multi_power_series_ring.py +1145 -0
- sage/rings/multi_power_series_ring_element.py +2184 -0
- sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/noncommutative_ideals.pyx +423 -0
- sage/rings/number_field/all__sagemath_categories.py +1 -0
- sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_base.pxd +8 -0
- sage/rings/number_field/number_field_base.pyx +507 -0
- sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_element_base.pxd +6 -0
- sage/rings/number_field/number_field_element_base.pyx +36 -0
- sage/rings/number_field/number_field_ideal.py +3550 -0
- sage/rings/padics/all__sagemath_categories.py +4 -0
- sage/rings/padics/local_generic.py +1670 -0
- sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/local_generic_element.pxd +5 -0
- sage/rings/padics/local_generic_element.pyx +1017 -0
- sage/rings/padics/misc.py +256 -0
- sage/rings/padics/padic_generic.py +1911 -0
- sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/pow_computer.pxd +38 -0
- sage/rings/padics/pow_computer.pyx +671 -0
- sage/rings/padics/precision_error.py +24 -0
- sage/rings/polynomial/all__sagemath_categories.py +25 -0
- sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/commutative_polynomial.pxd +6 -0
- sage/rings/polynomial/commutative_polynomial.pyx +24 -0
- sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/cyclotomic.pyx +404 -0
- sage/rings/polynomial/flatten.py +711 -0
- sage/rings/polynomial/ideal.py +102 -0
- sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
- sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
- sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/laurent_polynomial.pxd +18 -0
- sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
- sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
- sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
- sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
- sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial.pxd +12 -0
- sage/rings/polynomial/multi_polynomial.pyx +3082 -0
- sage/rings/polynomial/multi_polynomial_element.py +2570 -0
- sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
- sage/rings/polynomial/multi_polynomial_ring.py +947 -0
- sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
- sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
- sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polydict.pxd +45 -0
- sage/rings/polynomial/polydict.pyx +2701 -0
- sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_compiled.pxd +59 -0
- sage/rings/polynomial/polynomial_compiled.pyx +509 -0
- sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_element.pxd +64 -0
- sage/rings/polynomial/polynomial_element.pyx +13255 -0
- sage/rings/polynomial/polynomial_element_generic.py +1637 -0
- sage/rings/polynomial/polynomial_fateman.py +97 -0
- sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
- sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
- sage/rings/polynomial/polynomial_ring.py +3784 -0
- sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
- sage/rings/polynomial/polynomial_singular_interface.py +549 -0
- sage/rings/polynomial/symmetric_ideal.py +989 -0
- sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/symmetric_reduction.pxd +8 -0
- sage/rings/polynomial/symmetric_reduction.pyx +669 -0
- sage/rings/polynomial/term_order.py +2279 -0
- sage/rings/polynomial/toy_buchberger.py +449 -0
- sage/rings/polynomial/toy_d_basis.py +387 -0
- sage/rings/polynomial/toy_variety.py +362 -0
- sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_mpoly.pxd +9 -0
- sage/rings/power_series_mpoly.pyx +161 -0
- sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_poly.pxd +10 -0
- sage/rings/power_series_poly.pyx +1317 -0
- sage/rings/power_series_ring.py +1441 -0
- sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_ring_element.pxd +12 -0
- sage/rings/power_series_ring_element.pyx +3028 -0
- sage/rings/puiseux_series_ring.py +487 -0
- sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/puiseux_series_ring_element.pxd +7 -0
- sage/rings/puiseux_series_ring_element.pyx +1055 -0
- sage/rings/qqbar_decorators.py +167 -0
- sage/rings/quotient_ring.py +1598 -0
- sage/rings/quotient_ring_element.py +979 -0
- sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/rational.pxd +20 -0
- sage/rings/rational.pyx +4284 -0
- sage/rings/rational_field.py +1730 -0
- sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_double.pxd +16 -0
- sage/rings/real_double.pyx +2218 -0
- sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_lazy.pxd +30 -0
- sage/rings/real_lazy.pyx +1773 -0
- sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/ring.pxd +30 -0
- sage/rings/ring.pyx +850 -0
- sage/rings/semirings/all.py +3 -0
- sage/rings/semirings/non_negative_integer_semiring.py +107 -0
- sage/rings/semirings/tropical_mpolynomial.py +972 -0
- sage/rings/semirings/tropical_polynomial.py +997 -0
- sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/semirings/tropical_semiring.pyx +676 -0
- sage/rings/semirings/tropical_variety.py +1701 -0
- sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/sum_of_squares.pxd +3 -0
- sage/rings/sum_of_squares.pyx +336 -0
- sage/rings/tests.py +504 -0
- sage/schemes/affine/affine_homset.py +508 -0
- sage/schemes/affine/affine_morphism.py +1574 -0
- sage/schemes/affine/affine_point.py +460 -0
- sage/schemes/affine/affine_rational_point.py +308 -0
- sage/schemes/affine/affine_space.py +1264 -0
- sage/schemes/affine/affine_subscheme.py +592 -0
- sage/schemes/affine/all.py +25 -0
- sage/schemes/all__sagemath_categories.py +5 -0
- sage/schemes/generic/algebraic_scheme.py +2092 -0
- sage/schemes/generic/all.py +5 -0
- sage/schemes/generic/ambient_space.py +400 -0
- sage/schemes/generic/divisor.py +465 -0
- sage/schemes/generic/divisor_group.py +313 -0
- sage/schemes/generic/glue.py +84 -0
- sage/schemes/generic/homset.py +820 -0
- sage/schemes/generic/hypersurface.py +234 -0
- sage/schemes/generic/morphism.py +2107 -0
- sage/schemes/generic/point.py +237 -0
- sage/schemes/generic/scheme.py +1190 -0
- sage/schemes/generic/spec.py +199 -0
- sage/schemes/product_projective/all.py +6 -0
- sage/schemes/product_projective/homset.py +236 -0
- sage/schemes/product_projective/morphism.py +517 -0
- sage/schemes/product_projective/point.py +568 -0
- sage/schemes/product_projective/rational_point.py +550 -0
- sage/schemes/product_projective/space.py +1301 -0
- sage/schemes/product_projective/subscheme.py +466 -0
- sage/schemes/projective/all.py +24 -0
- sage/schemes/projective/proj_bdd_height.py +453 -0
- sage/schemes/projective/projective_homset.py +718 -0
- sage/schemes/projective/projective_morphism.py +2792 -0
- sage/schemes/projective/projective_point.py +1484 -0
- sage/schemes/projective/projective_rational_point.py +569 -0
- sage/schemes/projective/projective_space.py +2571 -0
- sage/schemes/projective/projective_subscheme.py +1574 -0
- sage/sets/all.py +17 -0
- sage/sets/cartesian_product.py +376 -0
- sage/sets/condition_set.py +525 -0
- sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/disjoint_set.pxd +36 -0
- sage/sets/disjoint_set.pyx +998 -0
- sage/sets/disjoint_union_enumerated_sets.py +625 -0
- sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/family.pxd +12 -0
- sage/sets/family.pyx +1556 -0
- sage/sets/finite_enumerated_set.py +406 -0
- sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/finite_set_map_cy.pxd +34 -0
- sage/sets/finite_set_map_cy.pyx +708 -0
- sage/sets/finite_set_maps.py +591 -0
- sage/sets/image_set.py +448 -0
- sage/sets/integer_range.py +829 -0
- sage/sets/non_negative_integers.py +241 -0
- sage/sets/positive_integers.py +93 -0
- sage/sets/primes.py +188 -0
- sage/sets/real_set.py +2760 -0
- sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/recursively_enumerated_set.pxd +31 -0
- sage/sets/recursively_enumerated_set.pyx +2082 -0
- sage/sets/set.py +2083 -0
- sage/sets/set_from_iterator.py +1021 -0
- sage/sets/totally_ordered_finite_set.py +329 -0
- sage/symbolic/all__sagemath_categories.py +1 -0
- sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/symbolic/function.pxd +29 -0
- sage/symbolic/function.pyx +1488 -0
- sage/symbolic/symbols.py +56 -0
- sage/tests/all__sagemath_categories.py +1 -0
- sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/cython.pyx +37 -0
- sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/stl_vector.pyx +171 -0
- sage/typeset/all.py +6 -0
- sage/typeset/ascii_art.py +295 -0
- sage/typeset/character_art.py +789 -0
- sage/typeset/character_art_factory.py +572 -0
- sage/typeset/symbols.py +334 -0
- sage/typeset/unicode_art.py +183 -0
- sage/typeset/unicode_characters.py +101 -0
sage/sets/real_set.py
ADDED
|
@@ -0,0 +1,2760 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
# sage.doctest: needs sage.rings.real_interval_field sage.rings.real_mpfr
|
|
3
|
+
"""
|
|
4
|
+
Subsets of the Real Line
|
|
5
|
+
|
|
6
|
+
This module contains subsets of the real line that can be constructed
|
|
7
|
+
as the union of a finite set of open and closed intervals.
|
|
8
|
+
|
|
9
|
+
EXAMPLES::
|
|
10
|
+
|
|
11
|
+
sage: RealSet(0,1)
|
|
12
|
+
(0, 1)
|
|
13
|
+
sage: RealSet((0,1), [2,3])
|
|
14
|
+
(0, 1) ∪ [2, 3]
|
|
15
|
+
sage: RealSet((1,3), (0,2))
|
|
16
|
+
(0, 3)
|
|
17
|
+
sage: RealSet(-oo, oo)
|
|
18
|
+
(-oo, +oo)
|
|
19
|
+
|
|
20
|
+
Brackets must be balanced in Python, so the naive notation for
|
|
21
|
+
half-open intervals does not work::
|
|
22
|
+
|
|
23
|
+
sage: RealSet([0,1))
|
|
24
|
+
Traceback (most recent call last):
|
|
25
|
+
...
|
|
26
|
+
SyntaxError: ...
|
|
27
|
+
|
|
28
|
+
Instead, you can use the following construction functions::
|
|
29
|
+
|
|
30
|
+
sage: RealSet.open_closed(0,1)
|
|
31
|
+
(0, 1]
|
|
32
|
+
sage: RealSet.closed_open(0,1)
|
|
33
|
+
[0, 1)
|
|
34
|
+
sage: RealSet.point(1/2)
|
|
35
|
+
{1/2}
|
|
36
|
+
sage: RealSet.unbounded_below_open(0)
|
|
37
|
+
(-oo, 0)
|
|
38
|
+
sage: RealSet.unbounded_below_closed(0)
|
|
39
|
+
(-oo, 0]
|
|
40
|
+
sage: RealSet.unbounded_above_open(1)
|
|
41
|
+
(1, +oo)
|
|
42
|
+
sage: RealSet.unbounded_above_closed(1)
|
|
43
|
+
[1, +oo)
|
|
44
|
+
|
|
45
|
+
The lower and upper endpoints will be sorted if necessary::
|
|
46
|
+
|
|
47
|
+
sage: RealSet.interval(1, 0, lower_closed=True, upper_closed=False)
|
|
48
|
+
[0, 1)
|
|
49
|
+
|
|
50
|
+
Relations containing symbols and numeric values or constants::
|
|
51
|
+
|
|
52
|
+
sage: # needs sage.symbolic
|
|
53
|
+
sage: RealSet(x != 0)
|
|
54
|
+
(-oo, 0) ∪ (0, +oo)
|
|
55
|
+
sage: RealSet(x == pi)
|
|
56
|
+
{pi}
|
|
57
|
+
sage: RealSet(x < 1/2)
|
|
58
|
+
(-oo, 1/2)
|
|
59
|
+
sage: RealSet(1/2 < x)
|
|
60
|
+
(1/2, +oo)
|
|
61
|
+
sage: RealSet(1.5 <= x)
|
|
62
|
+
[1.50000000000000, +oo)
|
|
63
|
+
|
|
64
|
+
Note that multiple arguments are combined as union::
|
|
65
|
+
|
|
66
|
+
sage: RealSet(x >= 0, x < 1) # needs sage.symbolic
|
|
67
|
+
(-oo, +oo)
|
|
68
|
+
sage: RealSet(x >= 0, x > 1) # needs sage.symbolic
|
|
69
|
+
[0, +oo)
|
|
70
|
+
sage: RealSet(x >= 0, x > -1) # needs sage.symbolic
|
|
71
|
+
(-1, +oo)
|
|
72
|
+
|
|
73
|
+
AUTHORS:
|
|
74
|
+
|
|
75
|
+
- Laurent Claessens (2010-12-10): Interval and ContinuousSet, posted
|
|
76
|
+
to sage-devel at
|
|
77
|
+
http://www.mail-archive.com/sage-support@googlegroups.com/msg21326.html.
|
|
78
|
+
|
|
79
|
+
- Ares Ribo (2011-10-24): Extended the previous work defining the
|
|
80
|
+
class RealSet.
|
|
81
|
+
|
|
82
|
+
- Jordi Saludes (2011-12-10): Documentation and file reorganization.
|
|
83
|
+
|
|
84
|
+
- Volker Braun (2013-06-22): Rewrite
|
|
85
|
+
|
|
86
|
+
- Yueqi Li, Yuan Zhou (2022-07-31): Rewrite RealSet. Adapt faster operations
|
|
87
|
+
by scan-line (merging) techniques from the code by Matthias Köppe et al., at
|
|
88
|
+
https://github.com/mkoeppe/cutgeneratingfunctionology/blob/master/cutgeneratingfunctionology/igp/intervals.py
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
# ****************************************************************************
|
|
92
|
+
# Copyright (C) 2013 Volker Braun <vbraun.name@gmail.com>
|
|
93
|
+
#
|
|
94
|
+
# This program is free software: you can redistribute it and/or modify
|
|
95
|
+
# it under the terms of the GNU General Public License as published by
|
|
96
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
97
|
+
# (at your option) any later version.
|
|
98
|
+
# https://www.gnu.org/licenses/
|
|
99
|
+
# ****************************************************************************
|
|
100
|
+
|
|
101
|
+
from sage.structure.richcmp import richcmp, richcmp_method
|
|
102
|
+
from sage.structure.parent import Parent
|
|
103
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
104
|
+
from sage.categories.topological_spaces import TopologicalSpaces
|
|
105
|
+
from sage.categories.sets_cat import EmptySetError
|
|
106
|
+
from sage.sets.set import Set_base, Set_boolean_operators, Set_add_sub_operators
|
|
107
|
+
from sage.rings.integer_ring import ZZ
|
|
108
|
+
from sage.rings.real_lazy import LazyFieldElement, RLF
|
|
109
|
+
from sage.rings.infinity import infinity, minus_infinity
|
|
110
|
+
from sage.misc.superseded import deprecated_function_alias
|
|
111
|
+
from heapq import merge
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@richcmp_method
|
|
115
|
+
class InternalRealInterval(UniqueRepresentation, Parent):
|
|
116
|
+
"""
|
|
117
|
+
A real interval.
|
|
118
|
+
|
|
119
|
+
You are not supposed to create :class:`InternalRealInterval` objects
|
|
120
|
+
yourself. Always use :class:`RealSet` instead.
|
|
121
|
+
|
|
122
|
+
INPUT:
|
|
123
|
+
|
|
124
|
+
- ``lower`` -- real or minus infinity; the lower bound of the interval
|
|
125
|
+
|
|
126
|
+
- ``lower_closed`` -- boolean; whether the interval is closed at the lower
|
|
127
|
+
bound
|
|
128
|
+
|
|
129
|
+
- ``upper`` -- real or (plus) infinity; the upper bound of the interval
|
|
130
|
+
|
|
131
|
+
- ``upper_closed`` -- boolean; whether the interval is closed at the upper
|
|
132
|
+
bound
|
|
133
|
+
|
|
134
|
+
- ``check`` -- boolean; whether to check the other arguments for validity
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
def __init__(self, lower, lower_closed, upper, upper_closed, check=True):
|
|
138
|
+
"""
|
|
139
|
+
Initialize ``self``.
|
|
140
|
+
|
|
141
|
+
EXAMPLES::
|
|
142
|
+
|
|
143
|
+
sage: RealSet([0, oo])
|
|
144
|
+
Traceback (most recent call last):
|
|
145
|
+
...
|
|
146
|
+
ValueError: interval cannot be closed at +oo
|
|
147
|
+
"""
|
|
148
|
+
self._lower = lower
|
|
149
|
+
self._upper = upper
|
|
150
|
+
self._lower_closed = lower_closed
|
|
151
|
+
self._upper_closed = upper_closed
|
|
152
|
+
if check:
|
|
153
|
+
if not (isinstance(lower, LazyFieldElement) or lower is minus_infinity):
|
|
154
|
+
raise ValueError('lower bound must be a real number or -oo')
|
|
155
|
+
if not (isinstance(upper, LazyFieldElement) or upper is infinity):
|
|
156
|
+
raise ValueError('upper bound must be a real number or +oo')
|
|
157
|
+
if not isinstance(lower_closed, bool):
|
|
158
|
+
raise ValueError('lower_closed must be boolean')
|
|
159
|
+
if not isinstance(upper_closed, bool):
|
|
160
|
+
raise ValueError('upper_closed must be boolean')
|
|
161
|
+
if lower > upper:
|
|
162
|
+
raise ValueError('lower/upper bounds are not sorted')
|
|
163
|
+
if (lower_closed and lower == minus_infinity):
|
|
164
|
+
raise ValueError('interval cannot be closed at -oo')
|
|
165
|
+
if (upper_closed and upper == infinity):
|
|
166
|
+
raise ValueError('interval cannot be closed at +oo')
|
|
167
|
+
# TODO: take care of the empty set case.
|
|
168
|
+
|
|
169
|
+
def is_empty(self):
|
|
170
|
+
"""
|
|
171
|
+
Return whether the interval is empty.
|
|
172
|
+
|
|
173
|
+
The normalized form of :class:`RealSet` has all intervals
|
|
174
|
+
non-empty, so this method usually returns ``False``.
|
|
175
|
+
|
|
176
|
+
OUTPUT: boolean
|
|
177
|
+
|
|
178
|
+
EXAMPLES::
|
|
179
|
+
|
|
180
|
+
sage: I = RealSet(0, 1)[0]
|
|
181
|
+
sage: I.is_empty()
|
|
182
|
+
False
|
|
183
|
+
"""
|
|
184
|
+
return (self._lower == self._upper) and not (self._lower_closed and self._upper_closed)
|
|
185
|
+
|
|
186
|
+
def is_point(self):
|
|
187
|
+
"""
|
|
188
|
+
Return whether the interval consists of a single point.
|
|
189
|
+
|
|
190
|
+
OUTPUT: boolean
|
|
191
|
+
|
|
192
|
+
EXAMPLES::
|
|
193
|
+
|
|
194
|
+
sage: I = RealSet(0, 1)[0]
|
|
195
|
+
sage: I.is_point()
|
|
196
|
+
False
|
|
197
|
+
"""
|
|
198
|
+
return (self._lower == self._upper) and self._lower_closed and self._upper_closed
|
|
199
|
+
|
|
200
|
+
def lower(self):
|
|
201
|
+
"""
|
|
202
|
+
Return the lower bound.
|
|
203
|
+
|
|
204
|
+
OUTPUT: the lower bound as it was originally specified
|
|
205
|
+
|
|
206
|
+
EXAMPLES::
|
|
207
|
+
|
|
208
|
+
sage: I = RealSet(0, 1)[0]
|
|
209
|
+
sage: I.lower()
|
|
210
|
+
0
|
|
211
|
+
sage: I.upper()
|
|
212
|
+
1
|
|
213
|
+
"""
|
|
214
|
+
if self._lower is minus_infinity:
|
|
215
|
+
return minus_infinity
|
|
216
|
+
else:
|
|
217
|
+
return self._lower._value
|
|
218
|
+
|
|
219
|
+
def upper(self):
|
|
220
|
+
"""
|
|
221
|
+
Return the upper bound.
|
|
222
|
+
|
|
223
|
+
OUTPUT: the upper bound as it was originally specified
|
|
224
|
+
|
|
225
|
+
EXAMPLES::
|
|
226
|
+
|
|
227
|
+
sage: I = RealSet(0, 1)[0]
|
|
228
|
+
sage: I.lower()
|
|
229
|
+
0
|
|
230
|
+
sage: I.upper()
|
|
231
|
+
1
|
|
232
|
+
"""
|
|
233
|
+
if self._upper is infinity:
|
|
234
|
+
return infinity
|
|
235
|
+
else:
|
|
236
|
+
return self._upper._value
|
|
237
|
+
|
|
238
|
+
def lower_closed(self):
|
|
239
|
+
"""
|
|
240
|
+
Return whether the interval is open at the lower bound.
|
|
241
|
+
|
|
242
|
+
OUTPUT: boolean
|
|
243
|
+
|
|
244
|
+
EXAMPLES::
|
|
245
|
+
|
|
246
|
+
sage: I = RealSet.open_closed(0, 1)[0]; I
|
|
247
|
+
(0, 1]
|
|
248
|
+
sage: I.lower_closed()
|
|
249
|
+
False
|
|
250
|
+
sage: I.lower_open()
|
|
251
|
+
True
|
|
252
|
+
sage: I.upper_closed()
|
|
253
|
+
True
|
|
254
|
+
sage: I.upper_open()
|
|
255
|
+
False
|
|
256
|
+
"""
|
|
257
|
+
return self._lower_closed
|
|
258
|
+
|
|
259
|
+
def upper_closed(self):
|
|
260
|
+
"""
|
|
261
|
+
Return whether the interval is closed at the lower bound.
|
|
262
|
+
|
|
263
|
+
OUTPUT: boolean
|
|
264
|
+
|
|
265
|
+
EXAMPLES::
|
|
266
|
+
|
|
267
|
+
sage: I = RealSet.open_closed(0, 1)[0]; I
|
|
268
|
+
(0, 1]
|
|
269
|
+
sage: I.lower_closed()
|
|
270
|
+
False
|
|
271
|
+
sage: I.lower_open()
|
|
272
|
+
True
|
|
273
|
+
sage: I.upper_closed()
|
|
274
|
+
True
|
|
275
|
+
sage: I.upper_open()
|
|
276
|
+
False
|
|
277
|
+
"""
|
|
278
|
+
return self._upper_closed
|
|
279
|
+
|
|
280
|
+
def lower_open(self):
|
|
281
|
+
"""
|
|
282
|
+
Return whether the interval is closed at the upper bound.
|
|
283
|
+
|
|
284
|
+
OUTPUT: boolean
|
|
285
|
+
|
|
286
|
+
EXAMPLES::
|
|
287
|
+
|
|
288
|
+
sage: I = RealSet.open_closed(0, 1)[0]; I
|
|
289
|
+
(0, 1]
|
|
290
|
+
sage: I.lower_closed()
|
|
291
|
+
False
|
|
292
|
+
sage: I.lower_open()
|
|
293
|
+
True
|
|
294
|
+
sage: I.upper_closed()
|
|
295
|
+
True
|
|
296
|
+
sage: I.upper_open()
|
|
297
|
+
False
|
|
298
|
+
"""
|
|
299
|
+
return not self._lower_closed
|
|
300
|
+
|
|
301
|
+
def upper_open(self):
|
|
302
|
+
"""
|
|
303
|
+
Return whether the interval is closed at the upper bound.
|
|
304
|
+
|
|
305
|
+
OUTPUT: boolean
|
|
306
|
+
|
|
307
|
+
EXAMPLES::
|
|
308
|
+
|
|
309
|
+
sage: I = RealSet.open_closed(0, 1)[0]; I
|
|
310
|
+
(0, 1]
|
|
311
|
+
sage: I.lower_closed()
|
|
312
|
+
False
|
|
313
|
+
sage: I.lower_open()
|
|
314
|
+
True
|
|
315
|
+
sage: I.upper_closed()
|
|
316
|
+
True
|
|
317
|
+
sage: I.upper_open()
|
|
318
|
+
False
|
|
319
|
+
"""
|
|
320
|
+
return not self._upper_closed
|
|
321
|
+
|
|
322
|
+
def __richcmp__(self, other, op):
|
|
323
|
+
"""
|
|
324
|
+
Intervals are sorted by lower bound, then upper bound.
|
|
325
|
+
|
|
326
|
+
OUTPUT: `-1`, `0`, or `+1` depending on how the intervals compare
|
|
327
|
+
|
|
328
|
+
EXAMPLES::
|
|
329
|
+
|
|
330
|
+
sage: I1 = RealSet.open_closed(1, 3)[0]; I1
|
|
331
|
+
(1, 3]
|
|
332
|
+
sage: I2 = RealSet.open_closed(0, 5)[0]; I2
|
|
333
|
+
(0, 5]
|
|
334
|
+
sage: I1 > I2
|
|
335
|
+
True
|
|
336
|
+
sage: sorted([I1, I2])
|
|
337
|
+
[(0, 5], (1, 3]]
|
|
338
|
+
|
|
339
|
+
TESTS:
|
|
340
|
+
|
|
341
|
+
Check if a bug in sorting is fixed (:issue:`17714`)::
|
|
342
|
+
|
|
343
|
+
sage: RealSet((0, 1),[1, 1],(1, 2))
|
|
344
|
+
(0, 2)
|
|
345
|
+
"""
|
|
346
|
+
x = (self._lower, not self._lower_closed, self._upper, self._upper_closed)
|
|
347
|
+
y = (other._lower, not other._lower_closed, other._upper, other._upper_closed)
|
|
348
|
+
# same as richcmp((self._scan_lower(), self._scan_upper()),
|
|
349
|
+
# (other._scan_lower(), other._scan_upper()), op)
|
|
350
|
+
return richcmp(x, y, op)
|
|
351
|
+
|
|
352
|
+
element_class = LazyFieldElement
|
|
353
|
+
|
|
354
|
+
def _repr_(self):
|
|
355
|
+
"""
|
|
356
|
+
Return a string representation.
|
|
357
|
+
|
|
358
|
+
OUTPUT: string
|
|
359
|
+
|
|
360
|
+
EXAMPLES::
|
|
361
|
+
|
|
362
|
+
sage: RealSet.open_closed(0, 1)
|
|
363
|
+
(0, 1]
|
|
364
|
+
sage: RealSet.point(0)
|
|
365
|
+
{0}
|
|
366
|
+
"""
|
|
367
|
+
if self.is_point():
|
|
368
|
+
return '{' + str(self.lower()) + '}'
|
|
369
|
+
s = '[' if self._lower_closed else '('
|
|
370
|
+
if self.lower() is minus_infinity:
|
|
371
|
+
s += '-oo'
|
|
372
|
+
else:
|
|
373
|
+
s += str(self.lower())
|
|
374
|
+
s += ', '
|
|
375
|
+
if self.upper() is infinity:
|
|
376
|
+
s += '+oo'
|
|
377
|
+
else:
|
|
378
|
+
s += str(self.upper())
|
|
379
|
+
s += ']' if self._upper_closed else ')'
|
|
380
|
+
return s
|
|
381
|
+
|
|
382
|
+
def _latex_(self) -> str:
|
|
383
|
+
"""
|
|
384
|
+
Return a latex representation of ``self``.
|
|
385
|
+
|
|
386
|
+
EXAMPLES::
|
|
387
|
+
|
|
388
|
+
sage: RealSet.open_closed(1/2, pi)._latex_() # needs sage.symbolic
|
|
389
|
+
'(\\frac{1}{2}, \\pi]'
|
|
390
|
+
sage: (RealSet.point(sqrt(2)))._latex_() # needs sage.symbolic
|
|
391
|
+
'\\{\\sqrt{2}\\}'
|
|
392
|
+
"""
|
|
393
|
+
from sage.misc.latex import latex
|
|
394
|
+
if self.is_point():
|
|
395
|
+
# Converting to str avoids the extra whitespace
|
|
396
|
+
# that LatexExpr add on concatenation. We do not need
|
|
397
|
+
# the whitespace because we are wrapping it in
|
|
398
|
+
# non-letter characters.
|
|
399
|
+
return r'\{' + str(latex(self.lower())) + r'\}'
|
|
400
|
+
s = '[' if self._lower_closed else '('
|
|
401
|
+
s += str(latex(self.lower()))
|
|
402
|
+
s += ', '
|
|
403
|
+
s += str(latex(self.upper()))
|
|
404
|
+
s += ']' if self._upper_closed else ')'
|
|
405
|
+
return s
|
|
406
|
+
|
|
407
|
+
def _sympy_condition_(self, variable):
|
|
408
|
+
"""
|
|
409
|
+
Convert to a sympy conditional expression.
|
|
410
|
+
|
|
411
|
+
INPUT:
|
|
412
|
+
|
|
413
|
+
- ``variable`` -- a symbolic variable
|
|
414
|
+
|
|
415
|
+
EXAMPLES::
|
|
416
|
+
|
|
417
|
+
sage: RealSet(0, 4)._sympy_condition_(x) # needs sage.symbolic
|
|
418
|
+
(0 < x) & (x < 4)
|
|
419
|
+
"""
|
|
420
|
+
x = variable
|
|
421
|
+
if self.is_point():
|
|
422
|
+
return (x == self.lower())._sympy_()
|
|
423
|
+
true = (x == 0)._sympy_() | True # trick to get sympy's True
|
|
424
|
+
if self.lower() is not minus_infinity:
|
|
425
|
+
if self._lower_closed:
|
|
426
|
+
lower_condition = (self.lower() <= x)._sympy_()
|
|
427
|
+
else:
|
|
428
|
+
lower_condition = (self.lower() < x)._sympy_()
|
|
429
|
+
else:
|
|
430
|
+
lower_condition = true
|
|
431
|
+
if self.upper() is not infinity:
|
|
432
|
+
if self._upper_closed:
|
|
433
|
+
upper_condition = (x <= self.upper())._sympy_()
|
|
434
|
+
else:
|
|
435
|
+
upper_condition = (x < self.upper())._sympy_()
|
|
436
|
+
else:
|
|
437
|
+
upper_condition = true
|
|
438
|
+
return lower_condition & upper_condition
|
|
439
|
+
|
|
440
|
+
def _sympy_(self):
|
|
441
|
+
r"""
|
|
442
|
+
Return the SymPy set corresponding to ``self``.
|
|
443
|
+
|
|
444
|
+
EXAMPLES::
|
|
445
|
+
|
|
446
|
+
sage: # needs sympy
|
|
447
|
+
sage: RealSet.open_closed(0, 1)[0]._sympy_()
|
|
448
|
+
Interval.Lopen(0, 1)
|
|
449
|
+
sage: RealSet.point(0)[0]._sympy_() # random - this output format is sympy >= 1.9
|
|
450
|
+
{0}
|
|
451
|
+
sage: type(_)
|
|
452
|
+
<class 'sympy.sets.sets.FiniteSet'>
|
|
453
|
+
sage: RealSet.open(0,1)[0]._sympy_()
|
|
454
|
+
Interval.open(0, 1)
|
|
455
|
+
sage: RealSet.open(-oo,1)[0]._sympy_()
|
|
456
|
+
Interval.open(-oo, 1)
|
|
457
|
+
sage: RealSet.open(0, oo)[0]._sympy_()
|
|
458
|
+
Interval.open(0, oo)
|
|
459
|
+
"""
|
|
460
|
+
from sympy import Interval
|
|
461
|
+
from sage.interfaces.sympy import sympy_init
|
|
462
|
+
sympy_init()
|
|
463
|
+
return Interval(self.lower(), self.upper(),
|
|
464
|
+
left_open=not self._lower_closed,
|
|
465
|
+
right_open=not self._upper_closed)
|
|
466
|
+
|
|
467
|
+
def _giac_condition_(self, variable):
|
|
468
|
+
"""
|
|
469
|
+
Convert to a Giac conditional expression.
|
|
470
|
+
|
|
471
|
+
INPUT:
|
|
472
|
+
|
|
473
|
+
- ``variable`` -- a symbolic variable
|
|
474
|
+
|
|
475
|
+
EXAMPLES::
|
|
476
|
+
|
|
477
|
+
sage: RealSet(0, 4)._giac_condition_(x) # needs sage.libs.giac
|
|
478
|
+
'((0 < sageVARx) and (sageVARx < 4))'
|
|
479
|
+
"""
|
|
480
|
+
x = variable
|
|
481
|
+
if self.is_point():
|
|
482
|
+
return (x == self.lower())._giac_init_()
|
|
483
|
+
true = 'true'
|
|
484
|
+
if self.lower() is not minus_infinity:
|
|
485
|
+
if self._lower_closed:
|
|
486
|
+
lower_condition = (self.lower() <= x)._giac_init_()
|
|
487
|
+
else:
|
|
488
|
+
lower_condition = (self.lower() < x)._giac_init_()
|
|
489
|
+
else:
|
|
490
|
+
lower_condition = true
|
|
491
|
+
if self.upper() is not infinity:
|
|
492
|
+
if self._upper_closed:
|
|
493
|
+
upper_condition = (x <= self.upper())._giac_init_()
|
|
494
|
+
else:
|
|
495
|
+
upper_condition = (x < self.upper())._giac_init_()
|
|
496
|
+
else:
|
|
497
|
+
upper_condition = true
|
|
498
|
+
return "((" + lower_condition + ") and (" + upper_condition + "))"
|
|
499
|
+
|
|
500
|
+
def closure(self):
|
|
501
|
+
"""
|
|
502
|
+
Return the closure.
|
|
503
|
+
|
|
504
|
+
OUTPUT: the closure as a new :class:`InternalRealInterval`
|
|
505
|
+
|
|
506
|
+
EXAMPLES::
|
|
507
|
+
|
|
508
|
+
sage: RealSet.open(0,1)[0].closure()
|
|
509
|
+
[0, 1]
|
|
510
|
+
sage: RealSet.open(-oo,1)[0].closure()
|
|
511
|
+
(-oo, 1]
|
|
512
|
+
sage: RealSet.open(0, oo)[0].closure()
|
|
513
|
+
[0, +oo)
|
|
514
|
+
"""
|
|
515
|
+
# Bug example: RealSet.point(5).interior().closure() returns {5}.
|
|
516
|
+
# TODO: take care of the empty set case.
|
|
517
|
+
# maybe not necessary because this is an interval class of
|
|
518
|
+
# :class:`RealSet` whose intervals are all non-empty.
|
|
519
|
+
lower_closed = (self._lower != minus_infinity)
|
|
520
|
+
upper_closed = (self._upper != infinity)
|
|
521
|
+
return InternalRealInterval(self._lower, lower_closed, self._upper, upper_closed)
|
|
522
|
+
|
|
523
|
+
def interior(self):
|
|
524
|
+
"""
|
|
525
|
+
Return the interior.
|
|
526
|
+
|
|
527
|
+
OUTPUT: the interior as a new :class:`InternalRealInterval`
|
|
528
|
+
|
|
529
|
+
EXAMPLES::
|
|
530
|
+
|
|
531
|
+
sage: RealSet.closed(0, 1)[0].interior()
|
|
532
|
+
(0, 1)
|
|
533
|
+
sage: RealSet.open_closed(-oo, 1)[0].interior()
|
|
534
|
+
(-oo, 1)
|
|
535
|
+
sage: RealSet.closed_open(0, oo)[0].interior()
|
|
536
|
+
(0, +oo)
|
|
537
|
+
"""
|
|
538
|
+
return InternalRealInterval(self._lower, False, self._upper, False)
|
|
539
|
+
|
|
540
|
+
def boundary_points(self):
|
|
541
|
+
"""
|
|
542
|
+
Generate the boundary points of ``self``.
|
|
543
|
+
|
|
544
|
+
EXAMPLES::
|
|
545
|
+
|
|
546
|
+
sage: list(RealSet.open_closed(-oo, 1)[0].boundary_points())
|
|
547
|
+
[1]
|
|
548
|
+
sage: list(RealSet.open(1, 2)[0].boundary_points())
|
|
549
|
+
[1, 2]
|
|
550
|
+
"""
|
|
551
|
+
if self._lower != minus_infinity:
|
|
552
|
+
yield self._lower
|
|
553
|
+
if self._upper != infinity:
|
|
554
|
+
yield self._upper
|
|
555
|
+
|
|
556
|
+
def is_connected(self, other):
|
|
557
|
+
"""
|
|
558
|
+
Test whether two intervals are connected.
|
|
559
|
+
|
|
560
|
+
OUTPUT:
|
|
561
|
+
|
|
562
|
+
boolean; whether the set-theoretic union of the two intervals
|
|
563
|
+
has a single connected component.
|
|
564
|
+
|
|
565
|
+
EXAMPLES::
|
|
566
|
+
|
|
567
|
+
sage: I1 = RealSet.open(0, 1)[0]; I1
|
|
568
|
+
(0, 1)
|
|
569
|
+
sage: I2 = RealSet.closed(1, 2)[0]; I2
|
|
570
|
+
[1, 2]
|
|
571
|
+
sage: I1.is_connected(I2)
|
|
572
|
+
True
|
|
573
|
+
sage: I1.is_connected(I2.interior())
|
|
574
|
+
False
|
|
575
|
+
sage: I1.closure().is_connected(I2.interior())
|
|
576
|
+
True
|
|
577
|
+
sage: I2.is_connected(I1)
|
|
578
|
+
True
|
|
579
|
+
sage: I2.interior().is_connected(I1)
|
|
580
|
+
False
|
|
581
|
+
sage: I2.closure().is_connected(I1.interior())
|
|
582
|
+
True
|
|
583
|
+
sage: I3 = RealSet.closed(1/2, 3/2)[0]; I3
|
|
584
|
+
[1/2, 3/2]
|
|
585
|
+
sage: I1.is_connected(I3)
|
|
586
|
+
True
|
|
587
|
+
sage: I3.is_connected(I1)
|
|
588
|
+
True
|
|
589
|
+
"""
|
|
590
|
+
# self is separated and below other
|
|
591
|
+
if self._upper < other._lower:
|
|
592
|
+
return False
|
|
593
|
+
# self is adjacent and below other
|
|
594
|
+
if self._upper == other._lower:
|
|
595
|
+
return self._upper_closed or other._lower_closed
|
|
596
|
+
# self is separated and above other
|
|
597
|
+
if other._upper < self._lower:
|
|
598
|
+
return False
|
|
599
|
+
# self is adjacent and above other
|
|
600
|
+
if other._upper == self._lower:
|
|
601
|
+
return self._lower_closed or other._upper_closed
|
|
602
|
+
# They are not separated
|
|
603
|
+
return True
|
|
604
|
+
|
|
605
|
+
def convex_hull(self, other):
|
|
606
|
+
"""
|
|
607
|
+
Return the convex hull of the two intervals.
|
|
608
|
+
|
|
609
|
+
OUTPUT: the convex hull as a new :class:`InternalRealInterval`
|
|
610
|
+
|
|
611
|
+
EXAMPLES::
|
|
612
|
+
|
|
613
|
+
sage: I1 = RealSet.open(0, 1)[0]; I1
|
|
614
|
+
(0, 1)
|
|
615
|
+
sage: I2 = RealSet.closed(1, 2)[0]; I2
|
|
616
|
+
[1, 2]
|
|
617
|
+
sage: I1.convex_hull(I2)
|
|
618
|
+
(0, 2]
|
|
619
|
+
sage: I2.convex_hull(I1)
|
|
620
|
+
(0, 2]
|
|
621
|
+
sage: I1.convex_hull(I2.interior())
|
|
622
|
+
(0, 2)
|
|
623
|
+
sage: I1.closure().convex_hull(I2.interior())
|
|
624
|
+
[0, 2)
|
|
625
|
+
sage: I1.closure().convex_hull(I2)
|
|
626
|
+
[0, 2]
|
|
627
|
+
sage: I3 = RealSet.closed(1/2, 3/2)[0]; I3
|
|
628
|
+
[1/2, 3/2]
|
|
629
|
+
sage: I1.convex_hull(I3)
|
|
630
|
+
(0, 3/2]
|
|
631
|
+
"""
|
|
632
|
+
if self._lower < other._lower:
|
|
633
|
+
lower = self._lower
|
|
634
|
+
lower_closed = self._lower_closed
|
|
635
|
+
elif self._lower > other._lower:
|
|
636
|
+
lower = other._lower
|
|
637
|
+
lower_closed = other._lower_closed
|
|
638
|
+
else:
|
|
639
|
+
lower = self._lower
|
|
640
|
+
lower_closed = self._lower_closed or other._lower_closed
|
|
641
|
+
if self._upper > other._upper:
|
|
642
|
+
upper = self._upper
|
|
643
|
+
upper_closed = self._upper_closed
|
|
644
|
+
elif self._upper < other._upper:
|
|
645
|
+
upper = other._upper
|
|
646
|
+
upper_closed = other._upper_closed
|
|
647
|
+
else:
|
|
648
|
+
upper = self._upper
|
|
649
|
+
upper_closed = self._upper_closed or other._upper_closed
|
|
650
|
+
return InternalRealInterval(lower, lower_closed, upper, upper_closed)
|
|
651
|
+
|
|
652
|
+
def intersection(self, other):
|
|
653
|
+
"""
|
|
654
|
+
Return the intersection of the two intervals.
|
|
655
|
+
|
|
656
|
+
INPUT:
|
|
657
|
+
|
|
658
|
+
- ``other`` -- a :class:`InternalRealInterval`
|
|
659
|
+
|
|
660
|
+
OUTPUT: the intersection as a new :class:`InternalRealInterval`
|
|
661
|
+
|
|
662
|
+
EXAMPLES::
|
|
663
|
+
|
|
664
|
+
sage: I1 = RealSet.open(0, 2)[0]; I1
|
|
665
|
+
(0, 2)
|
|
666
|
+
sage: I2 = RealSet.closed(1, 3)[0]; I2
|
|
667
|
+
[1, 3]
|
|
668
|
+
sage: I1.intersection(I2)
|
|
669
|
+
[1, 2)
|
|
670
|
+
sage: I2.intersection(I1)
|
|
671
|
+
[1, 2)
|
|
672
|
+
sage: I1.closure().intersection(I2.interior())
|
|
673
|
+
(1, 2]
|
|
674
|
+
sage: I2.interior().intersection(I1.closure())
|
|
675
|
+
(1, 2]
|
|
676
|
+
|
|
677
|
+
sage: I3 = RealSet.closed(10, 11)[0]; I3
|
|
678
|
+
[10, 11]
|
|
679
|
+
sage: I1.intersection(I3)
|
|
680
|
+
(0, 0)
|
|
681
|
+
sage: I3.intersection(I1)
|
|
682
|
+
(0, 0)
|
|
683
|
+
"""
|
|
684
|
+
lower = upper = None
|
|
685
|
+
lower_closed = upper_closed = None
|
|
686
|
+
if self._lower < other._lower:
|
|
687
|
+
lower = other._lower
|
|
688
|
+
lower_closed = other._lower_closed
|
|
689
|
+
elif self._lower > other._lower:
|
|
690
|
+
lower = self._lower
|
|
691
|
+
lower_closed = self._lower_closed
|
|
692
|
+
else:
|
|
693
|
+
lower = self._lower
|
|
694
|
+
lower_closed = self._lower_closed and other._lower_closed
|
|
695
|
+
if self._upper > other._upper:
|
|
696
|
+
upper = other._upper
|
|
697
|
+
upper_closed = other._upper_closed
|
|
698
|
+
elif self._upper < other._upper:
|
|
699
|
+
upper = self._upper
|
|
700
|
+
upper_closed = self._upper_closed
|
|
701
|
+
else:
|
|
702
|
+
upper = self._upper
|
|
703
|
+
upper_closed = self._upper_closed and other._upper_closed
|
|
704
|
+
if lower > upper:
|
|
705
|
+
lower = upper = RLF(0)
|
|
706
|
+
lower_closed = upper_closed = False
|
|
707
|
+
return InternalRealInterval(lower, lower_closed, upper, upper_closed)
|
|
708
|
+
|
|
709
|
+
def contains(self, x):
|
|
710
|
+
"""
|
|
711
|
+
Return whether `x` is contained in the interval.
|
|
712
|
+
|
|
713
|
+
INPUT:
|
|
714
|
+
|
|
715
|
+
- ``x`` -- a real number
|
|
716
|
+
|
|
717
|
+
OUTPUT: boolean
|
|
718
|
+
|
|
719
|
+
EXAMPLES::
|
|
720
|
+
|
|
721
|
+
sage: i = RealSet.open_closed(0,2)[0]; i
|
|
722
|
+
(0, 2]
|
|
723
|
+
sage: i.contains(0)
|
|
724
|
+
False
|
|
725
|
+
sage: i.contains(1)
|
|
726
|
+
True
|
|
727
|
+
sage: i.contains(2)
|
|
728
|
+
True
|
|
729
|
+
"""
|
|
730
|
+
if self._lower < x < self._upper:
|
|
731
|
+
return True
|
|
732
|
+
if self._lower == x:
|
|
733
|
+
return self._lower_closed
|
|
734
|
+
if self._upper == x:
|
|
735
|
+
return self._upper_closed
|
|
736
|
+
return False
|
|
737
|
+
|
|
738
|
+
def __mul__(self, right):
|
|
739
|
+
r"""
|
|
740
|
+
Scale an interval by a scalar on the left or right.
|
|
741
|
+
|
|
742
|
+
If scaled with a negative number, the interval is flipped.
|
|
743
|
+
|
|
744
|
+
EXAMPLES::
|
|
745
|
+
|
|
746
|
+
sage: i = RealSet.open_closed(0,2)[0]; i
|
|
747
|
+
(0, 2]
|
|
748
|
+
sage: 2 * i
|
|
749
|
+
(0, 4]
|
|
750
|
+
sage: 0 * i
|
|
751
|
+
{0}
|
|
752
|
+
sage: (-2) * i
|
|
753
|
+
[-4, 0)
|
|
754
|
+
sage: i * (-3)
|
|
755
|
+
[-6, 0)
|
|
756
|
+
sage: i * 0
|
|
757
|
+
{0}
|
|
758
|
+
sage: i * 1
|
|
759
|
+
(0, 2]
|
|
760
|
+
|
|
761
|
+
TESTS::
|
|
762
|
+
|
|
763
|
+
sage: from sage.sets.real_set import InternalRealInterval
|
|
764
|
+
sage: i = InternalRealInterval(RLF(0), False, RLF(0), False)
|
|
765
|
+
sage: (0 * i).is_empty()
|
|
766
|
+
True
|
|
767
|
+
"""
|
|
768
|
+
if not isinstance(right, InternalRealInterval):
|
|
769
|
+
right = RLF(right)
|
|
770
|
+
if self.is_empty():
|
|
771
|
+
return self
|
|
772
|
+
lower = self._lower * right
|
|
773
|
+
lower_closed = self._lower_closed
|
|
774
|
+
upper = self._upper * right
|
|
775
|
+
upper_closed = self._upper_closed
|
|
776
|
+
scalar = right
|
|
777
|
+
elif not isinstance(self, InternalRealInterval):
|
|
778
|
+
self = RLF(self)
|
|
779
|
+
if right.is_empty():
|
|
780
|
+
return right
|
|
781
|
+
lower = self * right._lower
|
|
782
|
+
lower_closed = right._lower_closed
|
|
783
|
+
upper = self * right._upper
|
|
784
|
+
upper_closed = right._upper_closed
|
|
785
|
+
scalar = self
|
|
786
|
+
else:
|
|
787
|
+
return NotImplemented
|
|
788
|
+
if scalar == RLF(0):
|
|
789
|
+
return InternalRealInterval(RLF(0), True, RLF(0), True)
|
|
790
|
+
elif scalar < RLF(0):
|
|
791
|
+
lower, lower_closed, upper, upper_closed = upper, upper_closed, lower, lower_closed
|
|
792
|
+
if lower == -infinity:
|
|
793
|
+
lower = -infinity
|
|
794
|
+
if upper == infinity:
|
|
795
|
+
upper = infinity
|
|
796
|
+
return InternalRealInterval(lower, lower_closed,
|
|
797
|
+
upper, upper_closed)
|
|
798
|
+
|
|
799
|
+
def __rmul__(self, other):
|
|
800
|
+
r"""
|
|
801
|
+
Scale an interval by a scalar on the left.
|
|
802
|
+
|
|
803
|
+
If scaled with a negative number, the interval is flipped.
|
|
804
|
+
|
|
805
|
+
EXAMPLES::
|
|
806
|
+
|
|
807
|
+
sage: i = RealSet.open_closed(0,2)[0]; i
|
|
808
|
+
(0, 2]
|
|
809
|
+
sage: 2 * i
|
|
810
|
+
(0, 4]
|
|
811
|
+
sage: 0 * i
|
|
812
|
+
{0}
|
|
813
|
+
sage: (-2) * i
|
|
814
|
+
[-4, 0)
|
|
815
|
+
"""
|
|
816
|
+
return self * other
|
|
817
|
+
|
|
818
|
+
def _scan_lower(self):
|
|
819
|
+
r"""
|
|
820
|
+
Helper function for the scan-line method of :class:`RealSet`.
|
|
821
|
+
|
|
822
|
+
OUTPUT:
|
|
823
|
+
|
|
824
|
+
An event of the form ``(x, epsilon), delta``:
|
|
825
|
+
|
|
826
|
+
- ``x`` is the lower endpoint
|
|
827
|
+
- ``epsilon`` is 0 if the interval is lower closed and 1 otherwise,
|
|
828
|
+
- ``delta = -1``
|
|
829
|
+
|
|
830
|
+
EXAMPLES::
|
|
831
|
+
|
|
832
|
+
sage: I1 = RealSet.open_closed(0,2)[0]; I1
|
|
833
|
+
(0, 2]
|
|
834
|
+
sage: I1._scan_lower()
|
|
835
|
+
((0, 1), -1)
|
|
836
|
+
sage: I2 = RealSet([0,2])[0]; I2
|
|
837
|
+
[0, 2]
|
|
838
|
+
sage: I2._scan_lower()
|
|
839
|
+
((0, 0), -1)
|
|
840
|
+
sage: I3 = RealSet([1,1])[0]; I3
|
|
841
|
+
{1}
|
|
842
|
+
sage: I3._scan_lower()
|
|
843
|
+
((1, 0), -1)
|
|
844
|
+
sage: I4 = RealSet((-oo,1))[0]; I4
|
|
845
|
+
(-oo, 1)
|
|
846
|
+
sage: I4._scan_lower()
|
|
847
|
+
((-Infinity, 1), -1)
|
|
848
|
+
"""
|
|
849
|
+
if self._lower_closed:
|
|
850
|
+
return (self._lower, 0), -1
|
|
851
|
+
else:
|
|
852
|
+
return (self._lower, 1), -1
|
|
853
|
+
|
|
854
|
+
def _scan_upper(self):
|
|
855
|
+
r"""
|
|
856
|
+
Helper function for the scan-line method of :class:`RealSet`.
|
|
857
|
+
|
|
858
|
+
OUTPUT:
|
|
859
|
+
|
|
860
|
+
An event of the form ``(x, epsilon), delta``:
|
|
861
|
+
|
|
862
|
+
- ``x`` is the upper endpoint
|
|
863
|
+
- ``epsilon`` is 1 if the interval is upper closed and 0 otherwise,
|
|
864
|
+
- ``delta = +1``
|
|
865
|
+
|
|
866
|
+
EXAMPLES::
|
|
867
|
+
|
|
868
|
+
sage: I1 = RealSet.closed_open(0,2)[0]; I1
|
|
869
|
+
[0, 2)
|
|
870
|
+
sage: I1._scan_upper()
|
|
871
|
+
((2, 0), 1)
|
|
872
|
+
sage: I2 = RealSet([0,2])[0]; I2
|
|
873
|
+
[0, 2]
|
|
874
|
+
sage: I2._scan_upper()
|
|
875
|
+
((2, 1), 1)
|
|
876
|
+
sage: I3 = RealSet([1,1])[0]; I3
|
|
877
|
+
{1}
|
|
878
|
+
sage: I3._scan_upper()
|
|
879
|
+
((1, 1), 1)
|
|
880
|
+
sage: I4 = RealSet((0,oo))[0]; I4
|
|
881
|
+
(0, +oo)
|
|
882
|
+
sage: I4._scan_upper()
|
|
883
|
+
((+Infinity, 0), 1)
|
|
884
|
+
"""
|
|
885
|
+
if self._upper_closed:
|
|
886
|
+
return (self._upper, 1), +1
|
|
887
|
+
else:
|
|
888
|
+
return (self._upper, 0), +1
|
|
889
|
+
|
|
890
|
+
|
|
891
|
+
@richcmp_method
|
|
892
|
+
class RealSet(UniqueRepresentation, Parent, Set_base,
|
|
893
|
+
Set_boolean_operators, Set_add_sub_operators):
|
|
894
|
+
r"""
|
|
895
|
+
A subset of the real line, a finite union of intervals.
|
|
896
|
+
|
|
897
|
+
INPUT:
|
|
898
|
+
|
|
899
|
+
- ``*args`` -- arguments defining a real set. Possibilities are either:
|
|
900
|
+
|
|
901
|
+
- two extended real numbers ``a, b``, to construct the open interval `(a, b)`, or
|
|
902
|
+
- a list/tuple/iterable of (not necessarily disjoint) intervals or real sets,
|
|
903
|
+
whose union is taken. The individual intervals can be specified by either
|
|
904
|
+
|
|
905
|
+
- a tuple ``(a, b)`` of two extended real numbers (constructing an open interval),
|
|
906
|
+
- a list ``[a, b]`` of two real numbers (constructing a closed interval),
|
|
907
|
+
- an :class:`InternalRealInterval`,
|
|
908
|
+
- an :class:`~sage.manifolds.differentiable.examples.real_line.OpenInterval`.
|
|
909
|
+
|
|
910
|
+
- ``structure`` -- (default: ``None``) if ``None``, construct the real set as an
|
|
911
|
+
instance of :class:`RealSet`; if ``'differentiable'``, construct it as a subset of
|
|
912
|
+
an instance of :class:`~sage.manifolds.differentiable.examples.real_line.RealLine`,
|
|
913
|
+
representing the differentiable manifold `\RR`.
|
|
914
|
+
- ``ambient`` -- (default: ``None``) an instance of
|
|
915
|
+
:class:`~sage.manifolds.differentiable.examples.real_line.RealLine`; construct
|
|
916
|
+
a subset of it. Using this keyword implies ``structure='differentiable'``.
|
|
917
|
+
- ``names`` or ``coordinate`` -- coordinate symbol for the canonical chart; see
|
|
918
|
+
:class:`~sage.manifolds.differentiable.examples.real_line.RealLine`. Using these
|
|
919
|
+
keywords implies ``structure='differentiable'``.
|
|
920
|
+
- ``name``, ``latex_name``, ``start_index`` -- see
|
|
921
|
+
:class:`~sage.manifolds.differentiable.examples.real_line.RealLine`
|
|
922
|
+
- ``normalized`` -- (default: ``None``) if ``True``, the input is already normalized,
|
|
923
|
+
i.e., ``*args`` are the connected components (type :class:`InternalRealInterval`)
|
|
924
|
+
of the real set in ascending order; no other keyword is provided.
|
|
925
|
+
|
|
926
|
+
There are also specialized constructors for various types of intervals:
|
|
927
|
+
|
|
928
|
+
====================================== ====================
|
|
929
|
+
Constructor Interval
|
|
930
|
+
====================================== ====================
|
|
931
|
+
:meth:`RealSet.open` `(a, b)`
|
|
932
|
+
:meth:`RealSet.closed` `[a, b]`
|
|
933
|
+
:meth:`RealSet.point` `\{a\}`
|
|
934
|
+
:meth:`RealSet.open_closed` `(a, b]`
|
|
935
|
+
:meth:`RealSet.closed_open` `[a, b)`
|
|
936
|
+
:meth:`RealSet.unbounded_below_closed` `(-\infty, b]`
|
|
937
|
+
:meth:`RealSet.unbounded_below_open` `(-\infty, b)`
|
|
938
|
+
:meth:`RealSet.unbounded_above_closed` `[a, +\infty)`
|
|
939
|
+
:meth:`RealSet.unbounded_above_open` `(a, +\infty)`
|
|
940
|
+
:meth:`RealSet.real_line` `(-\infty, +\infty)`
|
|
941
|
+
:meth:`RealSet.interval` any
|
|
942
|
+
====================================== ====================
|
|
943
|
+
|
|
944
|
+
EXAMPLES::
|
|
945
|
+
|
|
946
|
+
sage: RealSet(0, 1) # open set from two numbers
|
|
947
|
+
(0, 1)
|
|
948
|
+
sage: RealSet(1, 0) # the two numbers will be sorted
|
|
949
|
+
(0, 1)
|
|
950
|
+
sage: s1 = RealSet((1,2)); s1 # tuple of two numbers = open set
|
|
951
|
+
(1, 2)
|
|
952
|
+
sage: s2 = RealSet([3,4]); s2 # list of two numbers = closed set
|
|
953
|
+
[3, 4]
|
|
954
|
+
sage: i1, i2 = s1[0], s2[0]
|
|
955
|
+
sage: RealSet(i2, i1) # union of intervals
|
|
956
|
+
(1, 2) ∪ [3, 4]
|
|
957
|
+
sage: RealSet((-oo, 0), x > 6, i1, RealSet.point(5), # needs sage.symbolic
|
|
958
|
+
....: RealSet.closed_open(4, 3))
|
|
959
|
+
(-oo, 0) ∪ (1, 2) ∪ [3, 4) ∪ {5} ∪ (6, +oo)
|
|
960
|
+
|
|
961
|
+
Initialization from manifold objects::
|
|
962
|
+
|
|
963
|
+
sage: # needs sage.symbolic
|
|
964
|
+
sage: R = manifolds.RealLine(); R
|
|
965
|
+
Real number line ℝ
|
|
966
|
+
sage: RealSet(R)
|
|
967
|
+
(-oo, +oo)
|
|
968
|
+
sage: I02 = manifolds.OpenInterval(0, 2); I
|
|
969
|
+
I
|
|
970
|
+
sage: RealSet(I02)
|
|
971
|
+
(0, 2)
|
|
972
|
+
sage: I01_of_R = manifolds.OpenInterval(0, 1, ambient_interval=R); I01_of_R
|
|
973
|
+
Real interval (0, 1)
|
|
974
|
+
sage: RealSet(I01_of_R)
|
|
975
|
+
(0, 1)
|
|
976
|
+
sage: RealSet(I01_of_R.closure())
|
|
977
|
+
[0, 1]
|
|
978
|
+
sage: I01_of_I02 = manifolds.OpenInterval(0, 1,
|
|
979
|
+
....: ambient_interval=I02); I01_of_I02
|
|
980
|
+
Real interval (0, 1)
|
|
981
|
+
sage: RealSet(I01_of_I02)
|
|
982
|
+
(0, 1)
|
|
983
|
+
sage: RealSet(I01_of_I02.closure())
|
|
984
|
+
(0, 1]
|
|
985
|
+
|
|
986
|
+
Real sets belong to a subcategory of topological spaces::
|
|
987
|
+
|
|
988
|
+
sage: RealSet().category()
|
|
989
|
+
Join of
|
|
990
|
+
Category of finite sets and
|
|
991
|
+
Category of subobjects of sets and
|
|
992
|
+
Category of connected topological spaces
|
|
993
|
+
sage: RealSet.point(1).category()
|
|
994
|
+
Join of
|
|
995
|
+
Category of finite sets and
|
|
996
|
+
Category of subobjects of sets and
|
|
997
|
+
Category of connected topological spaces
|
|
998
|
+
sage: RealSet([1, 2]).category()
|
|
999
|
+
Join of
|
|
1000
|
+
Category of infinite sets and
|
|
1001
|
+
Category of compact topological spaces and
|
|
1002
|
+
Category of subobjects of sets and
|
|
1003
|
+
Category of connected topological spaces
|
|
1004
|
+
sage: RealSet((1, 2), (3, 4)).category()
|
|
1005
|
+
Join of
|
|
1006
|
+
Category of infinite sets and
|
|
1007
|
+
Category of subobjects of sets and
|
|
1008
|
+
Category of topological spaces
|
|
1009
|
+
|
|
1010
|
+
Constructing real sets as manifolds or manifold subsets by passing
|
|
1011
|
+
``structure='differentiable'``::
|
|
1012
|
+
|
|
1013
|
+
sage: # needs sage.symbolic
|
|
1014
|
+
sage: RealSet(-oo, oo, structure='differentiable')
|
|
1015
|
+
Real number line ℝ
|
|
1016
|
+
sage: RealSet([0, 1], structure='differentiable')
|
|
1017
|
+
Subset [0, 1] of the Real number line ℝ
|
|
1018
|
+
sage: _.category()
|
|
1019
|
+
Category of subobjects of sets
|
|
1020
|
+
sage: RealSet.open_closed(0, 5, structure='differentiable')
|
|
1021
|
+
Subset (0, 5] of the Real number line ℝ
|
|
1022
|
+
|
|
1023
|
+
This is implied when a coordinate name is given using the keywords ``coordinate``
|
|
1024
|
+
or ``names``::
|
|
1025
|
+
|
|
1026
|
+
sage: RealSet(0, 1, coordinate='λ') # needs sage.symbolic
|
|
1027
|
+
Open subset (0, 1) of the Real number line ℝ
|
|
1028
|
+
sage: _.category() # needs sage.symbolic
|
|
1029
|
+
Join of
|
|
1030
|
+
Category of smooth manifolds over Real Field with 53 bits of precision and
|
|
1031
|
+
Category of connected manifolds over Real Field with 53 bits of precision and
|
|
1032
|
+
Category of subobjects of sets
|
|
1033
|
+
|
|
1034
|
+
It is also implied by assigning a coordinate name using generator notation::
|
|
1035
|
+
|
|
1036
|
+
sage: R_xi.<ξ> = RealSet.real_line(); R_xi # needs sage.symbolic
|
|
1037
|
+
Real number line ℝ
|
|
1038
|
+
sage: R_xi.canonical_chart() # needs sage.symbolic
|
|
1039
|
+
Chart (ℝ, (ξ,))
|
|
1040
|
+
|
|
1041
|
+
With the keyword ``ambient``, we can construct a subset of a previously
|
|
1042
|
+
constructed manifold::
|
|
1043
|
+
|
|
1044
|
+
sage: # needs sage.symbolic
|
|
1045
|
+
sage: P_xi = RealSet(0, oo, ambient=R_xi); P_xi
|
|
1046
|
+
Open subset (0, +oo) of the Real number line ℝ
|
|
1047
|
+
sage: P_xi.default_chart()
|
|
1048
|
+
Chart ((0, +oo), (ξ,))
|
|
1049
|
+
sage: B_xi = RealSet(0, 1, ambient=P_xi); B_xi
|
|
1050
|
+
Open subset (0, 1) of the Real number line ℝ
|
|
1051
|
+
sage: B_xi.default_chart()
|
|
1052
|
+
Chart ((0, 1), (ξ,))
|
|
1053
|
+
sage: R_xi.subset_family()
|
|
1054
|
+
Set {(0, +oo), (0, 1), ℝ} of open subsets of the Real number line ℝ
|
|
1055
|
+
sage: F = RealSet.point(0).union(RealSet.point(1)).union(RealSet.point(2)); F
|
|
1056
|
+
{0} ∪ {1} ∪ {2}
|
|
1057
|
+
sage: F_tau = RealSet(F, names='τ'); F_tau
|
|
1058
|
+
Subset {0} ∪ {1} ∪ {2} of the Real number line ℝ
|
|
1059
|
+
sage: F_tau.manifold().canonical_chart()
|
|
1060
|
+
Chart (ℝ, (τ,))
|
|
1061
|
+
|
|
1062
|
+
TESTS::
|
|
1063
|
+
|
|
1064
|
+
sage: # needs sage.symbolic
|
|
1065
|
+
sage: TestSuite(R_xi).run()
|
|
1066
|
+
sage: TestSuite(P_xi).run()
|
|
1067
|
+
sage: R_xi.point((1,)) in P_xi
|
|
1068
|
+
True
|
|
1069
|
+
sage: R_xi.point((-1,)) in P_xi
|
|
1070
|
+
False
|
|
1071
|
+
sage: TestSuite(B_xi).run()
|
|
1072
|
+
sage: p = B_xi.an_element(); p
|
|
1073
|
+
Point on the Real number line ℝ
|
|
1074
|
+
sage: p.coordinates()
|
|
1075
|
+
(1/2,)
|
|
1076
|
+
"""
|
|
1077
|
+
|
|
1078
|
+
@staticmethod
|
|
1079
|
+
def __classcall__(cls, *args, **kwds):
|
|
1080
|
+
"""
|
|
1081
|
+
Normalize the input.
|
|
1082
|
+
|
|
1083
|
+
INPUT:
|
|
1084
|
+
|
|
1085
|
+
See :class:`RealSet`.
|
|
1086
|
+
|
|
1087
|
+
OUTPUT: a :class:`RealSet`
|
|
1088
|
+
|
|
1089
|
+
EXAMPLES::
|
|
1090
|
+
|
|
1091
|
+
sage: R = RealSet(RealSet.open_closed(0,1), RealSet.closed_open(2,3)); R
|
|
1092
|
+
(0, 1] ∪ [2, 3)
|
|
1093
|
+
|
|
1094
|
+
TESTS::
|
|
1095
|
+
|
|
1096
|
+
sage: # needs sage.symbolic
|
|
1097
|
+
sage: RealSet(x != 0)
|
|
1098
|
+
(-oo, 0) ∪ (0, +oo)
|
|
1099
|
+
sage: RealSet(x == pi)
|
|
1100
|
+
{pi}
|
|
1101
|
+
sage: RealSet(x < 1/2)
|
|
1102
|
+
(-oo, 1/2)
|
|
1103
|
+
sage: RealSet(1/2 < x)
|
|
1104
|
+
(1/2, +oo)
|
|
1105
|
+
sage: RealSet(1.5 <= x)
|
|
1106
|
+
[1.50000000000000, +oo)
|
|
1107
|
+
sage: RealSet(x >= -1)
|
|
1108
|
+
[-1, +oo)
|
|
1109
|
+
sage: RealSet(x > oo)
|
|
1110
|
+
{}
|
|
1111
|
+
sage: RealSet(x >= oo)
|
|
1112
|
+
{}
|
|
1113
|
+
sage: RealSet(x <= -oo)
|
|
1114
|
+
{}
|
|
1115
|
+
sage: RealSet(x < oo)
|
|
1116
|
+
(-oo, +oo)
|
|
1117
|
+
sage: RealSet(x > -oo)
|
|
1118
|
+
(-oo, +oo)
|
|
1119
|
+
sage: RealSet(x != oo)
|
|
1120
|
+
(-oo, +oo)
|
|
1121
|
+
sage: RealSet(x <= oo)
|
|
1122
|
+
Traceback (most recent call last):
|
|
1123
|
+
...
|
|
1124
|
+
ValueError: interval cannot be closed at +oo
|
|
1125
|
+
sage: RealSet(x == oo)
|
|
1126
|
+
Traceback (most recent call last):
|
|
1127
|
+
...
|
|
1128
|
+
ValueError: interval cannot be closed at +oo
|
|
1129
|
+
sage: RealSet(x >= -oo)
|
|
1130
|
+
Traceback (most recent call last):
|
|
1131
|
+
...
|
|
1132
|
+
ValueError: interval cannot be closed at -oo
|
|
1133
|
+
sage: r = RealSet(2,10)
|
|
1134
|
+
sage: RealSet((2, 6), (4, 10)) is r
|
|
1135
|
+
True
|
|
1136
|
+
sage: RealSet(x > 2).intersection(RealSet(x < 10)) is RealSet(r[0], normalized=True)
|
|
1137
|
+
True
|
|
1138
|
+
sage: RealSet(x > 0, normalized=True)
|
|
1139
|
+
Traceback (most recent call last):
|
|
1140
|
+
...
|
|
1141
|
+
AttributeError: ...
|
|
1142
|
+
"""
|
|
1143
|
+
normalized = kwds.pop('normalized', False)
|
|
1144
|
+
if normalized:
|
|
1145
|
+
# Fast path: The input is already normalized: Args is a list of
|
|
1146
|
+
# sorted and disjoint intervals of type InternalRealInterval.
|
|
1147
|
+
# No other kwds should be provided.
|
|
1148
|
+
return UniqueRepresentation.__classcall__(cls, *args, normalized=True)
|
|
1149
|
+
manifold_keywords = ('structure', 'ambient', 'names', 'coordinate')
|
|
1150
|
+
if any(kwds.get(kwd, None)
|
|
1151
|
+
for kwd in manifold_keywords):
|
|
1152
|
+
# Got manifold keywords
|
|
1153
|
+
real_set = cls.__classcall__(cls, *args)
|
|
1154
|
+
ambient = kwds.pop('ambient', None)
|
|
1155
|
+
structure = kwds.pop('structure', 'differentiable')
|
|
1156
|
+
if structure != 'differentiable':
|
|
1157
|
+
# TODO
|
|
1158
|
+
raise NotImplementedError
|
|
1159
|
+
|
|
1160
|
+
from sage.manifolds.differentiable.examples.real_line import RealLine
|
|
1161
|
+
if real_set.is_universe():
|
|
1162
|
+
if ambient is None:
|
|
1163
|
+
ambient = RealLine(**kwds)
|
|
1164
|
+
else:
|
|
1165
|
+
# TODO: Check that ambient makes sense
|
|
1166
|
+
pass
|
|
1167
|
+
return ambient
|
|
1168
|
+
|
|
1169
|
+
name = kwds.pop('name', None)
|
|
1170
|
+
latex_name = kwds.pop('latex_name', None)
|
|
1171
|
+
|
|
1172
|
+
if ambient is None:
|
|
1173
|
+
ambient = RealLine(**kwds)
|
|
1174
|
+
else:
|
|
1175
|
+
# TODO: Check that ambient makes sense
|
|
1176
|
+
pass
|
|
1177
|
+
|
|
1178
|
+
if name is None:
|
|
1179
|
+
name = str(real_set)
|
|
1180
|
+
if latex_name is None:
|
|
1181
|
+
from sage.misc.latex import latex
|
|
1182
|
+
latex_name = latex(real_set)
|
|
1183
|
+
|
|
1184
|
+
return ambient.manifold().canonical_chart().pullback(real_set, name=name, latex_name=latex_name)
|
|
1185
|
+
|
|
1186
|
+
if kwds:
|
|
1187
|
+
raise TypeError(f'RealSet constructors cannot take the keyword arguments {kwds}')
|
|
1188
|
+
|
|
1189
|
+
from sage.structure.element import Expression
|
|
1190
|
+
if len(args) == 1 and isinstance(args[0], RealSet):
|
|
1191
|
+
return args[0] # common optimization
|
|
1192
|
+
intervals = []
|
|
1193
|
+
if len(args) == 2:
|
|
1194
|
+
# allow RealSet(0,1) interval constructor
|
|
1195
|
+
try:
|
|
1196
|
+
lower, upper = args
|
|
1197
|
+
lower.n()
|
|
1198
|
+
upper.n()
|
|
1199
|
+
args = (RealSet._prep(lower, upper),)
|
|
1200
|
+
except (AttributeError, ValueError, TypeError):
|
|
1201
|
+
pass
|
|
1202
|
+
for arg in args:
|
|
1203
|
+
if isinstance(arg, tuple):
|
|
1204
|
+
lower, upper = RealSet._prep(*arg)
|
|
1205
|
+
intervals.append(InternalRealInterval(lower, False, upper, False))
|
|
1206
|
+
elif isinstance(arg, list):
|
|
1207
|
+
lower, upper = RealSet._prep(*arg)
|
|
1208
|
+
intervals.append(InternalRealInterval(lower, True, upper, True))
|
|
1209
|
+
elif isinstance(arg, InternalRealInterval):
|
|
1210
|
+
intervals.append(arg)
|
|
1211
|
+
elif isinstance(arg, RealSet):
|
|
1212
|
+
intervals.extend(arg._intervals)
|
|
1213
|
+
elif isinstance(arg, Expression) and arg.is_relational():
|
|
1214
|
+
from operator import eq, ne, lt, gt, le, ge
|
|
1215
|
+
|
|
1216
|
+
def rel_to_interval(op, val):
|
|
1217
|
+
"""
|
|
1218
|
+
Internal helper function.
|
|
1219
|
+
"""
|
|
1220
|
+
oo = infinity
|
|
1221
|
+
try:
|
|
1222
|
+
val = val.pyobject()
|
|
1223
|
+
except AttributeError:
|
|
1224
|
+
pass
|
|
1225
|
+
val = RLF(val)
|
|
1226
|
+
if op == eq:
|
|
1227
|
+
s = [InternalRealInterval(val, True, val, True)]
|
|
1228
|
+
elif op == gt:
|
|
1229
|
+
s = [InternalRealInterval(val, False, oo, False)]
|
|
1230
|
+
elif op == ge:
|
|
1231
|
+
s = [InternalRealInterval(val, True, oo, False)]
|
|
1232
|
+
elif op == lt:
|
|
1233
|
+
s = [InternalRealInterval(-oo, False, val, False)]
|
|
1234
|
+
elif op == le:
|
|
1235
|
+
s = [InternalRealInterval(-oo, False, val, True)]
|
|
1236
|
+
elif op == ne:
|
|
1237
|
+
s = [InternalRealInterval(-oo, False, val, False),
|
|
1238
|
+
InternalRealInterval(val, False, oo, False)]
|
|
1239
|
+
else:
|
|
1240
|
+
raise ValueError(str(arg) + ' does not determine real interval')
|
|
1241
|
+
return [i for i in s if not i.is_empty()]
|
|
1242
|
+
|
|
1243
|
+
if (arg.lhs().is_symbol()
|
|
1244
|
+
and (arg.rhs().is_numeric() or arg.rhs().is_constant())
|
|
1245
|
+
and arg.rhs().is_real()):
|
|
1246
|
+
intervals.extend(rel_to_interval(arg.operator(), arg.rhs()))
|
|
1247
|
+
elif (arg.rhs().is_symbol()
|
|
1248
|
+
and (arg.lhs().is_numeric() or arg.lhs().is_constant())
|
|
1249
|
+
and arg.lhs().is_real()):
|
|
1250
|
+
op = arg.operator()
|
|
1251
|
+
if op == lt:
|
|
1252
|
+
op = gt
|
|
1253
|
+
elif op == gt:
|
|
1254
|
+
op = lt
|
|
1255
|
+
elif op == le:
|
|
1256
|
+
op = ge
|
|
1257
|
+
elif op == ge:
|
|
1258
|
+
op = le
|
|
1259
|
+
intervals.extend(rel_to_interval(op, arg.lhs()))
|
|
1260
|
+
else:
|
|
1261
|
+
raise ValueError(str(arg) + ' does not determine real interval')
|
|
1262
|
+
else:
|
|
1263
|
+
from sage.manifolds.differentiable.examples.real_line import OpenInterval
|
|
1264
|
+
from sage.manifolds.subsets.closure import ManifoldSubsetClosure
|
|
1265
|
+
if isinstance(arg, OpenInterval):
|
|
1266
|
+
lower, upper = RealSet._prep(arg.lower_bound(), arg.upper_bound())
|
|
1267
|
+
intervals.append(InternalRealInterval(lower, False, upper, False))
|
|
1268
|
+
elif (isinstance(arg, ManifoldSubsetClosure)
|
|
1269
|
+
and isinstance(arg._subset, OpenInterval)):
|
|
1270
|
+
interval = arg._subset
|
|
1271
|
+
lower, upper = RealSet._prep(interval.lower_bound(),
|
|
1272
|
+
interval.upper_bound())
|
|
1273
|
+
ambient = interval.manifold()
|
|
1274
|
+
ambient_lower, ambient_upper = RealSet._prep(ambient.lower_bound(),
|
|
1275
|
+
ambient.upper_bound())
|
|
1276
|
+
lower_closed = ambient_lower < lower
|
|
1277
|
+
upper_closed = upper < ambient_upper
|
|
1278
|
+
intervals.append(InternalRealInterval(lower, lower_closed,
|
|
1279
|
+
upper, upper_closed))
|
|
1280
|
+
else:
|
|
1281
|
+
raise ValueError(str(arg) + ' does not determine real interval')
|
|
1282
|
+
|
|
1283
|
+
union_intervals = RealSet.normalize(intervals)
|
|
1284
|
+
return UniqueRepresentation.__classcall__(cls, *union_intervals, normalized=True)
|
|
1285
|
+
|
|
1286
|
+
def __init__(self, *intervals, normalized=True):
|
|
1287
|
+
r"""
|
|
1288
|
+
TESTS::
|
|
1289
|
+
|
|
1290
|
+
sage: Empty = RealSet(); Empty
|
|
1291
|
+
{}
|
|
1292
|
+
sage: TestSuite(Empty).run()
|
|
1293
|
+
sage: I1 = RealSet.open_closed(1, 3); I1
|
|
1294
|
+
(1, 3]
|
|
1295
|
+
sage: TestSuite(I1).run()
|
|
1296
|
+
sage: R = RealSet(RealSet.open_closed(0,1), RealSet.closed_open(2,3)); R
|
|
1297
|
+
(0, 1] ∪ [2, 3)
|
|
1298
|
+
sage: TestSuite(R).run()
|
|
1299
|
+
"""
|
|
1300
|
+
category = TopologicalSpaces()
|
|
1301
|
+
if len(intervals) <= 1:
|
|
1302
|
+
category = category.Connected()
|
|
1303
|
+
if all(i.is_point() for i in intervals):
|
|
1304
|
+
category = category.Subobjects().Finite()
|
|
1305
|
+
else:
|
|
1306
|
+
# Have at least one non-degenerate interval
|
|
1307
|
+
category = category.Infinite()
|
|
1308
|
+
inf = intervals[0].lower()
|
|
1309
|
+
sup = intervals[-1].upper()
|
|
1310
|
+
if not (len(intervals) == 1 and inf is minus_infinity and sup is infinity):
|
|
1311
|
+
category = category.Subobjects() # subobject of real line
|
|
1312
|
+
if inf is not minus_infinity and sup is not infinity:
|
|
1313
|
+
# Bounded
|
|
1314
|
+
if all(i.lower_closed() and i.upper_closed()
|
|
1315
|
+
for i in intervals):
|
|
1316
|
+
category = category.Compact()
|
|
1317
|
+
Parent.__init__(self, category=category)
|
|
1318
|
+
self._intervals = intervals
|
|
1319
|
+
|
|
1320
|
+
def __richcmp__(self, other, op):
|
|
1321
|
+
r"""
|
|
1322
|
+
Intervals are sorted by lower bound, then upper bound.
|
|
1323
|
+
|
|
1324
|
+
OUTPUT: `-1`, `0`, or `+1` depending on how the intervals compare
|
|
1325
|
+
|
|
1326
|
+
EXAMPLES::
|
|
1327
|
+
|
|
1328
|
+
sage: I1 = RealSet.open_closed(1, 3); I1
|
|
1329
|
+
(1, 3]
|
|
1330
|
+
sage: I2 = RealSet.open_closed(0, 5); I2
|
|
1331
|
+
(0, 5]
|
|
1332
|
+
sage: I1 > I2
|
|
1333
|
+
True
|
|
1334
|
+
sage: sorted([I1, I2])
|
|
1335
|
+
[(0, 5], (1, 3]]
|
|
1336
|
+
sage: I1 == I1
|
|
1337
|
+
True
|
|
1338
|
+
"""
|
|
1339
|
+
if not isinstance(other, RealSet):
|
|
1340
|
+
return NotImplemented
|
|
1341
|
+
# note that the interval representation is normalized into a
|
|
1342
|
+
# unique form
|
|
1343
|
+
return richcmp(self._intervals, other._intervals, op)
|
|
1344
|
+
|
|
1345
|
+
def __iter__(self):
|
|
1346
|
+
r"""
|
|
1347
|
+
Iterate over the component intervals is ascending order.
|
|
1348
|
+
|
|
1349
|
+
OUTPUT: an iterator over the intervals
|
|
1350
|
+
|
|
1351
|
+
EXAMPLES::
|
|
1352
|
+
|
|
1353
|
+
sage: s = RealSet(RealSet.open_closed(0,1), RealSet.closed_open(2,3))
|
|
1354
|
+
sage: i = iter(s)
|
|
1355
|
+
sage: next(i)
|
|
1356
|
+
(0, 1]
|
|
1357
|
+
sage: next(i)
|
|
1358
|
+
[2, 3)
|
|
1359
|
+
"""
|
|
1360
|
+
return iter(self._intervals)
|
|
1361
|
+
|
|
1362
|
+
def n_components(self):
|
|
1363
|
+
r"""
|
|
1364
|
+
Return the number of connected components.
|
|
1365
|
+
|
|
1366
|
+
See also :meth:`get_interval`.
|
|
1367
|
+
|
|
1368
|
+
EXAMPLES::
|
|
1369
|
+
|
|
1370
|
+
sage: s = RealSet(RealSet.open_closed(0,1), RealSet.closed_open(2,3))
|
|
1371
|
+
sage: s.n_components()
|
|
1372
|
+
2
|
|
1373
|
+
"""
|
|
1374
|
+
return len(self._intervals)
|
|
1375
|
+
|
|
1376
|
+
def cardinality(self):
|
|
1377
|
+
r"""
|
|
1378
|
+
Return the cardinality of the subset of the real line.
|
|
1379
|
+
|
|
1380
|
+
OUTPUT:
|
|
1381
|
+
|
|
1382
|
+
Integer or infinity; the size of a discrete set is the number
|
|
1383
|
+
of points; the size of a real interval is Infinity.
|
|
1384
|
+
|
|
1385
|
+
EXAMPLES::
|
|
1386
|
+
|
|
1387
|
+
sage: RealSet([0, 0], [1, 1], [3, 3]).cardinality()
|
|
1388
|
+
3
|
|
1389
|
+
sage: RealSet(0,3).cardinality()
|
|
1390
|
+
+Infinity
|
|
1391
|
+
"""
|
|
1392
|
+
n = ZZ(0)
|
|
1393
|
+
for interval in self._intervals:
|
|
1394
|
+
if interval.is_point():
|
|
1395
|
+
n += 1
|
|
1396
|
+
else:
|
|
1397
|
+
return infinity
|
|
1398
|
+
return n
|
|
1399
|
+
|
|
1400
|
+
def is_empty(self):
|
|
1401
|
+
r"""
|
|
1402
|
+
Return whether the set is empty.
|
|
1403
|
+
|
|
1404
|
+
EXAMPLES::
|
|
1405
|
+
|
|
1406
|
+
sage: RealSet(0, 1).is_empty()
|
|
1407
|
+
False
|
|
1408
|
+
sage: RealSet(0, 0).is_empty()
|
|
1409
|
+
True
|
|
1410
|
+
sage: RealSet.interval(1, 1, lower_closed=False, upper_closed=True).is_empty()
|
|
1411
|
+
True
|
|
1412
|
+
sage: RealSet.interval(1, -1, lower_closed=False, upper_closed=True).is_empty()
|
|
1413
|
+
False
|
|
1414
|
+
"""
|
|
1415
|
+
return len(self._intervals) == 0
|
|
1416
|
+
|
|
1417
|
+
def is_universe(self):
|
|
1418
|
+
r"""
|
|
1419
|
+
Return whether the set is the ambient space (the real line).
|
|
1420
|
+
|
|
1421
|
+
EXAMPLES::
|
|
1422
|
+
|
|
1423
|
+
sage: RealSet().ambient().is_universe()
|
|
1424
|
+
True
|
|
1425
|
+
"""
|
|
1426
|
+
return self == self.ambient()
|
|
1427
|
+
|
|
1428
|
+
def get_interval(self, i):
|
|
1429
|
+
r"""
|
|
1430
|
+
Return the ``i``-th connected component.
|
|
1431
|
+
|
|
1432
|
+
Note that the intervals representing the real set are always
|
|
1433
|
+
normalized, i.e., they are sorted, disjoint and not connected.
|
|
1434
|
+
|
|
1435
|
+
INPUT:
|
|
1436
|
+
|
|
1437
|
+
- ``i`` -- integer
|
|
1438
|
+
|
|
1439
|
+
OUTPUT: the `i`-th connected component as a :class:`InternalRealInterval`
|
|
1440
|
+
|
|
1441
|
+
EXAMPLES::
|
|
1442
|
+
|
|
1443
|
+
sage: s = RealSet(RealSet.open_closed(0,1), RealSet.closed_open(2,3))
|
|
1444
|
+
sage: s.get_interval(0)
|
|
1445
|
+
(0, 1]
|
|
1446
|
+
sage: s[0] # shorthand
|
|
1447
|
+
(0, 1]
|
|
1448
|
+
sage: s.get_interval(1)
|
|
1449
|
+
[2, 3)
|
|
1450
|
+
sage: s[0] == s.get_interval(0)
|
|
1451
|
+
True
|
|
1452
|
+
"""
|
|
1453
|
+
return self._intervals[i]
|
|
1454
|
+
|
|
1455
|
+
__getitem__ = get_interval
|
|
1456
|
+
|
|
1457
|
+
def __bool__(self):
|
|
1458
|
+
r"""
|
|
1459
|
+
A set is considered ``True`` unless it is empty, in which case it is
|
|
1460
|
+
considered to be ``False``.
|
|
1461
|
+
|
|
1462
|
+
EXAMPLES::
|
|
1463
|
+
|
|
1464
|
+
sage: bool(RealSet(0, 1))
|
|
1465
|
+
True
|
|
1466
|
+
sage: bool(RealSet())
|
|
1467
|
+
False
|
|
1468
|
+
"""
|
|
1469
|
+
return not self.is_empty()
|
|
1470
|
+
|
|
1471
|
+
# ParentMethods of Subobjects
|
|
1472
|
+
|
|
1473
|
+
def ambient(self):
|
|
1474
|
+
r"""
|
|
1475
|
+
Return the ambient space (the real line).
|
|
1476
|
+
|
|
1477
|
+
EXAMPLES::
|
|
1478
|
+
|
|
1479
|
+
sage: s = RealSet(RealSet.open_closed(0,1), RealSet.closed_open(2,3))
|
|
1480
|
+
sage: s.ambient()
|
|
1481
|
+
(-oo, +oo)
|
|
1482
|
+
"""
|
|
1483
|
+
return RealSet.real_line()
|
|
1484
|
+
|
|
1485
|
+
def lift(self, x):
|
|
1486
|
+
r"""
|
|
1487
|
+
Lift ``x`` to the ambient space for ``self``.
|
|
1488
|
+
|
|
1489
|
+
This version of the method just returns ``x``.
|
|
1490
|
+
|
|
1491
|
+
EXAMPLES::
|
|
1492
|
+
|
|
1493
|
+
sage: s = RealSet(0, 2); s
|
|
1494
|
+
(0, 2)
|
|
1495
|
+
sage: s.lift(1)
|
|
1496
|
+
1
|
|
1497
|
+
"""
|
|
1498
|
+
return x
|
|
1499
|
+
|
|
1500
|
+
def retract(self, x):
|
|
1501
|
+
r"""
|
|
1502
|
+
Retract ``x`` to ``self``.
|
|
1503
|
+
|
|
1504
|
+
It raises an error if ``x`` does not lie in the set ``self``.
|
|
1505
|
+
|
|
1506
|
+
EXAMPLES::
|
|
1507
|
+
|
|
1508
|
+
sage: s = RealSet(0, 2); s
|
|
1509
|
+
(0, 2)
|
|
1510
|
+
sage: s.retract(1)
|
|
1511
|
+
1
|
|
1512
|
+
sage: s.retract(2)
|
|
1513
|
+
Traceback (most recent call last):
|
|
1514
|
+
...
|
|
1515
|
+
ValueError: 2 is not an element of (0, 2)
|
|
1516
|
+
"""
|
|
1517
|
+
if x not in self:
|
|
1518
|
+
raise ValueError(f'{x} is not an element of {self}')
|
|
1519
|
+
return x
|
|
1520
|
+
|
|
1521
|
+
def normalize(intervals):
|
|
1522
|
+
r"""
|
|
1523
|
+
Bring a collection of intervals into canonical form.
|
|
1524
|
+
|
|
1525
|
+
INPUT:
|
|
1526
|
+
|
|
1527
|
+
- ``intervals`` -- list/tuple/iterable of intervals
|
|
1528
|
+
|
|
1529
|
+
OUTPUT: a tuple of intervals such that
|
|
1530
|
+
|
|
1531
|
+
* they are sorted in ascending order (by lower bound)
|
|
1532
|
+
|
|
1533
|
+
* there is a gap between each interval
|
|
1534
|
+
|
|
1535
|
+
* all intervals are non-empty
|
|
1536
|
+
|
|
1537
|
+
EXAMPLES::
|
|
1538
|
+
|
|
1539
|
+
sage: i1 = RealSet((0, 1))[0]
|
|
1540
|
+
sage: i2 = RealSet([1, 2])[0]
|
|
1541
|
+
sage: i3 = RealSet((2, 3))[0]
|
|
1542
|
+
sage: RealSet.normalize([i1, i2, i3])
|
|
1543
|
+
((0, 3),)
|
|
1544
|
+
"""
|
|
1545
|
+
scan = merge(*[[i._scan_lower(), i._scan_upper()] for i in intervals])
|
|
1546
|
+
union_intervals = tuple(RealSet._scan_to_intervals(scan, lambda i: i > 0))
|
|
1547
|
+
return union_intervals
|
|
1548
|
+
|
|
1549
|
+
def _repr_(self):
|
|
1550
|
+
r"""
|
|
1551
|
+
Return a string representation of ``self``.
|
|
1552
|
+
|
|
1553
|
+
OUTPUT: string representation
|
|
1554
|
+
|
|
1555
|
+
EXAMPLES::
|
|
1556
|
+
|
|
1557
|
+
sage: RealSet(0, 1)._repr_()
|
|
1558
|
+
'(0, 1)'
|
|
1559
|
+
"""
|
|
1560
|
+
if self.n_components() == 0:
|
|
1561
|
+
return '{}'
|
|
1562
|
+
else:
|
|
1563
|
+
return ' ∪ '.join(map(repr, self._intervals))
|
|
1564
|
+
|
|
1565
|
+
def _latex_(self):
|
|
1566
|
+
r"""
|
|
1567
|
+
Return a latex representation of ``self``.
|
|
1568
|
+
|
|
1569
|
+
EXAMPLES::
|
|
1570
|
+
|
|
1571
|
+
sage: latex(RealSet(0, 1))
|
|
1572
|
+
(0, 1)
|
|
1573
|
+
sage: latex((RealSet(0, 1).union(RealSet.unbounded_above_closed(2))))
|
|
1574
|
+
(0, 1) \cup [2, +\infty)
|
|
1575
|
+
"""
|
|
1576
|
+
from sage.misc.latex import latex
|
|
1577
|
+
if self.n_components() == 0:
|
|
1578
|
+
return r'\emptyset'
|
|
1579
|
+
else:
|
|
1580
|
+
return r' \cup '.join(latex(i) for i in self._intervals)
|
|
1581
|
+
|
|
1582
|
+
def _sympy_condition_(self, variable):
|
|
1583
|
+
r"""
|
|
1584
|
+
Convert to a sympy conditional expression.
|
|
1585
|
+
|
|
1586
|
+
INPUT:
|
|
1587
|
+
|
|
1588
|
+
- ``variable`` -- a symbolic variable
|
|
1589
|
+
|
|
1590
|
+
EXAMPLES::
|
|
1591
|
+
|
|
1592
|
+
sage: # needs sage.symbolic
|
|
1593
|
+
sage: RealSet(0, 1)._sympy_condition_(x)
|
|
1594
|
+
(0 < x) & (x < 1)
|
|
1595
|
+
sage: RealSet((0,1), [2,3])._sympy_condition_(x)
|
|
1596
|
+
((2 <= x) & (x <= 3)) | ((0 < x) & (x < 1))
|
|
1597
|
+
sage: RealSet.unbounded_below_open(0)._sympy_condition_(x)
|
|
1598
|
+
x < 0
|
|
1599
|
+
sage: RealSet.unbounded_above_closed(2)._sympy_condition_(x)
|
|
1600
|
+
2 <= x
|
|
1601
|
+
|
|
1602
|
+
TESTS::
|
|
1603
|
+
|
|
1604
|
+
sage: RealSet(6,6)._sympy_condition_(x) # needs sympy sage.symbolic
|
|
1605
|
+
False
|
|
1606
|
+
sage: RealSet([6,6])._sympy_condition_(x) # needs sympy sage.symbolic
|
|
1607
|
+
Eq(x, 6)
|
|
1608
|
+
"""
|
|
1609
|
+
x = variable
|
|
1610
|
+
false = (x == 0)._sympy_() & False # trick to get sympy's False
|
|
1611
|
+
if self.n_components() == 0:
|
|
1612
|
+
return false
|
|
1613
|
+
else:
|
|
1614
|
+
cond = false
|
|
1615
|
+
for it in self._intervals:
|
|
1616
|
+
cond = cond | it._sympy_condition_(x)
|
|
1617
|
+
return cond
|
|
1618
|
+
|
|
1619
|
+
def _giac_condition_(self, variable):
|
|
1620
|
+
r"""
|
|
1621
|
+
Convert to a Giac conditional expression.
|
|
1622
|
+
|
|
1623
|
+
INPUT:
|
|
1624
|
+
|
|
1625
|
+
- ``variable`` -- a symbolic variable
|
|
1626
|
+
|
|
1627
|
+
EXAMPLES::
|
|
1628
|
+
|
|
1629
|
+
sage: # needs sage.libs.giac
|
|
1630
|
+
sage: RealSet(0, 1)._giac_condition_(x)
|
|
1631
|
+
'((0 < sageVARx) and (sageVARx < 1))'
|
|
1632
|
+
sage: RealSet((0,1), [2,3])._giac_condition_(x)
|
|
1633
|
+
'((0 < sageVARx) and (sageVARx < 1)) or ((2 <= sageVARx) and (sageVARx <= 3))'
|
|
1634
|
+
sage: RealSet.unbounded_below_open(0)._giac_condition_(x)
|
|
1635
|
+
'((true) and (sageVARx < 0))'
|
|
1636
|
+
sage: RealSet.unbounded_above_closed(2)._giac_condition_(x)
|
|
1637
|
+
'((2 <= sageVARx) and (true))'
|
|
1638
|
+
|
|
1639
|
+
TESTS::
|
|
1640
|
+
|
|
1641
|
+
sage: RealSet(6,6)._giac_condition_(x) # needs sage.libs.giac
|
|
1642
|
+
'false'
|
|
1643
|
+
sage: RealSet([6,6])._giac_condition_(x) # needs sage.libs.giac
|
|
1644
|
+
'sageVARx == 6'
|
|
1645
|
+
"""
|
|
1646
|
+
x = variable
|
|
1647
|
+
false = 'false'
|
|
1648
|
+
if self.n_components() == 0:
|
|
1649
|
+
return false
|
|
1650
|
+
return ' or '.join(it._giac_condition_(x)
|
|
1651
|
+
for it in self._intervals)
|
|
1652
|
+
|
|
1653
|
+
@staticmethod
|
|
1654
|
+
def _prep(lower, upper=None):
|
|
1655
|
+
r"""
|
|
1656
|
+
Helper to prepare the lower and upper bounds.
|
|
1657
|
+
|
|
1658
|
+
EXAMPLES::
|
|
1659
|
+
|
|
1660
|
+
sage: RealSet._prep(1, 0)
|
|
1661
|
+
(0, 1)
|
|
1662
|
+
sage: RealSet._prep(-oo,+oo)
|
|
1663
|
+
(-Infinity, +Infinity)
|
|
1664
|
+
sage: RealSet._prep(oo)
|
|
1665
|
+
+Infinity
|
|
1666
|
+
"""
|
|
1667
|
+
if lower == minus_infinity:
|
|
1668
|
+
lower = minus_infinity
|
|
1669
|
+
elif lower == infinity:
|
|
1670
|
+
lower = infinity
|
|
1671
|
+
else:
|
|
1672
|
+
lower = RLF(lower)
|
|
1673
|
+
if upper is None:
|
|
1674
|
+
return lower
|
|
1675
|
+
if upper == minus_infinity:
|
|
1676
|
+
upper = minus_infinity
|
|
1677
|
+
elif upper == infinity:
|
|
1678
|
+
upper = infinity
|
|
1679
|
+
else:
|
|
1680
|
+
upper = RLF(upper)
|
|
1681
|
+
if upper is infinity or lower is minus_infinity:
|
|
1682
|
+
return lower, upper
|
|
1683
|
+
elif lower is infinity or upper is minus_infinity:
|
|
1684
|
+
return upper, lower
|
|
1685
|
+
elif upper < lower:
|
|
1686
|
+
return upper, lower
|
|
1687
|
+
else:
|
|
1688
|
+
return lower, upper
|
|
1689
|
+
|
|
1690
|
+
@staticmethod
|
|
1691
|
+
def interval(lower, upper, *, lower_closed=None, upper_closed=None, **kwds):
|
|
1692
|
+
r"""
|
|
1693
|
+
Construct an interval.
|
|
1694
|
+
|
|
1695
|
+
INPUT:
|
|
1696
|
+
|
|
1697
|
+
- ``lower``, ``upper`` -- two real numbers or infinity; they
|
|
1698
|
+
will be sorted if necessary
|
|
1699
|
+
|
|
1700
|
+
- ``lower_closed``, ``upper_closed`` -- boolean; whether the interval
|
|
1701
|
+
is closed at the lower and upper bound of the interval, respectively
|
|
1702
|
+
|
|
1703
|
+
- ``**kwds`` -- see :class:`RealSet`
|
|
1704
|
+
|
|
1705
|
+
OUTPUT: a new :class:`RealSet`
|
|
1706
|
+
|
|
1707
|
+
EXAMPLES::
|
|
1708
|
+
|
|
1709
|
+
sage: RealSet.interval(1, 0, lower_closed=True, upper_closed=False)
|
|
1710
|
+
[0, 1)
|
|
1711
|
+
"""
|
|
1712
|
+
if lower_closed is None or upper_closed is None:
|
|
1713
|
+
raise ValueError('lower_closed and upper_closed must be explicitly given')
|
|
1714
|
+
lower, upper = RealSet._prep(lower, upper)
|
|
1715
|
+
return RealSet(InternalRealInterval(lower, lower_closed, upper, upper_closed), **kwds)
|
|
1716
|
+
|
|
1717
|
+
@staticmethod
|
|
1718
|
+
def open(lower, upper, **kwds):
|
|
1719
|
+
r"""
|
|
1720
|
+
Construct an open interval.
|
|
1721
|
+
|
|
1722
|
+
INPUT:
|
|
1723
|
+
|
|
1724
|
+
- ``lower``, ``upper`` -- two real numbers or infinity; they
|
|
1725
|
+
will be sorted if necessary
|
|
1726
|
+
|
|
1727
|
+
- ``**kwds`` -- see :class:`RealSet`
|
|
1728
|
+
|
|
1729
|
+
OUTPUT: a new :class:`RealSet`
|
|
1730
|
+
|
|
1731
|
+
EXAMPLES::
|
|
1732
|
+
|
|
1733
|
+
sage: RealSet.open(1, 0)
|
|
1734
|
+
(0, 1)
|
|
1735
|
+
"""
|
|
1736
|
+
lower, upper = RealSet._prep(lower, upper)
|
|
1737
|
+
return RealSet(InternalRealInterval(lower, False, upper, False), **kwds)
|
|
1738
|
+
|
|
1739
|
+
@staticmethod
|
|
1740
|
+
def closed(lower, upper, **kwds):
|
|
1741
|
+
r"""
|
|
1742
|
+
Construct a closed interval.
|
|
1743
|
+
|
|
1744
|
+
INPUT:
|
|
1745
|
+
|
|
1746
|
+
- ``lower``, ``upper`` -- two real numbers or infinity; they
|
|
1747
|
+
will be sorted if necessary
|
|
1748
|
+
|
|
1749
|
+
- ``**kwds`` -- see :class:`RealSet`
|
|
1750
|
+
|
|
1751
|
+
OUTPUT: a new :class:`RealSet`
|
|
1752
|
+
|
|
1753
|
+
EXAMPLES::
|
|
1754
|
+
|
|
1755
|
+
sage: RealSet.closed(1, 0)
|
|
1756
|
+
[0, 1]
|
|
1757
|
+
"""
|
|
1758
|
+
lower, upper = RealSet._prep(lower, upper)
|
|
1759
|
+
return RealSet(InternalRealInterval(lower, True, upper, True), **kwds)
|
|
1760
|
+
|
|
1761
|
+
@staticmethod
|
|
1762
|
+
def point(p, **kwds):
|
|
1763
|
+
r"""
|
|
1764
|
+
Construct an interval containing a single point.
|
|
1765
|
+
|
|
1766
|
+
INPUT:
|
|
1767
|
+
|
|
1768
|
+
- ``p`` -- a real number
|
|
1769
|
+
|
|
1770
|
+
- ``**kwds`` -- see :class:`RealSet`
|
|
1771
|
+
|
|
1772
|
+
OUTPUT: a new :class:`RealSet`
|
|
1773
|
+
|
|
1774
|
+
EXAMPLES::
|
|
1775
|
+
|
|
1776
|
+
sage: RealSet.open(1, 0)
|
|
1777
|
+
(0, 1)
|
|
1778
|
+
"""
|
|
1779
|
+
p = RealSet._prep(p)
|
|
1780
|
+
return RealSet(InternalRealInterval(p, True, p, True), **kwds)
|
|
1781
|
+
|
|
1782
|
+
@staticmethod
|
|
1783
|
+
def open_closed(lower, upper, **kwds):
|
|
1784
|
+
r"""
|
|
1785
|
+
Construct a half-open interval.
|
|
1786
|
+
|
|
1787
|
+
INPUT:
|
|
1788
|
+
|
|
1789
|
+
- ``lower``, ``upper`` -- two real numbers or infinity; they
|
|
1790
|
+
will be sorted if necessary
|
|
1791
|
+
|
|
1792
|
+
- ``**kwds`` -- see :class:`RealSet`
|
|
1793
|
+
|
|
1794
|
+
OUTPUT:
|
|
1795
|
+
|
|
1796
|
+
A new :class:`RealSet` that is open at the lower bound and
|
|
1797
|
+
closed at the upper bound.
|
|
1798
|
+
|
|
1799
|
+
EXAMPLES::
|
|
1800
|
+
|
|
1801
|
+
sage: RealSet.open_closed(1, 0)
|
|
1802
|
+
(0, 1]
|
|
1803
|
+
"""
|
|
1804
|
+
lower, upper = RealSet._prep(lower, upper)
|
|
1805
|
+
return RealSet(InternalRealInterval(lower, False, upper, True), **kwds)
|
|
1806
|
+
|
|
1807
|
+
@staticmethod
|
|
1808
|
+
def closed_open(lower, upper, **kwds):
|
|
1809
|
+
r"""
|
|
1810
|
+
Construct a half-open interval.
|
|
1811
|
+
|
|
1812
|
+
INPUT:
|
|
1813
|
+
|
|
1814
|
+
- ``lower``, ``upper`` -- two real numbers or infinity; they
|
|
1815
|
+
will be sorted if necessary
|
|
1816
|
+
|
|
1817
|
+
- ``**kwds`` -- see :class:`RealSet`
|
|
1818
|
+
|
|
1819
|
+
OUTPUT:
|
|
1820
|
+
|
|
1821
|
+
A new :class:`RealSet` that is closed at the lower bound and
|
|
1822
|
+
open at the upper bound.
|
|
1823
|
+
|
|
1824
|
+
EXAMPLES::
|
|
1825
|
+
|
|
1826
|
+
sage: RealSet.closed_open(1, 0)
|
|
1827
|
+
[0, 1)
|
|
1828
|
+
"""
|
|
1829
|
+
lower, upper = RealSet._prep(lower, upper)
|
|
1830
|
+
return RealSet(InternalRealInterval(lower, True, upper, False), **kwds)
|
|
1831
|
+
|
|
1832
|
+
@staticmethod
|
|
1833
|
+
def unbounded_below_closed(bound, **kwds):
|
|
1834
|
+
r"""
|
|
1835
|
+
Construct a semi-infinite interval.
|
|
1836
|
+
|
|
1837
|
+
INPUT:
|
|
1838
|
+
|
|
1839
|
+
- ``bound`` -- a real number
|
|
1840
|
+
|
|
1841
|
+
OUTPUT:
|
|
1842
|
+
|
|
1843
|
+
A new :class:`RealSet` from minus infinity to the bound (including).
|
|
1844
|
+
|
|
1845
|
+
- ``**kwds`` -- see :class:`RealSet`
|
|
1846
|
+
|
|
1847
|
+
EXAMPLES::
|
|
1848
|
+
|
|
1849
|
+
sage: RealSet.unbounded_below_closed(1)
|
|
1850
|
+
(-oo, 1]
|
|
1851
|
+
"""
|
|
1852
|
+
bound = RealSet._prep(bound)
|
|
1853
|
+
return RealSet(InternalRealInterval(minus_infinity, False, bound, True), **kwds)
|
|
1854
|
+
|
|
1855
|
+
@staticmethod
|
|
1856
|
+
def unbounded_below_open(bound, **kwds):
|
|
1857
|
+
r"""
|
|
1858
|
+
Construct a semi-infinite interval.
|
|
1859
|
+
|
|
1860
|
+
INPUT:
|
|
1861
|
+
|
|
1862
|
+
- ``bound`` -- a real number
|
|
1863
|
+
|
|
1864
|
+
OUTPUT:
|
|
1865
|
+
|
|
1866
|
+
A new :class:`RealSet` from minus infinity to the bound (excluding).
|
|
1867
|
+
|
|
1868
|
+
- ``**kwds`` -- see :class:`RealSet`
|
|
1869
|
+
|
|
1870
|
+
EXAMPLES::
|
|
1871
|
+
|
|
1872
|
+
sage: RealSet.unbounded_below_open(1)
|
|
1873
|
+
(-oo, 1)
|
|
1874
|
+
"""
|
|
1875
|
+
bound = RealSet._prep(bound)
|
|
1876
|
+
return RealSet(InternalRealInterval(minus_infinity, False, RLF(bound), False), **kwds)
|
|
1877
|
+
|
|
1878
|
+
@staticmethod
|
|
1879
|
+
def unbounded_above_closed(bound, **kwds):
|
|
1880
|
+
r"""
|
|
1881
|
+
Construct a semi-infinite interval.
|
|
1882
|
+
|
|
1883
|
+
INPUT:
|
|
1884
|
+
|
|
1885
|
+
- ``bound`` -- a real number
|
|
1886
|
+
|
|
1887
|
+
- ``**kwds`` -- see :class:`RealSet`
|
|
1888
|
+
|
|
1889
|
+
OUTPUT:
|
|
1890
|
+
|
|
1891
|
+
A new :class:`RealSet` from the bound (including) to plus
|
|
1892
|
+
infinity.
|
|
1893
|
+
|
|
1894
|
+
EXAMPLES::
|
|
1895
|
+
|
|
1896
|
+
sage: RealSet.unbounded_above_closed(1)
|
|
1897
|
+
[1, +oo)
|
|
1898
|
+
"""
|
|
1899
|
+
bound = RealSet._prep(bound)
|
|
1900
|
+
return RealSet(InternalRealInterval(RLF(bound), True, infinity, False), **kwds)
|
|
1901
|
+
|
|
1902
|
+
@staticmethod
|
|
1903
|
+
def unbounded_above_open(bound, **kwds):
|
|
1904
|
+
r"""
|
|
1905
|
+
Construct a semi-infinite interval.
|
|
1906
|
+
|
|
1907
|
+
INPUT:
|
|
1908
|
+
|
|
1909
|
+
- ``bound`` -- a real number
|
|
1910
|
+
|
|
1911
|
+
- ``**kwds`` -- see :class:`RealSet`
|
|
1912
|
+
|
|
1913
|
+
OUTPUT:
|
|
1914
|
+
|
|
1915
|
+
A new :class:`RealSet` from the bound (excluding) to plus
|
|
1916
|
+
infinity.
|
|
1917
|
+
|
|
1918
|
+
EXAMPLES::
|
|
1919
|
+
|
|
1920
|
+
sage: RealSet.unbounded_above_open(1)
|
|
1921
|
+
(1, +oo)
|
|
1922
|
+
"""
|
|
1923
|
+
bound = RealSet._prep(bound)
|
|
1924
|
+
return RealSet(InternalRealInterval(RLF(bound), False, infinity, False), **kwds)
|
|
1925
|
+
|
|
1926
|
+
@staticmethod
|
|
1927
|
+
def real_line(**kwds):
|
|
1928
|
+
r"""
|
|
1929
|
+
Construct the real line.
|
|
1930
|
+
|
|
1931
|
+
INPUT:
|
|
1932
|
+
|
|
1933
|
+
- ``**kwds`` -- see :class:`RealSet`
|
|
1934
|
+
|
|
1935
|
+
EXAMPLES::
|
|
1936
|
+
|
|
1937
|
+
sage: RealSet.real_line()
|
|
1938
|
+
(-oo, +oo)
|
|
1939
|
+
"""
|
|
1940
|
+
return RealSet(InternalRealInterval(minus_infinity, False, infinity, False), **kwds)
|
|
1941
|
+
|
|
1942
|
+
def _scan(self):
|
|
1943
|
+
r"""
|
|
1944
|
+
Helper function for the scan-line method of :class:`RealSet`.
|
|
1945
|
+
|
|
1946
|
+
OUTPUT:
|
|
1947
|
+
|
|
1948
|
+
Generate events of the form ``(x, epsilon), delta``
|
|
1949
|
+
for each boundary point ``x`` of ``self``.
|
|
1950
|
+
|
|
1951
|
+
When ``x`` is the beginning of an interval ('on'):
|
|
1952
|
+
|
|
1953
|
+
- ``epsilon`` is 0 if the interval is lower closed and 1 otherwise,
|
|
1954
|
+
- ``delta`` is -1
|
|
1955
|
+
|
|
1956
|
+
When ``x`` is the end of an interval ('off'):
|
|
1957
|
+
|
|
1958
|
+
- ``epsilon`` is 1 if the interval is upper closed and 0 otherwise,
|
|
1959
|
+
- ``delta`` is +1
|
|
1960
|
+
|
|
1961
|
+
This is so that the events sort lexicographically in a way that if
|
|
1962
|
+
we have intervals whose closures intersect in one point, such as
|
|
1963
|
+
[a, b) and [b, c], we see first the 'on' event and then the 'off'
|
|
1964
|
+
event. In this way consumers of the scan can easily implement merging
|
|
1965
|
+
of such intervals.
|
|
1966
|
+
|
|
1967
|
+
EXAMPLES::
|
|
1968
|
+
|
|
1969
|
+
sage: s = RealSet((-oo,0), RealSet.open_closed(0, 1), (2, 3), [4, 5], [5, 5], (6, oo)); s
|
|
1970
|
+
(-oo, 0) ∪ (0, 1] ∪ (2, 3) ∪ [4, 5] ∪ (6, +oo)
|
|
1971
|
+
sage: list(s._scan())
|
|
1972
|
+
[((-Infinity, 1), -1),
|
|
1973
|
+
((0, 0), 1),
|
|
1974
|
+
((0, 1), -1),
|
|
1975
|
+
((1, 1), 1),
|
|
1976
|
+
((2, 1), -1),
|
|
1977
|
+
((3, 0), 1),
|
|
1978
|
+
((4, 0), -1),
|
|
1979
|
+
((5, 1), 1),
|
|
1980
|
+
((6, 1), -1),
|
|
1981
|
+
((+Infinity, 0), 1)]
|
|
1982
|
+
"""
|
|
1983
|
+
for i in self._intervals:
|
|
1984
|
+
yield i._scan_lower()
|
|
1985
|
+
yield i._scan_upper()
|
|
1986
|
+
|
|
1987
|
+
@staticmethod
|
|
1988
|
+
def _scan_to_intervals(scan, condition):
|
|
1989
|
+
r"""
|
|
1990
|
+
Helper function for the scan-line method of :class:`RealSet`.
|
|
1991
|
+
|
|
1992
|
+
INPUT:
|
|
1993
|
+
|
|
1994
|
+
- ``scan`` -- a generator/list/tuple/iterable of events of the form
|
|
1995
|
+
``(x, epsilon), delta``, see :meth:`_scan`
|
|
1996
|
+
- ``condition`` -- a function indicating the on or off boundary points
|
|
1997
|
+
|
|
1998
|
+
OUTPUT: generate :class:`InternalRealInterval` objects
|
|
1999
|
+
|
|
2000
|
+
EXAMPLES::
|
|
2001
|
+
|
|
2002
|
+
sage: s = RealSet((-oo,0), RealSet.open_closed(0, 1), (2, 3), [4, 5], [5, 5], (6, oo)); s
|
|
2003
|
+
(-oo, 0) ∪ (0, 1] ∪ (2, 3) ∪ [4, 5] ∪ (6, +oo)
|
|
2004
|
+
sage: scan = list(s._scan()); scan
|
|
2005
|
+
[((-Infinity, 1), -1),
|
|
2006
|
+
((0, 0), 1),
|
|
2007
|
+
((0, 1), -1),
|
|
2008
|
+
((1, 1), 1),
|
|
2009
|
+
((2, 1), -1),
|
|
2010
|
+
((3, 0), 1),
|
|
2011
|
+
((4, 0), -1),
|
|
2012
|
+
((5, 1), 1),
|
|
2013
|
+
((6, 1), -1),
|
|
2014
|
+
((+Infinity, 0), 1)]
|
|
2015
|
+
sage: list(RealSet._scan_to_intervals(scan, lambda i: i > 0))
|
|
2016
|
+
[(-oo, 0), (0, 1], (2, 3), [4, 5], (6, +oo)]
|
|
2017
|
+
"""
|
|
2018
|
+
indicator = 0
|
|
2019
|
+
(on_x, on_epsilon) = (None, None)
|
|
2020
|
+
was_on = False
|
|
2021
|
+
for event in scan:
|
|
2022
|
+
(x, epsilon), delta = event
|
|
2023
|
+
indicator -= delta
|
|
2024
|
+
now_on = condition(indicator)
|
|
2025
|
+
if not was_on and now_on: # switched on
|
|
2026
|
+
(on_x, on_epsilon) = (x, epsilon)
|
|
2027
|
+
elif was_on and not now_on: # switched off
|
|
2028
|
+
if (on_x, on_epsilon) < (x, epsilon):
|
|
2029
|
+
lower_closed = on_epsilon == 0
|
|
2030
|
+
upper_closed = epsilon > 0
|
|
2031
|
+
yield InternalRealInterval(on_x, lower_closed, x, upper_closed)
|
|
2032
|
+
was_on = now_on
|
|
2033
|
+
|
|
2034
|
+
def union(self, *real_set_collection):
|
|
2035
|
+
"""
|
|
2036
|
+
Return the union of real sets.
|
|
2037
|
+
|
|
2038
|
+
INPUT:
|
|
2039
|
+
|
|
2040
|
+
- ``*real_set_collection`` -- list/tuple/iterable of :class:`RealSet`
|
|
2041
|
+
or data that defines one
|
|
2042
|
+
|
|
2043
|
+
OUTPUT: the set-theoretic union as a new :class:`RealSet`
|
|
2044
|
+
|
|
2045
|
+
EXAMPLES::
|
|
2046
|
+
|
|
2047
|
+
sage: s1 = RealSet(0,2)
|
|
2048
|
+
sage: s2 = RealSet(1,3)
|
|
2049
|
+
sage: s1.union(s2)
|
|
2050
|
+
(0, 3)
|
|
2051
|
+
sage: s1.union(1,3)
|
|
2052
|
+
(0, 3)
|
|
2053
|
+
sage: s1 | s2 # syntactic sugar
|
|
2054
|
+
(0, 3)
|
|
2055
|
+
sage: s1 + s2 # syntactic sugar
|
|
2056
|
+
(0, 3)
|
|
2057
|
+
sage: RealSet().union(RealSet.real_line())
|
|
2058
|
+
(-oo, +oo)
|
|
2059
|
+
sage: s = RealSet().union([1, 2], (2, 3)); s
|
|
2060
|
+
[1, 3)
|
|
2061
|
+
sage: RealSet().union((-oo, 0), x > 6, s[0], # needs sage.symbolic
|
|
2062
|
+
....: RealSet.point(5.0), RealSet.closed_open(2, 4))
|
|
2063
|
+
(-oo, 0) ∪ [1, 4) ∪ {5} ∪ (6, +oo)
|
|
2064
|
+
"""
|
|
2065
|
+
sets = [self]
|
|
2066
|
+
if len(real_set_collection) == 1 and isinstance(real_set_collection[0], RealSet):
|
|
2067
|
+
sets.append(real_set_collection[0])
|
|
2068
|
+
elif len(real_set_collection) == 2:
|
|
2069
|
+
a, b = real_set_collection
|
|
2070
|
+
# allow self.union(0,1) syntax
|
|
2071
|
+
try:
|
|
2072
|
+
a.n()
|
|
2073
|
+
b.n()
|
|
2074
|
+
sets.append(RealSet(a, b))
|
|
2075
|
+
except (AttributeError, ValueError, TypeError):
|
|
2076
|
+
sets.append(RealSet(a))
|
|
2077
|
+
sets.append(RealSet(b))
|
|
2078
|
+
else:
|
|
2079
|
+
sets.extend([RealSet(_) for _ in real_set_collection])
|
|
2080
|
+
# Same as return RealSet(*real_set_collection). The following is a bit
|
|
2081
|
+
# better when the input consists of RealSets, since they are normalized
|
|
2082
|
+
scan = merge(*[real_set._scan() for real_set in sets])
|
|
2083
|
+
intervals = tuple(RealSet._scan_to_intervals(scan, lambda i: i > 0))
|
|
2084
|
+
return RealSet(*intervals, normalized=True)
|
|
2085
|
+
|
|
2086
|
+
def intersection(self, *real_set_collection):
|
|
2087
|
+
"""
|
|
2088
|
+
Return the intersection of real sets.
|
|
2089
|
+
|
|
2090
|
+
INPUT:
|
|
2091
|
+
|
|
2092
|
+
- ``*real_set_collection`` -- list/tuple/iterable of :class:`RealSet`
|
|
2093
|
+
or data that defines one
|
|
2094
|
+
|
|
2095
|
+
OUTPUT: the set-theoretic intersection as a new :class:`RealSet`
|
|
2096
|
+
|
|
2097
|
+
EXAMPLES::
|
|
2098
|
+
|
|
2099
|
+
sage: s1 = RealSet(0,2) + RealSet.unbounded_above_closed(10); s1
|
|
2100
|
+
(0, 2) ∪ [10, +oo)
|
|
2101
|
+
sage: s2 = RealSet(1,3) + RealSet.unbounded_below_closed(-10); s2
|
|
2102
|
+
(-oo, -10] ∪ (1, 3)
|
|
2103
|
+
sage: s1.intersection(s2)
|
|
2104
|
+
(1, 2)
|
|
2105
|
+
sage: s1 & s2 # syntactic sugar
|
|
2106
|
+
(1, 2)
|
|
2107
|
+
sage: s3 = RealSet((0, 1), (2, 3)); s3
|
|
2108
|
+
(0, 1) ∪ (2, 3)
|
|
2109
|
+
sage: s4 = RealSet([0, 1], [2, 3]); s4
|
|
2110
|
+
[0, 1] ∪ [2, 3]
|
|
2111
|
+
sage: s3.intersection(s4)
|
|
2112
|
+
(0, 1) ∪ (2, 3)
|
|
2113
|
+
sage: s3.intersection([1, 2])
|
|
2114
|
+
{}
|
|
2115
|
+
sage: s4.intersection([1, 2])
|
|
2116
|
+
{1} ∪ {2}
|
|
2117
|
+
sage: s4.intersection(1, 2)
|
|
2118
|
+
{}
|
|
2119
|
+
sage: s5 = RealSet.closed_open(1, 10); s5
|
|
2120
|
+
[1, 10)
|
|
2121
|
+
sage: s5.intersection(-oo, +oo)
|
|
2122
|
+
[1, 10)
|
|
2123
|
+
sage: s5.intersection(x != 2, (-oo, 3), RealSet.real_line()[0]) # needs sage.symbolic
|
|
2124
|
+
[1, 2) ∪ (2, 3)
|
|
2125
|
+
|
|
2126
|
+
TESTS::
|
|
2127
|
+
|
|
2128
|
+
sage: s1 = RealSet([1, 2])
|
|
2129
|
+
sage: s2 = RealSet([2, 3])
|
|
2130
|
+
sage: s3 = RealSet(3, 4)
|
|
2131
|
+
sage: s4 = RealSet.closed_open(4, 5)
|
|
2132
|
+
sage: s5 = RealSet(5, 6)
|
|
2133
|
+
sage: s1.intersection(RealSet())
|
|
2134
|
+
{}
|
|
2135
|
+
sage: s1.intersection(s2)
|
|
2136
|
+
{2}
|
|
2137
|
+
sage: s2.intersection(s3)
|
|
2138
|
+
{}
|
|
2139
|
+
sage: s3.intersection(s4)
|
|
2140
|
+
{}
|
|
2141
|
+
sage: s4.intersection(s5)
|
|
2142
|
+
{}
|
|
2143
|
+
"""
|
|
2144
|
+
sets = [self]
|
|
2145
|
+
if len(real_set_collection) == 1 and isinstance(real_set_collection[0], RealSet):
|
|
2146
|
+
sets.append(real_set_collection[0])
|
|
2147
|
+
elif len(real_set_collection) == 2:
|
|
2148
|
+
a, b = real_set_collection
|
|
2149
|
+
# allow self.intersection(0,1) syntax
|
|
2150
|
+
try:
|
|
2151
|
+
a.n()
|
|
2152
|
+
b.n()
|
|
2153
|
+
sets.append(RealSet(a, b))
|
|
2154
|
+
except (AttributeError, ValueError, TypeError):
|
|
2155
|
+
sets.append(RealSet(a))
|
|
2156
|
+
sets.append(RealSet(b))
|
|
2157
|
+
else:
|
|
2158
|
+
sets.extend([RealSet(_) for _ in real_set_collection])
|
|
2159
|
+
n = len(sets)
|
|
2160
|
+
scan = merge(*[real_set._scan() for real_set in sets])
|
|
2161
|
+
intervals = tuple(RealSet._scan_to_intervals(scan, lambda i: i == n))
|
|
2162
|
+
return RealSet(*intervals, normalized=True)
|
|
2163
|
+
|
|
2164
|
+
def inf(self):
|
|
2165
|
+
"""
|
|
2166
|
+
Return the infimum.
|
|
2167
|
+
|
|
2168
|
+
OUTPUT: a real number or infinity
|
|
2169
|
+
|
|
2170
|
+
EXAMPLES::
|
|
2171
|
+
|
|
2172
|
+
sage: s1 = RealSet(0,2) + RealSet.unbounded_above_closed(10); s1
|
|
2173
|
+
(0, 2) ∪ [10, +oo)
|
|
2174
|
+
sage: s1.inf()
|
|
2175
|
+
0
|
|
2176
|
+
|
|
2177
|
+
sage: s2 = RealSet(1,3) + RealSet.unbounded_below_closed(-10); s2
|
|
2178
|
+
(-oo, -10] ∪ (1, 3)
|
|
2179
|
+
sage: s2.inf()
|
|
2180
|
+
-Infinity
|
|
2181
|
+
"""
|
|
2182
|
+
if self.n_components() == 0:
|
|
2183
|
+
return infinity
|
|
2184
|
+
return self._intervals[0].lower()
|
|
2185
|
+
|
|
2186
|
+
def sup(self):
|
|
2187
|
+
"""
|
|
2188
|
+
Return the supremum.
|
|
2189
|
+
|
|
2190
|
+
OUTPUT: a real number or infinity
|
|
2191
|
+
|
|
2192
|
+
EXAMPLES::
|
|
2193
|
+
|
|
2194
|
+
sage: s1 = RealSet(0,2) + RealSet.unbounded_above_closed(10); s1
|
|
2195
|
+
(0, 2) ∪ [10, +oo)
|
|
2196
|
+
sage: s1.sup()
|
|
2197
|
+
+Infinity
|
|
2198
|
+
|
|
2199
|
+
sage: s2 = RealSet(1,3) + RealSet.unbounded_below_closed(-10); s2
|
|
2200
|
+
(-oo, -10] ∪ (1, 3)
|
|
2201
|
+
sage: s2.sup()
|
|
2202
|
+
3
|
|
2203
|
+
"""
|
|
2204
|
+
if self.n_components() == 0:
|
|
2205
|
+
return minus_infinity
|
|
2206
|
+
return self._intervals[-1].upper()
|
|
2207
|
+
|
|
2208
|
+
def complement(self):
|
|
2209
|
+
"""
|
|
2210
|
+
Return the complement.
|
|
2211
|
+
|
|
2212
|
+
OUTPUT: the set-theoretic complement as a new :class:`RealSet`
|
|
2213
|
+
|
|
2214
|
+
EXAMPLES::
|
|
2215
|
+
|
|
2216
|
+
sage: RealSet(0,1).complement()
|
|
2217
|
+
(-oo, 0] ∪ [1, +oo)
|
|
2218
|
+
|
|
2219
|
+
sage: s1 = RealSet(0,2) + RealSet.unbounded_above_closed(10); s1
|
|
2220
|
+
(0, 2) ∪ [10, +oo)
|
|
2221
|
+
sage: s1.complement()
|
|
2222
|
+
(-oo, 0] ∪ [2, 10)
|
|
2223
|
+
|
|
2224
|
+
sage: s2 = RealSet(1,3) + RealSet.unbounded_below_closed(-10); s2
|
|
2225
|
+
(-oo, -10] ∪ (1, 3)
|
|
2226
|
+
sage: s2.complement()
|
|
2227
|
+
(-10, 1] ∪ [3, +oo)
|
|
2228
|
+
|
|
2229
|
+
TESTS::
|
|
2230
|
+
|
|
2231
|
+
sage: RealSet(x != 0).complement() # needs sage.symbolic
|
|
2232
|
+
{0}
|
|
2233
|
+
sage: RealSet.real_line().complement()
|
|
2234
|
+
{}
|
|
2235
|
+
sage: _.complement()
|
|
2236
|
+
(-oo, +oo)
|
|
2237
|
+
"""
|
|
2238
|
+
return (self.ambient()).difference(self)
|
|
2239
|
+
|
|
2240
|
+
def difference(self, *other):
|
|
2241
|
+
"""
|
|
2242
|
+
Return ``self`` with ``other`` subtracted.
|
|
2243
|
+
|
|
2244
|
+
INPUT:
|
|
2245
|
+
|
|
2246
|
+
- ``other`` -- a :class:`RealSet` or data that defines one
|
|
2247
|
+
|
|
2248
|
+
OUTPUT:
|
|
2249
|
+
|
|
2250
|
+
The set-theoretic difference of ``self`` with ``other``
|
|
2251
|
+
removed as a new :class:`RealSet`.
|
|
2252
|
+
|
|
2253
|
+
EXAMPLES::
|
|
2254
|
+
|
|
2255
|
+
sage: s1 = RealSet(0,2) + RealSet.unbounded_above_closed(10); s1
|
|
2256
|
+
(0, 2) ∪ [10, +oo)
|
|
2257
|
+
sage: s2 = RealSet(1,3) + RealSet.unbounded_below_closed(-10); s2
|
|
2258
|
+
(-oo, -10] ∪ (1, 3)
|
|
2259
|
+
sage: s1.difference(s2)
|
|
2260
|
+
(0, 1] ∪ [10, +oo)
|
|
2261
|
+
sage: s1 - s2 # syntactic sugar
|
|
2262
|
+
(0, 1] ∪ [10, +oo)
|
|
2263
|
+
sage: s2.difference(s1)
|
|
2264
|
+
(-oo, -10] ∪ [2, 3)
|
|
2265
|
+
sage: s2 - s1 # syntactic sugar
|
|
2266
|
+
(-oo, -10] ∪ [2, 3)
|
|
2267
|
+
sage: s1.difference(1,11)
|
|
2268
|
+
(0, 1] ∪ [11, +oo)
|
|
2269
|
+
"""
|
|
2270
|
+
remove = [(pt, -delta) for (pt, delta) in RealSet(*other)._scan()]
|
|
2271
|
+
# Note: flip delta for boundary point in the removed set.
|
|
2272
|
+
# turn-on lower open becomes turn-off upper closed.
|
|
2273
|
+
scan = merge(self._scan(), remove)
|
|
2274
|
+
# Because the negative delta, indicator in def _scan_to_intervals can be negative.
|
|
2275
|
+
intervals = tuple(RealSet._scan_to_intervals(scan, lambda i: i > 0))
|
|
2276
|
+
return RealSet(*intervals, normalized=True)
|
|
2277
|
+
|
|
2278
|
+
def symmetric_difference(self, *other):
|
|
2279
|
+
r"""
|
|
2280
|
+
Return the symmetric difference of ``self`` and ``other``.
|
|
2281
|
+
|
|
2282
|
+
INPUT:
|
|
2283
|
+
|
|
2284
|
+
- ``other`` -- a :class:`RealSet` or data that defines one
|
|
2285
|
+
|
|
2286
|
+
OUTPUT:
|
|
2287
|
+
|
|
2288
|
+
The set-theoretic symmetric difference of ``self`` and ``other``
|
|
2289
|
+
as a new :class:`RealSet`.
|
|
2290
|
+
|
|
2291
|
+
EXAMPLES::
|
|
2292
|
+
|
|
2293
|
+
sage: s1 = RealSet(0,2); s1
|
|
2294
|
+
(0, 2)
|
|
2295
|
+
sage: s2 = RealSet.unbounded_above_open(1); s2
|
|
2296
|
+
(1, +oo)
|
|
2297
|
+
sage: s1.symmetric_difference(s2)
|
|
2298
|
+
(0, 1] ∪ [2, +oo)
|
|
2299
|
+
"""
|
|
2300
|
+
scan = merge(self._scan(), RealSet(*other)._scan())
|
|
2301
|
+
intervals = tuple(RealSet._scan_to_intervals(scan, lambda i: i == 1))
|
|
2302
|
+
return RealSet(*intervals, normalized=True)
|
|
2303
|
+
|
|
2304
|
+
def contains(self, x):
|
|
2305
|
+
"""
|
|
2306
|
+
Return whether `x` is contained in the set.
|
|
2307
|
+
|
|
2308
|
+
INPUT:
|
|
2309
|
+
|
|
2310
|
+
- ``x`` -- a real number
|
|
2311
|
+
|
|
2312
|
+
OUTPUT: boolean
|
|
2313
|
+
|
|
2314
|
+
EXAMPLES::
|
|
2315
|
+
|
|
2316
|
+
sage: s = RealSet(0,2) + RealSet.unbounded_above_closed(10); s
|
|
2317
|
+
(0, 2) ∪ [10, +oo)
|
|
2318
|
+
sage: s.contains(1)
|
|
2319
|
+
True
|
|
2320
|
+
sage: s.contains(0)
|
|
2321
|
+
False
|
|
2322
|
+
sage: s.contains(10.0)
|
|
2323
|
+
True
|
|
2324
|
+
sage: 10 in s # syntactic sugar
|
|
2325
|
+
True
|
|
2326
|
+
sage: s.contains(+oo)
|
|
2327
|
+
False
|
|
2328
|
+
sage: RealSet().contains(1)
|
|
2329
|
+
False
|
|
2330
|
+
"""
|
|
2331
|
+
x = RLF(x)
|
|
2332
|
+
for interval in self._intervals:
|
|
2333
|
+
if interval.contains(x):
|
|
2334
|
+
return True
|
|
2335
|
+
return False
|
|
2336
|
+
|
|
2337
|
+
__contains__ = contains
|
|
2338
|
+
|
|
2339
|
+
def is_subset(self, *other):
|
|
2340
|
+
r"""
|
|
2341
|
+
Return whether ``self`` is a subset of ``other``.
|
|
2342
|
+
|
|
2343
|
+
INPUT:
|
|
2344
|
+
|
|
2345
|
+
- ``*other`` -- a :class:`RealSet` or something that defines one
|
|
2346
|
+
|
|
2347
|
+
OUTPUT: boolean
|
|
2348
|
+
|
|
2349
|
+
EXAMPLES::
|
|
2350
|
+
|
|
2351
|
+
sage: I = RealSet((1,2))
|
|
2352
|
+
sage: J = RealSet((1,3))
|
|
2353
|
+
sage: K = RealSet((2,3))
|
|
2354
|
+
sage: I.is_subset(J)
|
|
2355
|
+
True
|
|
2356
|
+
sage: J.is_subset(K)
|
|
2357
|
+
False
|
|
2358
|
+
"""
|
|
2359
|
+
return RealSet(*other).intersection(self) == self
|
|
2360
|
+
|
|
2361
|
+
is_included_in = deprecated_function_alias(31927, is_subset)
|
|
2362
|
+
|
|
2363
|
+
def _an_element_(self):
|
|
2364
|
+
"""
|
|
2365
|
+
Return a point of the set.
|
|
2366
|
+
|
|
2367
|
+
OUTPUT: a real number
|
|
2368
|
+
|
|
2369
|
+
It raises an :class:`~sage.categories.sets_cat.EmptySetError` if the set is empty.
|
|
2370
|
+
|
|
2371
|
+
EXAMPLES::
|
|
2372
|
+
|
|
2373
|
+
sage: RealSet.open_closed(0, 1).an_element()
|
|
2374
|
+
1
|
|
2375
|
+
sage: RealSet(0, 1).an_element()
|
|
2376
|
+
1/2
|
|
2377
|
+
sage: RealSet(-oo,+oo).an_element()
|
|
2378
|
+
0
|
|
2379
|
+
sage: RealSet(-oo,7).an_element()
|
|
2380
|
+
6
|
|
2381
|
+
sage: RealSet(7,+oo).an_element()
|
|
2382
|
+
8
|
|
2383
|
+
sage: RealSet().an_element()
|
|
2384
|
+
Traceback (most recent call last):
|
|
2385
|
+
...
|
|
2386
|
+
sage.categories.sets_cat.EmptySetError
|
|
2387
|
+
"""
|
|
2388
|
+
from sage.rings.infinity import AnInfinity
|
|
2389
|
+
if not self._intervals:
|
|
2390
|
+
raise EmptySetError
|
|
2391
|
+
i = self._intervals[0]
|
|
2392
|
+
if isinstance(i.lower(), AnInfinity):
|
|
2393
|
+
if isinstance(i.upper(), AnInfinity):
|
|
2394
|
+
return ZZ.zero()
|
|
2395
|
+
else:
|
|
2396
|
+
return i.upper() - 1
|
|
2397
|
+
if isinstance(i.upper(), AnInfinity):
|
|
2398
|
+
return i.lower() + 1
|
|
2399
|
+
if i.lower_closed():
|
|
2400
|
+
return i.lower()
|
|
2401
|
+
if i.upper_closed():
|
|
2402
|
+
return i.upper()
|
|
2403
|
+
return (i.lower() + i.upper()) / ZZ(2)
|
|
2404
|
+
|
|
2405
|
+
def is_open(self):
|
|
2406
|
+
"""
|
|
2407
|
+
Return whether ``self`` is an open set.
|
|
2408
|
+
|
|
2409
|
+
EXAMPLES::
|
|
2410
|
+
|
|
2411
|
+
sage: RealSet().is_open()
|
|
2412
|
+
True
|
|
2413
|
+
sage: RealSet.point(1).is_open()
|
|
2414
|
+
False
|
|
2415
|
+
sage: RealSet((1, 2)).is_open()
|
|
2416
|
+
True
|
|
2417
|
+
sage: RealSet([1, 2], (3, 4)).is_open()
|
|
2418
|
+
False
|
|
2419
|
+
sage: RealSet(-oo, +oo).is_open()
|
|
2420
|
+
True
|
|
2421
|
+
"""
|
|
2422
|
+
return all(not i.lower_closed()
|
|
2423
|
+
and not i.upper_closed()
|
|
2424
|
+
for i in self._intervals)
|
|
2425
|
+
|
|
2426
|
+
def is_closed(self):
|
|
2427
|
+
"""
|
|
2428
|
+
Return whether ``self`` is a closed set.
|
|
2429
|
+
|
|
2430
|
+
EXAMPLES::
|
|
2431
|
+
|
|
2432
|
+
sage: RealSet().is_closed()
|
|
2433
|
+
True
|
|
2434
|
+
sage: RealSet.point(1).is_closed()
|
|
2435
|
+
True
|
|
2436
|
+
sage: RealSet([1, 2]).is_closed()
|
|
2437
|
+
True
|
|
2438
|
+
sage: RealSet([1, 2], (3, 4)).is_closed()
|
|
2439
|
+
False
|
|
2440
|
+
sage: RealSet(-oo, +oo).is_closed()
|
|
2441
|
+
True
|
|
2442
|
+
"""
|
|
2443
|
+
return all((i.lower_closed() or i.lower() is minus_infinity)
|
|
2444
|
+
and (i.upper_closed() or i.upper() is infinity)
|
|
2445
|
+
for i in self._intervals)
|
|
2446
|
+
|
|
2447
|
+
def closure(self):
|
|
2448
|
+
"""
|
|
2449
|
+
Return the topological closure of ``self`` as a new :class:`RealSet`.
|
|
2450
|
+
|
|
2451
|
+
EXAMPLES::
|
|
2452
|
+
|
|
2453
|
+
sage: RealSet(-oo, oo).closure()
|
|
2454
|
+
(-oo, +oo)
|
|
2455
|
+
sage: RealSet((1, 2), (2, 3)).closure()
|
|
2456
|
+
[1, 3]
|
|
2457
|
+
sage: RealSet().closure()
|
|
2458
|
+
{}
|
|
2459
|
+
"""
|
|
2460
|
+
return RealSet(*[i.closure() for i in self._intervals])
|
|
2461
|
+
|
|
2462
|
+
def interior(self):
|
|
2463
|
+
"""
|
|
2464
|
+
Return the topological interior of ``self`` as a new :class:`RealSet`.
|
|
2465
|
+
|
|
2466
|
+
EXAMPLES::
|
|
2467
|
+
|
|
2468
|
+
sage: RealSet(-oo, oo).interior()
|
|
2469
|
+
(-oo, +oo)
|
|
2470
|
+
sage: RealSet().interior()
|
|
2471
|
+
{}
|
|
2472
|
+
sage: RealSet.point(2).interior()
|
|
2473
|
+
{}
|
|
2474
|
+
sage: RealSet([1, 2], (3, 4)).interior()
|
|
2475
|
+
(1, 2) ∪ (3, 4)
|
|
2476
|
+
"""
|
|
2477
|
+
return RealSet(*[i.interior() for i in self._intervals])
|
|
2478
|
+
|
|
2479
|
+
def boundary(self):
|
|
2480
|
+
"""
|
|
2481
|
+
Return the topological boundary of ``self`` as a new :class:`RealSet`.
|
|
2482
|
+
|
|
2483
|
+
EXAMPLES::
|
|
2484
|
+
|
|
2485
|
+
sage: RealSet(-oo, oo).boundary()
|
|
2486
|
+
{}
|
|
2487
|
+
sage: RealSet().boundary()
|
|
2488
|
+
{}
|
|
2489
|
+
sage: RealSet.point(2).boundary()
|
|
2490
|
+
{2}
|
|
2491
|
+
sage: RealSet([1, 2], (3, 4)).boundary()
|
|
2492
|
+
{1} ∪ {2} ∪ {3} ∪ {4}
|
|
2493
|
+
sage: RealSet((1, 2), (2, 3)).boundary()
|
|
2494
|
+
{1} ∪ {2} ∪ {3}
|
|
2495
|
+
"""
|
|
2496
|
+
return RealSet(*[RealSet.point(x) for i in self._intervals for x in i.boundary_points()])
|
|
2497
|
+
|
|
2498
|
+
@staticmethod
|
|
2499
|
+
def convex_hull(*real_set_collection):
|
|
2500
|
+
"""
|
|
2501
|
+
Return the convex hull of real sets.
|
|
2502
|
+
|
|
2503
|
+
INPUT:
|
|
2504
|
+
|
|
2505
|
+
- ``*real_set_collection`` -- list/tuple/iterable of :class:`RealSet`
|
|
2506
|
+
or data that defines one
|
|
2507
|
+
|
|
2508
|
+
OUTPUT: the convex hull as a new :class:`RealSet`
|
|
2509
|
+
|
|
2510
|
+
EXAMPLES::
|
|
2511
|
+
|
|
2512
|
+
sage: s1 = RealSet(0,2) + RealSet.unbounded_above_closed(10); s1 # unbounded set
|
|
2513
|
+
(0, 2) ∪ [10, +oo)
|
|
2514
|
+
sage: s2 = RealSet(1,3) + RealSet.unbounded_below_closed(-10); s2
|
|
2515
|
+
(-oo, -10] ∪ (1, 3)
|
|
2516
|
+
sage: s3 = RealSet((0,2), RealSet.point(8)); s3
|
|
2517
|
+
(0, 2) ∪ {8}
|
|
2518
|
+
sage: s4 = RealSet(); s4 # empty set
|
|
2519
|
+
{}
|
|
2520
|
+
sage: RealSet.convex_hull(s1)
|
|
2521
|
+
(0, +oo)
|
|
2522
|
+
sage: RealSet.convex_hull(s2)
|
|
2523
|
+
(-oo, 3)
|
|
2524
|
+
sage: RealSet.convex_hull(s3)
|
|
2525
|
+
(0, 8]
|
|
2526
|
+
sage: RealSet.convex_hull(s4)
|
|
2527
|
+
{}
|
|
2528
|
+
sage: RealSet.convex_hull(s1, s2)
|
|
2529
|
+
(-oo, +oo)
|
|
2530
|
+
sage: RealSet.convex_hull(s2, s3)
|
|
2531
|
+
(-oo, 8]
|
|
2532
|
+
sage: RealSet.convex_hull(s2, s3, s4)
|
|
2533
|
+
(-oo, 8]
|
|
2534
|
+
"""
|
|
2535
|
+
lower_scan = ((infinity, 0), 1)
|
|
2536
|
+
upper_scan = ((minus_infinity, 1), -1)
|
|
2537
|
+
for real_set in real_set_collection:
|
|
2538
|
+
s = RealSet(real_set)
|
|
2539
|
+
if s.n_components() > 0:
|
|
2540
|
+
lower_s = s[0]._scan_lower()
|
|
2541
|
+
lower_scan = min(lower_s, lower_scan)
|
|
2542
|
+
upper_s = s[-1]._scan_upper()
|
|
2543
|
+
upper_scan = max(upper_s, upper_scan)
|
|
2544
|
+
if lower_scan < upper_scan:
|
|
2545
|
+
lower, lower_closed = lower_scan[0][0], lower_scan[0][1] == 0
|
|
2546
|
+
upper, upper_closed = upper_scan[0][0], upper_scan[0][1] > 0
|
|
2547
|
+
return RealSet(InternalRealInterval(lower, lower_closed, upper, upper_closed))
|
|
2548
|
+
else:
|
|
2549
|
+
return RealSet()
|
|
2550
|
+
|
|
2551
|
+
def is_connected(self):
|
|
2552
|
+
"""
|
|
2553
|
+
Return whether ``self`` is a connected set.
|
|
2554
|
+
|
|
2555
|
+
OUTPUT: boolean
|
|
2556
|
+
|
|
2557
|
+
EXAMPLES::
|
|
2558
|
+
|
|
2559
|
+
sage: s1 = RealSet((1, 2), (2, 4)); s1
|
|
2560
|
+
(1, 2) ∪ (2, 4)
|
|
2561
|
+
sage: s1.is_connected()
|
|
2562
|
+
False
|
|
2563
|
+
sage: s2 = RealSet((1, 2), (2, 4), RealSet.point(2)); s2
|
|
2564
|
+
(1, 4)
|
|
2565
|
+
sage: s2.is_connected()
|
|
2566
|
+
True
|
|
2567
|
+
sage: s3 = RealSet(1,3) + RealSet.unbounded_below_closed(-10); s3
|
|
2568
|
+
(-oo, -10] ∪ (1, 3)
|
|
2569
|
+
sage: s3.is_connected()
|
|
2570
|
+
False
|
|
2571
|
+
sage: RealSet(x != 0).is_connected() # needs sage.symbolic
|
|
2572
|
+
False
|
|
2573
|
+
sage: RealSet(-oo, oo).is_connected()
|
|
2574
|
+
True
|
|
2575
|
+
sage: RealSet().is_connected()
|
|
2576
|
+
False
|
|
2577
|
+
"""
|
|
2578
|
+
return self.n_components() == 1
|
|
2579
|
+
|
|
2580
|
+
def is_disjoint(self, *other):
|
|
2581
|
+
"""
|
|
2582
|
+
Test whether the two sets are disjoint.
|
|
2583
|
+
|
|
2584
|
+
INPUT:
|
|
2585
|
+
|
|
2586
|
+
- ``other`` -- a :class:`RealSet` or data defining one
|
|
2587
|
+
|
|
2588
|
+
OUTPUT: boolean
|
|
2589
|
+
|
|
2590
|
+
.. SEEALSO:: :meth:`are_pairwise_disjoint`
|
|
2591
|
+
|
|
2592
|
+
EXAMPLES::
|
|
2593
|
+
|
|
2594
|
+
sage: s = RealSet((0, 1), (2, 3)); s
|
|
2595
|
+
(0, 1) ∪ (2, 3)
|
|
2596
|
+
sage: s.is_disjoint(RealSet([1, 2]))
|
|
2597
|
+
True
|
|
2598
|
+
sage: s.is_disjoint([3/2, 5/2])
|
|
2599
|
+
False
|
|
2600
|
+
sage: s.is_disjoint(RealSet())
|
|
2601
|
+
True
|
|
2602
|
+
sage: s.is_disjoint(RealSet().real_line())
|
|
2603
|
+
False
|
|
2604
|
+
"""
|
|
2605
|
+
other = RealSet(*other)
|
|
2606
|
+
return self.are_pairwise_disjoint(self, other)
|
|
2607
|
+
|
|
2608
|
+
is_disjoint_from = deprecated_function_alias(31927, is_disjoint)
|
|
2609
|
+
|
|
2610
|
+
@staticmethod
|
|
2611
|
+
def are_pairwise_disjoint(*real_set_collection):
|
|
2612
|
+
"""
|
|
2613
|
+
Test whether the real sets are pairwise disjoint.
|
|
2614
|
+
|
|
2615
|
+
INPUT:
|
|
2616
|
+
|
|
2617
|
+
- ``*real_set_collection`` -- list/tuple/iterable of :class:`RealSet`
|
|
2618
|
+
or data that defines one
|
|
2619
|
+
|
|
2620
|
+
OUTPUT: boolean
|
|
2621
|
+
|
|
2622
|
+
.. SEEALSO:: :meth:`is_disjoint`
|
|
2623
|
+
|
|
2624
|
+
EXAMPLES::
|
|
2625
|
+
|
|
2626
|
+
sage: s1 = RealSet((0, 1), (2, 3))
|
|
2627
|
+
sage: s2 = RealSet((1, 2))
|
|
2628
|
+
sage: s3 = RealSet.point(3)
|
|
2629
|
+
sage: RealSet.are_pairwise_disjoint(s1, s2, s3)
|
|
2630
|
+
True
|
|
2631
|
+
sage: RealSet.are_pairwise_disjoint(s1, s2, s3, [10,10])
|
|
2632
|
+
True
|
|
2633
|
+
sage: RealSet.are_pairwise_disjoint(s1, s2, s3, [-1, 1/2])
|
|
2634
|
+
False
|
|
2635
|
+
"""
|
|
2636
|
+
scan = merge(*[RealSet(real_set)._scan() for real_set in real_set_collection])
|
|
2637
|
+
overlap_generator = RealSet._scan_to_intervals(scan, lambda i: i > 1)
|
|
2638
|
+
return next(overlap_generator, None) is None
|
|
2639
|
+
|
|
2640
|
+
def _sage_input_(self, sib, coerced):
|
|
2641
|
+
"""
|
|
2642
|
+
Produce an expression which will reproduce this value when evaluated.
|
|
2643
|
+
|
|
2644
|
+
TESTS::
|
|
2645
|
+
|
|
2646
|
+
sage: sage_input(RealSet())
|
|
2647
|
+
RealSet()
|
|
2648
|
+
sage: sage_input(RealSet.open(-oo, +oo))
|
|
2649
|
+
RealSet(-oo, oo)
|
|
2650
|
+
sage: sage_input(RealSet.point(77))
|
|
2651
|
+
RealSet.point(77)
|
|
2652
|
+
sage: sage_input(RealSet.closed_open(0, +oo))
|
|
2653
|
+
RealSet.closed_open(0, oo)
|
|
2654
|
+
sage: sage_input(RealSet.open_closed(-oo, 0))
|
|
2655
|
+
RealSet.open_closed(-oo, 0)
|
|
2656
|
+
sage: sage_input(RealSet.open_closed(-1, 0))
|
|
2657
|
+
RealSet.open_closed(-1, 0)
|
|
2658
|
+
sage: sage_input(RealSet.closed_open(-1, 0))
|
|
2659
|
+
RealSet.closed_open(-1, 0)
|
|
2660
|
+
sage: sage_input(RealSet.closed(0, 1))
|
|
2661
|
+
RealSet.closed(0, 1)
|
|
2662
|
+
sage: sage_input(RealSet.open(0, 1))
|
|
2663
|
+
RealSet.open(0, 1)
|
|
2664
|
+
sage: sage_input(RealSet.open(0, 1) + RealSet.open(1, 2))
|
|
2665
|
+
RealSet.open(0, 1) + RealSet.open(1, 2)
|
|
2666
|
+
"""
|
|
2667
|
+
|
|
2668
|
+
def interval_input(i):
|
|
2669
|
+
lower, upper = i.lower(), i.upper()
|
|
2670
|
+
if i.is_point():
|
|
2671
|
+
return sib.name('RealSet.point')(lower)
|
|
2672
|
+
elif lower == minus_infinity and upper == infinity:
|
|
2673
|
+
return sib.name('RealSet')(sib(minus_infinity), sib(infinity))
|
|
2674
|
+
else:
|
|
2675
|
+
if i.lower_closed():
|
|
2676
|
+
if i.upper_closed():
|
|
2677
|
+
t = 'RealSet.closed'
|
|
2678
|
+
else:
|
|
2679
|
+
t = 'RealSet.closed_open'
|
|
2680
|
+
else:
|
|
2681
|
+
if i.upper_closed():
|
|
2682
|
+
t = 'RealSet.open_closed'
|
|
2683
|
+
else:
|
|
2684
|
+
t = 'RealSet.open'
|
|
2685
|
+
return sib.name(t)(sib(lower), sib(upper))
|
|
2686
|
+
|
|
2687
|
+
if self.is_empty():
|
|
2688
|
+
return sib.name('RealSet')()
|
|
2689
|
+
else:
|
|
2690
|
+
return sib.sum(interval_input(i) for i in self)
|
|
2691
|
+
|
|
2692
|
+
def __mul__(self, right):
|
|
2693
|
+
r"""
|
|
2694
|
+
Scale a real set by a scalar on the left or right.
|
|
2695
|
+
|
|
2696
|
+
EXAMPLES::
|
|
2697
|
+
|
|
2698
|
+
sage: A = RealSet([0, 1/2], (2, infinity)); A
|
|
2699
|
+
[0, 1/2] ∪ (2, +oo)
|
|
2700
|
+
sage: 2 * A
|
|
2701
|
+
[0, 1] ∪ (4, +oo)
|
|
2702
|
+
sage: A * 100
|
|
2703
|
+
[0, 50] ∪ (200, +oo)
|
|
2704
|
+
sage: 1.5 * A
|
|
2705
|
+
[0.000000000000000, 0.750000000000000] ∪ (3.00000000000000, +oo)
|
|
2706
|
+
sage: (-2) * A
|
|
2707
|
+
(-oo, -4) ∪ [-1, 0]
|
|
2708
|
+
"""
|
|
2709
|
+
if not isinstance(right, RealSet):
|
|
2710
|
+
return RealSet(*[e * right for e in self])
|
|
2711
|
+
elif not isinstance(self, RealSet):
|
|
2712
|
+
return RealSet(*[self * e for e in right])
|
|
2713
|
+
else:
|
|
2714
|
+
return NotImplemented
|
|
2715
|
+
|
|
2716
|
+
def __rmul__(self, other):
|
|
2717
|
+
r"""
|
|
2718
|
+
Scale a real set by a scalar on the left.
|
|
2719
|
+
|
|
2720
|
+
TESTS::
|
|
2721
|
+
|
|
2722
|
+
sage: A = RealSet([0, 1/2], RealSet.unbounded_above_closed(2)); A
|
|
2723
|
+
[0, 1/2] ∪ [2, +oo)
|
|
2724
|
+
sage: pi * A # needs sage.symbolic
|
|
2725
|
+
[0, 1/2*pi] ∪ [2*pi, +oo)
|
|
2726
|
+
"""
|
|
2727
|
+
return self * other
|
|
2728
|
+
|
|
2729
|
+
def _sympy_(self):
|
|
2730
|
+
r"""
|
|
2731
|
+
Return the SymPy set corresponding to ``self``.
|
|
2732
|
+
|
|
2733
|
+
EXAMPLES::
|
|
2734
|
+
|
|
2735
|
+
sage: # needs sympy
|
|
2736
|
+
sage: RealSet()._sympy_()
|
|
2737
|
+
EmptySet
|
|
2738
|
+
sage: RealSet.point(5)._sympy_() # random - this format is sympy >= 1.9
|
|
2739
|
+
{5}
|
|
2740
|
+
sage: (RealSet.point(1).union(RealSet.point(2)))._sympy_() # random
|
|
2741
|
+
{1, 2}
|
|
2742
|
+
sage: (RealSet(1, 2).union(RealSet.closed(3, 4)))._sympy_()
|
|
2743
|
+
Union(Interval.open(1, 2), Interval(3, 4))
|
|
2744
|
+
sage: RealSet(-oo, oo)._sympy_()
|
|
2745
|
+
Reals
|
|
2746
|
+
|
|
2747
|
+
Infinities are not elements::
|
|
2748
|
+
|
|
2749
|
+
sage: import sympy # needs sympy
|
|
2750
|
+
sage: RealSet(-oo, oo)._sympy_().contains(sympy.oo) # needs sympy
|
|
2751
|
+
False
|
|
2752
|
+
"""
|
|
2753
|
+
from sympy import Reals, Union
|
|
2754
|
+
from sage.interfaces.sympy import sympy_init
|
|
2755
|
+
sympy_init()
|
|
2756
|
+
if self.is_universe():
|
|
2757
|
+
return Reals
|
|
2758
|
+
else:
|
|
2759
|
+
return Union(*[interval._sympy_()
|
|
2760
|
+
for interval in self._intervals])
|