Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/groups/matrix_gps/orthogonal.py
4069 views
1
r"""
2
Orthogonal Linear Groups
3
4
Paraphrased from the GAP manual: The general orthogonal group
5
`GO(e,d,q)` consists of those `d\times d` matrices
6
over the field `GF(q)` that respect a non-singular
7
quadratic form specified by `e`. (Use the GAP command
8
InvariantQuadraticForm to determine this form explicitly.) The
9
value of `e` must be `0` for odd `d` (and
10
can optionally be omitted in this case), respectively one of
11
`1` or `-1` for even `d`.
12
13
SpecialOrthogonalGroup returns a group isomorphic to the special
14
orthogonal group `SO(e,d,q)`, which is the subgroup of all
15
those matrices in the general orthogonal group that have
16
determinant one. (The index of `SO(e,d,q)` in
17
`GO(e,d,q)` is `2` if `q` is odd, but
18
`SO(e,d,q) = GO(e,d,q)` if `q` is even.)
19
20
.. warning::
21
22
GAP notation: GO([e,] d, q), SO([e,] d, q) ([...] denotes and
23
optional value)
24
25
Sage notation: GO(d, GF(q), e=0), SO( d, GF(q), e=0)
26
27
There is no Python trick I know of to allow the first argument to
28
have the default value e=0 and leave the other two arguments as
29
non-default. This forces us into non-standard notation.
30
31
AUTHORS:
32
33
- David Joyner (2006-03): initial version
34
35
- David Joyner (2006-05): added examples, _latex_, __str__, gens,
36
as_matrix_group
37
38
- William Stein (2006-12-09): rewrite
39
"""
40
41
#*****************************************************************************
42
# Copyright (C) 2006 David Joyner and William Stein
43
#
44
# Distributed under the terms of the GNU General Public License (GPL)
45
# http://www.gnu.org/licenses/
46
#*****************************************************************************
47
48
from sage.rings.all import is_FiniteField, Integer, FiniteField
49
from matrix_group import MatrixGroup_gap, MatrixGroup_gap_finite_field
50
51
from sage.interfaces.gap import gap
52
53
def SO(n, R, e=0, var='a'):
54
"""
55
Return the special orthogonal group of degree `n` over the
56
ring `R`.
57
58
INPUT:
59
60
61
- ``n`` - the degree
62
63
- ``R`` - ring
64
65
- ``e`` - a parameter for orthogonal groups only
66
depending on the invariant form
67
68
69
EXAMPLES::
70
71
sage: G = SO(3,GF(5))
72
sage: G.gens()
73
[
74
[2 0 0]
75
[0 3 0]
76
[0 0 1],
77
[3 2 3]
78
[0 2 0]
79
[0 3 1],
80
[1 4 4]
81
[4 0 0]
82
[2 0 4]
83
]
84
sage: G = SO(3,GF(5))
85
sage: G.as_matrix_group()
86
Matrix group over Finite Field of size 5 with 3 generators:
87
[[[2, 0, 0], [0, 3, 0], [0, 0, 1]], [[3, 2, 3], [0, 2, 0], [0, 3, 1]], [[1, 4, 4], [4, 0, 0], [2, 0, 4]]]
88
"""
89
if isinstance(R, (int, long, Integer)):
90
R = FiniteField(R, var)
91
if n%2!=0 and e != 0:
92
raise ValueError, "must have e = 0 for n even"
93
if n%2 == 0 and e**2 != 1:
94
raise ValueError, "must have e=-1 or e=1 if n is even"
95
if is_FiniteField(R):
96
return SpecialOrthogonalGroup_finite_field(n, R, e)
97
else:
98
return SpecialOrthogonalGroup_generic(n, R, e)
99
100
class OrthogonalGroup(MatrixGroup_gap):
101
def __init__(self, n, R, e=0, var='a'):
102
"""
103
INPUT:
104
105
106
- ``n`` - the degree
107
108
- ``R`` - the base ring
109
110
- ``e`` - a parameter for orthogonal groups only
111
depending on the invariant form
112
113
- ``var`` - variable used to define field of
114
definition of actual matrices in this group.
115
"""
116
MatrixGroup_gap.__init__(self, n, R, var)
117
self.__form = e
118
119
def invariant_form(self):
120
"""
121
Return the invariant form of this orthogonal group.
122
123
TODO: What is the point of this? What does it do? How does it
124
work?
125
126
EXAMPLES::
127
128
sage: G = SO( 4, GF(7), 1)
129
sage: G.invariant_form()
130
1
131
"""
132
return self.__form
133
134
class SpecialOrthogonalGroup_generic(OrthogonalGroup):
135
"""
136
EXAMPLES::
137
138
sage: G = SO( 4, GF(7), 1); G
139
Special Orthogonal Group of degree 4, form parameter 1, over the Finite Field of size 7
140
sage: G._gap_init_()
141
'SO(1, 4, 7)'
142
sage: G.random_element()
143
[1 2 5 0]
144
[2 2 1 0]
145
[1 3 1 5]
146
[1 3 1 3]
147
"""
148
def _gap_init_(self):
149
"""
150
EXAMPLES::
151
152
sage: G = SO(3,GF(5))
153
sage: G._gap_init_()
154
'SO(0, 3, 5)'
155
"""
156
return "SO(%s, %s, %s)"%( self.invariant_form(), self.degree(), self.base_ring().order())
157
158
def _repr_(self):
159
"""
160
EXAMPLES::
161
162
sage: G = SO(3,GF(5))
163
sage: G
164
Special Orthogonal Group of degree 3, form parameter 0, over the Finite Field of size 5
165
"""
166
return "Special Orthogonal Group of degree %s, form parameter %s, over the %s"%( self.degree(), self.invariant_form(), self.base_ring())
167
168
def _latex_(self):
169
"""
170
EXAMPLES::
171
172
sage: G = SO(3,GF(5))
173
sage: latex(G)
174
\text{SO}_{3}(\Bold{F}_{5}, 0)
175
"""
176
return "\\text{SO}_{%s}(%s, %s)"%(self.degree(), self.base_ring()._latex_(), self.invariant_form())
177
178
def invariant_quadratic_form(self):
179
r"""
180
Return the quadratic form `q(v) = v Q v^t` on the space on
181
which this group `G` that satisfies the equation
182
`q(v) = q(v M)` for all `v \in V` and
183
`M \in G`.
184
185
.. note::
186
187
Uses GAP's command InvariantQuadraticForm.
188
189
OUTPUT:
190
191
192
- ``Q`` - matrix that defines the invariant quadratic
193
form.
194
195
196
EXAMPLES::
197
198
sage: G = SO( 4, GF(7), 1)
199
sage: G.invariant_quadratic_form()
200
[0 1 0 0]
201
[0 0 0 0]
202
[0 0 3 0]
203
[0 0 0 1]
204
"""
205
F = self.base_ring()
206
I = gap(self).InvariantQuadraticForm()
207
Q = I.attribute('matrix')
208
return Q._matrix_(F)
209
210
211
class SpecialOrthogonalGroup_finite_field(SpecialOrthogonalGroup_generic, MatrixGroup_gap_finite_field):
212
pass
213
214
215
########################################################################
216
# General Orthogonal Group
217
########################################################################
218
219
def GO( n , R , e=0 ):
220
"""
221
Return the general orthogonal group.
222
223
EXAMPLES:
224
"""
225
if n%2!=0 and e!=0:
226
raise ValueError, "if e = 0, then n must be even."
227
if n%2 == 0 and e**2!=1:
228
raise ValueError, "must have e=-1 or e=1, if d is even."
229
if isinstance(R, (int, long, Integer)):
230
R = FiniteField(R)
231
if is_FiniteField(R):
232
return GeneralOrthogonalGroup_finite_field(n, R, e)
233
else:
234
return GeneralOrthogonalGroup_generic(n, R, e)
235
236
class GeneralOrthogonalGroup_generic(OrthogonalGroup):
237
"""
238
EXAMPLES::
239
240
sage: GO( 3, GF(7), 0)
241
General Orthogonal Group of degree 3, form parameter 0, over the Finite Field of size 7
242
sage: GO( 3, GF(7), 0).order()
243
672
244
sage: GO( 3, GF(7), 0).random_element()
245
[5 1 4]
246
[1 0 0]
247
[6 0 1]
248
"""
249
def _gap_init_(self):
250
"""
251
EXAMPLES::
252
253
sage: GO( 3, GF(7), 0)._gap_init_()
254
'GO(0, 3, 7)'
255
"""
256
return "GO(%s, %s, %s)"%( self.invariant_form(), self.degree(), (self.base_ring()).order() )
257
258
def _repr_(self):
259
"""
260
String representation of self.
261
262
EXAMPLES::
263
264
sage: GO(3,7)
265
General Orthogonal Group of degree 3, form parameter 0, over the Finite Field of size 7
266
"""
267
return "General Orthogonal Group of degree %s, form parameter %s, over the %s"%( self.degree(), self.invariant_form(), self.base_ring())
268
269
def _latex_(self):
270
"""
271
EXAMPLES::
272
273
sage: G = GO(3,GF(5))
274
sage: latex(G)
275
\text{GO}_{3}(5, 0)
276
"""
277
return "\\text{GO}_{%s}(%s, %s)"%( self.degree(), self.base_ring().order(),self.invariant_form() )
278
279
def invariant_quadratic_form(self):
280
"""
281
This wraps GAP's command "InvariantQuadraticForm". From the GAP
282
documentation:
283
284
INPUT:
285
286
287
- ``self`` - a matrix group G
288
289
290
OUTPUT:
291
292
293
- ``Q`` - the matrix satisfying the property: The
294
quadratic form q on the natural vector space V on which G acts is
295
given by `q(v) = v Q v^t`, and the invariance under G is
296
given by the equation `q(v) = q(v M)` for all
297
`v \in V` and `M \in G`.
298
299
300
EXAMPLES::
301
302
sage: G = GO( 4, GF(7), 1)
303
sage: G.invariant_quadratic_form()
304
[0 1 0 0]
305
[0 0 0 0]
306
[0 0 3 0]
307
[0 0 0 1]
308
"""
309
F = self.base_ring()
310
G = self._gap_init_()
311
cmd = "r := InvariantQuadraticForm("+G+")"
312
gap.eval(cmd)
313
cmd = "r.matrix"
314
Q = gap(cmd)
315
return Q._matrix_(F)
316
317
class GeneralOrthogonalGroup_finite_field(GeneralOrthogonalGroup_generic, MatrixGroup_gap_finite_field):
318
pass
319
320
321