passagemath-symbolics 10.8.1a1__cp314-cp314t-musllinux_1_2_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. passagemath_symbolics/__init__.py +3 -0
  2. passagemath_symbolics-10.8.1a1.dist-info/METADATA +186 -0
  3. passagemath_symbolics-10.8.1a1.dist-info/RECORD +181 -0
  4. passagemath_symbolics-10.8.1a1.dist-info/WHEEL +5 -0
  5. passagemath_symbolics-10.8.1a1.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 +2838 -0
  9. sage/calculus/desolvers.py +1864 -0
  10. sage/calculus/predefined.py +51 -0
  11. sage/calculus/tests.py +225 -0
  12. sage/calculus/var.cpython-314t-aarch64-linux-musl.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-314t-aarch64-linux-musl.so +0 -0
  18. sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1034 -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 +755 -0
  33. sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
  34. sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2419 -0
  35. sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
  36. sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1083 -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 +2991 -0
  44. sage/interfaces/magma_free.py +90 -0
  45. sage/interfaces/maple.py +1402 -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 +553 -0
  54. sage/manifolds/catalog.py +437 -0
  55. sage/manifolds/chart.py +4010 -0
  56. sage/manifolds/chart_func.py +3416 -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 +1668 -0
  70. sage/manifolds/differentiable/diff_form.py +1660 -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 +1522 -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 +912 -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 +1725 -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 +2721 -0
  118. sage/manifolds/subsets/all.py +1 -0
  119. sage/manifolds/subsets/closure.py +131 -0
  120. sage/manifolds/subsets/pullback.py +883 -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 +1347 -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-314t-aarch64-linux-musl.so +0 -0
  129. sage/matrix/matrix_symbolic_dense.pxd +6 -0
  130. sage/matrix/matrix_symbolic_dense.pyx +1030 -0
  131. sage/matrix/matrix_symbolic_sparse.cpython-314t-aarch64-linux-musl.so +0 -0
  132. sage/matrix/matrix_symbolic_sparse.pxd +6 -0
  133. sage/matrix/matrix_symbolic_sparse.pyx +1038 -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 +4106 -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 +5205 -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 +987 -0
  150. sage/symbolic/benchmark.py +93 -0
  151. sage/symbolic/callable.py +456 -0
  152. sage/symbolic/callable.pyi +66 -0
  153. sage/symbolic/comparison_impl.pyi +38 -0
  154. sage/symbolic/complexity_measures.py +35 -0
  155. sage/symbolic/constants.py +1286 -0
  156. sage/symbolic/constants_c_impl.pyi +10 -0
  157. sage/symbolic/expression_conversion_algebraic.py +310 -0
  158. sage/symbolic/expression_conversion_sympy.py +317 -0
  159. sage/symbolic/expression_conversions.py +1727 -0
  160. sage/symbolic/function_factory.py +355 -0
  161. sage/symbolic/function_factory.pyi +41 -0
  162. sage/symbolic/getitem_impl.pyi +24 -0
  163. sage/symbolic/integration/all.py +1 -0
  164. sage/symbolic/integration/external.py +271 -0
  165. sage/symbolic/integration/integral.py +1075 -0
  166. sage/symbolic/maxima_wrapper.py +162 -0
  167. sage/symbolic/operators.py +267 -0
  168. sage/symbolic/operators.pyi +61 -0
  169. sage/symbolic/pynac_constant_impl.pyi +13 -0
  170. sage/symbolic/pynac_function_impl.pyi +8 -0
  171. sage/symbolic/random_tests.py +461 -0
  172. sage/symbolic/relation.py +2062 -0
  173. sage/symbolic/ring.cpython-314t-aarch64-linux-musl.so +0 -0
  174. sage/symbolic/ring.pxd +5 -0
  175. sage/symbolic/ring.pyi +110 -0
  176. sage/symbolic/ring.pyx +1393 -0
  177. sage/symbolic/series_impl.pyi +10 -0
  178. sage/symbolic/subring.py +1025 -0
  179. sage/symbolic/symengine.py +19 -0
  180. sage/symbolic/tests.py +40 -0
  181. sage/symbolic/units.py +1468 -0
@@ -0,0 +1,883 @@
1
+ # sage_setup: distribution = sagemath-symbolics
2
+ r"""
3
+ Manifold Subsets Defined as Pullbacks of Subsets under Continuous Maps
4
+ """
5
+
6
+
7
+ # ****************************************************************************
8
+ # Copyright (C) 2021 Matthias Koeppe <mkoeppe@math.ucdavis.edu>
9
+ #
10
+ # This program is free software: you can redistribute it and/or modify
11
+ # it under the terms of the GNU General Public License as published by
12
+ # the Free Software Foundation, either version 2 of the License, or
13
+ # (at your option) any later version.
14
+ # https://www.gnu.org/licenses/
15
+ # ****************************************************************************
16
+
17
+ import sage.geometry.abc
18
+ from sage.categories.metric_spaces import MetricSpaces
19
+ from sage.categories.sets_cat import EmptySetError, Sets
20
+ from sage.manifolds.chart import Chart
21
+ from sage.manifolds.scalarfield import ScalarField
22
+ from sage.manifolds.subset import ManifoldSubset
23
+ from sage.misc.lazy_import import lazy_import
24
+ from sage.modules.free_module import FreeModule_generic
25
+ from sage.modules.free_module_element import vector
26
+ from sage.rings.complex_double import CDF
27
+ from sage.rings.infinity import infinity, minus_infinity
28
+ from sage.rings.integer_ring import ZZ
29
+ from sage.rings.rational_field import QQ
30
+ from sage.rings.real_double import RDF
31
+ from sage.rings.real_lazy import CLF, RLF
32
+ from sage.sets.real_set import RealSet
33
+ from sage.symbolic.ring import SR
34
+
35
+ lazy_import('sage.geometry.relative_interior', 'RelativeInterior')
36
+
37
+
38
+ class ManifoldSubsetPullback(ManifoldSubset):
39
+ """
40
+ Manifold subset defined as a pullback of a subset under a continuous map.
41
+
42
+ INPUT:
43
+
44
+ - ``map`` -- an instance of :class:`~sage.manifolds.continuous_map.ContinuousMap`,
45
+ :class:`ScalarField`, or :class:`Chart`
46
+
47
+ - ``codomain_subset`` -- an instance of :class:`~sage.manifolds.subset.ManifoldSubset`,
48
+ :class:`RealSet`, or :class:`~sage.geometry.convex_set.ConvexSet_base`
49
+
50
+ EXAMPLES::
51
+
52
+ sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback
53
+ sage: M = Manifold(2, 'R^2', structure='topological')
54
+ sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
55
+
56
+ Pulling back a real interval under a scalar field::
57
+
58
+ sage: r_squared = M.scalar_field(x^2+y^2)
59
+ sage: r_squared.set_immutable()
60
+ sage: cl_I = RealSet([1, 4]); cl_I
61
+ [1, 4]
62
+ sage: cl_O = ManifoldSubsetPullback(r_squared, cl_I); cl_O
63
+ Subset f_inv_[1, 4] of the 2-dimensional topological manifold R^2
64
+ sage: M.point((0, 0)) in cl_O
65
+ False
66
+ sage: M.point((0, 1)) in cl_O
67
+ True
68
+
69
+ Pulling back an open real interval gives an open subset::
70
+
71
+ sage: I = RealSet((1, 4)); I
72
+ (1, 4)
73
+ sage: O = ManifoldSubsetPullback(r_squared, I); O
74
+ Open subset f_inv_(1, 4) of the 2-dimensional topological manifold R^2
75
+ sage: M.point((1, 0)) in O
76
+ False
77
+ sage: M.point((1, 1)) in O
78
+ True
79
+
80
+ Pulling back a polytope under a chart::
81
+
82
+ sage: # needs sage.geometry.polyhedron
83
+ sage: P = Polyhedron(vertices=[[0, 0], [1, 2], [2, 1]]); P
84
+ A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
85
+ sage: S = ManifoldSubsetPullback(c_cart, P); S
86
+ Subset x_y_inv_P of the 2-dimensional topological manifold R^2
87
+ sage: M((1, 2)) in S
88
+ True
89
+ sage: M((2, 0)) in S
90
+ False
91
+
92
+ Pulling back the interior of a polytope under a chart::
93
+
94
+ sage: # needs sage.geometry.polyhedron
95
+ sage: int_P = P.interior(); int_P
96
+ Relative interior of a
97
+ 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
98
+ sage: int_S = ManifoldSubsetPullback(c_cart, int_P, name='int_S'); int_S
99
+ Open subset int_S of the 2-dimensional topological manifold R^2
100
+ sage: M((0, 0)) in int_S
101
+ False
102
+ sage: M((1, 1)) in int_S
103
+ True
104
+
105
+ Using the embedding map of a submanifold::
106
+
107
+ sage: M = Manifold(3, 'M', structure='topological')
108
+ sage: N = Manifold(2, 'N', ambient=M, structure='topological'); N
109
+ 2-dimensional topological submanifold N
110
+ immersed in the 3-dimensional topological manifold M
111
+ sage: CM.<x,y,z> = M.chart()
112
+ sage: CN.<u,v> = N.chart()
113
+ sage: t = var('t')
114
+ sage: phi = N.continuous_map(M, {(CN,CM): [u,v,t+u^2+v^2]})
115
+ sage: phi_inv = M.continuous_map(N, {(CM,CN): [x,y]})
116
+ sage: phi_inv_t = M.scalar_field({CM: z-x^2-y^2})
117
+ sage: N.set_immersion(phi, inverse=phi_inv, var=t,
118
+ ....: t_inverse={t: phi_inv_t})
119
+ sage: N.declare_embedding()
120
+
121
+ sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback
122
+ sage: S = M.open_subset('S', coord_def={CM: z<1})
123
+ sage: phi_without_t = N.continuous_map(M, {(CN, CM): [expr.subs(t=0)
124
+ ....: for expr in phi.expr()]})
125
+ sage: phi_without_t
126
+ Continuous map
127
+ from the 2-dimensional topological submanifold N
128
+ embedded in the 3-dimensional topological manifold M
129
+ to the 3-dimensional topological manifold M
130
+ sage: phi_without_t.expr()
131
+ (u, v, u^2 + v^2)
132
+ sage: D = ManifoldSubsetPullback(phi_without_t, S); D
133
+ Subset f_inv_S of the 2-dimensional topological submanifold N
134
+ embedded in the 3-dimensional topological manifold M
135
+ sage: N.point((2,0)) in D
136
+ False
137
+ """
138
+ @staticmethod
139
+ def __classcall_private__(cls, map, codomain_subset, inverse=None,
140
+ name=None, latex_name=None):
141
+ """
142
+ Normalize arguments and delegate to other constructors.
143
+
144
+ TESTS::
145
+
146
+ sage: # needs sage.geometry.polyhedron
147
+ sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback
148
+ sage: M = Manifold(2, 'R^2', structure='topological')
149
+ sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
150
+ sage: P = Polyhedron(vertices=[[0, 0], [1, 2], [3, 4]]); P
151
+ A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
152
+ sage: S = ManifoldSubsetPullback(c_cart, P); S
153
+ Subset x_y_inv_P of the 2-dimensional topological manifold R^2
154
+ sage: S is ManifoldSubsetPullback(c_cart, P)
155
+ True
156
+ """
157
+
158
+ try:
159
+ is_mutable = map.is_mutable()
160
+ except AttributeError:
161
+ pass
162
+ else:
163
+ if is_mutable:
164
+ map = map.copy()
165
+ map.set_immutable()
166
+ try:
167
+ is_mutable = inverse.is_mutable()
168
+ except AttributeError:
169
+ pass
170
+ else:
171
+ if is_mutable:
172
+ inverse = inverse.copy()
173
+ inverse.set_immutable()
174
+
175
+ if inverse is None:
176
+ if isinstance(map, Chart):
177
+ from sage.misc.latex import latex
178
+ inverse_latex_name = '(' + ','.join(str(latex(x)) + '^{-1}' for x in map) + ')'
179
+ inverse_name = '_'.join(repr(x) for x in map) + '_inv'
180
+ else:
181
+ map_name = map._name or 'f'
182
+ map_latex_name = map._latex_name or map_name
183
+ inverse_name = map_name + '_inv'
184
+ inverse_latex_name = map_latex_name + r'^{-1}'
185
+ else:
186
+ inverse_name = inverse._name
187
+ inverse_latex_name = inverse._latex_name
188
+ try:
189
+ codomain_subset_latex_name = codomain_subset._latex_name
190
+ codomain_subset_name = codomain_subset._name
191
+ except AttributeError:
192
+ from sage.misc.latex import latex
193
+ codomain_subset_latex_name = str(latex(codomain_subset))
194
+ s = repr(codomain_subset)
195
+ if len(s) > 10:
196
+ codomain_subset_name = 'P'
197
+ else:
198
+ codomain_subset_name = s
199
+ if latex_name is None:
200
+ if name is None:
201
+ latex_name = inverse_latex_name + '(' + codomain_subset_latex_name + ')'
202
+ else:
203
+ latex_name = name
204
+ if name is None:
205
+ name = inverse_name + '_' + codomain_subset_name
206
+
207
+ if cls._is_open(codomain_subset):
208
+
209
+ try:
210
+ coord_def = cls._coord_def(map, codomain_subset)
211
+ except NotImplementedError:
212
+ pass
213
+ else:
214
+ return map.domain().open_subset(name=name, latex_name=latex_name,
215
+ coord_def=coord_def)
216
+
217
+ self = super().__classcall__(cls, map, codomain_subset, inverse, name, latex_name)
218
+
219
+ return self
220
+
221
+ @staticmethod
222
+ def _is_open(codomain_subset):
223
+ """
224
+ Return whether ``codomain_subset`` is (known to be) an open subset of its ambient space.
225
+
226
+ EXAMPLES:
227
+
228
+ Manifolds and subsets::
229
+
230
+ sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback
231
+ sage: R2 = Manifold(2, 'R^2', structure='topological'); R2
232
+ 2-dimensional topological manifold R^2
233
+ sage: ManifoldSubsetPullback._is_open(R2)
234
+ True
235
+ sage: A = R2.subset('A'); A
236
+ Subset A of the 2-dimensional topological manifold R^2
237
+ sage: ManifoldSubsetPullback._is_open(A)
238
+ False
239
+
240
+ :class:`RealSet` instances::
241
+
242
+ sage: I = RealSet.open(1, 2); I
243
+ (1, 2)
244
+ sage: ManifoldSubsetPullback._is_open(I)
245
+ True
246
+ sage: cl_I = RealSet.closed(1, 2); cl_I
247
+ [1, 2]
248
+ sage: ManifoldSubsetPullback._is_open(cl_I)
249
+ False
250
+
251
+ Polyhedra::
252
+
253
+ sage: # needs sage.geometry.polyhedron
254
+ sage: Empty = Polyhedron(ambient_dim=2); Empty
255
+ The empty polyhedron in ZZ^2
256
+ sage: ManifoldSubsetPullback._is_open(Empty)
257
+ True
258
+ sage: C = polytopes.cube(); C
259
+ A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices
260
+ sage: ManifoldSubsetPullback._is_open(C)
261
+ False
262
+
263
+ Interiors of polyhedra::
264
+
265
+ sage: int_C = C.interior(); int_C # needs sage.geometry.polyhedron
266
+ Relative interior of a
267
+ 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices
268
+ sage: ManifoldSubsetPullback._is_open(int_C) # needs sage.geometry.polyhedron
269
+ True
270
+
271
+ PPL polyhedra and not-necessarily-closed polyhedra::
272
+
273
+ sage: # needs pplpy
274
+ sage: from ppl import Variable, C_Polyhedron, NNC_Polyhedron, Constraint_System
275
+ sage: u = Variable(0)
276
+ sage: v = Variable(1)
277
+ sage: CS = Constraint_System()
278
+ sage: CS.insert(0 < u)
279
+ sage: CS.insert(u < 1)
280
+ sage: CS.insert(0 < v)
281
+ sage: CS.insert(v < 1)
282
+ sage: CS.insert(u + v <= 3) # redundant inequality
283
+ sage: P = NNC_Polyhedron(CS); P
284
+ A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point, 4 closure_points
285
+ sage: ManifoldSubsetPullback._is_open(P)
286
+ True
287
+ sage: CS.insert(u + v <= 1)
288
+ sage: T = NNC_Polyhedron(CS); T
289
+ A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point, 3 closure_points
290
+ sage: ManifoldSubsetPullback._is_open(T)
291
+ False
292
+ """
293
+
294
+ if isinstance(codomain_subset, ManifoldSubset):
295
+ return codomain_subset.is_open()
296
+
297
+ if isinstance(codomain_subset, RealSet):
298
+ return codomain_subset.is_open()
299
+
300
+ if isinstance(codomain_subset, sage.geometry.abc.Polyhedron):
301
+ return codomain_subset.is_empty() or codomain_subset.is_universe()
302
+
303
+ if isinstance(codomain_subset, RelativeInterior):
304
+ return codomain_subset.closure().is_full_dimensional()
305
+
306
+ if codomain_subset in Sets().Finite():
307
+ return codomain_subset.cardinality() == 0
308
+
309
+ if hasattr(codomain_subset, 'minimized_constraints'):
310
+ try:
311
+ from ppl import C_Polyhedron, NNC_Polyhedron
312
+ except ImportError:
313
+ pass
314
+ else:
315
+ if isinstance(codomain_subset, (NNC_Polyhedron, C_Polyhedron)):
316
+ cs = codomain_subset.minimized_constraints()
317
+ if cs.has_equalities():
318
+ return False
319
+ return not any(constraint.is_nonstrict_inequality()
320
+ for constraint in cs)
321
+
322
+ return False
323
+
324
+ @staticmethod
325
+ def _interval_restriction(expr, interval):
326
+ """
327
+ Return a restriction expressing that ``expr`` lies in ``interval``.
328
+
329
+ INPUT:
330
+
331
+ - ``expr`` -- a symbolic expression
332
+ - ``interval`` -- an instance of :class:`~sage.sets.real_set.InternalRealInterval`
333
+
334
+ OUTPUT:
335
+
336
+ - A restriction suitable as input to :meth:`~sage.manifolds.chart.restrict`:
337
+ lists are conjunctions, tuples are disjunctions
338
+
339
+ EXAMPLES::
340
+
341
+ sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback
342
+ sage: _interval_restriction = ManifoldSubsetPullback._interval_restriction
343
+ sage: var('t')
344
+ t
345
+ sage: assume(t >= -2)
346
+ sage: assume(t <= 5)
347
+ sage: _interval_restriction(t, RealSet(3, 4)[0])
348
+ [t > 3, t < 4]
349
+ sage: _interval_restriction(t, RealSet.unbounded_below_closed(2)[0])
350
+ t <= 2
351
+ sage: _interval_restriction(t, RealSet.closed(-5, 5)[0])
352
+ []
353
+ sage: _interval_restriction(t, RealSet.unbounded_below_closed(-5)[0])
354
+ ()
355
+ sage: _interval_restriction(t, RealSet.unbounded_above_closed(6)[0])
356
+ ()
357
+ sage: _interval_restriction(t^2, RealSet.unbounded_above_closed(0)[0])
358
+ []
359
+ """
360
+
361
+ conjunction = []
362
+ if interval.lower() != minus_infinity:
363
+ if interval.lower_closed():
364
+ condition = (expr >= interval.lower())
365
+ negation = (expr < interval.lower())
366
+ else:
367
+ condition = (expr > interval.lower())
368
+ negation = (expr <= interval.lower())
369
+ if negation:
370
+ # known to be false
371
+ return ()
372
+ if not condition:
373
+ # not known to be true
374
+ conjunction.append(condition)
375
+
376
+ if interval.upper() != infinity:
377
+ if interval.upper_closed():
378
+ condition = (expr <= interval.upper())
379
+ negation = (expr > interval.upper())
380
+ else:
381
+ condition = (expr < interval.upper())
382
+ negation = (expr >= interval.upper())
383
+ if negation:
384
+ # known to be false
385
+ return ()
386
+ if not condition:
387
+ # not known to be true
388
+ conjunction.append(condition)
389
+
390
+ if len(conjunction) == 1:
391
+ return conjunction[0]
392
+ else:
393
+ # lists express 'and'
394
+ return conjunction
395
+
396
+ @staticmethod
397
+ def _realset_restriction(expr, realset):
398
+ """
399
+ Return a restriction expressing that ``expr`` lies in ``realset``.
400
+
401
+ INPUT:
402
+
403
+ - ``expr`` -- a symbolic expression
404
+ - ``interval`` -- an instance of :class:`~sage.sets.real_set.RealSet`
405
+
406
+ OUTPUT:
407
+
408
+ - A restriction suitable as input to :meth:`~sage.manifolds.chart.restrict`:
409
+ lists are conjunctions, tuples are disjunctions
410
+
411
+ EXAMPLES::
412
+
413
+ sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback
414
+ sage: _realset_restriction = ManifoldSubsetPullback._realset_restriction
415
+ sage: var('t')
416
+ t
417
+ sage: assume(t >= -2)
418
+ sage: assume(t <= 5)
419
+ sage: _realset_restriction(t, RealSet(-oo, oo))
420
+ []
421
+ sage: _realset_restriction(t, RealSet())
422
+ ()
423
+ sage: _realset_restriction(t, RealSet([-5, -4], (-1, 1), [3, 4], [6, 7]))
424
+ ([t > -1, t < 1], [t >= 3, t <= 4])
425
+ """
426
+ disjunction = []
427
+ for interval in realset:
428
+ condition = ManifoldSubsetPullback._interval_restriction(expr, interval)
429
+ if condition == []:
430
+ return []
431
+ if condition != ():
432
+ disjunction.append(condition)
433
+
434
+ if len(disjunction) == 1:
435
+ return disjunction[0]
436
+ else:
437
+ # tuples express 'or'
438
+ return tuple(disjunction)
439
+
440
+ @staticmethod
441
+ def _polyhedron_restriction(expr, polyhedron, relint=False):
442
+ """
443
+ Return a restriction expressing that ``expr`` lies in ``polyhedron`` or its relative interior.
444
+
445
+ INPUT:
446
+
447
+ - ``expr`` -- a symbolic expression
448
+ - ``polyhedron`` -- an instance of :class:`~sage.geometry.polyhedron.base.Polyhedron_base`
449
+ - ``relint`` -- whether the restriction should use the relative interior
450
+
451
+ OUTPUT:
452
+
453
+ - A restriction suitable as input to :meth:`~sage.manifolds.chart.restrict`:
454
+ lists are conjunctions, tuples are disjunctions
455
+
456
+ EXAMPLES::
457
+
458
+ sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback
459
+ sage: _polyhedron_restriction = ManifoldSubsetPullback._polyhedron_restriction
460
+ sage: var('x y z')
461
+ (x, y, z)
462
+ sage: c = polytopes.cube() # needs sage.geometry.polyhedron
463
+ sage: _polyhedron_restriction((x, y, z), c) # needs sage.geometry.polyhedron
464
+ [-x + 1 >= 0, -y + 1 >= 0, -z + 1 >= 0, x + 1 >= 0, z + 1 >= 0, y + 1 >= 0]
465
+ sage: _polyhedron_restriction((x, y, z), c, relint=True) # needs sage.geometry.polyhedron
466
+ [-x + 1 > 0, -y + 1 > 0, -z + 1 > 0, x + 1 > 0, z + 1 > 0, y + 1 > 0]
467
+ """
468
+ conjunction = []
469
+
470
+ expr = vector(SR, expr)
471
+ for constraint in polyhedron.Hrepresentation():
472
+
473
+ if constraint.is_inequality():
474
+ if relint:
475
+ condition = (constraint.eval(expr) > 0)
476
+ else:
477
+ condition = (constraint.eval(expr) >= 0)
478
+ else:
479
+ condition = (constraint.eval(expr) == 0)
480
+ if not condition:
481
+ # not known to be true
482
+ conjunction.append(condition)
483
+
484
+ if len(conjunction) == 1:
485
+ return conjunction[0]
486
+ else:
487
+ # lists express 'and'
488
+ return conjunction
489
+
490
+ @staticmethod
491
+ def _coord_def(map, codomain_subset):
492
+ r"""
493
+ Return a coordinate definition of the open subset that is the pullback of ``codomain_subset``.
494
+
495
+ INPUT:
496
+
497
+ - ``map`` -- an instance of :class:`ScalarField` or :class:`Chart`
498
+
499
+ - ``codomain_subset`` -- if ``map`` is a :class:`ScalarField`, an
500
+ instance of :class:`RealSet`; if ``map`` is a :class:`Chart`, the
501
+ relative interior of a polyhedron
502
+
503
+ For other inputs, a :exc:`NotImplementedError` will be raised.
504
+
505
+ OUTPUT:
506
+
507
+ - an object suitable for the parameter ``coord_def`` of
508
+ :meth:`sage.manifolds.manifold.TopologicalManifold.open_subset`.
509
+
510
+ EXAMPLES::
511
+
512
+ sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback
513
+ sage: _coord_def = ManifoldSubsetPullback._coord_def
514
+ sage: M = Manifold(2, 'R^2', structure='topological')
515
+
516
+ Coordinate definition of an open chart polyhedron::
517
+
518
+ sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
519
+ sage: P = Polyhedron(vertices=[[0, 0], [1, 2], [3, 4]]); P # needs sage.geometry.polyhedron
520
+ A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
521
+ sage: ri_P = P.relative_interior(); ri_P # needs sage.geometry.polyhedron
522
+ Relative interior of a 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
523
+ sage: _coord_def(c_cart, ri_P) # needs sage.geometry.polyhedron
524
+ {Chart (R^2, (x, y)): [2*x - y > 0, -4*x + 3*y > 0, x - y + 1 > 0]}
525
+
526
+ Coordinate definition of the pullback of an open interval under a scalar field::
527
+
528
+ sage: r_squared = M.scalar_field(x^2 + y^2)
529
+ sage: I = RealSet((1, 4)); I
530
+ (1, 4)
531
+ sage: _coord_def(r_squared, I)
532
+ {Chart (R^2, (x, y)): [x^2 + y^2 > 1, x^2 + y^2 < 4]}
533
+ """
534
+ if isinstance(map, ScalarField) and isinstance(codomain_subset, RealSet):
535
+
536
+ return {chart: ManifoldSubsetPullback._realset_restriction(func.expr(),
537
+ codomain_subset)
538
+ for chart, func in map._express.items()}
539
+
540
+ if isinstance(map, Chart):
541
+
542
+ chart = map
543
+
544
+ if isinstance(codomain_subset, RealSet):
545
+ return {chart: ManifoldSubsetPullback._realset_restriction(chart[0],
546
+ codomain_subset)}
547
+
548
+ if isinstance(codomain_subset, RelativeInterior) and isinstance(codomain_subset.closure(), sage.geometry.abc.Polyhedron):
549
+ return {chart: ManifoldSubsetPullback._polyhedron_restriction(
550
+ chart, codomain_subset.closure(), relint=True)}
551
+
552
+ raise NotImplementedError
553
+
554
+ def __init__(self, map, codomain_subset, inverse, name, latex_name):
555
+ r"""
556
+ Construct a manifold subset that is a pullback.
557
+
558
+ TESTS::
559
+
560
+ sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback
561
+ sage: M = Manifold(2, 'R^2', structure='topological')
562
+ sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
563
+ sage: r_squared = M.scalar_field(x^2+y^2)
564
+ sage: r_squared.set_immutable()
565
+ sage: cl_I = RealSet([1, 4]); cl_I
566
+ [1, 4]
567
+ sage: cl_O = ManifoldSubsetPullback(r_squared, cl_I); cl_O
568
+ Subset f_inv_[1, 4] of the 2-dimensional topological manifold R^2
569
+ sage: TestSuite(cl_O).run(skip='_test_elements')
570
+ """
571
+ if inverse is None and isinstance(map, Chart):
572
+ chart = map
573
+ scalar_codomain = (isinstance(codomain_subset, RealSet)
574
+ or any(field.has_coerce_map_from(codomain_subset)
575
+ for field in (CDF, RDF, CLF, RLF)))
576
+ if scalar_codomain:
577
+ if chart.domain().dimension() != 1:
578
+ raise ValueError('to pull back a set of scalars by a chart, the manifold must be 1-dimensional')
579
+ map = chart.domain().scalar_field({chart: chart[0]})
580
+
581
+ def _inverse(coord):
582
+ return self.point((coord,), chart=chart)
583
+ else:
584
+ def _inverse(coords):
585
+ return self.point(coords, chart=map)
586
+ inverse = _inverse
587
+
588
+ self._map = map
589
+ self._inverse = inverse
590
+
591
+ self._codomain_subset = codomain_subset
592
+ base_manifold = map.domain()
593
+ ManifoldSubset.__init__(self, base_manifold, name, latex_name=latex_name)
594
+
595
+ def _an_element_(self):
596
+ r"""
597
+ Construct some point in ``self``.
598
+
599
+ EXAMPLES::
600
+
601
+ sage: # needs sage.geometry.polyhedron
602
+ sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback
603
+ sage: M = Manifold(3, 'R^3', structure='topological')
604
+ sage: c_cart.<x,y,z> = M.chart() # Cartesian coordinates on R^3
605
+ sage: Cube = polytopes.cube(); Cube
606
+ A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices
607
+ sage: McCube = ManifoldSubsetPullback(c_cart, Cube, name='McCube'); McCube
608
+ Subset McCube of the 3-dimensional topological manifold R^3
609
+ sage: p = McCube.an_element(); p
610
+ Point on the 3-dimensional topological manifold R^3
611
+ sage: p.coordinates(c_cart)
612
+ (0, 0, 0)
613
+
614
+ sage: # needs sage.geometry.polyhedron
615
+ sage: Empty = Polyhedron(ambient_dim=3)
616
+ sage: McEmpty = ManifoldSubsetPullback(c_cart, Empty, name='McEmpty')
617
+ sage: McEmpty
618
+ Subset McEmpty of the 3-dimensional topological manifold R^3
619
+ sage: McEmpty.an_element()
620
+ Traceback (most recent call last):
621
+ ...
622
+ sage.categories.sets_cat.EmptySetError
623
+ """
624
+ try:
625
+ return next(iter(self.some_elements()))
626
+ except StopIteration:
627
+ raise EmptySetError
628
+
629
+ def some_elements(self):
630
+ r"""
631
+ Generate some elements of ``self``.
632
+
633
+ EXAMPLES::
634
+
635
+ sage: # needs sage.geometry.polyhedron
636
+ sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback
637
+ sage: M = Manifold(3, 'R^3', structure='topological')
638
+ sage: c_cart.<x,y,z> = M.chart() # Cartesian coordinates on R^3
639
+ sage: Cube = polytopes.cube(); Cube
640
+ A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices
641
+ sage: McCube = ManifoldSubsetPullback(c_cart, Cube, name='McCube'); McCube
642
+ Subset McCube of the 3-dimensional topological manifold R^3
643
+ sage: L = list(McCube.some_elements()); L
644
+ [Point on the 3-dimensional topological manifold R^3,
645
+ Point on the 3-dimensional topological manifold R^3,
646
+ Point on the 3-dimensional topological manifold R^3,
647
+ Point on the 3-dimensional topological manifold R^3,
648
+ Point on the 3-dimensional topological manifold R^3,
649
+ Point on the 3-dimensional topological manifold R^3]
650
+ sage: list(p.coordinates(c_cart) for p in L)
651
+ [(0, 0, 0),
652
+ (1, -1, -1),
653
+ (1, 0, -1),
654
+ (1, 1/2, 0),
655
+ (1, -1/4, 1/2),
656
+ (0, -5/8, 3/4)]
657
+
658
+ sage: # needs sage.geometry.polyhedron
659
+ sage: Empty = Polyhedron(ambient_dim=3)
660
+ sage: McEmpty = ManifoldSubsetPullback(c_cart, Empty, name='McEmpty')
661
+ sage: McEmpty
662
+ Subset McEmpty of the 3-dimensional topological manifold R^3
663
+ sage: list(McEmpty.some_elements())
664
+ []
665
+ """
666
+ if self._inverse is not None:
667
+ for y in self._codomain_subset.some_elements():
668
+ yield self._inverse(y)
669
+ elif self.is_empty():
670
+ return
671
+ else:
672
+ # Fallback
673
+ p = super()._an_element_()
674
+ if p in self:
675
+ yield p
676
+
677
+ def __contains__(self, point):
678
+ r"""
679
+ Check whether ``point`` is contained in ``self``.
680
+
681
+ EXAMPLES::
682
+
683
+ sage: # needs sage.geometry.polyhedron
684
+ sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback
685
+ sage: M = Manifold(3, 'R^3', structure='topological')
686
+ sage: c_cart.<x,y,z> = M.chart() # Cartesian coordinates on R^3
687
+ sage: Cube = polytopes.cube(); Cube
688
+ A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices
689
+ sage: Cube.vertices_list()
690
+ [[1, -1, -1],
691
+ [1, 1, -1],
692
+ [1, 1, 1],
693
+ [1, -1, 1],
694
+ [-1, -1, 1],
695
+ [-1, -1, -1],
696
+ [-1, 1, -1],
697
+ [-1, 1, 1]]
698
+ sage: McCube = ManifoldSubsetPullback(c_cart, Cube, name='McCube'); McCube
699
+ Subset McCube of the 3-dimensional topological manifold R^3
700
+ sage: p = M.point((0, 0, 0)); p
701
+ Point on the 3-dimensional topological manifold R^3
702
+ sage: p in McCube
703
+ True
704
+ sage: q = M.point((2, 3, 4)); q
705
+ Point on the 3-dimensional topological manifold R^3
706
+ sage: q in McCube
707
+ False
708
+ """
709
+ if super().__contains__(point):
710
+ return True
711
+ coords = self._map(point)
712
+ if isinstance(coords, (tuple, list)):
713
+ coords = vector(coords)
714
+ return coords in self._codomain_subset
715
+
716
+ def is_open(self):
717
+ """
718
+ Return if ``self`` is (known to be) an open set.
719
+
720
+ This version of the method always returns ``False``.
721
+
722
+ Because the map is continuous, the pullback is open if the
723
+ ``codomain_subset`` is open.
724
+
725
+ However, the design of :class:`~sage.manifolds.subset.ManifoldSubset` requires that open subsets
726
+ are instances of the subclass :class:`sage.manifolds.manifold.TopologicalManifold`.
727
+ The constructor of :class:`ManifoldSubsetPullback` delegates to a subclass
728
+ of :class:`sage.manifolds.manifold.TopologicalManifold` for some open subsets.
729
+
730
+ EXAMPLES::
731
+
732
+ sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback
733
+ sage: M = Manifold(2, 'R^2', structure='topological')
734
+ sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
735
+
736
+ sage: # needs sage.geometry.polyhedron
737
+ sage: P = Polyhedron(vertices=[[0, 0], [1, 2], [3, 4]]); P
738
+ A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
739
+ sage: P.is_open()
740
+ False
741
+ sage: McP = ManifoldSubsetPullback(c_cart, P, name='McP'); McP
742
+ Subset McP of the 2-dimensional topological manifold R^2
743
+ sage: McP.is_open()
744
+ False
745
+ """
746
+ return super().is_open()
747
+
748
+ def is_closed(self):
749
+ """
750
+ Return if ``self`` is (known to be) a closed subset of the manifold.
751
+
752
+ EXAMPLES::
753
+
754
+ sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback
755
+ sage: M = Manifold(2, 'R^2', structure='topological')
756
+ sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
757
+
758
+ The pullback of a closed real interval under a scalar field is closed::
759
+
760
+ sage: r_squared = M.scalar_field(x^2+y^2)
761
+ sage: r_squared.set_immutable()
762
+ sage: cl_I = RealSet([1, 2]); cl_I
763
+ [1, 2]
764
+ sage: cl_O = ManifoldSubsetPullback(r_squared, cl_I); cl_O
765
+ Subset f_inv_[1, 2] of the 2-dimensional topological manifold R^2
766
+ sage: cl_O.is_closed()
767
+ True
768
+
769
+ The pullback of a (closed convex) polyhedron under a chart is closed::
770
+
771
+ sage: # needs sage.geometry.polyhedron
772
+ sage: P = Polyhedron(vertices=[[0, 0], [1, 2], [3, 4]]); P
773
+ A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
774
+ sage: McP = ManifoldSubsetPullback(c_cart, P, name='McP'); McP
775
+ Subset McP of the 2-dimensional topological manifold R^2
776
+ sage: McP.is_closed()
777
+ True
778
+
779
+ The pullback of real vector subspaces under a chart is closed::
780
+
781
+ sage: V = span([[1, 2]], RR); V
782
+ Vector space of degree 2 and dimension 1 over Real Field with 53 bits of precision
783
+ Basis matrix:
784
+ [1.00000000000000 2.00000000000000]
785
+ sage: McV = ManifoldSubsetPullback(c_cart, V, name='McV'); McV
786
+ Subset McV of the 2-dimensional topological manifold R^2
787
+ sage: McV.is_closed()
788
+ True
789
+
790
+ The pullback of point lattices under a chart is closed::
791
+
792
+ sage: W = span([[1, 0], [3, 5]], ZZ); W
793
+ Free module of degree 2 and rank 2 over Integer Ring
794
+ Echelon basis matrix:
795
+ [1 0]
796
+ [0 5]
797
+ sage: McW = ManifoldSubsetPullback(c_cart, W, name='McW'); McW
798
+ Subset McW of the 2-dimensional topological manifold R^2
799
+ sage: McW.is_closed()
800
+ True
801
+
802
+ The pullback of finite sets is closed::
803
+
804
+ sage: F = Family([vector(QQ, [1, 2], immutable=True), vector(QQ, [2, 3], immutable=True)])
805
+ sage: McF = ManifoldSubsetPullback(c_cart, F, name='McF'); McF
806
+ Subset McF of the 2-dimensional topological manifold R^2
807
+ sage: McF.is_closed()
808
+ True
809
+ """
810
+ if self.manifold().dimension() == 0:
811
+ return True
812
+ if isinstance(self._codomain_subset, ManifoldSubset):
813
+ if self._codomain_subset.is_closed():
814
+ # known closed
815
+ return True
816
+ elif isinstance(self._codomain_subset, RealSet):
817
+ # RealSet can decide closedness authoritatively
818
+ return self._codomain_subset.is_closed()
819
+ elif isinstance(self._codomain_subset, sage.geometry.abc.Polyhedron):
820
+ # Regardless of their base_ring, we treat polyhedra as closed
821
+ # convex subsets of R^n
822
+ return True
823
+ elif isinstance(self._codomain_subset, FreeModule_generic) and self._codomain_subset.rank() != infinity:
824
+ if self._codomain_subset.base_ring() in MetricSpaces().Complete():
825
+ # Closed topological vector subspace
826
+ return True
827
+ if self._codomain_subset.base_ring() == ZZ:
828
+ if self._codomain_subset.coordinate_ring().is_subring(QQ):
829
+ # Discrete subgroup of R^n
830
+ return True
831
+ if self._codomain_subset.rank() == self._codomain_subset.base_extend(RR).dimension():
832
+ # Discrete subgroup of R^n
833
+ return True
834
+ elif self._codomain_subset in Sets().Finite():
835
+ return True
836
+ else:
837
+ if hasattr(self._codomain_subset, 'is_topologically_closed'):
838
+ try:
839
+ from ppl import C_Polyhedron, NNC_Polyhedron
840
+ except ImportError:
841
+ pass
842
+ else:
843
+ if isinstance(self._codomain_subset, (NNC_Polyhedron, C_Polyhedron)):
844
+ # ppl polyhedra can decide closedness authoritatively
845
+ return self._codomain_subset.is_topologically_closed()
846
+ return super().is_closed()
847
+
848
+ def closure(self, name=None, latex_name=None):
849
+ """
850
+ Return the topological closure of ``self`` in the manifold.
851
+
852
+ Because ``self`` is a pullback of some subset under a continuous map,
853
+ the closure of ``self`` is the pullback of the closure.
854
+
855
+ EXAMPLES::
856
+
857
+ sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback
858
+ sage: M = Manifold(2, 'R^2', structure='topological')
859
+ sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
860
+ sage: r_squared = M.scalar_field(x^2+y^2)
861
+ sage: r_squared.set_immutable()
862
+ sage: I = RealSet.open_closed(1, 2); I
863
+ (1, 2]
864
+ sage: O = ManifoldSubsetPullback(r_squared, I); O
865
+ Subset f_inv_(1, 2] of the 2-dimensional topological manifold R^2
866
+ sage: latex(O)
867
+ f^{-1}((1, 2])
868
+ sage: cl_O = O.closure(); cl_O
869
+ Subset f_inv_[1, 2] of the 2-dimensional topological manifold R^2
870
+ sage: cl_O.is_closed()
871
+ True
872
+ """
873
+ if self.is_closed():
874
+ return self
875
+ try:
876
+ codomain_subset_closure = self._codomain_subset.closure()
877
+ except AttributeError:
878
+ return super().closure()
879
+ closure = ManifoldSubsetPullback(self._map, codomain_subset_closure,
880
+ inverse=self._inverse,
881
+ name=name, latex_name=latex_name)
882
+ closure.declare_superset(self)
883
+ return closure