sagemath / sage

Main repository of SageMath
https://www.sagemath.org
Other
1.39k stars 473 forks source link

Refactor Components into parent & element, step 1 #34497

Open mkoeppe opened 2 years ago

mkoeppe commented 2 years ago

We introduce a parent class for Components, called TensorFreeModuleWithBasis (although it won't be a module yet as of this ticket).

We move symmetry attributes, frame, and output formatter there.

This is a step toward #30307.

CC: @egourgoulhon @tscrim

Component: linear algebra

Branch/Commit: u/mkoeppe/refactor_components_into_parent_elementstep_1 @ 96dfc4b

Issue created by migration from https://trac.sagemath.org/ticket/34497

mkoeppe commented 2 years ago

Branch: u/mkoeppe/refactor_components_into_parent_elementstep_1

egourgoulhon commented 2 years ago
comment:2

I am not convinced about the tensor module structure for the parent, because, in some cases, Components is used to store data that do not behave as tensor components under a change of basis, namely the coefficients of an affine connection on a differentiable manifold. Because of the lack of a clear algebraic structure, I am not convinced either that the !Parent/Element scheme is what we need here. We had a discussion about this in #30307. I understand the need to delegate the handling of symmetries to a devoted class, but maybe not a Parent class...


New commits:

96dfc4bsrc/sage/tensor/modules/with_basis/tensor_free_module.py: New
egourgoulhon commented 2 years ago

Commit: 96dfc4b

mkoeppe commented 2 years ago
comment:3

Replying to Eric Gourgoulhon:

I am not convinced about the tensor module structure for the parent, because, in some cases, Components is used to store data that do not behave as tensor components under a change of basis

The basis is fixed, and a Components instance does not even know which indices are covariant and which are contravariant positions, so I don't think any claims how things transform are made.

This module would be just like a FreeModule or a MatrixSpace. Note that a matrix also does not know how it should transform - whether as the matrix of a linear map or as the matrix of a quadratic form.

mkoeppe commented 2 years ago
comment:4

To add to this, the information how things transform is stored in the morphism from the TensorFreeModule to the TensorFreeModuleWithBasis, not in the module.

In the context of some of the other recent tickets: This morphism is exactly the isomorphism_with_fixed_basis (#34427).

egourgoulhon commented 2 years ago
comment:5

Replying to Matthias Köppe:

Replying to Eric Gourgoulhon:

I am not convinced about the tensor module structure for the parent, because, in some cases, Components is used to store data that do not behave as tensor components under a change of basis

The basis is fixed, and a Components instance does not even know which indices are covariant and which are contravariant positions, so I don't think any claims how things transform are made.

Indeed, but the very name TensorFreeModuleWithBasis suggests that we are dealing with the components of a tensor on a free module, while the connection coefficients are no such thing. In particular, the set of affine connections on a given manifold is usually not endowed with a module structure: there is no meaning in adding two affine connections, and the multiplication by an element of the (potential) base ring --- the algebra of smooth scalar fields, would not lead to another affine connection.

This module would be just like a FreeModule or a MatrixSpace. Note that a matrix also does not know how it should transform - whether as the matrix of a linear map or as the matrix of a quadratic form.

Yes, that's clear. The "matrix" point of view should be the one to adopt here. For the case of the connection coefficients, the module operations would have no meaning for the affine connections they come from, but this is OK, i.e. these operations will simply not be used in that case (there is no addition nor scalar multiplication defined at the level of AffineConnection).

mkoeppe commented 2 years ago
comment:6

Replying to Eric Gourgoulhon:

Replying to Matthias Köppe:

Replying to Eric Gourgoulhon:

I am not convinced about the tensor module structure for the parent, because, in some cases, Components is used to store data that do not behave as tensor components under a change of basis

The basis is fixed, and a Components instance does not even know which indices are covariant and which are contravariant positions, so I don't think any claims how things transform are made.

Indeed, but the very name TensorFreeModuleWithBasis suggests that we are dealing with the components of a tensor on a free module, while the connection coefficients are no such thing. In particular, the set of affine connections on a given manifold is usually not endowed with a module structure: there is no meaning in adding two affine connections, and the multiplication by an element of the (potential) base ring --- the algebra of smooth scalar fields, would not lead to another affine connection.

OK, this is a great point, thank you. Now I remember #30245, which goes in a similar direction. The presence of these automatically provided addition and multiplication operations can indeed be misleading in such situations.

It would be worthwhile to think about whether we should make it possible to create a MatrixSpace or TensorFreeModuleWithBasis in a larger category than ModulesWithBasis, perhaps just Sets, and in that case use an element class that does not provide the module operations (_add_, _lmul_ etc.)

mkoeppe commented 2 years ago
comment:7

Of course, one could say "if you want just an array, use an array, not a matrix", but this would ignore that we have specialized element classes for matrices over specific base rings, which are advantageous to use even if there's no module structure.

egourgoulhon commented 2 years ago
comment:8

Replying to Matthias Köppe:

Replying to Eric Gourgoulhon:

Replying to Matthias Köppe:

Replying to Eric Gourgoulhon:

I am not convinced about the tensor module structure for the parent, because, in some cases, Components is used to store data that do not behave as tensor components under a change of basis

The basis is fixed, and a Components instance does not even know which indices are covariant and which are contravariant positions, so I don't think any claims how things transform are made.

Indeed, but the very name TensorFreeModuleWithBasis suggests that we are dealing with the components of a tensor on a free module, while the connection coefficients are no such thing. In particular, the set of affine connections on a given manifold is usually not endowed with a module structure: there is no meaning in adding two affine connections, and the multiplication by an element of the (potential) base ring --- the algebra of smooth scalar fields, would not lead to another affine connection.

OK, this is a great point, thank you. Now I remember #30245, which goes in a similar direction. The presence of these automatically provided addition and multiplication operations can indeed be misleading in such situations.

It looks less severe here than in #30245: as you pointed out, the connection coefficients in a given basis can be considered as elements of a tensor module and one can performed module operations of them (after all, the class Components defines __add__ and __rmul__), simply these operations do not correspond to operations on the connections themselves, so that they will not be used in an actual code.

It would be worthwhile to think about whether we should make it possible to create a MatrixSpace or TensorFreeModuleWithBasis in a larger category than ModulesWithBasis, perhaps just Sets, and in that case use an element class that does not provide the module operations (_add_, _lmul_ etc.)

Given the remark above, I would say it is fine to stay with the category ModulesWithBasis.

egourgoulhon commented 2 years ago
comment:9

Replying to Matthias Köppe:

Of course, one could say "if you want just an array, use an array, not a matrix", but this would ignore that we have specialized element classes for matrices over specific base rings, which are advantageous to use even if there's no module structure.

That's a good point.

A possible concern about moving to the Parent/Element scheme is about the efficiency with respect to the pure array-like structure. The class Components is at the root of the calculus on manifolds and one should make sure that introducing parents does now yield some significant slow down. But this is something we can check and benchmark.

mkoeppe commented 2 years ago
comment:10

Absolutely. The intention here is to make construction of elements and arithmetic faster, not slower; and this will have to be benchmarked.

mjungmath commented 2 years ago
comment:11

We already had this discussion somewhere. I raised the concern that, mathematically speaking, a parent is not a "small object". The category of objects would be more appropriate, IMHO.

I also think that the name is misleading. In the previous ticket I proposed CompParent.

mkoeppe commented 2 years ago
comment:12

It's a module, hence ...Module.

mjungmath commented 2 years ago
comment:13

Ah I see, you let the parent handle the frames. Then, at least mathematically, it should be fine.

But from the programming viewpoint I see a problem with UniqueRepresentation. The nice thing about the current implementation (and also the curse for maintenance) is that frames can flexibly be added. If the parent's signature is determined by the list of frames, we run into troubles when we want to add another one at a later point.

mjungmath commented 2 years ago
comment:14

Perhaps a class of family of frames that is a UniqueRepresentation and allows to flexibly add (and remove?) frames is what we want?

mjungmath commented 2 years ago
comment:15

Actually, I think this is even a great idea in terms of the big picture. That way, we can build pre-sheaves of frames on manifolds and probably even frame-bundles more easily.

Moreover, I think we can get rid of a lot of code redundancies w.r.t. frames/bases.

What do you think?

mkoeppe commented 2 years ago
comment:16

Replying to Michael Jung:

from the programming viewpoint I see a problem with UniqueRepresentation. The nice thing about the current implementation (and also the curse for maintenance) is that frames can flexibly be added. If the parent's signature is determined by the list of frames, we run into troubles when we want to add another one at a later point.

You are misunderstanding the code on the branch. The frame is fixed in an instance of the parent TensorFreeModuleWithBasis. frames (and start_indices) are plural because I'm keeping one frame per tensor index as preparation for supporting tensor products of different spaces, such as V (x) W (x) V^* (x) W^*.

mjungmath commented 2 years ago
comment:17

Ah! That's clever. Then I agree with everything that was said.

(Otherwise it's also not a module...!)

Thank you for the clarification.

mjungmath commented 2 years ago
comment:18

We should keep the idea of families of frames in mind though.

mkoeppe commented 2 years ago
comment:19

Replying to Michael Jung:

We should keep the idea of families of frames in mind though.

Yes, I'm preparing the sheafy stuff in #34398, #34461