Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/groups/libgap_mixin.py
8814 views
1
"""
2
Mix-in Class for libGAP-based Groups
3
4
This class adds access to GAP functionality to groups such that parent
5
and element have a ``gap()`` method that returns a libGAP object for
6
the parent/element.
7
8
If your group implementation uses libgap, then you should add
9
:class:`GroupMixinLibGAP` as the first class that you are deriving
10
from. This ensures that it properly overrides any default methods that
11
just raise ``NotImplemented``.
12
"""
13
14
from sage.libs.all import libgap
15
from sage.misc.cachefunc import cached_method
16
17
18
class GroupElementMixinLibGAP(object):
19
20
@cached_method
21
def order(self):
22
"""
23
Return the order of this group element, which is the smallest
24
positive integer `n` such that `g^n = 1`, or
25
+Infinity if no such integer exists.
26
27
EXAMPLES::
28
29
sage: k = GF(7);
30
sage: G = MatrixGroup([matrix(k,2,[1,1,0,1]), matrix(k,2,[1,0,0,2])]); G
31
Matrix group over Finite Field of size 7 with 2 generators (
32
[1 1] [1 0]
33
[0 1], [0 2]
34
)
35
sage: G.order()
36
21
37
sage: G.gen(0).order(), G.gen(1).order()
38
(7, 3)
39
40
sage: k = QQ;
41
sage: G = MatrixGroup([matrix(k,2,[1,1,0,1]), matrix(k,2,[1,0,0,2])]); G
42
Matrix group over Rational Field with 2 generators (
43
[1 1] [1 0]
44
[0 1], [0 2]
45
)
46
sage: G.order()
47
+Infinity
48
sage: G.gen(0).order(), G.gen(1).order()
49
(+Infinity, +Infinity)
50
51
sage: gl = GL(2, ZZ); gl
52
General Linear Group of degree 2 over Integer Ring
53
sage: g = gl.gen(2); g
54
[1 1]
55
[0 1]
56
sage: g.order()
57
+Infinity
58
"""
59
order = self.gap().Order()
60
if order.IsInt():
61
return order.sage()
62
else:
63
assert order.IsInfinity()
64
from sage.rings.all import Infinity
65
return Infinity
66
67
def word_problem(self, gens=None):
68
r"""
69
Solve the word problem.
70
71
This method writes the group element as a product of the
72
elements of the list ``gens``, or the standard generators of
73
the parent of self if ``gens`` is None.
74
75
INPUT:
76
77
- ``gens`` -- a list/tuple/iterable of elements (or objects
78
that can be converted to group elements), or ``None``
79
(default). By default, the generators of the parent group
80
are used.
81
82
OUTPUT:
83
84
A factorization object that contains information about the
85
order of factors and the exponents. A ``ValueError`` is raised
86
if the group element cannot be written as a word in ``gens``.
87
88
ALGORITHM:
89
90
Use GAP, which has optimized algorithms for solving the word
91
problem (the GAP functions ``EpimorphismFromFreeGroup`` and
92
``PreImagesRepresentative``).
93
94
EXAMPLE::
95
96
sage: G = GL(2,5); G
97
General Linear Group of degree 2 over Finite Field of size 5
98
sage: G.gens()
99
(
100
[2 0] [4 1]
101
[0 1], [4 0]
102
)
103
sage: G(1).word_problem([G.gen(0)])
104
1
105
sage: type(_)
106
<class 'sage.structure.factorization.Factorization'>
107
108
sage: g = G([0,4,1,4])
109
sage: g.word_problem()
110
([4 1]
111
[4 0])^-1
112
113
Next we construct a more complicated element of the group from the
114
generators::
115
116
sage: s,t = G.0, G.1
117
sage: a = (s * t * s); b = a.word_problem(); b
118
([2 0]
119
[0 1]) *
120
([4 1]
121
[4 0]) *
122
([2 0]
123
[0 1])
124
sage: flatten(b)
125
[
126
[2 0] [4 1] [2 0]
127
[0 1], 1, [4 0], 1, [0 1], 1
128
]
129
sage: b.prod() == a
130
True
131
132
We solve the word problem using some different generators::
133
134
sage: s = G([2,0,0,1]); t = G([1,1,0,1]); u = G([0,-1,1,0])
135
sage: a.word_problem([s,t,u])
136
([2 0]
137
[0 1])^-1 *
138
([1 1]
139
[0 1])^-1 *
140
([0 4]
141
[1 0]) *
142
([2 0]
143
[0 1])^-1
144
145
We try some elements that don't actually generate the group::
146
147
sage: a.word_problem([t,u])
148
Traceback (most recent call last):
149
...
150
ValueError: word problem has no solution
151
152
AUTHORS:
153
154
- David Joyner and William Stein
155
- David Loeffler (2010): fixed some bugs
156
- Volker Braun (2013): LibGAP
157
"""
158
from sage.libs.gap.libgap import libgap
159
G = self.parent()
160
if gens:
161
gen = lambda i:gens[i]
162
H = libgap.Group([G(x).gap() for x in gens])
163
else:
164
gen = G.gen
165
H = G.gap()
166
hom = H.EpimorphismFromFreeGroup()
167
preimg = hom.PreImagesRepresentative(self.gap())
168
169
if preimg.is_bool():
170
assert preimg == libgap.eval('fail')
171
raise ValueError('word problem has no solution')
172
173
result = []
174
n = preimg.NumberSyllables().sage()
175
exponent_syllable = libgap.eval('ExponentSyllable')
176
generator_syllable = libgap.eval('GeneratorSyllable')
177
for i in range(n):
178
exponent = exponent_syllable(preimg, i+1).sage()
179
generator = gen(generator_syllable(preimg, i+1).sage() - 1)
180
result.append( (generator, exponent) )
181
from sage.structure.factorization import Factorization
182
result = Factorization(result)
183
result._set_cr(True)
184
return result
185
186
187
class GroupMixinLibGAP(object):
188
189
@cached_method
190
def is_abelian(self):
191
r"""
192
Test whether the group is Abelian.
193
194
OUTPUT:
195
196
Boolean. ``True`` if this group is an Abelian group.
197
198
EXAMPLES::
199
200
sage: SL(1, 17).is_abelian()
201
True
202
sage: SL(2, 17).is_abelian()
203
False
204
"""
205
return self.gap().IsAbelian().sage()
206
207
@cached_method
208
def is_finite(self):
209
"""
210
Test whether the matrix group is finite.
211
212
OUTPUT:
213
214
Boolean.
215
216
EXAMPLES::
217
218
sage: G = GL(2,GF(3))
219
sage: G.is_finite()
220
True
221
sage: SL(2,ZZ).is_finite()
222
False
223
"""
224
return self.gap().IsFinite().sage()
225
226
def cardinality(self):
227
"""
228
Implements :meth:`EnumeratedSets.ParentMethods.cardinality`.
229
230
EXAMPLES::
231
232
sage: G = Sp(4,GF(3))
233
sage: G.cardinality()
234
51840
235
236
sage: G = SL(4,GF(3))
237
sage: G.cardinality()
238
12130560
239
240
sage: F = GF(5); MS = MatrixSpace(F,2,2)
241
sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]
242
sage: G = MatrixGroup(gens)
243
sage: G.cardinality()
244
480
245
246
sage: G = MatrixGroup([matrix(ZZ,2,[1,1,0,1])])
247
sage: G.cardinality()
248
+Infinity
249
250
sage: G = Sp(4,GF(3))
251
sage: G.cardinality()
252
51840
253
254
sage: G = SL(4,GF(3))
255
sage: G.cardinality()
256
12130560
257
258
sage: F = GF(5); MS = MatrixSpace(F,2,2)
259
sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]
260
sage: G = MatrixGroup(gens)
261
sage: G.cardinality()
262
480
263
264
sage: G = MatrixGroup([matrix(ZZ,2,[1,1,0,1])])
265
sage: G.cardinality()
266
+Infinity
267
"""
268
if self.is_finite():
269
return self.gap().Size().sage()
270
from sage.rings.infinity import Infinity
271
return Infinity
272
273
order = cardinality
274
275
@cached_method
276
def conjugacy_class_representatives(self):
277
"""
278
Return a set of representatives for each of the conjugacy classes
279
of the group.
280
281
EXAMPLES::
282
283
sage: G = SU(3,GF(2))
284
sage: len(G.conjugacy_class_representatives())
285
16
286
287
sage: G = GL(2,GF(3))
288
sage: G.conjugacy_class_representatives()
289
(
290
[1 0] [0 2] [2 0] [0 2] [0 2] [0 1] [0 1] [2 0]
291
[0 1], [1 1], [0 2], [1 2], [1 0], [1 2], [1 1], [0 1]
292
)
293
294
sage: len(GU(2,GF(5)).conjugacy_class_representatives())
295
36
296
"""
297
G = self.gap()
298
reps = [ cc.Representative() for cc in G.ConjugacyClasses() ]
299
return tuple(self(g) for g in reps)
300
301
@cached_method
302
def conjugacy_classes(self):
303
r"""
304
Return a list with all the conjugacy classes of ``self``.
305
306
EXAMPLES::
307
308
sage: G = SL(2, GF(2))
309
sage: G.conjugacy_classes()
310
(Conjugacy class of [1 0]
311
[0 1] in Special Linear Group of degree 2 over Finite Field of size 2,
312
Conjugacy class of [0 1]
313
[1 0] in Special Linear Group of degree 2 over Finite Field of size 2,
314
Conjugacy class of [0 1]
315
[1 1] in Special Linear Group of degree 2 over Finite Field of size 2)
316
"""
317
from sage.groups.conjugacy_classes import ConjugacyClassGAP
318
G = self.gap()
319
reps = [ cc.Representative() for cc in G.ConjugacyClasses() ]
320
return tuple(ConjugacyClassGAP(self, self(g)) for g in reps)
321
322
def class_function(self, values):
323
"""
324
Return the class function with given values.
325
326
INPUT:
327
328
- ``values`` -- list/tuple/iterable of numbers. The values of the
329
class function on the conjugacy classes, in that order.
330
331
EXAMPLES::
332
333
sage: G = GL(2,GF(3))
334
sage: chi = G.class_function(range(8))
335
sage: list(chi)
336
[0, 1, 2, 3, 4, 5, 6, 7]
337
"""
338
from sage.groups.class_function import ClassFunction_libgap
339
return ClassFunction_libgap(self, values)
340
341
@cached_method
342
def center(self):
343
"""
344
Return the center of this linear group as a subgroup.
345
346
OUTPUT:
347
348
The center as a subgroup.
349
350
EXAMPLES::
351
352
sage: G = SU(3,GF(2))
353
sage: G.center()
354
Matrix group over Finite Field in a of size 2^2 with 1 generators (
355
[a 0 0]
356
[0 a 0]
357
[0 0 a]
358
)
359
sage: GL(2,GF(3)).center()
360
Matrix group over Finite Field of size 3 with 1 generators (
361
[2 0]
362
[0 2]
363
)
364
sage: GL(3,GF(3)).center()
365
Matrix group over Finite Field of size 3 with 1 generators (
366
[2 0 0]
367
[0 2 0]
368
[0 0 2]
369
)
370
sage: GU(3,GF(2)).center()
371
Matrix group over Finite Field in a of size 2^2 with 1 generators (
372
[a + 1 0 0]
373
[ 0 a + 1 0]
374
[ 0 0 a + 1]
375
)
376
377
sage: A = Matrix(FiniteField(5), [[2,0,0], [0,3,0], [0,0,1]])
378
sage: B = Matrix(FiniteField(5), [[1,0,0], [0,1,0], [0,1,1]])
379
sage: MatrixGroup([A,B]).center()
380
Matrix group over Finite Field of size 5 with 1 generators (
381
[1 0 0]
382
[0 1 0]
383
[0 0 1]
384
)
385
"""
386
G = self.gap()
387
center = list(G.Center().GeneratorsOfGroup())
388
if len(center) == 0:
389
center = [G.One()]
390
return self.subgroup(center)
391
392
@cached_method
393
def irreducible_characters(self):
394
"""
395
Returns the irreducible characters of the group.
396
397
OUTPUT:
398
399
A tuple containing all irreducible characters.
400
401
EXAMPLES::
402
403
sage: G = GL(2,2)
404
sage: G.irreducible_characters()
405
(Character of General Linear Group of degree 2 over Finite Field of size 2,
406
Character of General Linear Group of degree 2 over Finite Field of size 2,
407
Character of General Linear Group of degree 2 over Finite Field of size 2)
408
"""
409
Irr = self.gap().Irr()
410
L = []
411
from sage.groups.class_function import ClassFunction_libgap
412
for irr in Irr:
413
L.append(ClassFunction_libgap(self, irr))
414
return tuple(L)
415
416
def random_element(self):
417
"""
418
Return a random element of this group.
419
420
OUTPUT:
421
422
A group element.
423
424
EXAMPLES::
425
426
sage: G = Sp(4,GF(3))
427
sage: G.random_element() # random
428
[2 1 1 1]
429
[1 0 2 1]
430
[0 1 1 0]
431
[1 0 0 1]
432
sage: G.random_element() in G
433
True
434
435
sage: F = GF(5); MS = MatrixSpace(F,2,2)
436
sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]
437
sage: G = MatrixGroup(gens)
438
sage: G.random_element() # random
439
[1 3]
440
[0 3]
441
sage: G.random_element() in G
442
True
443
"""
444
return self(self.gap().Random())
445
446
def __iter__(self):
447
"""
448
Iterate over the elements of the group.
449
450
EXAMPLES::
451
452
sage: F = GF(3)
453
sage: gens = [matrix(F,2, [1,0, -1,1]), matrix(F, 2, [1,1,0,1])]
454
sage: G = MatrixGroup(gens)
455
sage: iter(G).next()
456
[0 1]
457
[2 0]
458
"""
459
if hasattr(self.list, 'get_cache') and self.list.get_cache() is not None:
460
for g in self.list():
461
yield g
462
return
463
iterator = self.gap().Iterator()
464
while not iterator.IsDoneIterator().sage():
465
yield self(iterator.NextIterator(), check=False)
466
467
@cached_method
468
def list(self):
469
"""
470
List all elements of this group.
471
472
OUTPUT:
473
474
A tuple containing all group elements in a random but fixed
475
order.
476
477
EXAMPLES::
478
479
sage: F = GF(3)
480
sage: gens = [matrix(F,2, [1,0, -1,1]), matrix(F, 2, [1,1,0,1])]
481
sage: G = MatrixGroup(gens)
482
sage: G.cardinality()
483
24
484
sage: v = G.list()
485
sage: len(v)
486
24
487
sage: v[:5]
488
(
489
[0 1] [0 1] [0 1] [0 2] [0 2]
490
[2 0], [2 1], [2 2], [1 0], [1 1]
491
)
492
sage: all(g in G for g in G.list())
493
True
494
495
An example over a ring (see trac 5241)::
496
497
sage: M1 = matrix(ZZ,2,[[-1,0],[0,1]])
498
sage: M2 = matrix(ZZ,2,[[1,0],[0,-1]])
499
sage: M3 = matrix(ZZ,2,[[-1,0],[0,-1]])
500
sage: MG = MatrixGroup([M1, M2, M3])
501
sage: MG.list()
502
(
503
[-1 0] [-1 0] [ 1 0] [1 0]
504
[ 0 -1], [ 0 1], [ 0 -1], [0 1]
505
)
506
sage: MG.list()[1]
507
[-1 0]
508
[ 0 1]
509
sage: MG.list()[1].parent()
510
Matrix group over Integer Ring with 3 generators (
511
[-1 0] [ 1 0] [-1 0]
512
[ 0 1], [ 0 -1], [ 0 -1]
513
)
514
515
An example over a field (see trac 10515)::
516
517
sage: gens = [matrix(QQ,2,[1,0,0,1])]
518
sage: MatrixGroup(gens).list()
519
(
520
[1 0]
521
[0 1]
522
)
523
524
Another example over a ring (see trac 9437)::
525
526
sage: len(SL(2, Zmod(4)).list())
527
48
528
529
An error is raised if the group is not finite::
530
531
sage: GL(2,ZZ).list()
532
Traceback (most recent call last):
533
...
534
NotImplementedError: group must be finite
535
"""
536
if not self.is_finite():
537
raise NotImplementedError('group must be finite')
538
elements = self.gap().Elements()
539
return tuple(self(x, check=False) for x in elements)
540
541
def is_isomorphic(self, H):
542
"""
543
Test whether ``self`` and ``H`` are isomorphic groups.
544
545
INPUT:
546
547
- ``H`` -- a group.
548
549
OUTPUT:
550
551
Boolean.
552
553
EXAMPLES::
554
555
sage: m1 = matrix(GF(3), [[1,1],[0,1]])
556
sage: m2 = matrix(GF(3), [[1,2],[0,1]])
557
sage: F = MatrixGroup(m1)
558
sage: G = MatrixGroup(m1, m2)
559
sage: H = MatrixGroup(m2)
560
sage: F.is_isomorphic(G)
561
True
562
sage: G.is_isomorphic(H)
563
True
564
sage: F.is_isomorphic(H)
565
True
566
sage: F==G, G==H, F==H
567
(False, False, False)
568
"""
569
iso = self.gap().IsomorphismGroups(H.gap())
570
if iso.is_bool(): # fail means not isomorphic
571
try:
572
iso.sage()
573
assert False
574
except ValueError:
575
pass
576
return False
577
return True
578
579