Opened 12 months ago
Closed 9 months ago
#33001 closed enhancement (fixed)
Invoke manifolds with structure more conveniently
Reported by:  Michael Jung  Owned by:  

Priority:  major  Milestone:  sage9.6 
Component:  manifolds  Keywords:  
Cc:  Eric Gourgoulhon, Travis Scrimshaw, Tobias Diez  Merged in:  
Authors:  Matthias Koeppe  Reviewers:  Travis Scrimshaw 
Report Upstream:  N/A  Work issues:  
Branch:  9548b50 (Commits, GitHub, GitLab)  Commit:  9548b506dc11216176512cf404fa9976d4c3eda1 
Dependencies:  Stopgaps: 
Description (last modified by )
Inspired by the discussion in #30362, comment:77, we change the Manifold
constructor so that once can omit the structure
parameter when parameters such as diff_degree
or metric_name
are given:
sage: M = Manifold(3, 'M', diff_degree=0); M 3dimensional topological manifold M sage: M = Manifold(3, 'M', diff_degree=2); M 3dimensional differentiable manifold M sage: M = Manifold(3, 'M', metric_name='g'); M 3dimensional Riemannian manifold M
Change History (28)
comment:2 Changed 12 months ago by
Alright, I see. That makes sense. What about something like Manifold.Topological(...)
?
comment:3 followup: 13 Changed 12 months ago by
I'd rather suggest to look into having certain keyword arguments trigger a choice of structure.
sage: Manifold(2, 'M', diff_degree=7) ValueError: diff_degree = 7 is not compatible with a smooth structure
Instead, this could perhaps imply structure='differentiable'
.
sage: Manifold(2, 'M', metric_name='g') 2dimensional differentiable manifold M
Instead, this should probably select structure='Riemannian'
.
It would also be good if users could pass a category
keyword to select the structure. In this direction, also for example the Riemannian structure is not yet reflected in the categories:
sage: E = EuclideanSpace(2) sage: E.category() Join of Category of smooth manifolds over Real Field with 53 bits of precision and Category of connected manifolds over Real Field with 53 bits of precision and Category of complete metric spaces
This is something that we should extend along the way.
comment:4 Changed 12 months ago by
I agree with Matthias. I would not be opposed to manifolds.Topological
, but I like having default behavior depend on extra parameters. +1 on adding more categories (although we have to differentiate be metric_function
and metric_tensor
) and having the category information yield the structure. Of course, in all cases, if the user explicitly passes structure
, that should take priority or raise an error if there is a conflict.
comment:5 Changed 12 months ago by
I agree. The categorical approach is the most natural one.
I think we should get rid of the structure implementation as it is right now and entirely jump over to categories. This would also have the great advantage that we can combine structures such as symplectic and Riemannian structures, which are not mutually exclusive.
Also this default behavior on extra parameters is a good idea.
comment:6 followup: 7 Changed 12 months ago by
I am fairly 1 on pushing the full structure into the categories. This was a very conscious design decision in full view of what could be done with categories.
 It makes it difficult to easily change. Right now, it is trivial if someone wants to promote/demote the structure of a manifold. (You change a parameter and do not have to create an entire new object, which is relatively expensive for manifolds.)
 It allows for something easy to transfer information across different base rings.
 It is easy to have extra parameterizations. For example, the classes of C^{k} manifolds.
It is meant to work in conjunction with the categories.
comment:7 followup: 8 Changed 12 months ago by
Replying to tscrim:
I am fairly 1 on pushing the full structure into the categories. This was a very conscious design decision in full view of what could be done with categories.
 It makes it difficult to easily change. Right now, it is trivial if someone wants to promote/demote the structure of a manifold. (You change a parameter and do not have to create an entire new object, which is relatively expensive for manifolds.)
 It allows for something easy to transfer information across different base rings.
 It is easy to have extra parameterizations. For example, the classes of C^{k} manifolds.
It is meant to work in conjunction with the categories.
Can you elaborate on 1, please?
As for 2, do you have an example where the structure design makes things easier opposed to categories?
I see the point in 3.
Nevertheless, we should rethink the design in some way. We have Riemannian manifolds, which are represented by the class PseudoRiemannianManifold
and carry the structure RiemannianStructure
. With #30362 we get new structures, namely Poisson/symplectic structures. But now, a manifold can have a Riemannian structure and a symplectic structure. Which base class do we use? Which structure? Do we want to combine structures? If so, how? I just see that the category framework already comes with the benefit of joint categories. It might be easier to use that preexisting architecture.
comment:8 followup: 9 Changed 12 months ago by
Replying to ghmjungmath:
Replying to tscrim:
I am fairly 1 on pushing the full structure into the categories. This was a very conscious design decision in full view of what could be done with categories.
 It makes it difficult to easily change. Right now, it is trivial if someone wants to promote/demote the structure of a manifold. (You change a parameter and do not have to create an entire new object, which is relatively expensive for manifolds.)
 It allows for something easy to transfer information across different base rings.
 It is easy to have extra parameterizations. For example, the classes of C^{k} manifolds.
It is meant to work in conjunction with the categories.
Can you elaborate on 1, please?
If you have a manifold M
with structure S
, and you realize that it should have structure T
. This becomes a very simple change of swapping S
for T
. In particular, you want to change the smoothness. (Admittedly, I don't think we have a good hook for doing this.)
As for 2, do you have an example where the structure design makes things easier opposed to categories?
You want information preserved for manifolds over CC
and over RR
. These will lie in different categories. It also gets around not having a clear specification of RR
(e.g., no dependency on precision or the particular implementation). It is also better to identify information with attributes rather than methods (e.g., the chart class) for speed and readability.
Nevertheless, we should rethink the design in some way. We have Riemannian manifolds, which are represented by the class
PseudoRiemannianManifold
and carry the structureRiemannianStructure
. With #30362 we get new structures, namely Poisson/symplectic structures. But now, a manifold can have a Riemannian structure and a symplectic structure. Which base class do we use? Which structure? Do we want to combine structures? If so, how? I just see that the category framework already comes with the benefit of joint categories. It might be easier to use that preexisting architecture.
Don't conflate structures and base classes. They are different and serve different roles. Don't try and force a square peg into a round hole. Right now there is not a combinatorial explosion of cases, so we don't need to use a backhoe when all we need is a shovel either. If you need a combined structure, then make a combined structure.
comment:9 followup: 10 Changed 12 months ago by
Replying to tscrim:
If you have a manifold
M
with structureS
, and you realize that it should have structureT
. This becomes a very simple change of swappingS
forT
. In particular, you want to change the smoothness. (Admittedly, I don't think we have a good hook for doing this.)
Why can't you just swap the category accordingly? As far as I see it, this is the same concept.
You want information preserved for manifolds over
CC
and overRR
. These will lie in different categories. It also gets around not having a clear specification ofRR
(e.g., no dependency on precision or the particular implementation). It is also better to identify information with attributes rather than methods (e.g., the chart class) for speed and readability.
That's a good argument. I think, though, this can easily be circumvented by using a category base class that is not build upon a "base ring" structure.
Don't conflate structures and base classes. They are different and serve different roles. Don't try and force a square peg into a round hole. Right now there is not a combinatorial explosion of cases, so we don't need to use a backhoe when all we need is a shovel either. If you need a combined structure, then make a combined structure.
Well, that is my point. Base classes and structures are different, and yet we have a Riemannian manifold base class and structure.
Though I'd prefer categories; if we stay with the structure design, I'd feel more comfortable if we'd implement joins of structures. This is far more flexible and robust for future structures. It's getting harder to change the architecture when the "combinatorial explosion of cases" is already too high.
comment:10 Changed 12 months ago by
Replying to ghmjungmath:
Replying to tscrim:
If you have a manifold
M
with structureS
, and you realize that it should have structureT
. This becomes a very simple change of swappingS
forT
. In particular, you want to change the smoothness. (Admittedly, I don't think we have a good hook for doing this.)Why can't you just swap the category accordingly? As far as I see it, this is the same concept.
Because categories are strongly tied to the creation of the object (and its elements) as it creates a dynamic subclass. In fact, strictly speaking, the differentiable structure of a manifold can give different objects in the category of differentiable manifolds (although we have actually pushed this data into the manifold itself).
You want information preserved for manifolds over
CC
and overRR
. These will lie in different categories. It also gets around not having a clear specification ofRR
(e.g., no dependency on precision or the particular implementation). It is also better to identify information with attributes rather than methods (e.g., the chart class) for speed and readability.That's a good argument. I think, though, this can easily be circumvented by using a category base class that is not build upon a "base ring" structure.
Categories carry mathematical information. You cannot separate the base ring.
Don't conflate structures and base classes. They are different and serve different roles. Don't try and force a square peg into a round hole. Right now there is not a combinatorial explosion of cases, so we don't need to use a backhoe when all we need is a shovel either. If you need a combined structure, then make a combined structure.
Well, that is my point. Base classes and structures are different, and yet we have a Riemannian manifold base class and structure.
You cannot get around having a base class when you want extra methods, at least without a performance penalty or monkeypatching. However, it can have a range of structures attached to it.
Though I'd prefer categories; if we stay with the structure design, I'd feel more comfortable if we'd implement joins of structures. This is far more flexible and robust for future structures. It's getting harder to change the architecture when the "combinatorial explosion of cases" is already too high.
That is a fallacy as good OOP design means you do not care about how the backend is implemented. This sounds like the engineer's paradox: spend 30% more time making something 10% faster.
comment:11 followups: 17 20 Changed 12 months ago by
My remark originally was that I find TopologicalManifold('M')
easier to write and remember than Manifold('M', structure='topological')
. What about exposing the different classes in mainfold/all
?
At least for a start the initialization code such as
https://github.com/sagemath/sage/blob/develop/src/sage/manifolds/manifold.py#L2960L2970
should go in the corresponding constructor of Topological(Sub)Manifold
in my opinion so that Manifold
is really only choosing the proper class to initialize based on the parameters provided. Then one can choose if one prefers to import TopologicalManifold? and uses it directly, or is the Manifold constructor.
I cannot really contribute to the category vs structure discussion as I'm not familiar enough with the category framework. (If someone wants to enlighten me: what are the practical consequences of viewing \C
as a complex manifold vs as a real manifold?)
From a mathematical perspective, the 'structure' is often easy to define whereas the relevant category may depend on the applications one has in mind (e.g. https://en.wikipedia.org/wiki/Symplectic_category).
comment:12 Changed 12 months ago by
Branch:  → u/mkoeppe/invoke_manifolds_with_structure_more_conveniently 

comment:13 Changed 12 months ago by
Commit:  → 6cc6200eefc2b2dc162af2427a18e74271997ded 

comment:14 Changed 12 months ago by
Authors:  → Matthias Koeppe 

comment:15 Changed 12 months ago by
Commit:  6cc6200eefc2b2dc162af2427a18e74271997ded → fbb5ec6e8c9cb84d5f28b82a2c135a4985978310 

Branch pushed to git repo; I updated commit sha1. New commits:
fbb5ec6  TopologicalSubmanifold._init_immersion: Move dimension check here from Manifold constructor

comment:16 Changed 12 months ago by
Commit:  fbb5ec6e8c9cb84d5f28b82a2c135a4985978310 → 14fa05598b55448f353477a58a0000a486d95bed 

Branch pushed to git repo; I updated commit sha1. New commits:
14fa055  Manifold: Move type checking for ambient to __init__ methods

comment:17 Changed 12 months ago by
Replying to ghtobiasdiez:
for a start the initialization code such as https://github.com/sagemath/sage/blob/develop/src/sage/manifolds/manifold.py#L2960L2970 should go in the corresponding constructor of
Topological(Sub)Manifold
in my opinion so thatManifold
is really only choosing the proper class to initialize based on the parameters provided.
Done
comment:18 Changed 12 months ago by
Commit:  14fa05598b55448f353477a58a0000a486d95bed → 9548b506dc11216176512cf404fa9976d4c3eda1 

Branch pushed to git repo; I updated commit sha1. New commits:
9548b50  TopologicalManifold.__init__: Move input checking for dimension parameter here from Manifold constructor

comment:19 Changed 12 months ago by
Description:  modified (diff) 

Status:  new → needs_review 
comment:20 followups: 22 23 Changed 12 months ago by
Replying to ghtobiasdiez:
My remark originally was that I find
TopologicalManifold('M')
easier to write and remember thanManifold('M', structure='topological')
. What about exposing the different classes inmainfold/all
? At least for a start the initialization code such as https://github.com/sagemath/sage/blob/develop/src/sage/manifolds/manifold.py#L2960L2970 should go in the corresponding constructor ofTopological(Sub)Manifold
in my opinion so thatManifold
is really only choosing the proper class to initialize based on the parameters provided. Then one can choose if one prefers to import TopologicalManifold? and uses it directly, or is the Manifold constructor.
I am very strong 1 on adding a bunch of things that pollute the global namespace when there is a generic concept (here a "manifold") and a global entry point. Not only does it create more imports at startup (even if done lazily, it still means more objects), more maintenance if names change, and more documentation fragmentation (it makes it much easier to decide where to put, e.g., construction information). (If you find it easier, then you can add it to your init.sage
file.) We also cannot fully move that code to the initialization because at that point it is too late to decide whether or not we are a submanifold (or decide our structure). The safety checks could be moved if desired.
comment:21 Changed 12 months ago by
The dispatching based on ambient
could of course also be done in a __classcall__
method, but I haven't made this change on the branch.
comment:22 Changed 12 months ago by
Replying to tscrim:
I am very strong 1 on adding a bunch of things that pollute the global namespace when there is a generic concept (here a "manifold") and a global entry point. Not only does it create more imports at startup (even if done lazily, it still means more objects), more maintenance if names change, and more documentation fragmentation (it makes it much easier to decide where to put, e.g., construction information). (If you find it easier, then you can add it to your
init.sage
file.) We also cannot fully move that code to the initialization because at that point it is too late to decide whether or not we are a submanifold (or decide our structure). The safety checks could be moved if desired.
I fully agree with all the above points.
comment:23 Changed 12 months ago by
Replying to tscrim:
I am very strong 1 on adding a bunch of things that pollute the global namespace when there is a generic concept (here a "manifold") and a global entry point.
Fair enough!
We also cannot fully move that code to the initialization because at that point it is too late to decide whether or not we are a submanifold (or decide our structure).
I agree with the submanifold part, but why is it not possible to decide about the structure? It seems to me that the structure of a topological manifold is completely determined by the base field (and similarly for diff manifolds). One could probably even remove the structure constructor argument of TopologicalManifold
, as its currently only used by the Manifold
constructor and by subclasses. The latter can also directly set the variable _structure
as they see fit. Has the advantage to make the whole structure thing an implementation detail that users of the class don't need to care about.
comment:24 Changed 11 months ago by
Milestone:  sage9.5 → sage9.6 

comment:25 Changed 9 months ago by
Description:  modified (diff) 

comment:26 Changed 9 months ago by
Reviewers:  → Travis Scrimshaw 

Status:  needs_review → positive_review 
LGTM.
comment:28 Changed 9 months ago by
Branch:  u/mkoeppe/invoke_manifolds_with_structure_more_conveniently → 9548b506dc11216176512cf404fa9976d4c3eda1 

Resolution:  → fixed 
Status:  positive_review → closed 
1 on adding classes such as
TopologicalManifold
tomanifolds
; to my understandingmanifolds
, likepolytopes
,groups
,algebras
, is intended to provide a "catalog" of examples, not a general "namespace".