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

Commit

Permalink
FiniteRankFreeModule_abstract.isomorphism_with_fixed_basis: Move here…
Browse files Browse the repository at this point in the history
… from FiniteRankFreeModule, rewrite using Family
  • Loading branch information
Matthias Koeppe committed Aug 27, 2022
1 parent 544ffab commit a4d65bc
Showing 1 changed file with 124 additions and 117 deletions.
241 changes: 124 additions & 117 deletions src/sage/tensor/modules/finite_rank_free_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,7 @@ class :class:`~sage.modules.free_module.FreeModule_generic`
from sage.categories.rings import Rings
from sage.misc.cachefunc import cached_method
from sage.rings.integer import Integer
from sage.sets.family import Family, TrivialFamily
from sage.structure.parent import Parent
from sage.structure.unique_representation import UniqueRepresentation
from sage.tensor.modules.free_module_element import FiniteRankFreeModuleElement
Expand Down Expand Up @@ -729,6 +730,129 @@ def is_submodule(self, other):
"""
return self == other or self.ambient_module() == other

def isomorphism_with_fixed_basis(self, basis=None, codomain=None):
r"""
Construct the canonical isomorphism from the free module ``self``
to a free module in which ``basis`` of ``self`` is mapped to the
distinguished basis of ``codomain``.
INPUT:
- ``basis`` -- (default: ``None``) the basis of ``self`` which
should be mapped to the distinguished basis on ``codomain``;
if ``None``, the default basis is assumed.
- ``codomain`` -- (default: ``None``) the codomain of the
isomorphism represented by a free module within the category
:class:`~sage.categories.modules_with_basis.ModulesWithBasis` with
the same rank and base ring as ``self``; if ``None`` a free module
represented by
:class:`~sage.combinat.free_module.CombinatorialFreeModule` is
constructed
OUTPUT:
- a module morphism represented by
:class:`~sage.modules.with_basis.morphism.ModuleMorphismFromFunction`
EXAMPLES::
sage: V = FiniteRankFreeModule(QQ, 3, start_index=1); V
3-dimensional vector space over the Rational Field
sage: basis = e = V.basis("e"); basis
Basis (e_1,e_2,e_3) on the 3-dimensional vector space over the
Rational Field
sage: phi_e = V.isomorphism_with_fixed_basis(basis); phi_e
Generic morphism:
From: 3-dimensional vector space over the Rational Field
To: Free module generated by {1, 2, 3} over Rational Field
sage: phi_e.codomain().category()
Category of finite dimensional vector spaces with basis over
Rational Field
sage: phi_e(e[1] + 2 * e[2])
e[1] + 2*e[2]
sage: abc = V.basis(['a', 'b', 'c'], symbol_dual=['d', 'e', 'f']); abc
Basis (a,b,c) on the 3-dimensional vector space over the Rational Field
sage: phi_abc = V.isomorphism_with_fixed_basis(abc); phi_abc
Generic morphism:
From: 3-dimensional vector space over the Rational Field
To: Free module generated by {1, 2, 3} over Rational Field
sage: phi_abc(abc[1] + 2 * abc[2])
B[1] + 2*B[2]
Providing a codomain::
sage: W = CombinatorialFreeModule(QQ, ['a', 'b', 'c'])
sage: phi_eW = V.isomorphism_with_fixed_basis(basis, codomain=W); phi_eW
Generic morphism:
From: 3-dimensional vector space over the Rational Field
To: Free module generated by {'a', 'b', 'c'} over Rational Field
sage: phi_eW(e[1] + 2 * e[2])
B['a'] + 2*B['b']
TESTS::
sage: V = FiniteRankFreeModule(QQ, 3); V
3-dimensional vector space over the Rational Field
sage: e = V.basis("e")
sage: V.isomorphism_with_fixed_basis(e, codomain=QQ^42)
Traceback (most recent call last):
...
ValueError: domain and codomain must have the same rank
sage: V.isomorphism_with_fixed_basis(e, codomain=RR^3)
Traceback (most recent call last):
...
ValueError: domain and codomain must have the same base ring
"""
base_ring = self.base_ring()
if basis is None:
basis = self.default_basis()
if codomain is None:
from sage.combinat.free_module import CombinatorialFreeModule
if isinstance(basis._symbol, str):
prefix = basis._symbol
else:
prefix = None
codomain = CombinatorialFreeModule(base_ring, basis.keys(),
prefix=prefix)
else:
if codomain.rank() != self.rank():
raise ValueError("domain and codomain must have the same rank")
if codomain.base_ring() != base_ring:
raise ValueError("domain and codomain must have the same "
"base ring")

codomain_basis = Family(codomain.basis())
if isinstance(codomain_basis, TrivialFamily):
# assume that codomain basis keys are to be ignored
key_pairs = enumerate(basis_keys())
else:
# assume that the keys of the codomain should be used
key_pairs = zip(codomain_basis.keys(), basis.keys())

def _isomorphism(x):
r"""
Concrete isomorphism from ``self`` to ``codomain``.
"""
return codomain.sum(x[basis, domain_key] * codomain_basis[codomain_key]
for codomain_key, domain_key in key_pairs)

return self.module_morphism(function=_isomorphism, codomain=codomain)

def _test_isomorphism_with_fixed_basis(self, **options):
r"""
Test that the method ``isomorphism_with_fixed_basis`` works correctly.
EXAMPLES::
sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: M._test_isomorphism_with_fixed_basis()
"""
tester = self._tester(**options)
basis = self.basis('test')
morphism = self.isomorphism_with_fixed_basis(basis)
tester.assertEqual(morphism.codomain().rank(), self.rank())


class FiniteRankFreeModule(FiniteRankFreeModule_abstract):
r"""
Expand Down Expand Up @@ -2713,123 +2837,6 @@ def hom(self, codomain, matrix_rep, bases=None, name=None,
return homset(matrix_rep, bases=bases, name=name,
latex_name=latex_name)

def isomorphism_with_fixed_basis(self, basis=None, codomain=None):
r"""
Construct the canonical isomorphism from the free module ``self``
to a free module in which ``basis`` of ``self`` is mapped to the
distinguished basis of ``codomain``.
INPUT:
- ``basis`` -- (default: ``None``) the basis of ``self`` which
should be mapped to the distinguished basis on ``codomain``;
if ``None``, the default basis is assumed.
- ``codomain`` -- (default: ``None``) the codomain of the
isomorphism represented by a free module within the category
:class:`~sage.categories.modules_with_basis.ModulesWithBasis` with
the same rank and base ring as ``self``; if ``None`` a free module
represented by
:class:`~sage.combinat.free_module.CombinatorialFreeModule` is
constructed
OUTPUT:
- a module morphism represented by
:class:`~sage.modules.with_basis.morphism.ModuleMorphismFromFunction`
EXAMPLES::
sage: V = FiniteRankFreeModule(QQ, 3, start_index=1); V
3-dimensional vector space over the Rational Field
sage: basis = e = V.basis("e"); basis
Basis (e_1,e_2,e_3) on the 3-dimensional vector space over the
Rational Field
sage: phi_e = V.isomorphism_with_fixed_basis(basis); phi_e
Generic morphism:
From: 3-dimensional vector space over the Rational Field
To: Free module generated by {1, 2, 3} over Rational Field
sage: phi_e.codomain().category()
Category of finite dimensional vector spaces with basis over
Rational Field
sage: phi_e(e[1] + 2 * e[2])
e[1] + 2*e[2]
sage: abc = V.basis(['a', 'b', 'c'], symbol_dual=['d', 'e', 'f']); abc
Basis (a,b,c) on the 3-dimensional vector space over the Rational Field
sage: phi_abc = V.isomorphism_with_fixed_basis(abc); phi_abc
Generic morphism:
From: 3-dimensional vector space over the Rational Field
To: Free module generated by {1, 2, 3} over Rational Field
sage: phi_abc(abc[1] + 2 * abc[2])
B[1] + 2*B[2]
Providing a codomain::
sage: W = CombinatorialFreeModule(QQ, ['a', 'b', 'c'])
sage: phi_eW = V.isomorphism_with_fixed_basis(basis, codomain=W); phi_eW
Generic morphism:
From: 3-dimensional vector space over the Rational Field
To: Free module generated by {'a', 'b', 'c'} over Rational Field
sage: phi_eW(e[1] + 2 * e[2])
B['a'] + 2*B['b']
TESTS::
sage: V = FiniteRankFreeModule(QQ, 3); V
3-dimensional vector space over the Rational Field
sage: e = V.basis("e")
sage: V.isomorphism_with_fixed_basis(e, codomain=QQ^42)
Traceback (most recent call last):
...
ValueError: domain and codomain must have the same rank
sage: V.isomorphism_with_fixed_basis(e, codomain=RR^3)
Traceback (most recent call last):
...
ValueError: domain and codomain must have the same base ring
"""
base_ring = self.base_ring()
if basis is None:
basis = self.default_basis()
if codomain is None:
from sage.combinat.free_module import CombinatorialFreeModule
if isinstance(basis._symbol, str):
prefix = basis._symbol
else:
prefix = None
codomain = CombinatorialFreeModule(base_ring, list(self.irange()),
prefix=prefix)
else:
if codomain.rank() != self.rank():
raise ValueError("domain and codomain must have the same rank")
if codomain.base_ring() != base_ring:
raise ValueError("domain and codomain must have the same "
"base ring")

codomain_basis = list(codomain.basis())

def _isomorphism(x):
r"""
Concrete isomorphism from ``self`` to ``codomain``.
"""
return codomain.sum(x[basis, i] * codomain_basis[i - self._sindex]
for i in self.irange())

return self.module_morphism(function=_isomorphism, codomain=codomain)

def _test_isomorphism_with_fixed_basis(self, **options):
r"""
Test that the method ``isomorphism_with_fixed_basis`` works correctly.
EXAMPLES::
sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: M._test_isomorphism_with_fixed_basis()
"""
tester = self._tester(**options)
basis = self.basis('test')
morphism = self.isomorphism_with_fixed_basis(basis)
tester.assertEqual(morphism.codomain().rank(), self.rank())

def endomorphism(self, matrix_rep, basis=None, name=None, latex_name=None):
r"""
Construct an endomorphism of the free module ``self``.
Expand Down

0 comments on commit a4d65bc

Please sign in to comment.