Opened 2 years ago

Last modified 3 months ago

## #30164 new enhancement

# Add category FreeModules (without distinguished basis)

Reported by: | Matthias Köppe | Owned by: | |
---|---|---|---|

Priority: | major | Milestone: | sage-9.8 |

Component: | linear algebra | Keywords: | |

Cc: | Travis Scrimshaw, Eric Gourgoulhon, Michael Jung | Merged in: | |

Authors: | Reviewers: | ||

Report Upstream: | N/A | Work issues: | |

Branch: | Commit: | ||

Dependencies: | Stopgaps: |

### Description

From `sage.tensor.modules.finite_rank_free_module`

:

.. TODO:: - implement submodules - create a FreeModules category (cf. the *TODO* statement in the documentation of :class:`~sage.categories.modules.Modules`: *Implement a ``FreeModules(R)`` category, when so prompted by a concrete use case*)

### Change History (19)

### comment:1 Changed 2 years ago by

### comment:2 Changed 2 years ago by

Perhaps, in fact, this category should define (as an abstract method) the method `isomorphism_with_fixed_basis`

proposed in #30094.

### comment:3 follow-up: 4 Changed 2 years ago by

My thought is that would be better left to the concrete implementation. It almost seems like you are proposing lifting the entire concrete implementation of `FiniteRankFreeModule`

to the category, at which point the category becomes the parent, rather than the abstraction of the properties you want the parent to have. I feel like that might make the code maintenance harder because the two concepts are becoming too blurred together.

### comment:4 follow-up: 5 Changed 2 years ago by

Replying to tscrim:

My thought is that would be better left to the concrete implementation. It almost seems like you are proposing lifting the entire concrete implementation of

`FiniteRankFreeModule`

to the category, at which point the category becomes the parent, rather than the abstraction of the properties you want the parent to have.

There is certainly a subtle line that separates expectations for a category's parent/element methods from those for abstract base classes.

I would think that user-facing methods that expose a mathematical concept/theorem do belong to the category.

Concretely, an implementation detail certainly is how a basis is designated or represented. `FiniteRankFreeModule`

uses a custom class for representing a basis and accepts symbols (strings) as designators for a basis. I agree that it would make maintenance harder if on the category level we tried to define this.

However, we can focus on the theorem that in a free module we can choose a basis and that therefore there exists a free module isomorphism with a free module with the same base ring and rank. And this is exactly what is expressed by the method `isomorphism_with_fixed_basis`

-- without having to expose the concrete concept of a basis on the category level.

I would generalize the method from #30094, `isomorphism_with_fixed_basis(self, basis, codomain=None)`

, so that the parameter `basis`

becomes optional - and when not provided uses some basis (such as the default basis if it has been set, or like `some_elements`

does, to set the default basis to something arbitrary).

The category's parent method would use the compatible signature
`isomorphism_with_fixed_basis(self, *, codomain=None)`

. It would be an optional abstract method.

### comment:5 follow-ups: 6 7 Changed 2 years ago by

Replying to mkoeppe:

Replying to tscrim:

My thought is that would be better left to the concrete implementation. It almost seems like you are proposing lifting the entire concrete implementation of

`FiniteRankFreeModule`

to the category, at which point the category becomes the parent, rather than the abstraction of the properties you want the parent to have.There is certainly a subtle line that separates expectations for a category's parent/element methods from those for abstract base classes.

I would think that user-facing methods that expose a mathematical concept/theorem do belong to the category.

Concretely, an implementation detail certainly is how a basis is designated or represented.

`FiniteRankFreeModule`

uses a custom class for representing a basis and accepts symbols (strings) as designators for a basis. I agree that it would make maintenance harder if on the category level we tried to define this.

The maintenance aspect with categories is something that I worry a bit more about. I have gotten a lot of questions asking how the category framework works with its black magic. Most of the times I point to a concrete implementation and the key methods someone needs to implement.

Additionally, abstracting free modules will not lead to a combinatorial explosion of classes involving different combinations of axioms (which is the main reason why we have this framework). We see this with `CombinatorialFreeModule`

; many implementations of different objects use that implementation for the underlying module rather than the abstraction in `ModulesWithBasis`

.

However, we can focus on the theorem that in a free module we can choose a basis and that therefore there exists a free module isomorphism with a free module with the same base ring and rank. And this is exactly what is expressed by the method

`isomorphism_with_fixed_basis`

-- without having to expose the concrete concept of a basis on the category level.I would generalize the method from #30094,

`isomorphism_with_fixed_basis(self, basis, codomain=None)`

, so that the parameter`basis`

becomes optional - and when not provided uses some basis (such as the default basis if it has been set, or like`some_elements`

does, to set the default basis to something arbitrary).

The difference with `some_elements`

would be that those elements are not a defining property of the set. Having a default basis sounds like a concrete implementation detail, and we don't want to impose a fixed semantic for `basis()`

. This would lead to a conflict between `FiniteRankFreeModule`

and anything in `ModulesWithBasis`

(which would naturally be a subcategory of `FreeModules`

).

The category's parent method would use the compatible signature

`isomorphism_with_fixed_basis(self, *, codomain=None)`

. It would be an optional abstract method.

This feels more like code bloat to me right now. At least, I cannot think of a definitive use-case for this over having a common ABC.

### comment:6 Changed 2 years ago by

Replying to tscrim:

I would generalize the method from #30094,

`isomorphism_with_fixed_basis(self, basis, codomain=None)`

, so that the parameter`basis`

becomes optional - and when not provided uses some basis (such as the default basis if it has been set, or like`some_elements`

does, to set the default basis to something arbitrary).The difference with

`some_elements`

would be that those elements are not a defining property of the set. Having a default basis sounds like a concrete implementation detail, and we don't want to impose a fixed semantic for`basis()`

. This would lead to a conflict between`FiniteRankFreeModule`

and anything in`ModulesWithBasis`

(which would naturally be a subcategory of`FreeModules`

).

In case it did not become clear, in my proposal I do NOT define a semantic for `basis()`

at all.

### comment:7 follow-up: 8 Changed 2 years ago by

Replying to tscrim:

The maintenance aspect with categories is something that I worry a bit more about. I have gotten a lot of questions asking how the category framework works with its black magic. Most of the times I point to a concrete implementation and the key methods someone needs to implement.

Could you elaborate on the maintenance aspect? This sounds to me just like a documentation problem. Would it not just suffice to add some comments to an implementation class what methods are already provided by the required category?

Additionally, abstracting free modules will not lead to a combinatorial explosion of classes involving different combinations of axioms (which is the main reason why we have this framework). We see this with

`CombinatorialFreeModule`

; many implementations of different objects use that implementation for the underlying module rather than the abstraction in`ModulesWithBasis`

.

I have noticed that, but the problem is that we have multiple incomplete and incompatible implementations of linear algebra. `CombinatorialFreeModule`

does not know about linear forms, `FiniteRankFreeModule`

does not know about triangular morphisms, ...

However, we can focus on the theorem that in a free module we can choose a basis and that therefore there exists a free module isomorphism with a free module with the same base ring and rank. And this is exactly what is expressed by the method

`isomorphism_with_fixed_basis`

-- without having to expose the concrete concept of a basis on the category level.`isomorphism_with_fixed_basis(self, basis, codomain=None)`

, so that the parameter`basis`

becomes optional - and when not provided uses some basis (such as the default basis if it has been set, or like`some_elements`

does, to set the default basis to something arbitrary).The difference with

`some_elements`

would be that those elements are not a defining property of the set. Having a default basis sounds like a concrete implementation detail, and we don't want to impose a fixed semantic for`basis()`

. This would lead to a conflict between`FiniteRankFreeModule`

and anything in`ModulesWithBasis`

(which would naturally be a subcategory of`FreeModules`

).The category's parent method would use the compatible signature

`isomorphism_with_fixed_basis(self, *, codomain=None)`

. It would be an optional abstract method.This feels more like code bloat to me right now. At least, I cannot think of a definitive use-case for this over having a common ABC.

My immediate application is #30198.

### comment:8 follow-up: 10 Changed 2 years ago by

Replying to mkoeppe:

Replying to tscrim:

The maintenance aspect with categories is something that I worry a bit more about. I have gotten a lot of questions asking how the category framework works with its black magic. Most of the times I point to a concrete implementation and the key methods someone needs to implement.

Could you elaborate on the maintenance aspect? This sounds to me just like a documentation problem. Would it not just suffice to add some comments to an implementation class what methods are already provided by the required category?

For someone who doesn't know the code, if you look at an object `X`

, how do you find the methods? The problem is that most of the classes in its MRO are dynamically created, so they don't exist as actual code. You also cannot easily point to specific points where to look. Generic answers are not very helpful, and there is documentation (including a number of tutorials), but it is a lot to process in one go. Now more often than not, the benefits of having the generic code outweigh the extra disassociation between the implementation and the use, but I don't see that here.

Additionally, abstracting free modules will not lead to a combinatorial explosion of classes involving different combinations of axioms (which is the main reason why we have this framework). We see this with

`CombinatorialFreeModule`

; many implementations of different objects use that implementation for the underlying module rather than the abstraction in`ModulesWithBasis`

.I have noticed that, but the problem is that we have multiple incomplete and incompatible implementations of linear algebra.

`CombinatorialFreeModule`

does not know about linear forms,`FiniteRankFreeModule`

does not know about triangular morphisms, ...

Not all of the features should necessarily be compatible because they are designed for different purposes. Sometimes these unaoidaby require specific implementation details. That being said, there are definitely missing features that could be lifted to an ABC, which can easily handle the generality you want.

Categories are heavier objects than ABCs, which are still effective at modeling the mathematics. There are more assumptions and a bigger ecosystem to worry about. For instance, you have to make sure that you cannot have a category for `FreeModulesWithBasis`

as an object in `ModulesWithBasis`

is free by definition. You have to make sure there are no possible convention conflicts (cf. metric).

`isomorphism_with_fixed_basis(self, *, codomain=None)`

. It would be an optional abstract method.

I feel like this method needs to handle a basis parameter. If you use a `default_basis()`

, then you need a method that should be named `basis()`

to create a basis. Also, something with a set `default_basis()`

is in `ModulesWithBasis`

essentially as the default basis is a distinguished basis. Not quite, but close. You have to also be a little more careful about what can happen when the default basis changes.

This feels more like code bloat to me right now. At least, I cannot think of a definitive use-case for this over having a common ABC.

My immediate application is #30198.

Why would you want a category over an ABC?

### comment:10 Changed 2 years ago by

Replying to tscrim:

Replying to mkoeppe:

`isomorphism_with_fixed_basis(self, *, codomain=None)`

. It would be an optional abstract method.I feel like this method needs to handle a basis parameter. If you use a

`default_basis()`

, then you need a method that should be named`basis()`

to create a basis. Also, something with a set`default_basis()`

is in`ModulesWithBasis`

essentially as the default basis is a distinguished basis. Not quite, but close. You have to also be a little more careful about what can happen when the default basis changes.

I think you're missing that I want the category (or, if you will, ABC) to provide the *abstract* method so that the protocol is specified, but not provide an implementation. Thus no methods `basis()`

or `default_basis()`

are assumed.

### comment:11 follow-up: 12 Changed 2 years ago by

In a slightly different direction: I think it should also be clarified what exactly the category `Modules(R).FiniteDimensional()`

is.

### comment:12 Changed 2 years ago by

### comment:13 Changed 2 years ago by

Your proposed method `isomorphism_with_fixed_basis`

would require the target object to be specified, which means a specific implementation. The other option I see would be that it just requires the image to have some fixed basis, but I don't see how that would be different than a basis implementation of the generic free module. Basically, this feels like it requires a concrete implementation.

### comment:14 Changed 2 years ago by

Milestone: | sage-9.2 → sage-9.3 |
---|

### comment:15 Changed 22 months ago by

Milestone: | sage-9.3 → sage-9.4 |
---|

Setting new milestone based on a cursory review of ticket status, priority, and last modification date.

### comment:16 Changed 17 months ago by

Milestone: | sage-9.4 → sage-9.5 |
---|

### comment:17 Changed 12 months ago by

Milestone: | sage-9.5 → sage-9.6 |
---|

### comment:18 Changed 9 months ago by

Milestone: | sage-9.6 → sage-9.7 |
---|

### comment:19 Changed 3 months ago by

Milestone: | sage-9.7 → sage-9.8 |
---|

**Note:**See TracTickets for help on using tickets.

I am not sure I agree with having this category. I don't see the use case why we would need this category as there are basically only one concrete implementation: an n-dimensional free module. It is not until you start selecting and manipulating bases that you start having the possibility for different concrete implementations. At least, I see better ways of doing this rather than a new category that I don't foresee having much room to expand.