Free module automorphisms#
Given a free module \(M\) of finite rank over a commutative ring \(R\), an automorphism of \(M\) is a map
that is linear (i.e. is a module homomorphism) and bijective.
Automorphisms of a free module of finite rank are implemented via the class
FreeModuleAutomorphism
.
AUTHORS:
Eric Gourgoulhon (2015): initial version
Michael Jung (2019): improve treatment of the identity element
REFERENCES:
Chaps. 15, 24 of R. Godement: Algebra [God1968]
- class sage.tensor.modules.free_module_automorphism.FreeModuleAutomorphism(fmodule, name=None, latex_name=None)[source]#
Bases:
FreeModuleTensor
,MultiplicativeGroupElement
Automorphism of a free module of finite rank over a commutative ring.
This is a Sage element class, the corresponding parent class being
FreeModuleLinearGroup
.This class inherits from the classes
FreeModuleTensor
andMultiplicativeGroupElement
.INPUT:
fmodule
– free module \(M\) of finite rank over a commutative ring \(R\), as an instance ofFiniteRankFreeModule
name
– (default:None
) name given to the automorphismlatex_name
– (default:None
) LaTeX symbol to denote the automorphism; if none is provided, the LaTeX symbol is set toname
is_identity
– (default:False
) determines whether the constructed object is the identity automorphism, i.e. the identity map of \(M\) considered as an automorphism (the identity element of the general linear group)
EXAMPLES:
Automorphism of a rank-2 free module over \(\ZZ\):
sage: M = FiniteRankFreeModule(ZZ, 2, name='M', start_index=1) sage: a = M.automorphism(name='a', latex_name=r'\alpha') ; a Automorphism a of the Rank-2 free module M over the Integer Ring sage: a.parent() General linear group of the Rank-2 free module M over the Integer Ring sage: a.parent() is M.general_linear_group() True sage: latex(a) \alpha
>>> from sage.all import * >>> M = FiniteRankFreeModule(ZZ, Integer(2), name='M', start_index=Integer(1)) >>> a = M.automorphism(name='a', latex_name=r'\alpha') ; a Automorphism a of the Rank-2 free module M over the Integer Ring >>> a.parent() General linear group of the Rank-2 free module M over the Integer Ring >>> a.parent() is M.general_linear_group() True >>> latex(a) \alpha
Setting the components of
a
w.r.t. a basis of moduleM
:sage: e = M.basis('e') ; e Basis (e_1,e_2) on the Rank-2 free module M over the Integer Ring sage: a[:] = [[1,2],[1,3]] sage: a.matrix(e) [1 2] [1 3] sage: a(e[1]).display() a(e_1) = e_1 + e_2 sage: a(e[2]).display() a(e_2) = 2 e_1 + 3 e_2
>>> from sage.all import * >>> e = M.basis('e') ; e Basis (e_1,e_2) on the Rank-2 free module M over the Integer Ring >>> a[:] = [[Integer(1),Integer(2)],[Integer(1),Integer(3)]] >>> a.matrix(e) [1 2] [1 3] >>> a(e[Integer(1)]).display() a(e_1) = e_1 + e_2 >>> a(e[Integer(2)]).display() a(e_2) = 2 e_1 + 3 e_2
Actually, the components w.r.t. a given basis can be specified at the construction of the object:
sage: a = M.automorphism(matrix=[[1,2],[1,3]], basis=e, name='a', ....: latex_name=r'\alpha') ; a Automorphism a of the Rank-2 free module M over the Integer Ring sage: a.matrix(e) [1 2] [1 3]
>>> from sage.all import * >>> a = M.automorphism(matrix=[[Integer(1),Integer(2)],[Integer(1),Integer(3)]], basis=e, name='a', ... latex_name=r'\alpha') ; a Automorphism a of the Rank-2 free module M over the Integer Ring >>> a.matrix(e) [1 2] [1 3]
Since e is the module’s default basis, it can be omitted in the argument list:
sage: a == M.automorphism(matrix=[[1,2],[1,3]], name='a', ....: latex_name=r'\alpha') True
>>> from sage.all import * >>> a == M.automorphism(matrix=[[Integer(1),Integer(2)],[Integer(1),Integer(3)]], name='a', ... latex_name=r'\alpha') True
The matrix of the automorphism can be obtained in any basis:
sage: f = M.basis('f', from_family=(3*e[1]+4*e[2], 5*e[1]+7*e[2])) ; f Basis (f_1,f_2) on the Rank-2 free module M over the Integer Ring sage: a.matrix(f) [2 3] [1 2]
>>> from sage.all import * >>> f = M.basis('f', from_family=(Integer(3)*e[Integer(1)]+Integer(4)*e[Integer(2)], Integer(5)*e[Integer(1)]+Integer(7)*e[Integer(2)])) ; f Basis (f_1,f_2) on the Rank-2 free module M over the Integer Ring >>> a.matrix(f) [2 3] [1 2]
Automorphisms are tensors of type \((1,1)\):
sage: a.tensor_type() (1, 1) sage: a.tensor_rank() 2
>>> from sage.all import * >>> a.tensor_type() (1, 1) >>> a.tensor_rank() 2
In particular, they can be displayed as such:
sage: a.display(e) a = e_1⊗e^1 + 2 e_1⊗e^2 + e_2⊗e^1 + 3 e_2⊗e^2 sage: a.display(f) a = 2 f_1⊗f^1 + 3 f_1⊗f^2 + f_2⊗f^1 + 2 f_2⊗f^2
>>> from sage.all import * >>> a.display(e) a = e_1⊗e^1 + 2 e_1⊗e^2 + e_2⊗e^1 + 3 e_2⊗e^2 >>> a.display(f) a = 2 f_1⊗f^1 + 3 f_1⊗f^2 + f_2⊗f^1 + 2 f_2⊗f^2
The automorphism acting on a module element:
sage: v = M([-2,3], name='v') ; v Element v of the Rank-2 free module M over the Integer Ring sage: a(v) Element a(v) of the Rank-2 free module M over the Integer Ring sage: a(v).display() a(v) = 4 e_1 + 7 e_2
>>> from sage.all import * >>> v = M([-Integer(2),Integer(3)], name='v') ; v Element v of the Rank-2 free module M over the Integer Ring >>> a(v) Element a(v) of the Rank-2 free module M over the Integer Ring >>> a(v).display() a(v) = 4 e_1 + 7 e_2
A second automorphism of the module
M
:sage: b = M.automorphism([[0,1],[-1,0]], name='b') ; b Automorphism b of the Rank-2 free module M over the Integer Ring sage: b.matrix(e) [ 0 1] [-1 0] sage: b(e[1]).display() b(e_1) = -e_2 sage: b(e[2]).display() b(e_2) = e_1
>>> from sage.all import * >>> b = M.automorphism([[Integer(0),Integer(1)],[-Integer(1),Integer(0)]], name='b') ; b Automorphism b of the Rank-2 free module M over the Integer Ring >>> b.matrix(e) [ 0 1] [-1 0] >>> b(e[Integer(1)]).display() b(e_1) = -e_2 >>> b(e[Integer(2)]).display() b(e_2) = e_1
The composition of automorphisms is performed via the multiplication operator:
sage: s = a*b ; s Automorphism of the Rank-2 free module M over the Integer Ring sage: s(v) == a(b(v)) True sage: s.matrix(f) [ 11 19] [ -7 -12] sage: s.matrix(f) == a.matrix(f) * b.matrix(f) True
>>> from sage.all import * >>> s = a*b ; s Automorphism of the Rank-2 free module M over the Integer Ring >>> s(v) == a(b(v)) True >>> s.matrix(f) [ 11 19] [ -7 -12] >>> s.matrix(f) == a.matrix(f) * b.matrix(f) True
It is not commutative:
sage: a*b != b*a True
>>> from sage.all import * >>> a*b != b*a True
In other words, the parent of
a
andb
, i.e. the group \(\mathrm{GL}(M)\), is not abelian:sage: M.general_linear_group() in CommutativeAdditiveGroups() False
>>> from sage.all import * >>> M.general_linear_group() in CommutativeAdditiveGroups() False
The neutral element for the composition law is the module identity map:
sage: id = M.identity_map() ; id Identity map of the Rank-2 free module M over the Integer Ring sage: id.parent() General linear group of the Rank-2 free module M over the Integer Ring sage: id(v) == v True sage: id.matrix(f) [1 0] [0 1] sage: id*a == a True sage: a*id == a True
>>> from sage.all import * >>> id = M.identity_map() ; id Identity map of the Rank-2 free module M over the Integer Ring >>> id.parent() General linear group of the Rank-2 free module M over the Integer Ring >>> id(v) == v True >>> id.matrix(f) [1 0] [0 1] >>> id*a == a True >>> a*id == a True
The inverse of an automorphism is obtained via the method
inverse()
, or the operator ~, or the exponent -1:sage: a.inverse() Automorphism a^(-1) of the Rank-2 free module M over the Integer Ring sage: a.inverse() is ~a True sage: a.inverse() is a^(-1) True sage: (a^(-1)).matrix(e) [ 3 -2] [-1 1] sage: a*a^(-1) == id True sage: a^(-1)*a == id True sage: a^(-1)*s == b True sage: (a^(-1))(a(v)) == v True
>>> from sage.all import * >>> a.inverse() Automorphism a^(-1) of the Rank-2 free module M over the Integer Ring >>> a.inverse() is ~a True >>> a.inverse() is a**(-Integer(1)) True >>> (a**(-Integer(1))).matrix(e) [ 3 -2] [-1 1] >>> a*a**(-Integer(1)) == id True >>> a**(-Integer(1))*a == id True >>> a**(-Integer(1))*s == b True >>> (a**(-Integer(1)))(a(v)) == v True
The module’s changes of basis are stored as automorphisms:
sage: M.change_of_basis(e,f) Automorphism of the Rank-2 free module M over the Integer Ring sage: M.change_of_basis(e,f).parent() General linear group of the Rank-2 free module M over the Integer Ring sage: M.change_of_basis(e,f).matrix(e) [3 5] [4 7] sage: M.change_of_basis(f,e) == M.change_of_basis(e,f).inverse() True
>>> from sage.all import * >>> M.change_of_basis(e,f) Automorphism of the Rank-2 free module M over the Integer Ring >>> M.change_of_basis(e,f).parent() General linear group of the Rank-2 free module M over the Integer Ring >>> M.change_of_basis(e,f).matrix(e) [3 5] [4 7] >>> M.change_of_basis(f,e) == M.change_of_basis(e,f).inverse() True
The opposite of an automorphism is still an automorphism:
sage: -a Automorphism -a of the Rank-2 free module M over the Integer Ring sage: (-a).parent() General linear group of the Rank-2 free module M over the Integer Ring sage: (-a).matrix(e) == - (a.matrix(e)) True
>>> from sage.all import * >>> -a Automorphism -a of the Rank-2 free module M over the Integer Ring >>> (-a).parent() General linear group of the Rank-2 free module M over the Integer Ring >>> (-a).matrix(e) == - (a.matrix(e)) True
Adding two automorphisms results in a generic type-\((1,1)\) tensor:
sage: s = a + b ; s Type-(1,1) tensor a+b on the Rank-2 free module M over the Integer Ring sage: s.parent() Free module of type-(1,1) tensors on the Rank-2 free module M over the Integer Ring sage: a[:], b[:], s[:] ( [1 2] [ 0 1] [1 3] [1 3], [-1 0], [0 3] )
>>> from sage.all import * >>> s = a + b ; s Type-(1,1) tensor a+b on the Rank-2 free module M over the Integer Ring >>> s.parent() Free module of type-(1,1) tensors on the Rank-2 free module M over the Integer Ring >>> a[:], b[:], s[:] ( [1 2] [ 0 1] [1 3] [1 3], [-1 0], [0 3] )
To get the result as an endomorphism, one has to explicitly convert it via the parent of endomorphisms, \(\mathrm{End}(M)\):
sage: s = End(M)(a+b) ; s Generic endomorphism of Rank-2 free module M over the Integer Ring sage: s(v) == a(v) + b(v) True sage: s.matrix(e) == a.matrix(e) + b.matrix(e) True sage: s.matrix(f) == a.matrix(f) + b.matrix(f) True
>>> from sage.all import * >>> s = End(M)(a+b) ; s Generic endomorphism of Rank-2 free module M over the Integer Ring >>> s(v) == a(v) + b(v) True >>> s.matrix(e) == a.matrix(e) + b.matrix(e) True >>> s.matrix(f) == a.matrix(f) + b.matrix(f) True
- add_comp(basis=None)[source]#
Return the components of
self
w.r.t. a given module basis for assignment, keeping the components w.r.t. other bases.To delete the components w.r.t. other bases, use the method
set_comp()
instead.INPUT:
basis
– (default:None
) basis in which the components are defined; if none is provided, the components are assumed to refer to the module’s default basis
Warning
If the automorphism has already components in other bases, it is the user’s responsibility to make sure that the components to be added are consistent with them.
OUTPUT:
components in the given basis, as an instance of the class
Components
; if such components did not exist previously, they are created
EXAMPLES:
Adding components to an automorphism of a rank-3 free \(\ZZ\)-module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') sage: a = M.automorphism(name='a') sage: a[e,:] = [[1,0,0],[0,-1,2],[0,1,-3]] sage: f = M.basis('f', from_family=(-e[0], 3*e[1]+4*e[2], ....: 5*e[1]+7*e[2])) ; f Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring sage: a.add_comp(f)[:] = [[1,0,0], [0, 80, 143], [0, -47, -84]]
>>> from sage.all import * >>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M') >>> e = M.basis('e') >>> a = M.automorphism(name='a') >>> a[e,:] = [[Integer(1),Integer(0),Integer(0)],[Integer(0),-Integer(1),Integer(2)],[Integer(0),Integer(1),-Integer(3)]] >>> f = M.basis('f', from_family=(-e[Integer(0)], Integer(3)*e[Integer(1)]+Integer(4)*e[Integer(2)], ... Integer(5)*e[Integer(1)]+Integer(7)*e[Integer(2)])) ; f Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring >>> a.add_comp(f)[:] = [[Integer(1),Integer(0),Integer(0)], [Integer(0), Integer(80), Integer(143)], [Integer(0), -Integer(47), -Integer(84)]]
The components in basis
e
have been kept:sage: a._components # random (dictionary output) {Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring: 2-indices components w.r.t. Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring, Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring: 2-indices components w.r.t. Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring}
>>> from sage.all import * >>> a._components # random (dictionary output) {Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring: 2-indices components w.r.t. Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring, Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring: 2-indices components w.r.t. Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring}
For the identity map, it is not permitted to invoke
add_comp()
:sage: id = M.identity_map() sage: id.add_comp(e) Traceback (most recent call last): ... ValueError: the components of the identity map cannot be changed
>>> from sage.all import * >>> id = M.identity_map() >>> id.add_comp(e) Traceback (most recent call last): ... ValueError: the components of the identity map cannot be changed
Indeed, the components are set automatically:
sage: id.comp(e) Kronecker delta of size 3x3 sage: id.comp(f) Kronecker delta of size 3x3
>>> from sage.all import * >>> id.comp(e) Kronecker delta of size 3x3 >>> id.comp(f) Kronecker delta of size 3x3
- characteristic_polynomial()[source]#
Return the characteristic polynomial of
self
.characteristic_polynomial()
andcharpoly()
are the same method.INPUT:
var
– string (default:'x'
); a variable name
EXAMPLES:
sage: M = FiniteRankFreeModule(QQ, 2, name='M') sage: e = M.basis('e') sage: a = M.automorphism([[1,1],[0,2]], name='a') sage: a.matrix(e) [1 1] [0 2] sage: a.characteristic_polynomial() x^2 - 3*x + 2 sage: a.charpoly() x^2 - 3*x + 2 sage: a.charpoly('T') T^2 - 3*T + 2
>>> from sage.all import * >>> M = FiniteRankFreeModule(QQ, Integer(2), name='M') >>> e = M.basis('e') >>> a = M.automorphism([[Integer(1),Integer(1)],[Integer(0),Integer(2)]], name='a') >>> a.matrix(e) [1 1] [0 2] >>> a.characteristic_polynomial() x^2 - 3*x + 2 >>> a.charpoly() x^2 - 3*x + 2 >>> a.charpoly('T') T^2 - 3*T + 2
- charpoly()[source]#
Return the characteristic polynomial of
self
.characteristic_polynomial()
andcharpoly()
are the same method.INPUT:
var
– string (default:'x'
); a variable name
EXAMPLES:
sage: M = FiniteRankFreeModule(QQ, 2, name='M') sage: e = M.basis('e') sage: a = M.automorphism([[1,1],[0,2]], name='a') sage: a.matrix(e) [1 1] [0 2] sage: a.characteristic_polynomial() x^2 - 3*x + 2 sage: a.charpoly() x^2 - 3*x + 2 sage: a.charpoly('T') T^2 - 3*T + 2
>>> from sage.all import * >>> M = FiniteRankFreeModule(QQ, Integer(2), name='M') >>> e = M.basis('e') >>> a = M.automorphism([[Integer(1),Integer(1)],[Integer(0),Integer(2)]], name='a') >>> a.matrix(e) [1 1] [0 2] >>> a.characteristic_polynomial() x^2 - 3*x + 2 >>> a.charpoly() x^2 - 3*x + 2 >>> a.charpoly('T') T^2 - 3*T + 2
- det()[source]#
Return the determinant of
self
.OUTPUT:
element of the base ring of the module on which
self
is defined, equal to the determinant ofself
.
EXAMPLES:
Determinant of an automorphism on a \(\ZZ\)-module of rank 2:
sage: M = FiniteRankFreeModule(ZZ, 2, name='M') sage: e = M.basis('e') sage: a = M.automorphism([[4,7],[3,5]], name='a') sage: a.matrix(e) [4 7] [3 5] sage: a.det() -1 sage: det(a) -1 sage: ~a.det() # determinant of the inverse automorphism -1 sage: id = M.identity_map() sage: id.det() 1
>>> from sage.all import * >>> M = FiniteRankFreeModule(ZZ, Integer(2), name='M') >>> e = M.basis('e') >>> a = M.automorphism([[Integer(4),Integer(7)],[Integer(3),Integer(5)]], name='a') >>> a.matrix(e) [4 7] [3 5] >>> a.det() -1 >>> det(a) -1 >>> ~a.det() # determinant of the inverse automorphism -1 >>> id = M.identity_map() >>> id.det() 1
- determinant()[source]#
Return the determinant of
self
.OUTPUT:
element of the base ring of the module on which
self
is defined, equal to the determinant ofself
.
EXAMPLES:
Determinant of an automorphism on a \(\ZZ\)-module of rank 2:
sage: M = FiniteRankFreeModule(ZZ, 2, name='M') sage: e = M.basis('e') sage: a = M.automorphism([[4,7],[3,5]], name='a') sage: a.matrix(e) [4 7] [3 5] sage: a.det() -1 sage: det(a) -1 sage: ~a.det() # determinant of the inverse automorphism -1 sage: id = M.identity_map() sage: id.det() 1
>>> from sage.all import * >>> M = FiniteRankFreeModule(ZZ, Integer(2), name='M') >>> e = M.basis('e') >>> a = M.automorphism([[Integer(4),Integer(7)],[Integer(3),Integer(5)]], name='a') >>> a.matrix(e) [4 7] [3 5] >>> a.det() -1 >>> det(a) -1 >>> ~a.det() # determinant of the inverse automorphism -1 >>> id = M.identity_map() >>> id.det() 1
- fcp()[source]#
Return the factorization of the characteristic polynomial of
self
.INPUT:
var
– string (default:'x'
); a variable name
EXAMPLES:
sage: M = FiniteRankFreeModule(QQ, 2, name='M') sage: e = M.basis('e') sage: a = M.automorphism([[1,1],[0,2]], name='a') sage: a.matrix(e) [1 1] [0 2] sage: a.fcp() # needs sage.libs.pari (x - 2) * (x - 1) sage: a.fcp('T') # needs sage.libs.pari (T - 2) * (T - 1)
>>> from sage.all import * >>> M = FiniteRankFreeModule(QQ, Integer(2), name='M') >>> e = M.basis('e') >>> a = M.automorphism([[Integer(1),Integer(1)],[Integer(0),Integer(2)]], name='a') >>> a.matrix(e) [1 1] [0 2] >>> a.fcp() # needs sage.libs.pari (x - 2) * (x - 1) >>> a.fcp('T') # needs sage.libs.pari (T - 2) * (T - 1)
- inverse()[source]#
Return the inverse automorphism.
OUTPUT:
instance of
FreeModuleAutomorphism
representing the automorphism that is the inverse ofself
.
EXAMPLES:
Inverse of an automorphism of a rank-3 free module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') sage: a = M.automorphism(name='a') sage: a[e,:] = [[1,0,0],[0,-1,2],[0,1,-3]] sage: a.inverse() Automorphism a^(-1) of the Rank-3 free module M over the Integer Ring sage: a.inverse().parent() General linear group of the Rank-3 free module M over the Integer Ring
>>> from sage.all import * >>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M') >>> e = M.basis('e') >>> a = M.automorphism(name='a') >>> a[e,:] = [[Integer(1),Integer(0),Integer(0)],[Integer(0),-Integer(1),Integer(2)],[Integer(0),Integer(1),-Integer(3)]] >>> a.inverse() Automorphism a^(-1) of the Rank-3 free module M over the Integer Ring >>> a.inverse().parent() General linear group of the Rank-3 free module M over the Integer Ring
Check that
a.inverse()
is indeed the inverse automorphism:sage: a.inverse() * a Identity map of the Rank-3 free module M over the Integer Ring sage: a * a.inverse() Identity map of the Rank-3 free module M over the Integer Ring sage: a.inverse().inverse() == a True
>>> from sage.all import * >>> a.inverse() * a Identity map of the Rank-3 free module M over the Integer Ring >>> a * a.inverse() Identity map of the Rank-3 free module M over the Integer Ring >>> a.inverse().inverse() == a True
Another check is:
sage: a.inverse().matrix(e) [ 1 0 0] [ 0 -3 -2] [ 0 -1 -1] sage: a.inverse().matrix(e) == (a.matrix(e))^(-1) True
>>> from sage.all import * >>> a.inverse().matrix(e) [ 1 0 0] [ 0 -3 -2] [ 0 -1 -1] >>> a.inverse().matrix(e) == (a.matrix(e))**(-Integer(1)) True
The inverse is cached (as long as
a
is not modified):sage: a.inverse() is a.inverse() True
>>> from sage.all import * >>> a.inverse() is a.inverse() True
If
a
is modified, the inverse is automatically recomputed:sage: a[0,0] = -1 sage: a.matrix(e) [-1 0 0] [ 0 -1 2] [ 0 1 -3] sage: a.inverse().matrix(e) # compare with above [-1 0 0] [ 0 -3 -2] [ 0 -1 -1]
>>> from sage.all import * >>> a[Integer(0),Integer(0)] = -Integer(1) >>> a.matrix(e) [-1 0 0] [ 0 -1 2] [ 0 1 -3] >>> a.inverse().matrix(e) # compare with above [-1 0 0] [ 0 -3 -2] [ 0 -1 -1]
Shortcuts for
inverse()
are the operator~
and the exponent-1
:sage: ~a is a.inverse() True sage: (a)^(-1) is a.inverse() True
>>> from sage.all import * >>> ~a is a.inverse() True >>> (a)**(-Integer(1)) is a.inverse() True
The inverse of the identity map is of course itself:
sage: id = M.identity_map() sage: id.inverse() is id True
>>> from sage.all import * >>> id = M.identity_map() >>> id.inverse() is id True
and we have:
sage: a*(a)^(-1) == id True sage: (a)^(-1)*a == id True
>>> from sage.all import * >>> a*(a)**(-Integer(1)) == id True >>> (a)**(-Integer(1))*a == id True
If the name could cause some confusion, a bracket is added around the element before taking the inverse:
sage: c = M.automorphism(name='a^(-1)*b') sage: c[e,:] = [[1,0,0],[0,-1,1],[0,2,-1]] sage: c.inverse() Automorphism (a^(-1)*b)^(-1) of the Rank-3 free module M over the Integer Ring
>>> from sage.all import * >>> c = M.automorphism(name='a^(-1)*b') >>> c[e,:] = [[Integer(1),Integer(0),Integer(0)],[Integer(0),-Integer(1),Integer(1)],[Integer(0),Integer(2),-Integer(1)]] >>> c.inverse() Automorphism (a^(-1)*b)^(-1) of the Rank-3 free module M over the Integer Ring
- 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 free module on whichself
is defined; if none is provided, the module’s default basis is assumedbasis2
– (default:None
) basis of the free module on whichself
is defined; if none is provided,basis2
is set tobasis1
OUTPUT:
the matrix representing the automorphism
self
w.r.t to basesbasis1
andbasis2
; more precisely, the columns of this matrix are formed by the components w.r.t.basis2
of the images of the elements ofbasis1
.
EXAMPLES:
Matrices of an automorphism of a rank-3 free \(\ZZ\)-module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M', start_index=1) sage: e = M.basis('e') sage: a = M.automorphism([[-1,0,0],[0,1,2],[0,1,3]], name='a') sage: a.matrix(e) [-1 0 0] [ 0 1 2] [ 0 1 3] sage: a.matrix() [-1 0 0] [ 0 1 2] [ 0 1 3] sage: f = M.basis('f', from_family=(-e[2], 4*e[1]+3*e[3], 7*e[1]+5*e[3])) ; f Basis (f_1,f_2,f_3) on the Rank-3 free module M over the Integer Ring sage: a.matrix(f) [ 1 -6 -10] [ -7 83 140] [ 4 -48 -81]
>>> from sage.all import * >>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M', start_index=Integer(1)) >>> e = M.basis('e') >>> a = M.automorphism([[-Integer(1),Integer(0),Integer(0)],[Integer(0),Integer(1),Integer(2)],[Integer(0),Integer(1),Integer(3)]], name='a') >>> a.matrix(e) [-1 0 0] [ 0 1 2] [ 0 1 3] >>> a.matrix() [-1 0 0] [ 0 1 2] [ 0 1 3] >>> f = M.basis('f', from_family=(-e[Integer(2)], Integer(4)*e[Integer(1)]+Integer(3)*e[Integer(3)], Integer(7)*e[Integer(1)]+Integer(5)*e[Integer(3)])) ; f Basis (f_1,f_2,f_3) on the Rank-3 free module M over the Integer Ring >>> a.matrix(f) [ 1 -6 -10] [ -7 83 140] [ 4 -48 -81]
Check of the above matrix:
sage: a(f[1]).display(f) a(f_1) = f_1 - 7 f_2 + 4 f_3 sage: a(f[2]).display(f) a(f_2) = -6 f_1 + 83 f_2 - 48 f_3 sage: a(f[3]).display(f) a(f_3) = -10 f_1 + 140 f_2 - 81 f_3
>>> from sage.all import * >>> a(f[Integer(1)]).display(f) a(f_1) = f_1 - 7 f_2 + 4 f_3 >>> a(f[Integer(2)]).display(f) a(f_2) = -6 f_1 + 83 f_2 - 48 f_3 >>> a(f[Integer(3)]).display(f) a(f_3) = -10 f_1 + 140 f_2 - 81 f_3
Check of the change-of-basis formula:
sage: P = M.change_of_basis(e,f).matrix(e) sage: a.matrix(f) == P^(-1) * a.matrix(e) * P True
>>> from sage.all import * >>> P = M.change_of_basis(e,f).matrix(e) >>> a.matrix(f) == P**(-Integer(1)) * a.matrix(e) * P True
Check that the matrix of the product of two automorphisms is the product of their matrices:
sage: b = M.change_of_basis(e,f) ; b Automorphism of the Rank-3 free module M over the Integer Ring sage: b.matrix(e) [ 0 4 7] [-1 0 0] [ 0 3 5] sage: (a*b).matrix(e) == a.matrix(e) * b.matrix(e) True
>>> from sage.all import * >>> b = M.change_of_basis(e,f) ; b Automorphism of the Rank-3 free module M over the Integer Ring >>> b.matrix(e) [ 0 4 7] [-1 0 0] [ 0 3 5] >>> (a*b).matrix(e) == a.matrix(e) * b.matrix(e) True
Check that the matrix of the inverse automorphism is the inverse of the automorphism’s matrix:
sage: (~a).matrix(e) [-1 0 0] [ 0 3 -2] [ 0 -1 1] sage: (~a).matrix(e) == ~(a.matrix(e)) True
>>> from sage.all import * >>> (~a).matrix(e) [-1 0 0] [ 0 3 -2] [ 0 -1 1] >>> (~a).matrix(e) == ~(a.matrix(e)) True
Matrices of the identity map:
sage: id = M.identity_map() sage: id.matrix(e) [1 0 0] [0 1 0] [0 0 1] sage: id.matrix(f) [1 0 0] [0 1 0] [0 0 1]
>>> from sage.all import * >>> id = M.identity_map() >>> id.matrix(e) [1 0 0] [0 1 0] [0 0 1] >>> id.matrix(f) [1 0 0] [0 1 0] [0 0 1]
- minimal_polynomial()[source]#
Return the minimal polynomial of
self
.minimal_polynomial()
andminpoly()
are the same method.INPUT:
var
– string (default:'x'
); a variable name
EXAMPLES:
sage: M = FiniteRankFreeModule(GF(7), 3, name='M') sage: e = M.basis('e') sage: a = M.automorphism([[0,1,2], [-1,0,3], [2,4,1]], name='a') sage: a.minpoly() # needs sage.libs.pari x^3 + 6*x^2 + 6*x + 1 sage: a.minimal_polynomial() # needs sage.libs.pari x^3 + 6*x^2 + 6*x + 1 sage: a.minimal_polynomial('T') # needs sage.libs.pari T^3 + 6*T^2 + 6*T + 1
>>> from sage.all import * >>> M = FiniteRankFreeModule(GF(Integer(7)), Integer(3), name='M') >>> e = M.basis('e') >>> a = M.automorphism([[Integer(0),Integer(1),Integer(2)], [-Integer(1),Integer(0),Integer(3)], [Integer(2),Integer(4),Integer(1)]], name='a') >>> a.minpoly() # needs sage.libs.pari x^3 + 6*x^2 + 6*x + 1 >>> a.minimal_polynomial() # needs sage.libs.pari x^3 + 6*x^2 + 6*x + 1 >>> a.minimal_polynomial('T') # needs sage.libs.pari T^3 + 6*T^2 + 6*T + 1
- minpoly()[source]#
Return the minimal polynomial of
self
.minimal_polynomial()
andminpoly()
are the same method.INPUT:
var
– string (default:'x'
); a variable name
EXAMPLES:
sage: M = FiniteRankFreeModule(GF(7), 3, name='M') sage: e = M.basis('e') sage: a = M.automorphism([[0,1,2], [-1,0,3], [2,4,1]], name='a') sage: a.minpoly() # needs sage.libs.pari x^3 + 6*x^2 + 6*x + 1 sage: a.minimal_polynomial() # needs sage.libs.pari x^3 + 6*x^2 + 6*x + 1 sage: a.minimal_polynomial('T') # needs sage.libs.pari T^3 + 6*T^2 + 6*T + 1
>>> from sage.all import * >>> M = FiniteRankFreeModule(GF(Integer(7)), Integer(3), name='M') >>> e = M.basis('e') >>> a = M.automorphism([[Integer(0),Integer(1),Integer(2)], [-Integer(1),Integer(0),Integer(3)], [Integer(2),Integer(4),Integer(1)]], name='a') >>> a.minpoly() # needs sage.libs.pari x^3 + 6*x^2 + 6*x + 1 >>> a.minimal_polynomial() # needs sage.libs.pari x^3 + 6*x^2 + 6*x + 1 >>> a.minimal_polynomial('T') # needs sage.libs.pari T^3 + 6*T^2 + 6*T + 1
- set_comp(basis=None)[source]#
Return the components of
self
w.r.t. a given module basis for assignment.The components with respect to other bases are deleted, in order to avoid any inconsistency. To keep them, use the method
add_comp()
instead.INPUT:
basis
– (default:None
) basis in which the components are defined; if none is provided, the components are assumed to refer to the module’s default basis
OUTPUT:
components in the given basis, as an instance of the class
Components
; if such components did not exist previously, they are created.
EXAMPLES:
Setting the components of an automorphism of a rank-3 free \(\ZZ\)-module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') sage: a = M.automorphism(name='a') sage: a.set_comp(e) 2-indices components w.r.t. Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring sage: a.set_comp(e)[:] = [[1,0,0],[0,1,2],[0,1,3]] sage: a.matrix(e) [1 0 0] [0 1 2] [0 1 3]
>>> from sage.all import * >>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M') >>> e = M.basis('e') >>> a = M.automorphism(name='a') >>> a.set_comp(e) 2-indices components w.r.t. Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring >>> a.set_comp(e)[:] = [[Integer(1),Integer(0),Integer(0)],[Integer(0),Integer(1),Integer(2)],[Integer(0),Integer(1),Integer(3)]] >>> a.matrix(e) [1 0 0] [0 1 2] [0 1 3]
Since
e
is the module’s default basis, one has:sage: a.set_comp() is a.set_comp(e) True
>>> from sage.all import * >>> a.set_comp() is a.set_comp(e) True
The method
set_comp()
can be used to modify a single component:sage: a.set_comp(e)[0,0] = -1 sage: a.matrix(e) [-1 0 0] [ 0 1 2] [ 0 1 3]
>>> from sage.all import * >>> a.set_comp(e)[Integer(0),Integer(0)] = -Integer(1) >>> a.matrix(e) [-1 0 0] [ 0 1 2] [ 0 1 3]
A short cut to
set_comp()
is the bracket operator, with the basis as first argument:sage: a[e,:] = [[1,0,0],[0,-1,2],[0,1,-3]] sage: a.matrix(e) [ 1 0 0] [ 0 -1 2] [ 0 1 -3] sage: a[e,0,0] = -1 sage: a.matrix(e) [-1 0 0] [ 0 -1 2] [ 0 1 -3]
>>> from sage.all import * >>> a[e,:] = [[Integer(1),Integer(0),Integer(0)],[Integer(0),-Integer(1),Integer(2)],[Integer(0),Integer(1),-Integer(3)]] >>> a.matrix(e) [ 1 0 0] [ 0 -1 2] [ 0 1 -3] >>> a[e,Integer(0),Integer(0)] = -Integer(1) >>> a.matrix(e) [-1 0 0] [ 0 -1 2] [ 0 1 -3]
The call to
set_comp()
erases the components previously defined in other bases; to keep them, use the methodadd_comp()
instead:sage: f = M.basis('f', from_family=(-e[0], 3*e[1]+4*e[2], ....: 5*e[1]+7*e[2])) ; f Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring sage: a._components {Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring: 2-indices components w.r.t. Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring} sage: a.set_comp(f)[:] = [[-1,0,0], [0,1,0], [0,0,-1]]
>>> from sage.all import * >>> f = M.basis('f', from_family=(-e[Integer(0)], Integer(3)*e[Integer(1)]+Integer(4)*e[Integer(2)], ... Integer(5)*e[Integer(1)]+Integer(7)*e[Integer(2)])) ; f Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring >>> a._components {Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring: 2-indices components w.r.t. Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring} >>> a.set_comp(f)[:] = [[-Integer(1),Integer(0),Integer(0)], [Integer(0),Integer(1),Integer(0)], [Integer(0),Integer(0),-Integer(1)]]
The components w.r.t. basis
e
have been erased:sage: a._components {Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring: 2-indices components w.r.t. Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring}
>>> from sage.all import * >>> a._components {Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring: 2-indices components w.r.t. Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring}
Of course, they can be computed from those in basis
f
by means of a change-of-basis formula, via the methodcomp()
ormatrix()
:sage: a.matrix(e) [ -1 0 0] [ 0 41 -30] [ 0 56 -41]
>>> from sage.all import * >>> a.matrix(e) [ -1 0 0] [ 0 41 -30] [ 0 56 -41]
For the identity map, it is not permitted to set components:
sage: id = M.identity_map() sage: id.set_comp(e) Traceback (most recent call last): ... ValueError: the components of the identity map cannot be changed
>>> from sage.all import * >>> id = M.identity_map() >>> id.set_comp(e) Traceback (most recent call last): ... ValueError: the components of the identity map cannot be changed
Indeed, the components are set automatically:
sage: id.comp(e) Kronecker delta of size 3x3 sage: id.comp(f) Kronecker delta of size 3x3
>>> from sage.all import * >>> id.comp(e) Kronecker delta of size 3x3 >>> id.comp(f) Kronecker delta of size 3x3
- trace()[source]#
Return the trace of
self
.OUTPUT:
element of the base ring of the module on which
self
is defined, equal to the trace ofself
.
EXAMPLES:
Trace of an automorphism on a \(\ZZ\)-module of rank 2:
sage: M = FiniteRankFreeModule(ZZ, 2, name='M') sage: e = M.basis('e') sage: a = M.automorphism([[4,7],[3,5]], name='a') sage: a.matrix(e) [4 7] [3 5] sage: a.trace() 9 sage: id = M.identity_map() sage: id.trace() 2
>>> from sage.all import * >>> M = FiniteRankFreeModule(ZZ, Integer(2), name='M') >>> e = M.basis('e') >>> a = M.automorphism([[Integer(4),Integer(7)],[Integer(3),Integer(5)]], name='a') >>> a.matrix(e) [4 7] [3 5] >>> a.trace() 9 >>> id = M.identity_map() >>> id.trace() 2