summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Gourgoulhon <eric.gourgoulhon@obspm.fr>2016-01-11 11:41:48 +0100
committerEric Gourgoulhon <eric.gourgoulhon@obspm.fr>2016-01-11 11:41:48 +0100
commitc01048f2c51f98798ef8f86548241d69e6578d56 (patch)
tree6c2b6c40fc887033ea7505077b5c0ccf96a519ba
parentScalarFieldAlgebra does not longer inherit from AbstractNamedObject (diff)
parentRevert to simple hierarchy for manifold classes (diff)
Scalar fields with the simplified hierarchy for manifold classes
-rw-r--r--src/doc/en/reference/manifolds/manifold.rst4
-rw-r--r--src/doc/en/reference/manifolds/scalarfield.rst2
-rw-r--r--src/sage/manifolds/abstract.py666
-rw-r--r--src/sage/manifolds/chart.py62
-rw-r--r--src/sage/manifolds/manifold.py195
-rw-r--r--src/sage/manifolds/point.py4
-rw-r--r--src/sage/manifolds/scalarfield.py2
-rw-r--r--src/sage/manifolds/scalarfield_algebra.py2
-rw-r--r--src/sage/manifolds/structure.py4
-rw-r--r--src/sage/manifolds/subset.py1064
10 files changed, 878 insertions, 1127 deletions
diff --git a/src/doc/en/reference/manifolds/manifold.rst b/src/doc/en/reference/manifolds/manifold.rst
index 0c4be1f..3ac4f04 100644
--- a/src/doc/en/reference/manifolds/manifold.rst
+++ b/src/doc/en/reference/manifolds/manifold.rst
@@ -1,4 +1,4 @@
-Topological manifolds
+Topological Manifolds
=====================
.. toctree::
@@ -6,8 +6,6 @@ Topological manifolds
sage/manifolds/manifold
- sage/manifolds/abstract
-
sage/manifolds/subset
sage/manifolds/structure
diff --git a/src/doc/en/reference/manifolds/scalarfield.rst b/src/doc/en/reference/manifolds/scalarfield.rst
index 99989a0..3ba7a2e 100644
--- a/src/doc/en/reference/manifolds/scalarfield.rst
+++ b/src/doc/en/reference/manifolds/scalarfield.rst
@@ -1,4 +1,4 @@
-Scalar fields
+Scalar Fields
=============
.. toctree::
diff --git a/src/sage/manifolds/abstract.py b/src/sage/manifolds/abstract.py
deleted file mode 100644
index 44801d4..00000000
--- a/src/sage/manifolds/abstract.py
+++ /dev/null
@@ -1,666 +0,0 @@
-r"""
-Abstract objects and sets
-
-These are base classes for the manifolds.
-
-AUTHORS:
-
-- Travis Scrimshaw (2015-11-25): initial version
-- Eric Gourgoulhon (2015): some methods from previous TopologicalManifold class
-
-"""
-
-#*****************************************************************************
-# Copyright (C) 2015 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr>
-# Copyright (C) 2015 Travis Scrimshaw <tscrimsh@umn.edu>
-#
-# Distributed under the terms of the GNU General Public License (GPL)
-# as published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-# http://www.gnu.org/licenses/
-#*****************************************************************************
-
-from sage.structure.parent import Parent
-from sage.structure.unique_representation import UniqueRepresentation
-from sage.categories.fields import Fields
-from sage.categories.manifolds import Manifolds
-from sage.categories.sets_cat import Sets
-from sage.rings.integer import Integer
-from sage.manifolds.point import ManifoldPoint
-
-class AbstractNamedObject(object):
- r"""
- An abstract named object.
-
- This abstract class handles the symbols (text and LaTeX) of named objects
- (e.g. parent objects in manifold classes).
-
- INPUT:
-
- - ``name`` -- (short) string; name (symbol) given to the object
- - ``latex_name`` -- (default: ``None``) string; LaTeX symbol to
- denote the object; if ``None``, the LaTeX symbol is set to ``name``
-
- EXAMPLES::
-
- sage: from sage.manifolds.abstract import AbstractNamedObject
- sage: a = AbstractNamedObject('A', latex_name=r'\mathcal{A}')
- sage: a._repr_()
- 'A'
- sage: a._latex_()
- '\\mathcal{A}'
- sage: latex(a)
- \mathcal{A}
-
- Using default values::
-
- sage: a = AbstractNamedObject('A')
- sage: a._repr_()
- 'A'
- sage: a._latex_()
- 'A'
- sage: latex(a)
- A
-
- """
- def __init__(self, name, latex_name=None):
- """
- Initialize ``self``.
-
- TEST::
-
- sage: from sage.manifolds.abstract import AbstractNamedObject
- sage: a = AbstractNamedObject('a')
- sage: type(a)
- <class 'sage.manifolds.abstract.AbstractNamedObject'>
-
- """
- 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
- else:
- if not isinstance(latex_name, str):
- raise TypeError("{} is not a string".format(latex_name))
- self._latex_name = latex_name
-
- def _repr_(self):
- """
- Return a string representation of ``self``.
-
- TEST::
-
- sage: from sage.manifolds.abstract import AbstractNamedObject
- sage: a = AbstractNamedObject('a')
- sage: a._repr_()
- 'a'
-
- """
- return self._name
-
- def _latex_(self):
- r"""
- LaTeX representation of ``self``.
-
- TESTS::
-
- sage: M = Manifold(2, 'M', structure='topological')
- sage: A = M.subset('A')
- sage: A._latex_()
- 'A'
- sage: B = A.subset('B', latex_name=r'\mathcal{B}')
- sage: B._latex_()
- '\\mathcal{B}'
- sage: latex(B) # indirect doctest
- \mathcal{B}
-
- sage: M = Manifold(3, 'M', structure='topological')
- sage: M._latex_()
- 'M'
- sage: latex(M)
- M
- sage: M = Manifold(3, 'M', latex_name=r'\mathcal{M}',
- ....: structure='topological')
- sage: M._latex_()
- '\\mathcal{M}'
- sage: latex(M) # indirect doctest
- \mathcal{M}
- """
- return self._latex_name
-
-class AbstractSet(AbstractNamedObject, UniqueRepresentation, Parent):
- """
- An abstract set on a topological manifold.
-
- An abstract set is an :class:`AbstractNamedObject` along with its known
- subsets, supersets, intersections, unions, and open covers.
-
- INPUT:
-
- - ``name`` -- (short) string; name (symbol) given to the object
- - ``latex_name`` -- (default: ``None``) string; LaTeX symbol to
- denote the object; if ``None``, the LaTeX symbol is set to ``name``
- - ``base`` -- (default: ``None``) base for the
- :class:`~sage.structure.parent.Parent` constructor
- - ``category`` -- (default: ``None``) category of the object
-
- """
- def __init__(self, name, latex_name=None, base=None, category=None):
- r"""
- Initialize ``self``
-
- TESTS::
-
- sage: M = Manifold(2, 'M', structure='topological')
- sage: X.<x,y> = M.chart()
- sage: A = M.subset('A'); A
- Subset A of the 2-dimensional topological manifold M
- """
- AbstractNamedObject.__init__(self, name, latex_name=latex_name)
-
- category = Sets().or_subcategory(category)
- Parent.__init__(self, base=base, category=category)
-
- self._supersets = set([self]) # subsets containing self
- self._subsets = set([self]) # subsets of self
- self._top_subsets = set([self]) # subsets contained in self but not
- # in another strict subset of self
- self._intersections = {} # dict. of intersections with other subsets
- # (key: subset name)
- self._unions = {} # dict. of unions with other subsets (key: subset
- # name)
- self._open_covers = [] # list of open covers of self
-
- #### Methods required for any Parent in the category of sets:
-
- def _element_constructor_(self, coords=None, chart=None, name=None,
- latex_name=None, check_coords=True):
- r"""
- Construct a point in the subset from its coordinates in some chart.
-
- INPUT:
-
- - ``coords`` -- (default: ``None``) either (i) the point coordinates
- (as a tuple or a list) in the chart ``chart`` or (ii) another point
- in the subset
- - ``chart`` -- (default: ``None``) chart in which the coordinates are
- given; if none is provided, the coordinates are assumed to refer to
- the subset's default chart
- - ``name`` -- (default: ``None``) name given to the point
- - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
- point; if none is provided, the LaTeX symbol is set to ``name``
- - ``check_coords`` -- (default: ``True``) determines whether ``coords``
- are valid coordinates for the chart ``chart``; for symbolic
- coordinates, it is recommended to set ``check_coords`` to ``False``.
-
- OUTPUT:
-
- - an instance of :class:`~sage.manifolds.point.ManifoldPoint`
- representing a point in the current subset.
-
- EXAMPLES::
-
- sage: M = Manifold(2, 'M', structure='topological')
- sage: X.<x,y> = M.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)
-
- A generic subset has no default chart, so the chart must be explicited::
-
- sage: A = M.subset('A')
- sage: p = A((-2,3), chart=X); p
- Point on the 2-dimensional topological manifold M
- sage: X(p)
- (-2, 3)
- sage: p.parent()
- Subset A of the 2-dimensional topological manifold M
- sage: p in A
- True
-
- Coordinates in a chart with some coordinate restrictions::
-
- sage: Y.<u,v> = M.chart('u:(-1,1) v:(-1,1)')
- 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((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((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((-2,3), chart=X, name='p'); p
- Point p on the 2-dimensional topological manifold M
-
- A point as entry::
-
- sage: q = A(p); q
- Point p on the 2-dimensional topological manifold M
- sage: X(q)
- (-2, 3)
-
- """
- if isinstance(coords, ManifoldPoint):
- point = coords # for readability
- # This should actually never happen by the coercion framework...
- if point.parent() is self:
- return point
- if point in self:
- resu = self.element_class(self, name=point._name,
- latex_name=point._latex_name)
- for chart, coords in point._coordinates.iteritems():
- resu._coordinates[chart] = coords
- return resu
- else:
- raise ValueError("the {}".format(point) +
- " is not in {}".format(self))
- return self.element_class(self, coords=coords, chart=chart, name=name,
- latex_name=latex_name, check_coords=check_coords)
-
- def _an_element_(self):
- r"""
- Construct some point in the subset.
-
- EXAMPLES::
-
- sage: M = Manifold(2, 'M', structure='topological')
- sage: X.<x,y> = M.chart()
- sage: A = M.subset('A')
- sage: p = A._an_element_(); p
- Point on the 2-dimensional topological manifold M
- sage: p in A
- True
-
- """
- #!# should be improved...
- return self.element_class(self)
-
- #### End of methods required for any Parent in the category of sets
-
- def open_covers(self):
- r"""
- Return the list of open covers of the current subset.
-
- If the current subset, `A` say, is a subset of the manifold `M`, an
- *open cover* of `A` is list (indexed set) `(U_i)_{i\in I}` of
- open subsets of `M` such that
-
- .. MATH::
-
- A \subset \bigcup_{i \in I} U_i
-
- If `A` is open, we ask that the above inclusion is actually an
- identity:
-
- .. MATH::
-
- A = \bigcup_{i \in I} U_i
-
- EXAMPLES::
-
- sage: M = Manifold(2, 'M', structure='topological')
- sage: M.open_covers()
- [[2-dimensional topological manifold M]]
- sage: U = M.open_subset('U')
- sage: U.open_covers()
- [[Open subset U of the 2-dimensional topological manifold M]]
- sage: A = U.open_subset('A')
- sage: B = U.open_subset('B')
- sage: U.declare_union(A,B)
- sage: U.open_covers()
- [[Open subset U of the 2-dimensional topological manifold M],
- [Open subset A of the 2-dimensional topological manifold M,
- Open subset B of the 2-dimensional topological manifold M]]
- sage: V = M.open_subset('V')
- sage: M.declare_union(U,V)
- sage: M.open_covers()
- [[2-dimensional topological manifold M],
- [Open subset U of the 2-dimensional topological manifold M,
- Open subset V of the 2-dimensional topological manifold M],
- [Open subset A of the 2-dimensional topological manifold M,
- Open subset B of the 2-dimensional topological manifold M,
- Open subset V of the 2-dimensional topological manifold M]]
-
- """
- return self._open_covers
-
- def subsets(self):
- r"""
- Return the set of subsets that have been defined on the current subset.
-
- OUTPUT:
-
- - A Python set containing all the subsets that have been defined on
- the current subset.
-
- .. NOTE::
-
- To get the subsets as a list, used the method
- :meth:`list_of_subsets` instead.
-
- EXAMPLE:
-
- Subsets of a 2-dimensional manifold::
-
- sage: M = Manifold(2, 'M', structure='topological')
- sage: U = M.open_subset('U')
- sage: V = M.subset('V')
- sage: M.subsets() # random (set output)
- {Subset V of the 2-dimensional topological manifold M,
- 2-dimensional topological manifold M,
- Open subset U of the 2-dimensional topological manifold M}
- sage: type(M.subsets())
- <type 'frozenset'>
- sage: U in M.subsets()
- True
-
- The method :meth:`list_of_subsets` returns a list (sorted
- alphabetically by the subset names) instead of a set::
-
- sage: M.list_of_subsets()
- [2-dimensional topological manifold M,
- Open subset U of the 2-dimensional topological manifold M,
- Subset V of the 2-dimensional topological manifold M]
-
- """
- return frozenset(self._subsets)
-
- def list_of_subsets(self):
- r"""
- Return the list of subsets that have been defined on the current
- subset.
-
- The list is sorted by the alphabetical names of the subsets.
-
- OUTPUT:
-
- - A list containing all the subsets that have been defined on
- the current subset.
-
- .. NOTE::
-
- To get the subsets as a Python set, used the method
- :meth:`subsets` instead.
-
- EXAMPLE:
-
- Subsets of a 2-dimensional manifold::
-
- sage: M = Manifold(2, 'M', structure='topological')
- sage: U = M.open_subset('U')
- sage: V = M.subset('V')
- sage: M.list_of_subsets()
- [2-dimensional topological manifold M,
- Open subset U of the 2-dimensional topological manifold M,
- Subset V of the 2-dimensional topological manifold M]
-
- The method :meth:`subsets` returns a set instead of a list::
-
- sage: M.subsets() # random (set output)
- {Subset V of the 2-dimensional topological manifold M,
- 2-dimensional topological manifold M,
- Open subset U of the 2-dimensional topological manifold M}
-
- """
- return sorted(self._subsets, key=lambda x: x._name)
-
- def subset(self, name, latex_name=None, is_open=False):
- r"""
- Create a subset of ``self``.
-
- INPUT:
-
- - ``name`` -- name given to the subset
- - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
- subset; if none is provided, it is set to ``name``
- - ``is_open`` -- (default: ``False``) if ``True``, the created subset
- is assumed to be open with respect to the manifold's topology
-
- OUTPUT:
-
- - the subset, as an instance of :class:`~sage.manifolds.subset.ManifoldSubset`, or
- of the derived class
- :class:`~sage.manifolds.subset.OpenTopologicalSubmanifold` if ``is_open``
- is ``True``.
-
- EXAMPLES:
-
- Creating a subset of a manifold::
-
- sage: M = Manifold(2, 'M', structure='topological')
- sage: a = M.subset('A'); a
- Subset A of the 2-dimensional topological manifold M
-
- Creating a subset of A::
-
- sage: b = a.subset('B', latex_name=r'\mathcal{B}'); b
- Subset B of the 2-dimensional topological manifold M
- sage: latex(b)
- \mathcal{B}
-
- We have then::
-
- sage: b.is_subset(a)
- True
- sage: b in a.subsets()
- True
- """
- if is_open:
- return self.open_subset(name, latex_name=latex_name)
- from sage.manifolds.subset import ManifoldSubset
- res = ManifoldSubset(self.manifold(), name, latex_name=latex_name)
- res._supersets.update(self._supersets)
- for sd in self._supersets:
- sd._subsets.add(res)
- self._top_subsets.add(res)
- return res
-
- def get_subset(self, name):
- r"""
- Get a subset by its name.
-
- The subset must have been previously created by the method
- :meth:`subset` (or
- :meth:`~sage.manifolds.manifold.TopologicalManifold.open_subset`)
-
- INPUT:
-
- - ``name`` -- (string) name of the subset
-
- OUTPUT:
-
- - instance of :class:`~sage.manifolds.subset.ManifoldSubset` (or
- of the derived class
- :class:`~sage.manifolds.subset.OpenTopologicalSubmanifold` for an open
- subset) representing the subset whose name is ``name``.
-
- EXAMPLES::
-
- sage: M = Manifold(4, 'M', structure='topological')
- sage: A = M.subset('A')
- sage: B = A.subset('B')
- sage: U = M.open_subset('U')
- sage: M.list_of_subsets()
- [Subset A of the 4-dimensional topological manifold M,
- Subset B of the 4-dimensional topological manifold M,
- 4-dimensional topological manifold M,
- Open subset U of the 4-dimensional topological manifold M]
- sage: M.get_subset('A')
- Subset A of the 4-dimensional topological manifold M
- sage: M.get_subset('A') is A
- True
- sage: M.get_subset('B') is B
- True
- sage: A.get_subset('B') is B
- True
- sage: M.get_subset('U')
- Open subset U of the 4-dimensional topological manifold M
- sage: M.get_subset('U') is U
- True
-
- """
- for ss in self._subsets:
- if ss._name == name:
- return ss
- raise ValueError("no subset of name '{}' found".format(name))
-
- def is_subset(self, other):
- r"""
- Return ``True`` iff ``self`` is included in ``other``.
-
- EXAMPLES:
-
- Subsets on a 2-dimensional manifold::
-
- sage: M = Manifold(2, 'M', structure='topological')
- sage: a = M.subset('A')
- sage: b = a.subset('B')
- sage: c = M.subset('C')
- sage: a.is_subset(M)
- True
- sage: b.is_subset(a)
- True
- sage: b.is_subset(M)
- True
- sage: a.is_subset(b)
- False
- sage: c.is_subset(a)
- False
- """
- return self in other._subsets
-
- def __contains__(self, point):
- r"""
- Check whether ``point`` is contained in ``self``.
-
- TESTS::
-
- sage: M = Manifold(2, 'M', structure='topological')
- sage: X.<x,y> = M.chart()
- sage: A = M.subset('A')
- sage: p = A((-2,3), chart=X); p
- Point on the 2-dimensional topological manifold M
- sage: A.__contains__(p)
- True
- sage: p in A # indirect doctest
- True
- sage: A.__contains__(A.an_element())
- True
- sage: q = M((0,0), chart=X); q
- Point on the 2-dimensional topological manifold M
- sage: A.__contains__(q)
- False
- """
- # for efficiency, a quick test first:
- if point.parent() is self:
- return True
- if point.parent().is_subset(self):
- return True
- #!# should be improved once coordinate definition have been introduced
- # in ManifoldSubset
- return False
-
- def declare_union(self, dom1, dom2):
- r"""
- Declare that the current subset is the union of two subsets,
- i.e. that
-
- .. MATH::
-
- U = U_1 \cup U_2,
-
- where `U` is the current subset, `U_1 \subset U` and `U_2 \subset U`.
-
- INPUT:
-
- - ``dom1`` -- subset `U_1`
- - ``dom2`` -- subset `U_2`
-
- EXAMPLE::
-
- sage: M = Manifold(2, 'M', structure='topological')
- sage: A = M.subset('A')
- sage: B = M.subset('B')
- sage: M.declare_union(A, B)
- sage: A.union(B)
- 2-dimensional topological manifold M
-
- """
- if dom1 == dom2:
- if dom1 != self:
- raise ValueError("the union of two identical sets must be " +
- "this set")
- return
- if not dom1.is_subset(self):
- raise TypeError("the {} is not a subset of ".format(dom1) +
- "the {}".format(self))
- if not dom2.is_subset(self):
- raise TypeError("the {} is not a subset of ".format(dom2) +
- "the {}".format(self))
- dom1._unions[dom2._name] = self
- dom2._unions[dom1._name] = self
- for oc1 in dom1._open_covers:
- for oc2 in dom2._open_covers:
- oc = oc1[:]
- for s in oc2:
- if s not in oc:
- oc.append(s)
- self._open_covers.append(oc)
-
- def point(self, coords=None, chart=None, name=None, latex_name=None):
- r"""
- Define a point in ``self``.
-
- See :class:`~sage.manifolds.point.ManifoldPoint` for a
- complete documentation.
-
- INPUT:
-
- - ``coords`` -- the point coordinates (as a tuple or a list) in the
- chart specified by ``chart``
- - ``chart`` -- (default: ``None``) chart in which the point coordinates
- are given; if ``None``, the coordinates are assumed to refer to
- the default chart of the current subset
- - ``name`` -- (default: ``None``) name given to the point
- - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
- point; if ``None``, the LaTeX symbol is set to ``name``
-
- OUTPUT:
-
- - the declared point, as an instance of
- :class:`~sage.manifolds.point.ManifoldPoint`.
-
- EXAMPLES:
-
- Points on a 2-dimensional manifold::
-
- sage: M = Manifold(2, 'M', structure='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
- sage: p in M
- True
- sage: a = M.open_subset('A')
- sage: c_uv.<u,v> = a.chart()
- sage: q = a.point((-1,0), name='q'); q
- Point q on the 2-dimensional topological manifold M
- sage: q in a
- True
- sage: p._coordinates
- {Chart (M, (x, y)): (1, 2)}
- sage: q._coordinates
- {Chart (A, (u, v)): (-1, 0)}
- """
- return self.element_class(self, coords=coords, chart=chart,
- name=name, latex_name=latex_name)
-
- Element = ManifoldPoint
diff --git a/src/sage/manifolds/chart.py b/src/sage/manifolds/chart.py
index 05ea5c3..31d2120 100644
--- a/src/sage/manifolds/chart.py
+++ b/src/sage/manifolds/chart.py
@@ -1,5 +1,5 @@
r"""
-Coordinate charts
+Coordinate Charts
The class :class:`Chart` implements coordinate charts on a topological manifold
over a topological field `K`. The subclass :class:`RealChart` is devoted
@@ -42,9 +42,9 @@ from sage.manifolds.coord_func_symb import CoordFunctionSymb
class Chart(UniqueRepresentation, SageObject):
r"""
- Chart on a manifold.
+ Chart on a topological manifold.
- Given a (topological) manifold `M` of dimension `n` over a topological
+ Given a topological manifold `M` of dimension `n` over a topological
field `K`, a *chart* on `M` is a pair `(U,\varphi)`, where `U` is an
open subset of `M` and `\varphi: U \rightarrow V \subset K^n` is a
homeomorphism from `U` to an open subset `V` of `K^n`.
@@ -1878,11 +1878,7 @@ class CoordChange(SageObject):
Change of coordinates from Chart (M, (x, y)) to Chart (M, (u, v))
sage: type(X_to_Y)
<class 'sage.manifolds.chart.CoordChange'>
- sage: TestSuite(X_to_Y).run(skip='_test_pickling')
-
- .. TODO::
-
- fix _test_pickling
+ sage: TestSuite(X_to_Y).run()
"""
self._n1 = len(chart1._xx)
@@ -1942,6 +1938,55 @@ class CoordChange(SageObject):
"""
return latex(self._chart1) + r' \rightarrow ' + latex(self._chart2)
+ def __eq__(self, other):
+ r"""
+ Equality operator.
+
+ TESTS::
+
+ sage: M = Manifold(2, 'M', structure='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])
+ sage: X_to_Y == X_to_Y
+ True
+ sage: X_to_Y1 = X.transition_map(Y, [x+y, x-y])
+ sage: X_to_Y == X_to_Y1
+ True
+ sage: X_to_Y2 = X.transition_map(Y, [2*y, -x])
+ sage: X_to_Y == X_to_Y2
+ False
+ sage: Z.<w,z> = M.chart()
+ sage: X_to_Z = X.transition_map(Z, [x+y, x-y])
+ sage: X_to_Y == X_to_Z
+ False
+
+ """
+ if other is self:
+ return True
+ if not isinstance(other, CoordChange):
+ return False
+ return (self._chart1 == other._chart1) and \
+ (self._chart2 == other._chart2) and \
+ (self._transf == other._transf)
+
+ def __ne__(self, other):
+ r"""
+ Unequality operator.
+
+ TESTS::
+
+ sage: M = Manifold(2, 'M', structure='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])
+ sage: X_to_Y2 = X.transition_map(Y, [2*y, -x])
+ sage: X_to_Y != X_to_Y2
+ True
+
+ """
+ return not (self == other)
+
def __call__(self, *coords):
r"""
Compute the new coordinates from old ones.
@@ -2278,4 +2323,3 @@ class CoordChange(SageObject):
return FormattedExpansion(rtxt, rlatex)
disp = display
-
diff --git a/src/sage/manifolds/manifold.py b/src/sage/manifolds/manifold.py
index 08b7fb2..bcc6e92 100644
--- a/src/sage/manifolds/manifold.py
+++ b/src/sage/manifolds/manifold.py
@@ -11,8 +11,8 @@ dimension* `n` *over K* is a topological space `M` such that
Topological manifolds are implemented via the class
:class:`TopologicalManifold`. Open subsets of topological manifolds
-are implemented via the subclass
-:class:`~sage.manifolds.subset.OpenTopologicalSubmanifold`.
+are also implemented via :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`).
@@ -300,8 +300,10 @@ A constant map `\CC^* \rightarrow \CC`::
AUTHORS:
- Eric Gourgoulhon (2015): initial version
-- Travis Scrimshaw (2015): inheritance from
- :class:`~sage.manifolds.abstract.AbstractSet`
+- Travis Scrimshaw (2015): structure described via
+ :class:`~sage.manifolds.structure.TopologicalStructure` or
+ :class:`~sage.manifolds.structure.RealTopologicalStructure`
+
REFERENCES:
@@ -327,20 +329,19 @@ REFERENCES:
from sage.categories.fields import Fields
from sage.categories.manifolds import Manifolds
-from sage.categories.sets_cat import Sets
from sage.rings.all import CC
from sage.rings.real_mpfr import RR, RealField_class
from sage.rings.complex_field import ComplexField_class
from sage.misc.prandom import getrandbits
from sage.rings.integer import Integer
-from sage.manifolds.abstract import AbstractSet
+from sage.manifolds.subset import ManifoldSubset
from sage.manifolds.structure import TopologicalStructure, \
RealTopologicalStructure
#############################################################################
## Class
-class TopologicalManifold(AbstractSet):
+class TopologicalManifold(ManifoldSubset):
r"""
Topological manifold over a topological field `K`.
@@ -374,6 +375,9 @@ class TopologicalManifold(AbstractSet):
- ``structure`` -- manifold structure (see
:class:`~sage.manifolds.structure.TopologicalStructure` or
:class:`~sage.manifolds.structure.RealTopologicalStructure`)
+ - ``ambient`` -- (default: ``None``) if not ``None``, must be a
+ topological manifold; the created object is then an open subset of
+ ``ambient``
- ``latex_name`` -- (default: ``None``) string; LaTeX symbol to
denote the manifold; if none is provided, it is set to ``name``
- ``start_index`` -- (default: 0) integer; lower value of the range of
@@ -387,7 +391,7 @@ class TopologicalManifold(AbstractSet):
(without ``unique_tag``, the
:class:`~sage.structure.unique_representation.UniqueRepresentation`
behavior inherited from
- :class:`~sage.manifolds.abstract.AbstractSet`
+ :class:`~sage.manifolds.subset.ManifoldSubset`
would return the previously constructed object corresponding to these
arguments).
@@ -473,8 +477,7 @@ class TopologicalManifold(AbstractSet):
Since an open subset of a topological manifold `M` is itself a
topological manifold, open subsets of `M` are instances of the class
- :class:`TopologicalManifold` (actually of the subclass
- :class:`~sage.manifolds.subset.OpenTopologicalSubmanifold`)::
+ :class:`TopologicalManifold`::
sage: U = M.open_subset('U'); U
Open subset U of the 4-dimensional topological manifold M
@@ -484,6 +487,9 @@ class TopologicalManifold(AbstractSet):
True
sage: dim(U) == dim(M)
True
+ sage: U.category()
+ Join of Category of subobjects of sets and Category of manifolds over
+ Real Field with 53 bits of precision
The manifold passes all the tests of the test suite relative to its
category::
@@ -491,8 +497,9 @@ class TopologicalManifold(AbstractSet):
sage: TestSuite(M).run()
"""
- def __init__(self, n, name, field, structure, latex_name=None,
- start_index=0, category=None, unique_tag=None):
+ def __init__(self, n, name, field, structure, ambient=None,
+ latex_name=None, start_index=0, category=None,
+ unique_tag=None):
r"""
Construct a topological manifold.
@@ -509,6 +516,13 @@ class TopologicalManifold(AbstractSet):
sage: X.<x,y,z> = M.chart()
sage: TestSuite(M).run()
+ Tests for open subsets::
+
+ sage: U = M.open_subset('U', coord_def={X: x>0})
+ sage: TestSuite(U).run()
+ sage: U.category() is M.category().Subobjects()
+ True
+
"""
# Initialization of the attributes _dim, _field, _field_type:
self._dim = n
@@ -530,11 +544,17 @@ class TopologicalManifold(AbstractSet):
self._field_type = 'neither_real_nor_complex'
# Structure and category:
self._structure = structure
- category = Manifolds(self._field).or_subcategory(category)
- category = self._structure.subcategory(category)
+ if ambient is None:
+ ambient = self
+ category = Manifolds(self._field).or_subcategory(category)
+ category = self._structure.subcategory(category)
+ else:
+ category = ambient.category().Subobjects()
# Initialization as a manifold set:
- AbstractSet.__init__(self, name, latex_name=latex_name,
- base=self._field, category=category)
+ ManifoldSubset.__init__(self, ambient, name, latex_name=latex_name,
+ category=category)
+ self._is_open = True
+ self._open_covers.append([self]) # list of open covers of self
#
if not isinstance(start_index, (int, Integer)):
raise TypeError("the starting index must be an integer")
@@ -552,7 +572,6 @@ class TopologicalManifold(AbstractSet):
# List of charts that individually cover self, i.e. whose
# domains are self (if non-empty, self is a coordinate domain):
self._covering_charts = []
- self._open_covers.append([self]) # list of open covers of self
# Algebra of scalar fields defined on self:
self._scalar_field_algebra = self._structure.scalar_field_algebra(self)
# The zero scalar field:
@@ -588,17 +607,21 @@ class TopologicalManifold(AbstractSet):
'Open subset U of the 3-dimensional topological manifold M over the Rational Field'
"""
- if self._field_type == 'real':
- return "{}-dimensional {} manifold {}".format(self._dim,
- self._structure.name,
- self._name)
- elif self._field_type == 'complex':
- return "Complex {}-dimensional {} manifold {}".format(self._dim,
+ if self is self._manifold:
+ if self._field_type == 'real':
+ return "{}-dimensional {} manifold {}".format(self._dim,
self._structure.name,
self._name)
- return "{}-dimensional {} manifold {} over the {}".format(self._dim,
- self._structure.name, self._name,
- self._field)
+ elif self._field_type == 'complex':
+ return "Complex {}-dimensional {} manifold {}".format(self._dim,
+ self._structure.name,
+ self._name)
+ return "{}-dimensional {} manifold {} over the {}".format(self._dim,
+ self._structure.name,
+ self._name,
+ self._field)
+ else:
+ return "Open subset {} of the {}".format(self._name, self._manifold)
def _an_element_(self):
r"""
@@ -738,21 +761,6 @@ class TopologicalManifold(AbstractSet):
return True
return False
- def manifold(self):
- """
- Return ``self`` since ``self`` is the ambient manifold.
-
- This is for compatibility with
- :class:`~sage.manifolds.subset.ManifoldSubset`.
-
- EXAMPLES::
-
- sage: M = Manifold(2, 'R^2', structure='topological')
- sage: M.manifold() is M
- True
- """
- return self
-
def open_subset(self, name, latex_name=None, coord_def={}):
r"""
Create an open subset of the manifold.
@@ -760,8 +768,7 @@ class TopologicalManifold(AbstractSet):
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:`~sage.manifolds.subset.OpenTopologicalSubmanifold`, which
- inherits from :class:`TopologicalManifold`.
+ :class:`TopologicalManifold`.
INPUT:
@@ -775,8 +782,7 @@ class TopologicalManifold(AbstractSet):
OUTPUT:
- - the open subset, as an instance of
- :class:`~sage.manifolds.subset.OpenTopologicalSubmanifold`.
+ - the open subset, as an instance of :class:`TopologicalManifold`.
EXAMPLES:
@@ -796,6 +802,8 @@ class TopologicalManifold(AbstractSet):
True
sage: dim(A) == dim(M)
True
+ sage: A.category() is M.category().Subobjects()
+ True
Creating an open subset of ``A``::
@@ -837,9 +845,10 @@ class TopologicalManifold(AbstractSet):
False
"""
- from sage.manifolds.subset import OpenTopologicalSubmanifold
- resu = OpenTopologicalSubmanifold(self.manifold(), name,
- latex_name=latex_name)
+ resu = TopologicalManifold(self._dim, name, self._field,
+ self._structure, ambient=self._manifold,
+ latex_name=latex_name,
+ start_index=self._sindex)
resu._supersets.update(self._supersets)
for sd in self._supersets:
sd._subsets.add(resu)
@@ -914,73 +923,6 @@ class TopologicalManifold(AbstractSet):
"do not correspond to any chart with " +
"the {} as domain".format(dom))
- def union(self, other, name=None, latex_name=None):
- r"""
- Return the union of the manifold with a subset, i.e. the manifold
- itself.
-
- INPUT:
-
- - ``other`` -- a subset of the manifold
- - ``name`` -- ignored
- - ``latex_name`` -- ignored
-
- OUTPUT:
-
- - the manifold
-
- EXAMPLES::
-
- sage: M = Manifold(2, 'M', structure='topological')
- sage: A = M.subset('A')
- sage: M.union(A)
- 2-dimensional topological manifold M
- sage: M.union(A) is M
- True
- sage: B = A.subset('B')
- sage: M.union(B) is M
- True
- sage: M.union(M) is M
- True
-
- """
- if other.manifold() is not self:
- raise ValueError("{} is not a subset of this manifold".format(other))
- return self
-
- def intersection(self, other, name=None, latex_name=None):
- r"""
- Return the intersection of the manifold with a subset, i.e. the subset.
-
- INPUT:
-
- - ``other`` -- a subset of the manifold
- - ``name`` -- ignored
- - ``latex_name`` -- ignored
-
- OUTPUT:
-
- - the subset ``other``
-
- EXAMPLES::
-
- sage: M = Manifold(2, 'M', structure='topological')
- sage: A = M.subset('A')
- sage: M.intersection(A)
- Subset A of the 2-dimensional topological manifold M
- sage: M.intersection(A) is A
- True
- sage: B = A.subset('B')
- sage: M.intersection(B) is B
- True
- sage: M.intersection(M) is M
- True
-
- """
- if other.manifold() is not self:
- raise ValueError("{} is not a subset of this manifold".format(other))
- return other
-
def dimension(self):
r"""
Return the dimension of the manifold over its base field.
@@ -1574,7 +1516,8 @@ class TopologicalManifold(AbstractSet):
"""
Return if ``self`` is an open set.
- In the present case (manifold), always return ``True``.
+ In the present case (manifold or open subset of it), always
+ return ``True``.
TEST::
@@ -1585,26 +1528,6 @@ class TopologicalManifold(AbstractSet):
"""
return True
- def superset(self, name=None, latex_name=None, is_open=False):
- r"""
- Return ``self`` since the only superset of the manifold is
- the manifold.
-
- INPUT:
-
- - ``name`` -- ignored
- - ``latex_name`` -- ignored
- - ``is_open`` -- ignored
-
- TEST::
-
- sage: M = Manifold(2, 'M', structure='topological')
- sage: M.superset() is M
- True
-
- """
- return self
-
def scalar_field_algebra(self):
r"""
Return the algebra of scalar fields defined the manifold.
diff --git a/src/sage/manifolds/point.py b/src/sage/manifolds/point.py
index 2f35145..34dbd88 100644
--- a/src/sage/manifolds/point.py
+++ b/src/sage/manifolds/point.py
@@ -1,5 +1,5 @@
r"""
-Points of topological manifolds
+Points of Topological Manifolds
The class :class:`ManifoldPoint` implements points of a
topological manifold.
@@ -80,7 +80,7 @@ class ManifoldPoint(Element):
INPUT:
- - ``parent`` -- the manifold (subset) to which the point belongs
+ - ``parent`` -- the manifold subset to which the point belongs
- ``coords`` -- (default: ``None``) the point coordinates (as a tuple
or a list) in the chart ``chart``
- ``chart`` -- (default: ``None``) chart in which the coordinates are
diff --git a/src/sage/manifolds/scalarfield.py b/src/sage/manifolds/scalarfield.py
index bfed24a..7ce1b31 100644
--- a/src/sage/manifolds/scalarfield.py
+++ b/src/sage/manifolds/scalarfield.py
@@ -1,5 +1,5 @@
r"""
-Scalar fields
+Scalar Fields
Given a topological manifold `M` over a topological field `K` (in most
applications, `K = \RR` or `K = \CC`), a *scalar field* on `M` is a continuous
diff --git a/src/sage/manifolds/scalarfield_algebra.py b/src/sage/manifolds/scalarfield_algebra.py
index e1d211b..37cbb37 100644
--- a/src/sage/manifolds/scalarfield_algebra.py
+++ b/src/sage/manifolds/scalarfield_algebra.py
@@ -1,5 +1,5 @@
r"""
-Scalar field algebra
+Algebra of Scalar Fields
The class :class:`ScalarFieldAlgebra` implements the commutative algebra
`C^0(M)` of scalar fields on a topological manifold `M` over a topological
diff --git a/src/sage/manifolds/structure.py b/src/sage/manifolds/structure.py
index 735410a..f597249 100644
--- a/src/sage/manifolds/structure.py
+++ b/src/sage/manifolds/structure.py
@@ -1,7 +1,7 @@
r"""
-Manifold structures
+Manifold Structures
-These classes encode the sturcture of a manifold.
+These classes encode the structure of a manifold.
AUTHORS:
diff --git a/src/sage/manifolds/subset.py b/src/sage/manifolds/subset.py
index 56254d6..c60f6b1 100644
--- a/src/sage/manifolds/subset.py
+++ b/src/sage/manifolds/subset.py
@@ -1,17 +1,16 @@
r"""
-Subsets of topological manifolds
+Subsets of Topological Manifolds
The class :class:`ManifoldSubset` implements generic subsets of a
topological manifold. Open subsets are implemented by the class
-:class:`~sage.manifolds.subset.OpenTopologicalSubmanifold`, which inherits from
-both :class:`ManifoldSubset` and
-:class:`~sage.manifolds.manifold.TopologicalManifold`.
+:class:`~sage.manifolds.manifold.TopologicalManifold` (since an open subset of
+a manifold is a manifold by itself), which inherits from
+:class:`ManifoldSubset`.
AUTHORS:
- Eric Gourgoulhon, Michal Bejger (2013-2015): initial version
-- Travis Scrimshaw (2015): inheritance from
- :class:`~sage.manifolds.abstract.AbstractSet`
+- Travis Scrimshaw (2015): review tweaks; removal of facade parents
REFERENCES:
@@ -73,23 +72,24 @@ Lists of subsets after the above operations::
# http://www.gnu.org/licenses/
#*****************************************************************************
+from sage.structure.parent import Parent
+from sage.structure.unique_representation import UniqueRepresentation
from sage.categories.sets_cat import Sets
-from sage.manifolds.abstract import AbstractSet
-from sage.manifolds.manifold import TopologicalManifold
+from sage.manifolds.point import ManifoldPoint
-class ManifoldSubset(AbstractSet):
+class ManifoldSubset(UniqueRepresentation, Parent):
r"""
Subset of a topological manifold.
- The class :class:`ManifoldSubset` inherits (via
- :class:`~sage.manifolds.abstract.AbstractSet`) from the generic
+ The class :class:`ManifoldSubset` inherits from the generic
class :class:`~sage.structure.parent.Parent`.
The corresponding element class is
:class:`~sage.manifolds.point.ManifoldPoint`.
Note that open subsets are not implemented directly by this class, but
- by the derived class
- :class:`~sage.manifolds.subset.OpenTopologicalSubmanifold`.
+ by the derived class :class:`~sage.manifolds.manifold.TopologicalManifold`
+ (an open subset of a topological manifold being itself a topological
+ manifold).
INPUT:
@@ -97,6 +97,8 @@ class ManifoldSubset(AbstractSet):
- ``name`` -- string; name (symbol) given to the subset
- ``latex_name`` -- (default: ``None``) string; LaTeX symbol to denote the
subset; if none is provided, it is set to ``name``
+ - ``category`` -- (default: ``None``) to specify the categeory; if ``None``,
+ the category for generic subsets is used
EXAMPLES:
@@ -114,7 +116,8 @@ class ManifoldSubset(AbstractSet):
Instead of importing :class:`ManifoldSubset` in the global
namespace, it is recommended to use the method
- :meth:`~sage.manifolds.abstract.AbstractSet.subset` to create a new subset::
+ :meth:`~sage.manifolds.subset.ManifoldSubset.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
@@ -123,6 +126,13 @@ class ManifoldSubset(AbstractSet):
Subset B of the 2-dimensional topological manifold M,
2-dimensional topological manifold M]
+ The manifold is itself a subset::
+
+ sage: isinstance(M, ManifoldSubset)
+ True
+ sage: M in M.subsets()
+ True
+
Instances of :class:`ManifoldSubset` are parents::
sage: isinstance(A, Parent)
@@ -137,9 +147,12 @@ class ManifoldSubset(AbstractSet):
True
sage: p in M
True
+
"""
- def __init__(self, manifold, name, latex_name=None):
+ Element = ManifoldPoint
+
+ def __init__(self, manifold, name, latex_name=None, category=None):
r"""
Construct a manifold subset.
@@ -152,27 +165,47 @@ class ManifoldSubset(AbstractSet):
<class 'sage.manifolds.subset.ManifoldSubset_with_category'>
sage: A.category()
Category of subobjects of sets
- sage: TestSuite(A).run(skip=['_test_elements', \
- '_test_not_implemented_methods'])
+ sage: TestSuite(A).run(skip='_test_elements')
- .. TODO::
+ .. NOTE::
- implement method ``lift`` so that ``_test_not_implemented_methods``
- is passed.
- NB: ``_test_elements`` cannot be passed without a proper
+ ``_test_elements`` cannot be passed without a proper
coordinate definition of the subset.
"""
- for dom in manifold._subsets:
- if name == dom._name:
- raise ValueError("the name '" + name +
- "' is already used for another " +
- "subset of the {}".format(manifold))
- category = Sets().Subobjects()
- AbstractSet.__init__(self, name=name, latex_name=latex_name,
- category=category)
- self._manifold = manifold
- manifold._subsets.add(self)
+ 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
+ else:
+ if not isinstance(latex_name, str):
+ raise TypeError("{} is not a string".format(latex_name))
+ self._latex_name = latex_name
+ if category is None:
+ category = Sets().Subobjects()
+ base = None
+ else:
+ base = manifold._field
+ Parent.__init__(self, base=base, category=category)
+ if self is not 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
+ # in another strict subset of self
+ self._intersections = {} # dict. of intersections with other subsets
+ # (key: subset name)
+ self._unions = {} # dict. of unions with other subsets (key: subset
+ # name)
+ self._open_covers = [] # list of open covers of self
+ self._is_open = False # a priori (may be redifined by subclasses)
+ self._manifold = manifold # the ambient manifold
def _repr_(self):
r"""
@@ -190,6 +223,260 @@ class ManifoldSubset(AbstractSet):
"""
return "Subset {} of the {}".format(self._name, self._manifold)
+ def _latex_(self):
+ r"""
+ LaTeX representation of ``self``.
+
+ TESTS::
+
+ sage: M = Manifold(2, 'M', structure='topological')
+ sage: A = M.subset('A')
+ sage: A._latex_()
+ 'A'
+ sage: B = A.subset('B', latex_name=r'\mathcal{B}')
+ sage: B._latex_()
+ '\\mathcal{B}'
+ sage: latex(B) # indirect doctest
+ \mathcal{B}
+
+ sage: M = Manifold(3, 'M', structure='topological')
+ sage: M._latex_()
+ 'M'
+ sage: latex(M)
+ M
+ sage: M = Manifold(3, 'M', latex_name=r'\mathcal{M}',
+ ....: structure='topological')
+ sage: M._latex_()
+ '\\mathcal{M}'
+ sage: latex(M) # indirect doctest
+ \mathcal{M}
+ """
+ return self._latex_name
+
+ #### Methods required for any Parent in the category of sets:
+
+ def _element_constructor_(self, coords=None, chart=None, name=None,
+ latex_name=None, check_coords=True):
+ r"""
+ Construct a point in the subset from its coordinates in some chart.
+
+ INPUT:
+
+ - ``coords`` -- (default: ``None``) either (i) the point coordinates
+ (as a tuple or a list) in the chart ``chart`` or (ii) another point
+ in the subset
+ - ``chart`` -- (default: ``None``) chart in which the coordinates are
+ given; if none is provided, the coordinates are assumed to refer to
+ the subset's default chart
+ - ``name`` -- (default: ``None``) name given to the point
+ - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
+ point; if none is provided, the LaTeX symbol is set to ``name``
+ - ``check_coords`` -- (default: ``True``) determines whether ``coords``
+ are valid coordinates for the chart ``chart``; for symbolic
+ coordinates, it is recommended to set ``check_coords`` to ``False``.
+
+ OUTPUT:
+
+ - an instance of :class:`~sage.manifolds.point.ManifoldPoint`
+ representing a point in the current subset.
+
+ EXAMPLES::
+
+ sage: M = Manifold(2, 'M', structure='topological')
+ sage: X.<x,y> = M.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)
+
+ A generic subset has no default chart, so the chart must be explicited::
+
+ sage: A = M.subset('A')
+ sage: p = A((-2,3), chart=X); p
+ Point on the 2-dimensional topological manifold M
+ sage: X(p)
+ (-2, 3)
+ sage: p.parent()
+ Subset A of the 2-dimensional topological manifold M
+ sage: p in A
+ True
+
+ Coordinates in a chart with some coordinate restrictions::
+
+ sage: Y.<u,v> = M.chart('u:(-1,1) v:(-1,1)')
+ 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((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((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((-2,3), chart=X, name='p'); p
+ Point p on the 2-dimensional topological manifold M
+
+ A point as entry::
+
+ sage: q = A(p); q
+ Point p on the 2-dimensional topological manifold M
+ sage: X(q)
+ (-2, 3)
+
+ """
+ if isinstance(coords, ManifoldPoint):
+ point = coords # for readability
+ # This should actually never happen by the coercion framework...
+ if point.parent() is self:
+ return point
+ if point in self:
+ resu = self.element_class(self, name=point._name,
+ latex_name=point._latex_name)
+ for chart, coords in point._coordinates.iteritems():
+ resu._coordinates[chart] = coords
+ return resu
+ else:
+ raise ValueError("the {}".format(point) +
+ " is not in {}".format(self))
+ return self.element_class(self, coords=coords, chart=chart, name=name,
+ latex_name=latex_name,
+ check_coords=check_coords)
+
+ def _an_element_(self):
+ r"""
+ Construct some point in the subset.
+
+ EXAMPLES::
+
+ sage: M = Manifold(2, 'M', structure='topological')
+ sage: X.<x,y> = M.chart()
+ sage: A = M.subset('A')
+ sage: p = A._an_element_(); p
+ Point on the 2-dimensional topological manifold M
+ sage: p in A
+ True
+
+ """
+ #!# should be improved...
+ return self.element_class(self)
+
+ #### End of methods required for any Parent in the category of sets
+
+ def __contains__(self, point):
+ r"""
+ Check whether ``point`` is contained in ``self``.
+
+ TESTS::
+
+ sage: M = Manifold(2, 'M', structure='topological')
+ sage: X.<x,y> = M.chart()
+ sage: A = M.subset('A')
+ sage: p = A((-2,3), chart=X); p
+ Point on the 2-dimensional topological manifold M
+ sage: A.__contains__(p)
+ True
+ sage: p in A # indirect doctest
+ True
+ sage: A.__contains__(A.an_element())
+ True
+ sage: q = M((0,0), chart=X); q
+ Point on the 2-dimensional topological manifold M
+ sage: A.__contains__(q)
+ False
+ """
+ # for efficiency, a quick test first:
+ if point.parent() is self:
+ return True
+ if point.parent().is_subset(self):
+ return True
+ #!# should be improved once coordinate definition have been introduced
+ # in ManifoldSubset
+ return False
+
+ def lift(self, p):
+ r"""
+ Lift map.
+
+ INPUT:
+
+ - ``p`` -- point of the subset
+
+ OUTPUT:
+
+ - the same point, considered as a point of the ambient manifold
+
+ EXAMPLE::
+
+ sage: M = Manifold(2, 'M', structure='topological')
+ sage: X.<x,y> = M.chart()
+ sage: A = M.open_subset('A', coord_def={X: x>0})
+ sage: p = A((1, -2)); p
+ Point on the 2-dimensional topological manifold M
+ sage: p.parent()
+ Open subset A of the 2-dimensional topological manifold M
+ sage: q = A.lift(p); q
+ Point on the 2-dimensional topological manifold M
+ sage: q.parent()
+ 2-dimensional topological manifold M
+ sage: q.coord()
+ (1, -2)
+ sage: (p == q) and (q == p)
+ True
+
+ """
+ return self._manifold(p)
+
+ def retract(self, p):
+ r"""
+ Retraction map.
+
+ INPUT:
+
+ - ``p`` -- point of the ambient manifold
+
+ OUTPUT:
+
+ - the same point, considered as a point of the subset
+
+ EXAMPLES::
+
+ sage: M = Manifold(2, 'M', structure='topological')
+ sage: X.<x,y> = M.chart()
+ sage: A = M.open_subset('A', coord_def={X: x>0})
+ sage: p = M((1, -2)); p
+ Point on the 2-dimensional topological manifold M
+ sage: p.parent()
+ 2-dimensional topological manifold M
+ sage: q = A.retract(p); q
+ Point on the 2-dimensional topological manifold M
+ sage: q.parent()
+ Open subset A of the 2-dimensional topological manifold M
+ sage: q.coord()
+ (1, -2)
+ sage: (q == p) and (p == q)
+ True
+
+ Of course, if the point does not belong to ``A``, the ``retract``
+ method fails::
+
+ sage: p = M((-1, 3)) # x < 0, so that p is not in A
+ sage: q = A.retract(p)
+ Traceback (most recent call last):
+ ...
+ ValueError: the Point on the 2-dimensional topological manifold M
+ is not in Open subset A of the 2-dimensional topological manifold M
+
+ """
+ return self(p)
+
+ #### Accessors
+
def manifold(self):
r"""
Return the manifold of which the current object is a subset.
@@ -222,7 +509,7 @@ class ManifoldSubset(AbstractSet):
This method always returns ``False``, since open subsets must be
constructed as instances of the subclass
- :class:`~sage.manifolds.subset.OpenTopologicalSubmanifold`
+ :class:`~sage.manifolds.manifold.TopologicalManifold`
(which redefines ``is_open``)
EXAMPLE::
@@ -235,6 +522,357 @@ class ManifoldSubset(AbstractSet):
"""
return False
+ def open_covers(self):
+ r"""
+ Return the list of open covers of the current subset.
+
+ If the current subset, `A` say, is a subset of the manifold `M`, an
+ *open cover* of `A` is list (indexed set) `(U_i)_{i\in I}` of
+ open subsets of `M` such that
+
+ .. MATH::
+
+ A \subset \bigcup_{i \in I} U_i
+
+ If `A` is open, we ask that the above inclusion is actually an
+ identity:
+
+ .. MATH::
+
+ A = \bigcup_{i \in I} U_i
+
+ EXAMPLES::
+
+ sage: M = Manifold(2, 'M', structure='topological')
+ sage: M.open_covers()
+ [[2-dimensional topological manifold M]]
+ sage: U = M.open_subset('U')
+ sage: U.open_covers()
+ [[Open subset U of the 2-dimensional topological manifold M]]
+ sage: A = U.open_subset('A')
+ sage: B = U.open_subset('B')
+ sage: U.declare_union(A,B)
+ sage: U.open_covers()
+ [[Open subset U of the 2-dimensional topological manifold M],
+ [Open subset A of the 2-dimensional topological manifold M,
+ Open subset B of the 2-dimensional topological manifold M]]
+ sage: V = M.open_subset('V')
+ sage: M.declare_union(U,V)
+ sage: M.open_covers()
+ [[2-dimensional topological manifold M],
+ [Open subset U of the 2-dimensional topological manifold M,
+ Open subset V of the 2-dimensional topological manifold M],
+ [Open subset A of the 2-dimensional topological manifold M,
+ Open subset B of the 2-dimensional topological manifold M,
+ Open subset V of the 2-dimensional topological manifold M]]
+
+ """
+ return self._open_covers
+
+ def subsets(self):
+ r"""
+ Return the set of subsets that have been defined on the current subset.
+
+ OUTPUT:
+
+ - A Python set containing all the subsets that have been defined on
+ the current subset.
+
+ .. NOTE::
+
+ To get the subsets as a list, used the method
+ :meth:`list_of_subsets` instead.
+
+ EXAMPLE:
+
+ Subsets of a 2-dimensional manifold::
+
+ sage: M = Manifold(2, 'M', structure='topological')
+ sage: U = M.open_subset('U')
+ sage: V = M.subset('V')
+ sage: M.subsets() # random (set output)
+ {Subset V of the 2-dimensional topological manifold M,
+ 2-dimensional topological manifold M,
+ Open subset U of the 2-dimensional topological manifold M}
+ sage: type(M.subsets())
+ <type 'frozenset'>
+ sage: U in M.subsets()
+ True
+
+ The method :meth:`list_of_subsets` returns a list (sorted
+ alphabetically by the subset names) instead of a set::
+
+ sage: M.list_of_subsets()
+ [2-dimensional topological manifold M,
+ Open subset U of the 2-dimensional topological manifold M,
+ Subset V of the 2-dimensional topological manifold M]
+
+ """
+ return frozenset(self._subsets)
+
+ def list_of_subsets(self):
+ r"""
+ Return the list of subsets that have been defined on the current
+ subset.
+
+ The list is sorted by the alphabetical names of the subsets.
+
+ OUTPUT:
+
+ - A list containing all the subsets that have been defined on
+ the current subset.
+
+ .. NOTE::
+
+ To get the subsets as a Python set, used the method
+ :meth:`subsets` instead.
+
+ EXAMPLE:
+
+ Subsets of a 2-dimensional manifold::
+
+ sage: M = Manifold(2, 'M', structure='topological')
+ sage: U = M.open_subset('U')
+ sage: V = M.subset('V')
+ sage: M.list_of_subsets()
+ [2-dimensional topological manifold M,
+ Open subset U of the 2-dimensional topological manifold M,
+ Subset V of the 2-dimensional topological manifold M]
+
+ The method :meth:`subsets` returns a set instead of a list::
+
+ sage: M.subsets() # random (set output)
+ {Subset V of the 2-dimensional topological manifold M,
+ 2-dimensional topological manifold M,
+ Open subset U of the 2-dimensional topological manifold M}
+
+ """
+ return sorted(self._subsets, key=lambda x: x._name)
+
+ def get_subset(self, name):
+ r"""
+ Get a subset by its name.
+
+ The subset must have been previously created by the method
+ :meth:`subset` (or
+ :meth:`~sage.manifolds.manifold.TopologicalManifold.open_subset`)
+
+ INPUT:
+
+ - ``name`` -- (string) name of the subset
+
+ OUTPUT:
+
+ - instance of :class:`~sage.manifolds.subset.ManifoldSubset` (or
+ of the derived class
+ :class:`~sage.manifolds.manifold.TopologicalManifold` for an open
+ subset) representing the subset whose name is ``name``.
+
+ EXAMPLES::
+
+ sage: M = Manifold(4, 'M', structure='topological')
+ sage: A = M.subset('A')
+ sage: B = A.subset('B')
+ sage: U = M.open_subset('U')
+ sage: M.list_of_subsets()
+ [Subset A of the 4-dimensional topological manifold M,
+ Subset B of the 4-dimensional topological manifold M,
+ 4-dimensional topological manifold M,
+ Open subset U of the 4-dimensional topological manifold M]
+ sage: M.get_subset('A')
+ Subset A of the 4-dimensional topological manifold M
+ sage: M.get_subset('A') is A
+ True
+ sage: M.get_subset('B') is B
+ True
+ sage: A.get_subset('B') is B
+ True
+ sage: M.get_subset('U')
+ Open subset U of the 4-dimensional topological manifold M
+ sage: M.get_subset('U') is U
+ True
+
+ """
+ for ss in self._subsets:
+ if ss._name == name:
+ return ss
+ raise ValueError("no subset of name '{}' found".format(name))
+
+ #### End of accessors
+
+ def is_subset(self, other):
+ r"""
+ Return ``True`` iff ``self`` is included in ``other``.
+
+ EXAMPLES:
+
+ Subsets on a 2-dimensional manifold::
+
+ sage: M = Manifold(2, 'M', structure='topological')
+ sage: a = M.subset('A')
+ sage: b = a.subset('B')
+ sage: c = M.subset('C')
+ sage: a.is_subset(M)
+ True
+ sage: b.is_subset(a)
+ True
+ sage: b.is_subset(M)
+ True
+ sage: a.is_subset(b)
+ False
+ sage: c.is_subset(a)
+ False
+ """
+ return self in other._subsets
+
+ def declare_union(self, dom1, dom2):
+ r"""
+ Declare that the current subset is the union of two subsets,
+ i.e. that
+
+ .. MATH::
+
+ U = U_1 \cup U_2,
+
+ where `U` is the current subset, `U_1 \subset U` and `U_2 \subset U`.
+
+ INPUT:
+
+ - ``dom1`` -- subset `U_1`
+ - ``dom2`` -- subset `U_2`
+
+ EXAMPLE::
+
+ sage: M = Manifold(2, 'M', structure='topological')
+ sage: A = M.subset('A')
+ sage: B = M.subset('B')
+ sage: M.declare_union(A, B)
+ sage: A.union(B)
+ 2-dimensional topological manifold M
+
+ """
+ if dom1 == dom2:
+ if dom1 != self:
+ raise ValueError("the union of two identical sets must be " +
+ "this set")
+ return
+ if not dom1.is_subset(self):
+ raise TypeError("the {} is not a subset of ".format(dom1) +
+ "the {}".format(self))
+ if not dom2.is_subset(self):
+ raise TypeError("the {} is not a subset of ".format(dom2) +
+ "the {}".format(self))
+ dom1._unions[dom2._name] = self
+ dom2._unions[dom1._name] = self
+ for oc1 in dom1._open_covers:
+ for oc2 in dom2._open_covers:
+ oc = oc1[:]
+ for s in oc2:
+ if s not in oc:
+ oc.append(s)
+ self._open_covers.append(oc)
+
+ def point(self, coords=None, chart=None, name=None, latex_name=None):
+ r"""
+ Define a point in ``self``.
+
+ See :class:`~sage.manifolds.point.ManifoldPoint` for a
+ complete documentation.
+
+ INPUT:
+
+ - ``coords`` -- the point coordinates (as a tuple or a list) in the
+ chart specified by ``chart``
+ - ``chart`` -- (default: ``None``) chart in which the point coordinates
+ are given; if ``None``, the coordinates are assumed to refer to
+ the default chart of the current subset
+ - ``name`` -- (default: ``None``) name given to the point
+ - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
+ point; if ``None``, the LaTeX symbol is set to ``name``
+
+ OUTPUT:
+
+ - the declared point, as an instance of
+ :class:`~sage.manifolds.point.ManifoldPoint`.
+
+ EXAMPLES:
+
+ Points on a 2-dimensional manifold::
+
+ sage: M = Manifold(2, 'M', structure='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
+ sage: p in M
+ True
+ sage: a = M.open_subset('A')
+ sage: c_uv.<u,v> = a.chart()
+ sage: q = a.point((-1,0), name='q'); q
+ Point q on the 2-dimensional topological manifold M
+ sage: q in a
+ True
+ sage: p._coordinates
+ {Chart (M, (x, y)): (1, 2)}
+ sage: q._coordinates
+ {Chart (A, (u, v)): (-1, 0)}
+ """
+ return self.element_class(self, coords=coords, chart=chart,
+ name=name, latex_name=latex_name)
+
+ #### Construction of new sets from self:
+
+ def subset(self, name, latex_name=None, is_open=False):
+ r"""
+ Create a subset of the current subset.
+
+ INPUT:
+
+ - ``name`` -- name given to the subset
+ - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
+ subset; if none is provided, it is set to ``name``
+ - ``is_open`` -- (default: ``False``) if ``True``, the created subset
+ is assumed to be open with respect to the manifold's topology
+
+ OUTPUT:
+
+ - the subset, as an instance of :class:`ManifoldSubset`, or
+ of the derived class
+ :class:`~sage.manifolds.manifold.TopologicalManifold` if ``is_open``
+ is ``True``.
+
+ EXAMPLES:
+
+ Creating a subset of a manifold::
+
+ sage: M = Manifold(2, 'M', structure='topological')
+ sage: a = M.subset('A'); a
+ Subset A of the 2-dimensional topological manifold M
+
+ Creating a subset of A::
+
+ sage: b = a.subset('B', latex_name=r'\mathcal{B}'); b
+ Subset B of the 2-dimensional topological manifold M
+ sage: latex(b)
+ \mathcal{B}
+
+ We have then::
+
+ sage: b.is_subset(a)
+ True
+ sage: b in a.subsets()
+ True
+
+
+ """
+ if is_open:
+ return self.open_subset(name, latex_name=latex_name)
+ res = ManifoldSubset(self._manifold, name, latex_name=latex_name)
+ res._supersets.update(self._supersets)
+ for sd in self._supersets:
+ sd._subsets.add(res)
+ self._top_subsets.add(res)
+ return res
+
def superset(self, name, latex_name=None, is_open=False):
r"""
Create a superset of the current subset.
@@ -254,7 +892,7 @@ class ManifoldSubset(AbstractSet):
- the superset, as an instance of :class:`ManifoldSubset` or
of the derived class
- :class:`~sage.manifolds.subset.OpenTopologicalSubmanifold` if ``is_open``
+ :class:`~sage.manifolds.manifold.TopologicalManifold` if ``is_open``
is ``True``.
EXAMPLES:
@@ -262,28 +900,43 @@ class ManifoldSubset(AbstractSet):
Creating some superset of a given subset::
sage: M = Manifold(2, 'M', structure='topological')
- sage: A = M.subset('A')
- sage: B = A.superset('B'); B
+ sage: a = M.subset('A')
+ sage: b = a.superset('B'); b
Subset B of the 2-dimensional topological manifold M
- sage: B.list_of_subsets()
+ sage: b.list_of_subsets()
[Subset A of the 2-dimensional topological manifold M,
Subset B of the 2-dimensional topological manifold M]
- sage: A._supersets # random (set output)
+ sage: a._supersets # random (set output)
{Subset B of the 2-dimensional topological manifold M,
Subset A of the 2-dimensional topological manifold M,
2-dimensional topological manifold M}
+ The superset of the whole manifold is itself::
+
+ sage: M.superset('SM') is M
+ True
+
Two supersets of a given subset are a priori different::
- sage: C = A.superset('C')
- sage: C == B
+ sage: c = a.superset('C')
+ sage: c == b
False
"""
- res = self._manifold.subset(name, latex_name, is_open)
+ if self is self._manifold:
+ return self
+ if is_open:
+ res = self._manifold.open_subset(name, latex_name=latex_name)
+ else:
+ res = ManifoldSubset(self._manifold, name, latex_name=latex_name)
res._subsets.update(self._subsets)
for sd in self._subsets:
sd._supersets.add(res)
+ if is_open and self._is_open:
+ res._atlas = list(self._atlas)
+ res._top_charts = list(self._top_charts)
+ res._coord_changes = dict(self._coord_changes)
+ res._def_chart = self._def_chart
return res
def intersection(self, other, name=None, latex_name=None):
@@ -296,7 +949,7 @@ class ManifoldSubset(AbstractSet):
- ``name`` -- (default: ``None``) name given to the intersection in the
case the latter has to be created; the default is
``self._name`` inter ``other._name``
- - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
+ - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
intersection in the case the latter has to be created; the default
is built upon the symbol `\cap`
@@ -342,43 +995,44 @@ class ManifoldSubset(AbstractSet):
True
sage: a.intersection(M) is a
True
+
"""
+ if other._manifold != self._manifold:
+ raise ValueError(
+ "the two subsets do not belong to the same manifold")
# Particular cases:
+ if self is self._manifold:
+ return other
if other is self._manifold:
return self
if self in other._subsets:
return self
if other in self._subsets:
return other
- if other._manifold != self._manifold:
- raise ValueError("the two subsets do not belong to the same manifold")
-
# Generic case:
if other._name in self._intersections:
# the intersection has already been created:
return self._intersections[other._name]
-
- # TODO: Check to see if we've already created a union of ``self`` and ``other``
-
- # the intersection must be created:
- if latex_name is None:
+ else:
+ # the intersection must be created:
+ if latex_name is None:
+ if name is None:
+ latex_name = self._latex_name + r'\cap ' + other._latex_name
+ else:
+ latex_name = name
if name is None:
- latex_name = self._latex_name + r'\cap ' + other._latex_name
+ name = self._name + "_inter_" + other._name
+ if self._is_open and other._is_open:
+ res = self.open_subset(name, latex_name=latex_name)
else:
- latex_name = name
- if name is None:
- name = self._name + "_inter_" + other._name
- if self.is_open() and other.is_open():
- res = self.open_subset(name, latex_name=latex_name)
- else:
- res = self.subset(name, latex_name=latex_name)
- res._supersets.update(other._supersets)
- for sd in other._supersets:
- sd._subsets.add(res)
- other._top_subsets.add(res)
- self._intersections[other._name] = res
- other._intersections[self._name] = res
- return res
+ res = self.subset(name, latex_name=latex_name)
+ res._supersets.update(other._supersets)
+ for sd in other._supersets:
+ sd._subsets.add(res)
+ other._top_subsets.add(res)
+ self._intersections[other._name] = res
+ other._intersections[self._name] = res
+ return res
def union(self, other, name=None, latex_name=None):
r"""
@@ -439,256 +1093,54 @@ class ManifoldSubset(AbstractSet):
True
"""
+ if other._manifold != self._manifold:
+ raise ValueError(
+ "the two subsets do not belong to the same manifold")
# Particular cases:
- if other is self._manifold:
+ if (self is self._manifold) or (other is self._manifold):
return self._manifold
if self in other._subsets:
return other
if other in self._subsets:
return self
- if other.manifold() != self._manifold:
- raise ValueError("the two subsets do not belong to the same manifold")
-
# Generic case:
if other._name in self._unions:
# the union has already been created:
return self._unions[other._name]
-
- # TODO: Check to see if we've already created a union of ``self`` and ``other``
-
- # the union must be created:
- if latex_name is None:
+ else:
+ # the union must be created:
+ if latex_name is None:
+ if name is None:
+ latex_name = self._latex_name + r'\cup ' + other._latex_name
+ else:
+ latex_name = name
if name is None:
- latex_name = self._latex_name + r'\cup ' + other._latex_name
- else:
- latex_name = name
- if name is None:
- name = self._name + "_union_" + other._name
- res_open = self.is_open() and other.is_open()
- res = self.superset(name, latex_name, is_open=res_open)
- res._subsets.update(other._subsets)
- res._top_subsets.add(self)
- res._top_subsets.add(other)
- for sd in other._subsets:
- sd._supersets.add(res)
- if res_open:
- for chart in other._atlas:
- if chart not in res._atlas:
- res._atlas.append(chart)
- for chart in other._top_charts:
- if chart not in res._top_charts:
- res._top_charts.append(chart)
- res._coord_changes.update(other._coord_changes)
- self._unions[other._name] = res
- other._unions[self._name] = res
- # Open covers of the union:
- for oc1 in self._open_covers:
- for oc2 in other._open_covers:
- oc = oc1[:]
- for s in oc2:
- if s not in oc:
- oc.append(s)
- res._open_covers.append(oc)
- return res
-
-#*****************************************************************************
-
-class OpenTopologicalSubmanifold(ManifoldSubset, TopologicalManifold):
- """
- An open submanifold of a topological manifold, which is any open subset
- of the manifold.
-
- INPUT:
-
- - ``ambient`` -- topological manifold on which the subset is defined
- - ``name`` -- string; name (symbol) given to the subset
- - ``latex_name`` -- (default: ``None``) string; LaTeX symbol to denote the
- subset; if none is provided, it is set to ``name``
-
- EXAMPLE:
-
- The unit ball of the Euclidean 2-plane::
-
- sage: M = Manifold(2, 'M', structure='topological')
- sage: X.<x,y> = M.chart()
- sage: B = M.open_subset('B', coord_def={X: x^2+y^2<1})
- sage: B
- Open subset B of the 2-dimensional topological manifold M
- sage: type(B)
- <class 'sage.manifolds.subset.OpenTopologicalSubmanifold_with_category'>
- sage: B.category()
- Join of Category of subobjects of sets and Category of manifolds over
- Real Field with 53 bits of precision
-
- An open subset of a topological manifold being a topological manifold
- by itself, ``B`` inherits of all the methods of class
- :class:`~sage.manifolds.manifold.TopologicalManifold`::
-
- sage: isinstance(B, sage.manifolds.manifold.TopologicalManifold)
- True
- sage: dim(B)
- 2
- sage: B.base_field()
- Real Field with 53 bits of precision
-
- Given the definition of ``B``, it is automatically endowed with a chart,
- which is the restriction of ``X`` to ``B``::
-
- sage: B.atlas()
- [Chart (B, (x, y))]