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