Free module morphisms#

The class FiniteRankFreeModuleMorphism implements homomorphisms between two free modules of finite rank over the same commutative ring.

The subclass FiniteRankFreeModuleEndomorphism implements the special case of endomorphisms.

AUTHORS:

REFERENCES:

class sage.tensor.modules.free_module_morphism.FiniteRankFreeModuleEndomorphism(parent, matrix_rep, bases=None, name=None, latex_name=None, is_identity=False)[source]#

Bases: FiniteRankFreeModuleMorphism

Endomorphism of a free module of finite rank over a commutative ring.

An instance of this class is an endomorphism

\[\phi:\ M \longrightarrow M,\]

where \(M\) is a free module of finite rank over a commutative ring \(R\).

This is a Sage element class, the corresponding parent class being FreeModuleEndset.

INPUT:

  • parent – hom-set Hom(M,M) to which the endomorphism belongs

  • matrix_rep – matrix representation of the endomorphism with respect to the basis bases; this entry can actually be any material from which a matrix of size rank(N)*rank(M) of elements of \(R\) can be constructed; the columns of the matrix give the images of the basis of \(M\) (see the convention in the example below)

  • bases – (default: None) pair (basis_domain, basis_codomain) defining the matrix representation, basis_domain and basis_codomain being two bases (typically the same) of the same module \(M\); if None, the default basis of \(M\) is used for both.

  • name – (default: None) string; name given to the endomorphism

  • latex_name – (default: None) string; LaTeX symbol to denote the endomorphism; if None, name will be used.

  • is_identity – (default: False) determines whether the constructed object is the identity endomorphism; if set to True, then the entry matrix_rep is not used.

EXAMPLES:

The identity endomorphism:

sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: e = M.basis('e')
sage: Id = End(M).one(); Id
Identity endomorphism of Rank-3 free module M over the Integer Ring
sage: Id.parent()
Set of Morphisms from Rank-3 free module M over the Integer Ring
 to Rank-3 free module M over the Integer Ring
 in Category of finite dimensional modules over Integer Ring
sage: Id.parent() is End(M)
True
>>> from sage.all import *
>>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M')
>>> e = M.basis('e')
>>> Id = End(M).one(); Id
Identity endomorphism of Rank-3 free module M over the Integer Ring
>>> Id.parent()
Set of Morphisms from Rank-3 free module M over the Integer Ring
 to Rank-3 free module M over the Integer Ring
 in Category of finite dimensional modules over Integer Ring
>>> Id.parent() is End(M)
True

The matrix of Id with respect to the basis e is of course the identity matrix:

sage: Id.matrix(e)
[1 0 0]
[0 1 0]
[0 0 1]
>>> from sage.all import *
>>> Id.matrix(e)
[1 0 0]
[0 1 0]
[0 0 1]

The identity acting on a module element:

sage: v = M([-2,1,4], basis=e, name='v'); v.display()
v = -2 e_0 + e_1 + 4 e_2
sage: Id(v) is v
True
>>> from sage.all import *
>>> v = M([-Integer(2),Integer(1),Integer(4)], basis=e, name='v'); v.display()
v = -2 e_0 + e_1 + 4 e_2
>>> Id(v) is v
True
characteristic_polynomial()[source]#

Return the characteristic polynomial of self.

characteristic_polynomial() and charpoly() are the same method.

INPUT:

  • var – string (default: 'x'); a variable name

EXAMPLES:

sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: e = M.basis('e')
sage: a = M.automorphism(matrix=[[-1,0,0],[0,1,2],[0,1,3]], basis=e)
sage: ep = e.new_basis(a, 'ep', latex_symbol="e'")
sage: phi = M.endomorphism([[1,2,3], [4,5,6], [7,8,9]], basis=ep)
sage: phi.matrix(e)
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]
sage: phi.characteristic_polynomial()
x^3 - 15*x^2 - 18*x
sage: phi.charpoly()
x^3 - 15*x^2 - 18*x
sage: phi.charpoly('T')
T^3 - 15*T^2 - 18*T
>>> from sage.all import *
>>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M')
>>> e = M.basis('e')
>>> a = M.automorphism(matrix=[[-Integer(1),Integer(0),Integer(0)],[Integer(0),Integer(1),Integer(2)],[Integer(0),Integer(1),Integer(3)]], basis=e)
>>> ep = e.new_basis(a, 'ep', latex_symbol="e'")
>>> phi = M.endomorphism([[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]], basis=ep)
>>> phi.matrix(e)
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]
>>> phi.characteristic_polynomial()
x^3 - 15*x^2 - 18*x
>>> phi.charpoly()
x^3 - 15*x^2 - 18*x
>>> phi.charpoly('T')
T^3 - 15*T^2 - 18*T
charpoly()[source]#

Return the characteristic polynomial of self.

characteristic_polynomial() and charpoly() are the same method.

INPUT:

  • var – string (default: 'x'); a variable name

EXAMPLES:

sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: e = M.basis('e')
sage: a = M.automorphism(matrix=[[-1,0,0],[0,1,2],[0,1,3]], basis=e)
sage: ep = e.new_basis(a, 'ep', latex_symbol="e'")
sage: phi = M.endomorphism([[1,2,3], [4,5,6], [7,8,9]], basis=ep)
sage: phi.matrix(e)
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]
sage: phi.characteristic_polynomial()
x^3 - 15*x^2 - 18*x
sage: phi.charpoly()
x^3 - 15*x^2 - 18*x
sage: phi.charpoly('T')
T^3 - 15*T^2 - 18*T
>>> from sage.all import *
>>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M')
>>> e = M.basis('e')
>>> a = M.automorphism(matrix=[[-Integer(1),Integer(0),Integer(0)],[Integer(0),Integer(1),Integer(2)],[Integer(0),Integer(1),Integer(3)]], basis=e)
>>> ep = e.new_basis(a, 'ep', latex_symbol="e'")
>>> phi = M.endomorphism([[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]], basis=ep)
>>> phi.matrix(e)
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]
>>> phi.characteristic_polynomial()
x^3 - 15*x^2 - 18*x
>>> phi.charpoly()
x^3 - 15*x^2 - 18*x
>>> phi.charpoly('T')
T^3 - 15*T^2 - 18*T
det()[source]#

Return the determinant of self.

OUTPUT:

  • element of the base ring of the modules on which self is defined, equal to the determinant of self.

EXAMPLES:

sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: e = M.basis('e')
sage: a = M.automorphism(matrix=[[-1,0,0],[0,1,2],[0,1,3]], basis=e)
sage: ep = e.new_basis(a, 'ep', latex_symbol="e'")
sage: phi = M.endomorphism([[1,2,3], [4,5,6], [7,8,9]], basis=ep)
sage: phi.matrix(e)
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]
sage: phi.det()
0
sage: det(phi)
0
>>> from sage.all import *
>>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M')
>>> e = M.basis('e')
>>> a = M.automorphism(matrix=[[-Integer(1),Integer(0),Integer(0)],[Integer(0),Integer(1),Integer(2)],[Integer(0),Integer(1),Integer(3)]], basis=e)
>>> ep = e.new_basis(a, 'ep', latex_symbol="e'")
>>> phi = M.endomorphism([[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]], basis=ep)
>>> phi.matrix(e)
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]
>>> phi.det()
0
>>> det(phi)
0
determinant()[source]#

Return the determinant of self.

OUTPUT:

  • element of the base ring of the modules on which self is defined, equal to the determinant of self.

EXAMPLES:

sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: e = M.basis('e')
sage: a = M.automorphism(matrix=[[-1,0,0],[0,1,2],[0,1,3]], basis=e)
sage: ep = e.new_basis(a, 'ep', latex_symbol="e'")
sage: phi = M.endomorphism([[1,2,3], [4,5,6], [7,8,9]], basis=ep)
sage: phi.matrix(e)
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]
sage: phi.det()
0
sage: det(phi)
0
>>> from sage.all import *
>>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M')
>>> e = M.basis('e')
>>> a = M.automorphism(matrix=[[-Integer(1),Integer(0),Integer(0)],[Integer(0),Integer(1),Integer(2)],[Integer(0),Integer(1),Integer(3)]], basis=e)
>>> ep = e.new_basis(a, 'ep', latex_symbol="e'")
>>> phi = M.endomorphism([[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]], basis=ep)
>>> phi.matrix(e)
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]
>>> phi.det()
0
>>> det(phi)
0
fcp()[source]#

Return the factorization of the characteristic polynomial of self.

INPUT:

  • var – string (default: 'x'); a variable name

EXAMPLES:

sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: e = M.basis('e')
sage: a = M.automorphism(matrix=[[-1,0,0],[0,1,2],[0,1,3]], basis=e)
sage: ep = e.new_basis(a, 'ep', latex_symbol="e'")
sage: phi = M.endomorphism([[1,2,3], [4,5,6], [7,8,9]], basis=ep)
sage: phi.matrix(e)
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]
sage: phi.fcp()                                                             # needs sage.libs.pari
x * (x^2 - 15*x - 18)
sage: phi.fcp('T')                                                          # needs sage.libs.pari
T * (T^2 - 15*T - 18)
>>> from sage.all import *
>>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M')
>>> e = M.basis('e')
>>> a = M.automorphism(matrix=[[-Integer(1),Integer(0),Integer(0)],[Integer(0),Integer(1),Integer(2)],[Integer(0),Integer(1),Integer(3)]], basis=e)
>>> ep = e.new_basis(a, 'ep', latex_symbol="e'")
>>> phi = M.endomorphism([[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]], basis=ep)
>>> phi.matrix(e)
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]
>>> phi.fcp()                                                             # needs sage.libs.pari
x * (x^2 - 15*x - 18)
>>> phi.fcp('T')                                                          # needs sage.libs.pari
T * (T^2 - 15*T - 18)
minimal_polynomial()[source]#

Return the minimal polynomial of self.

minimal_polynomial() and minpoly() are the same method.

INPUT:

  • var – string (default: 'x'); a variable name

EXAMPLES:

sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: e = M.basis('e')
sage: a = M.automorphism(matrix=[[-1,0,0],[0,1,2],[0,1,3]], basis=e)
sage: ep = e.new_basis(a, 'ep', latex_symbol="e'")
sage: phi = M.endomorphism([[1,2,3], [4,5,6], [7,8,9]], basis=ep)
sage: phi.matrix(e)
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]
sage: phi.minpoly()                                                         # needs sage.libs.pari
x^3 - 15*x^2 - 18*x
sage: phi.minimal_polynomial()                                              # needs sage.libs.pari
x^3 - 15*x^2 - 18*x
sage: phi.minimal_polynomial('T')                                           # needs sage.libs.pari
T^3 - 15*T^2 - 18*T
>>> from sage.all import *
>>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M')
>>> e = M.basis('e')
>>> a = M.automorphism(matrix=[[-Integer(1),Integer(0),Integer(0)],[Integer(0),Integer(1),Integer(2)],[Integer(0),Integer(1),Integer(3)]], basis=e)
>>> ep = e.new_basis(a, 'ep', latex_symbol="e'")
>>> phi = M.endomorphism([[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]], basis=ep)
>>> phi.matrix(e)
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]
>>> phi.minpoly()                                                         # needs sage.libs.pari
x^3 - 15*x^2 - 18*x
>>> phi.minimal_polynomial()                                              # needs sage.libs.pari
x^3 - 15*x^2 - 18*x
>>> phi.minimal_polynomial('T')                                           # needs sage.libs.pari
T^3 - 15*T^2 - 18*T
minpoly()[source]#

Return the minimal polynomial of self.

minimal_polynomial() and minpoly() are the same method.

INPUT:

  • var – string (default: 'x'); a variable name

EXAMPLES:

sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: e = M.basis('e')
sage: a = M.automorphism(matrix=[[-1,0,0],[0,1,2],[0,1,3]], basis=e)
sage: ep = e.new_basis(a, 'ep', latex_symbol="e'")
sage: phi = M.endomorphism([[1,2,3], [4,5,6], [7,8,9]], basis=ep)
sage: phi.matrix(e)
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]
sage: phi.minpoly()                                                         # needs sage.libs.pari
x^3 - 15*x^2 - 18*x
sage: phi.minimal_polynomial()                                              # needs sage.libs.pari
x^3 - 15*x^2 - 18*x
sage: phi.minimal_polynomial('T')                                           # needs sage.libs.pari
T^3 - 15*T^2 - 18*T
>>> from sage.all import *
>>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M')
>>> e = M.basis('e')
>>> a = M.automorphism(matrix=[[-Integer(1),Integer(0),Integer(0)],[Integer(0),Integer(1),Integer(2)],[Integer(0),Integer(1),Integer(3)]], basis=e)
>>> ep = e.new_basis(a, 'ep', latex_symbol="e'")
>>> phi = M.endomorphism([[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]], basis=ep)
>>> phi.matrix(e)
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]
>>> phi.minpoly()                                                         # needs sage.libs.pari
x^3 - 15*x^2 - 18*x
>>> phi.minimal_polynomial()                                              # needs sage.libs.pari
x^3 - 15*x^2 - 18*x
>>> phi.minimal_polynomial('T')                                           # needs sage.libs.pari
T^3 - 15*T^2 - 18*T
trace()[source]#

Return the trace of self.

OUTPUT:

  • element of the base ring of the modules on which self is defined, equal to the trace of self.

EXAMPLES:

sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: e = M.basis('e')
sage: a = M.automorphism(matrix=[[-1,0,0],[0,1,2],[0,1,3]], basis=e)
sage: ep = e.new_basis(a, 'ep', latex_symbol="e'")
sage: phi = M.endomorphism([[1,2,3], [4,5,6], [7,8,9]], basis=ep)
sage: phi.matrix(e)
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]
sage: phi.trace()
15
sage: id = M.identity_map()
sage: id.trace()
3
>>> from sage.all import *
>>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M')
>>> e = M.basis('e')
>>> a = M.automorphism(matrix=[[-Integer(1),Integer(0),Integer(0)],[Integer(0),Integer(1),Integer(2)],[Integer(0),Integer(1),Integer(3)]], basis=e)
>>> ep = e.new_basis(a, 'ep', latex_symbol="e'")
>>> phi = M.endomorphism([[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]], basis=ep)
>>> phi.matrix(e)
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]
>>> phi.trace()
15
>>> id = M.identity_map()
>>> id.trace()
3
class sage.tensor.modules.free_module_morphism.FiniteRankFreeModuleMorphism(parent, matrix_rep, bases=None, name=None, latex_name=None, is_identity=False)[source]#

Bases: Morphism

Homomorphism between free modules of finite rank over a commutative ring.

An instance of this class is a homomorphism

\[\phi:\ M \longrightarrow N,\]

where \(M\) and \(N\) are two free modules of finite rank over the same commutative ring \(R\).

This is a Sage element class, the corresponding parent class being FreeModuleHomset.

For the special case of endomorphisms (\(M=N\)), use the subclass FiniteRankFreeModuleEndomorphism.

INPUT:

  • parent – hom-set Hom(M,N) to which the homomorphism belongs

  • matrix_rep – matrix representation of the homomorphism with respect to the bases bases; this entry can actually be any material from which a matrix of size rank(N)*rank(M) of elements of \(R\) can be constructed; the columns of the matrix give the images of the basis of \(M\) (see the convention in the example below)

  • bases – (default: None) pair (basis_M, basis_N) defining the matrix representation, basis_M being a basis of module \(M\) and basis_N a basis of module \(N\) ; if None the pair formed by the default bases of each module is assumed.

  • name – (default: None) string; name given to the homomorphism

  • latex_name – (default: None) string; LaTeX symbol to denote the homomorphism; if None, name will be used.

EXAMPLES:

A homomorphism between two free modules over \(\ZZ\) is constructed as an element of the corresponding hom-set, by means of the function __call__:

sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: N = FiniteRankFreeModule(ZZ, 2, name='N')
sage: e = M.basis('e') ; f = N.basis('f')
sage: H = Hom(M,N) ; H
Set of Morphisms from Rank-3 free module M over the Integer Ring
 to Rank-2 free module N over the Integer Ring
 in Category of finite dimensional modules over Integer Ring
sage: phi = H([[2,-1,3], [1,0,-4]], name='phi', latex_name=r'\phi') ; phi
Generic morphism:
  From: Rank-3 free module M over the Integer Ring
  To:   Rank-2 free module N over the Integer Ring
>>> from sage.all import *
>>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M')
>>> N = FiniteRankFreeModule(ZZ, Integer(2), name='N')
>>> e = M.basis('e') ; f = N.basis('f')
>>> H = Hom(M,N) ; H
Set of Morphisms from Rank-3 free module M over the Integer Ring
 to Rank-2 free module N over the Integer Ring
 in Category of finite dimensional modules over Integer Ring
>>> phi = H([[Integer(2),-Integer(1),Integer(3)], [Integer(1),Integer(0),-Integer(4)]], name='phi', latex_name=r'\phi') ; phi
Generic morphism:
  From: Rank-3 free module M over the Integer Ring
  To:   Rank-2 free module N over the Integer Ring

Since no bases have been specified in the argument list, the provided matrix is relative to the default bases of modules M and N, so that the above is equivalent to:

sage: phi = H([[2,-1,3], [1,0,-4]], bases=(e,f), name='phi',
....:         latex_name=r'\phi') ; phi
Generic morphism:
  From: Rank-3 free module M over the Integer Ring
  To:   Rank-2 free module N over the Integer Ring
>>> from sage.all import *
>>> phi = H([[Integer(2),-Integer(1),Integer(3)], [Integer(1),Integer(0),-Integer(4)]], bases=(e,f), name='phi',
...         latex_name=r'\phi') ; phi
Generic morphism:
  From: Rank-3 free module M over the Integer Ring
  To:   Rank-2 free module N over the Integer Ring

An alternative way to construct a homomorphism is to call the method hom() on the domain:

sage: phi = M.hom(N, [[2,-1,3], [1,0,-4]], bases=(e,f), name='phi',
....:             latex_name=r'\phi') ; phi
Generic morphism:
  From: Rank-3 free module M over the Integer Ring
  To:   Rank-2 free module N over the Integer Ring
>>> from sage.all import *
>>> phi = M.hom(N, [[Integer(2),-Integer(1),Integer(3)], [Integer(1),Integer(0),-Integer(4)]], bases=(e,f), name='phi',
...             latex_name=r'\phi') ; phi
Generic morphism:
  From: Rank-3 free module M over the Integer Ring
  To:   Rank-2 free module N over the Integer Ring

The parent of a homomorphism is of course the corresponding hom-set:

sage: phi.parent() is H
True
sage: phi.parent() is Hom(M,N)
True
>>> from sage.all import *
>>> phi.parent() is H
True
>>> phi.parent() is Hom(M,N)
True

Due to Sage’s category scheme, the actual class of the homomorphism phi is a derived class of FiniteRankFreeModuleMorphism:

sage: type(phi)
<class 'sage.tensor.modules.free_module_homset.FreeModuleHomset_with_category_with_equality_by_id.element_class'>
sage: isinstance(phi, sage.tensor.modules.free_module_morphism.FiniteRankFreeModuleMorphism)
True
>>> from sage.all import *
>>> type(phi)
<class 'sage.tensor.modules.free_module_homset.FreeModuleHomset_with_category_with_equality_by_id.element_class'>
>>> isinstance(phi, sage.tensor.modules.free_module_morphism.FiniteRankFreeModuleMorphism)
True

The domain and codomain of the homomorphism are returned respectively by the methods domain() and codomain(), which are implemented as Sage’s constant functions:

sage: phi.domain()
Rank-3 free module M over the Integer Ring
sage: phi.codomain()
Rank-2 free module N over the Integer Ring
sage: type(phi.domain)
<... 'sage.misc.constant_function.ConstantFunction'>
>>> from sage.all import *
>>> phi.domain()
Rank-3 free module M over the Integer Ring
>>> phi.codomain()
Rank-2 free module N over the Integer Ring
>>> type(phi.domain)
<... 'sage.misc.constant_function.ConstantFunction'>

The matrix of the homomorphism with respect to a pair of bases is returned by the method matrix():

sage: phi.matrix(e,f)
[ 2 -1  3]
[ 1  0 -4]
>>> from sage.all import *
>>> phi.matrix(e,f)
[ 2 -1  3]
[ 1  0 -4]

The convention is that the columns of this matrix give the components of the images of the elements of basis e w.r.t basis f:

sage: phi(e[0]).display()
phi(e_0) = 2 f_0 + f_1
sage: phi(e[1]).display()
phi(e_1) = -f_0
sage: phi(e[2]).display()
phi(e_2) = 3 f_0 - 4 f_1
>>> from sage.all import *
>>> phi(e[Integer(0)]).display()
phi(e_0) = 2 f_0 + f_1
>>> phi(e[Integer(1)]).display()
phi(e_1) = -f_0
>>> phi(e[Integer(2)]).display()
phi(e_2) = 3 f_0 - 4 f_1

Test of the module homomorphism laws:

sage: phi(M.zero()) == N.zero()
True
sage: u = M([1,2,3], basis=e, name='u') ; u.display()
u = e_0 + 2 e_1 + 3 e_2
sage: v = M([-2,1,4], basis=e, name='v') ; v.display()
v = -2 e_0 + e_1 + 4 e_2
sage: phi(u).display()
phi(u) = 9 f_0 - 11 f_1
sage: phi(v).display()
phi(v) = 7 f_0 - 18 f_1
sage: phi(3*u + v).display()
34 f_0 - 51 f_1
sage: phi(3*u + v) == 3*phi(u) + phi(v)
True
>>> from sage.all import *
>>> phi(M.zero()) == N.zero()
True
>>> u = M([Integer(1),Integer(2),Integer(3)], basis=e, name='u') ; u.display()
u = e_0 + 2 e_1 + 3 e_2
>>> v = M([-Integer(2),Integer(1),Integer(4)], basis=e, name='v') ; v.display()
v = -2 e_0 + e_1 + 4 e_2
>>> phi(u).display()
phi(u) = 9 f_0 - 11 f_1
>>> phi(v).display()
phi(v) = 7 f_0 - 18 f_1
>>> phi(Integer(3)*u + v).display()
34 f_0 - 51 f_1
>>> phi(Integer(3)*u + v) == Integer(3)*phi(u) + phi(v)
True
display(basis1=None, basis2=None)[source]#

Display self as a matrix w.r.t to a pair of bases.

If the matrix is not known already, it is computed from the matrix in another pair of bases by means of the change-of-basis formula.

INPUT:

  • basis1 – (default: None) basis of the domain of self; if none is provided, the domain’s default basis is assumed

  • basis2 – (default: None) basis of the codomain of self; if none is provided, basis2 is set to basis1 if self is an endomorphism, otherwise, basis2 is set to the codomain’s default basis.

EXAMPLES:

sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: N = FiniteRankFreeModule(ZZ, 2, name='N')
sage: e = M.basis('e'); f = N.basis('f')
sage: phi = M.hom(N, [[-1,2,0], [5,1,2]])
sage: phi.display()     # default bases
    e_0 e_1 e_2
f_0⎛ -1   2   0⎞
f_1⎝  5   1   2⎠
sage: phi.display(e, f)  # given bases
    e_0 e_1 e_2
f_0⎛ -1   2   0⎞
f_1⎝  5   1   2⎠
>>> from sage.all import *
>>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M')
>>> N = FiniteRankFreeModule(ZZ, Integer(2), name='N')
>>> e = M.basis('e'); f = N.basis('f')
>>> phi = M.hom(N, [[-Integer(1),Integer(2),Integer(0)], [Integer(5),Integer(1),Integer(2)]])
>>> phi.display()     # default bases
    e_0 e_1 e_2
f_0⎛ -1   2   0⎞
f_1⎝  5   1   2⎠
>>> phi.display(e, f)  # given bases
    e_0 e_1 e_2
f_0⎛ -1   2   0⎞
f_1⎝  5   1   2⎠

Matrix of an endomorphism:

sage: a = M.automorphism(matrix=[[-1,0,0],[0,1,2],[0,1,3]], basis=e)
sage: ep = e.new_basis(a, 'ep', latex_symbol="e'")
sage: phi = M.endomorphism([[1,2,3], [4,5,6], [7,8,9]], basis=ep)
sage: phi.display(ep)
     ep_0 ep_1 ep_2
ep_0⎛   1    2    3⎞
ep_1⎜   4    5    6⎟
ep_2⎝   7    8    9⎠
sage: phi.display(ep, ep)  # same as above
     ep_0 ep_1 ep_2
ep_0⎛   1    2    3⎞
ep_1⎜   4    5    6⎟
ep_2⎝   7    8    9⎠
sage: phi.display()  # matrix w.r.t to the module's default basis
    e_0 e_1 e_2
e_0⎛  1  -3   1⎞
e_1⎜-18  39 -18⎟
e_2⎝-25  54 -25⎠
>>> from sage.all import *
>>> a = M.automorphism(matrix=[[-Integer(1),Integer(0),Integer(0)],[Integer(0),Integer(1),Integer(2)],[Integer(0),Integer(1),Integer(3)]], basis=e)
>>> ep = e.new_basis(a, 'ep', latex_symbol="e'")
>>> phi = M.endomorphism([[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]], basis=ep)
>>> phi.display(ep)
     ep_0 ep_1 ep_2
ep_0⎛   1    2    3⎞
ep_1⎜   4    5    6⎟
ep_2⎝   7    8    9⎠
>>> phi.display(ep, ep)  # same as above
     ep_0 ep_1 ep_2
ep_0⎛   1    2    3⎞
ep_1⎜   4    5    6⎟
ep_2⎝   7    8    9⎠
>>> phi.display()  # matrix w.r.t to the module's default basis
    e_0 e_1 e_2
e_0⎛  1  -3   1⎞
e_1⎜-18  39 -18⎟
e_2⎝-25  54 -25⎠
is_identity()[source]#

Check whether self is the identity morphism.

EXAMPLES:

sage: M = FiniteRankFreeModule(ZZ, 2, name='M')
sage: e = M.basis('e')
sage: phi = M.endomorphism([[1,0], [0,1]])
sage: phi.is_identity()
True
sage: (phi+phi).is_identity()
False
sage: End(M).zero().is_identity()
False
sage: a = M.automorphism() ; a[0,1], a[1,0] = 1, -1
sage: ep = e.new_basis(a, 'ep', latex_symbol="e'")
sage: phi = M.endomorphism([[1,0], [0,1]], basis=ep)
sage: phi.is_identity()
True
>>> from sage.all import *
>>> M = FiniteRankFreeModule(ZZ, Integer(2), name='M')
>>> e = M.basis('e')
>>> phi = M.endomorphism([[Integer(1),Integer(0)], [Integer(0),Integer(1)]])
>>> phi.is_identity()
True
>>> (phi+phi).is_identity()
False
>>> End(M).zero().is_identity()
False
>>> a = M.automorphism() ; a[Integer(0),Integer(1)], a[Integer(1),Integer(0)] = Integer(1), -Integer(1)
>>> ep = e.new_basis(a, 'ep', latex_symbol="e'")
>>> phi = M.endomorphism([[Integer(1),Integer(0)], [Integer(0),Integer(1)]], basis=ep)
>>> phi.is_identity()
True

Example illustrating that the identity can be constructed from a matrix that is not the identity one, provided that it is relative to different bases:

sage: phi = M.hom(M, [[0,1], [-1,0]], bases=(ep,e))
sage: phi.is_identity()
True
>>> from sage.all import *
>>> phi = M.hom(M, [[Integer(0),Integer(1)], [-Integer(1),Integer(0)]], bases=(ep,e))
>>> phi.is_identity()
True

Of course, if we ask for the matrix in a single basis, it is the identity matrix:

sage: phi.matrix(e)
[1 0]
[0 1]
sage: phi.matrix(ep)
[1 0]
[0 1]
>>> from sage.all import *
>>> phi.matrix(e)
[1 0]
[0 1]
>>> phi.matrix(ep)
[1 0]
[0 1]
is_injective()[source]#

Determine whether self is injective.

OUTPUT:

  • True if self is an injective homomorphism and False otherwise

EXAMPLES:

Homomorphisms between two \(\ZZ\)-modules:

sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: N = FiniteRankFreeModule(ZZ, 2, name='N')
sage: e = M.basis('e') ; f = N.basis('f')
sage: phi = M.hom(N, [[-1,2,0], [5,1,2]])
sage: phi.matrix(e,f)
[-1  2  0]
[ 5  1  2]
sage: phi.is_injective()
False
>>> from sage.all import *
>>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M')
>>> N = FiniteRankFreeModule(ZZ, Integer(2), name='N')
>>> e = M.basis('e') ; f = N.basis('f')
>>> phi = M.hom(N, [[-Integer(1),Integer(2),Integer(0)], [Integer(5),Integer(1),Integer(2)]])
>>> phi.matrix(e,f)
[-1  2  0]
[ 5  1  2]
>>> phi.is_injective()
False

Indeed, phi has a non trivial kernel:

sage: phi(4*e[0] + 2*e[1] - 11*e[2]).display()
0
>>> from sage.all import *
>>> phi(Integer(4)*e[Integer(0)] + Integer(2)*e[Integer(1)] - Integer(11)*e[Integer(2)]).display()
0

An injective homomorphism:

sage: psi = N.hom(M, [[1,-1], [0,3], [4,-5]])
sage: psi.matrix(f,e)
[ 1 -1]
[ 0  3]
[ 4 -5]
sage: psi.is_injective()
True
>>> from sage.all import *
>>> psi = N.hom(M, [[Integer(1),-Integer(1)], [Integer(0),Integer(3)], [Integer(4),-Integer(5)]])
>>> psi.matrix(f,e)
[ 1 -1]
[ 0  3]
[ 4 -5]
>>> psi.is_injective()
True

Of course, the identity endomorphism is injective:

sage: End(M).one().is_injective()
True
sage: End(N).one().is_injective()
True
>>> from sage.all import *
>>> End(M).one().is_injective()
True
>>> End(N).one().is_injective()
True
is_surjective()[source]#

Determine whether self is surjective.

OUTPUT:

  • True if self is a surjective homomorphism and False otherwise

EXAMPLES:

This method has not been implemented yet:

sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: N = FiniteRankFreeModule(ZZ, 2, name='N')
sage: e = M.basis('e') ; f = N.basis('f')
sage: phi = M.hom(N, [[-1,2,0], [5,1,2]])
sage: phi.is_surjective()
Traceback (most recent call last):
...
NotImplementedError: FiniteRankFreeModuleMorphism.is_surjective()
 has not been implemented yet
>>> from sage.all import *
>>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M')
>>> N = FiniteRankFreeModule(ZZ, Integer(2), name='N')
>>> e = M.basis('e') ; f = N.basis('f')
>>> phi = M.hom(N, [[-Integer(1),Integer(2),Integer(0)], [Integer(5),Integer(1),Integer(2)]])
>>> phi.is_surjective()
Traceback (most recent call last):
...
NotImplementedError: FiniteRankFreeModuleMorphism.is_surjective()
 has not been implemented yet

except for the identity endomorphism (!):

sage: End(M).one().is_surjective()
True
sage: End(N).one().is_surjective()
True
>>> from sage.all import *
>>> End(M).one().is_surjective()
True
>>> End(N).one().is_surjective()
True
matrix(basis1=None, basis2=None)[source]#

Return the matrix of self w.r.t to a pair of bases.

If the matrix is not known already, it is computed from the matrix in another pair of bases by means of the change-of-basis formula.

INPUT:

  • basis1 – (default: None) basis of the domain of self; if none is provided, the domain’s default basis is assumed

  • basis2 – (default: None) basis of the codomain of self; if none is provided, basis2 is set to basis1 if self is an endomorphism, otherwise, basis2 is set to the codomain’s default basis.

OUTPUT:

  • the matrix representing the homomorphism self w.r.t to bases basis1 and basis2; more precisely, the columns of this matrix are formed by the components w.r.t. basis2 of the images of the elements of basis1.

EXAMPLES:

Matrix of a homomorphism between two \(\ZZ\)-modules:

sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: N = FiniteRankFreeModule(ZZ, 2, name='N')
sage: e = M.basis('e') ; f = N.basis('f')
sage: phi = M.hom(N, [[-1,2,0], [5,1,2]])
sage: phi.matrix()     # default bases
[-1  2  0]
[ 5  1  2]
sage: phi.matrix(e, f)  # given bases
[-1  2  0]
[ 5  1  2]
sage: type(phi.matrix())                                                    # needs sage.libs.flint
<class 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'>
>>> from sage.all import *
>>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M')
>>> N = FiniteRankFreeModule(ZZ, Integer(2), name='N')
>>> e = M.basis('e') ; f = N.basis('f')
>>> phi = M.hom(N, [[-Integer(1),Integer(2),Integer(0)], [Integer(5),Integer(1),Integer(2)]])
>>> phi.matrix()     # default bases
[-1  2  0]
[ 5  1  2]
>>> phi.matrix(e, f)  # given bases
[-1  2  0]
[ 5  1  2]
>>> type(phi.matrix())                                                    # needs sage.libs.flint
<class 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'>

Matrix in bases different from those in which the homomorphism has been defined:

sage: a = M.automorphism(matrix=[[-1,0,0],[0,1,2],[0,1,3]], basis=e)
sage: ep = e.new_basis(a, 'ep', latex_symbol="e'")
sage: b = N.automorphism(matrix=[[3,5],[4,7]], basis=f)
sage: fp = f.new_basis(b, 'fp', latex_symbol="f'")
sage: phi.matrix(ep, fp)
[ 32  -1 -12]
[-19   1   8]
>>> from sage.all import *
>>> a = M.automorphism(matrix=[[-Integer(1),Integer(0),Integer(0)],[Integer(0),Integer(1),Integer(2)],[Integer(0),Integer(1),Integer(3)]], basis=e)
>>> ep = e.new_basis(a, 'ep', latex_symbol="e'")
>>> b = N.automorphism(matrix=[[Integer(3),Integer(5)],[Integer(4),Integer(7)]], basis=f)
>>> fp = f.new_basis(b, 'fp', latex_symbol="f'")
>>> phi.matrix(ep, fp)
[ 32  -1 -12]
[-19   1   8]

Check of the change-of-basis formula:

sage: phi.matrix(ep, fp) == (b^(-1)).matrix(f) * phi.matrix(e,f) * a.matrix(e)
True
>>> from sage.all import *
>>> phi.matrix(ep, fp) == (b**(-Integer(1))).matrix(f) * phi.matrix(e,f) * a.matrix(e)
True

Single change of basis:

sage: phi.matrix(ep, f)
[ 1  2  4]
[-5  3  8]
sage: phi.matrix(ep,f) == phi.matrix(e,f) * a.matrix(e)
True
sage: phi.matrix(e, fp)
[-32   9 -10]
[ 19  -5   6]
sage: phi.matrix(e, fp) == (b^(-1)).matrix(f) * phi.matrix(e,f)
True
>>> from sage.all import *
>>> phi.matrix(ep, f)
[ 1  2  4]
[-5  3  8]
>>> phi.matrix(ep,f) == phi.matrix(e,f) * a.matrix(e)
True
>>> phi.matrix(e, fp)
[-32   9 -10]
[ 19  -5   6]
>>> phi.matrix(e, fp) == (b**(-Integer(1))).matrix(f) * phi.matrix(e,f)
True

Matrix of an endomorphism:

sage: phi = M.endomorphism([[1,2,3], [4,5,6], [7,8,9]], basis=ep)
sage: phi.matrix(ep)
[1 2 3]
[4 5 6]
[7 8 9]
sage: phi.matrix(ep,ep)  # same as above
[1 2 3]
[4 5 6]
[7 8 9]
sage: phi.matrix()  # matrix w.r.t to the module's default basis
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]
>>> from sage.all import *
>>> phi = M.endomorphism([[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]], basis=ep)
>>> phi.matrix(ep)
[1 2 3]
[4 5 6]
[7 8 9]
>>> phi.matrix(ep,ep)  # same as above
[1 2 3]
[4 5 6]
[7 8 9]
>>> phi.matrix()  # matrix w.r.t to the module's default basis
[  1  -3   1]
[-18  39 -18]
[-25  54 -25]