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

Commit

Permalink
Merge #31764
Browse files Browse the repository at this point in the history
  • Loading branch information
mkoeppe committed May 3, 2021
2 parents c27d4d6 + a083569 commit 5d41b46
Show file tree
Hide file tree
Showing 25 changed files with 2,283 additions and 379 deletions.
2 changes: 2 additions & 0 deletions src/doc/en/reference/manifolds/manifold.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ Topological Manifolds
sage/manifolds/topological_submanifold

vector_bundle

sage/manifolds/family
18 changes: 17 additions & 1 deletion src/sage/graphs/digraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -3317,12 +3317,28 @@ def layout_acyclic_dummy(self, heights=None, rankdir='up', **options):
...
ValueError: `self` should be an acyclic graph
TESTS:
:trac:`31681` is fixed::
sage: H = DiGraph({0: [1], 'X': [1]}, format='dict_of_lists')
sage: pos = H.layout_acyclic_dummy(rankdir='up')
sage: pos['X'][1] == 0 and pos[0][1] == 0
True
sage: pos[1][1] == 1
True
"""
if heights is None:
if not self.is_directed_acyclic():
raise ValueError("`self` should be an acyclic graph")
levels = self.level_sets()
levels = [sorted(z) for z in levels]
# Sort vertices in each level in best effort mode
for i in range(len(levels)):
try:
l = sorted(levels[i])
levels[i] = l
except:
continue
if rankdir=='down' or rankdir=='left':
levels.reverse()
heights = {i: levels[i] for i in range(len(levels))}
Expand Down
30 changes: 11 additions & 19 deletions src/sage/manifolds/chart.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,9 @@ def __init__(self, domain, coordinates='', names=None, calc_method=None):
self._restrictions = [] # to be set with method add_restrictions()
#
# The chart is added to the domain's atlas, as well as to all the
# atlases of the domain's supersets; moreover the fist defined chart
# atlases of the domain's supersets; moreover the first defined chart
# is considered as the default chart
for sd in self._domain._supersets:
for sd in self._domain.open_supersets():
# the chart is added in the top charts only if its coordinates have
# not been used:
for chart in sd._atlas:
Expand All @@ -346,13 +346,9 @@ def __init__(self, domain, coordinates='', names=None, calc_method=None):
# The null and one functions of the coordinates:
# Expression in self of the zero and one scalar fields of open sets
# containing the domain of self:
for dom in self._domain._supersets:
if hasattr(dom, '_zero_scalar_field'):
# dom is an open set
dom._zero_scalar_field._express[self] = self.function_ring().zero()
if hasattr(dom, '_one_scalar_field'):
# dom is an open set
dom._one_scalar_field._express[self] = self.function_ring().one()
for dom in self._domain.open_supersets():
dom._zero_scalar_field._express[self] = self.function_ring().zero()
dom._one_scalar_field._express[self] = self.function_ring().one()

def _init_coordinates(self, coord_list):
r"""
Expand Down Expand Up @@ -932,12 +928,9 @@ def transition_map(self, other, transformations, intersection_name=None,
The subset `W`, intersection of `U` and `V`, has been created by
``transition_map()``::
sage: M.list_of_subsets()
[1-dimensional topological manifold S^1,
Open subset U of the 1-dimensional topological manifold S^1,
Open subset V of the 1-dimensional topological manifold S^1,
Open subset W of the 1-dimensional topological manifold S^1]
sage: W = M.list_of_subsets()[3]
sage: F = M.subset_family(); F
Set {S^1, U, V, W} of open subsets of the 1-dimensional topological manifold S^1
sage: W = F['W']
sage: W is U.intersection(V)
True
sage: M.atlas()
Expand All @@ -960,9 +953,8 @@ def transition_map(self, other, transformations, intersection_name=None,
In this case, no new subset has been created since `U \cap M = U`::
sage: M.list_of_subsets()
[2-dimensional topological manifold R^2,
Open subset U of the 2-dimensional topological manifold R^2]
sage: M.subset_family()
Set {R^2, U} of open subsets of the 2-dimensional topological manifold R^2
but a new chart has been created: `(U, (x, y))`::
Expand Down Expand Up @@ -3010,7 +3002,7 @@ def __init__(self, chart1, chart2, *transformations):
# is added to the subset (and supersets) dictionary:
if chart1._domain == chart2._domain:
domain = chart1._domain
for sdom in domain._supersets:
for sdom in domain.open_supersets():
sdom._coord_changes[(chart1, chart2)] = self

def _repr_(self):
Expand Down
22 changes: 9 additions & 13 deletions src/sage/manifolds/differentiable/chart.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,12 +357,9 @@ def transition_map(self, other, transformations, intersection_name=None,
The subset `W`, intersection of `U` and `V`, has been created by
``transition_map()``::
sage: M.list_of_subsets()
[1-dimensional differentiable manifold S^1,
Open subset U of the 1-dimensional differentiable manifold S^1,
Open subset V of the 1-dimensional differentiable manifold S^1,
Open subset W of the 1-dimensional differentiable manifold S^1]
sage: W = M.list_of_subsets()[3]
sage: F = M.subset_family(); F
Set {S^1, U, V, W} of open subsets of the 1-dimensional differentiable manifold S^1
sage: W = F['W']
sage: W is U.intersection(V)
True
sage: M.atlas()
Expand All @@ -385,9 +382,8 @@ def transition_map(self, other, transformations, intersection_name=None,
In this case, no new subset has been created since `U\cap M = U`::
sage: M.list_of_subsets()
[2-dimensional differentiable manifold R^2,
Open subset U of the 2-dimensional differentiable manifold R^2]
sage: M.subset_family()
Set {R^2, U} of open subsets of the 2-dimensional differentiable manifold R^2
but a new chart has been created: `(U, (x, y))`::
Expand Down Expand Up @@ -563,7 +559,7 @@ def restrict(self, subset, restrictions=None):
sframe._restrictions[subset] = resu._frame
# The subchart frame is not a "top frame" in the supersets
# (including self._domain):
for dom in self._domain._supersets:
for dom in self._domain.open_supersets():
if resu._frame in dom._top_frames:
# it was added by the Chart constructor invoked in
# Chart.restrict above
Expand Down Expand Up @@ -1046,7 +1042,7 @@ def restrict(self, subset, restrictions=None):
sframe._restrictions[subset] = resu._frame
# The subchart frame is not a "top frame" in the supersets
# (including self._domain):
for dom in self._domain._supersets:
for dom in self._domain.open_supersets():
if resu._frame in dom._top_frames:
# it was added by the Chart constructor invoked in
# Chart.restrict above
Expand Down Expand Up @@ -1138,15 +1134,15 @@ def __init__(self, chart1, chart2, *transformations):
ch_basis.add_comp(frame1)[:, chart1] = self._jacobian
ch_basis.add_comp(frame2)[:, chart1] = self._jacobian
vf_module._basis_changes[(frame2, frame1)] = ch_basis
for sdom in domain._supersets:
for sdom in domain.open_supersets():
sdom._frame_changes[(frame2, frame1)] = ch_basis
# The inverse is computed only if it does not exist already
# (because if it exists it may have a simpler expression than that
# obtained from the matrix inverse)
if (frame1, frame2) not in vf_module._basis_changes:
ch_basis_inv = ch_basis.inverse()
vf_module._basis_changes[(frame1, frame2)] = ch_basis_inv
for sdom in domain._supersets:
for sdom in domain.open_supersets():
sdom._frame_changes[(frame1, frame2)] = ch_basis_inv

def jacobian(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
lightlike submanifold) and in General Relativity. In geometry of lightlike
submanifolds, according to the dimension `r` of the radical distribution
(see below for definition of radical distribution), degenerate submanifolds
have been classify into 4 subgroups: `r`-lightlike submanifolds, Coisotropic
have been classified into 4 subgroups: `r`-lightlike submanifolds, Coisotropic
submanifolds, Isotropic submanifolds and Totally lightlike submanifolds.
(See the book of Krishan L. Duggal and Aurel Bejancu [DS2010]_.)
Expand Down
8 changes: 3 additions & 5 deletions src/sage/manifolds/differentiable/diff_form_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,16 +384,14 @@ def _an_element_(self):
"""
resu = self.element_class(self._vmodule, self._degree)
# Non-trivial open covers of the domain:
open_covers = self._domain.open_covers()[1:] # the open cover 0
# is trivial
if open_covers != []:
oc = open_covers[0] # the first non-trivial open cover is selected
for oc in self._domain.open_covers(trivial=False):
# the first non-trivial open cover is selected
for dom in oc:
vmodule_dom = dom.vector_field_module(
dest_map=self._dest_map.restrict(dom))
dmodule_dom = vmodule_dom.dual_exterior_power(self._degree)
resu.set_restriction(dmodule_dom._an_element_())
return resu
return resu

def _coerce_map_from_(self, other):
Expand Down
79 changes: 78 additions & 1 deletion src/sage/manifolds/differentiable/differentiable_submanifold.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
AUTHORS:
- Florentin Jaffredo (2018): initial version
- Eric Gourgoulhon (2018-2019): add documentation
- Matthias Koeppe (2021): open subsets of submanifolds
REFERENCES:
Expand All @@ -26,7 +28,9 @@
"""

# *****************************************************************************
# Copyright (C) 2018 Florentin Jaffredo <florentin.jaffredo@polytechnique.edu>
# Copyright (C) 2018 Florentin Jaffredo <florentin.jaffredo@polytechnique.edu>
# Copyright (C) 2018-2019 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr>
# 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 @@ -208,10 +212,83 @@ def _repr_(self):
3-dimensional differentiable manifold M
"""
if self is not self._manifold:
return "Open subset {} of the {}".format(self._name, self._manifold)
if self._ambient is None:
return super(DifferentiableManifold, self).__repr__()
if self._embedded:
return "{}-dimensional {} submanifold {} embedded in the {}".format(
self._dim, self._structure.name, self._name, self._ambient)
return "{}-dimensional {} submanifold {} immersed in the {}".format(
self._dim, self._structure.name, self._name, self._ambient)

def open_subset(self, name, latex_name=None, coord_def={}, supersets=None):
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 differentiable
manifold by itself.
As ``self`` is a submanifold of its ambient manifold,
the new open subset is also considered a submanifold of that.
Hence the returned object is an instance of
:class:`DifferentiableSubmanifold`.
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 in the manifold's atlas and values the symbolic expressions
formed by the coordinates to define the subset.
- ``supersets`` -- (default: only ``self``) list of sets that the
new open subset is a subset of
OUTPUT:
- the open subset, as an instance of :class:`DifferentiableSubmanifold`
EXAMPLES::
sage: M = Manifold(3, 'M', structure="differentiable")
sage: N = Manifold(2, 'N', ambient=M, structure="differentiable"); N
2-dimensional differentiable submanifold N immersed in the
3-dimensional differentiable manifold M
sage: S = N.subset('S'); S
Subset S of the
2-dimensional differentiable submanifold N immersed in the
3-dimensional differentiable manifold M
sage: O = N.subset('O', is_open=True); O # indirect doctest
Open subset O of the
2-dimensional differentiable submanifold N immersed in the
3-dimensional differentiable manifold M
sage: phi = N.diff_map(M)
sage: N.set_embedding(phi)
sage: N
2-dimensional differentiable submanifold N embedded in the
3-dimensional differentiable manifold M
sage: S = N.subset('S'); S
Subset S of the
2-dimensional differentiable submanifold N embedded in the
3-dimensional differentiable manifold M
sage: O = N.subset('O', is_open=True); O # indirect doctest
Open subset O of the
2-dimensional differentiable submanifold N embedded in the
3-dimensional differentiable manifold M
"""
resu = DifferentiableSubmanifold(self._dim, name, self._field,
self._structure, ambient=self._ambient,
base_manifold=self._manifold,
diff_degree=self._diff_degree,
latex_name=latex_name,
start_index=self._sindex)
if supersets is None:
supersets = [self]
for superset in supersets:
superset._init_open_subset(resu, coord_def=coord_def)
return resu
14 changes: 6 additions & 8 deletions src/sage/manifolds/differentiable/examples/real_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,11 @@ class OpenInterval(DifferentiableManifold):
We have::
sage: I.list_of_subsets()
sage: list(I.subset_family())
[Real interval (0, 1), Real interval (0, pi), Real interval (1/2, 1)]
sage: J.list_of_subsets()
sage: list(J.subset_family())
[Real interval (0, 1), Real interval (1/2, 1)]
sage: K.list_of_subsets()
sage: list(K.subset_family())
[Real interval (1/2, 1)]
As any open subset of a manifold, open subintervals are created in a
Expand Down Expand Up @@ -376,9 +376,7 @@ def __init__(self, lower, upper, ambient_interval=None,
if upper > ambient_interval.upper_bound():
raise ValueError("the upper bound is larger than that of "
+ "the containing interval")
self._supersets.update(ambient_interval._supersets)
for sd in ambient_interval._supersets:
sd._subsets.add(self)
self.declare_subset(ambient_interval)
ambient_interval._top_subsets.add(self)
t = ambient_interval.canonical_coordinate()
if lower != minus_infinity:
Expand Down Expand Up @@ -684,7 +682,7 @@ def open_interval(self, lower, upper, name=None, latex_name=None):
Real interval (0, pi)
sage: J.is_subset(I)
True
sage: I.list_of_subsets()
sage: list(I.subset_family())
[Real interval (-4, 4), Real interval (0, pi)]
``J`` is considered as an open submanifold of ``I``::
Expand Down Expand Up @@ -863,7 +861,7 @@ class RealLine(OpenInterval):
Real interval (0, 1)
sage: I.manifold()
Real number line R
sage: R.list_of_subsets()
sage: list(R.subset_family())
[Real interval (0, 1), Real number line R]
"""
Expand Down
18 changes: 7 additions & 11 deletions src/sage/manifolds/differentiable/examples/sphere.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,12 +275,9 @@ class Sphere(PseudoRiemannianSubmanifold):
sage: stereoN, stereoS = S2.coordinate_charts('stereographic')
sage: stereoN, stereoS
(Chart (S^2-{NP}, (y1, y2)), Chart (S^2-{SP}, (yp1, yp2)))
sage: S2.open_covers()
[[2-sphere S^2 of radius 1 smoothly embedded in the Euclidean space E^3],
[Open subset S^2-{NP} of the 2-sphere S^2 of radius 1 smoothly
embedded in the Euclidean space E^3,
Open subset S^2-{SP} of the 2-sphere S^2 of radius 1 smoothly
embedded in the Euclidean space E^3]]
sage: list(S2.open_covers())
[Set {S^2} of open subsets of the 2-sphere S^2 of radius 1 smoothly embedded in the Euclidean space E^3,
Set {S^2-{NP}, S^2-{SP}} of open subsets of the 2-sphere S^2 of radius 1 smoothly embedded in the Euclidean space E^3]
.. NOTE::
Expand Down Expand Up @@ -501,11 +498,10 @@ def _init_chart_domains(self):
TESTS::
sage: S2 = manifolds.Sphere(2)
sage: S2.open_covers()
[[2-sphere S^2 of radius 1 smoothly embedded in the Euclidean space E^3],
[Open subset S^2-{NP} of the 2-sphere S^2 of radius 1 smoothly embedded in the Euclidean space E^3,
Open subset S^2-{SP} of the 2-sphere S^2 of radius 1 smoothly embedded in the Euclidean space E^3]]
sage: S2.subsets() # random
sage: list(S2.open_covers())
[Set {S^2} of open subsets of the 2-sphere S^2 of radius 1 smoothly embedded in the Euclidean space E^3,
Set {S^2-{NP}, S^2-{SP}} of open subsets of the 2-sphere S^2 of radius 1 smoothly embedded in the Euclidean space E^3]
sage: frozenset(S2.subsets()) # random
frozenset({Euclidean 2-sphere S^2 of radius 1,
Open subset A of the Euclidean 2-sphere S^2 of radius 1,
Open subset S^2-{NP,SP} of the Euclidean 2-sphere S^2 of radius 1,
Expand Down

0 comments on commit 5d41b46

Please sign in to comment.