Orthogonal Linear Groups#
The general orthogonal group
In characteristics different from 2, a quadratic form is equivalent to
a bilinear symmetric form. Furthermore, over the real numbers a
positive definite quadratic form is equivalent to the diagonal
quadratic form, equivalent to the bilinear symmetric form defined by
the identity matrix. Hence, the orthogonal group
In the case of a finite field and if the degree e
must be specified to disambiguate these two possibilities. The index
of
Warning
GAP and Sage use different notations:
GAP notation: The optional
e
comes first, that is,GO([e,] d, q)
,SO([e,] d, q)
.Sage notation: The optional
e
comes last, the standard Python convention:GO(d, GF(q), e=0)
,SO(d, GF(q), e=0)
.
EXAMPLES:
sage: GO(3,7)
General Orthogonal Group of degree 3 over Finite Field of size 7
sage: G = SO(4, GF(7), 1); G
Special Orthogonal Group of degree 4 and form parameter 1
over Finite Field of size 7
sage: # needs sage.libs.gap
sage: G.random_element() # random
[4 3 5 2]
[6 6 4 0]
[0 4 6 0]
[4 4 5 1]
GO(3,7) G = SO(4, GF(7), 1); G # needs sage.libs.gap G.random_element() # random
>>> from sage.all import *
>>> GO(Integer(3),Integer(7))
General Orthogonal Group of degree 3 over Finite Field of size 7
>>> G = SO(Integer(4), GF(Integer(7)), Integer(1)); G
Special Orthogonal Group of degree 4 and form parameter 1
over Finite Field of size 7
>>> # needs sage.libs.gap
>>> G.random_element() # random
[4 3 5 2]
[6 6 4 0]
[0 4 6 0]
[4 4 5 1]
AUTHORS:
David Joyner (2006-03): initial version
David Joyner (2006-05): added examples, _latex_, __str__, gens, as_matrix_group
William Stein (2006-12-09): rewrite
Volker Braun (2013-1) port to new Parent, libGAP, extreme refactoring.
Sebastian Oehms (2018-8) add
invariant_form()
(as alias),_OG
, option for user defined invariant bilinear form, and bug-fix in cmd-string for calling GAP (see Issue #26028)
- sage.groups.matrix_gps.orthogonal.GO(n, R, e=0, var='a', invariant_form=None)[source]#
Return the general orthogonal group.
The general orthogonal group
consists of all matrices over the ring preserving an -ary positive definite quadratic form. In cases where there are multiple non-isomorphic quadratic forms, additional data needs to be specified to disambiguate.In the case of a finite field and if the degree
is even, then there are two inequivalent quadratic forms and a third parametere
must be specified to disambiguate these two possibilities.Note
This group is also available via
groups.matrix.GO()
.INPUT:
n
– integer; the degreeR
– ring or an integer; if an integer is specified, the corresponding finite field is usede
–+1
or-1
, and ignored by default; only relevant for finite fields and if the degree is even: a parameter that distinguishes inequivalent invariant formsvar
– (default:'a'
) variable used to represent generator of the finite field, if neededinvariant_form
– (optional) instances being accepted by the matrix-constructor which define a square matrix overR
describing the symmetric form to be kept invariant by the orthogonal group; the form is checked to be non-degenerate and symmetric but not to be positive definite
OUTPUT: the general orthogonal group of given degree, base ring, and choice of invariant form
EXAMPLES:
sage: GO(3, GF(7)) General Orthogonal Group of degree 3 over Finite Field of size 7 sage: # needs sage.libs.gap sage: GO(3, GF(7)).order() 672 sage: GO(3, GF(7)).gens() ( [3 0 0] [0 1 0] [0 5 0] [1 6 6] [0 0 1], [0 2 1] )
GO(3, GF(7)) # needs sage.libs.gap GO(3, GF(7)).order() GO(3, GF(7)).gens()
>>> from sage.all import * >>> GO(Integer(3), GF(Integer(7))) General Orthogonal Group of degree 3 over Finite Field of size 7 >>> # needs sage.libs.gap >>> GO(Integer(3), GF(Integer(7))).order() 672 >>> GO(Integer(3), GF(Integer(7))).gens() ( [3 0 0] [0 1 0] [0 5 0] [1 6 6] [0 0 1], [0 2 1] )
Using the
invariant_form
option:sage: m = matrix(QQ, 3, 3, [[0, 1, 0], [1, 0, 0], [0, 0, 3]]) sage: GO3 = GO(3, QQ) sage: GO3m = GO(3, QQ, invariant_form=m) sage: GO3 == GO3m False sage: GO3.invariant_form() [1 0 0] [0 1 0] [0 0 1] sage: GO3m.invariant_form() [0 1 0] [1 0 0] [0 0 3] sage: pm = Permutation([2,3,1]).to_matrix() sage: g = GO3(pm); g in GO3; g True [0 0 1] [1 0 0] [0 1 0] sage: GO3m(pm) Traceback (most recent call last): ... TypeError: matrix must be orthogonal with respect to the symmetric form [0 1 0] [1 0 0] [0 0 3] sage: GO(3,3, invariant_form=[[1,0,0], [0,2,0], [0,0,1]]) Traceback (most recent call last): ... NotImplementedError: invariant_form for finite groups is fixed by GAP sage: 5 + 5 10 sage: R.<x> = ZZ[] sage: GO(2, R, invariant_form=[[x,0], [0,1]]) General Orthogonal Group of degree 2 over Univariate Polynomial Ring in x over Integer Ring with respect to symmetric form [x 0] [0 1]
m = matrix(QQ, 3, 3, [[0, 1, 0], [1, 0, 0], [0, 0, 3]]) GO3 = GO(3, QQ) GO3m = GO(3, QQ, invariant_form=m) GO3 == GO3m GO3.invariant_form() GO3m.invariant_form() pm = Permutation([2,3,1]).to_matrix() g = GO3(pm); g in GO3; g GO3m(pm) GO(3,3, invariant_form=[[1,0,0], [0,2,0], [0,0,1]]) 5 + 5 R.<x> = ZZ[] GO(2, R, invariant_form=[[x,0], [0,1]])
>>> from sage.all import * >>> m = matrix(QQ, Integer(3), Integer(3), [[Integer(0), Integer(1), Integer(0)], [Integer(1), Integer(0), Integer(0)], [Integer(0), Integer(0), Integer(3)]]) >>> GO3 = GO(Integer(3), QQ) >>> GO3m = GO(Integer(3), QQ, invariant_form=m) >>> GO3 == GO3m False >>> GO3.invariant_form() [1 0 0] [0 1 0] [0 0 1] >>> GO3m.invariant_form() [0 1 0] [1 0 0] [0 0 3] >>> pm = Permutation([Integer(2),Integer(3),Integer(1)]).to_matrix() >>> g = GO3(pm); g in GO3; g True [0 0 1] [1 0 0] [0 1 0] >>> GO3m(pm) Traceback (most recent call last): ... TypeError: matrix must be orthogonal with respect to the symmetric form [0 1 0] [1 0 0] [0 0 3] >>> GO(Integer(3),Integer(3), invariant_form=[[Integer(1),Integer(0),Integer(0)], [Integer(0),Integer(2),Integer(0)], [Integer(0),Integer(0),Integer(1)]]) Traceback (most recent call last): ... NotImplementedError: invariant_form for finite groups is fixed by GAP >>> Integer(5) + Integer(5) 10 >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> GO(Integer(2), R, invariant_form=[[x,Integer(0)], [Integer(0),Integer(1)]]) General Orthogonal Group of degree 2 over Univariate Polynomial Ring in x over Integer Ring with respect to symmetric form [x 0] [0 1]
- class sage.groups.matrix_gps.orthogonal.OrthogonalMatrixGroup_generic(degree, base_ring, special, sage_name, latex_string, category=None, invariant_form=None)[source]#
Bases:
NamedMatrixGroup_generic
General Orthogonal Group over arbitrary rings.
EXAMPLES:
sage: G = GO(3, GF(7)); G General Orthogonal Group of degree 3 over Finite Field of size 7 sage: latex(G) \text{GO}_{3}(\Bold{F}_{7}) sage: G = SO(3, GF(5)); G Special Orthogonal Group of degree 3 over Finite Field of size 5 sage: latex(G) \text{SO}_{3}(\Bold{F}_{5}) sage: # needs sage.rings.number_field sage: CF3 = CyclotomicField(3); e3 = CF3.gen() sage: m = matrix(CF3, 3,3, [[1,e3,0],[e3,2,0],[0,0,1]]) sage: G = SO(3, CF3, invariant_form=m) sage: latex(G) \text{SO}_{3}(\Bold{Q}(\zeta_{3}))\text{ with respect to non positive definite symmetric form }\left(\begin{array}{rrr} 1 & \zeta_{3} & 0 \\ \zeta_{3} & 2 & 0 \\ 0 & 0 & 1 \end{array}\right)
G = GO(3, GF(7)); G latex(G) G = SO(3, GF(5)); G latex(G) # needs sage.rings.number_field CF3 = CyclotomicField(3); e3 = CF3.gen() m = matrix(CF3, 3,3, [[1,e3,0],[e3,2,0],[0,0,1]]) G = SO(3, CF3, invariant_form=m) latex(G)
>>> from sage.all import * >>> G = GO(Integer(3), GF(Integer(7))); G General Orthogonal Group of degree 3 over Finite Field of size 7 >>> latex(G) \text{GO}_{3}(\Bold{F}_{7}) >>> G = SO(Integer(3), GF(Integer(5))); G Special Orthogonal Group of degree 3 over Finite Field of size 5 >>> latex(G) \text{SO}_{3}(\Bold{F}_{5}) >>> # needs sage.rings.number_field >>> CF3 = CyclotomicField(Integer(3)); e3 = CF3.gen() >>> m = matrix(CF3, Integer(3),Integer(3), [[Integer(1),e3,Integer(0)],[e3,Integer(2),Integer(0)],[Integer(0),Integer(0),Integer(1)]]) >>> G = SO(Integer(3), CF3, invariant_form=m) >>> latex(G) \text{SO}_{3}(\Bold{Q}(\zeta_{3}))\text{ with respect to non positive definite symmetric form }\left(\begin{array}{rrr} 1 & \zeta_{3} & 0 \\ \zeta_{3} & 2 & 0 \\ 0 & 0 & 1 \end{array}\right)
- invariant_bilinear_form()[source]#
Return the symmetric bilinear form preserved by
self
.OUTPUT: a matrix
EXAMPLES:
sage: # needs sage.libs.gap sage: GO(2,3,+1).invariant_bilinear_form() [0 1] [1 0] sage: GO(2,3,-1).invariant_bilinear_form() [2 1] [1 1] sage: G = GO(4, QQ) sage: G.invariant_bilinear_form() [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] sage: GO3m = GO(3, QQ, invariant_form=(1,0,0, 0,2,0, 0,0,3)) sage: GO3m.invariant_bilinear_form() [1 0 0] [0 2 0] [0 0 3]
# needs sage.libs.gap GO(2,3,+1).invariant_bilinear_form() GO(2,3,-1).invariant_bilinear_form() G = GO(4, QQ) G.invariant_bilinear_form() GO3m = GO(3, QQ, invariant_form=(1,0,0, 0,2,0, 0,0,3)) GO3m.invariant_bilinear_form()
>>> from sage.all import * >>> # needs sage.libs.gap >>> GO(Integer(2),Integer(3),+Integer(1)).invariant_bilinear_form() [0 1] [1 0] >>> GO(Integer(2),Integer(3),-Integer(1)).invariant_bilinear_form() [2 1] [1 1] >>> G = GO(Integer(4), QQ) >>> G.invariant_bilinear_form() [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] >>> GO3m = GO(Integer(3), QQ, invariant_form=(Integer(1),Integer(0),Integer(0), Integer(0),Integer(2),Integer(0), Integer(0),Integer(0),Integer(3))) >>> GO3m.invariant_bilinear_form() [1 0 0] [0 2 0] [0 0 3]
- invariant_form()[source]#
Return the symmetric bilinear form preserved by
self
.OUTPUT: a matrix
EXAMPLES:
sage: # needs sage.libs.gap sage: GO(2,3,+1).invariant_bilinear_form() [0 1] [1 0] sage: GO(2,3,-1).invariant_bilinear_form() [2 1] [1 1] sage: G = GO(4, QQ) sage: G.invariant_bilinear_form() [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] sage: GO3m = GO(3, QQ, invariant_form=(1,0,0, 0,2,0, 0,0,3)) sage: GO3m.invariant_bilinear_form() [1 0 0] [0 2 0] [0 0 3]
# needs sage.libs.gap GO(2,3,+1).invariant_bilinear_form() GO(2,3,-1).invariant_bilinear_form() G = GO(4, QQ) G.invariant_bilinear_form() GO3m = GO(3, QQ, invariant_form=(1,0,0, 0,2,0, 0,0,3)) GO3m.invariant_bilinear_form()
>>> from sage.all import * >>> # needs sage.libs.gap >>> GO(Integer(2),Integer(3),+Integer(1)).invariant_bilinear_form() [0 1] [1 0] >>> GO(Integer(2),Integer(3),-Integer(1)).invariant_bilinear_form() [2 1] [1 1] >>> G = GO(Integer(4), QQ) >>> G.invariant_bilinear_form() [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] >>> GO3m = GO(Integer(3), QQ, invariant_form=(Integer(1),Integer(0),Integer(0), Integer(0),Integer(2),Integer(0), Integer(0),Integer(0),Integer(3))) >>> GO3m.invariant_bilinear_form() [1 0 0] [0 2 0] [0 0 3]
- invariant_quadratic_form()[source]#
Return the symmetric bilinear form preserved by
self
.OUTPUT: a matrix
EXAMPLES:
sage: # needs sage.libs.gap sage: GO(2,3,+1).invariant_bilinear_form() [0 1] [1 0] sage: GO(2,3,-1).invariant_bilinear_form() [2 1] [1 1] sage: G = GO(4, QQ) sage: G.invariant_bilinear_form() [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] sage: GO3m = GO(3, QQ, invariant_form=(1,0,0, 0,2,0, 0,0,3)) sage: GO3m.invariant_bilinear_form() [1 0 0] [0 2 0] [0 0 3]
# needs sage.libs.gap GO(2,3,+1).invariant_bilinear_form() GO(2,3,-1).invariant_bilinear_form() G = GO(4, QQ) G.invariant_bilinear_form() GO3m = GO(3, QQ, invariant_form=(1,0,0, 0,2,0, 0,0,3)) GO3m.invariant_bilinear_form()
>>> from sage.all import * >>> # needs sage.libs.gap >>> GO(Integer(2),Integer(3),+Integer(1)).invariant_bilinear_form() [0 1] [1 0] >>> GO(Integer(2),Integer(3),-Integer(1)).invariant_bilinear_form() [2 1] [1 1] >>> G = GO(Integer(4), QQ) >>> G.invariant_bilinear_form() [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] >>> GO3m = GO(Integer(3), QQ, invariant_form=(Integer(1),Integer(0),Integer(0), Integer(0),Integer(2),Integer(0), Integer(0),Integer(0),Integer(3))) >>> GO3m.invariant_bilinear_form() [1 0 0] [0 2 0] [0 0 3]
- sage.groups.matrix_gps.orthogonal.SO(n, R, e=None, var='a', invariant_form=None)[source]#
Return the special orthogonal group.
The special orthogonal group
consists of all matrices with determinant one over the ring preserving an -ary positive definite quadratic form. In cases where there are multiple non-isomorphic quadratic forms, additional data needs to be specified to disambiguate.Note
This group is also available via
groups.matrix.SO()
.INPUT:
n
– integer; the degreeR
– ring or an integer; if an integer is specified, the corresponding finite field is usede
–+1
or-1
, and ignored by default; only relevant for finite fields and if the degree is even: a parameter that distinguishes inequivalent invariant formsvar
– (default:'a'
) variable used to represent generator of the finite field, if neededinvariant_form
– (optional) instances being accepted by the matrix-constructor which define a square matrix overR
describing the symmetric form to be kept invariant by the orthogonal group; the form is checked to be non-degenerate and symmetric but not to be positive definite
OUTPUT: the special orthogonal group of given degree, base ring, and choice of invariant form
EXAMPLES:
sage: G = SO(3,GF(5)); G Special Orthogonal Group of degree 3 over Finite Field of size 5 sage: # needs sage.libs.gap sage: G = SO(3,GF(5)) sage: G.gens() ( [2 0 0] [3 2 3] [1 4 4] [0 3 0] [0 2 0] [4 0 0] [0 0 1], [0 3 1], [2 0 4] ) sage: G.as_matrix_group() Matrix group over Finite Field of size 5 with 3 generators ( [2 0 0] [3 2 3] [1 4 4] [0 3 0] [0 2 0] [4 0 0] [0 0 1], [0 3 1], [2 0 4] )
G = SO(3,GF(5)); G # needs sage.libs.gap G = SO(3,GF(5)) G.gens() G.as_matrix_group()
>>> from sage.all import * >>> G = SO(Integer(3),GF(Integer(5))); G Special Orthogonal Group of degree 3 over Finite Field of size 5 >>> # needs sage.libs.gap >>> G = SO(Integer(3),GF(Integer(5))) >>> G.gens() ( [2 0 0] [3 2 3] [1 4 4] [0 3 0] [0 2 0] [4 0 0] [0 0 1], [0 3 1], [2 0 4] ) >>> G.as_matrix_group() Matrix group over Finite Field of size 5 with 3 generators ( [2 0 0] [3 2 3] [1 4 4] [0 3 0] [0 2 0] [4 0 0] [0 0 1], [0 3 1], [2 0 4] )
Using the
invariant_form
option:sage: # needs sage.rings.number_field sage: CF3 = CyclotomicField(3); e3 = CF3.gen() sage: m = matrix(CF3, 3, 3, [[1,e3,0], [e3,2,0], [0,0,1]]) sage: SO3 = SO(3, CF3) sage: SO3m = SO(3, CF3, invariant_form=m) sage: SO3 == SO3m False sage: SO3.invariant_form() [1 0 0] [0 1 0] [0 0 1] sage: SO3m.invariant_form() [ 1 zeta3 0] [zeta3 2 0] [ 0 0 1] sage: pm = Permutation([2,3,1]).to_matrix() sage: g = SO3(pm); g in SO3; g True [0 0 1] [1 0 0] [0 1 0] sage: SO3m(pm) Traceback (most recent call last): ... TypeError: matrix must be orthogonal with respect to the symmetric form [ 1 zeta3 0] [zeta3 2 0] [ 0 0 1] sage: SO(3, 5, invariant_form=[[1,0,0], [0,2,0], [0,0,3]]) Traceback (most recent call last): ... NotImplementedError: invariant_form for finite groups is fixed by GAP sage: 5+5 10
# needs sage.rings.number_field CF3 = CyclotomicField(3); e3 = CF3.gen() m = matrix(CF3, 3, 3, [[1,e3,0], [e3,2,0], [0,0,1]]) SO3 = SO(3, CF3) SO3m = SO(3, CF3, invariant_form=m) SO3 == SO3m SO3.invariant_form() SO3m.invariant_form() pm = Permutation([2,3,1]).to_matrix() g = SO3(pm); g in SO3; g SO3m(pm) SO(3, 5, invariant_form=[[1,0,0], [0,2,0], [0,0,3]]) 5+5
>>> from sage.all import * >>> # needs sage.rings.number_field >>> CF3 = CyclotomicField(Integer(3)); e3 = CF3.gen() >>> m = matrix(CF3, Integer(3), Integer(3), [[Integer(1),e3,Integer(0)], [e3,Integer(2),Integer(0)], [Integer(0),Integer(0),Integer(1)]]) >>> SO3 = SO(Integer(3), CF3) >>> SO3m = SO(Integer(3), CF3, invariant_form=m) >>> SO3 == SO3m False >>> SO3.invariant_form() [1 0 0] [0 1 0] [0 0 1] >>> SO3m.invariant_form() [ 1 zeta3 0] [zeta3 2 0] [ 0 0 1] >>> pm = Permutation([Integer(2),Integer(3),Integer(1)]).to_matrix() >>> g = SO3(pm); g in SO3; g True [0 0 1] [1 0 0] [0 1 0] >>> SO3m(pm) Traceback (most recent call last): ... TypeError: matrix must be orthogonal with respect to the symmetric form [ 1 zeta3 0] [zeta3 2 0] [ 0 0 1] >>> SO(Integer(3), Integer(5), invariant_form=[[Integer(1),Integer(0),Integer(0)], [Integer(0),Integer(2),Integer(0)], [Integer(0),Integer(0),Integer(3)]]) Traceback (most recent call last): ... NotImplementedError: invariant_form for finite groups is fixed by GAP >>> Integer(5)+Integer(5) 10
- sage.groups.matrix_gps.orthogonal.normalize_args_e(degree, ring, e)[source]#
Normalize the arguments that relate the choice of quadratic form for special orthogonal groups over finite fields.
INPUT:
degree
– integer; the degree of the affine group, that is, the dimension of the affine space the group is acting onring
– a ring; the base ring of the affine spacee
– integer, one of , , . Only relevant for finite fields and if the degree is even. A parameter that distinguishes inequivalent invariant forms.
OUTPUT: the integer
e
with values required by GAP