passagemath-symbolics 10.8.1a1__cp311-cp311-macosx_13_0_arm64.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.
Files changed (182) hide show
  1. passagemath_symbolics/.dylibs/libgmp.10.dylib +0 -0
  2. passagemath_symbolics/__init__.py +3 -0
  3. passagemath_symbolics-10.8.1a1.dist-info/METADATA +186 -0
  4. passagemath_symbolics-10.8.1a1.dist-info/RECORD +182 -0
  5. passagemath_symbolics-10.8.1a1.dist-info/WHEEL +6 -0
  6. passagemath_symbolics-10.8.1a1.dist-info/top_level.txt +3 -0
  7. sage/all__sagemath_symbolics.py +17 -0
  8. sage/calculus/all.py +14 -0
  9. sage/calculus/calculus.py +2838 -0
  10. sage/calculus/desolvers.py +1864 -0
  11. sage/calculus/predefined.py +51 -0
  12. sage/calculus/tests.py +225 -0
  13. sage/calculus/var.cpython-311-darwin.so +0 -0
  14. sage/calculus/var.pyx +401 -0
  15. sage/dynamics/all__sagemath_symbolics.py +6 -0
  16. sage/dynamics/complex_dynamics/all.py +5 -0
  17. sage/dynamics/complex_dynamics/mandel_julia.py +765 -0
  18. sage/dynamics/complex_dynamics/mandel_julia_helper.cpython-311-darwin.so +0 -0
  19. sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1034 -0
  20. sage/ext/all__sagemath_symbolics.py +1 -0
  21. sage/ext_data/kenzo/CP2.txt +45 -0
  22. sage/ext_data/kenzo/CP3.txt +349 -0
  23. sage/ext_data/kenzo/CP4.txt +4774 -0
  24. sage/ext_data/kenzo/README.txt +49 -0
  25. sage/ext_data/kenzo/S4.txt +20 -0
  26. sage/ext_data/magma/latex/latex.m +1021 -0
  27. sage/ext_data/magma/latex/latex.spec +1 -0
  28. sage/ext_data/magma/sage/basic.m +356 -0
  29. sage/ext_data/magma/sage/sage.spec +1 -0
  30. sage/ext_data/magma/spec +9 -0
  31. sage/geometry/all__sagemath_symbolics.py +8 -0
  32. sage/geometry/hyperbolic_space/all.py +5 -0
  33. sage/geometry/hyperbolic_space/hyperbolic_coercion.py +755 -0
  34. sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
  35. sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2419 -0
  36. sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
  37. sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1083 -0
  38. sage/geometry/hyperbolic_space/hyperbolic_model.py +1502 -0
  39. sage/geometry/hyperbolic_space/hyperbolic_point.py +621 -0
  40. sage/geometry/riemannian_manifolds/all.py +7 -0
  41. sage/geometry/riemannian_manifolds/parametrized_surface3d.py +1632 -0
  42. sage/geometry/riemannian_manifolds/surface3d_generators.py +461 -0
  43. sage/interfaces/all__sagemath_symbolics.py +1 -0
  44. sage/interfaces/magma.py +2991 -0
  45. sage/interfaces/magma_free.py +90 -0
  46. sage/interfaces/maple.py +1402 -0
  47. sage/interfaces/mathematica.py +1345 -0
  48. sage/interfaces/mathics.py +1312 -0
  49. sage/interfaces/sympy.py +1398 -0
  50. sage/interfaces/sympy_wrapper.py +197 -0
  51. sage/interfaces/tides.py +938 -0
  52. sage/libs/all__sagemath_symbolics.py +6 -0
  53. sage/manifolds/all.py +7 -0
  54. sage/manifolds/calculus_method.py +553 -0
  55. sage/manifolds/catalog.py +437 -0
  56. sage/manifolds/chart.py +4010 -0
  57. sage/manifolds/chart_func.py +3416 -0
  58. sage/manifolds/continuous_map.py +2183 -0
  59. sage/manifolds/continuous_map_image.py +155 -0
  60. sage/manifolds/differentiable/affine_connection.py +2475 -0
  61. sage/manifolds/differentiable/all.py +1 -0
  62. sage/manifolds/differentiable/automorphismfield.py +1383 -0
  63. sage/manifolds/differentiable/automorphismfield_group.py +604 -0
  64. sage/manifolds/differentiable/bundle_connection.py +1445 -0
  65. sage/manifolds/differentiable/characteristic_cohomology_class.py +1840 -0
  66. sage/manifolds/differentiable/chart.py +1241 -0
  67. sage/manifolds/differentiable/curve.py +1028 -0
  68. sage/manifolds/differentiable/de_rham_cohomology.py +541 -0
  69. sage/manifolds/differentiable/degenerate.py +559 -0
  70. sage/manifolds/differentiable/degenerate_submanifold.py +1668 -0
  71. sage/manifolds/differentiable/diff_form.py +1660 -0
  72. sage/manifolds/differentiable/diff_form_module.py +1062 -0
  73. sage/manifolds/differentiable/diff_map.py +1315 -0
  74. sage/manifolds/differentiable/differentiable_submanifold.py +291 -0
  75. sage/manifolds/differentiable/examples/all.py +1 -0
  76. sage/manifolds/differentiable/examples/euclidean.py +2517 -0
  77. sage/manifolds/differentiable/examples/real_line.py +897 -0
  78. sage/manifolds/differentiable/examples/sphere.py +1186 -0
  79. sage/manifolds/differentiable/examples/symplectic_space.py +187 -0
  80. sage/manifolds/differentiable/examples/symplectic_space_test.py +40 -0
  81. sage/manifolds/differentiable/integrated_curve.py +4035 -0
  82. sage/manifolds/differentiable/levi_civita_connection.py +841 -0
  83. sage/manifolds/differentiable/manifold.py +4254 -0
  84. sage/manifolds/differentiable/manifold_homset.py +1826 -0
  85. sage/manifolds/differentiable/metric.py +3032 -0
  86. sage/manifolds/differentiable/mixed_form.py +1507 -0
  87. sage/manifolds/differentiable/mixed_form_algebra.py +559 -0
  88. sage/manifolds/differentiable/multivector_module.py +800 -0
  89. sage/manifolds/differentiable/multivectorfield.py +1522 -0
  90. sage/manifolds/differentiable/poisson_tensor.py +268 -0
  91. sage/manifolds/differentiable/pseudo_riemannian.py +755 -0
  92. sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +1839 -0
  93. sage/manifolds/differentiable/scalarfield.py +1343 -0
  94. sage/manifolds/differentiable/scalarfield_algebra.py +472 -0
  95. sage/manifolds/differentiable/symplectic_form.py +912 -0
  96. sage/manifolds/differentiable/symplectic_form_test.py +220 -0
  97. sage/manifolds/differentiable/tangent_space.py +412 -0
  98. sage/manifolds/differentiable/tangent_vector.py +616 -0
  99. sage/manifolds/differentiable/tensorfield.py +4665 -0
  100. sage/manifolds/differentiable/tensorfield_module.py +963 -0
  101. sage/manifolds/differentiable/tensorfield_paral.py +2450 -0
  102. sage/manifolds/differentiable/tensorfield_paral_test.py +16 -0
  103. sage/manifolds/differentiable/vector_bundle.py +1725 -0
  104. sage/manifolds/differentiable/vectorfield.py +1717 -0
  105. sage/manifolds/differentiable/vectorfield_module.py +2445 -0
  106. sage/manifolds/differentiable/vectorframe.py +1832 -0
  107. sage/manifolds/family.py +270 -0
  108. sage/manifolds/local_frame.py +1490 -0
  109. sage/manifolds/manifold.py +3090 -0
  110. sage/manifolds/manifold_homset.py +452 -0
  111. sage/manifolds/operators.py +359 -0
  112. sage/manifolds/point.py +994 -0
  113. sage/manifolds/scalarfield.py +3718 -0
  114. sage/manifolds/scalarfield_algebra.py +629 -0
  115. sage/manifolds/section.py +3111 -0
  116. sage/manifolds/section_module.py +831 -0
  117. sage/manifolds/structure.py +229 -0
  118. sage/manifolds/subset.py +2721 -0
  119. sage/manifolds/subsets/all.py +1 -0
  120. sage/manifolds/subsets/closure.py +131 -0
  121. sage/manifolds/subsets/pullback.py +883 -0
  122. sage/manifolds/topological_submanifold.py +891 -0
  123. sage/manifolds/trivialization.py +733 -0
  124. sage/manifolds/utilities.py +1348 -0
  125. sage/manifolds/vector_bundle.py +1347 -0
  126. sage/manifolds/vector_bundle_fiber.py +332 -0
  127. sage/manifolds/vector_bundle_fiber_element.py +111 -0
  128. sage/matrix/all__sagemath_symbolics.py +1 -0
  129. sage/matrix/matrix_symbolic_dense.cpython-311-darwin.so +0 -0
  130. sage/matrix/matrix_symbolic_dense.pxd +6 -0
  131. sage/matrix/matrix_symbolic_dense.pyx +1030 -0
  132. sage/matrix/matrix_symbolic_sparse.cpython-311-darwin.so +0 -0
  133. sage/matrix/matrix_symbolic_sparse.pxd +6 -0
  134. sage/matrix/matrix_symbolic_sparse.pyx +1038 -0
  135. sage/modules/all__sagemath_symbolics.py +1 -0
  136. sage/modules/vector_callable_symbolic_dense.py +105 -0
  137. sage/modules/vector_symbolic_dense.py +116 -0
  138. sage/modules/vector_symbolic_sparse.py +118 -0
  139. sage/rings/all__sagemath_symbolics.py +4 -0
  140. sage/rings/asymptotic/all.py +6 -0
  141. sage/rings/asymptotic/asymptotic_expansion_generators.py +1485 -0
  142. sage/rings/asymptotic/asymptotic_ring.py +4858 -0
  143. sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +4106 -0
  144. sage/rings/asymptotic/growth_group.py +5373 -0
  145. sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
  146. sage/rings/asymptotic/term_monoid.py +5205 -0
  147. sage/rings/function_field/all__sagemath_symbolics.py +2 -0
  148. sage/rings/polynomial/all__sagemath_symbolics.py +1 -0
  149. sage/symbolic/all.py +15 -0
  150. sage/symbolic/assumptions.py +987 -0
  151. sage/symbolic/benchmark.py +93 -0
  152. sage/symbolic/callable.py +456 -0
  153. sage/symbolic/callable.pyi +66 -0
  154. sage/symbolic/comparison_impl.pyi +38 -0
  155. sage/symbolic/complexity_measures.py +35 -0
  156. sage/symbolic/constants.py +1286 -0
  157. sage/symbolic/constants_c_impl.pyi +10 -0
  158. sage/symbolic/expression_conversion_algebraic.py +310 -0
  159. sage/symbolic/expression_conversion_sympy.py +317 -0
  160. sage/symbolic/expression_conversions.py +1727 -0
  161. sage/symbolic/function_factory.py +355 -0
  162. sage/symbolic/function_factory.pyi +41 -0
  163. sage/symbolic/getitem_impl.pyi +24 -0
  164. sage/symbolic/integration/all.py +1 -0
  165. sage/symbolic/integration/external.py +271 -0
  166. sage/symbolic/integration/integral.py +1075 -0
  167. sage/symbolic/maxima_wrapper.py +162 -0
  168. sage/symbolic/operators.py +267 -0
  169. sage/symbolic/operators.pyi +61 -0
  170. sage/symbolic/pynac_constant_impl.pyi +13 -0
  171. sage/symbolic/pynac_function_impl.pyi +8 -0
  172. sage/symbolic/random_tests.py +461 -0
  173. sage/symbolic/relation.py +2062 -0
  174. sage/symbolic/ring.cpython-311-darwin.so +0 -0
  175. sage/symbolic/ring.pxd +5 -0
  176. sage/symbolic/ring.pyi +110 -0
  177. sage/symbolic/ring.pyx +1393 -0
  178. sage/symbolic/series_impl.pyi +10 -0
  179. sage/symbolic/subring.py +1025 -0
  180. sage/symbolic/symengine.py +19 -0
  181. sage/symbolic/tests.py +40 -0
  182. sage/symbolic/units.py +1468 -0
@@ -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