Open mkoeppe opened 4 years ago
Branch pushed to git repo; I updated commit sha1. New commits:
c90acc6 | src/sage/modules/filtered_vector_space.py (FilteredVectorSpace_class.tensor_product): Check whether other is a filtered vector space |
Here's an attempt
Author: Matthais Koeppe
Changed author from Matthais Koeppe to Matthias Koeppe
Branch pushed to git repo; I updated commit sha1. New commits:
b98c5df | ModulesWithBasis.tensor_product: Fall back to trying to use the construction of the factors |
Branch pushed to git repo; I updated commit sha1. New commits:
ed6a13f | src/sage/categories/modules_with_basis.py: Update doctests |
I don’t like this fallback for two reasons:
FilteredVectorSpace.tensor_product
I gave in comment:40, it doesn’t know how it was built as a tensor product.Replying to Travis Scrimshaw:
I don’t like this fallback for two reasons:
- It runs into the same problem with
FilteredVectorSpace.tensor_product
I gave in comment:40, it doesn’t know how it was built as a tensor product.
The result doesn't have to know because it does not advertise itself as a tensor product.
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
I don’t like this fallback for two reasons:
- It runs into the same problem with
FilteredVectorSpace.tensor_product
I gave in comment:40, it doesn’t know how it was built as a tensor product.The result doesn't have to know because it does not advertise itself as a tensor product.
That is the problem. If I build an object as a tensor product (via the tensor
functor), then it should know that because I wanted it to know that explicitly. It should advertise itself as a tensor product.
Let me put it another way, the result is not in the codomain of the functor.
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
I don’t like this fallback for two reasons:
- It runs into the same problem with
FilteredVectorSpace.tensor_product
I gave in comment:40, it doesn’t know how it was built as a tensor product.The result doesn't have to know because it does not advertise itself as a tensor product.
That is the problem. If I build an object as a tensor product (via the
tensor
functor), then it should know that because I wanted it to know that explicitly. It should advertise itself as a tensor product.
Suppose as a user I want to construct it anyway. What should I do then?
Replying to Travis Scrimshaw:
Let me put it another way, the result is not in the codomain of the functor.
I think you're conflating mathematical structure with implementation here.
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
I don’t like this fallback for two reasons:
- It runs into the same problem with
FilteredVectorSpace.tensor_product
I gave in comment:40, it doesn’t know how it was built as a tensor product.The result doesn't have to know because it does not advertise itself as a tensor product.
That is the problem. If I build an object as a tensor product (via the
tensor
functor), then it should know that because I wanted it to know that explicitly. It should advertise itself as a tensor product.Suppose as a user I want to construct it anyway. What should I do then?
The class needs to have its own hook separate from the hook that the functor uses.
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
Let me put it another way, the result is not in the codomain of the functor.
I think you're conflating mathematical structure with implementation here.
How so? The result does not know it is a tensor product of modules, and there is no canonical way to deconstruct a vector space into a tensor product. For example, a 1-dimensional module could be a n
-fold tensor product of itself n
times. There are no canonical isomorphisms between these spaces. These are also not even isomorphic as graded vector spaces in general either (one needs a grading shift).
Mathematically an object is a tensor product if there exists a construction of it using the tensor functor.
In an implementation, we generally cannot know if something exists. An object is marked as a tensor product when the implementation has marked it as such. Like everything, this is subject to the implementation restrictions.
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
I don’t like this fallback for two reasons:
- It runs into the same problem with
FilteredVectorSpace.tensor_product
I gave in comment:40, it doesn’t know how it was built as a tensor product.The result doesn't have to know because it does not advertise itself as a tensor product.
That is the problem. If I build an object as a tensor product (via the
tensor
functor), then it should know that because I wanted it to know that explicitly. It should advertise itself as a tensor product.Suppose as a user I want to construct it anyway. What should I do then?
The class needs to have its own hook separate from the hook that the functor uses.
No, as a user. Suppose there is no such specific implementation. What should the user do?
Replying to Matthias Köppe:
Mathematically an object is a tensor product if there exists a construction of it using the tensor functor.
Then every object is a tensor product since we can always tensor with a 1-dimensional module. If we wanted to talk in that level of generality, there is no category of tensor products, Cartesean products, etc.
In an implementation, we generally cannot know if something exists. An object is marked as a tensor product when the implementation has marked it as such. Like everything, this is subject to the implementation restrictions.
Indeed, the category also contains some implementation requirements. (I would argue the tensor products category is the category with a distinguished tensor product construction, parallel to ModulesWithBasis
.) Consequently, the result of the functor is promising certain implementation details with its codomain: such objects have methods via the category’s ParentMethods
and provide an implementation of the corresponding @abstract_methods
.
More concretely, if I had code that does:
T = tensor([V,W])
for F in T.tensor_factors():
print(F)
This should work whenever T
is constructed because the codomain is Cat.TensorProducts()
, where Cat
is the meet of the categories of V
and W
. However, with changing the name, the functor now would work but the code would fail with FilteredVectorSpace
s.
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
I don’t like this fallback for two reasons:
- It runs into the same problem with
FilteredVectorSpace.tensor_product
I gave in comment:40, it doesn’t know how it was built as a tensor product.The result doesn't have to know because it does not advertise itself as a tensor product.
That is the problem. If I build an object as a tensor product (via the
tensor
functor), then it should know that because I wanted it to know that explicitly. It should advertise itself as a tensor product.Suppose as a user I want to construct it anyway. What should I do then?
The class needs to have its own hook separate from the hook that the functor uses.
No, as a user. Suppose there is no such specific implementation. What should the user do?
My guess is stop wishing for magical coding fairies and implement it. There is no generic way to give a tensor product the structure of a specific type of module. This essentially amounts to saying there is a canonical isomorphism between, e.g., R2 (x) R3 = R6. (Another version: How do you build a matrix from a tensor product of two matrices? There are two main ways to do this that are equivalent as they amount to choosing a different order of the isomorphism.) If a class Foo
wants to know that a tensor product of two of itself can again be realized as an object Foo
, then it needs to implement that and chose a specific isomorphism.
Replying to Travis Scrimshaw:
the result of the functor is promising certain implementation details with its codomain: such objects have methods via the category’s
ParentMethods
and provide an implementation of the corresponding@abstract_methods
.
No, I think this is too strict to be useful.
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
No, as a user. Suppose there is no such specific implementation. What should the user do?
My guess is stop wishing for magical coding fairies and implement it.
No, no, users wouldn't like to be talked to like that.
We often want to identify 1-fold tensor products with the base module -- and the base module won't have the tensor_factors
method. For example, this is what sage.tensor.modules
and sage.manifolds.differentiable
do.
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
the result of the functor is promising certain implementation details with its codomain: such objects have methods via the category’s
ParentMethods
and provide an implementation of the corresponding@abstract_methods
.No, I think this is too strict to be useful.
That an object in the codomain of a functor (or any morphism) must support what is required by that codomain (and should be an object such that X in Cat
returns True
)? I find this to actually be quite useful as I can expect certain properties to be there.
Consider the equivalent scenario: I have a function f: ZZ -> QQ[‘s’]
that returned 0
as an integer and all non-zero elements as polynomials. You now have to write special checks for 0
rather than have it behave uniformly.
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
the result of the functor is promising certain implementation details with its codomain: such objects have methods via the category’s
ParentMethods
and provide an implementation of the corresponding@abstract_methods
.No, I think this is too strict to be useful.
That an object in the codomain of a functor (or any morphism) must support what is required by that codomain (and should be an object such that
X in Cat
returnsTrue
)? I find this to actually be quite useful as I can expect certain properties to be there.
There's always a tradeoff. Identifications such as the ones that I mentioned in comment:74 are also quite useful.
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
No, as a user. Suppose there is no such specific implementation. What should the user do?
My guess is stop wishing for magical coding fairies and implement it.
No, no, users wouldn't like to be talked to like that.
Of course I wouldn’t necessarily tell them in that way. However, unless somebody actually writes the code, then it doesn’t magically come into existence. Unfortunately, this is not the Dire Straights song “Money for Nothing”; Also Hell is full of 10 year olds who wished for exactly the same thing with the holophonor.
In this case, I believe it is impossible to implement in the level of generality you want because it amounts to making a canonical choice where there is not one.
Replying to Travis Scrimshaw:
There is no generic way to give a tensor product the structure of a specific type of module. This essentially amounts to saying there is a canonical isomorphism between, e.g., R2 (x) R3 = R6.
It does not have to be canonical to be useful. And in fact one wouldn't construct that but rather construct a free module whose basis is indexed by the cartesian product of the input index sets.
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
the result of the functor is promising certain implementation details with its codomain: such objects have methods via the category’s
ParentMethods
and provide an implementation of the corresponding@abstract_methods
.No, I think this is too strict to be useful.
That an object in the codomain of a functor (or any morphism) must support what is required by that codomain (and should be an object such that
X in Cat
returnsTrue
)? I find this to actually be quite useful as I can expect certain properties to be there.There's always a tradeoff. Identifications such as the ones that I mentioned in comment:74 are also quite useful.
I agree that they are useful, but you need a canonical way to do it in general. The point is that you are making an identification based upon a specific choice of isomorphism. Individual classes are allowed to make that choice, which you are implicitly doing when you have either a as_foo()
method or Foo(T)
in your code.
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
There is no generic way to give a tensor product the structure of a specific type of module. This essentially amounts to saying there is a canonical isomorphism between, e.g., R2 (x) R3 = R6.
It does not have to be canonical to be useful. And in fact one wouldn't construct that but rather construct a free module whose basis is indexed by the cartesian product of the input index sets.
But that is doing what is mandated by the category. It is holding onto the knowledge of how it is constructed. What you are asking for is something to return the equivalent of R6.
I think in comment:79 you replied to the wrong comment.
Replying to Matthias Köppe:
I think in comment:79 you replied to the wrong comment.
It applies to both comment:76 and comment:74. I just chose the more recent one.
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
There is no generic way to give a tensor product the structure of a specific type of module. This essentially amounts to saying there is a canonical isomorphism between, e.g., R2 (x) R3 = R6.
It does not have to be canonical to be useful. And in fact one wouldn't construct that but rather construct a free module whose basis is indexed by the cartesian product of the input index sets.
But that is doing what is mandated by the category. It is holding onto the knowledge of how it is constructed. What you are asking for is something to return the equivalent of R6.
No, I don't think this resembles anything what I'm asking for. I think we've lost the context somewhere on the way here.
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
I think in comment:79 you replied to the wrong comment.
It applies to both comment:76 and comment:74. I just chose the more recent one.
Wait, you are concerned about the identification of a module M with its 1-fold tensor product not being canonical?
For the question of 1-fold tensor products, there's by the way an old ticket: #18349
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
There is no generic way to give a tensor product the structure of a specific type of module. This essentially amounts to saying there is a canonical isomorphism between, e.g., R2 (x) R3 = R6.
It does not have to be canonical to be useful. And in fact one wouldn't construct that but rather construct a free module whose basis is indexed by the cartesian product of the input index sets.
But that is doing what is mandated by the category. It is holding onto the knowledge of how it is constructed. What you are asking for is something to return the equivalent of R6.
No, I don't think this resembles anything what I'm asking for. I think we've lost the context somewhere on the way here.
Sorry, that was a bad phrasing on my part. You are asking for returning R6 to be okay, which you have had to make a (non-canonical) choice of a isomorphism that they user has no control over. The tensor product category has a special distinguished choice of construction as a tensor product, analogous to ModulesWithBasis
being modules with a distinguished choice of a basis.
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
I think in comment:79 you replied to the wrong comment.
It applies to both comment:76 and comment:74. I just chose the more recent one.
Wait, you are concerned about the identification of a module M with its 1-fold tensor product not being canonical?
Not specifically for the 1-fold tensor products, but more generally. This code is expected to work for arbitrary tensor products with no special cases, right? (I can also tell you about the troubles I’ve had with PartitionTuples
of length 1 versus Partitions
, which motivates my desire for uniformity.)
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
There is no generic way to give a tensor product the structure of a specific type of module. This essentially amounts to saying there is a canonical isomorphism between, e.g., R2 (x) R3 = R6.
It does not have to be canonical to be useful. And in fact one wouldn't construct that but rather construct a free module whose basis is indexed by the cartesian product of the input index sets.
But that is doing what is mandated by the category. It is holding onto the knowledge of how it is constructed. What you are asking for is something to return the equivalent of R6.
No, I don't think this resembles anything what I'm asking for. I think we've lost the context somewhere on the way here.
Sorry, that was a bad phrasing on my part. You are asking for returning R6 to be okay
No
Replying to Travis Scrimshaw:
Unfortunately, this is not the Dire Straights song “Money for Nothing”
I do appreciate the attempt to engage in intergenerational dialogue
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
There is no generic way to give a tensor product the structure of a specific type of module. This essentially amounts to saying there is a canonical isomorphism between, e.g., R2 (x) R3 = R6.
It does not have to be canonical to be useful. And in fact one wouldn't construct that but rather construct a free module whose basis is indexed by the cartesian product of the input index sets.
But that is doing what is mandated by the category. It is holding onto the knowledge of how it is constructed. What you are asking for is something to return the equivalent of R6.
No, I don't think this resembles anything what I'm asking for. I think we've lost the context somewhere on the way here.
Sorry, that was a bad phrasing on my part. You are asking for returning R6 to be okay
No
Then if you rename the functor hook to tensor_product
, then FilteredVectorSpace
's method of that name would have a bug.
Replying to Matthias Köppe:
Replying to Travis Scrimshaw:
Unfortunately, this is not the Dire Straights song “Money for Nothing”
I do appreciate the attempt to engage in intergenerational dialogue
Actually, that is music I like. ;)
Or should I say I appreciate that there's "No One Like You" that I appreciate to have these discussions with.
Description changed:
---
+++
@@ -62,8 +62,7 @@
Tickets:
- #31276 Tensor Product Method for `FiniteRankFreeModule`
-
-Follow-up:
- #34448 Put tensor modules of `FiniteRankFreeModule` in `Modules().TensorProducts()`
+- #34589 `VectorFieldModule`, `TensorFieldModule`, `DiffFormModule`: Add methods `tensor_product`, `tensor_power`, update category of `TensorFieldModule`
See also: #18349
We unify the use of the methods
tensor
vs.tensor_product
in parent classes.Current situation:
Category
ModulesWithBasis
provides a parent methodtensor
to construct a tensor product of modules.It is not implemented completely for
FreeModule
In contrast,
FiniteRankFreeModule
(which is not inModulesWithBasis
) uses a parent methodtensor
to construct elements.FilteredVectorSpace
has bothtensor
(fromModulesWithBasis
) andtensor_product
, but only the latter works.The same is true for
FreeQuadraticModule_integer_symmetric
:The proposed solution in this ticket is to standardize on the method
tensor_product
, makingtensor
a deprecated alias.Modules
already has atensor_square
method, whichtensor_product
complements well.We also add
tensor_power
.No changes are made to the global
tensor
(unique instance ofTensorProductFunctor
).Tickets:
31276 Tensor Product Method for
FiniteRankFreeModule
34448 Put tensor modules of
FiniteRankFreeModule
inModules().TensorProducts()
34589
VectorFieldModule
,TensorFieldModule
,DiffFormModule
: Add methodstensor_product
,tensor_power
, update category ofTensorFieldModule
See also: #18349
CC: @tscrim @egourgoulhon @mjungmath @jhpalmieri @fchapoton
Component: linear algebra
Author: Matthias Koeppe
Branch/Commit: u/mkoeppe/parent_methods_tensor_vs__tensor_product @
ed6a13f
Issue created by migration from https://trac.sagemath.org/ticket/30373