Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Merge #31653
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthias Koeppe committed Jun 5, 2021
2 parents b028715 + 0f3e36d commit 4a13d8b
Show file tree
Hide file tree
Showing 5 changed files with 240 additions and 2 deletions.
2 changes: 2 additions & 0 deletions src/doc/en/reference/manifolds/continuous_map.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ Continuous Maps
sage/manifolds/manifold_homset

sage/manifolds/continuous_map

sage/manifolds/continuous_map_image
52 changes: 51 additions & 1 deletion src/sage/manifolds/continuous_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@
"""

# ****************************************************************************
# Copyright (C) 2015 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr>
# Copyright (C) 2015-2019 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr>
# Copyright (C) 2015 Michal Bejger <bejger@camk.edu.pl>
# Copyright (C) 2016 Travis Scrimshaw <tscrimsh@umn.edu>
# Copyright (C) 2018 Florentin Jaffredo <florentin.jaffredo@polytechnique.edu>
# Copyright (C) 2020 Michael Jung <micjung@uni-potsdam.de>
# Copyright (C) 2021 Matthias Koeppe <mkoeppe@math.ucdavis.edu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -816,6 +819,53 @@ def _composition_(self, other, homset):
pass
return homset(resu_funct)

def image(self, subset=None, inverse=None):
r"""
Return the image of ``self`` or the image of ``subset`` under ``self``.
INPUT:
- ``inverse`` -- (default: ``None``) continuous map from
``map.codomain()`` to ``map.domain()``, which once restricted to the image
of `\Phi` is the inverse of `\Phi` onto its image if the latter
exists (NB: no check of this is performed)
- ``subset`` -- (default: the domain of ``map``) a subset of the domain of
``self``
EXAMPLES::
sage: M = Manifold(2, 'M', structure="topological")
sage: N = Manifold(1, 'N', ambient=M, structure="topological")
sage: CM.<x,y> = M.chart()
sage: CN.<u> = N.chart()
sage: CN.add_restrictions([u > -1, u < 1])
sage: Phi = N.continuous_map(M, {(CN,CM): [u, u^2]}, name='Phi')
sage: Phi.image()
Image of the Continuous map Phi
from the 1-dimensional topological submanifold N
immersed in the 2-dimensional topological manifold M
to the 2-dimensional topological manifold M
sage: S = N.subset('S')
sage: Phi_S = Phi.image(S); Phi_S
Image of the Subset S of the
1-dimensional topological submanifold N
immersed in the 2-dimensional topological manifold M
under the Continuous map Phi
from the 1-dimensional topological submanifold N
immersed in the 2-dimensional topological manifold M
to the 2-dimensional topological manifold M
sage: Phi_S.is_subset(M)
True
"""
from .continuous_map_image import ImageManifoldSubset
if self._is_identity:
if subset is None:
return self.domain()
else:
return subset
return ImageManifoldSubset(self, inverse=inverse, domain_subset=subset)

def pullback(self, codomain_subset, name=None, latex_name=None):
from sage.manifolds.subsets.pullback import ManifoldSubsetPullback
return ManifoldSubsetPullback(self, codomain_subset=codomain_subset,
Expand Down
157 changes: 157 additions & 0 deletions src/sage/manifolds/continuous_map_image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
r"""
Images of Manifold Subsets under Continuous Maps as Subsets of the Codomain
:class:`ImageManifoldSubset` implements the image of a continuous map `\Phi`
from a manifold `M` to some manifold `N` as a subset `\Phi(M)` of `N`,
or more generally, the image `\Phi(S)` of a subset `S \subseteq M` as a
subset of `N`.
"""

# ****************************************************************************
# Copyright (C) 2021 Matthias Koeppe <mkoeppe@math.ucdavis.edu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
# https://www.gnu.org/licenses/
# ****************************************************************************

from sage.manifolds.subset import ManifoldSubset

class ImageManifoldSubset(ManifoldSubset):
r"""
Subset of a topological manifold that is a continuous image of a manifold subset.
INPUT:
- ``map`` -- continuous map `\Phi`
- ``inverse`` -- (default: ``None``) continuous map from
``map.codomain()`` to ``map.domain()``, which once restricted to the image
of `\Phi` is the inverse of `\Phi` onto its image if the latter
exists (NB: no check of this is performed)
- ``name`` -- (default: computed from the names of the map and the subset)
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``
- ``domain_subset`` -- (default: the domain of ``map``) a subset of the domain of
``map``
"""

def __init__(self, map, inverse=None, name=None, latex_name=None, domain_subset=None):
r"""
Construct a manifold subset that is the image of a continuous map.
TESTS::
sage: M = Manifold(2, 'M', structure="topological")
sage: N = Manifold(1, 'N', ambient=M, structure="topological")
sage: CM.<x,y> = M.chart()
sage: CN.<u> = N.chart()
sage: CN.add_restrictions([u > -1, u < 1])
sage: Phi = N.continuous_map(M, {(CN,CM): [u, 1 + u^2]}, name='Phi')
sage: Phi_inv = M.continuous_map(N, {(CM, CN): [x]}, name='Phi_inv')
sage: Phi_N = Phi.image(inverse=Phi_inv)
sage: TestSuite(Phi_N).run()
"""
self._map = map
self._inverse = inverse
if domain_subset is None:
domain_subset = map.domain()
self._domain_subset = domain_subset
base_manifold = map.codomain()
map_name = map._name or 'f'
map_latex_name = map._latex_name or map_name
if latex_name is None:
if name is None:
latex_name = map_latex_name + r'(' + domain_subset._latex_name + ')'
else:
latex_name = name
if name is None:
name = map_name + '_' + domain_subset._name
ManifoldSubset.__init__(self, base_manifold, name, latex_name=latex_name)

def _repr_(self):
r"""
String representation of the object.
TESTS::
sage: M = Manifold(2, 'M', structure="topological")
sage: N = Manifold(1, 'N', ambient=M, structure="topological")
sage: CM.<x,y> = M.chart()
sage: CN.<u> = N.chart()
sage: CN.add_restrictions([u > -1, u < 1])
sage: Phi = N.continuous_map(M, {(CN,CM): [u, 1 + u^2]}, name='Phi')
sage: Phi.image() # indirect doctest
Image of the Continuous map Phi
from the 1-dimensional topological submanifold N immersed in the
2-dimensional topological manifold M
to the 2-dimensional topological manifold M
sage: S = N.subset('S')
sage: Phi.image(S) # indirect doctest
Image of the
Subset S of the
1-dimensional topological submanifold N immersed in the
2-dimensional topological manifold M
under the Continuous map Phi
from the 1-dimensional topological submanifold N immersed in the
2-dimensional topological manifold M
to the 2-dimensional topological manifold M
"""
if self._domain_subset is self._map.domain():
return f"Image of the {self._map}"
else:
return f"Image of the {self._domain_subset} under the {self._map}"

def _an_element_(self):
r"""
Construct some point in the subset.
EXAMPLES::
sage: M = Manifold(2, 'M', structure="topological")
sage: N = Manifold(1, 'N', ambient=M, structure="topological")
sage: CM.<x,y> = M.chart()
sage: CN.<u> = N.chart()
sage: CN.add_restrictions([u > -1, u < 1])
sage: Phi = N.continuous_map(M, {(CN,CM): [u, 1 + u^2]}, name='Phi')
sage: Phi_N = Phi.image()
sage: p = Phi_N.an_element(); p # indirect doctest
Point on the 2-dimensional topological manifold M
sage: p.coordinates()
(0, 1)
"""
return self._map(self._domain_subset.an_element())

def __contains__(self, point):
r"""
Check whether ``point`` is contained in ``self``.
TESTS::
sage: M = Manifold(2, 'M', structure="topological")
sage: N = Manifold(1, 'N', ambient=M, structure="topological")
sage: CM.<x,y> = M.chart()
sage: CN.<u> = N.chart()
sage: CN.add_restrictions([u > -1, u < 1])
sage: Phi = N.continuous_map(M, {(CN,CM): [u, 1 + u^2]}, name='Phi')
sage: Phi_inv = M.continuous_map(N, {(CM, CN): [x]}, name='Phi_inv')
sage: Phi_N = Phi.image(inverse=Phi_inv)
sage: M((0, 0)) in Phi_N
False
sage: M((0, 1)) in Phi_N
True
"""
if super().__contains__(point):
return True
if point not in self._map.codomain():
return False
if self._inverse is not None:
preimage = self._inverse(point)
if preimage not in self._domain_subset:
return False
return self._map(preimage) == point
raise NotImplementedError
4 changes: 3 additions & 1 deletion src/sage/manifolds/subset.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
topological manifold. Open subsets are implemented by the class
:class:`~sage.manifolds.manifold.TopologicalManifold` (since an
open subset of a manifold is a manifold by itself), which inherits
from :class:`ManifoldSubset`.
from :class:`ManifoldSubset`. Besides, subsets that are images of
a manifold subset under a continuous map are implemented by the
subclass :class:`~sage.manifolds.continuous_map_image.ImageManifoldSubset`.
AUTHORS:
Expand Down
27 changes: 27 additions & 0 deletions src/sage/manifolds/topological_submanifold.py
Original file line number Diff line number Diff line change
Expand Up @@ -747,3 +747,30 @@ def embedding(self):
if not self._embedded:
raise ValueError("the submanifold is not embedded")
return self._immersion

def as_subset(self):
r"""
Return ``self`` as a subset of the ambient manifold.
``self`` must be an embedded submanifold.
EXAMPLES::
sage: M = Manifold(2, 'M', structure="topological")
sage: N = Manifold(1, 'N', ambient=M, structure="topological")
sage: CM.<x,y> = M.chart()
sage: CN.<u> = N.chart()
sage: CN.add_restrictions([u > -1, u < 1])
sage: phi = N.continuous_map(M, {(CN,CM): [u, u^2]})
sage: N.set_embedding(phi)
sage: N
1-dimensional topological submanifold N
embedded in the 2-dimensional topological manifold M
sage: N.as_subset()
Image of the Continuous map
from the 1-dimensional topological submanifold N
embedded in the 2-dimensional topological manifold M
to the 2-dimensional topological manifold M
"""
return self.embedding().image()

0 comments on commit 4a13d8b

Please sign in to comment.