summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Gourgoulhon <eric.gourgoulhon@obspm.fr>2015-11-08 18:09:33 +0100
committerEric Gourgoulhon <eric.gourgoulhon@obspm.fr>2015-11-08 18:09:33 +0100
commite7139abffcdb5d072ddde1f98ecf03805bcc4509 (patch)
treea2a04ab981191a609ce7efd3fdac1f9959909882
parentImplement top. manifolds (scalar fields, #18640) on the new manifold categori... (diff)
parentRemove UniqueRepresentation, leaving only WithEqualityById, for topological m... (diff)
Merge branch top_manif_basics without UniqueRepresentation into top_manif_scalar_fields.
-rw-r--r--src/sage/manifolds/all.py2
-rw-r--r--src/sage/manifolds/chart.py226
-rw-r--r--src/sage/manifolds/manifold.py404
-rw-r--r--src/sage/manifolds/point.py86
-rw-r--r--src/sage/manifolds/subset.py208
5 files changed, 657 insertions, 269 deletions
diff --git a/src/sage/manifolds/all.py b/src/sage/manifolds/all.py
index 13f8964..01834c1 100644
--- a/src/sage/manifolds/all.py
+++ b/src/sage/manifolds/all.py
@@ -1,4 +1,4 @@
from sage.misc.lazy_import import lazy_import
-lazy_import('sage.manifolds.manifold', 'TopManifold')
+lazy_import('sage.manifolds.manifold', 'Manifold')
lazy_import('sage.manifolds.utilities', 'nice_derivatives')
lazy_import('sage.manifolds.utilities', 'omit_function_args')
diff --git a/src/sage/manifolds/chart.py b/src/sage/manifolds/chart.py
index 8766748..e538800 100644
--- a/src/sage/manifolds/chart.py
+++ b/src/sage/manifolds/chart.py
@@ -33,16 +33,16 @@ REFERENCES:
#*****************************************************************************
from sage.structure.sage_object import SageObject
-from sage.structure.unique_representation import UniqueRepresentation
+from sage.misc.fast_methods import WithEqualityById
from sage.symbolic.ring import SR
from sage.rings.all import CC
from sage.rings.real_mpfr import RR
from sage.rings.infinity import Infinity
from sage.misc.latex import latex
-from sage.manifolds.manifold import TopManifold
+from sage.manifolds.manifold import TopologicalManifold
from sage.manifolds.coord_func_symb import CoordFunctionSymb
-class Chart(UniqueRepresentation, SageObject):
+class Chart(WithEqualityById, SageObject):
r"""
Chart on a topological manifold.
@@ -58,7 +58,7 @@ class Chart(UniqueRepresentation, SageObject):
INPUT:
- ``domain`` -- open subset `U` on which the chart is defined (must be
- an instance of :class:`~sage.manifolds.manifold.TopManifold`)
+ an instance of :class:`~sage.manifolds.manifold.TopologicalManifold`)
- ``coordinates`` -- (default: '' (empty string)) single string defining
the coordinate symbols, with ' ' (whitespace) as a separator; each item
has at most two fields, separated by ':':
@@ -82,7 +82,7 @@ class Chart(UniqueRepresentation, SageObject):
A chart on a complex 2-dimensional topological manifold::
- sage: M = TopManifold(2, 'M', field='complex')
+ sage: M = Manifold(2, 'M', field='complex', type='topological')
sage: X = M.chart('x y'); X
Chart (M, (x, y))
sage: latex(X)
@@ -98,8 +98,7 @@ class Chart(UniqueRepresentation, SageObject):
side of the chart declaration (there is then no need to pass the string
``'x y'`` to ``chart()``)::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M', field='complex')
+ sage: M = Manifold(2, 'M', field='complex', type='topological')
sage: X.<x,y> = M.chart(); X
Chart (M, (x, y))
@@ -119,8 +118,7 @@ class Chart(UniqueRepresentation, SageObject):
names and do not have to coincide with the coordinate symbols;
for instance, one may write::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M', field='complex')
+ sage: M = Manifold(2, 'M', field='complex', type='topological')
sage: X.<x1,y1> = M.chart('x y'); X
Chart (M, (x, y))
@@ -137,8 +135,7 @@ class Chart(UniqueRepresentation, SageObject):
However, having the name of the Python variable coincide with the
coordinate symbol is quite convenient; so it is recommended to declare::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M', field='complex')
+ sage: M = Manifold(2, 'M', field='complex', type='topological')
sage: X.<x,y> = M.chart()
In the above example, the chart X covers entirely the manifold M::
@@ -180,7 +177,8 @@ class Chart(UniqueRepresentation, SageObject):
default, it starts at 0, but this can be changed via the parameter
``start_index``::
- sage: M1 = TopManifold(2, 'M_1', field='complex', start_index=1)
+ sage: M1 = Manifold(2, 'M_1', field='complex', type='topological',
+ ....: start_index=1)
sage: Z.<u,v> = M1.chart()
sage: Z[1], Z[2]
(u, v)
@@ -204,7 +202,7 @@ class Chart(UniqueRepresentation, SageObject):
Manifold subsets have a *default chart*, which, unless changed via the
method
- :meth:`~sage.manifolds.manifold.TopManifold.set_default_chart`,
+ :meth:`~sage.manifolds.manifold.TopologicalManifold.set_default_chart`,
is the first defined chart on the subset (or on a open subset of it)::
sage: M.default_chart()
@@ -238,7 +236,7 @@ class Chart(UniqueRepresentation, SageObject):
TESTS::
- sage: M = TopManifold(2, 'M', field='complex')
+ sage: M = Manifold(2, 'M', field='complex', type='topological')
sage: X.<x,y> = M.chart()
sage: X
Chart (M, (x, y))
@@ -249,12 +247,13 @@ class Chart(UniqueRepresentation, SageObject):
sage: TestSuite(X).run()
"""
- if not isinstance(domain, TopManifold):
+ if not isinstance(domain, TopologicalManifold):
raise TypeError("the first argument must be an open subset of " +
"a topological manifold")
if coordinates == '':
for x in names:
coordinates += x + ' '
+ self._coordinate_string = coordinates[:-1] # for pickling (cf. __reduce__)
self._manifold = domain.manifold()
self._domain = domain
# Treatment of the coordinates:
@@ -332,7 +331,7 @@ class Chart(UniqueRepresentation, SageObject):
TESTS::
- sage: M = TopManifold(2, 'M', field='complex')
+ sage: M = Manifold(2, 'M', field='complex', type='topological')
sage: X.<z1, z2> = M.chart()
sage: X._init_coordinates(['z1', 'z2'])
sage: X
@@ -363,7 +362,7 @@ class Chart(UniqueRepresentation, SageObject):
TESTS::
- sage: M = TopManifold(2, 'M', field='complex')
+ sage: M = Manifold(2, 'M', field='complex', type='topological')
sage: X.<x,y> = M.chart()
sage: X._repr_()
'Chart (M, (x, y))'
@@ -381,7 +380,7 @@ class Chart(UniqueRepresentation, SageObject):
TESTS::
- sage: M = TopManifold(2, 'M', field='complex')
+ sage: M = Manifold(2, 'M', field='complex', type='topological')
sage: X.<x,y> = M.chart()
sage: X._latex_()
'\\left(M,(x, y)\\right)'
@@ -411,6 +410,104 @@ class Chart(UniqueRepresentation, SageObject):
"""
return self[:]
+ def __reduce__(self):
+ r"""
+ Reduction function for the pickle protocole.
+
+ TESTS::
+
+ sage: M = Manifold(2, 'M', type='topological')
+ sage: X.<x,y> = M.chart()
+ sage: X.__reduce__()
+ (<class 'sage.manifolds.chart.RealChart'>,
+ (2-dimensional topological manifold M, 'x y'),
+ [])
+ sage: X.add_restrictions(x^2 + y^2 < 1)
+ sage: X.__reduce__()
+ (<class 'sage.manifolds.chart.RealChart'>,
+ (2-dimensional topological manifold M, 'x y'),
+ [x^2 + y^2 < 1])
+
+ Test of pickling::
+
+ sage: loads(dumps(X))
+ Chart (M, (x, y))
+
+ """
+ return (type(self), (self._domain, self._coordinate_string),
+ self.__getstate__())
+
+ def __getstate__(self):
+ r"""
+ Return the attributes of ``self`` that have been set after
+ the construction of the object.
+
+ This is used in pickling, to handle the coordinate restrictions,
+ since the latter have been defined by calls to
+ ``self.add_restrictions()`` and not at the object construction.
+
+ TESTS::
+
+ sage: M = Manifold(2, 'M', type='topological')
+ sage: X.<x,y> = M.chart()
+ sage: X.__getstate__()
+ []
+ sage: X.add_restrictions(x^2 + y^2 < 1)
+ sage: X.__getstate__()
+ [x^2 + y^2 < 1]
+
+ """
+ return self._restrictions
+
+ def __setstate__(self, coord_restrictions):
+ r"""
+ Set the attributes of ``self`` that are not initialized at the object
+ construction.
+
+ This is used in unpickling, to handle the coordinate restrictions,
+ since the latter have been defined by calls to
+ ``self.add_restrictions()`` and not at the object construction.
+
+ TESTS::
+
+ sage: M = Manifold(2, 'M', type='topological')
+ sage: X.<x,y> = M.chart()
+ sage: X._restrictions
+ []
+ sage: X.__setstate__([x^2+y^2<1])
+ sage: X._restrictions
+ [x^2 + y^2 < 1]
+
+ """
+ self._restrictions = coord_restrictions
+
+ def _test_pickling(self, **options):
+ r"""
+ Test pickling.
+
+ This test is weaker than
+ :meth:`sage.structure.sage_object.SageObject._test_pickling` in that
+ it does not require ``loads(dumps(self)) == self``.
+ It however checks that ``loads(dumps(self))`` proceeds without any
+ error and results in an object that is a chart with the same
+ coordinates as self.
+
+ TESTS::
+
+ sage: M = Manifold(2, 'M', type='topological')
+ sage: X.<x,y> = M.chart()
+ sage: X._test_pickling()
+ sage: X.add_restrictions(x < 0)
+ sage: X._test_pickling()
+
+ """
+ tester = self._tester(**options)
+ from sage.misc.all import loads, dumps
+ bckp = loads(dumps(self))
+ tester.assertEqual(type(bckp), type(self))
+ tester.assertEqual(bckp._xx, self._xx)
+ tester.assertEqual(bckp._restrictions, self._restrictions)
+
def __getitem__(self, i):
r"""
Access to the coordinates.
@@ -427,7 +524,7 @@ class Chart(UniqueRepresentation, SageObject):
EXAMPLES::
- sage: M = TopManifold(2, 'M', field='complex')
+ sage: M = Manifold(2, 'M', field='complex', type='topological')
sage: X.<x,y> = M.chart()
sage: X[0]
x
@@ -438,7 +535,8 @@ class Chart(UniqueRepresentation, SageObject):
The index range is controlled by the parameter ``start_index``::
- sage: M = TopManifold(2, 'M', field='complex', start_index=1)
+ sage: M = Manifold(2, 'M', field='complex', type='topological',
+ ....: start_index=1)
sage: X.<x,y> = M.chart()
sage: X[1]
x
@@ -467,7 +565,7 @@ class Chart(UniqueRepresentation, SageObject):
EXAMPLES::
- sage: M = TopManifold(2, 'M', field='complex')
+ sage: M = Manifold(2, 'M', field='complex', type='topological')
sage: X.<x,y> = M.chart()
sage: p = M.point((1+i, 2-i), chart=X)
sage: X(p)
@@ -484,7 +582,7 @@ class Chart(UniqueRepresentation, SageObject):
EXAMPLES::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: X.domain()
2-dimensional topological manifold M
@@ -502,7 +600,7 @@ class Chart(UniqueRepresentation, SageObject):
EXAMPLES::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: U = M.open_subset('U')
sage: X.<x,y> = U.chart()
sage: X.manifold()
@@ -534,7 +632,7 @@ class Chart(UniqueRepresentation, SageObject):
EXAMPLES::
- sage: M = TopManifold(2, 'M', field='complex')
+ sage: M = Manifold(2, 'M', field='complex', type='topological')
sage: X.<x,y> = M.chart()
sage: X.add_restrictions(abs(x) > 1)
sage: X.valid_coordinates(2+i, 1)
@@ -563,7 +661,7 @@ class Chart(UniqueRepresentation, SageObject):
INPUT:
- ``subset`` -- open subset `V` of the chart domain `U` (must be an
- instance of :class:`~sage.manifolds.manifold.TopManifold`)
+ instance of :class:`~sage.manifolds.manifold.TopologicalManifold`)
- ``restrictions`` -- (default: ``None``) list of coordinate
restrictions defining the subset `V`.
A restriction can be any symbolic equality or
@@ -588,7 +686,7 @@ class Chart(UniqueRepresentation, SageObject):
Coordinates on the unit open ball of `\CC^2` as a subchart
of the global coordinates of `\CC^2`::
- sage: M = TopManifold(2, 'C^2', field='complex')
+ sage: M = Manifold(2, 'C^2', field='complex', type='topological')
sage: X.<z1, z2> = M.chart()
sage: B = M.open_subset('B')
sage: X_B = X.restrict(B, abs(z1)^2 + abs(z2)^2 < 1); X_B
@@ -604,7 +702,7 @@ class Chart(UniqueRepresentation, SageObject):
coordinates = ""
for coord in self._xx:
coordinates += repr(coord) + ' '
- res = self.__class__(subset, coordinates)
+ res = type(self)(subset, coordinates)
res._restrictions.extend(self._restrictions)
# The coordinate restrictions are added to the result chart and
# possibly transformed into coordinate bounds:
@@ -639,8 +737,7 @@ class Chart(UniqueRepresentation, SageObject):
EXAMPLE::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M', field='complex')
+ sage: M = Manifold(2, 'M', field='complex', type='topological')
sage: X.<x,y> = M.chart()
sage: X.add_restrictions([abs(x)<1, y!=0])
sage: X.valid_coordinates(0, i)
@@ -745,7 +842,7 @@ class Chart(UniqueRepresentation, SageObject):
Transition map between two stereographic charts on the circle `S^1`::
- sage: M = TopManifold(1, 'S^1')
+ sage: M = Manifold(1, 'S^1', type='topological')
sage: U = M.open_subset('U') # Complement of the North pole
sage: cU.<x> = U.chart() # Stereographic chart from the North pole
sage: V = M.open_subset('V') # Complement of the South pole
@@ -775,8 +872,7 @@ class Chart(UniqueRepresentation, SageObject):
Transition map between the spherical chart and the Cartesian one on
`\RR^2`::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'R^2')
+ sage: M = Manifold(2, 'R^2', type='topological')
sage: c_cart.<x,y> = M.chart()
sage: U = M.open_subset('U') # the complement of the half line {y=0, x >= 0}
sage: c_spher.<r,phi> = U.chart(r'r:(0,+oo) phi:(0,2*pi):\phi')
@@ -794,7 +890,7 @@ class Chart(UniqueRepresentation, SageObject):
[2-dimensional topological manifold R^2,
Open subset U of the 2-dimensional topological manifold R^2]
- ... but a new chart has been created: `(U, (x, y))`::
+ but a new chart has been created: `(U, (x, y))`::
sage: M.atlas()
[Chart (R^2, (x, y)), Chart (U, (r, phi)), Chart (U, (x, y))]
@@ -1094,7 +1190,8 @@ class RealChart(Chart):
Cartesian coordinates on `\RR^3`::
- sage: M = TopManifold(3, 'R^3', r'\RR^3', start_index=1)
+ sage: M = Manifold(3, 'R^3', r'\RR^3', type='topological',
+ ....: start_index=1)
sage: c_cart = M.chart('x y z'); c_cart
Chart (R^3, (x, y, z))
sage: type(c_cart)
@@ -1108,8 +1205,8 @@ class RealChart(Chart):
side of the chart declaration (there is then no need to pass the string
``'x y z'`` to ``chart()``)::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(3, 'R^3', r'\RR^3', start_index=1)
+ sage: M = Manifold(3, 'R^3', r'\RR^3', type='topological',
+ ....: start_index=1)
sage: c_cart.<x,y,z> = M.chart(); c_cart
Chart (R^3, (x, y, z))
@@ -1129,7 +1226,7 @@ class RealChart(Chart):
names and do not have to coincide with the coordinate symbols; for instance,
one may write::
- sage: M = TopManifold(3, 'R^3', r'\RR^3', start_index=1)
+ sage: M = Manifold(3, 'R^3', r'\RR^3', type='topological', start_index=1)
sage: c_cart.<x1,y1,z1> = M.chart('x y z'); c_cart
Chart (R^3, (x, y, z))
@@ -1144,9 +1241,8 @@ class RealChart(Chart):
However, having the name of the Python variable coincide with the
coordinate symbol is quite convenient; so it is recommended to declare::
- sage: TopManifold._clear_cache_() # for doctests only
sage: forget() # for doctests only
- sage: M = TopManifold(3, 'R^3', r'\RR^3', start_index=1)
+ sage: M = Manifold(3, 'R^3', r'\RR^3', type='topological', start_index=1)
sage: c_cart.<x,y,z> = M.chart()
Spherical coordinates on the subset `U` of `\RR^3` that is the
@@ -1218,7 +1314,7 @@ class RealChart(Chart):
Manifold subsets have a *default chart*, which, unless changed via the
method
- :meth:`~sage.manifolds.manifold.TopManifold.set_default_chart`,
+ :meth:`~sage.manifolds.manifold.TopologicalManifold.set_default_chart`,
is the first defined chart on the subset (or on a open subset of it)::
sage: M.default_chart()
@@ -1277,7 +1373,7 @@ class RealChart(Chart):
TESTS::
sage: forget() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: X
Chart (M, (x, y))
@@ -1306,7 +1402,7 @@ class RealChart(Chart):
TESTS::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: X._init_coordinates(['x', 'y'])
sage: X
@@ -1403,8 +1499,7 @@ class RealChart(Chart):
Some coordinate bounds on a 2-dimensional manifold::
sage: forget() # for doctests only
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: c_xy.<x,y> = M.chart('x y:[0,1)')
sage: c_xy.coord_bounds(0) # x in (-oo,+oo) (the default)
((-Infinity, False), (+Infinity, False))
@@ -1452,7 +1547,7 @@ class RealChart(Chart):
Ranges of coordinates on a 2-dimensional manifold::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: X.coord_range()
x: (-oo, +oo); y: (-oo, +oo)
@@ -1544,8 +1639,7 @@ class RealChart(Chart):
Cartesian coordinates on the open unit disc in $\RR^2$::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M') # the open unit disc
+ sage: M = Manifold(2, 'M', type='topological') # the open unit disc
sage: X.<x,y> = M.chart()
sage: X.add_restrictions(x^2+y^2<1)
sage: X.valid_coordinates(0,2)
@@ -1645,7 +1739,7 @@ class RealChart(Chart):
INPUT:
- ``subset`` -- open subset `V` of the chart domain `U` (must be an
- instance of :class:`~sage.manifolds.manifold.TopManifold`)
+ instance of :class:`~sage.manifolds.manifold.TopologicalManifold`)
- ``restrictions`` -- (default: ``None``) list of coordinate
restrictions defining the subset `V`.
A restriction can be any symbolic equality or
@@ -1670,7 +1764,7 @@ class RealChart(Chart):
Cartesian coordinates on the unit open disc in `\RR^2` as a subchart
of the global Cartesian coordinates::
- sage: M = TopManifold(2, 'R^2')
+ sage: M = Manifold(2, 'R^2', type='topological')
sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
sage: D = M.open_subset('D') # the unit open disc
sage: c_cart_D = c_cart.restrict(D, x^2+y^2<1)
@@ -1701,7 +1795,7 @@ class RealChart(Chart):
coordinates = ""
for coord in self._xx:
coordinates += repr(coord) + ' '
- res = self.__class__(subset, coordinates)
+ res = type(self)(subset, coordinates)
res._bounds = self._bounds
res._restrictions.extend(self._restrictions)
# The coordinate restrictions are added to the result chart and
@@ -1741,7 +1835,7 @@ class RealChart(Chart):
Cartesian coordinates on a square interior::
sage: forget() # for doctest only
- sage: M = TopManifold(2, 'M') # the square interior
+ sage: M = Manifold(2, 'M', type='topological') # the square interior
sage: X.<x,y> = M.chart('x:(-2,2) y:(-2,2)')
sage: X.valid_coordinates(0,1)
True
@@ -1846,7 +1940,7 @@ class CoordChange(SageObject):
Transition map on a 2-dimensional topological manifold::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: Y.<u,v> = M.chart()
sage: X_to_Y = X.transition_map(Y, [x+y, x-y])
@@ -1865,7 +1959,7 @@ class CoordChange(SageObject):
TESTS::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: Y.<u,v> = M.chart()
sage: X_to_Y = X.transition_map(Y, [x+y, x-y])
@@ -1904,7 +1998,7 @@ class CoordChange(SageObject):
TESTS::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: Y.<u,v> = M.chart()
sage: X_to_Y = X.transition_map(Y, [x+y, x-y])
@@ -1925,7 +2019,7 @@ class CoordChange(SageObject):
TESTS::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: Y.<u,v> = M.chart()
sage: X_to_Y = X.transition_map(Y, [x+y, x-y])
@@ -1951,7 +2045,7 @@ class CoordChange(SageObject):
EXAMPLE::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: Y.<u,v> = M.chart()
sage: X_to_Y = X.transition_map(Y, [x+y, x-y])
@@ -1975,7 +2069,7 @@ class CoordChange(SageObject):
Inverse of a coordinate transformation corresponding to a pi/3-rotation
in the plane::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: c_xy.<x,y> = M.chart()
sage: c_uv.<u,v> = M.chart()
sage: xy_to_uv = c_xy.transition_map(c_uv, ((x - sqrt(3)*y)/2, (sqrt(3)*x + y)/2))
@@ -2069,7 +2163,7 @@ class CoordChange(SageObject):
"transformation; use set_inverse() to set the inverse " +
"manually")
x2_to_x1 = list_x2_to_x1[0]
- self._inverse = self.__class__(self._chart2, self._chart1, *x2_to_x1)
+ self._inverse = type(self)(self._chart2, self._chart1, *x2_to_x1)
return self._inverse
@@ -2094,7 +2188,7 @@ class CoordChange(SageObject):
From spherical coordinates to Cartesian ones in the plane::
- sage: M = TopManifold(2, 'R^2')
+ sage: M = Manifold(2, 'R^2', type='topological')
sage: U = M.open_subset('U') # the complement of the half line {y=0, x>= 0}
sage: c_cart.<x,y> = U.chart()
sage: c_spher.<r,ph> = U.chart(r'r:(0,+oo) ph:(0,2*pi):\phi')
@@ -2127,7 +2221,7 @@ class CoordChange(SageObject):
check = kwds['check']
else:
check = True
- self._inverse = self.__class__(self._chart2, self._chart1,
+ self._inverse = type(self)(self._chart2, self._chart1,
*transformations)
if check:
print "Check of the inverse coordinate transformation:"
@@ -2155,7 +2249,7 @@ class CoordChange(SageObject):
EXAMPLE::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: U.<u,v> = M.chart()
sage: X_to_U = X.transition_map(U, (x+y, x-y))
@@ -2175,7 +2269,7 @@ class CoordChange(SageObject):
"{} is different from {}".format(other._chart2,
other._chart1))
transf = self._transf(*(other._transf.expr()))
- return self.__class__(other._chart1, self._chart2, *transf)
+ return type(self)(other._chart1, self._chart2, *transf)
def restrict(self, dom1, dom2=None):
r"""
@@ -2194,7 +2288,7 @@ class CoordChange(SageObject):
EXAMPLE::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: Y.<u,v> = M.chart()
sage: X_to_Y = X.transition_map(Y, [x+y, x-y])
@@ -2217,8 +2311,8 @@ class CoordChange(SageObject):
ch2 = self._chart2.restrict(dom2)
if (ch1, ch2) in dom1.coord_changes():
return dom1.coord_changes()[(ch1,ch2)]
- return self.__class__(self._chart1.restrict(dom1),
- self._chart2.restrict(dom2), *(self._transf.expr()))
+ return type(self)(self._chart1.restrict(dom1),
+ self._chart2.restrict(dom2), *(self._transf.expr()))
def display(self):
r"""
@@ -2231,7 +2325,7 @@ class CoordChange(SageObject):
From spherical coordinates to Cartesian ones in the plane::
- sage: M = TopManifold(2, 'R^2')
+ sage: M = Manifold(2, 'R^2', type='topological')
sage: U = M.open_subset('U') # the complement of the half line {y=0, x>= 0}
sage: c_cart.<x,y> = U.chart()
sage: c_spher.<r,ph> = U.chart(r'r:(0,+oo) ph:(0,2*pi):\phi')
diff --git a/src/sage/manifolds/manifold.py b/src/sage/manifolds/manifold.py
index d9dff13..904f4e1 100644
--- a/src/sage/manifolds/manifold.py
+++ b/src/sage/manifolds/manifold.py
@@ -9,26 +9,30 @@ dimension* `n` *over K* is a topological space `M` such that
- `M` is second countable,
- every point in `M` has a neighborhood homeomorphic to `K^n`
-Topological manifolds are implemented via the class :class:`TopManifold`.
+Topological manifolds are implemented via the class :class:`TopologicalManifold`.
Open subsets of topological manifolds are also implemented via
-:class:`TopManifold`, since they are topological manifolds by themselves.
+:class:`TopologicalManifold`, since they are topological manifolds by themselves.
In the current setting, topological manifolds are mostly described by means of
charts (see :class:`~sage.manifolds.chart.Chart`).
-:class:`TopManifold` serves as a base class for more specific manifold classes.
+:class:`TopologicalManifold` serves as a base class for more specific manifold
+classes.
+
+The user interface is provided by the generic function :func:`Manifold`, with
+the argument ``type`` set to ``'topological'``.
.. RUBRIC:: Example 1: the 2-sphere as a topological manifold of dimension
2 over `\RR`
One starts by declaring `S^2` as a 2-dimensional topological manifold::
- sage: M = TopManifold(2, 'S^2')
+ sage: M = Manifold(2, 'S^2', type='topological')
sage: M
2-dimensional topological manifold S^2
Since the base topological field has not been specified in the argument list
-of ``TopManifold``, `\RR` is assumed::
+of ``Manifold``, `\RR` is assumed::
sage: M.base_field()
Real Field with 53 bits of precision
@@ -82,9 +86,9 @@ and `V`::
sage: M.declare_union(U,V)
and we provide the transition map between the charts ``stereoN`` = `(U, (x, y))`
-and ``stereoS`` = `(V, (u, v))`, denoting by W the intersection of U and V
-(W is the subset of U defined by `x^2+y^2\not=0`, as well as the subset of V
-defined by`u^2+v^2\not=0`)::
+and ``stereoS`` = `(V, (u, v))`, denoting by `W` the intersection of `U` and `V`
+(`W` is the subset of `U` defined by `x^2+y^2\not=0`, as well as the subset of
+`V` defined by `u^2+v^2\not=0`)::
sage: stereoN_to_S = stereoN.transition_map(stereoS, [x/(x^2+y^2), y/(x^2+y^2)],
....: intersection_name='W', restrictions1= x^2+y^2!=0,
@@ -143,7 +147,8 @@ Let us consider the point of coordinates (1,2) in the chart ``stereoN``::
sage: p in W
True
-The coordinates of `p` in the chart ``stereoS`` are::
+The coordinates of `p` in the chart ``stereoS`` are computed by letting
+the chart act on the point::
sage: stereoS(p)
(1/5, 2/5)
@@ -188,7 +193,7 @@ A continuous map `S^2\rightarrow \RR` (scalar field)::
We declare the Riemann sphere `\CC^*` as a 1-dimensional topological manifold
over `\CC`::
- sage: M = TopManifold(1, 'C*', field='complex'); M
+ sage: M = Manifold(1, 'C*', type='topological', field='complex'); M
Complex 1-dimensional topological manifold C*
We introduce a first open subset, which is actually
@@ -297,10 +302,10 @@ from sage.categories.fields import Fields
from sage.categories.manifolds import Manifolds
from sage.rings.all import CC
from sage.rings.real_mpfr import RR
-from sage.manifolds.subset import TopManifoldSubset
+from sage.manifolds.subset import TopologicalManifoldSubset
from sage.manifolds.scalarfield_algebra import ScalarFieldAlgebra
-class TopManifold(TopManifoldSubset):
+class TopologicalManifold(TopologicalManifoldSubset):
r"""
Topological manifold over a topological field `K`.
@@ -313,7 +318,7 @@ class TopManifold(TopManifoldSubset):
- every point in `M` has a neighborhood homeomorphic to `K^n`
This is a Sage *parent* class, the corresponding *element*
- class being :class:`~sage.manifolds.point.TopManifoldPoint`.
+ class being :class:`~sage.manifolds.point.TopologicalManifoldPoint`.
INPUT:
@@ -345,11 +350,13 @@ class TopManifold(TopManifoldSubset):
A 4-dimensional topological manifold (over `\RR`)::
- sage: M = TopManifold(4, 'M', latex_name=r'\mathcal{M}')
+ sage: M = Manifold(4, 'M', latex_name=r'\mathcal{M}', type='topological')
sage: M
4-dimensional topological manifold M
sage: latex(M)
\mathcal{M}
+ sage: type(M)
+ <class 'sage.manifolds.manifold.TopologicalManifold_with_category'>
sage: M.base_field()
Real Field with 53 bits of precision
sage: dim(M)
@@ -358,28 +365,28 @@ class TopManifold(TopManifoldSubset):
The input parameter ``start_index`` defines the range of indices on the
manifold::
- sage: M = TopManifold(4, 'M')
+ sage: M = Manifold(4, 'M', type='topological')
sage: list(M.irange())
[0, 1, 2, 3]
- sage: M = TopManifold(4, 'M', start_index=1)
+ sage: M = Manifold(4, 'M', type='topological', start_index=1)
sage: list(M.irange())
[1, 2, 3, 4]
- sage: list(TopManifold(4, 'M', start_index=-2).irange())
+ sage: list(Manifold(4, 'M', type='topological', start_index=-2).irange())
[-2, -1, 0, 1]
A complex manifold::
- sage: N = TopManifold(3, 'N', field='complex'); N
+ sage: N = Manifold(3, 'N', type='topological', field='complex'); N
Complex 3-dimensional topological manifold N
A manifold over `\QQ`::
- sage: N = TopManifold(6, 'N', field=QQ); N
+ sage: N = Manifold(6, 'N', type='topological', field=QQ); N
6-dimensional topological manifold N over the Rational Field
A manifold over `\QQ_5`, the field of 5-adic numbers::
- sage: N = TopManifold(2, 'N', field=Qp(5)); N
+ sage: N = Manifold(2, 'N', type='topological', field=Qp(5)); N
2-dimensional topological manifold N over the 5-adic Field with capped
relative precision 20
@@ -414,27 +421,18 @@ class TopManifold(TopManifoldSubset):
True
The manifold's points are instances of class
- :class:`~sage.manifolds.point.TopManifoldPoint`::
-
- sage: isinstance(p, sage.manifolds.point.TopManifoldPoint)
- True
-
- Manifolds are unique, as long as they are created with the same arguments::
+ :class:`~sage.manifolds.point.TopologicalManifoldPoint`::
- sage: M is TopManifold(4, 'M', start_index=1)
+ sage: isinstance(p, sage.manifolds.point.TopologicalManifoldPoint)
True
- sage: M is TopManifold(4, 'M')
- False
- sage: M is TopManifold(4, 'M', latex_name='M', start_index=1)
- False
Since an open subset of a topological manifold `M` is itself a topological
manifold, open subsets of `M` are instances of the class
- :class:`TopManifold`::
+ :class:`TopologicalManifold`::
sage: U = M.open_subset('U'); U
Open subset U of the 4-dimensional topological manifold M
- sage: isinstance(U, sage.manifolds.manifold.TopManifold)
+ sage: isinstance(U, sage.manifolds.manifold.TopologicalManifold)
True
sage: U.base_field() == M.base_field()
True
@@ -454,7 +452,8 @@ class TopManifold(TopManifoldSubset):
TESTS::
- sage: M = TopManifold(3, 'M', latex_name=r'\mathbb{M}', start_index=1)
+ sage: M = Manifold(3, 'M', latex_name=r'\mathbb{M}',
+ ....: type='topological', start_index=1)
sage: M
3-dimensional topological manifold M
sage: latex(M)
@@ -488,12 +487,12 @@ class TopManifold(TopManifoldSubset):
category = Manifolds(self._field)
if ambient_manifold is None:
ambient_manifold = self
- elif not isinstance(ambient_manifold, TopManifold):
+ elif not isinstance(ambient_manifold, TopologicalManifold):
raise TypeError("the argument 'ambient_manifold' must be " +
"a topological manifold")
# Initialization as a subset of the ambient manifold (possibly itself):
- TopManifoldSubset.__init__(self, ambient_manifold, name,
- latex_name=latex_name, category=category)
+ TopologicalManifoldSubset.__init__(self, ambient_manifold, name,
+ latex_name=latex_name, category=category)
self._is_open = True
self._open_covers = [[self]] # list of open covers of self
self._atlas = [] # list of charts defined on subsets of self
@@ -517,17 +516,17 @@ class TopManifold(TopManifoldSubset):
TESTS::
- sage: M = TopManifold(3, 'M')
+ sage: M = Manifold(3, 'M', type='topological')
sage: M._repr_()
'3-dimensional topological manifold M'
sage: repr(M) # indirect doctest
'3-dimensional topological manifold M'
sage: M # indirect doctest
3-dimensional topological manifold M
- sage: M = TopManifold(3, 'M', field='complex')
+ sage: M = Manifold(3, 'M', type='topological', field='complex')
sage: M._repr_()
'Complex 3-dimensional topological manifold M'
- sage: M = TopManifold(3, 'M', field=QQ)
+ sage: M = Manifold(3, 'M', type='topological', field=QQ)
sage: M._repr_()
'3-dimensional topological manifold M over the Rational Field'
@@ -558,12 +557,13 @@ class TopManifold(TopManifoldSubset):
TESTS::
- sage: M = TopManifold(3, 'M')
+ sage: M = Manifold(3, 'M', type='topological')
sage: M._latex_()
'M'
sage: latex(M)
M
- sage: M = TopManifold(3, 'M', latex_name=r'\mathcal{M}')
+ sage: M = Manifold(3, 'M', latex_name=r'\mathcal{M}',
+ ....: type='topological')
sage: M._latex_()
'\\mathcal{M}'
sage: latex(M)
@@ -572,13 +572,83 @@ class TopManifold(TopManifoldSubset):
"""
return self._latex_name
+ def __reduce__(self):
+ r"""
+ Reduction function for the pickle protocole.
+
+ TESTS::
+
+ sage: M = Manifold(3, 'M', type='topological')
+ sage: M.__reduce__()
+ (<class 'sage.manifolds.manifold.TopologicalManifold'>,
+ (3,
+ 'M',
+ 'M',
+ Real Field with 53 bits of precision,
+ 0,
+ Category of manifolds over Real Field with 53 bits of precision,
+ None))
+ sage: U = M.open_subset('U')
+ sage: U.__reduce__()
+ (<class 'sage.manifolds.manifold.TopologicalManifold'>,
+ (3,
+ 'U',
+ 'U',
+ Real Field with 53 bits of precision,
+ 0,
+ Category of facade manifolds over Real Field with 53 bits of precision,
+ 3-dimensional topological manifold M))
+
+ Tests of pickling::
+
+ sage: loads(dumps(M))
+ 3-dimensional topological manifold M
+ sage: loads(dumps(U))
+ Open subset U of the 3-dimensional topological manifold M
+
+ """
+ if self._manifold is self:
+ ambient_manifold = None
+ else:
+ ambient_manifold = self._manifold
+ return (TopologicalManifold, (self._dim, self._name, self._latex_name,
+ self._field, self._sindex,
+ self.category(), ambient_manifold))
+
+ def _test_pickling(self, **options):
+ r"""
+ Test pickling.
+
+ This test is weaker than
+ :meth:`sage.structure.sage_object.SageObject._test_pickling` in that
+ it does not require ``loads(dumps(self)) == self``.
+ It however checks that ``loads(dumps(self))`` proceeds without any
+ error and results in an object that is a manifold of the same type as
+ ``self``, with some identical characteristics (dimension, name).
+
+ TESTS::
+
+ sage: M = Manifold(3, 'M', type='topological')
+ sage: M._test_pickling()
+ sage: M = Manifold(3, 'M', type='topological', field='complex')
+ sage: M._test_pickling()
+
+ """
+ tester = self._tester(**options)
+ from sage.misc.all import loads, dumps
+ bckp = loads(dumps(self))
+ tester.assertEqual(type(bckp), type(self))
+ tester.assertEqual(bckp.category(), self.category())
+ tester.assertEqual(bckp._dim, self._dim)
+ tester.assertEqual(bckp._name, self._name)
+
def _an_element_(self):
r"""
Construct some point on the manifold.
EXAMPLES::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: p = M._an_element_(); p
Point on the 2-dimensional topological manifold M
@@ -675,7 +745,7 @@ class TopManifold(TopManifoldSubset):
EXAMPLES::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: p = M.point((1,2), chart=X)
sage: M.__contains__(p)
@@ -716,7 +786,7 @@ class TopManifold(TopManifoldSubset):
EXAMPLE::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: M.dimension()
2
@@ -745,13 +815,13 @@ class TopManifold(TopManifoldSubset):
EXAMPLES::
- sage: M = TopManifold(3, 'M')
+ sage: M = Manifold(3, 'M', type='topological')
sage: M.base_field()
Real Field with 53 bits of precision
- sage: M = TopManifold(3, 'M', field='complex')
+ sage: M = Manifold(3, 'M', type='topological', field='complex')
sage: M.base_field()
Complex Field with 53 bits of precision
- sage: M = TopManifold(3, 'M', field=QQ)
+ sage: M = Manifold(3, 'M', type='topological', field=QQ)
sage: M.base_field()
Rational Field
@@ -773,10 +843,10 @@ class TopManifold(TopManifoldSubset):
EXAMPLES::
- sage: M = TopManifold(3, 'M')
+ sage: M = Manifold(3, 'M', type='topological')
sage: M.start_index()
0
- sage: M = TopManifold(3, 'M', start_index=1)
+ sage: M = Manifold(3, 'M', type='topological', start_index=1)
sage: M.start_index()
1
@@ -802,7 +872,7 @@ class TopManifold(TopManifoldSubset):
Index range on a 4-dimensional manifold::
- sage: M = TopManifold(4, 'M')
+ sage: M = Manifold(4, 'M', type='topological')
sage: for i in M.irange():
....: print i,
....:
@@ -816,7 +886,7 @@ class TopManifold(TopManifoldSubset):
Index range on a 4-dimensional manifold with starting index=1::
- sage: M = TopManifold(4, 'M', start_index=1)
+ sage: M = Manifold(4, 'M', type='topological', start_index=1)
sage: for i in M.irange():
....: print i,
....:
@@ -859,7 +929,7 @@ class TopManifold(TopManifoldSubset):
Indices on a 2-dimensional manifold::
- sage: M = TopManifold(2, 'M', start_index=1)
+ sage: M = Manifold(2, 'M', type='topological', start_index=1)
sage: for ind in M.index_generator(2):
....: print ind
....:
@@ -907,23 +977,42 @@ class TopManifold(TopManifoldSubset):
EXAMPLES:
- Charts on subsets of `\RR^2`::
+ Let us consider `\RR^2` as a 2-dimensional manifold::
- sage: M = TopManifold(2, 'R^2')
- sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
+ sage: M = Manifold(2, 'R^2', type='topological')
+
+ Immediately after the manifold creation, the atlas is empty, since no
+ chart has been defined yet::
+
+ sage: M.atlas()
+ []
+
+ Let us introduce the chart of Cartesian coordinates::
+
+ sage: c_cart.<x,y> = M.chart()
sage: M.atlas()
[Chart (R^2, (x, y))]
- sage: U = M.open_subset('U', coord_def={c_cart: (y!=0,x<0)}) # U = R^2 \ half line {y=0,x>=0}
+
+ The complement of the half line `\{y=0,\; x\geq 0\}`::
+
+ sage: U = M.open_subset('U', coord_def={c_cart: (y!=0,x<0)})
sage: U.atlas()
[Chart (U, (x, y))]
sage: M.atlas()
[Chart (R^2, (x, y)), Chart (U, (x, y))]
- sage: c_spher.<r, ph> = U.chart(r'r:(0,+oo) ph:(0,2*pi):\phi') # spherical (polar) coordinates on U
+
+ Spherical (polar) coordinates on `U`::
+
+ sage: c_spher.<r, ph> = U.chart(r'r:(0,+oo) ph:(0,2*pi):\phi')
sage: U.atlas()
[Chart (U, (x, y)), Chart (U, (r, ph))]
sage: M.atlas()
[Chart (R^2, (x, y)), Chart (U, (x, y)), Chart (U, (r, ph))]
+ .. SEEALSO::
+
+ :meth:`top_charts`
+
"""
return self._atlas
@@ -941,20 +1030,24 @@ class TopManifold(TopManifoldSubset):
Charts on a 2-dimensional manifold::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: U = M.open_subset('U', coord_def={X: x>0})
sage: Y.<u,v> = U.chart()
sage: M.top_charts()
[Chart (M, (x, y)), Chart (U, (u, v))]
- Note that the (user) atlas contains one more chart: (U, (x,y)), which
- is not a "top" chart::
+ Note that the (user) atlas contains one more chart: ``(U, (x,y))``,
+ which is not a "top" chart::
sage: M.atlas()
[Chart (M, (x, y)), Chart (U, (x, y)), Chart (U, (u, v))]
+ .. SEEALSO::
+
+ :meth:`atlas` for the complete list of charts defined on the
+ manifold.
+
"""
return self._top_charts
@@ -974,8 +1067,7 @@ class TopManifold(TopManifoldSubset):
Default chart on a 2-dimensional manifold and on some subsets::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: M.chart('x y')
Chart (M, (x, y))
sage: M.chart('u v')
@@ -1003,8 +1095,7 @@ class TopManifold(TopManifoldSubset):
Charts on a 2-dimensional manifold::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: c_xy.<x,y> = M.chart()
sage: c_uv.<u,v> = M.chart()
sage: M.default_chart()
@@ -1049,13 +1140,12 @@ class TopManifold(TopManifoldSubset):
Change of coordinates on a 2-dimensional manifold::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: c_xy.<x,y> = M.chart()
sage: c_uv.<u,v> = M.chart()
- sage: c_xy.transition_map(c_uv, (x+y, x-y)) # defines the coordinate change
+ sage: c_xy.transition_map(c_uv, (x+y, x-y)) # defines the coord. change
Change of coordinates from Chart (M, (x, y)) to Chart (M, (u, v))
- sage: M.coord_change(c_xy, c_uv) # returns the coordinate change defined above
+ sage: M.coord_change(c_xy, c_uv) # returns the coord. change defined above
Change of coordinates from Chart (M, (x, y)) to Chart (M, (u, v))
"""
@@ -1078,8 +1168,7 @@ class TopManifold(TopManifoldSubset):
Various changes of coordinates on a 2-dimensional manifold::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: c_xy.<x,y> = M.chart()
sage: c_uv.<u,v> = M.chart()
sage: xy_to_uv = c_xy.transition_map(c_uv, [x+y, x-y])
@@ -1125,8 +1214,7 @@ class TopManifold(TopManifoldSubset):
EXAMPLES::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: U = M.open_subset('U')
sage: X.<x,y> = U.chart()
sage: U.is_manifestly_coordinate_domain()
@@ -1147,7 +1235,7 @@ class TopManifold(TopManifoldSubset):
An open subset is a set that is (i) included in the manifold and (ii)
open with respect to the manifold's topology. It is a topological
manifold by itself. Hence the returned object is an instance of
- :class:`TopManifold`.
+ :class:`TopologicalManifold`.
INPUT:
@@ -1161,14 +1249,13 @@ class TopManifold(TopManifoldSubset):
OUTPUT:
- - the open subset, as an instance of :class:`TopManifold`.
+ - the open subset, as an instance of :class:`TopologicalManifold`.
EXAMPLES:
Creating an open subset of a 2-dimensional manifold::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: A = M.open_subset('A'); A
Open subset A of the 2-dimensional topological manifold M
@@ -1176,7 +1263,7 @@ class TopManifold(TopManifoldSubset):
topological manifold, on the same topological field and of the same
dimension as ``M``::
- sage: isinstance(A, sage.manifolds.manifold.TopManifold)
+ sage: isinstance(A, sage.manifolds.manifold.TopologicalManifold)
True
sage: A.base_field() == M.base_field()
True
@@ -1201,7 +1288,7 @@ class TopManifold(TopManifoldSubset):
Defining an open subset by some coordinate restrictions: the open
unit disk in `\RR^2`::
- sage: M = TopManifold(2, 'R^2')
+ sage: M = Manifold(2, 'R^2', type='topological')
sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
sage: U = M.open_subset('U', coord_def={c_cart: x^2+y^2<1}); U
Open subset U of the 2-dimensional topological manifold R^2
@@ -1223,16 +1310,17 @@ class TopManifold(TopManifoldSubset):
False
"""
- resu = TopManifold(self._dim, name, latex_name=latex_name,
+ resu = TopologicalManifold(self._dim, name, latex_name=latex_name,
field=self._field, start_index=self._sindex,
category=self.category(),
ambient_manifold=self._manifold)
#!# NB: the above could have been
- # resu = type(self).__base__(...) instead of resu = TopManifold(...)
+ # resu = type(self).__base__(...)
+ # instead of resu = TopologicalManifold(...)
# to allow for open_subset() of derived classes to call first this
# version,
# but, because of the category framework, it could NOT have been
- # resu = self.__class__(...)
+ # resu = type(self)(...)
# cf. the discussion in
# https://groups.google.com/forum/#!topic/sage-devel/jHlFxhMDf3Y
resu._supersets.update(self._supersets)
@@ -1313,8 +1401,7 @@ class TopManifold(TopManifoldSubset):
Chart on a 2-dimensional manifold::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: U = M.open_subset('U')
sage: X = U.chart('x y'); X
Chart (U, (x, y))
@@ -1344,8 +1431,7 @@ class TopManifold(TopManifoldSubset):
left-hand side of the chart declaration (there is then no need to
pass the string 'x y' to chart())::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: U = M.open_subset('U')
sage: X.<x,y> = U.chart(); X
Chart (U, (x, y))
@@ -1608,3 +1694,147 @@ class TopManifold(TopManifoldSubset):
"""
return self._one_scalar_field
+
+
+def Manifold(dim, name, latex_name=None, field='real', type='smooth',
+ start_index=0, **extra_kwds):
+ r"""
+ Construct a manifold of a given type over a topological field `K`.
+
+ INPUT:
+
+ - ``dim`` -- positive integer; dimension of the manifold
+ - ``name`` -- string; name (symbol) given to the manifold
+ - ``latex_name`` -- (default: ``None``) string; LaTeX symbol to denote the
+ manifold; if none is provided, it is set to ``name``
+ - ``field`` -- (default: ``'real'``) field `K` on which the manifold is
+ defined; allowed values are
+
+ - ``'real'`` or ``RR`` for a manifold over `\RR`
+ - ``'complex'`` or ``CC`` for a manifold over `\CC`
+ - an object in the category of topological fields (see
+ :class:`~sage.categories.fields.Fields` and
+ :class:`~sage.categories.topological_spaces.TopologicalSpaces`)
+ for other types of manifolds
+
+ - ``type`` -- (default: ``'smooth'``) to specify the type of manifold;
+ allowed values are
+
+ - ``'topological'`` or ``'top'`` for a topological manifold
+ - ``'differentiable'`` or ``'diff'`` for a differentiable manifold
+ - ``'smooth'`` for a smooth manifold
+ - ``'analytic'`` for an analytic manifold
+
+ - ``start_index`` -- (default: 0) integer; lower value of the range of
+ indices used for "indexed objects" on the manifold, e.g. coordinates
+ in a chart
+ - ``extra_kwds`` -- keywords meaningful only for some specific types of
+ manifolds
+
+ OUTPUT:
+
+ - a manifold of the specified type, as an instance of
+ :class:`~sage.manifolds.manifold.TopologicalManifold` or one of its
+ subclasses.
+
+ EXAMPLES:
+
+ A 3-dimensional real topological manifold::
+
+ sage: M = Manifold(3, 'M', type='topological'); M
+ 3-dimensional topological manifold M
+
+ Given the default value of the parameter ``field``, the above is equivalent
+ to::
+
+ sage: M = Manifold(3, 'M', type='topological', field='real'); M
+ 3-dimensional topological manifold M
+
+ A complex topological manifold::
+
+ sage: M = Manifold(3, 'M', type='topological', field='complex'); M
+ Complex 3-dimensional topological manifold M
+
+ A topological manifold over `\QQ`::
+
+ sage: M = Manifold(3, 'M', type='topological', field=QQ); M
+ 3-dimensional topological manifold M over the Rational Field
+
+ See the documentation of class
+ :class:`~sage.manifolds.manifold.TopologicalManifold` for more
+ detailed examples.
+
+ .. RUBRIC:: Uniqueness of manifold objects
+
+ Suppose we construct a manifold named `M`::
+
+ sage: M = Manifold(2, 'M', type='topological')
+ sage: X.<x,y> = M.chart()
+
+ At some point, we change our mind and would like to restart with a new
+ manifold, using the same name `M` and keeping the previous manifold for
+ reference::
+
+ sage: M_old = M # for reference
+ sage: M = Manifold(2, 'M', type='topological')
+
+ This results in a brand new object::
+
+ sage: M.atlas()
+ []
+
+ The object ``M_old`` is intact::
+
+ sage: M_old.atlas()
+ [Chart (M, (x, y))]
+
+ Both objects have the same display::
+
+ sage: M
+ 2-dimensional topological manifold M
+ sage: M_old
+ 2-dimensional topological manifold M
+
+ but they are different::
+
+ sage: M != M_old
+ True
+
+ Let us introduce a chart on ``M``, using the same coordinate symbols as
+ for ``M_old``::
+
+ sage: X.<x,y> = M.chart()
+
+ The charts are displayed in the same way::
+
+ sage: M.atlas()
+ [Chart (M, (x, y))]
+ sage: M_old.atlas()
+ [Chart (M, (x, y))]
+
+ but they are actually different::
+
+ sage: M.atlas()[0] != M_old.atlas()[0]
+ True
+
+ Moreover, the two manifolds ``M`` and ``M_old`` are still considered
+ distinct::
+
+ sage: M != M_old
+ True
+
+ This reflects the fact that the equality of manifold objects holds only
+ for identical objects, i.e. one has ``M1 == M2`` if, and only if,
+ ``M1 is M2``. Actually, the manifold classes inherit from
+ :class:`~sage.misc.fast_methods.WithEqualityById`::
+
+ sage: isinstance(M, sage.misc.fast_methods.WithEqualityById)
+ True
+
+ """
+ type_ = type # in case the built-in function type is to be restored...
+ if type_ in ['topological', 'top']:
+ return TopologicalManifold(dim, name, latex_name=latex_name,
+ field=field, start_index=start_index)
+ raise NotImplementedError("manifolds of type {} are not ".format(type_) +
+ "implemented")
diff --git a/src/sage/manifolds/point.py b/src/sage/manifolds/point.py
index 3e4ce31..25c8adc 100644
--- a/src/sage/manifolds/point.py
+++ b/src/sage/manifolds/point.py
@@ -1,9 +1,9 @@
r"""
Points of topological manifolds
-The class :class:`TopManifoldPoint` implements points of a
+The class :class:`TopologicalManifoldPoint` implements points of a
topological manifold.
-A :class:`TopManifoldPoint` object can have coordinates in
+A :class:`TopologicalManifoldPoint` object can have coordinates in
various charts defined on the manifold. Two points are declared equal if they
have the same coordinates in the same chart.
@@ -22,7 +22,7 @@ EXAMPLES:
Defining a point in `\RR^3` by its spherical coordinates::
- sage: M = TopManifold(3, 'R^3')
+ sage: M = Manifold(3, 'R^3', type='topological')
sage: U = M.open_subset('U') # the complement of the half-plane (y=0, x>=0)
sage: c_spher.<r,th,ph> = U.chart(r'r:(0,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi')
sage: p = U((1, pi/2, pi), name='P') # coordinates in U's default chart (c_spher)
@@ -70,12 +70,12 @@ Points can be compared::
from sage.structure.element import Element
-class TopManifoldPoint(Element):
+class TopologicalManifoldPoint(Element):
r"""
Point of a topological manifold.
This is a Sage *element* class, the corresponding *parent* class being
- :class:`~sage.manifolds.manifold.TopManifold`.
+ :class:`~sage.manifolds.manifold.TopologicalManifold`.
INPUT:
@@ -97,7 +97,7 @@ class TopManifoldPoint(Element):
A point on a 2-dimensional manifold::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: c_xy.<x,y> = M.chart()
sage: (a, b) = var('a b') # generic coordinates for the point
sage: p = M.point((a, b), name='P'); p
@@ -154,8 +154,7 @@ class TopManifoldPoint(Element):
TESTS::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: p = M((2,3), name='p'); p
Point p on the 2-dimensional topological manifold M
@@ -203,7 +202,7 @@ class TopManifoldPoint(Element):
TESTS::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: p = M((2,-3))
sage: p._repr_()
@@ -227,7 +226,7 @@ class TopManifoldPoint(Element):
TESTS::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: p = M((2,-3))
sage: p._latex_()
@@ -257,14 +256,13 @@ class TopManifoldPoint(Element):
OUTPUT:
- an instance of
- :class:`~sage.manifolds.subset.TopManifoldSubset`
+ :class:`~sage.manifolds.subset.TopologicalManifoldSubset`
EXAMPLES:
Points on a 2-dimensional manifold::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: p = M.point((1,3), name='p'); p
Point p on the 2-dimensional topological manifold M
@@ -314,8 +312,7 @@ class TopManifoldPoint(Element):
Spherical coordinates of a point on `\RR^3`::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(3, 'M') # the part of R^3 covered by spherical coordinates
+ sage: M = Manifold(3, 'M', type='topological') # the part of R^3 covered by spherical coordinates
sage: c_spher.<r,th,ph> = M.chart(r'r:(0,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi') # spherical coordinates
sage: p = M.point((1, pi/2, pi))
sage: p.coord() # coordinates on the manifold's default chart
@@ -342,8 +339,7 @@ class TopManifoldPoint(Element):
Coordinates of a point on a 2-dimensional manifold::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: c_xy.<x,y> = M.chart()
sage: (a, b) = var('a b') # generic coordinates for the point
sage: p = M.point((a, b), name='P')
@@ -462,7 +458,7 @@ class TopManifoldPoint(Element):
Setting coordinates to a point on a 2-dimensional manifold::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: p = M.point()
sage: p.set_coord((2,-3)) # coordinates on the manifold's default chart
@@ -513,7 +509,7 @@ class TopManifoldPoint(Element):
Setting coordinates to a point on a 2-dimensional manifold::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: p = M.point()
sage: p.add_coord((2,-3)) # coordinates on the manifold's default chart
@@ -561,7 +557,7 @@ class TopManifoldPoint(Element):
Comparison with coordinates in the same chart::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: p = M((2,-3), chart=X)
sage: q = M((2,-3), chart=X)
@@ -596,14 +592,19 @@ class TopManifoldPoint(Element):
False
"""
- if not isinstance(other, TopManifoldPoint):
+ if other is self:
+ return True
+ if not isinstance(other, TopologicalManifoldPoint):
return False
if other._manifold != self._manifold:
return False
# Search for a common chart to compare the coordinates
common_chart = None
# the subset's default chart is privileged:
- def_chart = self._subset._def_chart
+ if hasattr(self._subset, '_def_chart'): # self._subset is open
+ def_chart = self._subset._def_chart
+ else:
+ def_chart = self._manifold._def_chart
if def_chart in self._coordinates and def_chart in other._coordinates:
common_chart = def_chart
else:
@@ -636,7 +637,7 @@ class TopManifoldPoint(Element):
# raise ValueError("no common chart has been found to compare " +
# "{} and {}".format(self, other))
return self._coordinates[common_chart] == \
- other._coordinates[common_chart]
+ other._coordinates[common_chart]
def __ne__(self, other):
r"""
@@ -644,7 +645,7 @@ class TopManifoldPoint(Element):
TESTS::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: p = M((2,-3), chart=X)
sage: q = M((0,1), chart=X)
@@ -654,7 +655,7 @@ class TopManifoldPoint(Element):
False
"""
- return not self.__eq__(other)
+ return not (self == other)
def __cmp__(self, other):
r"""
@@ -664,7 +665,7 @@ class TopManifoldPoint(Element):
TESTS::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: p = M((2,-3), chart=X)
sage: q = M((2,-3), chart=X)
@@ -675,7 +676,7 @@ class TopManifoldPoint(Element):
-1
"""
- if self.__eq__(other):
+ if self == other:
return 0
else:
return -1
@@ -690,13 +691,36 @@ class TopManifoldPoint(Element):
TESTS::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: p = M((2,-3), chart=X)
- sage: p.__hash__() # random
+ sage: hash(p) # random
8791657334475
- sage: p.__hash__() == hash(M)
+ sage: hash(p) == hash(M)
True
"""
- return self._manifold.__hash__()
+ return hash(self._manifold)
+
+ def _test_pickling(self, **options):
+ r"""
+ Test pickling.
+
+ This test is weaker than
+ :meth:`sage.structure.sage_object.SageObject._test_pickling` in that
+ it does not require ``loads(dumps(self)) == self``.
+ It however checks that ``loads(dumps(self))`` proceeds without any
+ error and results in an object that is a manifold point.
+
+ TESTS::
+
+ sage: M = Manifold(2, 'M', type='topological')
+ sage: X.<x,y> = M.chart()
+ sage: p = M((1,2), chart=X)
+ sage: p._test_pickling()
+
+ """
+ tester = self._tester(**options)
+ from sage.misc.all import loads, dumps
+ bckp = loads(dumps(self))
+ tester.assertEqual(type(bckp), type(self))
diff --git a/src/sage/manifolds/subset.py b/src/sage/manifolds/subset.py
index d488883..8df3d34 100644
--- a/src/sage/manifolds/subset.py
+++ b/src/sage/manifolds/subset.py
@@ -1,11 +1,11 @@
r"""
Subsets of topological manifolds
-The class :class:`TopManifoldSubset` implements generic subsets of a
+The class :class:`TopologicalManifoldSubset` implements generic subsets of a
topological manifold. Open subsets are implemented by the class
-:class:`~sage.manifolds.manifold.TopManifold` (since an open subset of a
-manifold is a manifold by itself), which inherits from
-:class:`TopManifoldSubset`.
+:class:`~sage.manifolds.manifold.TopologicalManifold` (since an open subset of
+a manifold is a manifold by itself), which inherits from
+:class:`TopologicalManifoldSubset`.
AUTHORS:
@@ -20,7 +20,7 @@ EXAMPLES:
Two subsets on a manifold::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: a = M.subset('A'); a
Subset A of the 2-dimensional topological manifold M
sage: b = M.subset('B'); b
@@ -71,28 +71,27 @@ Lists of subsets after the above operations::
#*****************************************************************************
from sage.structure.parent import Parent
-from sage.structure.unique_representation import UniqueRepresentation
+from sage.misc.fast_methods import WithEqualityById
from sage.categories.sets_cat import Sets
-from sage.categories.homset import Hom
-from sage.rings.infinity import Infinity
-from sage.manifolds.point import TopManifoldPoint
+from sage.manifolds.point import TopologicalManifoldPoint
-class TopManifoldSubset(UniqueRepresentation, Parent):
+class TopologicalManifoldSubset(WithEqualityById, Parent):
r"""
Subset of a topological manifold.
- The class :class:`TopManifoldSubset` inherits from the generic Sage class
- :class:`~sage.structure.parent.Parent` and is declared to belong to
+ The class :class:`TopologicalManifoldSubset` inherits from the generic Sage
+ class :class:`~sage.structure.parent.Parent` and is declared to belong to
the category of facade sets
(see :meth:`~sage.categories.sets_cat.Sets.SubcategoryMethods.Facade`).
The corresponding element class is
- :class:`~sage.manifolds.point.TopManifoldPoint`. A subset acts
+ :class:`~sage.manifolds.point.TopologicalManifoldPoint`. A subset acts
as a facade for the true parent of its points, which is the whole manifold
(see example below).
Note that open subsets are not implemented directly by this class, but
- by the derived class :class:`~sage.manifolds.manifold.TopManifold` (an
- open subset of a topological manifold being itself a topological manifold).
+ by the derived class :class:`~sage.manifolds.manifold.TopologicalManifold`
+ (an open subset of a topological manifold being itself a topological
+ manifold).
INPUT:
@@ -107,18 +106,19 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
A subset of a manifold::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
- sage: from sage.manifolds.subset import TopManifoldSubset
- sage: A = TopManifoldSubset(M, 'A', latex_name=r'\mathcal{A}'); A
+ sage: M = Manifold(2, 'M', type='topological')
+ sage: from sage.manifolds.subset import TopologicalManifoldSubset
+ sage: A = TopologicalManifoldSubset(M, 'A', latex_name=r'\mathcal{A}')
+ sage: A
Subset A of the 2-dimensional topological manifold M
sage: latex(A)
\mathcal{A}
sage: A.is_subset(M)
True
- Instead of importing :class:`TopManifoldSubset` in the global namespace,
- it is recommended to use the method :meth:`subset` to create a new subset::
+ Instead of importing :class:`TopologicalManifoldSubset` in the global
+ namespace, it is recommended to use the method :meth:`subset` to create a
+ new subset::
sage: B = M.subset('B', latex_name=r'\mathcal{B}'); B
Subset B of the 2-dimensional topological manifold M
@@ -129,13 +129,13 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
The manifold is itself a subset::
- sage: isinstance(M, TopManifoldSubset)
+ sage: isinstance(M, TopologicalManifoldSubset)
True
- Instances of :class:`TopManifoldSubset` are Sage's facade sets
+ Instances of :class:`TopologicalManifoldSubset` are Sage's facade sets
(see :meth:`~sage.categories.sets_cat.Sets.SubcategoryMethods.Facade`):
their elements are manifold points
- (class :class:`~sage.manifolds.point.TopManifoldPoint`),
+ (class :class:`~sage.manifolds.point.TopologicalManifoldPoint`),
which have the manifold (and not the subset) as parent::
sage: isinstance(A, Parent)
@@ -155,7 +155,7 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
"""
- Element = TopManifoldPoint
+ Element = TopologicalManifoldPoint
def __init__(self, manifold, name, latex_name=None, category=None):
r"""
@@ -163,15 +163,12 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
TESTS::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: A = M.subset('A'); A
Subset A of the 2-dimensional topological manifold M
"""
- if not isinstance(name, str):
- raise TypeError("{} is not a string".format(name))
if category is None:
base = None
category = Sets()
@@ -183,13 +180,9 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
else:
Parent.__init__(self, base=base, category=category,
facade=manifold)
- for dom in manifold._subsets:
- if name == dom._name:
- raise ValueError("the name '" + name +
- "' is already used for another " +
- "subset of the {}".format(manifold))
- manifold._subsets.add(self)
self._manifold = manifold
+ if not isinstance(name, str):
+ raise TypeError("{} is not a string".format(name))
self._name = name
if latex_name is None:
self._latex_name = self._name
@@ -197,6 +190,13 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
if not isinstance(latex_name, str):
raise TypeError("{} is not a string".format(latex_name))
self._latex_name = latex_name
+ if self is not self._manifold:
+ for dom in manifold._subsets:
+ if name == dom._name:
+ raise ValueError("the name '" + name +
+ "' is already used for another " +
+ "subset of the {}".format(manifold))
+ manifold._subsets.add(self)
self._supersets = set([manifold, self]) # subsets containing self
self._subsets = set([self]) # subsets of self
self._top_subsets = set([self]) # subsets contained in self but not
@@ -232,16 +232,14 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
OUTPUT:
- - an instance of :class:`~sage.manifolds.point.TopManifoldPoint`
+ - an instance of :class:`~sage.manifolds.point.TopologicalManifoldPoint`
representing a point in the current subset.
EXAMPLES::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
- sage: p = M._element_constructor_(); p
- Point on the 2-dimensional topological manifold M
- sage: p = M._element_constructor_((-2,3)); p # coord in the default chart
+ sage: p = M((-2,3)); p # coord in the default chart
Point on the 2-dimensional topological manifold M
sage: X(p)
(-2, 3)
@@ -249,7 +247,7 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
A generic subset has no default chart, so the chart must be explicited::
sage: A = M.subset('A')
- sage: p = A._element_constructor_((-2,3), chart=X); p
+ sage: p = A((-2,3), chart=X); p
Point on the 2-dimensional topological manifold M
sage: X(p)
(-2, 3)
@@ -261,34 +259,33 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
Coordinates in a chart with some coordinate restrictions::
sage: Y.<u,v> = M.chart('u:(-1,1) v:(-1,1)')
- sage: p = A._element_constructor_((0,1/2), chart=Y); p
+ sage: p = A((0,1/2), chart=Y); p
Point on the 2-dimensional topological manifold M
sage: Y(p)
(0, 1/2)
- sage: p = A._element_constructor_((0,1/2), chart=Y,
- ....: check_coords=False); p
+ sage: p = A((0,1/2), chart=Y, check_coords=False); p
Point on the 2-dimensional topological manifold M
sage: Y(p)
(0, 1/2)
- sage: p = A._element_constructor_((3,1/2), chart=Y)
+ sage: p = A((3,1/2), chart=Y)
Traceback (most recent call last):
...
ValueError: the coordinates (3, 1/2) are not valid on the Chart (M, (u, v))
Specifying the name of the point::
- sage: p = A._element_constructor_((-2,3), chart=X, name='p'); p
+ sage: p = A((-2,3), chart=X, name='p'); p
Point p on the 2-dimensional topological manifold M
A point as entry::
- sage: q = A._element_constructor_(p); q
+ sage: q = A(p); q
Point p on the 2-dimensional topological manifold M
sage: X(q)
(-2, 3)
"""
- if isinstance(coords, TopManifoldPoint):
+ if isinstance(coords, TopologicalManifoldPoint):
point = coords # for readability
if point._subset is self:
return point
@@ -310,7 +307,7 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
EXAMPLES::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: A = M.subset('A')
sage: p = A._an_element_(); p
@@ -330,7 +327,7 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
TESTS::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: A = M.subset('A')
sage: A._repr_()
'Subset A of the 2-dimensional topological manifold M'
@@ -346,7 +343,7 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
TESTS::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: A = M.subset('A')
sage: A._latex_()
'A'
@@ -359,14 +356,62 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
"""
return self._latex_name
+ def __reduce__(self):
+ r"""
+ Reduction function for the pickle protocole.
+
+ TEST::
+
+ sage: M = Manifold(3, 'M', type='topological')
+ sage: A = M.subset('A')
+ sage: A.__reduce__()
+ (<class 'sage.manifolds.subset.TopologicalManifoldSubset'>,
+ (3-dimensional topological manifold M, 'A', 'A',
+ Category of facade sets))
+
+ Test of pickling::
+
+ sage: loads(dumps(A))
+ Subset A of the 3-dimensional topological manifold M
+
+ """
+ return (TopologicalManifoldSubset, (self._manifold, self._name,
+ self._latex_name, self.category()))
+
+ def _test_pickling(self, **options):
+ r"""
+ Test pickling.
+
+ This test is weaker than
+ :meth:`sage.structure.sage_object.SageObject._test_pickling` in that
+ it does not require ``loads(dumps(self)) == self``.
+ It however checks that ``loads(dumps(self))`` proceeds without any
+ error and results in an object that is a manifold subset of the same
+ type as ``self``, with the same name.
+
+ TESTS::
+
+ sage: M = Manifold(3, 'M', type='topological')
+ sage: A = M.subset('A')
+ sage: A._test_pickling()
+ sage: B = A.subset('B')
+ sage: B._test_pickling()
+
+ """
+ tester = self._tester(**options)
+ from sage.misc.all import loads, dumps
+ bckp = loads(dumps(self))
+ tester.assertEqual(type(bckp), type(self))
+ tester.assertEqual(bckp.category(), self.category())
+ tester.assertEqual(bckp._name, self._name)
+
def manifold(self):
r"""
Return the manifold of which the current object is a subset.
EXAMPLES::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: A = M.subset('A')
sage: A.manifold()
2-dimensional topological manifold M
@@ -400,8 +445,7 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
EXAMPLES::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: M.open_covers()
[[2-dimensional topological manifold M]]
sage: U = M.open_subset('U')
@@ -445,8 +489,7 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
Subsets of a 2-dimensional manifold::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: U = M.open_subset('U')
sage: V = M.subset('V')
sage: M.subsets() # random (set output)
@@ -490,8 +533,7 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
Subsets of a 2-dimensional manifold::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: U = M.open_subset('U')
sage: V = M.subset('V')
sage: M.list_of_subsets()
@@ -523,15 +565,15 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
OUTPUT:
- - the subset, as an instance of :class:`TopManifoldSubset`, or of
- the derived class :class:`TopManifold` if ``is_open`` is ``True``.
+ - the subset, as an instance of :class:`TopologicalManifoldSubset`, or
+ of the derived class :class:`TopologicalManifold` if ``is_open`` is
+ ``True``.
EXAMPLES:
Creating a subset of a manifold::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: a = M.subset('A'); a
Subset A of the 2-dimensional topological manifold M
@@ -553,7 +595,7 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
"""
if is_open:
return self.open_subset(name, latex_name=latex_name)
- res = TopManifoldSubset(self._manifold, name, latex_name=latex_name)
+ res = TopologicalManifoldSubset(self._manifold, name, latex_name=latex_name)
res._supersets.update(self._supersets)
for sd in self._supersets:
sd._subsets.add(res)
@@ -577,15 +619,15 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
OUTPUT:
- - the superset, as an instance of :class:`TopManifoldSubset` or of
- the derived class :class:`TopManifold` if ``is_open`` is ``True``.
+ - the superset, as an instance of :class:`TopologicalManifoldSubset` or
+ of the derived class :class:`TopologicalManifold` if ``is_open`` is
+ ``True``.
EXAMPLES:
Creating some superset of a given subset::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: a = M.subset('A')
sage: b = a.superset('B'); b
Subset B of the 2-dimensional topological manifold M
@@ -614,7 +656,7 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
if is_open:
res = self._manifold.open_subset(name, latex_name=latex_name)
else:
- res = TopManifoldSubset(self._manifold, name,
+ res = TopologicalManifoldSubset(self._manifold, name,
latex_name=latex_name)
res._subsets.update(self._subsets)
for sd in self._subsets:
@@ -642,15 +684,14 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
OUTPUT:
- - instance of :class:`TopManifoldSubset` representing the subset that
- is the intersection of the current subset with ``other``
+ - instance of :class:`TopologicalManifoldSubset` representing the
+ subset that is the intersection of the current subset with ``other``
EXAMPLES:
Intersection of two subsets::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: a = M.subset('A')
sage: b = M.subset('B')
sage: c = a.intersection(b); c
@@ -738,14 +779,14 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
OUTPUT:
- - instance of :class:`TopManifoldSubset` representing the subset that
- is the union of the current subset with ``other``
+ - instance of :class:`TopologicalManifoldSubset` representing the
+ subset that is the union of the current subset with ``other``
EXAMPLES:
Union of two subsets::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: a = M.subset('A')
sage: b = M.subset('B')
sage: c = a.union(b); c
@@ -849,7 +890,7 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
EXAMPLE::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: A = M.subset('A')
sage: B = M.subset('B')
sage: M.declare_union(A, B)
@@ -886,7 +927,7 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
Subsets on a 2-dimensional manifold::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: a = M.subset('A')
sage: b = a.subset('B')
sage: c = M.subset('C')
@@ -910,7 +951,7 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
TESTS::
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: X.<x,y> = M.chart()
sage: A = M.subset('A')
sage: p = A((-2,3), chart=X); p
@@ -933,14 +974,14 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
if point._subset.is_subset(self):
return True
#!# should be improved once coordinate definition have been introduced
- # in TopManifoldSubset
+ # in TopologicalManifoldSubset
return False
def point(self, coords=None, chart=None, name=None, latex_name=None):
r"""
Define a point in the subset.
- See :class:`~sage.manifolds.point.TopManifoldPoint` for a
+ See :class:`~sage.manifolds.point.TopologicalManifoldPoint` for a
complete documentation.
INPUT:
@@ -957,14 +998,13 @@ class TopManifoldSubset(UniqueRepresentation, Parent):
OUTPUT:
- the declared point, as an instance of
- :class:`~sage.manifolds.point.TopManifoldPoint`.
+ :class:`~sage.manifolds.point.TopologicalManifoldPoint`.
EXAMPLES:
Points on a 2-dimensional manifold::
- sage: TopManifold._clear_cache_() # for doctests only
- sage: M = TopManifold(2, 'M')
+ sage: M = Manifold(2, 'M', type='topological')
sage: c_xy.<x,y> = M.chart()
sage: p = M.point((1,2), name='p'); p
Point p on the 2-dimensional topological manifold M