Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/groups/matrix_gps/morphism.py
8815 views
1
"""
2
Homomorphisms Between Matrix Groups
3
4
AUTHORS:
5
6
- David Joyner and William Stein (2006-03): initial version
7
8
- David Joyner (2006-05): examples
9
10
- Simon King (2011-01): cleaning and improving code
11
12
- Volker Braun (2013-1) port to new Parent, libGAP.
13
"""
14
15
#*****************************************************************************
16
# Copyright (C) 2006 David Joyner and William Stein <[email protected]>
17
#
18
# Distributed under the terms of the GNU General Public License (GPL)
19
# as published by the Free Software Foundation; either version 2 of
20
# the License, or (at your option) any later version.
21
# http://www.gnu.org/licenses/
22
#*****************************************************************************
23
24
from sage.categories.morphism import Morphism
25
from sage.misc.latex import latex
26
27
28
def to_libgap(x):
29
"""
30
Helper to convert ``x`` to a LibGAP matrix or matrix group
31
element.
32
33
EXAMPLES::
34
35
sage: from sage.groups.matrix_gps.morphism import to_libgap
36
sage: to_libgap(GL(2,3).gen(0))
37
[ [ Z(3), 0*Z(3) ], [ 0*Z(3), Z(3)^0 ] ]
38
sage: to_libgap(matrix(QQ, [[1,2],[3,4]]))
39
[ [ 1, 2 ], [ 3, 4 ] ]
40
"""
41
try:
42
return x.gap()
43
except AttributeError:
44
from sage.libs.gap.libgap import libgap
45
return libgap(x)
46
47
48
class MatrixGroupMap(Morphism):
49
50
def __init__(self, parent):
51
"""
52
Set-theoretic map between matrix groups.
53
54
EXAMPLES::
55
56
sage: from sage.groups.matrix_gps.morphism import MatrixGroupMap
57
sage: MatrixGroupMap(ZZ.Hom(ZZ)) # mathematical nonsense
58
MatrixGroup endomorphism of Integer Ring
59
"""
60
Morphism.__init__(self, parent)
61
62
def _repr_type(self):
63
"""
64
Part of the implementation of :meth:`_repr_`
65
66
EXAMPLES::
67
68
sage: from sage.groups.matrix_gps.morphism import MatrixGroupMap
69
sage: MatrixGroupMap(ZZ.Hom(ZZ))._repr_type()
70
'MatrixGroup'
71
"""
72
return "MatrixGroup"
73
74
75
class MatrixGroupMorphism(MatrixGroupMap):
76
pass
77
78
79
class MatrixGroupMorphism_im_gens(MatrixGroupMorphism):
80
81
def __init__(self, homset, imgsH, check=True):
82
"""
83
Group morphism specified by images of generators.
84
85
Some Python code for wrapping GAP's GroupHomomorphismByImages
86
function but only for matrix groups. Can be expensive if G is
87
large.
88
89
EXAMPLES::
90
91
sage: F = GF(5); MS = MatrixSpace(F,2,2)
92
sage: G = MatrixGroup([MS([1,1,0,1])])
93
sage: H = MatrixGroup([MS([1,0,1,1])])
94
sage: phi = G.hom(H.gens())
95
sage: phi
96
Homomorphism : Matrix group over Finite Field of size 5 with 1 generators (
97
[1 1]
98
[0 1]
99
) --> Matrix group over Finite Field of size 5 with 1 generators (
100
[1 0]
101
[1 1]
102
)
103
sage: phi(MS([1,1,0,1]))
104
[1 0]
105
[1 1]
106
sage: F = GF(7); MS = MatrixSpace(F,2,2)
107
sage: F.multiplicative_generator()
108
3
109
sage: G = MatrixGroup([MS([3,0,0,1])])
110
sage: a = G.gens()[0]^2
111
sage: phi = G.hom([a])
112
"""
113
MatrixGroupMorphism.__init__(self, homset) # sets the parent
114
from sage.libs.gap.libgap import libgap
115
G = homset.domain()
116
H = homset.codomain()
117
gens = [x.gap() for x in G.gens()]
118
imgs = [to_libgap(x) for x in imgsH]
119
self._phi = phi = libgap.GroupHomomorphismByImages(G.gap(), H.gap(), gens, imgs)
120
if not phi.IsGroupHomomorphism():
121
raise ValueError('The map '+str(gensG)+'-->'+str(imgsH)+' is not a homomorphism')
122
123
def gap(self):
124
"""
125
Return the underlying LibGAP group homomorphism
126
127
OUTPUT:
128
129
A LibGAP element.
130
131
EXAMPLES::
132
133
sage: F = GF(5); MS = MatrixSpace(F,2,2)
134
sage: G = MatrixGroup([MS([1,1,0,1])])
135
sage: H = MatrixGroup([MS([1,0,1,1])])
136
sage: phi = G.hom(H.gens())
137
sage: phi.gap()
138
CompositionMapping( [ (6,7,8,10,9)(11,13,14,12,15)(16,19,20,18,17)(21,25,22,24,23) ]
139
-> [ [ [ Z(5)^0, 0*Z(5) ], [ Z(5)^0, Z(5)^0 ] ] ], <action isomorphism> )
140
sage: type(_)
141
<type 'sage.libs.gap.element.GapElement'>
142
"""
143
return self._phi
144
145
def _repr_(self):
146
"""
147
EXAMPLES::
148
149
sage: F = GF(5); MS = MatrixSpace(F,2,2)
150
sage: G = MatrixGroup([MS([1,1,0,1])])
151
sage: H = MatrixGroup([MS([1,0,1,1])])
152
sage: phi = G.hom(H.gens())
153
sage: phi
154
Homomorphism : Matrix group over Finite Field of size 5 with 1 generators (
155
[1 1]
156
[0 1]
157
) --> Matrix group over Finite Field of size 5 with 1 generators (
158
[1 0]
159
[1 1]
160
)
161
sage: phi(MS([1,1,0,1]))
162
[1 0]
163
[1 1]
164
"""
165
return "Homomorphism : %s --> %s"%(self.domain(),self.codomain())
166
167
def _latex_(self):
168
r"""
169
EXAMPLES::
170
171
sage: F = GF(5); MS = MatrixSpace(F,2,2)
172
sage: G = MatrixGroup([MS([1,1,0,1])])
173
sage: phi = G.hom(G.gens())
174
sage: print latex(phi)
175
\left\langle \left(\begin{array}{rr}
176
1 & 1 \\
177
0 & 1
178
\end{array}\right) \right\rangle \rightarrow{} \left\langle \left(\begin{array}{rr}
179
1 & 1 \\
180
0 & 1
181
\end{array}\right) \right\rangle
182
"""
183
return "%s \\rightarrow{} %s"%(latex(self.domain()), latex(self.codomain()))
184
185
def kernel(self):
186
"""
187
Return the kernel of ``self``, i.e., a matrix group.
188
189
EXAMPLES::
190
191
sage: F = GF(7); MS = MatrixSpace(F,2,2)
192
sage: F.multiplicative_generator()
193
3
194
sage: G = MatrixGroup([MS([3,0,0,1])])
195
sage: a = G.gens()[0]^2
196
sage: phi = G.hom([a])
197
sage: phi.kernel()
198
Matrix group over Finite Field of size 7 with 1 generators (
199
[6 0]
200
[0 1]
201
)
202
"""
203
gap_ker = self.gap().Kernel()
204
F = self.domain().base_ring()
205
from sage.groups.matrix_gps.all import MatrixGroup
206
return MatrixGroup([x.matrix(F) for x in gap_ker.GeneratorsOfGroup()])
207
208
def pushforward(self, J, *args,**kwds):
209
"""
210
The image of an element or a subgroup.
211
212
INPUT:
213
214
``J`` -- a subgroup or an element of the domain of ``self``.
215
216
OUTPUT:
217
218
The image of ``J`` under ``self``
219
220
NOTE:
221
222
``pushforward`` is the method that is used when a map is called on
223
anything that is not an element of its domain. For historical reasons,
224
we keep the alias ``image()`` for this method.
225
226
EXAMPLES::
227
228
sage: F = GF(7); MS = MatrixSpace(F,2,2)
229
sage: F.multiplicative_generator()
230
3
231
sage: G = MatrixGroup([MS([3,0,0,1])])
232
sage: a = G.gens()[0]^2
233
sage: phi = G.hom([a])
234
sage: phi.image(G.gens()[0]) # indirect doctest
235
[2 0]
236
[0 1]
237
sage: H = MatrixGroup([MS(a.list())])
238
sage: H
239
Matrix group over Finite Field of size 7 with 1 generators (
240
[2 0]
241
[0 1]
242
)
243
244
The following tests against trac ticket #10659::
245
246
sage: phi(H) # indirect doctestest
247
Matrix group over Finite Field of size 7 with 1 generators (
248
[4 0]
249
[0 1]
250
)
251
"""
252
phi = self.gap()
253
F = self.codomain().base_ring()
254
gapJ = to_libgap(J)
255
if gapJ.IsGroup():
256
from sage.groups.matrix_gps.all import MatrixGroup
257
img_gens = [x.matrix(F) for x in phi.Image(gapJ).GeneratorsOfGroup()]
258
return MatrixGroup(img_gens)
259
return phi.Image(gapJ).matrix(F)
260
261
image = pushforward
262
263
def _call_( self, g ):
264
"""
265
Call syntax for morphisms.
266
267
Some python code for wrapping GAP's Images function for a
268
matrix group G. Returns an error if g is not in G.
269
270
EXAMPLES::
271
272
sage: F = GF(5); MS = MatrixSpace(F,2,2)
273
sage: g = MS([1,1,0,1])
274
sage: G = MatrixGroup([g])
275
sage: phi = G.hom(G.gens())
276
sage: phi(G.0)
277
[1 1]
278
[0 1]
279
sage: phi(G(g^2))
280
[1 2]
281
[0 1]
282
283
sage: F = GF(5); MS = MatrixSpace(F,2,2)
284
sage: gens = [MS([1,2, -1,1]),MS([1,1, 0,1])]
285
sage: G = MatrixGroup(gens)
286
sage: phi = G.hom(G.gens())
287
sage: phi(G.0)
288
[1 2]
289
[4 1]
290
sage: phi(G.1)
291
[1 1]
292
[0 1]
293
294
TEST:
295
296
The following tests that the call method was successfully
297
improved in trac ticket #10659::
298
299
sage: O = WeylGroup(['D',6])
300
sage: r = prod(O.gens())
301
sage: r_ = r^-1
302
sage: f = O.hom([r*x*r_ for x in O.gens()]) # long time (19s on sage.math, 2011)
303
sage: [f(x) for x in O.gens()] # long time
304
[
305
[1 0 0 0 0 0] [1 0 0 0 0 0] [1 0 0 0 0 0] [ 0 0 0 0 -1 0]
306
[0 0 1 0 0 0] [0 1 0 0 0 0] [0 1 0 0 0 0] [ 0 1 0 0 0 0]
307
[0 1 0 0 0 0] [0 0 0 1 0 0] [0 0 1 0 0 0] [ 0 0 1 0 0 0]
308
[0 0 0 1 0 0] [0 0 1 0 0 0] [0 0 0 0 1 0] [ 0 0 0 1 0 0]
309
[0 0 0 0 1 0] [0 0 0 0 1 0] [0 0 0 1 0 0] [-1 0 0 0 0 0]
310
[0 0 0 0 0 1], [0 0 0 0 0 1], [0 0 0 0 0 1], [ 0 0 0 0 0 1],
311
<BLANKLINE>
312
[0 0 0 0 0 1] [ 0 0 0 0 0 -1]
313
[0 1 0 0 0 0] [ 0 1 0 0 0 0]
314
[0 0 1 0 0 0] [ 0 0 1 0 0 0]
315
[0 0 0 1 0 0] [ 0 0 0 1 0 0]
316
[0 0 0 0 1 0] [ 0 0 0 0 1 0]
317
[1 0 0 0 0 0], [-1 0 0 0 0 0]
318
]
319
sage: f(O) # long time
320
Matrix group over Rational Field with 6 generators
321
sage: f(O).gens() # long time
322
(
323
[1 0 0 0 0 0] [1 0 0 0 0 0] [1 0 0 0 0 0] [ 0 0 0 0 -1 0]
324
[0 0 1 0 0 0] [0 1 0 0 0 0] [0 1 0 0 0 0] [ 0 1 0 0 0 0]
325
[0 1 0 0 0 0] [0 0 0 1 0 0] [0 0 1 0 0 0] [ 0 0 1 0 0 0]
326
[0 0 0 1 0 0] [0 0 1 0 0 0] [0 0 0 0 1 0] [ 0 0 0 1 0 0]
327
[0 0 0 0 1 0] [0 0 0 0 1 0] [0 0 0 1 0 0] [-1 0 0 0 0 0]
328
[0 0 0 0 0 1], [0 0 0 0 0 1], [0 0 0 0 0 1], [ 0 0 0 0 0 1],
329
<BLANKLINE>
330
[0 0 0 0 0 1] [ 0 0 0 0 0 -1]
331
[0 1 0 0 0 0] [ 0 1 0 0 0 0]
332
[0 0 1 0 0 0] [ 0 0 1 0 0 0]
333
[0 0 0 1 0 0] [ 0 0 0 1 0 0]
334
[0 0 0 0 1 0] [ 0 0 0 0 1 0]
335
[1 0 0 0 0 0], [-1 0 0 0 0 0]
336
)
337
"""
338
phi = self.gap()
339
G = self.domain()
340
F = G.base_ring()
341
h = g.gap()
342
return phi.Image(h).matrix(F)
343
344