Skip to content

Commit 6903923

Browse files
author
Matthias Koeppe
committed
FiniteRankFreeModule_abstract.isomorphism_with_fixed_basis: Return a SetIsomorphism
1 parent 57af00f commit 6903923

File tree

1 file changed

+81
-28
lines changed

1 file changed

+81
-28
lines changed

src/sage/tensor/modules/finite_rank_free_module.py

Lines changed: 81 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,9 @@ class :class:`~sage.modules.free_module.FreeModule_generic`
539539
from typing import Generator, Optional
540540

541541
from sage.categories.fields import Fields
542+
from sage.categories.homset import Hom
542543
from sage.categories.modules import Modules
544+
from sage.categories.morphism import SetIsomorphism
543545
from sage.categories.rings import Rings
544546
from sage.misc.cachefunc import cached_method
545547
from sage.rings.integer import Integer
@@ -755,15 +757,15 @@ def isomorphism_with_fixed_basis(self, basis=None, codomain=None):
755757
- ``codomain`` -- (default: ``None``) the codomain of the
756758
isomorphism represented by a free module within the category
757759
:class:`~sage.categories.modules_with_basis.ModulesWithBasis` with
758-
the same rank and base ring as ``self``; if ``None`` a free module
760+
the same rank and base ring as ``self``; if ``None``, a free module
759761
represented by
760762
:class:`~sage.combinat.free_module.CombinatorialFreeModule` is
761763
constructed
762764
763765
OUTPUT:
764766
765-
- a module morphism represented by
766-
:class:`~sage.modules.with_basis.morphism.ModuleMorphismFromFunction`
767+
- a module isomorphism represented by
768+
:class:`~sage.categories.morphism.SetIsomorphism`
767769
768770
EXAMPLES::
769771
@@ -800,6 +802,12 @@ def isomorphism_with_fixed_basis(self, basis=None, codomain=None):
800802
To: Free module generated by {'a', 'b', 'c'} over Rational Field
801803
sage: phi_eW(e[1] + 2 * e[2])
802804
B['a'] + 2*B['b']
805+
sage: ~phi_eW
806+
Generic morphism:
807+
From: Free module generated by {'a', 'b', 'c'} over Rational Field
808+
To: 3-dimensional vector space over the Rational Field
809+
sage: (~phi_eW)(W.basis()['b']).display()
810+
e_2
803811
804812
Providing a :class:`~sage.modules.free_module.Module_free_ambient` as the codomain::
805813
@@ -814,44 +822,60 @@ def isomorphism_with_fixed_basis(self, basis=None, codomain=None):
814822
Sending (1,1)-tensors to matrices::
815823
816824
sage: T11 = V.tensor_module(1, 1); T11
817-
Free module of type-(1,1) tensors on the 3-dimensional vector space over the Rational Field
825+
Free module of type-(1,1) tensors on the
826+
3-dimensional vector space over the Rational Field
818827
sage: e_T11 = T11.basis("e"); e_T11
819828
Standard basis on the
820829
Free module of type-(1,1) tensors on the 3-dimensional vector space over the Rational Field
821830
induced by Basis (e_1,e_2,e_3) on the 3-dimensional vector space over the Rational Field
822831
sage: W = MatrixSpace(QQ, 3)
823832
sage: phi_e_T11 = T11.isomorphism_with_fixed_basis(e_T11, codomain=W); phi_e_T11
824833
Generic morphism:
825-
From: Free module of type-(1,1) tensors on the 3-dimensional vector space over the Rational Field
834+
From: Free module of type-(1,1) tensors on the
835+
3-dimensional vector space over the Rational Field
826836
To: Full MatrixSpace of 3 by 3 dense matrices over Rational Field
827837
sage: t = T11.an_element(); t.display()
828838
1/2 e_1⊗e^1
829839
sage: phi_e_T11(t)
830840
[1/2 0 0]
831841
[ 0 0 0]
832842
[ 0 0 0]
843+
sage: ~phi_e_T11
844+
Generic morphism:
845+
From: Full MatrixSpace of 3 by 3 dense matrices over Rational Field
846+
To: Free module of type-(1,1) tensors on the
847+
3-dimensional vector space over the Rational Field
848+
sage: (~phi_e_T11)(W([[0, 1/2, 1/3],
849+
....: [-1/2, 0, 0],
850+
....: [-1/3, 0, 0]])).display()
851+
1/2 e_1⊗e^2 + 1/3 e_1⊗e^3 - 1/2 e_2⊗e^1 - 1/3 e_3⊗e^1
833852
834853
Sending symmetric bilinear forms to matrices (note that they are currently elements
835854
of `T^{(0,2)}(M)`, not the symmetric power of `M`)::
836855
837856
sage: T02 = V.tensor_module(0, 2); T02
838-
Free module of type-(0,2) tensors on the 3-dimensional vector space over the Rational Field
857+
Free module of type-(0,2) tensors on the
858+
3-dimensional vector space over the Rational Field
839859
sage: e_T02 = T02.basis("e"); e_T02
840860
Standard basis on the
841-
Free module of type-(0,2) tensors on the 3-dimensional vector space over the Rational Field
842-
induced by Basis (e_1,e_2,e_3) on the 3-dimensional vector space over the Rational Field
861+
Free module of type-(0,2) tensors on the
862+
3-dimensional vector space over the Rational Field
863+
induced by Basis (e_1,e_2,e_3) on the
864+
3-dimensional vector space over the Rational Field
843865
sage: W = MatrixSpace(QQ, 3)
844866
sage: phi_e_T02 = T02.isomorphism_with_fixed_basis(e_T02, codomain=W); phi_e_T02
845867
Generic morphism:
846-
From: Free module of type-(0,2) tensors on the 3-dimensional vector space over the Rational Field
868+
From: Free module of type-(0,2) tensors on the
869+
3-dimensional vector space over the Rational Field
847870
To: Full MatrixSpace of 3 by 3 dense matrices over Rational Field
848871
849872
sage: a = V.sym_bilinear_form()
850873
sage: a[1,1], a[1,2], a[1,3] = 1, 2, 3
851874
sage: a[2,2], a[2,3] = 4, 5
852875
sage: a[3,3] = 6
853876
sage: a.display()
854-
e^1⊗e^1 + 2 e^1⊗e^2 + 3 e^1⊗e^3 + 2 e^2⊗e^1 + 4 e^2⊗e^2 + 5 e^2⊗e^3 + 3 e^3⊗e^1 + 5 e^3⊗e^2 + 6 e^3⊗e^3
877+
e^1⊗e^1 + 2 e^1⊗e^2 + 3 e^1⊗e^3 + 2 e^2⊗e^1 + 4 e^2⊗e^2 + 5 e^2⊗e^3
878+
+ 3 e^3⊗e^1 + 5 e^3⊗e^2 + 6 e^3⊗e^3
855879
sage: phi_e_T02(a)
856880
[1 2 3]
857881
[2 4 5]
@@ -860,15 +884,18 @@ def isomorphism_with_fixed_basis(self, basis=None, codomain=None):
860884
Same but explicitly in the subspace of symmetric bilinear forms::
861885
862886
sage: Sym2Vdual = V.dual_symmetric_power(2); Sym2Vdual
863-
Free module of fully symmetric type-(0,2) tensors on the 3-dimensional vector space over the Rational Field
887+
Free module of fully symmetric type-(0,2) tensors on the
888+
3-dimensional vector space over the Rational Field
864889
sage: Sym2Vdual.is_submodule(T02)
865890
True
866891
sage: Sym2Vdual.rank()
867892
6
868893
sage: e_Sym2Vdual = Sym2Vdual.basis("e"); e_Sym2Vdual
869894
Standard basis on the
870-
Free module of fully symmetric type-(0,2) tensors on the 3-dimensional vector space over the Rational Field
871-
induced by Basis (e_1,e_2,e_3) on the 3-dimensional vector space over the Rational Field
895+
Free module of fully symmetric type-(0,2) tensors on the
896+
3-dimensional vector space over the Rational Field
897+
induced by Basis (e_1,e_2,e_3) on the
898+
3-dimensional vector space over the Rational Field
872899
sage: W_basis = [phi_e_T02(b) for b in e_Sym2Vdual]; W_basis
873900
[
874901
[1 0 0] [0 1 0] [0 0 1] [0 0 0] [0 0 0] [0 0 0]
@@ -877,25 +904,34 @@ def isomorphism_with_fixed_basis(self, basis=None, codomain=None):
877904
]
878905
sage: W = MatrixSpace(QQ, 3).submodule(W_basis); W
879906
Free module generated by {0, 1, 2, 3, 4, 5} over Rational Field
880-
sage: phi_e_Sym2Vdual = Sym2Vdual.isomorphism_with_fixed_basis(e_Sym2Vdual, codomain=W); phi_e_Sym2Vdual
907+
sage: phi_e_Sym2Vdual = Sym2Vdual.isomorphism_with_fixed_basis(e_Sym2Vdual,
908+
....: codomain=W)
909+
sage: phi_e_Sym2Vdual
881910
Generic morphism:
882-
From: Free module of fully symmetric type-(0,2) tensors on the 3-dimensional vector space over the Rational Field
911+
From: Free module of fully symmetric type-(0,2) tensors on the
912+
3-dimensional vector space over the Rational Field
883913
To: Free module generated by {0, 1, 2, 3, 4, 5} over Rational Field
884914
885915
Sending tensors to elements of the tensor square of :class:`CombinatorialFreeModule`::
886916
887917
sage: T20 = V.tensor_module(2, 0); T20
888-
Free module of type-(2,0) tensors on the 3-dimensional vector space over the Rational Field
918+
Free module of type-(2,0) tensors on the
919+
3-dimensional vector space over the Rational Field
889920
sage: e_T20 = T02.basis("e"); e_T20
890921
Standard basis on the
891-
Free module of type-(0,2) tensors on the 3-dimensional vector space over the Rational Field
892-
induced by Basis (e_1,e_2,e_3) on the 3-dimensional vector space over the Rational Field
922+
Free module of type-(0,2) tensors on the
923+
3-dimensional vector space over the Rational Field
924+
induced by Basis (e_1,e_2,e_3) on the
925+
3-dimensional vector space over the Rational Field
893926
sage: W = CombinatorialFreeModule(QQ, [1, 2, 3]).tensor_square(); W
894-
Free module generated by {1, 2, 3} over Rational Field # Free module generated by {1, 2, 3} over Rational Field
927+
Free module generated by {1, 2, 3} over Rational Field
928+
# Free module generated by {1, 2, 3} over Rational Field
895929
sage: phi_e_T20 = T20.isomorphism_with_fixed_basis(e_T20, codomain=W); phi_e_T20
896930
Generic morphism:
897-
From: Free module of type-(2,0) tensors on the 3-dimensional vector space over the Rational Field
898-
To: Free module generated by {1, 2, 3} over Rational Field # Free module generated by {1, 2, 3} over Rational Field
931+
From: Free module of type-(2,0) tensors on the
932+
3-dimensional vector space over the Rational Field
933+
To: Free module generated by {1, 2, 3} over Rational Field
934+
# Free module generated by {1, 2, 3} over Rational Field
899935
sage: t = T20.an_element(); t.display()
900936
1/2 e_1⊗e_1
901937
sage: phi_e_T20(t)
@@ -940,13 +976,17 @@ def isomorphism_with_fixed_basis(self, basis=None, codomain=None):
940976

941977
codomain_basis = Family(codomain.basis())
942978
if isinstance(codomain_basis, TrivialFamily):
943-
# assume that codomain basis keys are to be ignored
944-
key_pairs = enumerate(basis.keys())
979+
# assume that codomain basis keys are to be ignored;
980+
# need them several times, can't keep as generators
981+
key_pairs = tuple(enumerate(basis.keys()))
982+
basis_by_codomain_key = basis
945983
else:
946984
# assume that the keys of the codomain should be used
947-
key_pairs = zip(codomain_basis.keys(), basis.keys())
948-
# Need them several times, can't keep as generators
949-
key_pairs = tuple(key_pairs)
985+
# need them several times, can't keep as generators
986+
key_pairs = tuple(zip(codomain_basis.keys(), basis.keys()))
987+
basis_by_codomain_key = {}
988+
for codomain_key, domain_key in key_pairs:
989+
basis_by_codomain_key[codomain_key] = basis[domain_key]
950990

951991
def _isomorphism(x):
952992
r"""
@@ -955,7 +995,21 @@ def _isomorphism(x):
955995
return codomain.sum(x[basis, domain_key] * codomain_basis[codomain_key]
956996
for codomain_key, domain_key in key_pairs)
957997

958-
return self.module_morphism(function=_isomorphism, codomain=codomain)
998+
def _inverse(y):
999+
r"""
1000+
Concrete isomorphism from ``codomain`` to ``self``.
1001+
"""
1002+
return self.linear_combination(
1003+
(basis_by_codomain_key[codomain_key], coefficient)
1004+
for codomain_key, coefficient in y.monomial_coefficients().items())
1005+
1006+
category = Modules(self.base_ring())
1007+
homset = Hom(self, codomain, category)
1008+
isomorphism = SetIsomorphism(homset, _isomorphism)
1009+
inverse = SetIsomorphism(homset.reversed(), _inverse)
1010+
isomorphism._set_inverse(inverse)
1011+
inverse._set_inverse(isomorphism)
1012+
return isomorphism
9591013

9601014
def _test_isomorphism_with_fixed_basis(self, **options):
9611015
r"""
@@ -3160,7 +3214,6 @@ def hom(self, codomain, matrix_rep, bases=None, name=None,
31603214
for more documentation.
31613215
31623216
"""
3163-
from sage.categories.homset import Hom
31643217
homset = Hom(self, codomain)
31653218
return homset(matrix_rep, bases=bases, name=name,
31663219
latex_name=latex_name)

0 commit comments

Comments
 (0)