summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Gourgoulhon <eric.gourgoulhon@obspm.fr>2015-12-13 23:24:56 +0100
committerEric Gourgoulhon <eric.gourgoulhon@obspm.fr>2015-12-13 23:24:56 +0100
commitcdfa817ba2779f89cd720d05b8738edd66d422d6 (patch)
tree71801230efbdd4c383c9240f8a2a50abeb3b8e10
parentMerge branch 'public/manifolds/top_manif_basics' of git://trac.sagemath.org/s... (diff)
parentRefactoring the code to separate out the structural part of the manifold. (diff)
Merge branch u/tscrim/top_manifolds_refactor into Sage 6.10.rc1 + public/manifolds/top_manif_basics
-rw-r--r--src/sage/manifolds/abstract.py620
-rw-r--r--src/sage/manifolds/all.py2
-rw-r--r--src/sage/manifolds/chart.py24
-rw-r--r--src/sage/manifolds/manifold.py544
-rw-r--r--src/sage/manifolds/point.py84
-rw-r--r--src/sage/manifolds/structure.py52
-rw-r--r--src/sage/manifolds/subset.py773
7 files changed, 1172 insertions, 927 deletions
diff --git a/src/sage/manifolds/abstract.py b/src/sage/manifolds/abstract.py
new file mode 100644
index 0000000..539393f
--- /dev/null
+++ b/src/sage/manifolds/abstract.py
@@ -0,0 +1,620 @@
+r"""
+Abstract objects and sets
+
+These are base classes for the manifolds.
+
+AUTHORS:
+
+- Eric Gourgoulhon (2015): initial version
+- Travis Scrimshaw (2015-11-25): Initial version
+"""
+
+#*****************************************************************************
+# Copyright (C) 2015 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr>
+# Copyright (C) 2015 Michal Bejger <bejger@camk.edu.pl>
+#
+# 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 AbstractObject(object):
+ """
+ An abstract object.
+
+ An abstract object is a variable name and latex name.
+ """
+ def __init__(self, name, latex_name=None):
+ """
+ Initialize ``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
+
+ def _repr_(self):
+ """
+ Return a string representation of ``self``.
+ """
+ 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)
+ \mathcal{M}
+ """
+ return self._latex_name
+
+class AbstractSet(AbstractObject, UniqueRepresentation, Parent):
+ """
+ An abstract set.
+
+ An abstract set is an :class:`AbstractObject` along with its known
+ subsets, supersets, intersections, unions, and open covers.
+ """
+ def __init__(self, name, latex_name, 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
+ """
+ AbstractObject.__init__(self, 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 = set() # set 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.containing_set()
+ 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 sorted(sorted(oc, key=lambda x: x._name) for oc in 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)
+
+ # Do we need this?
+ 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:`ManifoldSubset`, or
+ of the derived class
+ :class:`~sage.manifolds.manifold.Manifold` 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.Manifold.open_subset`)
+
+ INPUT:
+
+ - ``name`` -- (string) name of the subset
+
+ OUTPUT:
+
+ - instance of :class:`ManifoldSubset` (or
+ of the derived class
+ :class:`~sage.manifolds.manifold.Manifold` 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 = set(oc1) # Make a (shallow) copy
+ for s in oc2:
+ if s not in oc:
+ oc.add(s)
+ self._open_covers.add(frozenset(oc))
+
+ def is_open(self):
+ """
+ Return if ``self`` is an open set.
+ """
+ return True
+
+ 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/all.py b/src/sage/manifolds/all.py
index c7defde..367ca68 100644
--- a/src/sage/manifolds/all.py
+++ b/src/sage/manifolds/all.py
@@ -1,2 +1,2 @@
from sage.misc.lazy_import import lazy_import
-lazy_import('sage.manifolds.manifold', 'Manifold')
+lazy_import('sage.manifolds.manifold', 'manifold_constructor', 'Manifold')
diff --git a/src/sage/manifolds/chart.py b/src/sage/manifolds/chart.py
index e2e4974..2752731 100644
--- a/src/sage/manifolds/chart.py
+++ b/src/sage/manifolds/chart.py
@@ -38,16 +38,15 @@ from sage.structure.unique_representation import UniqueRepresentation
from sage.symbolic.ring import SR
from sage.rings.infinity import Infinity
from sage.misc.latex import latex
-from sage.manifolds.manifold import TopologicalManifold
class Chart(UniqueRepresentation, SageObject):
r"""
- Chart on a topological manifold.
+ Chart on a manifold.
- 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`.
+ 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`.
The components `(x^1, \ldots, x^n)` of `\varphi`, defined by
`\varphi(p) = (x^1(p), \ldots, x^n(p)) \in K^n` for any point
@@ -56,7 +55,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.TopologicalManifold`)
+ an instance of :class:`~sage.manifolds.manifold.Manifold`)
- ``coordinates`` -- (default: ``''`` (empty string)) single string
defining the coordinate symbols, with ``' '`` (whitespace) as a
separator; each item has at most two fields, separated by ``:``:
@@ -203,7 +202,7 @@ class Chart(UniqueRepresentation, SageObject):
Manifold subsets have a *default chart*, which, unless changed via the
method
- :meth:`~sage.manifolds.manifold.TopologicalManifold.set_default_chart`,
+ :meth:`~sage.manifolds.manifold.Manifold.set_default_chart`,
is the first defined chart on the subset (or on a open subset of it)::
sage: M.default_chart()
@@ -248,7 +247,8 @@ class Chart(UniqueRepresentation, SageObject):
sage: TestSuite(X).run()
"""
- if not isinstance(domain, TopologicalManifold):
+ from sage.manifolds.manifold import Manifold
+ if not isinstance(domain, Manifold):
raise TypeError("the first argument must be an open subset of " +
"a topological manifold")
if coordinates == '':
@@ -560,7 +560,7 @@ class Chart(UniqueRepresentation, SageObject):
INPUT:
- ``subset`` -- open subset `V` of the chart domain `U` (must be an
- instance of :class:`~sage.manifolds.manifold.TopologicalManifold`)
+ instance of :class:`~sage.manifolds.manifold.Manifold`)
- ``restrictions`` -- (default: ``None``) list of coordinate
restrictions defining the subset `V`.
A restriction can be any symbolic equality or
@@ -979,7 +979,7 @@ class RealChart(Chart):
Manifold subsets have a *default chart*, which, unless changed via the
method
- :meth:`~sage.manifolds.manifold.TopologicalManifold.set_default_chart`,
+ :meth:`~sage.manifolds.manifold.Manifold.set_default_chart`,
is the first defined chart on the subset (or on a open subset of it)::
sage: M.default_chart()
@@ -1402,7 +1402,7 @@ class RealChart(Chart):
INPUT:
- ``subset`` -- open subset `V` of the chart domain `U` (must be an
- instance of :class:`~sage.manifolds.manifold.TopologicalManifold`)
+ instance of :class:`~sage.manifolds.manifold.Manifold`)
- ``restrictions`` -- (default: ``None``) list of coordinate
restrictions defining the subset `V`.
A restriction can be any symbolic equality or
diff --git a/src/sage/manifolds/manifold.py b/src/sage/manifolds/manifold.py
index 39155c7..f18e7ab 100644
--- a/src/sage/manifolds/manifold.py
+++ b/src/sage/manifolds/manifold.py
@@ -1,5 +1,5 @@
r"""
-Topological manifolds
+Manifolds
Given a topological field `K` (in most applications, `K = \RR` or
`K = \CC`) and a non-negative integer `n`, a *topological manifold of
@@ -10,14 +10,14 @@ dimension* `n` *over K* is a topological space `M` such that
- every point in `M` has a neighborhood homeomorphic to `K^n`
Topological manifolds are implemented via the class
-:class:`TopologicalManifold`. Open subsets of topological manifolds
-are also implemented via :class:`TopologicalManifold`, since they are
+:class:`Manifold`. Open subsets of topological manifolds
+are also implemented via :class:`Manifold`, 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:`TopologicalManifold` serves as a base class for more specific
+:class:`Manifold` serves as a base class for more specific
manifold classes.
The user interface is provided by the generic function :func:`Manifold`,
@@ -259,7 +259,7 @@ The following subsets and charts have been defined::
AUTHORS:
- Eric Gourgoulhon (2015): initial version
-- Travis Scrimshaw (2015): review tweaks
+- Travis Scrimshaw (2015): inheritance from AbstractSet
REFERENCES:
@@ -285,15 +285,21 @@ 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.manifolds.subset import TopologicalManifoldSubset
+from sage.rings.integer import Integer
+from sage.manifolds.abstract import AbstractSet
+from sage.manifolds.structure import TopologicalStructure, RealTopologicalStructure
-class TopologicalManifold(TopologicalManifoldSubset):
+#####################################################################
+## Classes
+
+class Manifold(AbstractSet):
r"""
- Topological manifold over a topological field `K`.
+ Manifold over a topological field `K`.
Given a topological field `K` (in most applications, `K = \RR` or
`K = \CC`) and a non-negative integer `n`, a *topological manifold of
@@ -304,7 +310,7 @@ class TopologicalManifold(TopologicalManifoldSubset):
- 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.TopologicalManifoldPoint`.
+ class being :class:`~sage.manifolds.point.ManifoldPoint`.
INPUT:
@@ -352,7 +358,7 @@ class TopologicalManifold(TopologicalManifoldSubset):
sage: latex(M)
\mathcal{M}
sage: type(M)
- <class 'sage.manifolds.manifold.TopologicalManifold_with_category'>
+ <class 'sage.manifolds.manifold.Manifold_with_category'>
sage: M.base_field()
Real Field with 53 bits of precision
sage: dim(M)
@@ -417,18 +423,18 @@ class TopologicalManifold(TopologicalManifoldSubset):
True
The manifold's points are instances of class
- :class:`~sage.manifolds.point.TopologicalManifoldPoint`::
+ :class:`~sage.manifolds.point.ManifoldPoint`::
- sage: isinstance(p, sage.manifolds.point.TopologicalManifoldPoint)
+ sage: isinstance(p, sage.manifolds.point.ManifoldPoint)
True
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`::
+ :class:`Manifold`::
sage: U = M.open_subset('U'); U
Open subset U of the 4-dimensional topological manifold M
- sage: isinstance(U, sage.manifolds.manifold.TopologicalManifold)
+ sage: isinstance(U, sage.manifolds.manifold.Manifold)
True
sage: U.base_field() == M.base_field()
True
@@ -441,8 +447,8 @@ class TopologicalManifold(TopologicalManifoldSubset):
sage: TestSuite(M).run()
"""
- def __init__(self, n, name, latex_name=None, field='real', start_index=0,
- category=None, ambient_manifold=None, unique_tag=None):
+ def __init__(self, n, name, latex_name, field, structure,
+ start_index, category=None, unique_tag=None):
r"""
Construct a topological manifold.
@@ -458,14 +464,8 @@ class TopologicalManifold(TopologicalManifoldSubset):
3
sage: X.<x,y,z> = M.chart()
sage: TestSuite(M).run()
-
"""
# Initialization of the attributes _dim, _field and _start_index:
- from sage.rings.integer import Integer
- if not isinstance(n, (int, Integer)):
- raise TypeError("the manifold dimension must be an integer")
- if n<1:
- raise ValueError("the manifold dimension must be strictly positive")
self._dim = n
if field == 'real':
self._field = RR
@@ -483,20 +483,17 @@ class TopologicalManifold(TopologicalManifoldSubset):
self._field_type = 'complex'
else:
self._field_type = 'neither_real_nor_complex'
+
+ self._structure = structure
+ category = Manifolds(self._field).or_subcategory(category)
+ category = self._structure.subcategory(category)
+
+ AbstractSet.__init__(self, name, latex_name, self._field, category)
+
if not isinstance(start_index, (int, Integer)):
raise TypeError("the starting index must be an integer")
self._sindex = start_index
- category = Manifolds(self._field).or_subcategory(category)
- if ambient_manifold is None:
- ambient_manifold = self
- 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):
- 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
self._top_charts = [] # list of charts defined on subsets of self
# that are not subcharts of charts on larger subsets
@@ -510,6 +507,8 @@ class TopologicalManifold(TopologicalManifoldSubset):
# domains are self (if non-empty, self is a coordinate domain):
self._covering_charts = []
+ self._open_covers.add(frozenset([self])) # set of open covers of self
+
def _repr_(self):
r"""
Return a string representation of the manifold.
@@ -538,38 +537,16 @@ class TopologicalManifold(TopologicalManifoldSubset):
'Open subset U of the 3-dimensional topological manifold M over the Rational Field'
"""
- if self._manifold is self:
- if self._field_type == 'real':
- return "{}-dimensional topological manifold {}".format(
- self._dim, self._name)
- elif self._field_type == 'complex':
- return "Complex {}-dimensional topological manifold {}".format(
- self._dim, self._name)
- return "{}-dimensional topological manifold {} over the {}".format(
- self._dim, self._name, self._field)
- else:
- return "Open subset {} of the {}".format(self._name, self._manifold)
-
- def _latex_(self):
- r"""
- Return a LaTeX representation of the manifold.
-
- TESTS::
-
- 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)
- \mathcal{M}
-
- """
- return self._latex_name
+ 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,
+ self._structure.name,
+ self._name)
+ return "{}-dimensional {} manifold {} over the {}".format(self._dim,
+ self._structure.name, self._name, self._field)
def _an_element_(self):
r"""
@@ -694,9 +671,9 @@ class TopologicalManifold(TopologicalManifoldSubset):
"""
# for efficiency, a quick test first:
- if point._subset is self:
+ if point.parent() is self:
return True
- if point._subset.is_subset(self):
+ if point.parent().is_subset(self):
return True
for chart in self._atlas:
if chart in point._coordinates:
@@ -709,6 +686,222 @@ class TopologicalManifold(TopologicalManifoldSubset):
return True
return False
+ def manifold(self):
+ """
+ Return ``self`` since ``self`` is the ambient manifold.
+
+ This is for compatibility with :class:`TopologicalSubmanifold`.
+
+ 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.
+
+ 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:`Manifold`.
+
+ INPUT:
+
+ - ``name`` -- name given to the open subset
+ - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
+ subset; if none is provided, it is set to ``name``
+ - ``coord_def`` -- (default: {}) definition of the subset in
+ terms of coordinates; ``coord_def`` must a be dictionary with keys
+ charts on the manifold and values the symbolic expressions formed by
+ the coordinates to define the subset.
+
+ OUTPUT:
+
+ - the open subset, as an instance of :class:`Manifold`.
+
+ EXAMPLES:
+
+ Creating an open subset of a 2-dimensional manifold::
+
+ sage: M = Manifold(2, 'M', structure='topological')
+ sage: A = M.open_subset('A'); A
+ Open subset A of the 2-dimensional topological manifold M
+
+ As an open subset of a topological manifold, ``A`` is itself a
+ topological manifold, on the same topological field and of the same
+ dimension as ``M``::
+
+ sage: isinstance(A, sage.manifolds.manifold.Manifold)
+ True
+ sage: A.base_field() == M.base_field()
+ True
+ sage: dim(A) == dim(M)
+ True
+
+ Creating an open subset of ``A``::
+
+ sage: B = A.open_subset('B'); B
+ Open subset B of the 2-dimensional topological manifold M
+
+ We have then::
+
+ sage: A.subsets() # random (set output)
+ {Open subset B of the 2-dimensional topological manifold M,
+ Open subset A of the 2-dimensional topological manifold M}
+ sage: B.is_subset(A)
+ True
+ sage: B.is_subset(M)
+ True
+
+ Defining an open subset by some coordinate restrictions: the open
+ unit disk in `\RR^2`::
+
+ sage: M = Manifold(2, 'R^2', structure='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
+
+ Since the argument ``coord_def`` has been set, ``U`` is automatically
+ provided with a chart, which is the restriction of the Cartesian one
+ to ``U``::
+
+ sage: U.atlas()
+ [Chart (U, (x, y))]
+
+ Therefore, one can immediately check whether a point belongs to U::
+
+ sage: M.point((0,0)) in U
+ True
+ sage: M.point((1/2,1/3)) in U
+ True
+ sage: M.point((1,2)) in U
+ False
+
+ """
+ from sage.manifolds.subset import TopologicalSubmanifold
+ resu = TopologicalSubmanifold(ambient=self.manifold(),
+ name=name, latex_name=latex_name,
+ category=self.category())
+
+ resu._supersets.update(self._supersets)
+ for sd in self._supersets:
+ sd._subsets.add(resu)
+ self._top_subsets.add(resu)
+ # Charts on the result from the coordinate definition:
+ for chart, restrictions in coord_def.iteritems():
+ if chart not in self._atlas:
+ raise ValueError("the {} does not belong to ".format(chart) +
+ "the atlas of {}".format(self))
+ chart.restrict(resu, restrictions)
+ # Transition maps on the result inferred from those of self:
+ for chart1 in coord_def:
+ for chart2 in coord_def:
+ if chart2 != chart1 and (chart1, chart2) in self._coord_changes:
+ self._coord_changes[(chart1, chart2)].restrict(resu)
+ return resu
+
+ def get_chart(self, coordinates, domain=None):
+ r"""
+ Get a chart from its coordinates.
+
+ The chart must have been previously created by the method
+ :meth:`chart`.
+
+ INPUT:
+
+ - ``coordinates`` -- single string composed of the coordinate symbols
+ separated by a space
+ - ``domain`` -- (default: ``None``) string containing the name of the
+ chart's domain, which must be a subset of the current manifold; if
+ ``None``, the current manifold is assumed.
+
+ OUTPUT:
+
+ - instance of
+ :class:`~sage.manifolds.chart.Chart` (or of the subclass
+ :class:`~sage.manifolds.chart.RealChart`) representing the chart
+ corresponding to the above specifications.
+
+ EXAMPLES::
+
+ sage: M = Manifold(2, 'M', structure='topological')
+ sage: X.<x,y> = M.chart()
+ sage: M.get_chart('x y')
+ Chart (M, (x, y))
+ sage: M.get_chart('x y') is X
+ True
+ sage: U = M.open_subset('U', coord_def={X: (y!=0,x<0)})
+ sage: Y.<r, ph> = U.chart(r'r:(0,+oo) ph:(0,2*pi):\phi')
+ sage: M.atlas()
+ [Chart (M, (x, y)), Chart (U, (x, y)), Chart (U, (r, ph))]
+ sage: M.get_chart('x y', domain='U')
+ Chart (U, (x, y))
+ sage: M.get_chart('x y', domain='U') is X.restrict(U)
+ True
+ sage: U.get_chart('r ph')
+ Chart (U, (r, ph))
+ sage: M.get_chart('r ph', domain='U')
+ Chart (U, (r, ph))
+ sage: M.get_chart('r ph', domain='U') is Y
+ True
+
+ """
+ if domain is None:
+ dom = self
+ else:
+ dom = self.get_subset(domain)
+ try:
+ return dom._charts_by_coord[coordinates]
+ except KeyError:
+ raise KeyError("the coordinates '{}' ".format(coordinates) +
+ "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 ``self`` with ``other``.
+
+ INPUT:
+
+ - ``other`` -- another subset of the same manifold
+ - ``name`` -- ignored
+ - ``latex_name`` -- ignored
+
+ OUTPUT:
+
+ - ``self``
+
+ EXAMPLES::
+ """
+ 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 current subset with another subset.
+
+ INPUT:
+
+ - ``other`` -- another subset of the same manifold
+ - ``name`` -- ignored
+ - ``latex_name`` -- ignored
+
+ OUTPUT:
+
+ - instance of :class:`ManifoldSubset` representing the
+ subset that is the intersection of the current subset with ``other``
+
+ EXAMPLES::
+ """
+ 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.
@@ -971,7 +1164,7 @@ class TopologicalManifold(TopologicalManifoldSubset):
:meth:`top_charts`
"""
- return self._atlas
+ return list(self._atlas) # Make a (shallow) copy
def top_charts(self):
r"""
@@ -1006,7 +1199,7 @@ class TopologicalManifold(TopologicalManifoldSubset):
manifold.
"""
- return self._top_charts
+ return list(self._top_charts) # Make a (shallow) copy
def default_chart(self):
r"""
@@ -1183,119 +1376,7 @@ class TopologicalManifold(TopologicalManifoldSubset):
True
"""
- return not self._covering_charts == []
-
- def open_subset(self, name, latex_name=None, coord_def={}):
- r"""
- Create an open subset of the manifold.
-
- 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:`TopologicalManifold`.
-
- INPUT:
-
- - ``name`` -- name given to the open subset
- - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
- subset; if none is provided, it is set to ``name``
- - ``coord_def`` -- (default: {}) definition of the subset in
- terms of coordinates; ``coord_def`` must a be dictionary with keys
- charts on the manifold and values the symbolic expressions formed by
- the coordinates to define the subset.
-
- OUTPUT:
-
- - the open subset, as an instance of :class:`TopologicalManifold`.
-
- EXAMPLES:
-
- Creating an open subset of a 2-dimensional manifold::
-
- sage: M = Manifold(2, 'M', structure='topological')
- sage: A = M.open_subset('A'); A
- Open subset A of the 2-dimensional topological manifold M
-
- As an open subset of a topological manifold, ``A`` is itself a
- topological manifold, on the same topological field and of the same
- dimension as ``M``::
-
- sage: isinstance(A, sage.manifolds.manifold.TopologicalManifold)
- True
- sage: A.base_field() == M.base_field()
- True
- sage: dim(A) == dim(M)
- True
-
- Creating an open subset of ``A``::
-
- sage: B = A.open_subset('B'); B
- Open subset B of the 2-dimensional topological manifold M
-
- We have then::
-
- sage: A.subsets() # random (set output)
- {Open subset B of the 2-dimensional topological manifold M,
- Open subset A of the 2-dimensional topological manifold M}
- sage: B.is_subset(A)
- True
- sage: B.is_subset(M)
- True
-
- Defining an open subset by some coordinate restrictions: the open
- unit disk in `\RR^2`::
-
- sage: M = Manifold(2, 'R^2', structure='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
-
- Since the argument ``coord_def`` has been set, ``U`` is automatically
- provided with a chart, which is the restriction of the Cartesian one
- to ``U``::
-
- sage: U.atlas()
- [Chart (U, (x, y))]
-
- Therefore, one can immediately check whether a point belongs to U::
-
- sage: M.point((0,0)) in U
- True
- sage: M.point((1/2,1/3)) in U
- True
- sage: M.point((1,2)) in U
- False
-
- """
- 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 = 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 = type(self)(...)
- # cf. the discussion in
- # https://groups.google.com/forum/#!topic/sage-devel/jHlFxhMDf3Y
- resu._supersets.update(self._supersets)
- for sd in self._supersets:
- sd._subsets.add(resu)
- self._top_subsets.add(resu)
- # Charts on the result from the coordinate definition:
- for chart, restrictions in coord_def.iteritems():
- if chart not in self._atlas:
- raise ValueError("the {} does not belong to ".format(chart) +
- "the atlas of {}".format(self))
- chart.restrict(resu, restrictions)
- # Transition maps on the result inferred from those of self:
- for chart1 in coord_def:
- for chart2 in coord_def:
- if chart2 != chart1 and (chart1, chart2) in self._coord_changes:
- self._coord_changes[(chart1, chart2)].restrict(resu)
- return resu
+ return bool(self._covering_charts)
def chart(self, coordinates='', names=None):
r"""
@@ -1408,70 +1489,29 @@ class TopologicalManifold(TopologicalManifoldSubset):
especially regarding the coordinates ranges and restrictions.
"""
- from sage.manifolds.chart import Chart, RealChart
- if self._field_type == 'real':
- return RealChart(self, coordinates=coordinates, names=names)
- return Chart(self, coordinates=coordinates, names=names)
+ return self._structure.chart(self, coordinates=coordinates, names=names)
- def get_chart(self, coordinates, domain=None):
+ def superset(self, name=None, latex_name=None, is_open=False):
r"""
- Get a chart from its coordinates.
-
- The chart must have been previously created by the method
- :meth:`chart`.
+ Return ``self`` since the only superset of the manifold is
+ the manifold.
INPUT:
- - ``coordinates`` -- single string composed of the coordinate symbols
- separated by a space
- - ``domain`` -- (default: ``None``) string containing the name of the
- chart's domain, which must be a subset of the current manifold; if
- ``None``, the current manifold is assumed.
-
- OUTPUT:
-
- - instance of
- :class:`~sage.manifolds.chart.Chart` (or of the subclass
- :class:`~sage.manifolds.chart.RealChart`) representing the chart
- corresponding to the above specifications.
+ - ``name`` -- ignored
+ - ``latex_name`` -- ignored
+ - ``is_open`` -- ignored
EXAMPLES::
-
- sage: M = Manifold(2, 'M', structure='topological')
- sage: X.<x,y> = M.chart()
- sage: M.get_chart('x y')
- Chart (M, (x, y))
- sage: M.get_chart('x y') is X
- True
- sage: U = M.open_subset('U', coord_def={X: (y!=0,x<0)})
- sage: Y.<r, ph> = U.chart(r'r:(0,+oo) ph:(0,2*pi):\phi')
- sage: M.atlas()
- [Chart (M, (x, y)), Chart (U, (x, y)), Chart (U, (r, ph))]
- sage: M.get_chart('x y', domain='U')
- Chart (U, (x, y))
- sage: M.get_chart('x y', domain='U') is X.restrict(U)
- True
- sage: U.get_chart('r ph')
- Chart (U, (r, ph))
- sage: M.get_chart('r ph', domain='U')
- Chart (U, (r, ph))
- sage: M.get_chart('r ph', domain='U') is Y
- True
-
"""
- if domain is None:
- dom = self
- else:
- dom = self.get_subset(domain)
- try:
- return dom._charts_by_coord[coordinates]
- except KeyError:
- raise KeyError("the coordinates '{}' ".format(coordinates) +
- "do not correspond to any chart with " +
- "the {} as domain".format(dom))
+ return self
+
+#####################################################################
+## Constructor function
-def Manifold(dim, name, latex_name=None, field='real', structure='smooth',
- start_index=0, **extra_kwds):
+def manifold_constructor(dim, name, latex_name=None,
+ field='real', structure='smooth',
+ start_index=0, **extra_kwds):
r"""
Construct a manifold of a given type over a topological field `K`.
@@ -1493,8 +1533,8 @@ def Manifold(dim, name, latex_name=None, field='real', structure='smooth',
:class:`~sage.categories.topological_spaces.TopologicalSpaces`)
for other types of manifolds
- - ``structure`` -- (default: ``'smooth'``) to specify the type of manifold;
- allowed values are
+ - ``structure`` -- (default: ``'smooth'``) to specify the structure or
+ type of manifold; allowed values are
- ``'topological'`` or ``'top'`` for a topological manifold
- ``'differentiable'`` or ``'diff'`` for a differentiable manifold
@@ -1510,7 +1550,7 @@ def Manifold(dim, name, latex_name=None, field='real', structure='smooth',
OUTPUT:
- a manifold of the specified type, as an instance of
- :class:`~sage.manifolds.manifold.TopologicalManifold` or one of its
+ :class:`~sage.manifolds.manifold.Manifold` or one of its
subclasses.
EXAMPLES:
@@ -1537,7 +1577,7 @@ def Manifold(dim, name, latex_name=None, field='real', structure='smooth',
3-dimensional topological manifold M over the Rational Field
See the documentation of class
- :class:`~sage.manifolds.manifold.TopologicalManifold` for more
+ :class:`~sage.manifolds.manifold.Manifold` for more
detailed examples.
.. RUBRIC:: Uniqueness of manifold objects
@@ -1606,12 +1646,22 @@ def Manifold(dim, name, latex_name=None, field='real', structure='smooth',
sage: isinstance(M, sage.misc.fast_methods.WithEqualityById)
True
-
"""
from time import time
+ # Some sanity checks
+ if not isinstance(dim, (int, Integer)):
+ raise TypeError("the manifold dimension must be an integer")
+ if dim < 1:
+ raise ValueError("the manifold dimension must be strictly positive")
+
if structure in ['topological', 'top']:
- return TopologicalManifold(dim, name, latex_name=latex_name,
- field=field, start_index=start_index,
- unique_tag=getrandbits(128)*time())
- raise NotImplementedError("manifolds of type {} are ".format(structure) +
- "not implemented")
+ if field == 'real':
+ structure = RealTopologicalStructure()
+ else:
+ structure = TopologicalStructure()
+ else:
+ raise NotImplementedError("manifolds of type {} are not ".format(structure) +
+ "implemented")
+
+ return Manifold(dim, name, latex_name, field, structure, start_index,
+ unique_tag=getrandbits(128)*time())
diff --git a/src/sage/manifolds/point.py b/src/sage/manifolds/point.py
index c0c9b95..b99b3b5 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:`TopologicalManifoldPoint` implements points of a
+The class :class:`ManifoldPoint` implements points of a
topological manifold.
-A :class:`TopologicalManifoldPoint` object can have coordinates in
+A :class:`ManifoldPoint` 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.
@@ -70,22 +70,22 @@ Points can be compared::
from sage.structure.element import Element
-class TopologicalManifoldPoint(Element):
+# TODO: Inherit from AbstractObject
+class ManifoldPoint(Element):
r"""
Point of a topological manifold.
This is a Sage *element* class, the corresponding *parent* class being
- :class:`~sage.manifolds.manifold.TopologicalManifold`.
+ :class:`~sage.manifolds.manifold.Manifold`.
INPUT:
- - ``subset`` -- the manifold subset to which the point belongs (can be
- the entire manifold)
- - ``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 given;
- if ``None``, the coordinates are assumed to refer to the subset's
- default chart
+ - ``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
+ given; if ``None``, the coordinates are assumed to refer to the
+ default chart of ``parent``
- ``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``
@@ -147,7 +147,7 @@ class TopologicalManifoldPoint(Element):
Points can be drawn in 2D or 3D graphics thanks to the method :meth:`plot`.
"""
- def __init__(self, subset, coords=None, chart=None, name=None,
+ def __init__(self, parent, coords=None, chart=None, name=None,
latex_name=None, check_coords=True):
r"""
Construct a manifold point.
@@ -165,21 +165,20 @@ class TopologicalManifoldPoint(Element):
sage: TestSuite(q).run()
"""
- Element.__init__(self, subset._manifold)
- self._manifold = subset._manifold
- self._subset = subset
+ Element.__init__(self, parent)
self._coordinates = {} # dictionary of the point coordinates in various
# charts, with the charts as keys
if coords is not None:
- if len(coords) != self._manifold._dim:
+ if len(coords) != parent.manifold().dimension():
raise ValueError("the number of coordinates must be equal " +
"to the manifold's dimension")
+ from sage.manifolds.manifold import Manifold
if chart is None:
- chart = self._subset._def_chart
- elif self._subset._is_open:
- if chart not in self._subset._atlas:
+ chart = parent._def_chart
+ elif isinstance(parent, Manifold):
+ if chart not in parent._atlas:
raise ValueError("the {} has not been".format(chart) +
- "defined on the {}".format(self._subset))
+ "defined on the {}".format(parent))
if check_coords:
if not chart.valid_coordinates(*coords):
raise ValueError("the coordinates {}".format(coords) +
@@ -217,7 +216,7 @@ class TopologicalManifoldPoint(Element):
description = "Point"
if self._name is not None:
description += " " + self._name
- description += " on the {}".format(self._manifold)
+ description += " on the {}".format(self.parent().manifold())
return description
def _latex_(self):
@@ -243,9 +242,9 @@ class TopologicalManifoldPoint(Element):
"""
if self._latex_name is None:
return r'\mbox{' + str(self) + r'}'
- else:
- return self._latex_name
+ return self._latex_name
+ # TODO: Convert these doctests to doctests elsewhere
def containing_set(self):
r"""
Return a manifold subset that contains the point.
@@ -256,7 +255,7 @@ class TopologicalManifoldPoint(Element):
OUTPUT:
- an instance of
- :class:`~sage.manifolds.subset.TopologicalManifoldSubset`
+ :class:`~sage.manifolds.subset.ManifoldSubset`
EXAMPLES:
@@ -303,10 +302,10 @@ class TopologicalManifoldPoint(Element):
- ``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
- - ``old_chart`` -- (default: ``None``) chart from which the coordinates
- in ``chart`` are to be computed. If ``None``, a chart in which the
- point's coordinates are already known will be picked, privileging the
- subset's default chart.
+ - ``old_chart`` -- (default: ``None``) chart from which the
+ coordinates in ``chart`` are to be computed; if ``None``, a chart
+ in which the point's coordinates are already known will be picked,
+ privileging the subset's default chart
EXAMPLES:
@@ -375,7 +374,7 @@ class TopologicalManifoldPoint(Element):
"""
if chart is None:
- dom = self._subset
+ dom = self.parent()
chart = dom._def_chart
def_chart = chart
else:
@@ -435,8 +434,7 @@ class TopologicalManifoldPoint(Element):
"by means of known changes of charts.")
else:
chcoord = dom._coord_changes[(s_old_chart, s_chart)]
- self._coordinates[chart] = \
- chcoord(*self._coordinates[old_chart])
+ self._coordinates[chart] = chcoord(*self._coordinates[old_chart])
return self._coordinates[chart]
def set_coord(self, coords, chart=None):
@@ -538,15 +536,15 @@ class TopologicalManifoldPoint(Element):
{Chart (M, (u, v)): (-1, 5)}
"""
- if len(coords) != self._manifold._dim:
+ if len(coords) != self.parent().manifold()._dim:
raise ValueError("the number of coordinates must be equal to " +
"the manifold's dimension.")
if chart is None:
- chart = self._subset._def_chart
+ chart = self.parent()._def_chart
else:
- if chart not in self._subset._atlas:
+ if chart not in self.parent()._atlas:
raise ValueError("the {}".format(chart) + " has not been " +
- "defined on the {}".format(self._subset))
+ "defined on the {}".format(self.parent()))
self._coordinates[chart] = coords
def __eq__(self, other):
@@ -594,17 +592,18 @@ class TopologicalManifoldPoint(Element):
"""
if other is self:
return True
- if not isinstance(other, TopologicalManifoldPoint):
+ if not isinstance(other, ManifoldPoint):
return False
- if other._manifold != self._manifold:
+ if other.parent().manifold() != self.parent().manifold():
return False
# Search for a common chart to compare the coordinates
common_chart = None
# the subset's default chart is privileged:
- if hasattr(self._subset, '_def_chart'): # self._subset is open
- def_chart = self._subset._def_chart
+ # FIXME: Make this a better test
+ if hasattr(self.parent(), '_def_chart'): # self.parent() is open
+ def_chart = self.parent()._def_chart
else:
- def_chart = self._manifold._def_chart
+ def_chart = self.parent().manifold()._def_chart
if def_chart in self._coordinates and def_chart in other._coordinates:
common_chart = def_chart
else:
@@ -636,8 +635,7 @@ class TopologicalManifoldPoint(Element):
#!# Another option would be:
# raise ValueError("no common chart has been found to compare " +
# "{} and {}".format(self, other))
- return self._coordinates[common_chart] == \
- other._coordinates[common_chart]
+ return self._coordinates[common_chart] == other._coordinates[common_chart]
def __ne__(self, other):
r"""
@@ -700,4 +698,4 @@ class TopologicalManifoldPoint(Element):
True
"""
- return hash(self._manifold)
+ return hash(self.parent().manifold())
diff --git a/src/sage/manifolds/structure.py b/src/sage/manifolds/structure.py
new file mode 100644
index 0000000..132f0f7
--- /dev/null
+++ b/src/sage/manifolds/structure.py
@@ -0,0 +1,52 @@
+r"""
+Manifold structures
+
+These classes encode the sturcture of a manifold.
+
+AUTHORS:
+
+- Travis Scrimshaw (2015-11-25): Initial version
+"""
+
+#*****************************************************************************
+# Copyright (C) 2015 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr>
+# Copyright (C) 2015 Michal Bejger <bejger@camk.edu.pl>
+# Copyright (C) 2015 Travis Scrimshaw <tscrimsh at 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.misc.fast_methods import Singleton
+from sage.manifolds.chart import Chart, RealChart
+
+# This is a slight abuse by making this a Singleton, but there is no
+# need to have different copies of this object.
+class TopologicalStructure(Singleton):
+ """
+ The structure of a topological manifold over a general field.
+ """
+ chart = Chart
+ name = "topological"
+ def subcategory(self, cat):
+ """
+ Return the subcategory of ``cat`` corresponding to the structure
+ of ``self``.
+ """
+ return cat
+
+class RealTopologicalStructure(Singleton):
+ """
+ The structure of a topological manifold over `\RR`.
+ """
+ chart = RealChart
+ name = "topological"
+ def subcategory(self, cat):
+ """
+ Return the subcategory of ``cat`` corresponding to the structure
+ of ``self``.
+ """
+ return cat
+
diff --git a/src/sage/manifolds/subset.py b/src/sage/manifolds/subset.py
index 6b33dbf..23c20b0 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:`TopologicalManifoldSubset` implements generic subsets of a
+The class :class:`ManifoldSubset` implements generic subsets of a
topological manifold. Open subsets are implemented by the class
-:class:`~sage.manifolds.manifold.TopologicalManifold` (since an open subset of
+:class:`~sage.manifolds.manifold.Manifold` (since an open subset of
a manifold is a manifold by itself), which inherits from
-:class:`TopologicalManifoldSubset`.
+:class:`ManifoldSubset`.
AUTHORS:
@@ -70,26 +70,25 @@ 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.point import TopologicalManifoldPoint
+from sage.manifolds.abstract import AbstractSet
+from sage.manifolds.manifold import Manifold
-class TopologicalManifoldSubset(UniqueRepresentation, Parent):
+class ManifoldSubset(AbstractSet):
r"""
Subset of a topological manifold.
- The class :class:`TopologicalManifoldSubset` inherits from the generic Sage
+ The class :class:`ManifoldSubset` 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.TopologicalManifoldPoint`. A subset acts
+ :class:`~sage.manifolds.point.ManifoldPoint`. 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.TopologicalManifold`
+ by the derived class :class:`~sage.manifolds.manifold.Manifold`
(an open subset of a topological manifold being itself a topological
manifold).
@@ -107,8 +106,8 @@ class TopologicalManifoldSubset(UniqueRepresentation, Parent):
A subset of a manifold::
sage: M = Manifold(2, 'M', structure='topological')
- sage: from sage.manifolds.subset import TopologicalManifoldSubset
- sage: A = TopologicalManifoldSubset(M, 'A', latex_name=r'\mathcal{A}')
+ sage: from sage.manifolds.subset import ManifoldSubset
+ sage: A = ManifoldSubset(M, 'A', latex_name=r'\mathcal{A}')
sage: A
Subset A of the 2-dimensional topological manifold M
sage: latex(A)
@@ -116,7 +115,7 @@ class TopologicalManifoldSubset(UniqueRepresentation, Parent):
sage: A.is_subset(M)
True
- Instead of importing :class:`TopologicalManifoldSubset` in the global
+ Instead of importing :class:`ManifoldSubset` in the global
namespace, it is recommended to use the method :meth:`subset` to create a
new subset::
@@ -129,13 +128,13 @@ class TopologicalManifoldSubset(UniqueRepresentation, Parent):
The manifold is itself a subset::
- sage: isinstance(M, TopologicalManifoldSubset)
+ sage: isinstance(M, ManifoldSubset)
True
- Instances of :class:`TopologicalManifoldSubset` are Sage's facade sets
+ Instances of :class:`ManifoldSubset` are Sage's facade sets
(see :meth:`~sage.categories.sets_cat.Sets.SubcategoryMethods.Facade`):
their elements are manifold points
- (class :class:`~sage.manifolds.point.TopologicalManifoldPoint`),
+ (class :class:`~sage.manifolds.point.ManifoldPoint`),
which have the manifold (and not the subset) as parent::
sage: isinstance(A, Parent)
@@ -152,11 +151,8 @@ class TopologicalManifoldSubset(UniqueRepresentation, Parent):
True
sage: p in M
True
-
"""
- Element = TopologicalManifoldPoint
-
def __init__(self, manifold, name, latex_name=None, category=None):
r"""
Construct a manifold subset.
@@ -167,159 +163,18 @@ class TopologicalManifoldSubset(UniqueRepresentation, Parent):
sage: X.<x,y> = M.chart()
sage: A = M.subset('A'); A
Subset A of the 2-dimensional topological manifold M
-
"""
- if category is None:
- base = None
- category = Sets()
- else:
- base = manifold._field
- # Except for the manifold itself, the subsets are facade sets:
- if self is manifold:
- Parent.__init__(self, base=base, category=category)
- else:
- Parent.__init__(self, base=base, category=category,
- facade=manifold)
- 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
- else:
- 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
- # 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)
-
- #### 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.TopologicalManifoldPoint`
- 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.containing_set()
- 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)
+ category = Sets().Subobjects()
+ AbstractSet.__init__(self, name=name, latex_name=latex_name,
+ category=category)
- """
- if isinstance(coords, TopologicalManifoldPoint):
- point = coords # for readability
- if point._subset 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
+ self._manifold = 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)
def _repr_(self):
r"""
@@ -337,25 +192,6 @@ class TopologicalManifoldSubset(UniqueRepresentation, Parent):
"""
return "Subset {} of the {}".format(self._name, self._manifold)
- def _latex_(self):
- r"""
- LaTeX representation of the object.
-
- 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}
-
- """
- return self._latex_name
-
def manifold(self):
r"""
Return the manifold of which the current object is a subset.
@@ -375,234 +211,13 @@ class TopologicalManifoldSubset(UniqueRepresentation, Parent):
"""
return self._manifold
- 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 'set'>
- 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 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 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:`TopologicalManifoldSubset`, 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
-
+ ambient = manifold
+ def is_open(self):
"""
- if is_open:
- return self.open_subset(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)
- 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:`TopologicalManifoldSubset` (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
-
+ Return if ``self`` is an open set.
"""
- for ss in self._subsets:
- if ss._name == name:
- return ss
- raise ValueError("no subset of name '{}' found".format(name))
+ return False
def superset(self, name, latex_name=None, is_open=False):
r"""
@@ -621,9 +236,9 @@ class TopologicalManifoldSubset(UniqueRepresentation, Parent):
OUTPUT:
- - the superset, as an instance of :class:`TopologicalManifoldSubset` or
+ - the superset, as an instance of :class:`ManifoldSubset` or
of the derived class
- :class:`~sage.manifolds.manifold.TopologicalManifold` if ``is_open``
+ :class:`~sage.manifolds.manifold.Manifold` if ``is_open``
is ``True``.
EXAMPLES:
@@ -654,21 +269,10 @@ class TopologicalManifoldSubset(UniqueRepresentation, Parent):
False
"""
- if self is self._manifold:
- return self
- if is_open:
- res = self._manifold.open_subset(name, latex_name=latex_name)
- else:
- res = TopologicalManifoldSubset(self._manifold, name,
- latex_name=latex_name)
+ res = self._manifold.subset(name, latex_name, is_open)
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):
@@ -681,13 +285,13 @@ class TopologicalManifoldSubset(UniqueRepresentation, Parent):
- ``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`
OUTPUT:
- - instance of :class:`TopologicalManifoldSubset` representing the
+ - instance of :class:`ManifoldSubset` representing the
subset that is the intersection of the current subset with ``other``
EXAMPLES:
@@ -727,44 +331,43 @@ class TopologicalManifoldSubset(UniqueRepresentation, Parent):
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]
- 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
+
+ # 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:
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)
+ latex_name = self._latex_name + r'\cap ' + other._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
+ 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
def union(self, other, name=None, latex_name=None):
r"""
@@ -782,7 +385,7 @@ class TopologicalManifoldSubset(UniqueRepresentation, Parent):
OUTPUT:
- - instance of :class:`TopologicalManifoldSubset` representing the
+ - instance of :class:`ManifoldSubset` representing the
subset that is the union of the current subset with ``other``
EXAMPLES:
@@ -825,205 +428,127 @@ class TopologicalManifoldSubset(UniqueRepresentation, Parent):
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) or (other is self._manifold):
+ if 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]
- 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:
- 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._is_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
-
- 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
+ # TODO: Check to see if we've already created a union of ``self`` and ``other``
- """
- 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:
+ # 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:
+ 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)
- self._open_covers.append(oc)
-
- def is_subset(self, other):
- r"""
- Return ``True`` iff the current subset 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
+ res._open_covers.append(oc)
+ return res
+class TopologicalSubmanifold(ManifoldSubset, Manifold):
+ """
+ A submanifold of a manifold, which is any open subset of a manifold.
+ """
+ def __init__(self, ambient, name, latex_name=None, category=None):
"""
- return self in other._subsets
-
- def __contains__(self, point):
- r"""
- Check whether a point is contained in the current subset.
-
- 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
+ Initialize ``self``.
+ """
+ # TODO: This test probably needs a better place, like open_subset
+ if not isinstance(ambient, Manifold):
+ raise TypeError("the argument 'manifold' must be " +
+ "a topological manifold")
+
+ # This is copied from ManifoldSubset to avoid twice
+ # initializing AbstractSet
+ self._manifold = ambient
+ for dom in ambient._subsets:
+ if name == dom._name:
+ raise ValueError("the name '" + name +
+ "' is already used for another " +
+ "subset of the {}".format(ambient))
+ ambient._subsets.add(self)
+
+ category = ambient.category().Subobjects()
+ Manifold.__init__(self, ambient.dim(), name, latex_name,
+ ambient._field, ambient._structure,
+ ambient._sindex, category)
+ def _repr_(self):
"""
- # for efficiency, a quick test first:
- if point._subset is self:
- return True
- if point._subset.is_subset(self):
- return True
- #!# should be improved once coordinate definition have been introduced
- # in TopologicalManifoldSubset
- return False
+ Return a string representation of ``self``.
+ """
+ return "Open subset {} of the {}".format(self._name, self._manifold)
+
- def point(self, coords=None, chart=None, name=None, latex_name=None):
+ def superset(self, name, latex_name=None, is_open=False):
r"""
- Define a point in the subset.
+ Create a superset of the current subset.
- See :class:`~sage.manifolds.point.TopologicalManifoldPoint` for a
- complete documentation.
+ A *superset* is a manifold subset in which the current subset is
+ included.
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``
+ - ``name`` -- name given to the superset
+ - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
+ superset; 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 declared point, as an instance of
- :class:`~sage.manifolds.point.TopologicalManifoldPoint`.
+ - the superset, as an instance of :class:`ManifoldSubset` or
+ of the derived class
+ :class:`~sage.manifolds.manifold.Manifold` if ``is_open``
+ is ``True``.
EXAMPLES:
+ """
+ res = ManifoldSubset.superset(self, name, latex_name, is_open)
+ if 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
- 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)}
-
+ def is_open(self):
+ """
+ Return if ``self`` is an open set.
"""
- return self.element_class(self, coords=coords, chart=chart, name=name,
- latex_name=latex_name)
+ return True