Finitely Generated Matrix Groups#

This class is designed for computing with matrix groups defined by a finite set of generating matrices.

EXAMPLES:

sage: F = GF(3)
sage: gens = [matrix(F, 2, [1,0, -1,1]), matrix(F, 2, [1,1,0,1])]
sage: G = MatrixGroup(gens)
sage: G.conjugacy_classes_representatives()                                         # needs sage.libs.gap
(
[1 0]  [0 2]  [0 1]  [2 0]  [0 2]  [0 1]  [0 2]
[0 1], [1 1], [2 1], [0 2], [1 2], [2 2], [1 0]
)
>>> from sage.all import *
>>> F = GF(Integer(3))
>>> gens = [matrix(F, Integer(2), [Integer(1),Integer(0), -Integer(1),Integer(1)]), matrix(F, Integer(2), [Integer(1),Integer(1),Integer(0),Integer(1)])]
>>> G = MatrixGroup(gens)
>>> G.conjugacy_classes_representatives()                                         # needs sage.libs.gap
(
[1 0]  [0 2]  [0 1]  [2 0]  [0 2]  [0 1]  [0 2]
[0 1], [1 1], [2 1], [0 2], [1 2], [2 2], [1 0]
)

The finitely generated matrix groups can also be constructed as subgroups of matrix groups:

sage: SL2Z = SL(2, ZZ)
sage: S, T = SL2Z.gens()
sage: SL2Z.subgroup([T^2])
Subgroup with 1 generators (
[1 2]
[0 1]
) of Special Linear Group of degree 2 over Integer Ring
>>> from sage.all import *
>>> SL2Z = SL(Integer(2), ZZ)
>>> S, T = SL2Z.gens()
>>> SL2Z.subgroup([T**Integer(2)])
Subgroup with 1 generators (
[1 2]
[0 1]
) of Special Linear Group of degree 2 over Integer Ring

AUTHORS:

  • William Stein: initial version

  • David Joyner (2006-03-15): degree, base_ring, _contains_, list, random, order methods; examples

  • William Stein (2006-12): rewrite

  • David Joyner (2007-12): Added invariant_generators (with Martin Albrecht and Simon King)

  • David Joyner (2008-08): Added module_composition_factors (interface to GAP’s MeatAxe implementation) and as_permutation_group (returns isomorphic PermutationGroup).

  • Simon King (2010-05): Improve invariant_generators by using GAP for the construction of the Reynolds operator in Singular.

  • Volker Braun (2013-1) port to new Parent, libGAP.

  • Sebastian Oehms (2018-07): Added _permutation_group_element_ (Issue #25706)

  • Sebastian Oehms (2019-01): Revision of Issue #25706 (Issue #26903 and Issue #27143).

class sage.groups.matrix_gps.finitely_generated.FinitelyGeneratedMatrixGroup_generic(degree, base_ring, generator_matrices, category=None)[source]#

Bases: MatrixGroup_generic

gen(i)[source]#

Return the \(i\)-th generator.

OUTPUT: the \(i\)-th generator of the group

EXAMPLES:

sage: # needs sage.libs.gap
sage: H = GL(2, GF(3))
sage: h1, h2 = H([[1,0], [2,1]]), H([[1,1], [0,1]])
sage: G = H.subgroup([h1, h2])
sage: G.gen(0)
[1 0]
[2 1]
sage: G.gen(0).matrix() == h1.matrix()
True
>>> from sage.all import *
>>> # needs sage.libs.gap
>>> H = GL(Integer(2), GF(Integer(3)))
>>> h1, h2 = H([[Integer(1),Integer(0)], [Integer(2),Integer(1)]]), H([[Integer(1),Integer(1)], [Integer(0),Integer(1)]])
>>> G = H.subgroup([h1, h2])
>>> G.gen(Integer(0))
[1 0]
[2 1]
>>> G.gen(Integer(0)).matrix() == h1.matrix()
True
gens()[source]#

Return the generators of the matrix group.

EXAMPLES:

sage: F = GF(3); MS = MatrixSpace(F, 2, 2)
sage: gens = [MS([[1,0], [0,1]]), MS([[1,1], [0,1]])]
sage: G = MatrixGroup(gens)
sage: gens[0] in G
True
sage: gens = G.gens()
sage: gens[0] in G
True
sage: gens = [MS([[1,0], [0,1]]), MS([[1,1], [0,1]])]

sage: F = GF(5); MS = MatrixSpace(F, 2, 2)
sage: G = MatrixGroup([MS(1), MS([1,2, 3,4])])
sage: G
Matrix group over Finite Field of size 5 with 2 generators (
[1 0]  [1 2]
[0 1], [3 4]
)
sage: G.gens()
(
[1 0]  [1 2]
[0 1], [3 4]
)
>>> from sage.all import *
>>> F = GF(Integer(3)); MS = MatrixSpace(F, Integer(2), Integer(2))
>>> gens = [MS([[Integer(1),Integer(0)], [Integer(0),Integer(1)]]), MS([[Integer(1),Integer(1)], [Integer(0),Integer(1)]])]
>>> G = MatrixGroup(gens)
>>> gens[Integer(0)] in G
True
>>> gens = G.gens()
>>> gens[Integer(0)] in G
True
>>> gens = [MS([[Integer(1),Integer(0)], [Integer(0),Integer(1)]]), MS([[Integer(1),Integer(1)], [Integer(0),Integer(1)]])]

>>> F = GF(Integer(5)); MS = MatrixSpace(F, Integer(2), Integer(2))
>>> G = MatrixGroup([MS(Integer(1)), MS([Integer(1),Integer(2), Integer(3),Integer(4)])])
>>> G
Matrix group over Finite Field of size 5 with 2 generators (
[1 0]  [1 2]
[0 1], [3 4]
)
>>> G.gens()
(
[1 0]  [1 2]
[0 1], [3 4]
)
ngens()[source]#

Return the number of generators.

OUTPUT: integer; the number of generators

EXAMPLES:

sage: # needs sage.libs.gap
sage: H = GL(2, GF(3))
sage: h1, h2 = H([[1,0], [2,1]]), H([[1,1], [0,1]])
sage: G = H.subgroup([h1, h2])
sage: G.ngens()
2
>>> from sage.all import *
>>> # needs sage.libs.gap
>>> H = GL(Integer(2), GF(Integer(3)))
>>> h1, h2 = H([[Integer(1),Integer(0)], [Integer(2),Integer(1)]]), H([[Integer(1),Integer(1)], [Integer(0),Integer(1)]])
>>> G = H.subgroup([h1, h2])
>>> G.ngens()
2
sage.groups.matrix_gps.finitely_generated.MatrixGroup(*gens, **kwds)[source]#

Return the matrix group with given generators.

INPUT:

  • *gens – matrices, or a single list/tuple/iterable of matrices, or a matrix group

  • check – boolean keyword argument (default: True); whether to check that each matrix is invertible

EXAMPLES:

sage: F = GF(5)
sage: gens = [matrix(F, 2, [1,2, -1,1]), matrix(F,2, [1,1, 0,1])]
sage: G = MatrixGroup(gens); G
Matrix group over Finite Field of size 5 with 2 generators (
[1 2]  [1 1]
[4 1], [0 1]
)
>>> from sage.all import *
>>> F = GF(Integer(5))
>>> gens = [matrix(F, Integer(2), [Integer(1),Integer(2), -Integer(1),Integer(1)]), matrix(F,Integer(2), [Integer(1),Integer(1), Integer(0),Integer(1)])]
>>> G = MatrixGroup(gens); G
Matrix group over Finite Field of size 5 with 2 generators (
[1 2]  [1 1]
[4 1], [0 1]
)

In the second example, the generators are a matrix over \(\ZZ\), a matrix over a finite field, and the integer \(2\). Sage determines that they both canonically map to matrices over the finite field, so creates that matrix group there:

sage: gens = [matrix(2, [1,2, -1,1]), matrix(GF(7), 2, [1,1, 0,1]), 2]
sage: G = MatrixGroup(gens); G
Matrix group over Finite Field of size 7 with 3 generators (
[1 2]  [1 1]  [2 0]
[6 1], [0 1], [0 2]
)
>>> from sage.all import *
>>> gens = [matrix(Integer(2), [Integer(1),Integer(2), -Integer(1),Integer(1)]), matrix(GF(Integer(7)), Integer(2), [Integer(1),Integer(1), Integer(0),Integer(1)]), Integer(2)]
>>> G = MatrixGroup(gens); G
Matrix group over Finite Field of size 7 with 3 generators (
[1 2]  [1 1]  [2 0]
[6 1], [0 1], [0 2]
)

Each generator must be invertible:

sage: G = MatrixGroup([matrix(ZZ, 2, [1,2,3,4])])
Traceback (most recent call last):
...
ValueError: each generator must be an invertible matrix

sage: F = GF(5); MS = MatrixSpace(F, 2, 2)
sage: MatrixGroup([MS.0])
Traceback (most recent call last):
...
ValueError: each generator must be an invertible matrix
sage: MatrixGroup([MS.0], check=False)  # works formally but is mathematical nonsense
Matrix group over Finite Field of size 5 with 1 generators (
[1 0]
[0 0]
)
>>> from sage.all import *
>>> G = MatrixGroup([matrix(ZZ, Integer(2), [Integer(1),Integer(2),Integer(3),Integer(4)])])
Traceback (most recent call last):
...
ValueError: each generator must be an invertible matrix

>>> F = GF(Integer(5)); MS = MatrixSpace(F, Integer(2), Integer(2))
>>> MatrixGroup([MS.gen(0)])
Traceback (most recent call last):
...
ValueError: each generator must be an invertible matrix
>>> MatrixGroup([MS.gen(0)], check=False)  # works formally but is mathematical nonsense
Matrix group over Finite Field of size 5 with 1 generators (
[1 0]
[0 0]
)

Some groups are not supported, or do not have much functionality implemented:

sage: G = SL(0, QQ)
Traceback (most recent call last):
...
ValueError: the degree must be at least 1

sage: SL2C = SL(2, CC);  SL2C
Special Linear Group of degree 2 over Complex Field with 53 bits of precision
sage: SL2C.gens()
Traceback (most recent call last):
...
AttributeError: 'LinearMatrixGroup_generic_with_category' object has no attribute 'gens'...
>>> from sage.all import *
>>> G = SL(Integer(0), QQ)
Traceback (most recent call last):
...
ValueError: the degree must be at least 1

>>> SL2C = SL(Integer(2), CC);  SL2C
Special Linear Group of degree 2 over Complex Field with 53 bits of precision
>>> SL2C.gens()
Traceback (most recent call last):
...
AttributeError: 'LinearMatrixGroup_generic_with_category' object has no attribute 'gens'...
sage.groups.matrix_gps.finitely_generated.QuaternionMatrixGroupGF3()[source]#

The quaternion group as a set of \(2\times 2\) matrices over \(\GF{3}\).

OUTPUT:

A matrix group consisting of \(2\times 2\) matrices with elements from the finite field of order 3. The group is the quaternion group, the nonabelian group of order 8 that is not isomorphic to the group of symmetries of a square (the dihedral group \(D_4\)).

Note

This group is most easily available via groups.matrix.QuaternionGF3().

EXAMPLES:

The generators are the matrix representations of the elements commonly called \(I\) and \(J\), while \(K\) is the product of \(I\) and \(J\).

sage: from sage.groups.matrix_gps.finitely_generated import QuaternionMatrixGroupGF3

sage: # needs sage.libs.gap
sage: Q = QuaternionMatrixGroupGF3()
sage: Q.order()
8
sage: aye = Q.gens()[0]; aye
[1 1]
[1 2]
sage: jay = Q.gens()[1]; jay
[2 1]
[1 1]
sage: kay = aye*jay; kay
[0 2]
[1 0]
>>> from sage.all import *
>>> from sage.groups.matrix_gps.finitely_generated import QuaternionMatrixGroupGF3

>>> # needs sage.libs.gap
>>> Q = QuaternionMatrixGroupGF3()
>>> Q.order()
8
>>> aye = Q.gens()[Integer(0)]; aye
[1 1]
[1 2]
>>> jay = Q.gens()[Integer(1)]; jay
[2 1]
[1 1]
>>> kay = aye*jay; kay
[0 2]
[1 0]
sage.groups.matrix_gps.finitely_generated.normalize_square_matrices(matrices)[source]#

Find a common space for all matrices.

OUTPUT: a list of matrices, all elements of the same matrix space

EXAMPLES:

sage: from sage.groups.matrix_gps.finitely_generated import normalize_square_matrices
sage: m1 = [[1,2], [3,4]]
sage: m2 = [2, 3, 4, 5]
sage: m3 = matrix(QQ, [[1/2,1/3], [1/4,1/5]])
sage: m4 = MatrixGroup(m3).gen(0)
sage: normalize_square_matrices([m1, m2, m3, m4])
[
[1 2]  [2 3]  [1/2 1/3]  [1/2 1/3]
[3 4], [4 5], [1/4 1/5], [1/4 1/5]
]
>>> from sage.all import *
>>> from sage.groups.matrix_gps.finitely_generated import normalize_square_matrices
>>> m1 = [[Integer(1),Integer(2)], [Integer(3),Integer(4)]]
>>> m2 = [Integer(2), Integer(3), Integer(4), Integer(5)]
>>> m3 = matrix(QQ, [[Integer(1)/Integer(2),Integer(1)/Integer(3)], [Integer(1)/Integer(4),Integer(1)/Integer(5)]])
>>> m4 = MatrixGroup(m3).gen(Integer(0))
>>> normalize_square_matrices([m1, m2, m3, m4])
[
[1 2]  [2 3]  [1/2 1/3]  [1/2 1/3]
[3 4], [4 5], [1/4 1/5], [1/4 1/5]
]