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

Commit 08d6a65

Browse files
author
Matthias Koeppe
committed
Merge #30229
2 parents a7c79de + fc66ad1 commit 08d6a65

File tree

3 files changed

+21
-113
lines changed

3 files changed

+21
-113
lines changed

src/sage/tensor/modules/ext_pow_free_module.py

Lines changed: 3 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -572,21 +572,12 @@ class ExtPowerDualFreeModule(FiniteRankFreeModule_abstract):
572572
sage: latex(M.dual())
573573
M^*
574574
575-
Since any tensor of type (0,1) is a linear form, there is a coercion map
576-
from the set `T^{(0,1)}(M)` of such tensors to `M^*`::
575+
It also coincides with the module of type-`(0,1)` tensors::
577576
578-
sage: T01 = M.tensor_module(0,1) ; T01
579-
Free module of type-(0,1) tensors on the Rank-3 free module M over the
580-
Integer Ring
581-
sage: M.dual().has_coerce_map_from(T01)
582-
True
583-
584-
There is also a coercion map in the reverse direction::
585-
586-
sage: T01.has_coerce_map_from(M.dual())
577+
sage: M.dual_exterior_power(1) is M.tensor_module(0,1)
587578
True
588579
589-
For a degree `p\geq 2`, the coercion holds only in the direction
580+
For a degree `p\geq 2`, there is a coercion map
590581
`\Lambda^p(M^*)\rightarrow T^{(0,p)}(M)`::
591582
592583
sage: T02 = M.tensor_module(0,2) ; T02
@@ -597,24 +588,6 @@ class ExtPowerDualFreeModule(FiniteRankFreeModule_abstract):
597588
sage: A.has_coerce_map_from(T02)
598589
False
599590
600-
The coercion map `T^{(0,1)}(M) \rightarrow M^*` in action::
601-
602-
sage: b = T01([-2,1,4], basis=e, name='b') ; b
603-
Type-(0,1) tensor b on the Rank-3 free module M over the Integer Ring
604-
sage: b.display(e)
605-
b = -2 e^0 + e^1 + 4 e^2
606-
sage: lb = M.dual()(b) ; lb
607-
Linear form b on the Rank-3 free module M over the Integer Ring
608-
sage: lb.display(e)
609-
b = -2 e^0 + e^1 + 4 e^2
610-
611-
The coercion map `M^* \rightarrow T^{(0,1)}(M)` in action::
612-
613-
sage: tlb = T01(lb) ; tlb
614-
Type-(0,1) tensor b on the Rank-3 free module M over the Integer Ring
615-
sage: tlb == b
616-
True
617-
618591
The coercion map `\Lambda^2(M^*)\rightarrow T^{(0,2)}(M)` in action::
619592
620593
sage: ta = T02(a) ; ta
@@ -782,47 +755,6 @@ def _an_element_(self):
782755
resu.set_comp()[ind] = self._fmodule._ring.an_element()
783756
return resu
784757

785-
def _coerce_map_from_(self, other):
786-
r"""
787-
Determine whether coercion to ``self`` exists from other parent.
788-
789-
EXAMPLES:
790-
791-
Sets of type-`(0,1)` tensors coerce to ``self`` if the degree is 1::
792-
793-
sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
794-
sage: L1 = M.dual_exterior_power(1) ; L1
795-
Dual of the Rank-3 free module M over the Integer Ring
796-
sage: T01 = M.tensor_module(0,1) ; T01
797-
Free module of type-(0,1) tensors on the Rank-3 free module M over
798-
the Integer Ring
799-
sage: L1._coerce_map_from_(T01)
800-
True
801-
802-
Of course, coercions from other tensor types are meaningless::
803-
804-
sage: L1._coerce_map_from_(M.tensor_module(1,0))
805-
False
806-
sage: L1._coerce_map_from_(M.tensor_module(0,2))
807-
False
808-
809-
If the degree is larger than 1, there is no coercion::
810-
811-
sage: L2 = M.dual_exterior_power(2) ; L2
812-
2nd exterior power of the dual of the Rank-3 free module M over
813-
the Integer Ring
814-
sage: L2._coerce_map_from_(M.tensor_module(0,2))
815-
False
816-
817-
"""
818-
from sage.tensor.modules.tensor_free_module import TensorFreeModule
819-
if isinstance(other, TensorFreeModule):
820-
# coercion of a type-(0,1) tensor to a linear form
821-
if self._fmodule is other._fmodule and self._degree == 1 and \
822-
other.tensor_type() == (0,1):
823-
return True
824-
return False
825-
826758
#### End of parent methods
827759

828760
@cached_method

src/sage/tensor/modules/finite_rank_free_module.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -676,10 +676,12 @@ def tensor_product(self, *others):
676676
raise NotImplementedError('all factors must be tensor modules over the same base module')
677677
factors = [self] + list(others)
678678
result_tensor_type = sum(vector(factor.tensor_type()) for factor in factors)
679-
index_maps = []
680-
running_indices = vector([0, result_tensor_type[0]])
681679
result_sym = []
682680
result_antisym = []
681+
# Keep track of reordering of the contravariant and covariant indices
682+
# (compatible with FreeModuleTensor.__mul__)
683+
index_maps = []
684+
running_indices = vector([0, result_tensor_type[0]])
683685
for factor in factors:
684686
tensor_type = factor.tensor_type()
685687
index_map = tuple(i + running_indices[0] for i in range(tensor_type[0]))
@@ -1543,11 +1545,16 @@ def tensor_module(self, k, l, *, sym=None, antisym=None):
15431545
sage: M.tensor_module(1,2) is T
15441546
True
15451547
1546-
The base module is itself the module of all type-`(1,0)` tensors::
1548+
The module of type-`(1,0)` tensors is the base module itself::
15471549
15481550
sage: M.tensor_module(1,0) is M
15491551
True
15501552
1553+
while the module of type-`(0,1)` tensors is the dual of the base module::
1554+
1555+
sage: M.tensor_module(0, 1) is M.dual()
1556+
True
1557+
15511558
By using the arguments ``sym`` and ``antisym``, submodules of a full tensor
15521559
module can be constructed::
15531560
@@ -1582,6 +1589,8 @@ def tensor_module(self, k, l, *, sym=None, antisym=None):
15821589
except KeyError:
15831590
if key == (1, 0):
15841591
T = self
1592+
elif key == (0, 1):
1593+
T = self.dual()
15851594
elif sym or antisym:
15861595
from sage.tensor.modules.tensor_free_submodule import TensorFreeSubmodule_sym
15871596
T = TensorFreeSubmodule_sym(self, (k, l), sym=sym, antisym=antisym)
@@ -1638,8 +1647,8 @@ def dual_symmetric_power(self, p):
16381647
sage: e = M.basis('e')
16391648
sage: M.dual_symmetric_power(0)
16401649
Free module of type-(0,0) tensors on the Rank-3 free module M over the Integer Ring
1641-
sage: M.dual_symmetric_power(1) # return the module itself
1642-
Free module of type-(0,1) tensors on the Rank-3 free module M over the Integer Ring
1650+
sage: M.dual_symmetric_power(1) # return the dual module
1651+
Dual of the Rank-3 free module M over the Integer Ring
16431652
sage: M.dual_symmetric_power(2)
16441653
Free module of fully symmetric type-(0,2) tensors
16451654
on the Rank-3 free module M over the Integer Ring

src/sage/tensor/modules/tensor_free_module.py

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -238,39 +238,11 @@ class TensorFreeModule(FiniteRankFreeModule_abstract):
238238
sage: ta.symmetries() # the antisymmetry is of course preserved
239239
no symmetry; antisymmetry: (0, 1)
240240
241-
For the degree `p=1`, there is a coercion in both directions::
241+
For the degree `p=1`, we have the identity `\Lambda^1(M^*) = T^{(0,1)}(M) = M^*`::
242242
243-
sage: L1 = M.dual_exterior_power(1) ; L1
244-
Dual of the Rank-3 free module M over the Integer Ring
245-
sage: T01 = M.tensor_module(0,1) ; T01
246-
Free module of type-(0,1) tensors on the Rank-3 free module M over the
247-
Integer Ring
248-
sage: T01.has_coerce_map_from(L1)
249-
True
250-
sage: L1.has_coerce_map_from(T01)
243+
sage: M.dual_exterior_power(1) is M.tensor_module(0,1)
251244
True
252-
253-
The coercion map `\Lambda^1(M^*)\rightarrow T^{(0,1)}(M)` in action::
254-
255-
sage: a = M.linear_form('a')
256-
sage: a[:] = -2, 4, 1 ; a.display(e)
257-
a = -2 e^0 + 4 e^1 + e^2
258-
sage: a.parent() is L1
259-
True
260-
sage: ta = T01(a) ; ta
261-
Type-(0,1) tensor a on the Rank-3 free module M over the Integer Ring
262-
sage: ta.display(e)
263-
a = -2 e^0 + 4 e^1 + e^2
264-
265-
The coercion map `T^{(0,1)}(M) \rightarrow \Lambda^1(M^*)` in action::
266-
267-
sage: ta.parent() is T01
268-
True
269-
sage: lta = L1(ta) ; lta
270-
Linear form a on the Rank-3 free module M over the Integer Ring
271-
sage: lta.display(e)
272-
a = -2 e^0 + 4 e^1 + e^2
273-
sage: lta == a
245+
sage: M.tensor_module(0,1) is M.dual()
274246
True
275247
276248
There is a canonical identification between tensors of type `(1,1)` and
@@ -597,7 +569,7 @@ def _coerce_map_from_(self, other):
597569
598570
but not to tensor modules of other types::
599571
600-
sage: M.tensor_module(0,1)._coerce_map_from_(End(M))
572+
sage: M.tensor_module(0,2)._coerce_map_from_(End(M))
601573
False
602574
603575
and not to type-`(1,1)` tensor modules defined on another free module::
@@ -623,8 +595,6 @@ def _coerce_map_from_(self, other):
623595
624596
Coercion from alternating forms::
625597
626-
sage: M.tensor_module(0,1)._coerce_map_from_(M.dual_exterior_power(1))
627-
True
628598
sage: M.tensor_module(0,2)._coerce_map_from_(M.dual_exterior_power(2))
629599
True
630600
sage: M.tensor_module(0,2)._coerce_map_from_(M.dual_exterior_power(3))
@@ -682,9 +652,6 @@ def _repr_(self):
682652
sage: M.tensor_module(1,1)
683653
Free module of type-(1,1) tensors on the 2-dimensional vector space
684654
M over the Rational Field
685-
sage: M.tensor_module(0,1)
686-
Free module of type-(0,1) tensors on the 2-dimensional vector space
687-
M over the Rational Field
688655
689656
"""
690657
description = "Free module of type-({},{}) tensors on the {}".format(

0 commit comments

Comments
 (0)