General linear group of a free module#

The set \(\mathrm{GL}(M)\) of automorphisms (i.e. invertible endomorphisms) of a free module of finite rank \(M\) is a group under composition of automorphisms, named the general linear group of \(M\). In other words, \(\mathrm{GL}(M)\) is the group of units (i.e. invertible elements) of \(\mathrm{End}(M)\), the endomorphism ring of \(M\).

The group \(\mathrm{GL}(M)\) is implemented via the class FreeModuleLinearGroup.

AUTHORS:

  • Eric Gourgoulhon (2015): initial version

  • Michael Jung (2019): improve treatment of the identity element

REFERENCES:

  • Chap. 15 of R. Godement : Algebra [God1968]

class sage.tensor.modules.free_module_linear_group.FreeModuleLinearGroup(fmodule)[source]#

Bases: UniqueRepresentation, Parent

General linear group of a free module of finite rank over a commutative ring.

Given a free module of finite rank \(M\) over a commutative ring \(R\), the general linear group of \(M\) is the group \(\mathrm{GL}(M)\) of automorphisms (i.e. invertible endomorphisms) of \(M\). It is the group of units (i.e. invertible elements) of \(\mathrm{End}(M)\), the endomorphism ring of \(M\).

This is a Sage parent class, whose element class is FreeModuleAutomorphism.

INPUT:

  • fmodule – free module \(M\) of finite rank over a commutative ring \(R\), as an instance of FiniteRankFreeModule

EXAMPLES:

General linear group of a free \(\ZZ\)-module of rank 3:

sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: e = M.basis('e')
sage: from sage.tensor.modules.free_module_linear_group import FreeModuleLinearGroup
sage: GL = FreeModuleLinearGroup(M) ; GL
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')
>>> from sage.tensor.modules.free_module_linear_group import FreeModuleLinearGroup
>>> GL = FreeModuleLinearGroup(M) ; GL
General linear group of the Rank-3 free module M over the Integer Ring

Instead of importing FreeModuleLinearGroup in the global name space, it is recommended to use the module’s method general_linear_group():

sage: GL = M.general_linear_group() ; GL
General linear group of the Rank-3 free module M over the Integer Ring
sage: latex(GL)
\mathrm{GL}\left( M \right)
>>> from sage.all import *
>>> GL = M.general_linear_group() ; GL
General linear group of the Rank-3 free module M over the Integer Ring
>>> latex(GL)
\mathrm{GL}\left( M \right)

As most parents, the general linear group has a unique instance:

sage: GL is M.general_linear_group()
True
>>> from sage.all import *
>>> GL is M.general_linear_group()
True

\(\mathrm{GL}(M)\) is in the category of groups:

sage: GL.category()
Category of groups
sage: GL in Groups()
True
>>> from sage.all import *
>>> GL.category()
Category of groups
>>> GL in Groups()
True

GL is a parent object, whose elements are automorphisms of \(M\), represented by instances of the class FreeModuleAutomorphism:

sage: GL.Element
<class 'sage.tensor.modules.free_module_automorphism.FreeModuleAutomorphism'>
sage: a = GL.an_element() ; a
Automorphism of the Rank-3 free module M over the Integer Ring
sage: a.matrix(e)
[ 1  0  0]
[ 0 -1  0]
[ 0  0  1]
sage: a in GL
True
sage: GL.is_parent_of(a)
True
>>> from sage.all import *
>>> GL.Element
<class 'sage.tensor.modules.free_module_automorphism.FreeModuleAutomorphism'>
>>> a = GL.an_element() ; a
Automorphism of the Rank-3 free module M over the Integer Ring
>>> a.matrix(e)
[ 1  0  0]
[ 0 -1  0]
[ 0  0  1]
>>> a in GL
True
>>> GL.is_parent_of(a)
True

As an endomorphism, a maps elements of \(M\) to elements of \(M\):

sage: v = M.an_element() ; v
Element of the Rank-3 free module M over the Integer Ring
sage: v.display()
e_0 + e_1 + e_2
sage: a(v)
Element of the Rank-3 free module M over the Integer Ring
sage: a(v).display()
e_0 - e_1 + e_2
>>> from sage.all import *
>>> v = M.an_element() ; v
Element of the Rank-3 free module M over the Integer Ring
>>> v.display()
e_0 + e_1 + e_2
>>> a(v)
Element of the Rank-3 free module M over the Integer Ring
>>> a(v).display()
e_0 - e_1 + e_2

An automorphism can also be viewed as a tensor of type \((1,1)\) on \(M\):

sage: a.tensor_type()
(1, 1)
sage: a.display(e)
e_0⊗e^0 - e_1⊗e^1 + e_2⊗e^2
sage: type(a)
<class 'sage.tensor.modules.free_module_linear_group.FreeModuleLinearGroup_with_category.element_class'>
>>> from sage.all import *
>>> a.tensor_type()
(1, 1)
>>> a.display(e)
e_0⊗e^0 - e_1⊗e^1 + e_2⊗e^2
>>> type(a)
<class 'sage.tensor.modules.free_module_linear_group.FreeModuleLinearGroup_with_category.element_class'>

As for any group, the identity element is obtained by the method one():

sage: id = GL.one() ; id
Identity map of the Rank-3 free module M over the Integer Ring
sage: id*a == a
True
sage: a*id == a
True
sage: a*a^(-1) == id
True
sage: a^(-1)*a == id
True
>>> from sage.all import *
>>> id = GL.one() ; id
Identity map of the Rank-3 free module M over the Integer Ring
>>> id*a == a
True
>>> a*id == a
True
>>> a*a**(-Integer(1)) == id
True
>>> a**(-Integer(1))*a == id
True

The identity element is of course the identity map of the module \(M\):

sage: id(v) == v
True
sage: id.matrix(e)
[1 0 0]
[0 1 0]
[0 0 1]
>>> from sage.all import *
>>> id(v) == v
True
>>> id.matrix(e)
[1 0 0]
[0 1 0]
[0 0 1]

The module’s changes of basis are stored as elements of the general linear group:

sage: f = M.basis('f', from_family=(-e[1], 4*e[0]+3*e[2], 7*e[0]+5*e[2]))
sage: f
Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring
sage: M.change_of_basis(e,f)
Automorphism of the Rank-3 free module M over the Integer Ring
sage: M.change_of_basis(e,f) in GL
True
sage: M.change_of_basis(e,f).parent()
General linear group of the Rank-3 free module M over the Integer Ring
sage: M.change_of_basis(e,f).matrix(e)
[ 0  4  7]
[-1  0  0]
[ 0  3  5]
sage: M.change_of_basis(e,f) == M.change_of_basis(f,e).inverse()
True
>>> from sage.all import *
>>> f = M.basis('f', from_family=(-e[Integer(1)], Integer(4)*e[Integer(0)]+Integer(3)*e[Integer(2)], Integer(7)*e[Integer(0)]+Integer(5)*e[Integer(2)]))
>>> f
Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring
>>> M.change_of_basis(e,f)
Automorphism of the Rank-3 free module M over the Integer Ring
>>> M.change_of_basis(e,f) in GL
True
>>> M.change_of_basis(e,f).parent()
General linear group of the Rank-3 free module M over the Integer Ring
>>> M.change_of_basis(e,f).matrix(e)
[ 0  4  7]
[-1  0  0]
[ 0  3  5]
>>> M.change_of_basis(e,f) == M.change_of_basis(f,e).inverse()
True

Since every automorphism is an endomorphism, there is a coercion \(\mathrm{GL}(M) \rightarrow \mathrm{End}(M)\) (the endomorphism ring of module \(M\)):

sage: End(M).has_coerce_map_from(GL)
True
>>> from sage.all import *
>>> End(M).has_coerce_map_from(GL)
True

(see FreeModuleHomset for details), but not in the reverse direction, since only bijective endomorphisms are automorphisms:

sage: GL.has_coerce_map_from(End(M))
False
>>> from sage.all import *
>>> GL.has_coerce_map_from(End(M))
False

A bijective endomorphism can be converted to an element of \(\mathrm{GL}(M)\):

sage: h = M.endomorphism([[1,0,0], [0,-1,2], [0,1,-3]]) ; h
Generic endomorphism of Rank-3 free module M over the Integer Ring
sage: h.parent() is End(M)
True
sage: ah = GL(h) ; ah
Automorphism of the Rank-3 free module M over the Integer Ring
sage: ah.parent() is GL
True
>>> from sage.all import *
>>> h = M.endomorphism([[Integer(1),Integer(0),Integer(0)], [Integer(0),-Integer(1),Integer(2)], [Integer(0),Integer(1),-Integer(3)]]) ; h
Generic endomorphism of Rank-3 free module M over the Integer Ring
>>> h.parent() is End(M)
True
>>> ah = GL(h) ; ah
Automorphism of the Rank-3 free module M over the Integer Ring
>>> ah.parent() is GL
True

As maps \(M\rightarrow M\), ah and h are identical:

sage: v  # recall
Element of the Rank-3 free module M over the Integer Ring
sage: ah(v) == h(v)
True
sage: ah.matrix(e) == h.matrix(e)
True
>>> from sage.all import *
>>> v  # recall
Element of the Rank-3 free module M over the Integer Ring
>>> ah(v) == h(v)
True
>>> ah.matrix(e) == h.matrix(e)
True

Of course, non-invertible endomorphisms cannot be converted to elements of \(\mathrm{GL}(M)\):

sage: GL(M.endomorphism([[0,0,0], [0,-1,2], [0,1,-3]]))
Traceback (most recent call last):
...
TypeError: the Generic endomorphism of Rank-3 free module M over the
 Integer Ring is not invertible
>>> from sage.all import *
>>> GL(M.endomorphism([[Integer(0),Integer(0),Integer(0)], [Integer(0),-Integer(1),Integer(2)], [Integer(0),Integer(1),-Integer(3)]]))
Traceback (most recent call last):
...
TypeError: the Generic endomorphism of Rank-3 free module M over the
 Integer Ring is not invertible

Similarly, there is a coercion \(\mathrm{GL}(M)\rightarrow T^{(1,1)}(M)\) (module of type-\((1,1)\) tensors):

sage: M.tensor_module(1,1).has_coerce_map_from(GL)
True
>>> from sage.all import *
>>> M.tensor_module(Integer(1),Integer(1)).has_coerce_map_from(GL)
True

(see TensorFreeModule for details), but not in the reverse direction, since not every type-\((1,1)\) tensor can be considered as an automorphism:

sage: GL.has_coerce_map_from(M.tensor_module(1,1))
False
>>> from sage.all import *
>>> GL.has_coerce_map_from(M.tensor_module(Integer(1),Integer(1)))
False

Invertible type-\((1,1)\) tensors can be converted to automorphisms:

sage: t = M.tensor((1,1), name='t')
sage: t[e,:] = [[-1,0,0], [0,1,2], [0,1,3]]
sage: at = GL(t) ; at
Automorphism t of the Rank-3 free module M over the Integer Ring
sage: at.matrix(e)
[-1  0  0]
[ 0  1  2]
[ 0  1  3]
sage: at.matrix(e) == t[e,:]
True
>>> from sage.all import *
>>> t = M.tensor((Integer(1),Integer(1)), name='t')
>>> t[e,:] = [[-Integer(1),Integer(0),Integer(0)], [Integer(0),Integer(1),Integer(2)], [Integer(0),Integer(1),Integer(3)]]
>>> at = GL(t) ; at
Automorphism t of the Rank-3 free module M over the Integer Ring
>>> at.matrix(e)
[-1  0  0]
[ 0  1  2]
[ 0  1  3]
>>> at.matrix(e) == t[e,:]
True

Non-invertible ones cannot:

sage: t0 = M.tensor((1,1), name='t_0')
sage: t0[e,0,0] = 1
sage: t0[e,:]  # the matrix is clearly not invertible
[1 0 0]
[0 0 0]
[0 0 0]
sage: GL(t0)
Traceback (most recent call last):
...
TypeError: the Type-(1,1) tensor t_0 on the Rank-3 free module M over
 the Integer Ring is not invertible
sage: t0[e,1,1], t0[e,2,2] = 2, 3
sage: t0[e,:]  # the matrix is not invertible in Mat_3(ZZ)
[1 0 0]
[0 2 0]
[0 0 3]
sage: GL(t0)
Traceback (most recent call last):
...
TypeError: the Type-(1,1) tensor t_0 on the Rank-3 free module M over
 the Integer Ring is not invertible
>>> from sage.all import *
>>> t0 = M.tensor((Integer(1),Integer(1)), name='t_0')
>>> t0[e,Integer(0),Integer(0)] = Integer(1)
>>> t0[e,:]  # the matrix is clearly not invertible
[1 0 0]
[0 0 0]
[0 0 0]
>>> GL(t0)
Traceback (most recent call last):
...
TypeError: the Type-(1,1) tensor t_0 on the Rank-3 free module M over
 the Integer Ring is not invertible
>>> t0[e,Integer(1),Integer(1)], t0[e,Integer(2),Integer(2)] = Integer(2), Integer(3)
>>> t0[e,:]  # the matrix is not invertible in Mat_3(ZZ)
[1 0 0]
[0 2 0]
[0 0 3]
>>> GL(t0)
Traceback (most recent call last):
...
TypeError: the Type-(1,1) tensor t_0 on the Rank-3 free module M over
 the Integer Ring is not invertible
Element[source]#

alias of FreeModuleAutomorphism

base_module()[source]#

Return the free module of which self is the general linear group.

OUTPUT:

  • instance of FiniteRankFreeModule representing the free module of which self is the general linear group

EXAMPLES:

sage: M = FiniteRankFreeModule(ZZ, 2, name='M')
sage: GL = M.general_linear_group()
sage: GL.base_module()
Rank-2 free module M over the Integer Ring
sage: GL.base_module() is M
True
>>> from sage.all import *
>>> M = FiniteRankFreeModule(ZZ, Integer(2), name='M')
>>> GL = M.general_linear_group()
>>> GL.base_module()
Rank-2 free module M over the Integer Ring
>>> GL.base_module() is M
True
one()[source]#

Return the group identity element of self.

The group identity element is nothing but the module identity map.

OUTPUT:

EXAMPLES:

Identity element of the general linear group of a rank-2 free module:

sage: M = FiniteRankFreeModule(ZZ, 2, name='M', start_index=1)
sage: GL = M.general_linear_group()
sage: GL.one()
Identity map of the Rank-2 free module M over the Integer Ring
>>> from sage.all import *
>>> M = FiniteRankFreeModule(ZZ, Integer(2), name='M', start_index=Integer(1))
>>> GL = M.general_linear_group()
>>> GL.one()
Identity map of the Rank-2 free module M over the Integer Ring

The identity element is cached:

sage: GL.one() is GL.one()
True
>>> from sage.all import *
>>> GL.one() is GL.one()
True

Check that the element returned is indeed the neutral element for the group law:

sage: e = M.basis('e')
sage: a = GL([[3,4],[5,7]], basis=e) ; a
Automorphism of the Rank-2 free module M over the Integer Ring
sage: a.matrix(e)
[3 4]
[5 7]
sage: GL.one() * a == a
True
sage: a * GL.one() == a
True
sage: a * a^(-1) == GL.one()
True
sage: a^(-1) * a == GL.one()
True
>>> from sage.all import *
>>> e = M.basis('e')
>>> a = GL([[Integer(3),Integer(4)],[Integer(5),Integer(7)]], basis=e) ; a
Automorphism of the Rank-2 free module M over the Integer Ring
>>> a.matrix(e)
[3 4]
[5 7]
>>> GL.one() * a == a
True
>>> a * GL.one() == a
True
>>> a * a**(-Integer(1)) == GL.one()
True
>>> a**(-Integer(1)) * a == GL.one()
True

The unit element of \(\mathrm{GL}(M)\) is the identity map of \(M\):

sage: GL.one()(e[1])
Element e_1 of the Rank-2 free module M over the Integer Ring
sage: GL.one()(e[2])
Element e_2 of the Rank-2 free module M over the Integer Ring
>>> from sage.all import *
>>> GL.one()(e[Integer(1)])
Element e_1 of the Rank-2 free module M over the Integer Ring
>>> GL.one()(e[Integer(2)])
Element e_2 of the Rank-2 free module M over the Integer Ring

Its matrix is the identity matrix in any basis:

sage: GL.one().matrix(e)
[1 0]
[0 1]
sage: f = M.basis('f', from_family=(e[1]+2*e[2], e[1]+3*e[2]))
sage: GL.one().matrix(f)
[1 0]
[0 1]
>>> from sage.all import *
>>> GL.one().matrix(e)
[1 0]
[0 1]
>>> f = M.basis('f', from_family=(e[Integer(1)]+Integer(2)*e[Integer(2)], e[Integer(1)]+Integer(3)*e[Integer(2)]))
>>> GL.one().matrix(f)
[1 0]
[0 1]