passagemath-symbolics 10.8.1a1__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_symbolics/__init__.py +3 -0
- passagemath_symbolics-10.8.1a1.dist-info/METADATA +186 -0
- passagemath_symbolics-10.8.1a1.dist-info/RECORD +181 -0
- passagemath_symbolics-10.8.1a1.dist-info/WHEEL +5 -0
- passagemath_symbolics-10.8.1a1.dist-info/top_level.txt +3 -0
- sage/all__sagemath_symbolics.py +17 -0
- sage/calculus/all.py +14 -0
- sage/calculus/calculus.py +2838 -0
- sage/calculus/desolvers.py +1864 -0
- sage/calculus/predefined.py +51 -0
- sage/calculus/tests.py +225 -0
- sage/calculus/var.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/calculus/var.pyx +401 -0
- sage/dynamics/all__sagemath_symbolics.py +6 -0
- sage/dynamics/complex_dynamics/all.py +5 -0
- sage/dynamics/complex_dynamics/mandel_julia.py +765 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1034 -0
- sage/ext/all__sagemath_symbolics.py +1 -0
- sage/ext_data/kenzo/CP2.txt +45 -0
- sage/ext_data/kenzo/CP3.txt +349 -0
- sage/ext_data/kenzo/CP4.txt +4774 -0
- sage/ext_data/kenzo/README.txt +49 -0
- sage/ext_data/kenzo/S4.txt +20 -0
- sage/ext_data/magma/latex/latex.m +1021 -0
- sage/ext_data/magma/latex/latex.spec +1 -0
- sage/ext_data/magma/sage/basic.m +356 -0
- sage/ext_data/magma/sage/sage.spec +1 -0
- sage/ext_data/magma/spec +9 -0
- sage/geometry/all__sagemath_symbolics.py +8 -0
- sage/geometry/hyperbolic_space/all.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_coercion.py +755 -0
- sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2419 -0
- sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
- sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1083 -0
- sage/geometry/hyperbolic_space/hyperbolic_model.py +1502 -0
- sage/geometry/hyperbolic_space/hyperbolic_point.py +621 -0
- sage/geometry/riemannian_manifolds/all.py +7 -0
- sage/geometry/riemannian_manifolds/parametrized_surface3d.py +1632 -0
- sage/geometry/riemannian_manifolds/surface3d_generators.py +461 -0
- sage/interfaces/all__sagemath_symbolics.py +1 -0
- sage/interfaces/magma.py +2991 -0
- sage/interfaces/magma_free.py +90 -0
- sage/interfaces/maple.py +1402 -0
- sage/interfaces/mathematica.py +1345 -0
- sage/interfaces/mathics.py +1312 -0
- sage/interfaces/sympy.py +1398 -0
- sage/interfaces/sympy_wrapper.py +197 -0
- sage/interfaces/tides.py +938 -0
- sage/libs/all__sagemath_symbolics.py +6 -0
- sage/manifolds/all.py +7 -0
- sage/manifolds/calculus_method.py +553 -0
- sage/manifolds/catalog.py +437 -0
- sage/manifolds/chart.py +4010 -0
- sage/manifolds/chart_func.py +3416 -0
- sage/manifolds/continuous_map.py +2183 -0
- sage/manifolds/continuous_map_image.py +155 -0
- sage/manifolds/differentiable/affine_connection.py +2475 -0
- sage/manifolds/differentiable/all.py +1 -0
- sage/manifolds/differentiable/automorphismfield.py +1383 -0
- sage/manifolds/differentiable/automorphismfield_group.py +604 -0
- sage/manifolds/differentiable/bundle_connection.py +1445 -0
- sage/manifolds/differentiable/characteristic_cohomology_class.py +1840 -0
- sage/manifolds/differentiable/chart.py +1241 -0
- sage/manifolds/differentiable/curve.py +1028 -0
- sage/manifolds/differentiable/de_rham_cohomology.py +541 -0
- sage/manifolds/differentiable/degenerate.py +559 -0
- sage/manifolds/differentiable/degenerate_submanifold.py +1668 -0
- sage/manifolds/differentiable/diff_form.py +1660 -0
- sage/manifolds/differentiable/diff_form_module.py +1062 -0
- sage/manifolds/differentiable/diff_map.py +1315 -0
- sage/manifolds/differentiable/differentiable_submanifold.py +291 -0
- sage/manifolds/differentiable/examples/all.py +1 -0
- sage/manifolds/differentiable/examples/euclidean.py +2517 -0
- sage/manifolds/differentiable/examples/real_line.py +897 -0
- sage/manifolds/differentiable/examples/sphere.py +1186 -0
- sage/manifolds/differentiable/examples/symplectic_space.py +187 -0
- sage/manifolds/differentiable/examples/symplectic_space_test.py +40 -0
- sage/manifolds/differentiable/integrated_curve.py +4035 -0
- sage/manifolds/differentiable/levi_civita_connection.py +841 -0
- sage/manifolds/differentiable/manifold.py +4254 -0
- sage/manifolds/differentiable/manifold_homset.py +1826 -0
- sage/manifolds/differentiable/metric.py +3032 -0
- sage/manifolds/differentiable/mixed_form.py +1507 -0
- sage/manifolds/differentiable/mixed_form_algebra.py +559 -0
- sage/manifolds/differentiable/multivector_module.py +800 -0
- sage/manifolds/differentiable/multivectorfield.py +1522 -0
- sage/manifolds/differentiable/poisson_tensor.py +268 -0
- sage/manifolds/differentiable/pseudo_riemannian.py +755 -0
- sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +1839 -0
- sage/manifolds/differentiable/scalarfield.py +1343 -0
- sage/manifolds/differentiable/scalarfield_algebra.py +472 -0
- sage/manifolds/differentiable/symplectic_form.py +912 -0
- sage/manifolds/differentiable/symplectic_form_test.py +220 -0
- sage/manifolds/differentiable/tangent_space.py +412 -0
- sage/manifolds/differentiable/tangent_vector.py +616 -0
- sage/manifolds/differentiable/tensorfield.py +4665 -0
- sage/manifolds/differentiable/tensorfield_module.py +963 -0
- sage/manifolds/differentiable/tensorfield_paral.py +2450 -0
- sage/manifolds/differentiable/tensorfield_paral_test.py +16 -0
- sage/manifolds/differentiable/vector_bundle.py +1725 -0
- sage/manifolds/differentiable/vectorfield.py +1717 -0
- sage/manifolds/differentiable/vectorfield_module.py +2445 -0
- sage/manifolds/differentiable/vectorframe.py +1832 -0
- sage/manifolds/family.py +270 -0
- sage/manifolds/local_frame.py +1490 -0
- sage/manifolds/manifold.py +3090 -0
- sage/manifolds/manifold_homset.py +452 -0
- sage/manifolds/operators.py +359 -0
- sage/manifolds/point.py +994 -0
- sage/manifolds/scalarfield.py +3718 -0
- sage/manifolds/scalarfield_algebra.py +629 -0
- sage/manifolds/section.py +3111 -0
- sage/manifolds/section_module.py +831 -0
- sage/manifolds/structure.py +229 -0
- sage/manifolds/subset.py +2721 -0
- sage/manifolds/subsets/all.py +1 -0
- sage/manifolds/subsets/closure.py +131 -0
- sage/manifolds/subsets/pullback.py +883 -0
- sage/manifolds/topological_submanifold.py +891 -0
- sage/manifolds/trivialization.py +733 -0
- sage/manifolds/utilities.py +1348 -0
- sage/manifolds/vector_bundle.py +1347 -0
- sage/manifolds/vector_bundle_fiber.py +332 -0
- sage/manifolds/vector_bundle_fiber_element.py +111 -0
- sage/matrix/all__sagemath_symbolics.py +1 -0
- sage/matrix/matrix_symbolic_dense.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_symbolic_dense.pxd +6 -0
- sage/matrix/matrix_symbolic_dense.pyx +1030 -0
- sage/matrix/matrix_symbolic_sparse.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_symbolic_sparse.pxd +6 -0
- sage/matrix/matrix_symbolic_sparse.pyx +1038 -0
- sage/modules/all__sagemath_symbolics.py +1 -0
- sage/modules/vector_callable_symbolic_dense.py +105 -0
- sage/modules/vector_symbolic_dense.py +116 -0
- sage/modules/vector_symbolic_sparse.py +118 -0
- sage/rings/all__sagemath_symbolics.py +4 -0
- sage/rings/asymptotic/all.py +6 -0
- sage/rings/asymptotic/asymptotic_expansion_generators.py +1485 -0
- sage/rings/asymptotic/asymptotic_ring.py +4858 -0
- sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +4106 -0
- sage/rings/asymptotic/growth_group.py +5373 -0
- sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
- sage/rings/asymptotic/term_monoid.py +5205 -0
- sage/rings/function_field/all__sagemath_symbolics.py +2 -0
- sage/rings/polynomial/all__sagemath_symbolics.py +1 -0
- sage/symbolic/all.py +15 -0
- sage/symbolic/assumptions.py +987 -0
- sage/symbolic/benchmark.py +93 -0
- sage/symbolic/callable.py +456 -0
- sage/symbolic/callable.pyi +66 -0
- sage/symbolic/comparison_impl.pyi +38 -0
- sage/symbolic/complexity_measures.py +35 -0
- sage/symbolic/constants.py +1286 -0
- sage/symbolic/constants_c_impl.pyi +10 -0
- sage/symbolic/expression_conversion_algebraic.py +310 -0
- sage/symbolic/expression_conversion_sympy.py +317 -0
- sage/symbolic/expression_conversions.py +1727 -0
- sage/symbolic/function_factory.py +355 -0
- sage/symbolic/function_factory.pyi +41 -0
- sage/symbolic/getitem_impl.pyi +24 -0
- sage/symbolic/integration/all.py +1 -0
- sage/symbolic/integration/external.py +271 -0
- sage/symbolic/integration/integral.py +1075 -0
- sage/symbolic/maxima_wrapper.py +162 -0
- sage/symbolic/operators.py +267 -0
- sage/symbolic/operators.pyi +61 -0
- sage/symbolic/pynac_constant_impl.pyi +13 -0
- sage/symbolic/pynac_function_impl.pyi +8 -0
- sage/symbolic/random_tests.py +461 -0
- sage/symbolic/relation.py +2062 -0
- sage/symbolic/ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/symbolic/ring.pxd +5 -0
- sage/symbolic/ring.pyi +110 -0
- sage/symbolic/ring.pyx +1393 -0
- sage/symbolic/series_impl.pyi +10 -0
- sage/symbolic/subring.py +1025 -0
- sage/symbolic/symengine.py +19 -0
- sage/symbolic/tests.py +40 -0
- sage/symbolic/units.py +1468 -0
sage/manifolds/subset.py
ADDED
|
@@ -0,0 +1,2721 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-symbolics
|
|
2
|
+
r"""
|
|
3
|
+
Subsets of Topological Manifolds
|
|
4
|
+
|
|
5
|
+
The class :class:`ManifoldSubset` implements generic subsets of a
|
|
6
|
+
topological manifold. Open subsets are implemented by the class
|
|
7
|
+
:class:`~sage.manifolds.manifold.TopologicalManifold` (since an
|
|
8
|
+
open subset of a manifold is a manifold by itself), which inherits
|
|
9
|
+
from :class:`ManifoldSubset`. Besides, subsets that are images of
|
|
10
|
+
a manifold subset under a continuous map are implemented by the
|
|
11
|
+
subclass :class:`~sage.manifolds.continuous_map_image.ImageManifoldSubset`.
|
|
12
|
+
|
|
13
|
+
AUTHORS:
|
|
14
|
+
|
|
15
|
+
- Eric Gourgoulhon, Michal Bejger (2013-2015): initial version
|
|
16
|
+
- Travis Scrimshaw (2015): review tweaks; removal of facade parents
|
|
17
|
+
- Matthias Koeppe (2021): Families and posets of subsets
|
|
18
|
+
|
|
19
|
+
REFERENCES:
|
|
20
|
+
|
|
21
|
+
- [Lee2011]_
|
|
22
|
+
|
|
23
|
+
EXAMPLES:
|
|
24
|
+
|
|
25
|
+
Two subsets on a manifold::
|
|
26
|
+
|
|
27
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
28
|
+
sage: a = M.subset('A'); a
|
|
29
|
+
Subset A of the 2-dimensional topological manifold M
|
|
30
|
+
sage: b = M.subset('B'); b
|
|
31
|
+
Subset B of the 2-dimensional topological manifold M
|
|
32
|
+
sage: M.subset_family()
|
|
33
|
+
Set {A, B, M} of subsets of the 2-dimensional topological manifold M
|
|
34
|
+
|
|
35
|
+
The intersection of the two subsets::
|
|
36
|
+
|
|
37
|
+
sage: c = a.intersection(b); c
|
|
38
|
+
Subset A_inter_B of the 2-dimensional topological manifold M
|
|
39
|
+
|
|
40
|
+
Their union::
|
|
41
|
+
|
|
42
|
+
sage: d = a.union(b); d
|
|
43
|
+
Subset A_union_B of the 2-dimensional topological manifold M
|
|
44
|
+
|
|
45
|
+
Families of subsets after the above operations::
|
|
46
|
+
|
|
47
|
+
sage: M.subset_family()
|
|
48
|
+
Set {A, A_inter_B, A_union_B, B, M} of subsets
|
|
49
|
+
of the 2-dimensional topological manifold M
|
|
50
|
+
sage: a.subset_family()
|
|
51
|
+
Set {A, A_inter_B} of subsets of the 2-dimensional topological manifold M
|
|
52
|
+
sage: c.subset_family()
|
|
53
|
+
Set {A_inter_B} of subsets of the 2-dimensional topological manifold M
|
|
54
|
+
sage: d.subset_family()
|
|
55
|
+
Set {A, A_inter_B, A_union_B, B} of subsets
|
|
56
|
+
of the 2-dimensional topological manifold M
|
|
57
|
+
"""
|
|
58
|
+
# ***************************************************************************
|
|
59
|
+
# Copyright (C) 2015-2020 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr>
|
|
60
|
+
# Copyright (C) 2015 Michal Bejger <bejger@camk.edu.pl>
|
|
61
|
+
# Copyright (C) 2015-2016 Travis Scrimshaw <tscrimsh@umn.edu>
|
|
62
|
+
# Copyright (C) 2021 Matthias Koeppe <mkoeppe@math.ucdavis.edu>
|
|
63
|
+
#
|
|
64
|
+
# This program is free software: you can redistribute it and/or modify
|
|
65
|
+
# it under the terms of the GNU General Public License as published by
|
|
66
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
67
|
+
# (at your option) any later version.
|
|
68
|
+
# https://www.gnu.org/licenses/
|
|
69
|
+
# ***************************************************************************
|
|
70
|
+
from __future__ import annotations
|
|
71
|
+
|
|
72
|
+
import itertools
|
|
73
|
+
from collections import defaultdict
|
|
74
|
+
from typing import Optional
|
|
75
|
+
|
|
76
|
+
from sage.categories.sets_cat import Sets
|
|
77
|
+
from sage.manifolds.family import ManifoldObjectFiniteFamily, ManifoldSubsetFiniteFamily
|
|
78
|
+
from sage.manifolds.point import ManifoldPoint
|
|
79
|
+
from sage.structure.parent import Parent
|
|
80
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class ManifoldSubset(UniqueRepresentation, Parent):
|
|
84
|
+
r"""
|
|
85
|
+
Subset of a topological manifold.
|
|
86
|
+
|
|
87
|
+
The class :class:`ManifoldSubset` inherits from the generic
|
|
88
|
+
class :class:`~sage.structure.parent.Parent`.
|
|
89
|
+
The corresponding element class is
|
|
90
|
+
:class:`~sage.manifolds.point.ManifoldPoint`.
|
|
91
|
+
|
|
92
|
+
Note that open subsets are not implemented directly by this class, but
|
|
93
|
+
by the derived class :class:`~sage.manifolds.manifold.TopologicalManifold`
|
|
94
|
+
(an open subset of a topological manifold being itself a topological
|
|
95
|
+
manifold).
|
|
96
|
+
|
|
97
|
+
INPUT:
|
|
98
|
+
|
|
99
|
+
- ``manifold`` -- topological manifold on which the subset is defined
|
|
100
|
+
- ``name`` -- string; name (symbol) given to the subset
|
|
101
|
+
- ``latex_name`` -- string (default: ``None``); LaTeX symbol to
|
|
102
|
+
denote the subset; if none are provided, it is set to ``name``
|
|
103
|
+
- ``category`` -- (default: ``None``) to specify the category;
|
|
104
|
+
if ``None``, the category for generic subsets is used
|
|
105
|
+
|
|
106
|
+
EXAMPLES:
|
|
107
|
+
|
|
108
|
+
A subset of a manifold::
|
|
109
|
+
|
|
110
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
111
|
+
sage: from sage.manifolds.subset import ManifoldSubset
|
|
112
|
+
sage: A = ManifoldSubset(M, 'A', latex_name=r'\mathcal{A}')
|
|
113
|
+
sage: A
|
|
114
|
+
Subset A of the 2-dimensional topological manifold M
|
|
115
|
+
sage: latex(A)
|
|
116
|
+
\mathcal{A}
|
|
117
|
+
sage: A.is_subset(M)
|
|
118
|
+
True
|
|
119
|
+
|
|
120
|
+
Instead of importing :class:`ManifoldSubset` in the global
|
|
121
|
+
namespace, it is recommended to use the method
|
|
122
|
+
:meth:`~sage.manifolds.subset.ManifoldSubset.subset` to create a new
|
|
123
|
+
subset::
|
|
124
|
+
|
|
125
|
+
sage: B = M.subset('B', latex_name=r'\mathcal{B}'); B
|
|
126
|
+
Subset B of the 2-dimensional topological manifold M
|
|
127
|
+
sage: M.subset_family()
|
|
128
|
+
Set {A, B, M} of subsets of the 2-dimensional topological manifold M
|
|
129
|
+
|
|
130
|
+
The manifold is itself a subset::
|
|
131
|
+
|
|
132
|
+
sage: isinstance(M, ManifoldSubset)
|
|
133
|
+
True
|
|
134
|
+
sage: M in M.subsets()
|
|
135
|
+
True
|
|
136
|
+
|
|
137
|
+
Instances of :class:`ManifoldSubset` are parents::
|
|
138
|
+
|
|
139
|
+
sage: isinstance(A, Parent)
|
|
140
|
+
True
|
|
141
|
+
sage: A.category()
|
|
142
|
+
Category of subobjects of sets
|
|
143
|
+
sage: p = A.an_element(); p
|
|
144
|
+
Point on the 2-dimensional topological manifold M
|
|
145
|
+
sage: p.parent()
|
|
146
|
+
Subset A of the 2-dimensional topological manifold M
|
|
147
|
+
sage: p in A
|
|
148
|
+
True
|
|
149
|
+
sage: p in M
|
|
150
|
+
True
|
|
151
|
+
"""
|
|
152
|
+
|
|
153
|
+
Element = ManifoldPoint
|
|
154
|
+
|
|
155
|
+
_name: str
|
|
156
|
+
|
|
157
|
+
def __init__(self, manifold, name: str, latex_name=None, category=None):
|
|
158
|
+
r"""
|
|
159
|
+
Construct a manifold subset.
|
|
160
|
+
|
|
161
|
+
TESTS::
|
|
162
|
+
|
|
163
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
164
|
+
sage: A = M.subset('A'); A
|
|
165
|
+
Subset A of the 2-dimensional topological manifold M
|
|
166
|
+
sage: type(A)
|
|
167
|
+
<class 'sage.manifolds.subset.ManifoldSubset_with_category'>
|
|
168
|
+
sage: A.category()
|
|
169
|
+
Category of subobjects of sets
|
|
170
|
+
sage: TestSuite(A).run(skip='_test_elements')
|
|
171
|
+
|
|
172
|
+
.. NOTE::
|
|
173
|
+
|
|
174
|
+
``_test_elements`` cannot be passed without a proper
|
|
175
|
+
coordinate definition of the subset.
|
|
176
|
+
"""
|
|
177
|
+
if not isinstance(name, str):
|
|
178
|
+
raise TypeError("{} is not a string".format(name))
|
|
179
|
+
self._name = name
|
|
180
|
+
if latex_name is None:
|
|
181
|
+
self._latex_name = self._name
|
|
182
|
+
else:
|
|
183
|
+
if not isinstance(latex_name, str):
|
|
184
|
+
raise TypeError("{} is not a string".format(latex_name))
|
|
185
|
+
self._latex_name = latex_name
|
|
186
|
+
if category is None:
|
|
187
|
+
category = Sets().Subobjects()
|
|
188
|
+
base = None
|
|
189
|
+
else:
|
|
190
|
+
base = manifold._field
|
|
191
|
+
Parent.__init__(self, base=base, category=category)
|
|
192
|
+
if self is not manifold:
|
|
193
|
+
for dom in manifold._subsets:
|
|
194
|
+
if name == dom._name:
|
|
195
|
+
raise ValueError("the name '" + name +
|
|
196
|
+
"' is already used for another " +
|
|
197
|
+
"subset of the {}".format(manifold))
|
|
198
|
+
manifold._subsets.add(self)
|
|
199
|
+
|
|
200
|
+
# subsets containing self
|
|
201
|
+
self._supersets = {manifold, self}
|
|
202
|
+
|
|
203
|
+
# subsets of self
|
|
204
|
+
self._subsets = {self}
|
|
205
|
+
|
|
206
|
+
# subsets contained in self but not in another strict subset of self
|
|
207
|
+
self._top_subsets = {self}
|
|
208
|
+
|
|
209
|
+
# dict. of intersections with other subsets (key: subset name)
|
|
210
|
+
self._intersections = {}
|
|
211
|
+
|
|
212
|
+
# dict. of unions with other subsets (key: subset name)
|
|
213
|
+
self._unions = {}
|
|
214
|
+
|
|
215
|
+
self._open_covers = [] # list of open covers of self
|
|
216
|
+
self._is_open = False # a priori (may be redefined by subclasses)
|
|
217
|
+
self._manifold = manifold # the ambient manifold
|
|
218
|
+
self._has_defined_points = False
|
|
219
|
+
|
|
220
|
+
def _repr_(self) -> str:
|
|
221
|
+
r"""
|
|
222
|
+
String representation of the object.
|
|
223
|
+
|
|
224
|
+
TESTS::
|
|
225
|
+
|
|
226
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
227
|
+
sage: A = M.subset('A')
|
|
228
|
+
sage: A._repr_()
|
|
229
|
+
'Subset A of the 2-dimensional topological manifold M'
|
|
230
|
+
sage: repr(A) # indirect doctest
|
|
231
|
+
'Subset A of the 2-dimensional topological manifold M'
|
|
232
|
+
"""
|
|
233
|
+
return "Subset {} of the {}".format(self._name, self._manifold)
|
|
234
|
+
|
|
235
|
+
def _latex_(self) -> str:
|
|
236
|
+
r"""
|
|
237
|
+
LaTeX representation of ``self``.
|
|
238
|
+
|
|
239
|
+
TESTS::
|
|
240
|
+
|
|
241
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
242
|
+
sage: A = M.subset('A')
|
|
243
|
+
sage: A._latex_()
|
|
244
|
+
'A'
|
|
245
|
+
sage: B = A.subset('B', latex_name=r'\mathcal{B}')
|
|
246
|
+
sage: B._latex_()
|
|
247
|
+
'\\mathcal{B}'
|
|
248
|
+
sage: latex(B) # indirect doctest
|
|
249
|
+
\mathcal{B}
|
|
250
|
+
|
|
251
|
+
sage: M = Manifold(3, 'M', structure='topological')
|
|
252
|
+
sage: M._latex_()
|
|
253
|
+
'M'
|
|
254
|
+
sage: latex(M)
|
|
255
|
+
M
|
|
256
|
+
sage: M = Manifold(3, 'M', latex_name=r'\mathcal{M}',
|
|
257
|
+
....: structure='topological')
|
|
258
|
+
sage: M._latex_()
|
|
259
|
+
'\\mathcal{M}'
|
|
260
|
+
sage: latex(M) # indirect doctest
|
|
261
|
+
\mathcal{M}
|
|
262
|
+
"""
|
|
263
|
+
return self._latex_name
|
|
264
|
+
|
|
265
|
+
# ### Methods required for any Parent in the category of sets:
|
|
266
|
+
|
|
267
|
+
def _element_constructor_(self, coords=None, chart=None, name=None,
|
|
268
|
+
latex_name=None, check_coords=True):
|
|
269
|
+
r"""
|
|
270
|
+
Construct a point in the subset from its coordinates in some chart.
|
|
271
|
+
|
|
272
|
+
INPUT:
|
|
273
|
+
|
|
274
|
+
- ``coords`` -- (default: ``None``) either (i) the point coordinates
|
|
275
|
+
(as a tuple or a list) in the chart ``chart`` or (ii) another point
|
|
276
|
+
in the subset
|
|
277
|
+
- ``chart`` -- (default: ``None``) chart in which the coordinates
|
|
278
|
+
are given; if none are provided, the coordinates are assumed to
|
|
279
|
+
refer to the subset's default chart
|
|
280
|
+
- ``name`` -- (default: ``None``) name given to the point
|
|
281
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
282
|
+
point; if none are provided, the LaTeX symbol is set to ``name``
|
|
283
|
+
- ``check_coords`` -- boolean (default: ``True``); determines whether
|
|
284
|
+
``coords`` are valid coordinates for the chart ``chart``.
|
|
285
|
+
For symbolic coordinates, it is recommended to set ``check_coords``
|
|
286
|
+
to ``False``.
|
|
287
|
+
|
|
288
|
+
OUTPUT:
|
|
289
|
+
|
|
290
|
+
An instance of :class:`~sage.manifolds.point.ManifoldPoint`
|
|
291
|
+
representing a point in the current subset.
|
|
292
|
+
|
|
293
|
+
EXAMPLES::
|
|
294
|
+
|
|
295
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
296
|
+
sage: X.<x,y> = M.chart()
|
|
297
|
+
sage: p = M((-2,3)); p # coord in the default chart
|
|
298
|
+
Point on the 2-dimensional topological manifold M
|
|
299
|
+
sage: X(p)
|
|
300
|
+
(-2, 3)
|
|
301
|
+
|
|
302
|
+
A generic subset has no default chart, so the chart must
|
|
303
|
+
be explicitly given::
|
|
304
|
+
|
|
305
|
+
sage: A = M.subset('A')
|
|
306
|
+
sage: p = A((-2,3), chart=X); p
|
|
307
|
+
Point on the 2-dimensional topological manifold M
|
|
308
|
+
sage: X(p)
|
|
309
|
+
(-2, 3)
|
|
310
|
+
sage: p.parent()
|
|
311
|
+
Subset A of the 2-dimensional topological manifold M
|
|
312
|
+
sage: p in A
|
|
313
|
+
True
|
|
314
|
+
|
|
315
|
+
Coordinates in a chart with some coordinate restrictions::
|
|
316
|
+
|
|
317
|
+
sage: Y.<u,v> = M.chart('u:(-1,1) v:(-1,1)')
|
|
318
|
+
sage: p = A((0,1/2), chart=Y); p
|
|
319
|
+
Point on the 2-dimensional topological manifold M
|
|
320
|
+
sage: Y(p)
|
|
321
|
+
(0, 1/2)
|
|
322
|
+
sage: p = A((0,1/2), chart=Y, check_coords=False); p
|
|
323
|
+
Point on the 2-dimensional topological manifold M
|
|
324
|
+
sage: Y(p)
|
|
325
|
+
(0, 1/2)
|
|
326
|
+
sage: p = A((3,1/2), chart=Y)
|
|
327
|
+
Traceback (most recent call last):
|
|
328
|
+
...
|
|
329
|
+
ValueError: the coordinates (3, 1/2) are not valid on the Chart (M, (u, v))
|
|
330
|
+
|
|
331
|
+
Specifying the name of the point::
|
|
332
|
+
|
|
333
|
+
sage: p = A((-2,3), chart=X, name='p'); p
|
|
334
|
+
Point p on the 2-dimensional topological manifold M
|
|
335
|
+
|
|
336
|
+
A point as entry::
|
|
337
|
+
|
|
338
|
+
sage: q = A(p); q
|
|
339
|
+
Point p on the 2-dimensional topological manifold M
|
|
340
|
+
sage: X(q)
|
|
341
|
+
(-2, 3)
|
|
342
|
+
"""
|
|
343
|
+
if isinstance(coords, ManifoldPoint):
|
|
344
|
+
point = coords # for readability
|
|
345
|
+
# This should actually never happen by the coercion framework...
|
|
346
|
+
if point.parent() is self:
|
|
347
|
+
return point
|
|
348
|
+
if point in self:
|
|
349
|
+
resu = self.element_class(self, name=point._name,
|
|
350
|
+
latex_name=point._latex_name)
|
|
351
|
+
for chart, coords in point._coordinates.items():
|
|
352
|
+
resu._coordinates[chart] = coords
|
|
353
|
+
return resu
|
|
354
|
+
else:
|
|
355
|
+
raise ValueError("the {}".format(point) +
|
|
356
|
+
" is not in {}".format(self))
|
|
357
|
+
return self.element_class(self, coords=coords, chart=chart,
|
|
358
|
+
name=name, latex_name=latex_name,
|
|
359
|
+
check_coords=check_coords)
|
|
360
|
+
|
|
361
|
+
def _an_element_(self):
|
|
362
|
+
r"""
|
|
363
|
+
Construct some point in the subset.
|
|
364
|
+
|
|
365
|
+
EXAMPLES::
|
|
366
|
+
|
|
367
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
368
|
+
sage: X.<x,y> = M.chart()
|
|
369
|
+
sage: A = M.subset('A')
|
|
370
|
+
sage: p = A._an_element_(); p
|
|
371
|
+
Point on the 2-dimensional topological manifold M
|
|
372
|
+
sage: p in A
|
|
373
|
+
True
|
|
374
|
+
"""
|
|
375
|
+
# ! should be improved...
|
|
376
|
+
return self.element_class(self)
|
|
377
|
+
|
|
378
|
+
# ### End of methods required for any Parent in the category of sets
|
|
379
|
+
|
|
380
|
+
def __contains__(self, point):
|
|
381
|
+
r"""
|
|
382
|
+
Check whether ``point`` is contained in ``self``.
|
|
383
|
+
|
|
384
|
+
TESTS::
|
|
385
|
+
|
|
386
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
387
|
+
sage: X.<x,y> = M.chart()
|
|
388
|
+
sage: A = M.subset('A')
|
|
389
|
+
sage: p = A((-2,3), chart=X); p
|
|
390
|
+
Point on the 2-dimensional topological manifold M
|
|
391
|
+
sage: A.__contains__(p)
|
|
392
|
+
True
|
|
393
|
+
sage: p in A # indirect doctest
|
|
394
|
+
True
|
|
395
|
+
sage: A.__contains__(A.an_element())
|
|
396
|
+
True
|
|
397
|
+
sage: q = M((0,0), chart=X); q
|
|
398
|
+
Point on the 2-dimensional topological manifold M
|
|
399
|
+
sage: A.__contains__(q)
|
|
400
|
+
False
|
|
401
|
+
"""
|
|
402
|
+
# for efficiency, a quick test first:
|
|
403
|
+
if point.parent() is self:
|
|
404
|
+
return True
|
|
405
|
+
if point.parent().is_subset(self):
|
|
406
|
+
return True
|
|
407
|
+
# ! should be improved once coordinate definition have been introduced
|
|
408
|
+
# in ManifoldSubset
|
|
409
|
+
return False
|
|
410
|
+
|
|
411
|
+
def lift(self, p):
|
|
412
|
+
r"""
|
|
413
|
+
Return the lift of ``p`` to the ambient manifold of ``self``.
|
|
414
|
+
|
|
415
|
+
INPUT:
|
|
416
|
+
|
|
417
|
+
- ``p`` -- point of the subset
|
|
418
|
+
|
|
419
|
+
OUTPUT: the same point, considered as a point of the ambient manifold
|
|
420
|
+
|
|
421
|
+
EXAMPLES::
|
|
422
|
+
|
|
423
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
424
|
+
sage: X.<x,y> = M.chart()
|
|
425
|
+
sage: A = M.open_subset('A', coord_def={X: x>0})
|
|
426
|
+
sage: p = A((1, -2)); p
|
|
427
|
+
Point on the 2-dimensional topological manifold M
|
|
428
|
+
sage: p.parent()
|
|
429
|
+
Open subset A of the 2-dimensional topological manifold M
|
|
430
|
+
sage: q = A.lift(p); q
|
|
431
|
+
Point on the 2-dimensional topological manifold M
|
|
432
|
+
sage: q.parent()
|
|
433
|
+
2-dimensional topological manifold M
|
|
434
|
+
sage: q.coord()
|
|
435
|
+
(1, -2)
|
|
436
|
+
sage: (p == q) and (q == p)
|
|
437
|
+
True
|
|
438
|
+
"""
|
|
439
|
+
return self._manifold(p)
|
|
440
|
+
|
|
441
|
+
def retract(self, p):
|
|
442
|
+
r"""
|
|
443
|
+
Return the retract of ``p`` to ``self``.
|
|
444
|
+
|
|
445
|
+
INPUT:
|
|
446
|
+
|
|
447
|
+
- ``p`` -- point of the ambient manifold
|
|
448
|
+
|
|
449
|
+
OUTPUT: the same point, considered as a point of the subset
|
|
450
|
+
|
|
451
|
+
EXAMPLES::
|
|
452
|
+
|
|
453
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
454
|
+
sage: X.<x,y> = M.chart()
|
|
455
|
+
sage: A = M.open_subset('A', coord_def={X: x>0})
|
|
456
|
+
sage: p = M((1, -2)); p
|
|
457
|
+
Point on the 2-dimensional topological manifold M
|
|
458
|
+
sage: p.parent()
|
|
459
|
+
2-dimensional topological manifold M
|
|
460
|
+
sage: q = A.retract(p); q
|
|
461
|
+
Point on the 2-dimensional topological manifold M
|
|
462
|
+
sage: q.parent()
|
|
463
|
+
Open subset A of the 2-dimensional topological manifold M
|
|
464
|
+
sage: q.coord()
|
|
465
|
+
(1, -2)
|
|
466
|
+
sage: (q == p) and (p == q)
|
|
467
|
+
True
|
|
468
|
+
|
|
469
|
+
Of course, if the point does not belong to ``A``, the ``retract``
|
|
470
|
+
method fails::
|
|
471
|
+
|
|
472
|
+
sage: p = M((-1, 3)) # x < 0, so that p is not in A
|
|
473
|
+
sage: q = A.retract(p)
|
|
474
|
+
Traceback (most recent call last):
|
|
475
|
+
...
|
|
476
|
+
ValueError: the Point on the 2-dimensional topological manifold M
|
|
477
|
+
is not in Open subset A of the 2-dimensional topological manifold M
|
|
478
|
+
"""
|
|
479
|
+
return self(p)
|
|
480
|
+
|
|
481
|
+
# ### Accessors
|
|
482
|
+
|
|
483
|
+
def manifold(self):
|
|
484
|
+
r"""
|
|
485
|
+
Return the ambient manifold of ``self``.
|
|
486
|
+
|
|
487
|
+
EXAMPLES::
|
|
488
|
+
|
|
489
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
490
|
+
sage: A = M.subset('A')
|
|
491
|
+
sage: A.manifold()
|
|
492
|
+
2-dimensional topological manifold M
|
|
493
|
+
sage: A.manifold() is M
|
|
494
|
+
True
|
|
495
|
+
sage: B = A.subset('B')
|
|
496
|
+
sage: B.manifold() is M
|
|
497
|
+
True
|
|
498
|
+
|
|
499
|
+
An alias is ``ambient``::
|
|
500
|
+
|
|
501
|
+
sage: A.ambient() is A.manifold()
|
|
502
|
+
True
|
|
503
|
+
"""
|
|
504
|
+
return self._manifold
|
|
505
|
+
|
|
506
|
+
ambient = manifold
|
|
507
|
+
|
|
508
|
+
def is_open(self):
|
|
509
|
+
r"""
|
|
510
|
+
Return if ``self`` is an open set.
|
|
511
|
+
|
|
512
|
+
This method always returns ``False``, since open subsets must be
|
|
513
|
+
constructed as instances of the subclass
|
|
514
|
+
:class:`~sage.manifolds.manifold.TopologicalManifold`
|
|
515
|
+
(which redefines ``is_open``)
|
|
516
|
+
|
|
517
|
+
EXAMPLES::
|
|
518
|
+
|
|
519
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
520
|
+
sage: A = M.subset('A')
|
|
521
|
+
sage: A.is_open()
|
|
522
|
+
False
|
|
523
|
+
"""
|
|
524
|
+
return False
|
|
525
|
+
|
|
526
|
+
def is_closed(self):
|
|
527
|
+
r"""
|
|
528
|
+
Return if ``self`` is a closed set.
|
|
529
|
+
|
|
530
|
+
EXAMPLES::
|
|
531
|
+
|
|
532
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
533
|
+
sage: M.is_closed()
|
|
534
|
+
True
|
|
535
|
+
sage: also_M = M.subset('also_M')
|
|
536
|
+
sage: M.declare_subset(also_M)
|
|
537
|
+
sage: also_M.is_closed()
|
|
538
|
+
True
|
|
539
|
+
|
|
540
|
+
sage: A = M.subset('A')
|
|
541
|
+
sage: A.is_closed()
|
|
542
|
+
False
|
|
543
|
+
sage: A.declare_empty()
|
|
544
|
+
sage: A.is_closed()
|
|
545
|
+
True
|
|
546
|
+
|
|
547
|
+
sage: N = M.open_subset('N')
|
|
548
|
+
sage: N.is_closed()
|
|
549
|
+
False
|
|
550
|
+
sage: complement_N = M.subset('complement_N')
|
|
551
|
+
sage: M.declare_union(N, complement_N, disjoint=True)
|
|
552
|
+
sage: complement_N.is_closed()
|
|
553
|
+
True
|
|
554
|
+
"""
|
|
555
|
+
if self.manifold().is_subset(self):
|
|
556
|
+
return True
|
|
557
|
+
if self.is_empty():
|
|
558
|
+
return True
|
|
559
|
+
for other_name, intersection in self._intersections.items():
|
|
560
|
+
if intersection.is_empty():
|
|
561
|
+
other = self.manifold().subset_family()[other_name]
|
|
562
|
+
if other.is_open():
|
|
563
|
+
try:
|
|
564
|
+
union = self._unions[other_name]
|
|
565
|
+
except KeyError:
|
|
566
|
+
pass
|
|
567
|
+
else:
|
|
568
|
+
if union.is_open():
|
|
569
|
+
# self is complement of open other in open union
|
|
570
|
+
return True
|
|
571
|
+
return False
|
|
572
|
+
|
|
573
|
+
def open_covers(self, trivial=True, supersets=False):
|
|
574
|
+
r"""
|
|
575
|
+
Generate the open covers of the current subset.
|
|
576
|
+
|
|
577
|
+
If the current subset, `A` say, is a subset of the manifold `M`, an
|
|
578
|
+
*open cover* of `A` is a :class:`ManifoldSubsetFiniteFamily` `F`
|
|
579
|
+
of open subsets `U \in F` of `M` such that
|
|
580
|
+
|
|
581
|
+
.. MATH::
|
|
582
|
+
|
|
583
|
+
A \subset \bigcup_{U \in F} U.
|
|
584
|
+
|
|
585
|
+
If `A` is open, we ask that the above inclusion is actually an
|
|
586
|
+
identity:
|
|
587
|
+
|
|
588
|
+
.. MATH::
|
|
589
|
+
|
|
590
|
+
A = \bigcup_{U \in F} U.
|
|
591
|
+
|
|
592
|
+
.. NOTE::
|
|
593
|
+
|
|
594
|
+
To get the open covers as a family, sorted lexicographically by the
|
|
595
|
+
names of the subsets forming the open covers, use the method
|
|
596
|
+
:meth:`open_cover_family` instead.
|
|
597
|
+
|
|
598
|
+
INPUT:
|
|
599
|
+
|
|
600
|
+
- ``trivial`` -- boolean (default: ``True``); if ``self`` is open,
|
|
601
|
+
include the trivial open cover of ``self`` by itself
|
|
602
|
+
- ``supersets`` -- boolean (default: ``False``); if ``True``, include
|
|
603
|
+
open covers of all the supersets. It can also be an iterable of
|
|
604
|
+
supersets to include.
|
|
605
|
+
|
|
606
|
+
EXAMPLES::
|
|
607
|
+
|
|
608
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
609
|
+
sage: M.open_covers()
|
|
610
|
+
<generator ...>
|
|
611
|
+
sage: list(M.open_covers())
|
|
612
|
+
[Set {M} of open subsets of the 2-dimensional topological manifold M]
|
|
613
|
+
sage: U = M.open_subset('U')
|
|
614
|
+
sage: list(U.open_covers())
|
|
615
|
+
[Set {U} of open subsets of the 2-dimensional topological manifold M]
|
|
616
|
+
sage: A = U.open_subset('A')
|
|
617
|
+
sage: B = U.open_subset('B')
|
|
618
|
+
sage: U.declare_union(A,B)
|
|
619
|
+
sage: list(U.open_covers())
|
|
620
|
+
[Set {U} of open subsets of the 2-dimensional topological manifold M,
|
|
621
|
+
Set {A, B} of open subsets of the 2-dimensional topological manifold M]
|
|
622
|
+
sage: list(U.open_covers(trivial=False))
|
|
623
|
+
[Set {A, B} of open subsets of the 2-dimensional topological manifold M]
|
|
624
|
+
sage: V = M.open_subset('V')
|
|
625
|
+
sage: M.declare_union(U,V)
|
|
626
|
+
sage: list(M.open_covers())
|
|
627
|
+
[Set {M} of open subsets of the 2-dimensional topological manifold M,
|
|
628
|
+
Set {U, V} of open subsets of the 2-dimensional topological manifold M,
|
|
629
|
+
Set {A, B, V} of open subsets of the 2-dimensional topological manifold M]
|
|
630
|
+
"""
|
|
631
|
+
if supersets is False:
|
|
632
|
+
supersets = [self]
|
|
633
|
+
elif supersets is True:
|
|
634
|
+
supersets = self._supersets
|
|
635
|
+
for superset in supersets:
|
|
636
|
+
for oc in superset._open_covers:
|
|
637
|
+
if not trivial:
|
|
638
|
+
if any(x in supersets for x in oc):
|
|
639
|
+
continue
|
|
640
|
+
yield ManifoldSubsetFiniteFamily(oc)
|
|
641
|
+
|
|
642
|
+
def open_cover_family(self, trivial=True, supersets=False):
|
|
643
|
+
r"""
|
|
644
|
+
Return the family of open covers of the current subset.
|
|
645
|
+
|
|
646
|
+
If the current subset, `A` say, is a subset of the manifold `M`, an
|
|
647
|
+
*open cover* of `A` is a :class:`ManifoldSubsetFiniteFamily` `F`
|
|
648
|
+
of open subsets `U \in F` of `M` such that
|
|
649
|
+
|
|
650
|
+
.. MATH::
|
|
651
|
+
|
|
652
|
+
A \subset \bigcup_{U \in F} U.
|
|
653
|
+
|
|
654
|
+
If `A` is open, we ask that the above inclusion is actually an
|
|
655
|
+
identity:
|
|
656
|
+
|
|
657
|
+
.. MATH::
|
|
658
|
+
|
|
659
|
+
A = \bigcup_{U \in F} U.
|
|
660
|
+
|
|
661
|
+
The family is sorted lexicographically by the names of the subsets
|
|
662
|
+
forming the open covers.
|
|
663
|
+
|
|
664
|
+
.. NOTE::
|
|
665
|
+
|
|
666
|
+
If you only need to iterate over the open covers in arbitrary
|
|
667
|
+
order, you can use the generator method :meth:`open_covers`
|
|
668
|
+
instead.
|
|
669
|
+
|
|
670
|
+
INPUT:
|
|
671
|
+
|
|
672
|
+
- ``trivial`` -- boolean (default: ``True``); if ``self`` is open,
|
|
673
|
+
include the trivial open cover of ``self`` by itself
|
|
674
|
+
- ``supersets`` -- boolean (default: ``False``); if ``True``, include
|
|
675
|
+
open covers of all the supersets. It can also be an iterable of
|
|
676
|
+
supersets to include
|
|
677
|
+
|
|
678
|
+
EXAMPLES::
|
|
679
|
+
|
|
680
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
681
|
+
sage: M.open_cover_family()
|
|
682
|
+
Set {{M}} of objects of the 2-dimensional topological manifold M
|
|
683
|
+
sage: U = M.open_subset('U')
|
|
684
|
+
sage: U.open_cover_family()
|
|
685
|
+
Set {{U}} of objects of the 2-dimensional topological manifold M
|
|
686
|
+
sage: A = U.open_subset('A')
|
|
687
|
+
sage: B = U.open_subset('B')
|
|
688
|
+
sage: U.declare_union(A,B)
|
|
689
|
+
sage: U.open_cover_family()
|
|
690
|
+
Set {{A, B}, {U}} of objects of the 2-dimensional topological manifold M
|
|
691
|
+
sage: U.open_cover_family(trivial=False)
|
|
692
|
+
Set {{A, B}} of objects of the 2-dimensional topological manifold M
|
|
693
|
+
sage: V = M.open_subset('V')
|
|
694
|
+
sage: M.declare_union(U,V)
|
|
695
|
+
sage: M.open_cover_family()
|
|
696
|
+
Set {{A, B, V}, {M}, {U, V}} of objects of the 2-dimensional topological manifold M
|
|
697
|
+
"""
|
|
698
|
+
return ManifoldObjectFiniteFamily(self.open_covers(
|
|
699
|
+
trivial=trivial, supersets=supersets))
|
|
700
|
+
|
|
701
|
+
def open_supersets(self):
|
|
702
|
+
r"""
|
|
703
|
+
Generate the open supersets of ``self``.
|
|
704
|
+
|
|
705
|
+
.. NOTE::
|
|
706
|
+
|
|
707
|
+
To get the open supersets as a family, sorted by name, use the method
|
|
708
|
+
:meth:`open_superset_family` instead.
|
|
709
|
+
|
|
710
|
+
EXAMPLES::
|
|
711
|
+
|
|
712
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
713
|
+
sage: U = M.open_subset('U')
|
|
714
|
+
sage: V = U.subset('V')
|
|
715
|
+
sage: W = V.subset('W')
|
|
716
|
+
sage: sorted(W.open_supersets(), key=lambda S: S._name)
|
|
717
|
+
[2-dimensional topological manifold M,
|
|
718
|
+
Open subset U of the 2-dimensional topological manifold M]
|
|
719
|
+
"""
|
|
720
|
+
for superset in self._supersets:
|
|
721
|
+
if superset.is_open():
|
|
722
|
+
yield superset
|
|
723
|
+
|
|
724
|
+
def open_superset_family(self):
|
|
725
|
+
r"""
|
|
726
|
+
Return the family of open supersets of ``self``.
|
|
727
|
+
|
|
728
|
+
The family is sorted by the alphabetical names of the subsets.
|
|
729
|
+
|
|
730
|
+
OUTPUT:
|
|
731
|
+
|
|
732
|
+
- a :class:`ManifoldSubsetFiniteFamily` instance containing all the
|
|
733
|
+
open supersets that have been defined on the current subset
|
|
734
|
+
|
|
735
|
+
.. NOTE::
|
|
736
|
+
|
|
737
|
+
If you only need to iterate over the open supersets in arbitrary
|
|
738
|
+
order, you can use the generator method :meth:`open_supersets`
|
|
739
|
+
instead.
|
|
740
|
+
|
|
741
|
+
EXAMPLES::
|
|
742
|
+
|
|
743
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
744
|
+
sage: U = M.open_subset('U')
|
|
745
|
+
sage: V = U.subset('V')
|
|
746
|
+
sage: W = V.subset('W')
|
|
747
|
+
sage: W.open_superset_family()
|
|
748
|
+
Set {M, U} of open subsets of the 2-dimensional topological manifold M
|
|
749
|
+
"""
|
|
750
|
+
return ManifoldSubsetFiniteFamily(self.open_supersets())
|
|
751
|
+
|
|
752
|
+
def subsets(self):
|
|
753
|
+
r"""
|
|
754
|
+
Generate the subsets that have been defined on the current subset.
|
|
755
|
+
|
|
756
|
+
.. NOTE::
|
|
757
|
+
|
|
758
|
+
To get the subsets as a family, sorted by name, use the method
|
|
759
|
+
:meth:`subset_family` instead.
|
|
760
|
+
|
|
761
|
+
EXAMPLES:
|
|
762
|
+
|
|
763
|
+
Subsets of a 2-dimensional manifold::
|
|
764
|
+
|
|
765
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
766
|
+
sage: U = M.open_subset('U')
|
|
767
|
+
sage: V = M.subset('V')
|
|
768
|
+
sage: frozenset(M.subsets()) # random (set output)
|
|
769
|
+
{Subset V of the 2-dimensional topological manifold M,
|
|
770
|
+
2-dimensional topological manifold M,
|
|
771
|
+
Open subset U of the 2-dimensional topological manifold M}
|
|
772
|
+
sage: U in M.subsets()
|
|
773
|
+
True
|
|
774
|
+
|
|
775
|
+
The method :meth:`subset_family` returns a family (sorted
|
|
776
|
+
alphabetically by the subset names)::
|
|
777
|
+
|
|
778
|
+
sage: M.subset_family()
|
|
779
|
+
Set {M, U, V} of subsets of the 2-dimensional topological manifold M
|
|
780
|
+
"""
|
|
781
|
+
yield from self._subsets
|
|
782
|
+
|
|
783
|
+
def subset_family(self):
|
|
784
|
+
r"""
|
|
785
|
+
Return the family of subsets that have been defined on the current subset.
|
|
786
|
+
|
|
787
|
+
The family is sorted by the alphabetical names of the subsets.
|
|
788
|
+
|
|
789
|
+
OUTPUT:
|
|
790
|
+
|
|
791
|
+
- a :class:`ManifoldSubsetFiniteFamily` instance containing all the
|
|
792
|
+
subsets that have been defined on the current subset
|
|
793
|
+
|
|
794
|
+
.. NOTE::
|
|
795
|
+
|
|
796
|
+
If you only need to iterate over the subsets in arbitrary order,
|
|
797
|
+
you can use the generator method :meth:`subsets` instead.
|
|
798
|
+
|
|
799
|
+
EXAMPLES:
|
|
800
|
+
|
|
801
|
+
Subsets of a 2-dimensional manifold::
|
|
802
|
+
|
|
803
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
804
|
+
sage: U = M.open_subset('U')
|
|
805
|
+
sage: V = M.subset('V')
|
|
806
|
+
sage: M.subset_family()
|
|
807
|
+
Set {M, U, V} of subsets of the 2-dimensional topological manifold M
|
|
808
|
+
"""
|
|
809
|
+
return ManifoldSubsetFiniteFamily(self.subsets())
|
|
810
|
+
|
|
811
|
+
def subset_digraph(self, loops=False, quotient=False, open_covers=False, points=False, lower_bound=None):
|
|
812
|
+
r"""
|
|
813
|
+
Return the digraph whose arcs represent subset relations among the subsets of ``self``.
|
|
814
|
+
|
|
815
|
+
INPUT:
|
|
816
|
+
|
|
817
|
+
- ``loops`` -- boolean (default: ``False``); whether to include the trivial containment
|
|
818
|
+
of each subset in itself as loops of the digraph
|
|
819
|
+
- ``quotient`` -- boolean (default: ``False``); whether to contract directed
|
|
820
|
+
cycles in the graph, replacing equivalence classes of equal subsets by a
|
|
821
|
+
single vertex. In this case, each vertex of the digraph is a set of
|
|
822
|
+
:class:`ManifoldSubset` instances.
|
|
823
|
+
- ``open_covers`` -- boolean (default: ``False``); whether to include vertices for open covers
|
|
824
|
+
- ``points`` -- boolean (default: ``False``); whether to include vertices for declared points;
|
|
825
|
+
this can also be an iterable for the points to include
|
|
826
|
+
- ``lower_bound`` -- (default: ``None``) only include supersets of this
|
|
827
|
+
|
|
828
|
+
OUTPUT: a digraph; each vertex of the digraph is either:
|
|
829
|
+
|
|
830
|
+
- a :class:`ManifoldSubsetFiniteFamily` containing one instance of :class:`ManifoldSubset`.
|
|
831
|
+
- (if ``open_covers`` is ``True``) a tuple of :class:`ManifoldSubsetFiniteFamily` instances,
|
|
832
|
+
representing an open cover.
|
|
833
|
+
|
|
834
|
+
EXAMPLES::
|
|
835
|
+
|
|
836
|
+
sage: # needs sage.graphs
|
|
837
|
+
sage: M = Manifold(3, 'M')
|
|
838
|
+
sage: U = M.open_subset('U'); V = M.open_subset('V'); W = M.open_subset('W')
|
|
839
|
+
sage: D = M.subset_digraph(); D
|
|
840
|
+
Digraph on 4 vertices
|
|
841
|
+
sage: D.edges(sort=True, key=lambda e: (e[0]._name, e[1]._name)) # needs sage.graphs
|
|
842
|
+
[(Set {U} of open subsets of the 3-dimensional differentiable manifold M,
|
|
843
|
+
Set {M} of open subsets of the 3-dimensional differentiable manifold M,
|
|
844
|
+
None),
|
|
845
|
+
(Set {V} of open subsets of the 3-dimensional differentiable manifold M,
|
|
846
|
+
Set {M} of open subsets of the 3-dimensional differentiable manifold M,
|
|
847
|
+
None),
|
|
848
|
+
(Set {W} of open subsets of the 3-dimensional differentiable manifold M,
|
|
849
|
+
Set {M} of open subsets of the 3-dimensional differentiable manifold M,
|
|
850
|
+
None)]
|
|
851
|
+
sage: D.plot(layout='acyclic') # needs sage.plot
|
|
852
|
+
Graphics object consisting of 8 graphics primitives
|
|
853
|
+
sage: def label(element):
|
|
854
|
+
....: try:
|
|
855
|
+
....: return element._name
|
|
856
|
+
....: except AttributeError:
|
|
857
|
+
....: return '[' + ', '.join(sorted(x._name for x in element)) + ']'
|
|
858
|
+
sage: D.relabel(label, inplace=False).plot(layout='acyclic') # needs sage.plot
|
|
859
|
+
Graphics object consisting of 8 graphics primitives
|
|
860
|
+
sage: VW = V.union(W)
|
|
861
|
+
sage: D = M.subset_digraph(); D
|
|
862
|
+
Digraph on 5 vertices
|
|
863
|
+
sage: D.relabel(label, inplace=False).plot(layout='acyclic') # needs sage.plot
|
|
864
|
+
Graphics object consisting of 12 graphics primitives
|
|
865
|
+
|
|
866
|
+
If ``open_covers`` is ``True``, the digraph includes a special vertex for
|
|
867
|
+
each nontrivial open cover of a subset::
|
|
868
|
+
|
|
869
|
+
sage: D = M.subset_digraph(open_covers=True) # needs sage.graphs
|
|
870
|
+
sage: D.relabel(label, inplace=False).plot(layout='acyclic') # needs sage.graphs sage.plot
|
|
871
|
+
Graphics object consisting of 14 graphics primitives
|
|
872
|
+
|
|
873
|
+
.. PLOT::
|
|
874
|
+
|
|
875
|
+
def label(element):
|
|
876
|
+
try:
|
|
877
|
+
return element._name
|
|
878
|
+
except AttributeError:
|
|
879
|
+
return '[' + ', '.join(sorted(x._name for x in element)) + ']'
|
|
880
|
+
M = Manifold(3, 'M')
|
|
881
|
+
U = M.open_subset('U'); V = M.open_subset('V'); W = M.open_subset('W')
|
|
882
|
+
D = M.subset_digraph()
|
|
883
|
+
g1 = D.relabel(label, inplace=False).plot(layout='acyclic')
|
|
884
|
+
VW = V.union(W)
|
|
885
|
+
D = M.subset_digraph()
|
|
886
|
+
g2 = D.relabel(label, inplace=False).plot(layout='acyclic')
|
|
887
|
+
D = M.subset_digraph(open_covers=True)
|
|
888
|
+
g3 = D.relabel(label, inplace=False).plot(layout='acyclic')
|
|
889
|
+
sphinx_plot(graphics_array([g1, g2, g3]), figsize=(8, 3))
|
|
890
|
+
"""
|
|
891
|
+
from sage.graphs.digraph import DiGraph
|
|
892
|
+
D = DiGraph(multiedges=False, loops=loops)
|
|
893
|
+
|
|
894
|
+
if loops:
|
|
895
|
+
add_edges = D.add_edges
|
|
896
|
+
else:
|
|
897
|
+
def add_edges(edges):
|
|
898
|
+
for u, v in edges:
|
|
899
|
+
if u != v:
|
|
900
|
+
D.add_edge((u, v))
|
|
901
|
+
|
|
902
|
+
if quotient:
|
|
903
|
+
def vertex_family(subset):
|
|
904
|
+
return ManifoldSubsetFiniteFamily(subset.equal_subsets())
|
|
905
|
+
else:
|
|
906
|
+
def vertex_family(subset):
|
|
907
|
+
return ManifoldSubsetFiniteFamily([subset])
|
|
908
|
+
subset_to_vertex = {}
|
|
909
|
+
|
|
910
|
+
def vertex(subset):
|
|
911
|
+
try:
|
|
912
|
+
return subset_to_vertex[subset]
|
|
913
|
+
except KeyError:
|
|
914
|
+
family = vertex_family(subset)
|
|
915
|
+
for S in family:
|
|
916
|
+
subset_to_vertex[S] = family
|
|
917
|
+
return family
|
|
918
|
+
|
|
919
|
+
if lower_bound is not None:
|
|
920
|
+
if not lower_bound.is_subset(self):
|
|
921
|
+
return D
|
|
922
|
+
visited = set()
|
|
923
|
+
to_visit = [self]
|
|
924
|
+
while to_visit:
|
|
925
|
+
S = to_visit.pop()
|
|
926
|
+
if S in visited:
|
|
927
|
+
continue
|
|
928
|
+
visited.add(S)
|
|
929
|
+
|
|
930
|
+
if lower_bound is None:
|
|
931
|
+
subsets = S._subsets
|
|
932
|
+
else:
|
|
933
|
+
subsets = [subset for subset in S._subsets
|
|
934
|
+
if lower_bound.is_subset(subset)]
|
|
935
|
+
|
|
936
|
+
add_edges((vertex(subset), vertex(S)) for subset in subsets)
|
|
937
|
+
|
|
938
|
+
subsets_without_S = [subset for subset in subsets
|
|
939
|
+
if subset is not S]
|
|
940
|
+
to_visit.extend(subsets_without_S)
|
|
941
|
+
|
|
942
|
+
# Make sure to include isolated vertices in the graph
|
|
943
|
+
D.add_vertices(subset_to_vertex.values())
|
|
944
|
+
|
|
945
|
+
if open_covers:
|
|
946
|
+
|
|
947
|
+
def open_cover_vertex(open_cover):
|
|
948
|
+
return tuple(sorted(ManifoldSubsetFiniteFamily([subset]) for subset in open_cover))
|
|
949
|
+
|
|
950
|
+
for S in visited:
|
|
951
|
+
add_edges((vertex(S), open_cover_vertex(open_cover))
|
|
952
|
+
for open_cover in S.open_covers(trivial=False))
|
|
953
|
+
|
|
954
|
+
if points is not False:
|
|
955
|
+
subset_to_points = defaultdict(list)
|
|
956
|
+
if points is not True:
|
|
957
|
+
# Manifolds do not keep track of the points defined on them.
|
|
958
|
+
# Use the provided iterator.
|
|
959
|
+
def point_vertex(point):
|
|
960
|
+
return point
|
|
961
|
+
|
|
962
|
+
for point in points:
|
|
963
|
+
S = point.parent()
|
|
964
|
+
subset_to_points[S].append(point)
|
|
965
|
+
D.add_edge((point_vertex(point), vertex(S)))
|
|
966
|
+
|
|
967
|
+
# Add a placeholder vertex under each subset that has a defined
|
|
968
|
+
# point that we do not know about.
|
|
969
|
+
def anonymous_point_vertex(S):
|
|
970
|
+
return f"p{S._name}"
|
|
971
|
+
|
|
972
|
+
add_edges((anonymous_point_vertex(S), vertex(S))
|
|
973
|
+
for S in visited
|
|
974
|
+
if S.has_defined_points(subsets=False)
|
|
975
|
+
and S not in subset_to_points)
|
|
976
|
+
|
|
977
|
+
return D
|
|
978
|
+
|
|
979
|
+
def subset_poset(self, open_covers=False, points=False, lower_bound=None):
|
|
980
|
+
r"""
|
|
981
|
+
Return the poset of equivalence classes of the subsets of ``self``.
|
|
982
|
+
|
|
983
|
+
Each element of the poset is a set of :class:`ManifoldSubset` instances,
|
|
984
|
+
which are known to be equal.
|
|
985
|
+
|
|
986
|
+
INPUT:
|
|
987
|
+
|
|
988
|
+
- ``open_covers`` -- boolean (default: ``False``); whether to include vertices for open covers
|
|
989
|
+
- ``points`` -- boolean (default: ``False``); whether to include vertices for declared points;
|
|
990
|
+
this can also be an iterable for the points to include
|
|
991
|
+
- ``lower_bound`` -- (default: ``None``) only include supersets of this
|
|
992
|
+
|
|
993
|
+
EXAMPLES::
|
|
994
|
+
|
|
995
|
+
sage: # needs sage.graphs
|
|
996
|
+
sage: M = Manifold(3, 'M')
|
|
997
|
+
sage: U = M.open_subset('U'); V = M.open_subset('V'); W = M.open_subset('W')
|
|
998
|
+
sage: P = M.subset_poset(); P
|
|
999
|
+
Finite poset containing 4 elements
|
|
1000
|
+
sage: P.plot(element_labels={element: element._name for element in P}) # needs sage.plot
|
|
1001
|
+
Graphics object consisting of 8 graphics primitives
|
|
1002
|
+
sage: VW = V.union(W)
|
|
1003
|
+
sage: P = M.subset_poset(); P
|
|
1004
|
+
Finite poset containing 5 elements
|
|
1005
|
+
sage: P.maximal_elements()
|
|
1006
|
+
[Set {M} of open subsets of the 3-dimensional differentiable manifold M]
|
|
1007
|
+
sage: sorted(P.minimal_elements(), key=lambda v: v._name)
|
|
1008
|
+
[Set {U} of open subsets of the 3-dimensional differentiable manifold M,
|
|
1009
|
+
Set {V} of open subsets of the 3-dimensional differentiable manifold M,
|
|
1010
|
+
Set {W} of open subsets of the 3-dimensional differentiable manifold M]
|
|
1011
|
+
sage: from sage.manifolds.subset import ManifoldSubsetFiniteFamily
|
|
1012
|
+
sage: sorted(P.lower_covers(ManifoldSubsetFiniteFamily([M])), key=str)
|
|
1013
|
+
[Set {U} of open subsets of the 3-dimensional differentiable manifold M,
|
|
1014
|
+
Set {V_union_W} of open subsets of the 3-dimensional differentiable manifold M]
|
|
1015
|
+
sage: P.plot(element_labels={element: element._name for element in P}) # needs sage.plot
|
|
1016
|
+
Graphics object consisting of 10 graphics primitives
|
|
1017
|
+
|
|
1018
|
+
If ``open_covers`` is ``True``, the poset includes a special vertex for
|
|
1019
|
+
each nontrivial open cover of a subset::
|
|
1020
|
+
|
|
1021
|
+
sage: # needs sage.graphs
|
|
1022
|
+
sage: P = M.subset_poset(open_covers=True); P
|
|
1023
|
+
Finite poset containing 6 elements
|
|
1024
|
+
sage: from sage.manifolds.subset import ManifoldSubsetFiniteFamily
|
|
1025
|
+
sage: sorted(P.upper_covers(ManifoldSubsetFiniteFamily([VW])), key=str)
|
|
1026
|
+
[(Set {V} of open subsets of the 3-dimensional differentiable manifold M,
|
|
1027
|
+
Set {W} of open subsets of the 3-dimensional differentiable manifold M),
|
|
1028
|
+
Set {M} of open subsets of the 3-dimensional differentiable manifold M]
|
|
1029
|
+
sage: def label(element):
|
|
1030
|
+
....: try:
|
|
1031
|
+
....: return element._name
|
|
1032
|
+
....: except AttributeError:
|
|
1033
|
+
....: return '[' + ', '.join(sorted(x._name for x in element)) + ']'
|
|
1034
|
+
sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.plot
|
|
1035
|
+
Graphics object consisting of 12 graphics primitives
|
|
1036
|
+
|
|
1037
|
+
.. PLOT::
|
|
1038
|
+
|
|
1039
|
+
def label(element):
|
|
1040
|
+
try:
|
|
1041
|
+
return element._name
|
|
1042
|
+
except AttributeError:
|
|
1043
|
+
return '[' + ', '.join(sorted(x._name for x in element)) + ']'
|
|
1044
|
+
M = Manifold(3, 'M')
|
|
1045
|
+
U = M.open_subset('U'); V = M.open_subset('V'); W = M.open_subset('W')
|
|
1046
|
+
P = M.subset_poset()
|
|
1047
|
+
g1 = P.plot(element_labels={element: label(element) for element in P})
|
|
1048
|
+
VW = V.union(W)
|
|
1049
|
+
P = M.subset_poset()
|
|
1050
|
+
g2 = P.plot(element_labels={element: label(element) for element in P})
|
|
1051
|
+
P = M.subset_poset(open_covers=True)
|
|
1052
|
+
g3 = P.plot(element_labels={element: label(element) for element in P})
|
|
1053
|
+
sphinx_plot(graphics_array([g1, g2, g3]), figsize=(8, 3))
|
|
1054
|
+
"""
|
|
1055
|
+
from sage.combinat.posets.posets import Poset
|
|
1056
|
+
return Poset(self.subset_digraph(open_covers=open_covers, points=points,
|
|
1057
|
+
quotient=True, lower_bound=lower_bound))
|
|
1058
|
+
|
|
1059
|
+
def equal_subsets(self):
|
|
1060
|
+
r"""
|
|
1061
|
+
Generate the declared manifold subsets that are equal to ``self``.
|
|
1062
|
+
|
|
1063
|
+
.. NOTE::
|
|
1064
|
+
|
|
1065
|
+
To get the equal subsets as a family, sorted by name, use the method
|
|
1066
|
+
:meth:`equal_subset_family` instead.
|
|
1067
|
+
|
|
1068
|
+
EXAMPLES::
|
|
1069
|
+
|
|
1070
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
1071
|
+
sage: U = M.open_subset('U')
|
|
1072
|
+
sage: V = U.subset('V')
|
|
1073
|
+
sage: V.declare_equal(M)
|
|
1074
|
+
sage: sorted(V.equal_subsets(), key=lambda v: v._name)
|
|
1075
|
+
[2-dimensional topological manifold M,
|
|
1076
|
+
Open subset U of the 2-dimensional topological manifold M,
|
|
1077
|
+
Subset V of the 2-dimensional topological manifold M]
|
|
1078
|
+
"""
|
|
1079
|
+
for S in self.supersets():
|
|
1080
|
+
if S in self._subsets:
|
|
1081
|
+
yield S
|
|
1082
|
+
|
|
1083
|
+
def equal_subset_family(self):
|
|
1084
|
+
r"""
|
|
1085
|
+
Generate the declared manifold subsets that are equal to ``self``.
|
|
1086
|
+
|
|
1087
|
+
.. NOTE::
|
|
1088
|
+
|
|
1089
|
+
If you only need to iterate over the equal sets in arbitrary order,
|
|
1090
|
+
you can use the generator method :meth:`equal_subsets` instead.
|
|
1091
|
+
|
|
1092
|
+
EXAMPLES::
|
|
1093
|
+
|
|
1094
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
1095
|
+
sage: U = M.open_subset('U')
|
|
1096
|
+
sage: V = U.subset('V')
|
|
1097
|
+
sage: V.declare_equal(M)
|
|
1098
|
+
sage: V.equal_subset_family()
|
|
1099
|
+
Set {M, U, V} of subsets of the 2-dimensional topological manifold M
|
|
1100
|
+
"""
|
|
1101
|
+
return ManifoldSubsetFiniteFamily(self.equal_subsets())
|
|
1102
|
+
|
|
1103
|
+
def supersets(self):
|
|
1104
|
+
r"""
|
|
1105
|
+
Generate the declared supersets of the current subset.
|
|
1106
|
+
|
|
1107
|
+
.. NOTE::
|
|
1108
|
+
|
|
1109
|
+
To get the supersets as a family, sorted by name, use the method
|
|
1110
|
+
:meth:`superset_family` instead.
|
|
1111
|
+
|
|
1112
|
+
EXAMPLES::
|
|
1113
|
+
|
|
1114
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
1115
|
+
sage: U = M.open_subset('U')
|
|
1116
|
+
sage: V = M.subset('V')
|
|
1117
|
+
sage: sorted(V.supersets(), key=lambda v: v._name)
|
|
1118
|
+
[2-dimensional topological manifold M,
|
|
1119
|
+
Subset V of the 2-dimensional topological manifold M]
|
|
1120
|
+
"""
|
|
1121
|
+
yield from self._supersets
|
|
1122
|
+
|
|
1123
|
+
def superset_family(self):
|
|
1124
|
+
r"""
|
|
1125
|
+
Return the family of declared supersets of the current subset.
|
|
1126
|
+
|
|
1127
|
+
The family is sorted by the alphabetical names of the supersets.
|
|
1128
|
+
|
|
1129
|
+
OUTPUT:
|
|
1130
|
+
|
|
1131
|
+
- a :class:`ManifoldSubsetFiniteFamily` instance containing all the
|
|
1132
|
+
supersets
|
|
1133
|
+
|
|
1134
|
+
.. NOTE::
|
|
1135
|
+
|
|
1136
|
+
If you only need to iterate over the supersets in arbitrary order,
|
|
1137
|
+
you can use the generator method :meth:`supersets` instead.
|
|
1138
|
+
|
|
1139
|
+
EXAMPLES::
|
|
1140
|
+
|
|
1141
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
1142
|
+
sage: U = M.open_subset('U')
|
|
1143
|
+
sage: V = M.subset('V')
|
|
1144
|
+
sage: V.superset_family()
|
|
1145
|
+
Set {M, V} of subsets of the 2-dimensional topological manifold M
|
|
1146
|
+
"""
|
|
1147
|
+
return ManifoldSubsetFiniteFamily(self.supersets())
|
|
1148
|
+
|
|
1149
|
+
def superset_digraph(self, loops=False, quotient=False, open_covers=False, points=False, upper_bound=None):
|
|
1150
|
+
r"""
|
|
1151
|
+
Return the digraph whose arcs represent subset relations among the supersets of ``self``.
|
|
1152
|
+
|
|
1153
|
+
INPUT:
|
|
1154
|
+
|
|
1155
|
+
- ``loops`` -- boolean (default: ``False``); whether to include the trivial containment
|
|
1156
|
+
of each subset in itself as loops of the digraph
|
|
1157
|
+
- ``quotient`` -- boolean (default: ``False``); whether to contract
|
|
1158
|
+
directed cycles in the graph, replacing equivalence classes of equal
|
|
1159
|
+
subsets by a single vertex. In this case, each vertex of the digraph
|
|
1160
|
+
is a set of :class:`ManifoldSubset` instances.
|
|
1161
|
+
- ``open_covers`` -- boolean (default: ``False``); whether to include vertices for open covers
|
|
1162
|
+
- ``points`` -- boolean (default: ``False``); whether to include vertices for declared points;
|
|
1163
|
+
this can also be an iterable for the points to include
|
|
1164
|
+
- ``upper_bound`` -- (default: ``None``) only include subsets of this
|
|
1165
|
+
|
|
1166
|
+
EXAMPLES::
|
|
1167
|
+
|
|
1168
|
+
sage: M = Manifold(3, 'M')
|
|
1169
|
+
sage: U = M.open_subset('U'); V = M.open_subset('V'); W = M.open_subset('W')
|
|
1170
|
+
sage: VW = V.union(W)
|
|
1171
|
+
sage: P = V.superset_digraph(loops=False, upper_bound=VW); P # needs sage.graphs
|
|
1172
|
+
Digraph on 2 vertices
|
|
1173
|
+
"""
|
|
1174
|
+
if upper_bound is None:
|
|
1175
|
+
upper_bound = self._manifold
|
|
1176
|
+
return upper_bound.subset_digraph(loops=loops, open_covers=open_covers, points=points,
|
|
1177
|
+
quotient=quotient, lower_bound=self)
|
|
1178
|
+
|
|
1179
|
+
def superset_poset(self, open_covers=False, points=False, upper_bound=None):
|
|
1180
|
+
r"""
|
|
1181
|
+
Return the poset of the supersets of ``self``.
|
|
1182
|
+
|
|
1183
|
+
INPUT:
|
|
1184
|
+
|
|
1185
|
+
- ``open_covers`` -- boolean (default: ``False``); whether to include vertices for open covers
|
|
1186
|
+
- ``points`` -- boolean (default: ``False``); whether to include vertices for declared points;
|
|
1187
|
+
this can also be an iterable for the points to include
|
|
1188
|
+
- ``upper_bound`` -- (default: ``None``) only include subsets of this
|
|
1189
|
+
|
|
1190
|
+
EXAMPLES::
|
|
1191
|
+
|
|
1192
|
+
sage: M = Manifold(3, 'M')
|
|
1193
|
+
sage: U = M.open_subset('U'); V = M.open_subset('V'); W = M.open_subset('W')
|
|
1194
|
+
sage: VW = V.union(W)
|
|
1195
|
+
sage: P = V.superset_poset(); P # needs sage.graphs
|
|
1196
|
+
Finite poset containing 3 elements
|
|
1197
|
+
sage: P.plot(element_labels={element: element._name for element in P}) # needs sage.graphs sage.plot
|
|
1198
|
+
Graphics object consisting of 6 graphics primitives
|
|
1199
|
+
"""
|
|
1200
|
+
if upper_bound is None:
|
|
1201
|
+
upper_bound = self._manifold
|
|
1202
|
+
return upper_bound.subset_poset(open_covers=open_covers, points=points,
|
|
1203
|
+
lower_bound=self)
|
|
1204
|
+
|
|
1205
|
+
def get_subset(self, name):
|
|
1206
|
+
r"""
|
|
1207
|
+
Get a subset by its name.
|
|
1208
|
+
|
|
1209
|
+
The subset must have been previously created by the method
|
|
1210
|
+
:meth:`subset` (or
|
|
1211
|
+
:meth:`~sage.manifolds.manifold.TopologicalManifold.open_subset`)
|
|
1212
|
+
|
|
1213
|
+
INPUT:
|
|
1214
|
+
|
|
1215
|
+
- ``name`` -- string; name of the subset
|
|
1216
|
+
|
|
1217
|
+
OUTPUT:
|
|
1218
|
+
|
|
1219
|
+
- instance of :class:`~sage.manifolds.subset.ManifoldSubset` (or
|
|
1220
|
+
of the derived class
|
|
1221
|
+
:class:`~sage.manifolds.manifold.TopologicalManifold` for an open
|
|
1222
|
+
subset) representing the subset whose name is ``name``
|
|
1223
|
+
|
|
1224
|
+
EXAMPLES::
|
|
1225
|
+
|
|
1226
|
+
sage: M = Manifold(4, 'M', structure='topological')
|
|
1227
|
+
sage: A = M.subset('A')
|
|
1228
|
+
sage: B = A.subset('B')
|
|
1229
|
+
sage: U = M.open_subset('U')
|
|
1230
|
+
sage: M.subset_family()
|
|
1231
|
+
Set {A, B, M, U} of subsets of the 4-dimensional topological manifold M
|
|
1232
|
+
sage: M.get_subset('A')
|
|
1233
|
+
Subset A of the 4-dimensional topological manifold M
|
|
1234
|
+
sage: M.get_subset('A') is A
|
|
1235
|
+
True
|
|
1236
|
+
sage: M.get_subset('B') is B
|
|
1237
|
+
True
|
|
1238
|
+
sage: A.get_subset('B') is B
|
|
1239
|
+
True
|
|
1240
|
+
sage: M.get_subset('U')
|
|
1241
|
+
Open subset U of the 4-dimensional topological manifold M
|
|
1242
|
+
sage: M.get_subset('U') is U
|
|
1243
|
+
True
|
|
1244
|
+
"""
|
|
1245
|
+
for ss in self._subsets:
|
|
1246
|
+
if ss._name == name:
|
|
1247
|
+
return ss
|
|
1248
|
+
raise ValueError("no subset of name '{}' found".format(name))
|
|
1249
|
+
|
|
1250
|
+
# ### End of accessors
|
|
1251
|
+
|
|
1252
|
+
def is_subset(self, other):
|
|
1253
|
+
r"""
|
|
1254
|
+
Return ``True`` if and only if ``self`` is included in ``other``.
|
|
1255
|
+
|
|
1256
|
+
EXAMPLES:
|
|
1257
|
+
|
|
1258
|
+
Subsets on a 2-dimensional manifold::
|
|
1259
|
+
|
|
1260
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
1261
|
+
sage: a = M.subset('A')
|
|
1262
|
+
sage: b = a.subset('B')
|
|
1263
|
+
sage: c = M.subset('C')
|
|
1264
|
+
sage: a.is_subset(M)
|
|
1265
|
+
True
|
|
1266
|
+
sage: b.is_subset(a)
|
|
1267
|
+
True
|
|
1268
|
+
sage: b.is_subset(M)
|
|
1269
|
+
True
|
|
1270
|
+
sage: a.is_subset(b)
|
|
1271
|
+
False
|
|
1272
|
+
sage: c.is_subset(a)
|
|
1273
|
+
False
|
|
1274
|
+
"""
|
|
1275
|
+
return self in other._subsets
|
|
1276
|
+
|
|
1277
|
+
def declare_union(self, *subsets_or_families, disjoint=False):
|
|
1278
|
+
r"""
|
|
1279
|
+
Declare that the current subset is the union of two subsets.
|
|
1280
|
+
|
|
1281
|
+
Suppose `U` is the current subset, then this method declares
|
|
1282
|
+
that `U = \bigcup_{S\in F} S`.
|
|
1283
|
+
|
|
1284
|
+
INPUT:
|
|
1285
|
+
|
|
1286
|
+
- ``subsets_or_families`` -- finitely many subsets or iterables of subsets
|
|
1287
|
+
- ``disjoint`` -- boolean (default: ``False``); whether to declare the subsets
|
|
1288
|
+
pairwise disjoint
|
|
1289
|
+
|
|
1290
|
+
EXAMPLES::
|
|
1291
|
+
|
|
1292
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
1293
|
+
sage: AB = M.subset('AB')
|
|
1294
|
+
sage: A = AB.subset('A')
|
|
1295
|
+
sage: B = AB.subset('B')
|
|
1296
|
+
sage: def label(element):
|
|
1297
|
+
....: try:
|
|
1298
|
+
....: return element._name
|
|
1299
|
+
....: except AttributeError:
|
|
1300
|
+
....: return '[' + ', '.join(sorted(x._name for x in element)) + ']'
|
|
1301
|
+
sage: P = M.subset_poset(open_covers=True); P # needs sage.graphs
|
|
1302
|
+
Finite poset containing 4 elements
|
|
1303
|
+
sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot
|
|
1304
|
+
Graphics object consisting of 8 graphics primitives
|
|
1305
|
+
|
|
1306
|
+
sage: AB.declare_union(A, B)
|
|
1307
|
+
sage: A.union(B)
|
|
1308
|
+
Subset AB of the 2-dimensional topological manifold M
|
|
1309
|
+
sage: P = M.subset_poset(open_covers=True); P # needs sage.graphs
|
|
1310
|
+
Finite poset containing 4 elements
|
|
1311
|
+
sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot
|
|
1312
|
+
Graphics object consisting of 8 graphics primitives
|
|
1313
|
+
|
|
1314
|
+
sage: B1 = B.subset('B1', is_open=True)
|
|
1315
|
+
sage: B2 = B.subset('B2', is_open=True)
|
|
1316
|
+
sage: B.declare_union(B1, B2, disjoint=True)
|
|
1317
|
+
sage: P = M.subset_poset(open_covers=True); P # needs sage.graphs
|
|
1318
|
+
Finite poset containing 9 elements
|
|
1319
|
+
sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot
|
|
1320
|
+
Graphics object consisting of 19 graphics primitives
|
|
1321
|
+
|
|
1322
|
+
.. PLOT::
|
|
1323
|
+
|
|
1324
|
+
def label(element):
|
|
1325
|
+
try:
|
|
1326
|
+
return element._name
|
|
1327
|
+
except AttributeError:
|
|
1328
|
+
return '[' + ', '.join(sorted(x._name for x in element)) + ']'
|
|
1329
|
+
M = Manifold(2, 'M', structure='topological')
|
|
1330
|
+
AB = M.subset('AB')
|
|
1331
|
+
A = AB.subset('A')
|
|
1332
|
+
B = AB.subset('B')
|
|
1333
|
+
P = M.subset_poset(open_covers=True); P
|
|
1334
|
+
g1 = P.plot(element_labels={element: label(element) for element in P})
|
|
1335
|
+
AB.declare_union(A, B)
|
|
1336
|
+
A.union(B)
|
|
1337
|
+
P = M.subset_poset(open_covers=True); P
|
|
1338
|
+
g2 = P.plot(element_labels={element: label(element) for element in P})
|
|
1339
|
+
B1 = B.subset('B1', is_open=True)
|
|
1340
|
+
B2 = B.subset('B2', is_open=True)
|
|
1341
|
+
B.declare_union(B1, B2, disjoint=True)
|
|
1342
|
+
P = M.subset_poset(open_covers=True); P
|
|
1343
|
+
g3 = P.plot(element_labels={element: label(element) for element in P})
|
|
1344
|
+
sphinx_plot(graphics_array([g1, g2, g3]), figsize=(8, 3))
|
|
1345
|
+
"""
|
|
1346
|
+
subsets = ManifoldSubsetFiniteFamily.from_subsets_or_families(*subsets_or_families)
|
|
1347
|
+
if disjoint:
|
|
1348
|
+
for U, V in itertools.combinations(subsets, 2):
|
|
1349
|
+
U.intersection(V).declare_empty()
|
|
1350
|
+
subsets = self._reduce_union_members(subsets)
|
|
1351
|
+
if not subsets:
|
|
1352
|
+
self.declare_empty()
|
|
1353
|
+
elif len(subsets) == 1:
|
|
1354
|
+
self.declare_equal(*subsets)
|
|
1355
|
+
else:
|
|
1356
|
+
subset_iter = iter(subsets)
|
|
1357
|
+
first = next(subset_iter)
|
|
1358
|
+
second = next(subset_iter)
|
|
1359
|
+
self._declare_union_2_subsets(first, second.union(subset_iter))
|
|
1360
|
+
|
|
1361
|
+
def _declare_union_2_subsets(self, dom1, dom2):
|
|
1362
|
+
r"""
|
|
1363
|
+
Declare that the current subset is the union of two of its subsets.
|
|
1364
|
+
|
|
1365
|
+
Suppose `U` is the current subset, then this method declares that
|
|
1366
|
+
|
|
1367
|
+
.. MATH::
|
|
1368
|
+
|
|
1369
|
+
U = U_1 \cup U_2,
|
|
1370
|
+
|
|
1371
|
+
where `U_1 \subset U` and `U_2 \subset U`.
|
|
1372
|
+
|
|
1373
|
+
INPUT:
|
|
1374
|
+
|
|
1375
|
+
- ``dom1`` -- the subset `U_1`
|
|
1376
|
+
- ``dom2`` -- the subset `U_2`
|
|
1377
|
+
|
|
1378
|
+
EXAMPLES::
|
|
1379
|
+
|
|
1380
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
1381
|
+
sage: A = M.subset('A')
|
|
1382
|
+
sage: B = M.subset('B')
|
|
1383
|
+
sage: M.declare_union(A, B)
|
|
1384
|
+
sage: A.union(B)
|
|
1385
|
+
2-dimensional topological manifold M
|
|
1386
|
+
"""
|
|
1387
|
+
if dom1 == dom2:
|
|
1388
|
+
if dom1 != self:
|
|
1389
|
+
raise ValueError("the union of two identical sets must be " +
|
|
1390
|
+
"this set")
|
|
1391
|
+
return
|
|
1392
|
+
if not dom1.is_subset(self):
|
|
1393
|
+
raise TypeError("the {} is not a subset of ".format(dom1) +
|
|
1394
|
+
"the {}".format(self))
|
|
1395
|
+
if not dom2.is_subset(self):
|
|
1396
|
+
raise TypeError("the {} is not a subset of ".format(dom2) +
|
|
1397
|
+
"the {}".format(self))
|
|
1398
|
+
dom1._unions[dom2._name] = self
|
|
1399
|
+
dom2._unions[dom1._name] = self
|
|
1400
|
+
for oc1 in dom1._open_covers:
|
|
1401
|
+
for oc2 in dom2._open_covers:
|
|
1402
|
+
oc = oc1[:]
|
|
1403
|
+
for s in oc2:
|
|
1404
|
+
if s not in oc:
|
|
1405
|
+
oc.append(s)
|
|
1406
|
+
self._open_covers.append(oc)
|
|
1407
|
+
|
|
1408
|
+
def declare_equal(self, *others):
|
|
1409
|
+
r"""
|
|
1410
|
+
Declare that ``self`` and ``others`` are the same sets.
|
|
1411
|
+
|
|
1412
|
+
INPUT:
|
|
1413
|
+
|
|
1414
|
+
- ``others`` -- finitely many subsets or iterables of subsets of the same
|
|
1415
|
+
manifold as ``self``
|
|
1416
|
+
|
|
1417
|
+
EXAMPLES::
|
|
1418
|
+
|
|
1419
|
+
sage: M = Manifold(2, 'M')
|
|
1420
|
+
sage: U = M.open_subset('U')
|
|
1421
|
+
sage: V = M.open_subset('V')
|
|
1422
|
+
sage: Vs = [M.open_subset(f'V{i}') for i in range(2)]
|
|
1423
|
+
sage: UV = U.intersection(V)
|
|
1424
|
+
sage: W = UV.open_subset('W')
|
|
1425
|
+
sage: P = M.subset_poset() # needs sage.graphs
|
|
1426
|
+
sage: def label(element):
|
|
1427
|
+
....: return element._name
|
|
1428
|
+
sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot
|
|
1429
|
+
Graphics object consisting of 15 graphics primitives
|
|
1430
|
+
sage: V.declare_equal(Vs)
|
|
1431
|
+
sage: P = M.subset_poset() # needs sage.graphs
|
|
1432
|
+
sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot
|
|
1433
|
+
Graphics object consisting of 11 graphics primitives
|
|
1434
|
+
sage: W.declare_equal(U)
|
|
1435
|
+
sage: P = M.subset_poset() # needs sage.graphs
|
|
1436
|
+
sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot
|
|
1437
|
+
Graphics object consisting of 6 graphics primitives
|
|
1438
|
+
|
|
1439
|
+
.. PLOT::
|
|
1440
|
+
|
|
1441
|
+
def label(element):
|
|
1442
|
+
return element._name
|
|
1443
|
+
M = Manifold(2, 'M')
|
|
1444
|
+
U = M.open_subset('U')
|
|
1445
|
+
V = M.open_subset('V')
|
|
1446
|
+
Vs = [M.open_subset(f'V{i}') for i in range(2)]
|
|
1447
|
+
UV = U.intersection(V)
|
|
1448
|
+
W = UV.open_subset('W')
|
|
1449
|
+
P = M.subset_poset()
|
|
1450
|
+
g1 = P.plot(element_labels={element: label(element) for element in P})
|
|
1451
|
+
V.declare_equal(Vs)
|
|
1452
|
+
P = M.subset_poset()
|
|
1453
|
+
g2 = P.plot(element_labels={element: label(element) for element in P})
|
|
1454
|
+
W.declare_equal(U)
|
|
1455
|
+
P = M.subset_poset()
|
|
1456
|
+
g3 = P.plot(element_labels={element: label(element) for element in P})
|
|
1457
|
+
sphinx_plot(graphics_array([g1, g2, g3]), figsize=(8, 3))
|
|
1458
|
+
"""
|
|
1459
|
+
F = ManifoldSubsetFiniteFamily.from_subsets_or_families
|
|
1460
|
+
equal_sets = F(self, *others)
|
|
1461
|
+
all_supersets = F(*[S.supersets() for S in equal_sets])
|
|
1462
|
+
all_subsets = F(*[S.subsets() for S in equal_sets])
|
|
1463
|
+
for superset in all_supersets:
|
|
1464
|
+
superset._subsets.update(all_subsets)
|
|
1465
|
+
for subset in all_subsets:
|
|
1466
|
+
subset._supersets.update(all_supersets)
|
|
1467
|
+
|
|
1468
|
+
def declare_subset(self, *supersets):
|
|
1469
|
+
r"""
|
|
1470
|
+
Declare ``self`` to be a subset of each of the given supersets.
|
|
1471
|
+
|
|
1472
|
+
INPUT:
|
|
1473
|
+
|
|
1474
|
+
- ``supersets`` -- other subsets of the same manifold
|
|
1475
|
+
|
|
1476
|
+
EXAMPLES::
|
|
1477
|
+
|
|
1478
|
+
sage: M = Manifold(2, 'M')
|
|
1479
|
+
sage: U1 = M.open_subset('U1')
|
|
1480
|
+
sage: U2 = M.open_subset('U2')
|
|
1481
|
+
sage: V = M.open_subset('V')
|
|
1482
|
+
sage: V.superset_family()
|
|
1483
|
+
Set {M, V} of open subsets of the 2-dimensional differentiable manifold M
|
|
1484
|
+
sage: U1.subset_family()
|
|
1485
|
+
Set {U1} of open subsets of the 2-dimensional differentiable manifold M
|
|
1486
|
+
sage: P = M.subset_poset() # needs sage.graphs
|
|
1487
|
+
sage: def label(element):
|
|
1488
|
+
....: return element._name
|
|
1489
|
+
sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot
|
|
1490
|
+
Graphics object consisting of 8 graphics primitives
|
|
1491
|
+
sage: V.declare_subset(U1, U2)
|
|
1492
|
+
sage: V.superset_family()
|
|
1493
|
+
Set {M, U1, U2, V} of open subsets of the 2-dimensional differentiable manifold M
|
|
1494
|
+
sage: P = M.subset_poset() # needs sage.graphs
|
|
1495
|
+
sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot
|
|
1496
|
+
Graphics object consisting of 9 graphics primitives
|
|
1497
|
+
|
|
1498
|
+
Subsets in a directed cycle of inclusions are equal::
|
|
1499
|
+
|
|
1500
|
+
sage: M.declare_subset(V)
|
|
1501
|
+
sage: M.superset_family()
|
|
1502
|
+
Set {M, U1, U2, V} of open subsets of the 2-dimensional differentiable manifold M
|
|
1503
|
+
sage: M.equal_subset_family()
|
|
1504
|
+
Set {M, U1, U2, V} of open subsets of the 2-dimensional differentiable manifold M
|
|
1505
|
+
sage: P = M.subset_poset() # needs sage.graphs
|
|
1506
|
+
sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot
|
|
1507
|
+
Graphics object consisting of 2 graphics primitives
|
|
1508
|
+
|
|
1509
|
+
.. PLOT::
|
|
1510
|
+
|
|
1511
|
+
def label(element):
|
|
1512
|
+
return element._name
|
|
1513
|
+
M = Manifold(2, 'M')
|
|
1514
|
+
U1 = M.open_subset('U1')
|
|
1515
|
+
U2 = M.open_subset('U2')
|
|
1516
|
+
V = M.open_subset('V')
|
|
1517
|
+
P = M.subset_poset()
|
|
1518
|
+
g1 = P.plot(element_labels={element: label(element) for element in P})
|
|
1519
|
+
V.declare_subset(U1, U2)
|
|
1520
|
+
P = M.subset_poset()
|
|
1521
|
+
g2 = P.plot(element_labels={element: label(element) for element in P})
|
|
1522
|
+
M.declare_subset(V)
|
|
1523
|
+
P = M.subset_poset()
|
|
1524
|
+
g3 = P.plot(element_labels={element: label(element) for element in P})
|
|
1525
|
+
sphinx_plot(graphics_array([g1, g2, g3]), figsize=(8, 3))
|
|
1526
|
+
"""
|
|
1527
|
+
F = ManifoldSubsetFiniteFamily.from_subsets_or_families
|
|
1528
|
+
supersets = F(*supersets)
|
|
1529
|
+
all_supersets = F(*[S.supersets() for S in supersets])
|
|
1530
|
+
for superset in all_supersets:
|
|
1531
|
+
superset._subsets.update(self._subsets)
|
|
1532
|
+
for subset in self._subsets:
|
|
1533
|
+
subset._supersets.update(all_supersets)
|
|
1534
|
+
|
|
1535
|
+
def declare_superset(self, *subsets):
|
|
1536
|
+
r"""
|
|
1537
|
+
Declare ``self`` to be a superset of each of the given subsets.
|
|
1538
|
+
|
|
1539
|
+
INPUT:
|
|
1540
|
+
|
|
1541
|
+
- ``subsets`` -- other subsets of the same manifold
|
|
1542
|
+
|
|
1543
|
+
EXAMPLES::
|
|
1544
|
+
|
|
1545
|
+
sage: M = Manifold(2, 'M')
|
|
1546
|
+
sage: U = M.open_subset('U')
|
|
1547
|
+
sage: V1 = M.open_subset('V1')
|
|
1548
|
+
sage: V2 = M.open_subset('V2')
|
|
1549
|
+
sage: W = V1.intersection(V2)
|
|
1550
|
+
sage: U.subset_family()
|
|
1551
|
+
Set {U} of open subsets of the 2-dimensional differentiable manifold M
|
|
1552
|
+
sage: P = M.subset_poset() # needs sage.graphs
|
|
1553
|
+
sage: def label(element):
|
|
1554
|
+
....: return element._name
|
|
1555
|
+
sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot
|
|
1556
|
+
Graphics object consisting of 11 graphics primitives
|
|
1557
|
+
sage: U.declare_superset(V1, V2)
|
|
1558
|
+
sage: U.subset_family()
|
|
1559
|
+
Set {U, V1, V1_inter_V2, V2} of open subsets of the 2-dimensional differentiable manifold M
|
|
1560
|
+
sage: P = M.subset_poset() # needs sage.graphs
|
|
1561
|
+
sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot
|
|
1562
|
+
Graphics object consisting of 11 graphics primitives
|
|
1563
|
+
|
|
1564
|
+
Subsets in a directed cycle of inclusions are equal::
|
|
1565
|
+
|
|
1566
|
+
sage: W.declare_superset(U)
|
|
1567
|
+
sage: W.subset_family()
|
|
1568
|
+
Set {U, V1, V1_inter_V2, V2} of open subsets of the 2-dimensional differentiable manifold M
|
|
1569
|
+
sage: W.equal_subset_family()
|
|
1570
|
+
Set {U, V1, V1_inter_V2, V2} of open subsets of the 2-dimensional differentiable manifold M
|
|
1571
|
+
sage: P = M.subset_poset() # needs sage.graphs
|
|
1572
|
+
sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot
|
|
1573
|
+
Graphics object consisting of 4 graphics primitives
|
|
1574
|
+
|
|
1575
|
+
.. PLOT::
|
|
1576
|
+
|
|
1577
|
+
def label(element):
|
|
1578
|
+
return element._name
|
|
1579
|
+
M = Manifold(2, 'M')
|
|
1580
|
+
U = M.open_subset('U')
|
|
1581
|
+
V1 = M.open_subset('V1')
|
|
1582
|
+
V2 = M.open_subset('V2')
|
|
1583
|
+
W = V1.intersection(V2)
|
|
1584
|
+
P = M.subset_poset()
|
|
1585
|
+
def label(element):
|
|
1586
|
+
return element._name
|
|
1587
|
+
g1 = P.plot(element_labels={element: label(element) for element in P})
|
|
1588
|
+
U.declare_superset(V1, V2)
|
|
1589
|
+
P = M.subset_poset()
|
|
1590
|
+
g2 = P.plot(element_labels={element: label(element) for element in P})
|
|
1591
|
+
W.declare_superset(U)
|
|
1592
|
+
P = M.subset_poset()
|
|
1593
|
+
g3 = P.plot(element_labels={element: label(element) for element in P})
|
|
1594
|
+
sphinx_plot(graphics_array([g1, g2, g3]), figsize=(8, 3))
|
|
1595
|
+
"""
|
|
1596
|
+
F = ManifoldSubsetFiniteFamily.from_subsets_or_families
|
|
1597
|
+
subsets = F(*subsets)
|
|
1598
|
+
all_subsets = F(*[S.subsets() for S in subsets])
|
|
1599
|
+
for subset in all_subsets:
|
|
1600
|
+
subset._supersets.update(self._supersets)
|
|
1601
|
+
for superset in self._supersets:
|
|
1602
|
+
superset._subsets.update(all_subsets)
|
|
1603
|
+
|
|
1604
|
+
def declare_empty(self):
|
|
1605
|
+
r"""
|
|
1606
|
+
Declare that ``self`` is the empty set.
|
|
1607
|
+
|
|
1608
|
+
EXAMPLES::
|
|
1609
|
+
|
|
1610
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
1611
|
+
sage: A = M.subset('A', is_open=True)
|
|
1612
|
+
sage: AA = A.subset('AA')
|
|
1613
|
+
sage: A
|
|
1614
|
+
Open subset A of the 2-dimensional topological manifold M
|
|
1615
|
+
sage: A.declare_empty()
|
|
1616
|
+
sage: A.is_empty()
|
|
1617
|
+
True
|
|
1618
|
+
|
|
1619
|
+
Empty sets do not allow to define points on them::
|
|
1620
|
+
|
|
1621
|
+
sage: A.point()
|
|
1622
|
+
Traceback (most recent call last):
|
|
1623
|
+
...
|
|
1624
|
+
TypeError: cannot define a point on the
|
|
1625
|
+
Open subset A of the 2-dimensional topological manifold M
|
|
1626
|
+
because it has been declared empty
|
|
1627
|
+
|
|
1628
|
+
Emptiness transfers to subsets::
|
|
1629
|
+
|
|
1630
|
+
sage: AA.is_empty()
|
|
1631
|
+
True
|
|
1632
|
+
sage: AA.point()
|
|
1633
|
+
Traceback (most recent call last):
|
|
1634
|
+
...
|
|
1635
|
+
TypeError: cannot define a point on the
|
|
1636
|
+
Subset AA of the 2-dimensional topological manifold M
|
|
1637
|
+
because it has been declared empty
|
|
1638
|
+
sage: AD = A.subset('AD')
|
|
1639
|
+
sage: AD.is_empty()
|
|
1640
|
+
True
|
|
1641
|
+
|
|
1642
|
+
If points have already been defined on ``self`` (or its subsets),
|
|
1643
|
+
it is an error to declare it to be empty::
|
|
1644
|
+
|
|
1645
|
+
sage: B = M.subset('B')
|
|
1646
|
+
sage: b = B.point(name='b'); b
|
|
1647
|
+
Point b on the 2-dimensional topological manifold M
|
|
1648
|
+
sage: B.declare_empty()
|
|
1649
|
+
Traceback (most recent call last):
|
|
1650
|
+
...
|
|
1651
|
+
TypeError: cannot be empty because it has defined points
|
|
1652
|
+
|
|
1653
|
+
Emptiness is recorded as empty open covers::
|
|
1654
|
+
|
|
1655
|
+
sage: P = M.subset_poset(open_covers=True, points=[b]) # needs sage.graphs
|
|
1656
|
+
sage: def label(element):
|
|
1657
|
+
....: if isinstance(element, str):
|
|
1658
|
+
....: return element
|
|
1659
|
+
....: try:
|
|
1660
|
+
....: return element._name
|
|
1661
|
+
....: except AttributeError:
|
|
1662
|
+
....: return '[' + ', '.join(sorted(x._name for x in element)) + ']'
|
|
1663
|
+
sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot
|
|
1664
|
+
Graphics object consisting of 10 graphics primitives
|
|
1665
|
+
|
|
1666
|
+
.. PLOT::
|
|
1667
|
+
|
|
1668
|
+
def label(element):
|
|
1669
|
+
if isinstance(element, str):
|
|
1670
|
+
return element
|
|
1671
|
+
try:
|
|
1672
|
+
return element._name
|
|
1673
|
+
except AttributeError:
|
|
1674
|
+
return '[' + ', '.join(sorted(x._name for x in element)) + ']'
|
|
1675
|
+
M = Manifold(2, 'M', structure='topological')
|
|
1676
|
+
A = M.subset('A', is_open=True)
|
|
1677
|
+
AA = A.subset('AA')
|
|
1678
|
+
A.declare_empty()
|
|
1679
|
+
AD = A.subset('AD')
|
|
1680
|
+
B = M.subset('B')
|
|
1681
|
+
b = B.point(name='b')
|
|
1682
|
+
|
|
1683
|
+
D = M.subset_digraph(open_covers=True, points=[b])
|
|
1684
|
+
g1 = D.relabel(label, inplace=False).plot(layout='spring')
|
|
1685
|
+
P = M.subset_poset(open_covers=True, points=[b])
|
|
1686
|
+
g2 = P.plot(element_labels={element: label(element) for element in P})
|
|
1687
|
+
sphinx_plot(graphics_array([g1, g2]), figsize=(8, 5))
|
|
1688
|
+
"""
|
|
1689
|
+
if self.has_defined_points():
|
|
1690
|
+
raise TypeError('cannot be empty because it has defined points')
|
|
1691
|
+
if not self.is_empty():
|
|
1692
|
+
self._open_covers.append([])
|
|
1693
|
+
self.declare_equal(self.subsets())
|
|
1694
|
+
|
|
1695
|
+
def is_empty(self):
|
|
1696
|
+
r"""
|
|
1697
|
+
Return whether the current subset is empty.
|
|
1698
|
+
|
|
1699
|
+
By default, manifold subsets are considered nonempty: The method :meth:`point` can be
|
|
1700
|
+
used to define points on it, either with or without coordinates some chart.
|
|
1701
|
+
|
|
1702
|
+
However, using :meth:`declare_empty`, a subset can be declared empty, and emptiness
|
|
1703
|
+
transfers to all of its subsets.
|
|
1704
|
+
|
|
1705
|
+
EXAMPLES::
|
|
1706
|
+
|
|
1707
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
1708
|
+
sage: A = M.subset('A', is_open=True)
|
|
1709
|
+
sage: AA = A.subset('AA')
|
|
1710
|
+
sage: A.is_empty()
|
|
1711
|
+
False
|
|
1712
|
+
sage: A.declare_empty()
|
|
1713
|
+
sage: A.is_empty()
|
|
1714
|
+
True
|
|
1715
|
+
sage: AA.is_empty()
|
|
1716
|
+
True
|
|
1717
|
+
"""
|
|
1718
|
+
if self.has_defined_points(subsets=False):
|
|
1719
|
+
# Fast path, do not check subsets
|
|
1720
|
+
return False
|
|
1721
|
+
return any(not cover
|
|
1722
|
+
for cover in self.open_covers(trivial=False, supersets=True))
|
|
1723
|
+
|
|
1724
|
+
def declare_nonempty(self):
|
|
1725
|
+
r"""
|
|
1726
|
+
Declare that ``self`` is nonempty.
|
|
1727
|
+
|
|
1728
|
+
Once declared nonempty, ``self`` (or any of its supersets) cannot be declared empty.
|
|
1729
|
+
|
|
1730
|
+
This is equivalent to defining a point on ``self`` using :meth:`point`
|
|
1731
|
+
but is cheaper than actually creating a :class:`~sage.manifolds.point.ManifoldPoint`
|
|
1732
|
+
instance.
|
|
1733
|
+
|
|
1734
|
+
EXAMPLES::
|
|
1735
|
+
|
|
1736
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
1737
|
+
sage: A = M.subset('A', is_open=True)
|
|
1738
|
+
sage: AA = A.subset('AA')
|
|
1739
|
+
sage: AA.declare_nonempty()
|
|
1740
|
+
sage: A.has_defined_points()
|
|
1741
|
+
True
|
|
1742
|
+
sage: A.declare_empty()
|
|
1743
|
+
Traceback (most recent call last):
|
|
1744
|
+
...
|
|
1745
|
+
TypeError: cannot be empty because it has defined points
|
|
1746
|
+
"""
|
|
1747
|
+
if self.has_defined_points(subsets=False):
|
|
1748
|
+
# Fast path, do not check subsets
|
|
1749
|
+
return
|
|
1750
|
+
if self.is_empty():
|
|
1751
|
+
raise TypeError('cannot be nonempty because it has already been declared empty')
|
|
1752
|
+
self._has_defined_points = True
|
|
1753
|
+
|
|
1754
|
+
def has_defined_points(self, subsets=True) -> bool:
|
|
1755
|
+
r"""
|
|
1756
|
+
Return whether any points have been defined on ``self`` or any of its subsets.
|
|
1757
|
+
|
|
1758
|
+
INPUT:
|
|
1759
|
+
|
|
1760
|
+
- ``subsets`` -- boolean (default: ``True``); if ``False``, only consider points that have
|
|
1761
|
+
been defined directly on ``self``. If ``True``, also consider points on all subsets.
|
|
1762
|
+
|
|
1763
|
+
EXAMPLES::
|
|
1764
|
+
|
|
1765
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
1766
|
+
sage: A = M.subset('A', is_open=True)
|
|
1767
|
+
sage: AA = A.subset('AA')
|
|
1768
|
+
sage: AA.point()
|
|
1769
|
+
Point on the 2-dimensional topological manifold M
|
|
1770
|
+
sage: AA.has_defined_points()
|
|
1771
|
+
True
|
|
1772
|
+
sage: A.has_defined_points(subsets=False)
|
|
1773
|
+
False
|
|
1774
|
+
sage: A.has_defined_points()
|
|
1775
|
+
True
|
|
1776
|
+
"""
|
|
1777
|
+
if subsets:
|
|
1778
|
+
return any(subset._has_defined_points for subset in self.subsets())
|
|
1779
|
+
else:
|
|
1780
|
+
return self._has_defined_points
|
|
1781
|
+
|
|
1782
|
+
def point(self, coords=None, chart=None, name=None, latex_name=None):
|
|
1783
|
+
r"""
|
|
1784
|
+
Define a point in ``self``.
|
|
1785
|
+
|
|
1786
|
+
See :class:`~sage.manifolds.point.ManifoldPoint` for a
|
|
1787
|
+
complete documentation.
|
|
1788
|
+
|
|
1789
|
+
INPUT:
|
|
1790
|
+
|
|
1791
|
+
- ``coords`` -- the point coordinates (as a tuple or a list) in the
|
|
1792
|
+
chart specified by ``chart``
|
|
1793
|
+
- ``chart`` -- (default: ``None``) chart in which the point
|
|
1794
|
+
coordinates are given; if ``None``, the coordinates are assumed
|
|
1795
|
+
to refer to the default chart of the current subset
|
|
1796
|
+
- ``name`` -- (default: ``None``) name given to the point
|
|
1797
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
1798
|
+
point; if ``None``, the LaTeX symbol is set to ``name``
|
|
1799
|
+
|
|
1800
|
+
OUTPUT:
|
|
1801
|
+
|
|
1802
|
+
- the declared point, as an instance of
|
|
1803
|
+
:class:`~sage.manifolds.point.ManifoldPoint`
|
|
1804
|
+
|
|
1805
|
+
EXAMPLES:
|
|
1806
|
+
|
|
1807
|
+
Points on a 2-dimensional manifold::
|
|
1808
|
+
|
|
1809
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
1810
|
+
sage: c_xy.<x,y> = M.chart()
|
|
1811
|
+
sage: p = M.point((1,2), name='p'); p
|
|
1812
|
+
Point p on the 2-dimensional topological manifold M
|
|
1813
|
+
sage: p in M
|
|
1814
|
+
True
|
|
1815
|
+
sage: a = M.open_subset('A')
|
|
1816
|
+
sage: c_uv.<u,v> = a.chart()
|
|
1817
|
+
sage: q = a.point((-1,0), name='q'); q
|
|
1818
|
+
Point q on the 2-dimensional topological manifold M
|
|
1819
|
+
sage: q in a
|
|
1820
|
+
True
|
|
1821
|
+
sage: p._coordinates
|
|
1822
|
+
{Chart (M, (x, y)): (1, 2)}
|
|
1823
|
+
sage: q._coordinates
|
|
1824
|
+
{Chart (A, (u, v)): (-1, 0)}
|
|
1825
|
+
"""
|
|
1826
|
+
return self.element_class(self, coords=coords, chart=chart,
|
|
1827
|
+
name=name, latex_name=latex_name)
|
|
1828
|
+
|
|
1829
|
+
def declare_closed(self):
|
|
1830
|
+
r"""
|
|
1831
|
+
Declare ``self`` to be a closed subset of the manifold.
|
|
1832
|
+
|
|
1833
|
+
EXAMPLES::
|
|
1834
|
+
|
|
1835
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
1836
|
+
sage: A = M.subset('A')
|
|
1837
|
+
sage: B1 = A.subset('B1')
|
|
1838
|
+
sage: B1.is_closed()
|
|
1839
|
+
False
|
|
1840
|
+
sage: B1.declare_closed()
|
|
1841
|
+
sage: B1.is_closed()
|
|
1842
|
+
True
|
|
1843
|
+
|
|
1844
|
+
sage: B2 = A.subset('B2')
|
|
1845
|
+
sage: cl_B2 = B2.closure()
|
|
1846
|
+
sage: A.declare_closed()
|
|
1847
|
+
sage: cl_B2.is_subset(A)
|
|
1848
|
+
True
|
|
1849
|
+
"""
|
|
1850
|
+
if self.is_closed():
|
|
1851
|
+
return
|
|
1852
|
+
self.complement(is_open=True)
|
|
1853
|
+
from sage.manifolds.subsets.closure import ManifoldSubsetClosure
|
|
1854
|
+
for closure in self.manifold().subsets():
|
|
1855
|
+
if isinstance(closure, ManifoldSubsetClosure):
|
|
1856
|
+
if closure._subset.is_subset(self):
|
|
1857
|
+
closure.declare_subset(self)
|
|
1858
|
+
|
|
1859
|
+
# ### Construction of new sets from self:
|
|
1860
|
+
|
|
1861
|
+
def subset(self, name, latex_name=None, is_open=False):
|
|
1862
|
+
r"""
|
|
1863
|
+
Create a subset of the current subset.
|
|
1864
|
+
|
|
1865
|
+
INPUT:
|
|
1866
|
+
|
|
1867
|
+
- ``name`` -- name given to the subset
|
|
1868
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote
|
|
1869
|
+
the subset; if none are provided, it is set to ``name``
|
|
1870
|
+
- ``is_open`` -- boolean (default: ``False``); if ``True``, the created subset
|
|
1871
|
+
is assumed to be open with respect to the manifold's topology
|
|
1872
|
+
|
|
1873
|
+
OUTPUT:
|
|
1874
|
+
|
|
1875
|
+
- the subset, as an instance of :class:`ManifoldSubset`, or
|
|
1876
|
+
of the derived class
|
|
1877
|
+
:class:`~sage.manifolds.manifold.TopologicalManifold`
|
|
1878
|
+
if ``is_open`` is ``True``
|
|
1879
|
+
|
|
1880
|
+
EXAMPLES:
|
|
1881
|
+
|
|
1882
|
+
Creating a subset of a manifold::
|
|
1883
|
+
|
|
1884
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
1885
|
+
sage: a = M.subset('A'); a
|
|
1886
|
+
Subset A of the 2-dimensional topological manifold M
|
|
1887
|
+
|
|
1888
|
+
Creating a subset of ``A``::
|
|
1889
|
+
|
|
1890
|
+
sage: b = a.subset('B', latex_name=r'\mathcal{B}'); b
|
|
1891
|
+
Subset B of the 2-dimensional topological manifold M
|
|
1892
|
+
sage: latex(b)
|
|
1893
|
+
\mathcal{B}
|
|
1894
|
+
|
|
1895
|
+
We have then::
|
|
1896
|
+
|
|
1897
|
+
sage: b.is_subset(a)
|
|
1898
|
+
True
|
|
1899
|
+
sage: b in a.subsets()
|
|
1900
|
+
True
|
|
1901
|
+
"""
|
|
1902
|
+
if is_open:
|
|
1903
|
+
return self.open_subset(name, latex_name=latex_name)
|
|
1904
|
+
res = ManifoldSubset(self._manifold, name, latex_name=latex_name)
|
|
1905
|
+
if self.is_empty():
|
|
1906
|
+
self.declare_equal(res)
|
|
1907
|
+
else:
|
|
1908
|
+
self.declare_superset(res)
|
|
1909
|
+
self._top_subsets.add(res)
|
|
1910
|
+
return res
|
|
1911
|
+
|
|
1912
|
+
def open_subset(self, name, latex_name=None, coord_def={}, supersets=None):
|
|
1913
|
+
r"""
|
|
1914
|
+
Create an open subset of the manifold that is a subset of ``self``.
|
|
1915
|
+
|
|
1916
|
+
An open subset is a set that is (i) included in the manifold and (ii)
|
|
1917
|
+
open with respect to the manifold's topology. It is a topological
|
|
1918
|
+
manifold by itself. Hence the returned object is an instance of
|
|
1919
|
+
:class:`~sage.manifolds.manifold.TopologicalManifold`.
|
|
1920
|
+
|
|
1921
|
+
INPUT:
|
|
1922
|
+
|
|
1923
|
+
- ``name`` -- name given to the open subset
|
|
1924
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote
|
|
1925
|
+
the subset; if none are provided, it is set to ``name``
|
|
1926
|
+
- ``coord_def`` -- (default: {}) definition of the subset in
|
|
1927
|
+
terms of coordinates; ``coord_def`` must a be dictionary with keys
|
|
1928
|
+
charts on the manifold and values the symbolic expressions formed
|
|
1929
|
+
by the coordinates to define the subset
|
|
1930
|
+
- ``supersets`` -- (default: only ``self``) list of sets that the
|
|
1931
|
+
new open subset is a subset of
|
|
1932
|
+
|
|
1933
|
+
OUTPUT:
|
|
1934
|
+
|
|
1935
|
+
- the open subset, as an instance of
|
|
1936
|
+
:class:`~sage.manifolds.manifold.TopologicalManifold`
|
|
1937
|
+
or one of its subclasses
|
|
1938
|
+
|
|
1939
|
+
EXAMPLES::
|
|
1940
|
+
|
|
1941
|
+
sage: M = Manifold(2, 'R^2', structure='topological')
|
|
1942
|
+
sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
|
|
1943
|
+
sage: cl_D = M.subset('cl_D'); cl_D
|
|
1944
|
+
Subset cl_D of the 2-dimensional topological manifold R^2
|
|
1945
|
+
sage: D = cl_D.open_subset('D', coord_def={c_cart: x^2+y^2<1}); D
|
|
1946
|
+
Open subset D of the 2-dimensional topological manifold R^2
|
|
1947
|
+
sage: D.is_subset(cl_D)
|
|
1948
|
+
True
|
|
1949
|
+
sage: D.is_subset(M)
|
|
1950
|
+
True
|
|
1951
|
+
|
|
1952
|
+
sage: M = Manifold(2, 'R^2', structure='differentiable')
|
|
1953
|
+
sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
|
|
1954
|
+
sage: cl_D = M.subset('cl_D'); cl_D
|
|
1955
|
+
Subset cl_D of the 2-dimensional differentiable manifold R^2
|
|
1956
|
+
sage: D = cl_D.open_subset('D', coord_def={c_cart: x^2+y^2<1}); D
|
|
1957
|
+
Open subset D of the 2-dimensional differentiable manifold R^2
|
|
1958
|
+
sage: D.is_subset(cl_D)
|
|
1959
|
+
True
|
|
1960
|
+
sage: D.is_subset(M)
|
|
1961
|
+
True
|
|
1962
|
+
|
|
1963
|
+
sage: M = Manifold(2, 'R^2', structure='Riemannian')
|
|
1964
|
+
sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
|
|
1965
|
+
sage: cl_D = M.subset('cl_D'); cl_D
|
|
1966
|
+
Subset cl_D of the 2-dimensional Riemannian manifold R^2
|
|
1967
|
+
sage: D = cl_D.open_subset('D', coord_def={c_cart: x^2+y^2<1}); D
|
|
1968
|
+
Open subset D of the 2-dimensional Riemannian manifold R^2
|
|
1969
|
+
sage: D.is_subset(cl_D)
|
|
1970
|
+
True
|
|
1971
|
+
sage: D.is_subset(M)
|
|
1972
|
+
True
|
|
1973
|
+
"""
|
|
1974
|
+
if supersets is None:
|
|
1975
|
+
supersets = set()
|
|
1976
|
+
else:
|
|
1977
|
+
supersets = set(supersets)
|
|
1978
|
+
supersets.update([self])
|
|
1979
|
+
# Delegate to the manifold's method.
|
|
1980
|
+
return self._manifold.open_subset(name, latex_name=latex_name,
|
|
1981
|
+
coord_def=coord_def,
|
|
1982
|
+
supersets=supersets)
|
|
1983
|
+
|
|
1984
|
+
def _init_open_subset(self, resu, coord_def):
|
|
1985
|
+
r"""
|
|
1986
|
+
Initialize ``resu`` as an open subset of ``self``.
|
|
1987
|
+
|
|
1988
|
+
INPUT:
|
|
1989
|
+
|
|
1990
|
+
- ``resu`` -- an instance of :class:`TopologicalManifold` or
|
|
1991
|
+
a subclass
|
|
1992
|
+
|
|
1993
|
+
- ``coord_def`` -- (default: {}) definition of the subset in
|
|
1994
|
+
terms of coordinates; ``coord_def`` must a be dictionary with keys
|
|
1995
|
+
charts on the manifold and values the symbolic expressions formed
|
|
1996
|
+
by the coordinates to define the subset
|
|
1997
|
+
|
|
1998
|
+
EXAMPLES::
|
|
1999
|
+
|
|
2000
|
+
sage: M = Manifold(2, 'R^2', structure='topological')
|
|
2001
|
+
sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
|
|
2002
|
+
sage: cl_D = M.subset('cl_D')
|
|
2003
|
+
sage: coord_def = {c_cart: x^2+y^2<1}
|
|
2004
|
+
sage: D = M.open_subset('D', coord_def=coord_def)
|
|
2005
|
+
sage: D.is_subset(cl_D)
|
|
2006
|
+
False
|
|
2007
|
+
sage: cl_D._init_open_subset(D, coord_def)
|
|
2008
|
+
sage: D.is_subset(cl_D)
|
|
2009
|
+
True
|
|
2010
|
+
"""
|
|
2011
|
+
resu._supersets.update(self._supersets)
|
|
2012
|
+
self._subsets.add(resu)
|
|
2013
|
+
# Recursively delegate to the supersets.
|
|
2014
|
+
for superset in self._supersets:
|
|
2015
|
+
if superset is not self:
|
|
2016
|
+
superset._init_open_subset(resu, coord_def=coord_def)
|
|
2017
|
+
|
|
2018
|
+
def superset(self, name, latex_name=None, is_open=False):
|
|
2019
|
+
r"""
|
|
2020
|
+
Create a superset of the current subset.
|
|
2021
|
+
|
|
2022
|
+
A *superset* is a manifold subset in which the current subset is
|
|
2023
|
+
included.
|
|
2024
|
+
|
|
2025
|
+
INPUT:
|
|
2026
|
+
|
|
2027
|
+
- ``name`` -- name given to the superset
|
|
2028
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote
|
|
2029
|
+
the superset; if none are provided, it is set to ``name``
|
|
2030
|
+
- ``is_open`` -- boolean (default: ``False``); if ``True``, the created
|
|
2031
|
+
subset is assumed to be open with respect to the manifold's topology
|
|
2032
|
+
|
|
2033
|
+
OUTPUT:
|
|
2034
|
+
|
|
2035
|
+
- the superset, as an instance of :class:`ManifoldSubset` or
|
|
2036
|
+
of the derived class
|
|
2037
|
+
:class:`~sage.manifolds.manifold.TopologicalManifold`
|
|
2038
|
+
if ``is_open`` is ``True``
|
|
2039
|
+
|
|
2040
|
+
EXAMPLES:
|
|
2041
|
+
|
|
2042
|
+
Creating some superset of a given subset::
|
|
2043
|
+
|
|
2044
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
2045
|
+
sage: a = M.subset('A')
|
|
2046
|
+
sage: b = a.superset('B'); b
|
|
2047
|
+
Subset B of the 2-dimensional topological manifold M
|
|
2048
|
+
sage: b.subset_family()
|
|
2049
|
+
Set {A, B} of subsets of the 2-dimensional topological manifold M
|
|
2050
|
+
sage: a.superset_family()
|
|
2051
|
+
Set {A, B, M} of subsets of the 2-dimensional topological manifold M
|
|
2052
|
+
|
|
2053
|
+
The superset of the whole manifold is itself::
|
|
2054
|
+
|
|
2055
|
+
sage: M.superset('SM') is M
|
|
2056
|
+
True
|
|
2057
|
+
|
|
2058
|
+
Two supersets of a given subset are a priori different::
|
|
2059
|
+
|
|
2060
|
+
sage: c = a.superset('C')
|
|
2061
|
+
sage: c == b
|
|
2062
|
+
False
|
|
2063
|
+
"""
|
|
2064
|
+
if self is self._manifold:
|
|
2065
|
+
return self
|
|
2066
|
+
if is_open:
|
|
2067
|
+
res = self._manifold.open_subset(name, latex_name=latex_name)
|
|
2068
|
+
else:
|
|
2069
|
+
res = ManifoldSubset(self._manifold, name, latex_name=latex_name)
|
|
2070
|
+
res.declare_superset(self)
|
|
2071
|
+
if is_open and self._is_open:
|
|
2072
|
+
res._atlas = list(self._atlas)
|
|
2073
|
+
res._top_charts = list(self._top_charts)
|
|
2074
|
+
res._coord_changes = dict(self._coord_changes)
|
|
2075
|
+
res._def_chart = self._def_chart
|
|
2076
|
+
return res
|
|
2077
|
+
|
|
2078
|
+
def intersection(self, *others: ManifoldSubset, name: Optional[str] = None, latex_name: Optional[str] = None) -> ManifoldSubset:
|
|
2079
|
+
r"""
|
|
2080
|
+
Return the intersection of the current subset with other subsets.
|
|
2081
|
+
|
|
2082
|
+
This method may return a previously constructed intersection instead
|
|
2083
|
+
of creating a new subset. In this case, ``name`` and ``latex_name``
|
|
2084
|
+
are not used.
|
|
2085
|
+
|
|
2086
|
+
INPUT:
|
|
2087
|
+
|
|
2088
|
+
- ``others`` -- other subsets of the same manifold
|
|
2089
|
+
- ``name`` -- (default: ``None``) name given to the intersection
|
|
2090
|
+
in the case the latter has to be created; the default is
|
|
2091
|
+
``self._name`` inter ``other._name``
|
|
2092
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
2093
|
+
intersection in the case the latter has to be created; the default
|
|
2094
|
+
is built upon the symbol `\cap`
|
|
2095
|
+
|
|
2096
|
+
OUTPUT:
|
|
2097
|
+
|
|
2098
|
+
- instance of :class:`ManifoldSubset` representing the
|
|
2099
|
+
subset that is the intersection of the current subset with ``others``
|
|
2100
|
+
|
|
2101
|
+
EXAMPLES:
|
|
2102
|
+
|
|
2103
|
+
Intersection of two subsets::
|
|
2104
|
+
|
|
2105
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
2106
|
+
sage: a = M.subset('A')
|
|
2107
|
+
sage: b = M.subset('B')
|
|
2108
|
+
sage: c = a.intersection(b); c
|
|
2109
|
+
Subset A_inter_B of the 2-dimensional topological manifold M
|
|
2110
|
+
sage: a.subset_family()
|
|
2111
|
+
Set {A, A_inter_B} of subsets of the 2-dimensional topological manifold M
|
|
2112
|
+
sage: b.subset_family()
|
|
2113
|
+
Set {A_inter_B, B} of subsets of the 2-dimensional topological manifold M
|
|
2114
|
+
sage: c.superset_family()
|
|
2115
|
+
Set {A, A_inter_B, B, M} of subsets of the 2-dimensional topological manifold M
|
|
2116
|
+
|
|
2117
|
+
Intersection of six subsets::
|
|
2118
|
+
|
|
2119
|
+
sage: T = Manifold(2, 'T', structure='topological')
|
|
2120
|
+
sage: S = [T.subset(f'S{i}') for i in range(6)]
|
|
2121
|
+
sage: [S[i].intersection(S[i+3]) for i in range(3)]
|
|
2122
|
+
[Subset S0_inter_S3 of the 2-dimensional topological manifold T,
|
|
2123
|
+
Subset S1_inter_S4 of the 2-dimensional topological manifold T,
|
|
2124
|
+
Subset S2_inter_S5 of the 2-dimensional topological manifold T]
|
|
2125
|
+
sage: inter_S_i = T.intersection(*S, name='inter_S_i'); inter_S_i
|
|
2126
|
+
Subset inter_S_i of the 2-dimensional topological manifold T
|
|
2127
|
+
sage: inter_S_i.superset_family()
|
|
2128
|
+
Set {S0, S0_inter_S3, S0_inter_S3_inter_S1_inter_S4, S1, S1_inter_S4,
|
|
2129
|
+
S2, S2_inter_S5, S3, S4, S5, T, inter_S_i} of
|
|
2130
|
+
subsets of the 2-dimensional topological manifold T
|
|
2131
|
+
|
|
2132
|
+
.. PLOT::
|
|
2133
|
+
|
|
2134
|
+
def label(element):
|
|
2135
|
+
if isinstance(element, str):
|
|
2136
|
+
return element
|
|
2137
|
+
try:
|
|
2138
|
+
return element._name.replace('_inter_', '∩')
|
|
2139
|
+
except AttributeError:
|
|
2140
|
+
return '[' + ', '.join(sorted(label(x) for x in element)) + ']'
|
|
2141
|
+
|
|
2142
|
+
M = Manifold(2, 'M', structure='topological')
|
|
2143
|
+
a = M.subset('A')
|
|
2144
|
+
b = M.subset('B')
|
|
2145
|
+
c = a.intersection(b); c
|
|
2146
|
+
P = M.subset_poset(open_covers=True)
|
|
2147
|
+
g1 = P.plot(element_labels={element: label(element) for element in P})
|
|
2148
|
+
|
|
2149
|
+
T = Manifold(2, 'T', structure='topological')
|
|
2150
|
+
from sage.typeset.unicode_art import unicode_subscript
|
|
2151
|
+
S = [T.subset(f'S{unicode_subscript(i)}') for i in range(6)]
|
|
2152
|
+
[S[i].intersection(S[i+3]) for i in range(3)]
|
|
2153
|
+
T.intersection(*S, name='⋂ᵢSᵢ')
|
|
2154
|
+
P = T.subset_poset(open_covers=True)
|
|
2155
|
+
g2 = P.plot(element_labels={element: label(element) for element in P})
|
|
2156
|
+
|
|
2157
|
+
sphinx_plot(graphics_array([g1, g2]), figsize=(8, 3))
|
|
2158
|
+
|
|
2159
|
+
TESTS::
|
|
2160
|
+
|
|
2161
|
+
sage: (a.intersection(b)).is_subset(a)
|
|
2162
|
+
True
|
|
2163
|
+
sage: (a.intersection(b)).is_subset(a)
|
|
2164
|
+
True
|
|
2165
|
+
sage: a.intersection(b) is b.intersection(a)
|
|
2166
|
+
True
|
|
2167
|
+
sage: a.intersection(a.intersection(b)) is a.intersection(b)
|
|
2168
|
+
True
|
|
2169
|
+
sage: (a.intersection(b)).intersection(a) is a.intersection(b)
|
|
2170
|
+
True
|
|
2171
|
+
sage: M.intersection(a) is a
|
|
2172
|
+
True
|
|
2173
|
+
sage: a.intersection(M) is a
|
|
2174
|
+
True
|
|
2175
|
+
"""
|
|
2176
|
+
subsets = ManifoldSubsetFiniteFamily.from_subsets_or_families(self, *others)
|
|
2177
|
+
subset_iter = iter(self._reduce_intersection_members(subsets))
|
|
2178
|
+
# _intersection_subset is able to build the intersection of several
|
|
2179
|
+
# subsets directly; but because we cache only pairwise intersections,
|
|
2180
|
+
# we build the intersection by a sequence of pairwise intersections.
|
|
2181
|
+
res = next(subset_iter)
|
|
2182
|
+
others = list(subset_iter)
|
|
2183
|
+
if not others:
|
|
2184
|
+
return res
|
|
2185
|
+
for other in others[:-1]:
|
|
2186
|
+
res = res._intersection_subset(other)
|
|
2187
|
+
# The last one gets the name
|
|
2188
|
+
return res._intersection_subset(others[-1], name=name, latex_name=latex_name)
|
|
2189
|
+
|
|
2190
|
+
@staticmethod
|
|
2191
|
+
def _reduce_intersection_members(subsets):
|
|
2192
|
+
r"""
|
|
2193
|
+
Return a reduced set of subsets with the same intersection as the given subsets.
|
|
2194
|
+
|
|
2195
|
+
It is reduced with respect to two operations:
|
|
2196
|
+
|
|
2197
|
+
- replacing an inclusion chain by its minimal element
|
|
2198
|
+
|
|
2199
|
+
- replacing a pair of subsets with a declared intersection by the intersection
|
|
2200
|
+
|
|
2201
|
+
INPUT:
|
|
2202
|
+
|
|
2203
|
+
- ``subsets`` -- a non-empty iterable of :class:`ManifoldSubset` instances
|
|
2204
|
+
of the same manifold
|
|
2205
|
+
|
|
2206
|
+
EXAMPLES::
|
|
2207
|
+
|
|
2208
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
2209
|
+
sage: A = M.subset('A')
|
|
2210
|
+
sage: B1 = A.subset('B1')
|
|
2211
|
+
sage: B2 = A.subset('B2')
|
|
2212
|
+
sage: C = B1.intersection(B2)
|
|
2213
|
+
sage: M._reduce_intersection_members([A, M, A])
|
|
2214
|
+
Set {A} of subsets of the 2-dimensional topological manifold M
|
|
2215
|
+
sage: M._reduce_intersection_members([A, B1])
|
|
2216
|
+
Set {B1} of subsets of the 2-dimensional topological manifold M
|
|
2217
|
+
sage: M._reduce_intersection_members([B1, B2])
|
|
2218
|
+
Set {B1_inter_B2} of subsets of the 2-dimensional topological manifold M
|
|
2219
|
+
sage: M._reduce_intersection_members([])
|
|
2220
|
+
Traceback (most recent call last):
|
|
2221
|
+
...
|
|
2222
|
+
TypeError: input set must be nonempty
|
|
2223
|
+
"""
|
|
2224
|
+
subsets = set(subsets)
|
|
2225
|
+
if not subsets:
|
|
2226
|
+
raise TypeError('input set must be nonempty')
|
|
2227
|
+
|
|
2228
|
+
def reduce():
|
|
2229
|
+
# Greedily replace inclusion chains by their minimal element
|
|
2230
|
+
# and pairs with declared intersections by their intersection
|
|
2231
|
+
for U, V in itertools.combinations(subsets, 2):
|
|
2232
|
+
if U.is_subset(V):
|
|
2233
|
+
subsets.remove(V)
|
|
2234
|
+
return True
|
|
2235
|
+
if V.is_subset(U):
|
|
2236
|
+
subsets.remove(U)
|
|
2237
|
+
return True
|
|
2238
|
+
try:
|
|
2239
|
+
UV = U._intersections[V._name]
|
|
2240
|
+
except KeyError:
|
|
2241
|
+
pass
|
|
2242
|
+
else:
|
|
2243
|
+
subsets.difference_update([U, V])
|
|
2244
|
+
subsets.add(UV)
|
|
2245
|
+
return True
|
|
2246
|
+
return False
|
|
2247
|
+
while reduce():
|
|
2248
|
+
pass
|
|
2249
|
+
assert subsets # there must be a survivor
|
|
2250
|
+
return ManifoldSubsetFiniteFamily(subsets)
|
|
2251
|
+
|
|
2252
|
+
def _intersection_subset(self, *others, name=None, latex_name=None):
|
|
2253
|
+
r"""
|
|
2254
|
+
Return a subset that is the intersection of ``self`` and ``others``.
|
|
2255
|
+
|
|
2256
|
+
The result is always a new subset of the manifold. If the intersection
|
|
2257
|
+
involves two subsets only, the result is stored in the dictionaries
|
|
2258
|
+
of known intersections for later reuse by other methods.
|
|
2259
|
+
|
|
2260
|
+
INPUT:
|
|
2261
|
+
|
|
2262
|
+
- ``others`` -- an iterable of :class:`ManifoldSubset` instances
|
|
2263
|
+
of the same manifold
|
|
2264
|
+
- ``name`` -- (default: ``None``) name given to the intersection; the
|
|
2265
|
+
default is ``self._name`` inter [...] inter ``last_other._name``
|
|
2266
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
2267
|
+
intersection; the default is built upon the symbol `\cap`
|
|
2268
|
+
|
|
2269
|
+
EXAMPLES::
|
|
2270
|
+
|
|
2271
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
2272
|
+
sage: B1 = M.subset('B1')
|
|
2273
|
+
sage: B2 = M.subset('B2')
|
|
2274
|
+
sage: B3 = M.subset('B3')
|
|
2275
|
+
sage: B1._intersection_subset(B2)
|
|
2276
|
+
Subset B1_inter_B2 of the 2-dimensional topological manifold M
|
|
2277
|
+
sage: B1._intersection_subset(B2, B3)
|
|
2278
|
+
Subset B1_inter_B2_inter_B3 of the 2-dimensional topological manifold M
|
|
2279
|
+
"""
|
|
2280
|
+
subsets = ManifoldSubsetFiniteFamily.from_subsets_or_families(self, *others)
|
|
2281
|
+
if latex_name is None:
|
|
2282
|
+
if name is None:
|
|
2283
|
+
latex_name = r'\cap '.join(S._latex_name for S in subsets)
|
|
2284
|
+
else:
|
|
2285
|
+
latex_name = name
|
|
2286
|
+
if name is None:
|
|
2287
|
+
name = "_inter_".join(S._name for S in subsets)
|
|
2288
|
+
if all(S.is_open() for S in subsets):
|
|
2289
|
+
res = self.open_subset(name, latex_name=latex_name, supersets=subsets)
|
|
2290
|
+
else:
|
|
2291
|
+
res = self.subset(name, latex_name=latex_name)
|
|
2292
|
+
res.declare_subset(subsets)
|
|
2293
|
+
for S in subsets:
|
|
2294
|
+
S._top_subsets.add(res)
|
|
2295
|
+
if len(subsets) == 2:
|
|
2296
|
+
S1, S2 = subsets
|
|
2297
|
+
S1._intersections[S2._name] = S2._intersections[S1._name] = res
|
|
2298
|
+
return res
|
|
2299
|
+
|
|
2300
|
+
def union(self, *others, name=None, latex_name=None):
|
|
2301
|
+
r"""
|
|
2302
|
+
Return the union of the current subset with other subsets.
|
|
2303
|
+
|
|
2304
|
+
This method may return a previously constructed union instead
|
|
2305
|
+
of creating a new subset. In this case, ``name`` and ``latex_name``
|
|
2306
|
+
are not used.
|
|
2307
|
+
|
|
2308
|
+
INPUT:
|
|
2309
|
+
|
|
2310
|
+
- ``others`` -- other subsets of the same manifold
|
|
2311
|
+
- ``name`` -- (default: ``None``) name given to the union in the
|
|
2312
|
+
case the latter has to be created; the default is
|
|
2313
|
+
``self._name`` union ``other._name``
|
|
2314
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
2315
|
+
union in the case the latter has to be created; the default
|
|
2316
|
+
is built upon the symbol `\cup`
|
|
2317
|
+
|
|
2318
|
+
OUTPUT:
|
|
2319
|
+
|
|
2320
|
+
- instance of :class:`ManifoldSubset` representing the
|
|
2321
|
+
subset that is the union of the current subset with ``others``
|
|
2322
|
+
|
|
2323
|
+
EXAMPLES:
|
|
2324
|
+
|
|
2325
|
+
Union of two subsets::
|
|
2326
|
+
|
|
2327
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
2328
|
+
sage: a = M.subset('A')
|
|
2329
|
+
sage: b = M.subset('B')
|
|
2330
|
+
sage: c = a.union(b); c
|
|
2331
|
+
Subset A_union_B of the 2-dimensional topological manifold M
|
|
2332
|
+
sage: a.superset_family()
|
|
2333
|
+
Set {A, A_union_B, M} of subsets of the 2-dimensional topological manifold M
|
|
2334
|
+
sage: b.superset_family()
|
|
2335
|
+
Set {A_union_B, B, M} of subsets of the 2-dimensional topological manifold M
|
|
2336
|
+
sage: c.superset_family()
|
|
2337
|
+
Set {A_union_B, M} of subsets of the 2-dimensional topological manifold M
|
|
2338
|
+
|
|
2339
|
+
Union of six subsets::
|
|
2340
|
+
|
|
2341
|
+
sage: T = Manifold(2, 'T', structure='topological')
|
|
2342
|
+
sage: S = [T.subset(f'S{i}') for i in range(6)]
|
|
2343
|
+
sage: [S[i].union(S[i+3]) for i in range(3)]
|
|
2344
|
+
[Subset S0_union_S3 of the 2-dimensional topological manifold T,
|
|
2345
|
+
Subset S1_union_S4 of the 2-dimensional topological manifold T,
|
|
2346
|
+
Subset S2_union_S5 of the 2-dimensional topological manifold T]
|
|
2347
|
+
sage: union_S_i = S[0].union(S[1:], name='union_S_i'); union_S_i
|
|
2348
|
+
Subset union_S_i of the 2-dimensional topological manifold T
|
|
2349
|
+
sage: T.subset_family()
|
|
2350
|
+
Set {S0, S0_union_S3, S0_union_S3_union_S1_union_S4, S1,
|
|
2351
|
+
S1_union_S4, S2, S2_union_S5, S3, S4, S5, T, union_S_i}
|
|
2352
|
+
of subsets of the 2-dimensional topological manifold T
|
|
2353
|
+
|
|
2354
|
+
.. PLOT::
|
|
2355
|
+
|
|
2356
|
+
def label(element):
|
|
2357
|
+
if isinstance(element, str):
|
|
2358
|
+
return element
|
|
2359
|
+
try:
|
|
2360
|
+
return element._name.replace('_union_', '∪')
|
|
2361
|
+
except AttributeError:
|
|
2362
|
+
return '[' + ', '.join(sorted(label(x) for x in element)) + ']'
|
|
2363
|
+
|
|
2364
|
+
M = Manifold(2, 'M', structure='topological')
|
|
2365
|
+
a = M.subset('A')
|
|
2366
|
+
b = M.subset('B')
|
|
2367
|
+
c = a.union(b); c
|
|
2368
|
+
P = M.subset_poset(open_covers=True)
|
|
2369
|
+
g1 = P.plot(element_labels={element: label(element) for element in P})
|
|
2370
|
+
|
|
2371
|
+
T = Manifold(2, 'T', structure='topological')
|
|
2372
|
+
from sage.typeset.unicode_art import unicode_subscript
|
|
2373
|
+
S = [T.subset(f'S{unicode_subscript(i)}') for i in range(6)]
|
|
2374
|
+
[S[i].union(S[i+3]) for i in range(3)]
|
|
2375
|
+
union_S_i = S[0].union(S[1:], name='⋃ᵢSᵢ'); union_S_i
|
|
2376
|
+
P = T.subset_poset(open_covers=True)
|
|
2377
|
+
g2 = P.plot(element_labels={element: label(element) for element in P})
|
|
2378
|
+
|
|
2379
|
+
sphinx_plot(graphics_array([g1, g2]), figsize=(8, 3))
|
|
2380
|
+
|
|
2381
|
+
TESTS::
|
|
2382
|
+
|
|
2383
|
+
sage: a.is_subset(a.union(b))
|
|
2384
|
+
True
|
|
2385
|
+
sage: b.is_subset(a.union(b))
|
|
2386
|
+
True
|
|
2387
|
+
sage: a.union(b) is b.union(a)
|
|
2388
|
+
True
|
|
2389
|
+
sage: a.union(a.union(b)) is a.union(b)
|
|
2390
|
+
True
|
|
2391
|
+
sage: (a.union(b)).union(a) is a.union(b)
|
|
2392
|
+
True
|
|
2393
|
+
sage: a.union(M) is M
|
|
2394
|
+
True
|
|
2395
|
+
sage: M.union(a) is M
|
|
2396
|
+
True
|
|
2397
|
+
|
|
2398
|
+
Check that :issue:`30401` is fixed::
|
|
2399
|
+
|
|
2400
|
+
sage: d = a.subset('D')
|
|
2401
|
+
sage: e = a.subset('E')
|
|
2402
|
+
sage: d.union(e).is_subset(a)
|
|
2403
|
+
True
|
|
2404
|
+
"""
|
|
2405
|
+
subsets = ManifoldSubsetFiniteFamily.from_subsets_or_families(self, *others)
|
|
2406
|
+
subsets = self._reduce_union_members(subsets)
|
|
2407
|
+
assert subsets
|
|
2408
|
+
subset_iter = iter(subsets)
|
|
2409
|
+
res = next(subset_iter)
|
|
2410
|
+
others = list(subset_iter)
|
|
2411
|
+
if not others:
|
|
2412
|
+
return res
|
|
2413
|
+
for other in others[:-1]:
|
|
2414
|
+
res = res._union_subset(other)
|
|
2415
|
+
# The last one gets the name
|
|
2416
|
+
return res._union_subset(others[-1], name=name, latex_name=latex_name)
|
|
2417
|
+
|
|
2418
|
+
@staticmethod
|
|
2419
|
+
def _reduce_union_members(subsets):
|
|
2420
|
+
r"""
|
|
2421
|
+
Return a reduced set of subsets with the same union as the given subsets.
|
|
2422
|
+
|
|
2423
|
+
It is reduced with respect to two operations:
|
|
2424
|
+
|
|
2425
|
+
- replacing an inclusion chain by its maximal element
|
|
2426
|
+
|
|
2427
|
+
- replacing a pair of subsets with a declared union by the union
|
|
2428
|
+
|
|
2429
|
+
INPUT:
|
|
2430
|
+
|
|
2431
|
+
- ``subsets`` -- an iterable of :class:`ManifoldSubset` instances
|
|
2432
|
+
of the same manifold
|
|
2433
|
+
|
|
2434
|
+
EXAMPLES::
|
|
2435
|
+
|
|
2436
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
2437
|
+
sage: A = M.subset('A')
|
|
2438
|
+
sage: B1 = A.subset('B1')
|
|
2439
|
+
sage: B2 = A.subset('B2')
|
|
2440
|
+
sage: B = B1.union(B2)
|
|
2441
|
+
sage: M._reduce_union_members([])
|
|
2442
|
+
{}
|
|
2443
|
+
sage: M._reduce_union_members([B1, B])
|
|
2444
|
+
Set {B1_union_B2} of subsets of the 2-dimensional topological manifold M
|
|
2445
|
+
sage: M._reduce_union_members([A, B1, B2])
|
|
2446
|
+
Set {A} of subsets of the 2-dimensional topological manifold M
|
|
2447
|
+
"""
|
|
2448
|
+
subsets = set(subsets)
|
|
2449
|
+
|
|
2450
|
+
def reduce():
|
|
2451
|
+
# Greedily replace inclusion chains by their maximal element
|
|
2452
|
+
# and pairs with declared unions by their union
|
|
2453
|
+
for U, V in itertools.combinations(subsets, 2):
|
|
2454
|
+
if U.is_subset(V):
|
|
2455
|
+
subsets.remove(U)
|
|
2456
|
+
return True
|
|
2457
|
+
if V.is_subset(U):
|
|
2458
|
+
subsets.remove(V)
|
|
2459
|
+
return True
|
|
2460
|
+
try:
|
|
2461
|
+
UV = U._unions[V._name]
|
|
2462
|
+
except KeyError:
|
|
2463
|
+
pass
|
|
2464
|
+
else:
|
|
2465
|
+
subsets.difference_update([U, V])
|
|
2466
|
+
subsets.add(UV)
|
|
2467
|
+
return True
|
|
2468
|
+
return False
|
|
2469
|
+
while reduce():
|
|
2470
|
+
pass
|
|
2471
|
+
return ManifoldSubsetFiniteFamily(subsets)
|
|
2472
|
+
|
|
2473
|
+
def _union_subset(self, other, name=None, latex_name=None):
|
|
2474
|
+
r"""
|
|
2475
|
+
Return a subset of the manifold that is the union of ``self`` and ``other``.
|
|
2476
|
+
|
|
2477
|
+
The result is always a new subset of the manifold and is also
|
|
2478
|
+
stored in ``self`` and ``other``'s dictionaries of known unions.
|
|
2479
|
+
|
|
2480
|
+
INPUT:
|
|
2481
|
+
|
|
2482
|
+
- ``other`` -- an instance of :class:`ManifoldSubset`
|
|
2483
|
+
- ``name`` -- (default: ``None``) name given to the union; the default is
|
|
2484
|
+
``self._name`` union ``other._name``
|
|
2485
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
2486
|
+
union; the default is built upon the symbol `\cup`
|
|
2487
|
+
|
|
2488
|
+
EXAMPLES::
|
|
2489
|
+
|
|
2490
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
2491
|
+
sage: B1 = M.subset('B1')
|
|
2492
|
+
sage: B2 = M.subset('B2')
|
|
2493
|
+
sage: B1._union_subset(B2)
|
|
2494
|
+
Subset B1_union_B2 of the 2-dimensional topological manifold M
|
|
2495
|
+
"""
|
|
2496
|
+
if latex_name is None:
|
|
2497
|
+
if name is None:
|
|
2498
|
+
latex_name = r'\cup '.join(S._latex_name for S in (self, other))
|
|
2499
|
+
else:
|
|
2500
|
+
latex_name = name
|
|
2501
|
+
if name is None:
|
|
2502
|
+
name = "_union_".join(S._name for S in (self, other))
|
|
2503
|
+
res_open = all(S.is_open() for S in (self, other))
|
|
2504
|
+
res = self.superset(name, latex_name, is_open=res_open)
|
|
2505
|
+
res.declare_superset(other)
|
|
2506
|
+
res._top_subsets.add(self)
|
|
2507
|
+
res._top_subsets.add(other)
|
|
2508
|
+
self._unions[other._name] = other._unions[self._name] = res
|
|
2509
|
+
for sp in self._supersets:
|
|
2510
|
+
if sp in other._supersets:
|
|
2511
|
+
sp._subsets.add(res)
|
|
2512
|
+
res._supersets.add(sp)
|
|
2513
|
+
if res._is_open:
|
|
2514
|
+
for chart in other._atlas:
|
|
2515
|
+
if chart not in res._atlas:
|
|
2516
|
+
res._atlas.append(chart)
|
|
2517
|
+
for chart in other._top_charts:
|
|
2518
|
+
if chart not in res._top_charts:
|
|
2519
|
+
res._top_charts.append(chart)
|
|
2520
|
+
res._coord_changes.update(other._coord_changes)
|
|
2521
|
+
# Open covers of the union:
|
|
2522
|
+
for oc1 in self._open_covers:
|
|
2523
|
+
for oc2 in other._open_covers:
|
|
2524
|
+
oc = oc1[:]
|
|
2525
|
+
for s in oc2:
|
|
2526
|
+
if s not in oc:
|
|
2527
|
+
oc.append(s)
|
|
2528
|
+
res._open_covers.append(oc)
|
|
2529
|
+
return res
|
|
2530
|
+
|
|
2531
|
+
def complement(self, superset=None, name=None, latex_name=None, is_open=False):
|
|
2532
|
+
r"""
|
|
2533
|
+
Return the complement of ``self`` in the manifold or in ``superset``.
|
|
2534
|
+
|
|
2535
|
+
INPUT:
|
|
2536
|
+
|
|
2537
|
+
- ``superset`` -- (default: ``self.manifold()``) a superset of ``self``
|
|
2538
|
+
- ``name`` -- (default: ``None``) name given to the complement in the
|
|
2539
|
+
case the latter has to be created; the default is
|
|
2540
|
+
``superset._name`` minus ``self._name``
|
|
2541
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
2542
|
+
complement in the case the latter has to be created; the default
|
|
2543
|
+
is built upon the symbol `\setminus`
|
|
2544
|
+
- ``is_open`` -- boolean (default: ``False``); if ``True``, the created
|
|
2545
|
+
subset is assumed to be open with respect to the manifold's topology
|
|
2546
|
+
|
|
2547
|
+
OUTPUT:
|
|
2548
|
+
|
|
2549
|
+
- instance of :class:`ManifoldSubset` representing the subset that
|
|
2550
|
+
is ``superset`` minus ``self``
|
|
2551
|
+
|
|
2552
|
+
EXAMPLES::
|
|
2553
|
+
|
|
2554
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
2555
|
+
sage: A = M.subset('A')
|
|
2556
|
+
sage: B1 = A.subset('B1')
|
|
2557
|
+
sage: B2 = A.subset('B2')
|
|
2558
|
+
sage: B1.complement()
|
|
2559
|
+
Subset M_minus_B1 of the 2-dimensional topological manifold M
|
|
2560
|
+
sage: B1.complement(A)
|
|
2561
|
+
Subset A_minus_B1 of the 2-dimensional topological manifold M
|
|
2562
|
+
sage: B1.complement(B2)
|
|
2563
|
+
Traceback (most recent call last):
|
|
2564
|
+
...
|
|
2565
|
+
TypeError: superset must be a superset of self
|
|
2566
|
+
|
|
2567
|
+
Demanding that the complement is open makes ``self`` a closed subset::
|
|
2568
|
+
|
|
2569
|
+
sage: A.is_closed() # False a priori
|
|
2570
|
+
False
|
|
2571
|
+
sage: A.complement(is_open=True)
|
|
2572
|
+
Open subset M_minus_A of the 2-dimensional topological manifold M
|
|
2573
|
+
sage: A.is_closed()
|
|
2574
|
+
True
|
|
2575
|
+
"""
|
|
2576
|
+
if superset is None:
|
|
2577
|
+
superset = self.manifold()
|
|
2578
|
+
elif not self.is_subset(superset):
|
|
2579
|
+
raise TypeError("superset must be a superset of self")
|
|
2580
|
+
return superset.difference(self,
|
|
2581
|
+
name=name, latex_name=latex_name,
|
|
2582
|
+
is_open=is_open)
|
|
2583
|
+
|
|
2584
|
+
def difference(self, other, name=None, latex_name=None, is_open=False):
|
|
2585
|
+
r"""
|
|
2586
|
+
Return the set difference of ``self`` minus ``other``.
|
|
2587
|
+
|
|
2588
|
+
INPUT:
|
|
2589
|
+
|
|
2590
|
+
- ``other`` -- another subset of the same manifold
|
|
2591
|
+
- ``name`` -- (default: ``None``) name given to the difference in the
|
|
2592
|
+
case the latter has to be created; the default is
|
|
2593
|
+
``self._name`` minus ``other._name``
|
|
2594
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
2595
|
+
difference in the case the latter has to be created; the default
|
|
2596
|
+
is built upon the symbol `\setminus`
|
|
2597
|
+
- ``is_open`` -- boolean (default: ``False``); if ``True``, the created
|
|
2598
|
+
subset is assumed to be open with respect to the manifold's topology
|
|
2599
|
+
|
|
2600
|
+
OUTPUT:
|
|
2601
|
+
|
|
2602
|
+
- instance of :class:`ManifoldSubset` representing the subset that is
|
|
2603
|
+
``self`` minus ``other``
|
|
2604
|
+
|
|
2605
|
+
EXAMPLES::
|
|
2606
|
+
|
|
2607
|
+
sage: M = Manifold(2, 'M', structure='topological')
|
|
2608
|
+
sage: A = M.subset('A')
|
|
2609
|
+
sage: CA = M.difference(A); CA
|
|
2610
|
+
Subset M_minus_A of the 2-dimensional topological manifold M
|
|
2611
|
+
sage: latex(CA)
|
|
2612
|
+
M\setminus A
|
|
2613
|
+
sage: A.intersection(CA).is_empty()
|
|
2614
|
+
True
|
|
2615
|
+
sage: A.union(CA)
|
|
2616
|
+
2-dimensional topological manifold M
|
|
2617
|
+
|
|
2618
|
+
sage: O = M.open_subset('O')
|
|
2619
|
+
sage: CO = M.difference(O); CO
|
|
2620
|
+
Subset M_minus_O of the 2-dimensional topological manifold M
|
|
2621
|
+
sage: M.difference(O) is CO
|
|
2622
|
+
True
|
|
2623
|
+
|
|
2624
|
+
sage: CO2 = M.difference(O, is_open=True, name='CO2'); CO2
|
|
2625
|
+
Open subset CO2 of the 2-dimensional topological manifold M
|
|
2626
|
+
sage: CO is CO2
|
|
2627
|
+
False
|
|
2628
|
+
sage: CO.is_subset(CO2) and CO2.is_subset(CO)
|
|
2629
|
+
True
|
|
2630
|
+
sage: M.difference(O, is_open=True)
|
|
2631
|
+
Open subset CO2 of the 2-dimensional topological manifold M
|
|
2632
|
+
|
|
2633
|
+
Since `O` is open and we have asked `M\setminus O` to be open, `O`
|
|
2634
|
+
is a clopen set (if `O\neq M` and `O\neq\emptyset`, this implies that
|
|
2635
|
+
`M` is not connected)::
|
|
2636
|
+
|
|
2637
|
+
sage: O.is_closed() and O.is_open()
|
|
2638
|
+
True
|
|
2639
|
+
"""
|
|
2640
|
+
# See if it has been created already
|
|
2641
|
+
diffs = []
|
|
2642
|
+
for diff_name, intersection in other._intersections.items():
|
|
2643
|
+
if intersection.is_empty():
|
|
2644
|
+
try:
|
|
2645
|
+
union = other._unions[diff_name]
|
|
2646
|
+
except KeyError:
|
|
2647
|
+
pass
|
|
2648
|
+
else:
|
|
2649
|
+
if union == self:
|
|
2650
|
+
diff = self.subset_family()[diff_name]
|
|
2651
|
+
if not is_open:
|
|
2652
|
+
return diff
|
|
2653
|
+
if diff.is_open():
|
|
2654
|
+
return diff
|
|
2655
|
+
# is_open=True but we found a subset that
|
|
2656
|
+
# is not known to be open - and we cannot
|
|
2657
|
+
# declare it open.
|
|
2658
|
+
diffs.append(diff)
|
|
2659
|
+
|
|
2660
|
+
if latex_name is None:
|
|
2661
|
+
if name is None:
|
|
2662
|
+
latex_name = r'\setminus '.join(S._latex_name
|
|
2663
|
+
for S in (self, other))
|
|
2664
|
+
else:
|
|
2665
|
+
latex_name = name
|
|
2666
|
+
if name is None:
|
|
2667
|
+
name = "_minus_".join(S._name for S in (self, other))
|
|
2668
|
+
|
|
2669
|
+
is_open = is_open or (self.is_open() and other.is_closed())
|
|
2670
|
+
|
|
2671
|
+
diff = self.subset(name=name, latex_name=latex_name, is_open=is_open)
|
|
2672
|
+
diff.declare_equal(diffs)
|
|
2673
|
+
self.declare_union(other, diff, disjoint=True)
|
|
2674
|
+
return diff
|
|
2675
|
+
|
|
2676
|
+
def closure(self, name=None, latex_name=None):
|
|
2677
|
+
r"""
|
|
2678
|
+
Return the topological closure of ``self`` as a subset of the manifold.
|
|
2679
|
+
|
|
2680
|
+
INPUT:
|
|
2681
|
+
|
|
2682
|
+
- ``name`` -- (default: ``None``) name given to the difference in the
|
|
2683
|
+
case the latter has to be created; the default prepends ``cl_``
|
|
2684
|
+
to ``self._name``
|
|
2685
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
2686
|
+
difference in the case the latter has to be created; the default
|
|
2687
|
+
is built upon the operator `\mathrm{cl}`
|
|
2688
|
+
|
|
2689
|
+
OUTPUT:
|
|
2690
|
+
|
|
2691
|
+
- if ``self`` is already known to be closed (see :meth:`is_closed`),
|
|
2692
|
+
``self``; otherwise, an instance of
|
|
2693
|
+
:class:`~sage.manifolds.subsets.closure.ManifoldSubsetClosure`
|
|
2694
|
+
|
|
2695
|
+
EXAMPLES::
|
|
2696
|
+
|
|
2697
|
+
sage: M = Manifold(2, 'R^2', structure='topological')
|
|
2698
|
+
sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
|
|
2699
|
+
sage: M.closure() is M
|
|
2700
|
+
True
|
|
2701
|
+
sage: D2 = M.open_subset('D2', coord_def={c_cart: x^2+y^2<2}); D2
|
|
2702
|
+
Open subset D2 of the 2-dimensional topological manifold R^2
|
|
2703
|
+
sage: cl_D2 = D2.closure(); cl_D2
|
|
2704
|
+
Topological closure cl_D2 of the
|
|
2705
|
+
Open subset D2 of the 2-dimensional topological manifold R^2
|
|
2706
|
+
sage: cl_D2.is_closed()
|
|
2707
|
+
True
|
|
2708
|
+
sage: cl_D2 is cl_D2.closure()
|
|
2709
|
+
True
|
|
2710
|
+
|
|
2711
|
+
sage: D1 = D2.open_subset('D1'); D1
|
|
2712
|
+
Open subset D1 of the 2-dimensional topological manifold R^2
|
|
2713
|
+
sage: D1.closure().is_subset(D2.closure())
|
|
2714
|
+
True
|
|
2715
|
+
"""
|
|
2716
|
+
if self.is_closed():
|
|
2717
|
+
return self
|
|
2718
|
+
from sage.manifolds.subsets.closure import ManifoldSubsetClosure
|
|
2719
|
+
return ManifoldSubsetClosure(self, name=name, latex_name=latex_name)
|
|
2720
|
+
|
|
2721
|
+
# ### End of construction of new sets from self
|