summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Gourgoulhon <eric.gourgoulhon@obspm.fr>2015-11-04 00:27:31 +0100
committerEric Gourgoulhon <eric.gourgoulhon@obspm.fr>2015-11-04 00:27:31 +0100
commit902908b41a95d3455bfcc497997ad2054c530a96 (patch)
tree9eb1f3379f874d1e2b7c4cdcda6af0869b124669
parentRemove UniqueRepresentation from topological manifolds, subsets and charts. (diff)
Revert to UniqueRepresentation for topological manifolds and charts, with the possibility to reuse manifold names.
-rw-r--r--src/sage/manifolds/chart.py131
-rw-r--r--src/sage/manifolds/manifold.py176
-rw-r--r--src/sage/manifolds/subset.py77
3 files changed, 78 insertions, 306 deletions
diff --git a/src/sage/manifolds/chart.py b/src/sage/manifolds/chart.py
index fd8556e..77cce77 100644
--- a/src/sage/manifolds/chart.py
+++ b/src/sage/manifolds/chart.py
@@ -33,6 +33,7 @@ REFERENCES:
#*****************************************************************************
from sage.structure.sage_object import SageObject
+from sage.structure.unique_representation import UniqueRepresentation
from sage.symbolic.ring import SR
from sage.rings.all import CC
from sage.rings.real_mpfr import RR
@@ -40,7 +41,7 @@ from sage.rings.infinity import Infinity
from sage.misc.latex import latex
from sage.manifolds.manifold import TopologicalManifold
-class Chart(SageObject):
+class Chart(UniqueRepresentation, SageObject):
r"""
Chart on a topological manifold.
@@ -251,7 +252,6 @@ class Chart(SageObject):
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:
@@ -391,131 +391,6 @@ class Chart(SageObject):
"""
return self[:]
- def __hash__(self):
- r"""
- Hash function.
-
- TEST::
-
- sage: M = Manifold(2, 'M', type='topological')
- sage: X.<x,y> = M.chart()
- sage: X.__hash__() # random
- -4817665684801967664
-
- """
- return hash((self._domain,) + self._xx)
-
- def __eq__(self, other):
- r"""
- Compare ``self`` with ``other``.
-
- TESTS::
-
- sage: M = Manifold(2, 'M', type='topological')
- sage: X.<x,y> = M.chart()
- sage: Y.<u,v> = M.chart()
- sage: X.__eq__(Y)
- False
- sage: X.__eq__(X)
- True
- sage: U = M.open_subset('U', coord_def={X: x>0})
- sage: XU = X.restrict(U)
- sage: XU.__eq__(X)
- False
-
- """
- if not isinstance(other, Chart):
- return False
- return (self._domain == other._domain) and (self._xx == other._xx)
-
- def __ne__(self, other):
- r"""
- Non-equality operator.
-
- TESTS::
-
- sage: M = Manifold(2, 'M', type='topological')
- sage: X.<x,y> = M.chart()
- sage: Y.<u,v> = M.chart()
- sage: X.__ne__(Y)
- True
- sage: X.__ne__(X)
- False
-
- """
- return not self.__eq__(other)
-
- 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)) == X
- True
-
- """
- return (self.__class__, (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 __getitem__(self, i):
r"""
Access to the coordinates.
@@ -898,7 +773,7 @@ class Chart(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))]
diff --git a/src/sage/manifolds/manifold.py b/src/sage/manifolds/manifold.py
index 097bc64..f2fcedb 100644
--- a/src/sage/manifolds/manifold.py
+++ b/src/sage/manifolds/manifold.py
@@ -322,6 +322,14 @@ class TopologicalManifold(TopologicalManifoldSubset):
- ``ambient_manifold`` -- (default: ``None``) if not ``None``, the created
object is considered as an open subset of the topological manifold
``ambient_manifold``
+ - ``unique_tag`` -- (default: ``None``) tag used to force the construction
+ of a new object when all the other arguments have been used previously
+ (without ``unique_tag``, the
+ :class:`~sage.structure.unique_representation.UniqueRepresentation`
+ behavior inherited from
+ :class:`~sage.manifolds.subset.TopologicalManifoldSubset`
+ would return the previously constructed object corresponding to these
+ arguments).
EXAMPLES:
@@ -423,7 +431,7 @@ class TopologicalManifold(TopologicalManifoldSubset):
"""
def __init__(self, n, name, latex_name=None, field='real', start_index=0,
- category=None, ambient_manifold=None):
+ category=None, ambient_manifold=None, unique_tag=None):
r"""
Construct a topological manifold.
@@ -543,106 +551,6 @@ class TopologicalManifold(TopologicalManifoldSubset):
"""
return self._latex_name
- def __hash__(self):
- r"""
- Hash function.
-
- TESTS::
-
- sage: M = Manifold(3, 'M', type='topological')
- sage: M.__hash__() # random
- 9122374470132259666
-
- """
- return hash((self._dim, self._field, self._name))
-
- def __eq__(self, other):
- r"""
- Compare ``self`` with ``other``.
-
- TESTS::
-
- sage: M = Manifold(3, 'M', type='topological')
- sage: N = Manifold(3, 'M', type='topological')
- sage: M.__eq__(N)
- True
- sage: N = Manifold(3, 'N', type='topological') # change the name
- sage: M.__eq__(N)
- False
- sage: N = Manifold(2, 'M', type='topological') # change the dimension
- sage: M.__eq__(N)
- False
- sage: N = Manifold(3, 'M', type='topological', field='complex') # change the base field
- sage: M.__eq__(N)
- False
-
- """
- if not isinstance(other, TopologicalManifold):
- return False
- return (self._dim == other._dim) and (self._field == other._field) \
- and (self._name == other._name)
- #!# this is rather primitive: the atlases should be compared as well...
-
- def __ne__(self, other):
- r"""
- Non-equality operator.
-
- TESTS::
-
- sage: M = Manifold(3, 'M', type='topological')
- sage: N = Manifold(3, 'M', type='topological')
- sage: M.__ne__(N)
- False
- sage: N = Manifold(3, 'N', type='topological') # change the name
- sage: M.__ne__(N)
- True
-
- """
- return not self.__eq__(other)
-
- 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)) == M
- True
- sage: loads(dumps(U)) == U
- True
-
- """
- 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 _an_element_(self):
r"""
Construct some point on the manifold.
@@ -1491,7 +1399,7 @@ def Manifold(dim, name, latex_name=None, field='real', type='smooth',
- ``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 specific types of
+ - ``extra_kwds`` -- keywords meaningful only for some specific types of
manifolds
OUTPUT:
@@ -1527,10 +1435,72 @@ def Manifold(dim, name, latex_name=None, field='real', type='smooth',
:class:`~sage.manifolds.manifold.TopologicalManifold` for more
detailed examples.
+ .. RUBRIC:: Reusability of the manifold name
+
+ 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
+
+ The pickling works for both objects::
+
+ sage: loads(dumps(M)) == M
+ True
+ sage: loads(dumps(M_old)) == M_old
+ True
+
"""
+ from time import time
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)
+ field=field, start_index=start_index,
+ unique_tag=time())
raise NotImplementedError("manifolds of type {} are not ".format(type_) +
"implemented")
diff --git a/src/sage/manifolds/subset.py b/src/sage/manifolds/subset.py
index 4962170..36c28ce 100644
--- a/src/sage/manifolds/subset.py
+++ b/src/sage/manifolds/subset.py
@@ -71,10 +71,11 @@ Lists of subsets after the above operations::
#*****************************************************************************
from sage.structure.parent import Parent
+from sage.structure.unique_representation import UniqueRepresentation
from sage.categories.sets_cat import Sets
from sage.manifolds.point import TopologicalManifoldPoint
-class TopologicalManifoldSubset(Parent):
+class TopologicalManifoldSubset(UniqueRepresentation, Parent):
r"""
Subset of a topological manifold.
@@ -355,80 +356,6 @@ class TopologicalManifoldSubset(Parent):
"""
return self._latex_name
- def __hash__(self):
- r"""
- Hash function.
-
- TEST::
-
- sage: M = Manifold(3, 'M', type='topological')
- sage: A = M.subset('A')
- sage: A.__hash__() # random
- 1649998564335275777
-
- """
- return hash((self._manifold, self._name))
-
-
- def __eq__(self, other):
- r"""
- Compare ``self`` with ``other``.
-
- TESTS::
-
- sage: M = Manifold(3, 'M', type='topological')
- sage: A = M.subset('A')
- sage: B = M.subset('B')
- sage: A.__eq__(A)
- True
- sage: A.__eq__(B)
- False
-
- """
- if not isinstance(other, TopologicalManifoldSubset):
- return False
- return (self._manifold == other._manifold) and \
- (self._name == other._name)
-
- def __ne__(self, other):
- r"""
- Non-equality operator.
-
- TESTS::
-
- sage: M = Manifold(3, 'M', type='topological')
- sage: A = M.subset('A')
- sage: B = M.subset('B')
- sage: A.__ne__(A)
- False
- sage: A.__ne__(B)
- True
-
- """
- return not self.__eq__(other)
-
- 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)) == A
- True
-
- """
- return (TopologicalManifoldSubset, (self._manifold, self._name,
- self._latex_name, self.category()))
-
def manifold(self):
r"""
Return the manifold of which the current object is a subset.