Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/groups/perm_gps/permgroup_named.py
8815 views
1
r"""
2
"Named" Permutation groups (such as the symmetric group, S_n)
3
4
You can construct the following permutation groups:
5
6
-- SymmetricGroup, $S_n$ of order $n!$ (n can also be a list $X$ of distinct
7
positive integers, in which case it returns $S_X$)
8
9
-- AlternatingGroup, $A_n$ or order $n!/2$ (n can also be a list $X$
10
of distinct positive integers, in which case it returns
11
$A_X$)
12
13
-- DihedralGroup, $D_n$ of order $2n$
14
15
-- GeneralDihedralGroup, $Dih(G)$, where G is an abelian group
16
17
-- CyclicPermutationGroup, $C_n$ of order $n$
18
19
-- DiCyclicGroup, nonabelian groups of order `4m` with a unique element of order 2
20
21
-- TransitiveGroup, $n^{th}$ transitive group of degree $d$
22
from the GAP tables of transitive groups (requires
23
the "optional" package database_gap)
24
25
-- TransitiveGroups(d), TransitiveGroups(), set of all of the above
26
27
-- PrimitiveGroup, $n^{th}$ primitive group of degree $d$
28
from the GAP tables of primitive groups (requires
29
the "optional" package database_gap)
30
31
-- PrimitiveGroups(d), PrimitiveGroups(), set of all of the above
32
33
-- MathieuGroup(degree), Mathieu group of degree 9, 10, 11, 12, 21, 22, 23, or 24.
34
35
-- KleinFourGroup, subgroup of $S_4$ of order $4$ which is not $C_2 \times C_2$
36
37
-- QuaternionGroup, non-abelian group of order `8`, `\{\pm 1, \pm I, \pm J, \pm K\}`
38
39
-- SplitMetacyclicGroup, nonabelian groups of order `p^m` with cyclic
40
subgroups of index p
41
42
-- SemidihedralGroup, nonabelian 2-groups with cyclic subgroups of index 2
43
44
-- PGL(n,q), projective general linear group of $n\times n$ matrices over
45
the finite field GF(q)
46
47
-- PSL(n,q), projective special linear group of $n\times n$ matrices over
48
the finite field GF(q)
49
50
-- PSp(2n,q), projective symplectic linear group of $2n\times 2n$ matrices
51
over the finite field GF(q)
52
53
-- PSU(n,q), projective special unitary group of $n \times n$ matrices having
54
coefficients in the finite field $GF(q^2)$ that respect a
55
fixed nondegenerate sesquilinear form, of determinant 1.
56
57
-- PGU(n,q), projective general unitary group of $n\times n$ matrices having
58
coefficients in the finite field $GF(q^2)$ that respect a
59
fixed nondegenerate sesquilinear form, modulo the centre.
60
61
-- SuzukiGroup(q), Suzuki group over GF(q), $^2 B_2(2^{2k+1}) = Sz(2^{2k+1})$.
62
63
64
AUTHOR:
65
- David Joyner (2007-06): split from permgp.py (suggested by Nick Alexander)
66
67
REFERENCES:
68
Cameron, P., Permutation Groups. New York: Cambridge University Press, 1999.
69
Wielandt, H., Finite Permutation Groups. New York: Academic Press, 1964.
70
Dixon, J. and Mortimer, B., Permutation Groups, Springer-Verlag, Berlin/New York, 1996.
71
72
NOTE:
73
Though Suzuki groups are okay, Ree groups should *not* be wrapped as
74
permutation groups - the construction is too slow - unless (for
75
small values or the parameter) they are made using explicit generators.
76
"""
77
78
#*****************************************************************************
79
# Copyright (C) 2006 William Stein <[email protected]>
80
# David Joyner <[email protected]>
81
#
82
# Distributed under the terms of the GNU General Public License (GPL)
83
# http://www.gnu.org/licenses/
84
#*****************************************************************************
85
86
from sage.rings.all import Integer
87
from sage.interfaces.all import gap
88
from sage.rings.finite_rings.constructor import FiniteField as GF
89
from sage.rings.arith import factor
90
from sage.groups.abelian_gps.abelian_group import AbelianGroup
91
from sage.misc.functional import is_even
92
from sage.misc.cachefunc import cached_method, weak_cached_function
93
from sage.misc.classcall_metaclass import typecall
94
from sage.misc.superseded import deprecated_function_alias
95
from sage.groups.perm_gps.permgroup import PermutationGroup_generic
96
from sage.groups.perm_gps.permgroup_element import PermutationGroupElement
97
from sage.structure.unique_representation import CachedRepresentation
98
from sage.structure.parent import Parent
99
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
100
from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
101
from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets
102
from sage.categories.enumerated_sets import EnumeratedSets
103
from sage.sets.non_negative_integers import NonNegativeIntegers
104
from sage.sets.family import Family
105
from sage.sets.primes import Primes
106
107
class PermutationGroup_unique(CachedRepresentation, PermutationGroup_generic):
108
"""
109
.. TODO::
110
111
Fix the broken hash.
112
::
113
114
sage: G = SymmetricGroup(6)
115
sage: G3 = G.subgroup([G((1,2,3,4,5,6)),G((1,2))])
116
sage: hash(G) == hash(G3) # todo: Should be True!
117
False
118
"""
119
@weak_cached_function
120
def __classcall__(cls, *args, **kwds):
121
"""
122
This makes sure that domain is a FiniteEnumeratedSet before it gets passed
123
on to the __init__ method.
124
125
EXAMPLES::
126
127
sage: SymmetricGroup(['a','b']).domain() #indirect doctest
128
{'a', 'b'}
129
"""
130
domain = kwds.pop('domain', None)
131
if domain is not None:
132
if domain not in FiniteEnumeratedSets():
133
domain = FiniteEnumeratedSet(domain)
134
kwds['domain'] = domain
135
return super(PermutationGroup_unique, cls).__classcall__(cls, *args, **kwds)
136
137
def __eq__(self, other):
138
"""
139
EXAMPLES::
140
141
sage: G = SymmetricGroup(6)
142
sage: G3 = G.subgroup([G((1,2,3,4,5,6)),G((1,2))])
143
sage: G == G3
144
True
145
146
.. WARNING::
147
148
The hash currently is broken for this comparison.
149
"""
150
return self.__cmp__(other) == 0
151
152
153
class PermutationGroup_symalt(PermutationGroup_unique):
154
"""
155
This is a class used to factor out some of the commonality
156
in the SymmetricGroup and AlternatingGroup classes.
157
"""
158
159
@staticmethod
160
def __classcall__(cls, domain):
161
"""
162
Normalizes the input of the constructor into a set
163
164
INPUT:
165
166
- ``n`` - an integer or list or tuple thereof
167
168
Calls the constructor with a tuple representing the set.
169
170
EXAMPLES::
171
172
sage: S1 = SymmetricGroup(4)
173
sage: S2 = SymmetricGroup([1,2,3,4])
174
sage: S3 = SymmetricGroup((1,2,3,4))
175
sage: S1 is S2
176
True
177
sage: S1 is S3
178
True
179
180
TESTS::
181
182
sage: SymmetricGroup(0)
183
Symmetric group of order 0! as a permutation group
184
sage: SymmetricGroup(1)
185
Symmetric group of order 1! as a permutation group
186
sage: SymmetricGroup(-1)
187
Traceback (most recent call last):
188
...
189
ValueError: domain (=-1) must be an integer >= 0 or a list
190
"""
191
if domain not in FiniteEnumeratedSets():
192
if not isinstance(domain, (tuple, list)):
193
try:
194
domain = Integer(domain)
195
except TypeError:
196
raise ValueError("domain (=%s) must be an integer >= 0 or a finite set (but domain has type %s)"%(domain,type(domain)))
197
198
if domain < 0:
199
raise ValueError("domain (=%s) must be an integer >= 0 or a list"%domain)
200
else:
201
domain = range(1, domain+1)
202
v = FiniteEnumeratedSet(domain)
203
else:
204
v = domain
205
206
return super(PermutationGroup_symalt, cls).__classcall__(cls, domain=v)
207
208
set = deprecated_function_alias(10335, PermutationGroup_generic.domain)
209
210
class SymmetricGroup(PermutationGroup_symalt):
211
def __init__(self, domain=None):
212
"""
213
The full symmetric group of order $n!$, as a permutation group.
214
If n is a list or tuple of positive integers then it returns the
215
symmetric group of the associated set.
216
217
INPUT:
218
219
- ``n`` - a positive integer, or list or tuple thereof
220
221
.. note::
222
This group is also available via ``groups.permutation.Symmetric()``.
223
224
EXAMPLES::
225
226
sage: G = SymmetricGroup(8)
227
sage: G.order()
228
40320
229
sage: G
230
Symmetric group of order 8! as a permutation group
231
sage: G.degree()
232
8
233
sage: S8 = SymmetricGroup(8)
234
sage: G = SymmetricGroup([1,2,4,5])
235
sage: G
236
Symmetric group of order 4! as a permutation group
237
sage: G.domain()
238
{1, 2, 4, 5}
239
sage: G = SymmetricGroup(4)
240
sage: G
241
Symmetric group of order 4! as a permutation group
242
sage: G.domain()
243
{1, 2, 3, 4}
244
sage: G.category()
245
Join of Category of finite permutation groups and Category of finite weyl groups
246
sage: TestSuite(G).run()
247
248
TESTS::
249
250
sage: TestSuite(SymmetricGroup(0)).run()
251
252
sage: groups.permutation.Symmetric(4)
253
Symmetric group of order 4! as a permutation group
254
"""
255
from sage.categories.finite_weyl_groups import FiniteWeylGroups
256
from sage.categories.finite_permutation_groups import FinitePermutationGroups
257
from sage.categories.category import Category
258
259
#Note that we skip the call to the superclass initializer in order to
260
#avoid infinite recursion since SymmetricGroup is called by
261
#PermutationGroupElement
262
super(PermutationGroup_generic, self).__init__(category = Category.join([FinitePermutationGroups(), FiniteWeylGroups()]))
263
264
self._domain = domain
265
self._deg = len(self._domain)
266
self._domain_to_gap = dict((key, i+1) for i, key in enumerate(self._domain))
267
self._domain_from_gap = dict((i+1, key) for i, key in enumerate(self._domain))
268
269
#Create the generators for the symmetric group
270
gens = [ tuple(self._domain) ]
271
if len(self._domain) > 2:
272
gens.append( tuple(self._domain[:2]) )
273
self._gens = [PermutationGroupElement(g, self, check=False) for g in gens]
274
275
276
def _gap_init_(self, gap=None):
277
"""
278
Returns the string used to create this group in GAP.
279
280
EXAMPLES::
281
282
sage: S = SymmetricGroup(3)
283
sage: S._gap_init_()
284
'SymmetricGroup(3)'
285
sage: S = SymmetricGroup(['a', 'b', 'c'])
286
sage: S._gap_init_()
287
'SymmetricGroup(3)'
288
"""
289
return 'SymmetricGroup(%s)'%self.degree()
290
291
@cached_method
292
def index_set(self):
293
"""
294
Indexing sets of descent of the symmetric group.
295
296
EXAMPLES::
297
298
sage: S8 = SymmetricGroup(8)
299
sage: S8.index_set()
300
[1, 2, 3, 4, 5, 6, 7]
301
302
sage: S = SymmetricGroup([3,1,4,5])
303
sage: S.index_set()
304
[3, 1, 4]
305
"""
306
return self.domain()[:-1]
307
308
def __cmp__(self, x):
309
"""
310
Fast comparison for SymmetricGroups.
311
312
EXAMPLES::
313
314
sage: S8 = SymmetricGroup(8)
315
sage: S3 = SymmetricGroup(3)
316
sage: S8 > S3
317
True
318
"""
319
if isinstance(x, SymmetricGroup):
320
return cmp((self._deg, self._domain), (x._deg, x._domain))
321
else:
322
return PermutationGroup_generic.__cmp__(self, x)
323
324
def _repr_(self):
325
"""
326
EXAMPLES::
327
328
sage: A = SymmetricGroup([2,3,7]); A
329
Symmetric group of order 3! as a permutation group
330
"""
331
return "Symmetric group of order %s! as a permutation group"%self.degree()
332
333
def simple_reflection(self, i):
334
"""
335
For `i` in the index set of ``self``, this returns the
336
elementary transposition `s_i=(i,i+1)`.
337
338
EXAMPLES::
339
340
sage: A = SymmetricGroup(5)
341
sage: A.simple_reflection(3)
342
(3,4)
343
344
sage: A = SymmetricGroup([2,3,7])
345
sage: A.simple_reflections()
346
Finite family {2: (2,3), 3: (3,7)}
347
"""
348
return self([(i, self._domain[self._domain.index(i)+1])], check=False)
349
350
def young_subgroup(self, comp):
351
"""
352
Return the Young subgroup associated with the composition ``comp``.
353
354
EXAMPLES::
355
356
sage: S = SymmetricGroup(8)
357
sage: c = Composition([2,2,2,2])
358
sage: S.young_subgroup(c)
359
Subgroup of (Symmetric group of order 8! as a permutation group) generated by [(7,8), (5,6), (3,4), (1,2)]
360
361
sage: S = SymmetricGroup(['a','b','c'])
362
sage: S.young_subgroup([2,1])
363
Subgroup of (Symmetric group of order 3! as a permutation group) generated by [('a','b')]
364
365
sage: Y = S.young_subgroup([2,2,2,2,2])
366
Traceback (most recent call last):
367
...
368
ValueError: The composition is not of expected size
369
"""
370
if sum(comp) != self.degree():
371
raise ValueError('The composition is not of expected size')
372
373
domain = self.domain()
374
gens = []
375
pos = 0
376
for c in comp:
377
for i in range(c-1):
378
gens.append(self((domain[pos + i], domain[pos + i + 1])))
379
pos += c
380
381
return self.subgroup(gens)
382
383
def major_index(self, parameter=None):
384
r"""
385
Returns the *major index generating polynomial* of ``self``,
386
which is a gadget counting the elements of ``self`` by major
387
index.
388
389
INPUT:
390
391
- ``parameter`` - an element of a ring. The result is
392
more explicit with a formal variable. (default:
393
element q of Univariate Polynomial Ring in q over
394
Integer Ring)
395
396
.. math::
397
398
P(q) = \sum_{g\in S_n} q^{ \operatorname{major\ index}(g) }
399
400
EXAMPLES::
401
402
sage: S4 = SymmetricGroup(4)
403
sage: S4.major_index()
404
q^6 + 3*q^5 + 5*q^4 + 6*q^3 + 5*q^2 + 3*q + 1
405
sage: K.<t> = QQ[]
406
sage: S4.major_index(t)
407
t^6 + 3*t^5 + 5*t^4 + 6*t^3 + 5*t^2 + 3*t + 1
408
"""
409
from sage.combinat.q_analogues import q_factorial
410
return q_factorial(self.degree(), parameter)
411
412
class AlternatingGroup(PermutationGroup_symalt):
413
def __init__(self, domain=None):
414
"""
415
The alternating group of order $n!/2$, as a permutation group.
416
417
INPUT:
418
419
``n`` -- a positive integer, or list or tuple thereof
420
421
.. note::
422
This group is also available via ``groups.permutation.Alternating()``.
423
424
EXAMPLES::
425
426
sage: G = AlternatingGroup(6)
427
sage: G.order()
428
360
429
sage: G
430
Alternating group of order 6!/2 as a permutation group
431
sage: G.category()
432
Category of finite permutation groups
433
sage: TestSuite(G).run()
434
435
sage: G = AlternatingGroup([1,2,4,5])
436
sage: G
437
Alternating group of order 4!/2 as a permutation group
438
sage: G.domain()
439
{1, 2, 4, 5}
440
sage: G.category()
441
Category of finite permutation groups
442
sage: TestSuite(G).run()
443
444
TESTS::
445
446
sage: groups.permutation.Alternating(6)
447
Alternating group of order 6!/2 as a permutation group
448
"""
449
PermutationGroup_symalt.__init__(self, gap_group='AlternatingGroup(%s)'%len(domain), domain=domain)
450
451
def _repr_(self):
452
"""
453
EXAMPLES::
454
455
sage: A = AlternatingGroup([2,3,7]); A
456
Alternating group of order 3!/2 as a permutation group
457
"""
458
return "Alternating group of order %s!/2 as a permutation group"%self.degree()
459
460
def _gap_init_(self, gap=None):
461
"""
462
Returns the string used to create this group in GAP.
463
464
EXAMPLES::
465
466
sage: A = AlternatingGroup(3)
467
sage: A._gap_init_()
468
'AlternatingGroup(3)'
469
sage: A = AlternatingGroup(['a', 'b', 'c'])
470
sage: A._gap_init_()
471
'AlternatingGroup(3)'
472
"""
473
return 'AlternatingGroup(%s)'%(self.degree())
474
475
class CyclicPermutationGroup(PermutationGroup_unique):
476
def __init__(self, n):
477
"""
478
A cyclic group of order n, as a permutation group.
479
480
INPUT:
481
n -- a positive integer
482
483
.. note::
484
This group is also available via ``groups.permutation.Cyclic()``.
485
486
EXAMPLES::
487
488
sage: G = CyclicPermutationGroup(8)
489
sage: G.order()
490
8
491
sage: G
492
Cyclic group of order 8 as a permutation group
493
sage: G.category()
494
Category of finite permutation groups
495
sage: TestSuite(G).run()
496
sage: C = CyclicPermutationGroup(10)
497
sage: C.is_abelian()
498
True
499
sage: C = CyclicPermutationGroup(10)
500
sage: C.as_AbelianGroup()
501
Multiplicative Abelian group isomorphic to C2 x C5
502
503
TESTS::
504
505
sage: groups.permutation.Cyclic(6)
506
Cyclic group of order 6 as a permutation group
507
"""
508
n = Integer(n)
509
if n < 1:
510
raise ValueError("n (=%s) must be >= 1" % n)
511
gens = tuple(range(1, n+1))
512
PermutationGroup_generic.__init__(self, [gens], n)
513
514
def _repr_(self):
515
"""
516
EXAMPLES::
517
518
sage: CyclicPermutationGroup(8)
519
Cyclic group of order 8 as a permutation group
520
"""
521
return "Cyclic group of order %s as a permutation group"%self.order()
522
523
def is_commutative(self):
524
"""
525
Return True if this group is commutative.
526
527
EXAMPLES::
528
529
sage: C = CyclicPermutationGroup(8)
530
sage: C.is_commutative()
531
True
532
"""
533
return True
534
535
def is_abelian(self):
536
"""
537
Return True if this group is abelian.
538
539
EXAMPLES::
540
541
sage: C = CyclicPermutationGroup(8)
542
sage: C.is_abelian()
543
True
544
"""
545
return True
546
547
def as_AbelianGroup(self):
548
"""
549
Returns the corresponding Abelian Group instance.
550
551
EXAMPLES::
552
553
sage: C = CyclicPermutationGroup(8)
554
sage: C.as_AbelianGroup()
555
Multiplicative Abelian group isomorphic to C8
556
"""
557
n = self.order()
558
a = list(factor(n))
559
invs = [x[0]**x[1] for x in a]
560
G = AbelianGroup(len(a), invs)
561
return G
562
563
class DiCyclicGroup(PermutationGroup_unique):
564
r"""
565
The dicyclic group of order `4n`, for `n\geq 2`.
566
567
INPUT:
568
- n -- a positive integer, two or greater
569
570
OUTPUT:
571
572
This is a nonabelian group similar in some respects to the
573
dihedral group of the same order, but with far fewer
574
elements of order 2 (it has just one). The permutation
575
representation constructed here is based on the presentation
576
577
.. MATH::
578
579
\langle a, x\mid a^{2n}=1, x^{2}=a^{n}, x^{-1}ax=a^{-1}\rangle
580
581
For `n=2` this is the group of quaternions
582
(`{\pm 1, \pm I,\pm J, \pm K}`), which is the nonabelian
583
group of order 8 that is not the dihedral group `D_4`,
584
the symmetries of a square. For `n=3` this is the nonabelian
585
group of order 12 that is not the dihedral group `D_6`
586
nor the alternating group `A_4`. This group of order 12 is
587
also the semi-direct product of of `C_2` by `C_4`,
588
`C_3\rtimes C_4`. [CONRAD2009]_
589
590
591
When the order of the group is a
592
power of 2 it is known as a "generalized quaternion group."
593
594
IMPLEMENTATION:
595
596
The presentation above means every element can be written as
597
`a^{i}x^{j}` with `0\leq i<2n`, `j=0,1`. We code `a^i` as the symbol
598
`i+1` and code `a^{i}x` as the symbol `2n+i+1`. The two generators
599
are then represented using a left regular representation.
600
601
.. note::
602
This group is also available via ``groups.permutation.DiCyclic()``.
603
604
EXAMPLES:
605
606
A dicyclic group of order 384, with a large power of 2 as a divisor::
607
608
sage: n = 3*2^5
609
sage: G = DiCyclicGroup(n)
610
sage: G.order()
611
384
612
sage: a = G.gen(0)
613
sage: x = G.gen(1)
614
sage: a^(2*n)
615
()
616
sage: a^n==x^2
617
True
618
sage: x^-1*a*x==a^-1
619
True
620
621
A large generalized quaternion group (order is a power of 2)::
622
623
sage: n = 2^10
624
sage: G=DiCyclicGroup(n)
625
sage: G.order()
626
4096
627
sage: a = G.gen(0)
628
sage: x = G.gen(1)
629
sage: a^(2*n)
630
()
631
sage: a^n==x^2
632
True
633
sage: x^-1*a*x==a^-1
634
True
635
636
Just like the dihedral group, the dicyclic group has
637
an element whose order is half the order of the group.
638
Unlike the dihedral group, the dicyclic group has only
639
one element of order 2. Like the dihedral groups of
640
even order, the center of the dicyclic group is a
641
subgroup of order 2 (thus has the unique element of
642
order 2 as its non-identity element). ::
643
644
sage: G=DiCyclicGroup(3*5*4)
645
sage: G.order()
646
240
647
sage: two = [g for g in G if g.order()==2]; two
648
[(1,5)(2,6)(3,7)(4,8)(9,13)(10,14)(11,15)(12,16)]
649
sage: G.center().order()
650
2
651
652
For small orders, we check this is really a group
653
we do not have in Sage otherwise. ::
654
655
sage: G = DiCyclicGroup(2)
656
sage: H = DihedralGroup(4)
657
sage: G.is_isomorphic(H)
658
False
659
sage: G = DiCyclicGroup(3)
660
sage: H = DihedralGroup(6)
661
sage: K = AlternatingGroup(6)
662
sage: G.is_isomorphic(H) or G.is_isomorphic(K)
663
False
664
665
TESTS::
666
667
sage: groups.permutation.DiCyclic(6)
668
Diyclic group of order 24 as a permutation group
669
670
REFERENCES:
671
672
.. [CONRAD2009] `Groups of order 12
673
<http://www.math.uconn.edu/~kconrad/blurbs/grouptheory/group12.pdf>`_.
674
Keith Conrad, accessed 21 October 2009.
675
676
AUTHOR:
677
- Rob Beezer (2009-10-18)
678
"""
679
def __init__(self, n):
680
r"""
681
The dicyclic group of order `4*n`, as a permutation group.
682
683
INPUT:
684
n -- a positive integer, two or greater
685
686
EXAMPLES::
687
688
sage: G = DiCyclicGroup(3*8)
689
sage: G.order()
690
96
691
sage: TestSuite(G).run()
692
"""
693
n = Integer(n)
694
if n < 2:
695
raise ValueError("n (=%s) must be 2 or greater" % n)
696
697
# Certainly 2^2 is part of the first factor of the order
698
# r is maximum power of 2 in the order
699
# m is the rest, the odd part
700
order = 4*n
701
factored = order.factor()
702
r = factored[0][0]**factored[0][1]
703
m = order//r
704
halfr, fourthr = r//2, r//4
705
706
# Representation of a
707
# Two cycles of length halfr
708
a = [tuple(range(1, halfr+1)), tuple(range(halfr+1, r+1))]
709
# With an odd part, a cycle of length m will give the right order for a
710
if m > 1:
711
a.append( tuple(range(r+1, r+m+1)) )
712
713
# Representation of x
714
# Four-cycles that will conjugate the generator a properly
715
x = [(i+1, (-i)%halfr + halfr + 1, (fourthr+i)%halfr + 1, (-fourthr-i)%halfr + halfr + 1)
716
for i in range(0, fourthr)]
717
# With an odd part, transpositions will conjugate the m-cycle to create inverse
718
if m > 1:
719
x += [(r+i+1, r+m-i) for i in range(0, (m-1)//2)]
720
721
PermutationGroup_generic.__init__(self, gens=[a, x])
722
723
def _repr_(self):
724
r"""
725
EXAMPLES::
726
727
sage: DiCyclicGroup(12)
728
Diyclic group of order 48 as a permutation group
729
"""
730
return "Diyclic group of order %s as a permutation group"%self.order()
731
732
def is_commutative(self):
733
r"""
734
Return True if this group is commutative.
735
736
EXAMPLES::
737
738
sage: D = DiCyclicGroup(12)
739
sage: D.is_commutative()
740
False
741
"""
742
return False
743
744
def is_abelian(self):
745
r"""
746
Return True if this group is abelian.
747
748
EXAMPLES::
749
750
sage: D = DiCyclicGroup(12)
751
sage: D.is_abelian()
752
False
753
"""
754
return False
755
756
class KleinFourGroup(PermutationGroup_unique):
757
def __init__(self):
758
r"""
759
The Klein 4 Group, which has order $4$ and exponent $2$, viewed
760
as a subgroup of $S_4$.
761
762
OUTPUT:
763
-- the Klein 4 group of order 4, as a permutation group of degree 4.
764
765
.. note::
766
This group is also available via ``groups.permutation.KleinFour()``.
767
768
EXAMPLES::
769
770
sage: G = KleinFourGroup(); G
771
The Klein 4 group of order 4, as a permutation group
772
sage: list(G)
773
[(), (3,4), (1,2), (1,2)(3,4)]
774
775
TESTS::
776
777
sage: G.category()
778
Category of finite permutation groups
779
sage: TestSuite(G).run()
780
781
sage: groups.permutation.KleinFour()
782
The Klein 4 group of order 4, as a permutation group
783
784
AUTHOR:
785
-- Bobby Moretti (2006-10)
786
"""
787
gens = [(1,2),(3,4)]
788
PermutationGroup_generic.__init__(self, gens)
789
790
def _repr_(self):
791
"""
792
EXAMPLES::
793
794
sage: G = KleinFourGroup(); G
795
The Klein 4 group of order 4, as a permutation group
796
"""
797
return 'The Klein 4 group of order 4, as a permutation group'
798
799
class QuaternionGroup(DiCyclicGroup):
800
r"""
801
The quaternion group of order 8.
802
803
OUTPUT:
804
The quaternion group of order 8, as a permutation group.
805
See the ``DiCyclicGroup`` class for a generalization of this
806
construction.
807
808
.. note::
809
This group is also available via ``groups.permutation.Quaternion()``.
810
811
EXAMPLES:
812
813
The quaternion group is one of two non-abelian groups of order 8,
814
the other being the dihedral group `D_4`. One way to describe this
815
group is with three generators, `I, J, K`, so the whole group is
816
then given as the set `\{\pm 1, \pm I, \pm J, \pm K\}` with relations
817
such as `I^2=J^2=K^2=-1`, `IJ=K` and `JI=-K`.
818
819
The examples below illustrate how to use this group in a similar
820
manner, by testing some of these relations. The representation used
821
here is the left-regular representation. ::
822
823
sage: Q = QuaternionGroup()
824
sage: I = Q.gen(0)
825
sage: J = Q.gen(1)
826
sage: K = I*J
827
sage: [I,J,K]
828
[(1,2,3,4)(5,6,7,8), (1,5,3,7)(2,8,4,6), (1,8,3,6)(2,7,4,5)]
829
sage: neg_one = I^2; neg_one
830
(1,3)(2,4)(5,7)(6,8)
831
sage: J^2 == neg_one and K^2 == neg_one
832
True
833
sage: J*I == neg_one*K
834
True
835
sage: Q.center().order() == 2
836
True
837
sage: neg_one in Q.center()
838
True
839
840
TESTS::
841
842
sage: groups.permutation.Quaternion()
843
Quaternion group of order 8 as a permutation group
844
845
AUTHOR:
846
-- Rob Beezer (2009-10-09)
847
"""
848
def __init__(self):
849
r"""
850
TESTS::
851
852
sage: Q = QuaternionGroup()
853
sage: TestSuite(Q).run()
854
"""
855
DiCyclicGroup.__init__(self, 2)
856
857
def _repr_(self):
858
r"""
859
EXAMPLES::
860
861
sage: Q=QuaternionGroup(); Q
862
Quaternion group of order 8 as a permutation group
863
"""
864
return "Quaternion group of order 8 as a permutation group"
865
866
class GeneralDihedralGroup(PermutationGroup_generic):
867
r"""
868
The Generalized Dihedral Group generated by the abelian group with
869
direct factors in the input list.
870
871
INPUT:
872
873
- ``factors`` - a list of the sizes of the cyclic factors of the
874
abelian group being dihedralized (this will be sorted once
875
entered)
876
877
OUTPUT:
878
879
For a given abelian group (noting that each finite abelian group
880
can be represented as the direct product of cyclic groups), the
881
General Dihedral Group it generates is simply the semi-direct
882
product of the given group with `C_2`, where the nonidentity
883
element of `C_2` acts on the abelian group by turning each element
884
into its inverse. In this implementation, each input abelian group
885
will be standardized so as to act on a minimal amount of letters.
886
This will be done by breaking the direct factors into products of
887
p-groups, before this new set of factors is ordered from smallest
888
to largest for complete standardization. Note that the generalized
889
dihedral group corresponding to a cyclic group, `C_n`, is simply
890
the dihedral group `D_n`.
891
892
EXAMPLES:
893
894
As is noted in [1], `Dih(C_3 \times C_3)` has the presentation
895
896
.. MATH::
897
898
\langle a, b, c\mid a^{3}, b^{3}, c^{2}, ab = ba, ac = ca^{-1}, bc = cb^{-1} \rangle
899
900
Note also the fact, verified by [1]_, that the dihedralization of
901
`C_3 \times C_3` is the only nonabelian group of order 18
902
with no element of order 6. ::
903
904
sage: G = GeneralDihedralGroup([3,3])
905
sage: G
906
Generalized dihedral group generated by C3 x C3
907
sage: G.order()
908
18
909
sage: G.gens()
910
[(4,5,6), (2,3)(5,6), (1,2,3)]
911
sage: a = G.gens()[2]; b = G.gens()[0]; c = G.gens()[1]
912
sage: a.order() == 3, b.order() == 3, c.order() == 2
913
(True, True, True)
914
sage: a*b == b*a, a*c == c*a.inverse(), b*c == c*b.inverse()
915
(True, True, True)
916
sage: G.subgroup([a,b,c]) == G
917
True
918
sage: G.is_abelian()
919
False
920
sage: all([x.order() != 6 for x in G])
921
True
922
923
If all of the direct factors are `C_2`, then the action turning
924
each element into its inverse is trivial, and the semi-direct
925
product becomes a direct product. ::
926
927
sage: G = GeneralDihedralGroup([2,2,2])
928
sage: G.order()
929
16
930
sage: G.gens()
931
[(7,8), (5,6), (3,4), (1,2)]
932
sage: G.is_abelian()
933
True
934
sage: H = KleinFourGroup()
935
sage: G.is_isomorphic(H.direct_product(H)[0])
936
True
937
938
If two nonidentical input lists generate isomorphic abelian
939
groups, then they will generate identical groups (with each direct
940
factor broken up into its prime factors), but they will still have
941
distinct descriptions. Note that If `gcd(n,m)=1`, then `C_n \times
942
C_m \cong C_{nm}`, while the general dihedral groups
943
generated by isomorphic abelian groups should be themselves
944
isomorphic. ::
945
946
sage: G = GeneralDihedralGroup([6,34,46,14])
947
sage: H = GeneralDihedralGroup([7,17,3,46,2,2,2])
948
sage: G == H, G.gens() == H.gens()
949
(True, True)
950
sage: [x.order() for x in G.gens()]
951
[23, 17, 7, 2, 3, 2, 2, 2, 2]
952
sage: G
953
Generalized dihedral group generated by C6 x C34 x C46 x C14
954
sage: H
955
Generalized dihedral group generated by C7 x C17 x C3 x C46 x C2 x C2 x C2
956
957
A cyclic input yields a Classical Dihedral Group. ::
958
959
sage: G = GeneralDihedralGroup([6])
960
sage: D = DihedralGroup(6)
961
sage: G.is_isomorphic(D)
962
True
963
964
A Generalized Dihedral Group will always have size twice the
965
underlying group, be solvable (as it has an abelian subgroup with
966
index 2), and, unless the underlying group is of the form
967
`{C_2}^n`, be nonabelian (by the structure theorem of finite
968
abelian groups and the fact that a semi-direct product is a
969
direct product only when the underlying action is trivial). ::
970
971
sage: G = GeneralDihedralGroup([6,18,33,60])
972
sage: (6*18*33*60)*2
973
427680
974
sage: G.order()
975
427680
976
sage: G.is_solvable()
977
True
978
sage: G.is_abelian()
979
False
980
981
TESTS::
982
983
sage: G = GeneralDihedralGroup("foobar")
984
Traceback (most recent call last):
985
...
986
TypeError: factors of abelian group must be a list, not foobar
987
988
sage: GeneralDihedralGroup([])
989
Traceback (most recent call last):
990
...
991
ValueError: there must be at least one direct factor in the abelian group being dihedralized
992
993
sage: GeneralDihedralGroup([3, 1.5])
994
Traceback (most recent call last):
995
...
996
TypeError: the input list must consist of Integers
997
998
sage: GeneralDihedralGroup([4, -8])
999
Traceback (most recent call last):
1000
...
1001
ValueError: all direct factors must be greater than 1
1002
1003
REFERENCES:
1004
1005
.. [1] A.D. Thomas and G.V. Wood, Group Tables (Exeter: Shiva Publishing, 1980)
1006
1007
AUTHOR:
1008
1009
- Kevin Halasz (2012-7-12)
1010
1011
"""
1012
def __init__(self, factors):
1013
r"""
1014
Init method of class <GeneralDihedralGroup>. See the docstring
1015
for :class:`<GeneralDihedralGroup>`.
1016
1017
EXAMPLES::
1018
1019
sage: G = GeneralDihedralGroup([5,5,5])
1020
sage: G.order()
1021
250
1022
sage: TestSuite(G).run()
1023
"""
1024
1025
1026
if not isinstance(factors, list):
1027
msg = "factors of abelian group must be a list, not {}"
1028
raise TypeError(msg.format(factors))
1029
1030
if len(factors) < 1:
1031
raise ValueError('there must be at least one direct factor in the abelian group being dihedralized')
1032
1033
if not all(isinstance(x, Integer) for x in factors):
1034
raise TypeError('the input list must consist of Integers')
1035
1036
if not all(x >= 2 for x in factors):
1037
s = 'all direct factors must be greater than 1'
1038
raise ValueError(s)
1039
1040
self.factors = factors
1041
# To get uniform outputs for isomorphic inputs, we break
1042
# each inputted cyclic group into a direct product of cyclic
1043
# p-groups
1044
simplified = [term[0]**term[1] for a in factors for term in a.factor()]
1045
simplified.sort()
1046
1047
gens = []
1048
# genx is an element of order two that turns each of the
1049
# generators of the abelian group into its inverse via
1050
# conjugation
1051
genx = []
1052
jumppoint = Integer(1)
1053
for a in simplified:
1054
# create one of the generators for the abelian group
1055
gens.append([tuple(range(jumppoint, jumppoint+a))])
1056
# make contribution to the generator that dihedralizes the
1057
# abelian group
1058
for i in range(1, (a//2)+1):
1059
if i != a-i:
1060
genx.append(tuple((jumppoint+i, jumppoint+a-i)))
1061
jumppoint = jumppoint + a
1062
# If all of the direct factors are C2, then the action turning
1063
# each element into its inverse is trivial, and the
1064
# semi-direct product becomes a direct product, so we simply
1065
# tack on another disjoint transposition
1066
if all(x==2 for x in simplified):
1067
genx.append(tuple((jumppoint, jumppoint+1)))
1068
gens.append(genx)
1069
PermutationGroup_generic.__init__(self, gens=gens)
1070
1071
def _repr_(self):
1072
r"""
1073
EXAMPLES::
1074
1075
sage: G = GeneralDihedralGroup([2,4,8])
1076
sage: G
1077
Generalized dihedral group generated by C2 x C4 x C8
1078
"""
1079
grouplist = []
1080
for n in self.factors:
1081
grouplist.append('C{}'.format(n))
1082
return 'Generalized dihedral group generated by ' + ' x '.join(grouplist)
1083
1084
class DihedralGroup(PermutationGroup_unique):
1085
def __init__(self, n):
1086
"""
1087
The Dihedral group of order $2n$ for any integer $n\geq 1$.
1088
1089
INPUT:
1090
n -- a positive integer
1091
1092
OUTPUT:
1093
-- the dihedral group of order 2*n, as a permutation group
1094
1095
.. note::
1096
This group is also available via ``groups.permutation.Dihedral()``.
1097
1098
EXAMPLES::
1099
1100
sage: DihedralGroup(1)
1101
Dihedral group of order 2 as a permutation group
1102
1103
sage: DihedralGroup(2)
1104
Dihedral group of order 4 as a permutation group
1105
sage: DihedralGroup(2).gens()
1106
[(3,4), (1,2)]
1107
1108
sage: DihedralGroup(5).gens()
1109
[(1,2,3,4,5), (1,5)(2,4)]
1110
sage: list(DihedralGroup(5))
1111
[(), (2,5)(3,4), (1,2)(3,5), (1,2,3,4,5), (1,3)(4,5), (1,3,5,2,4), (1,4)(2,3), (1,4,2,5,3), (1,5,4,3,2), (1,5)(2,4)]
1112
1113
sage: G = DihedralGroup(6)
1114
sage: G.order()
1115
12
1116
sage: G = DihedralGroup(5)
1117
sage: G.order()
1118
10
1119
sage: G
1120
Dihedral group of order 10 as a permutation group
1121
sage: G.gens()
1122
[(1,2,3,4,5), (1,5)(2,4)]
1123
1124
sage: DihedralGroup(0)
1125
Traceback (most recent call last):
1126
...
1127
ValueError: n must be positive
1128
1129
TESTS::
1130
1131
sage: TestSuite(G).run()
1132
sage: G.category()
1133
Category of finite permutation groups
1134
sage: TestSuite(G).run()
1135
1136
sage: groups.permutation.Dihedral(6)
1137
Dihedral group of order 12 as a permutation group
1138
"""
1139
n = Integer(n)
1140
if n <= 0:
1141
raise ValueError("n must be positive")
1142
1143
# the first generator generates the cyclic subgroup of D_n, <(1...n)> in
1144
# cycle notation
1145
gen0 = range(1,n+1)
1146
1147
if n < 1:
1148
raise ValueError("n (=%s) must be >= 1" % n)
1149
1150
# D_1 is a subgroup of S_2, we need the cyclic group of order 2
1151
if n == 1:
1152
gens = CyclicPermutationGroup(2).gens()
1153
elif n == 2:
1154
gens = ((1,2),(3,4))
1155
else:
1156
gen1 = [(i, n-i+1) for i in range(1, n//2 +1)]
1157
gens = tuple([tuple(gen0),tuple(gen1)])
1158
1159
PermutationGroup_generic.__init__(self, gens)
1160
1161
def _repr_(self):
1162
"""
1163
EXAMPLES::
1164
1165
sage: G = DihedralGroup(5); G
1166
Dihedral group of order 10 as a permutation group
1167
"""
1168
return "Dihedral group of order %s as a permutation group"%self.order()
1169
1170
1171
1172
class SplitMetacyclicGroup(PermutationGroup_unique):
1173
def __init__(self, p, m):
1174
r"""
1175
The split metacyclic group of order `p^m`.
1176
1177
INPUT:
1178
1179
- ``p`` - a prime number that is the prime underlying this
1180
p-group
1181
1182
- ``m`` - a positive integer such that the order of this
1183
group is the `p^m`. Be aware that, for even `p`, `m` must be
1184
greater than 3, while for odd `p`, `m` must be greater than
1185
2.
1186
1187
OUTPUT:
1188
1189
The split metacyclic group of order `p^m`. This family of
1190
groups has presentation
1191
1192
.. MATH::
1193
1194
\langle x, y\mid x^{p^{m-1}}, y^{p}, y^{-1}xy=x^{1+p^{m-2}} \rangle
1195
1196
This family is notable because, for odd `p`, these are the
1197
only `p`-groups with a cyclic subgroup of index `p`, a
1198
result proven in [GORENSTEIN]_. It is also shown in
1199
[GORENSTEIN]_ that this is one of four families containing
1200
nonabelian 2-groups with a cyclic subgroup of index 2
1201
(with the others being the dicyclic groups, the dihedral
1202
groups, and the semidihedral groups).
1203
1204
EXAMPLES:
1205
1206
Using the last relation in the group's presentation,
1207
one can see that the elements of the form `y^{i}x`,
1208
`0 \leq i \leq p-1` all have order `p^{m-1}`, as it can be
1209
shown that their `p` th powers are all `x^{p^{m-2}+p}`,
1210
an element with order `p^{m-2}`. Manipulation of the same
1211
relation shows that none of these elements are powers of
1212
any other. Thus, there are `p` cyclic maximal subgroups in
1213
each split metacyclic group. It is also proven in
1214
[GORENSTEIN]_ that this family has commutator subgroup
1215
of order `p`, and the Frattini subgroup is equal to the
1216
center, with this group being cyclic of order `p^{m-2}`.
1217
These characteristics are necessary to identify these
1218
groups in the case that `p=2`, although the possession of
1219
a cyclic maximal subgroup in a non-abelian `p`-group is
1220
enough for odd `p` given the group's order. ::
1221
1222
sage: G = SplitMetacyclicGroup(2,8)
1223
sage: G.order() == 2**8
1224
True
1225
sage: G.is_abelian()
1226
False
1227
sage: len([H for H in G.subgroups() if H.order() == 2^7 and H.is_cyclic()])
1228
2
1229
sage: G.commutator().order()
1230
2
1231
sage: G.frattini_subgroup() == G.center()
1232
True
1233
sage: G.center().order() == 2^6
1234
True
1235
sage: G.center().is_cyclic()
1236
True
1237
1238
sage: G = SplitMetacyclicGroup(3,3)
1239
sage: len([H for H in G.subgroups() if H.order() == 3^2 and H.is_cyclic()])
1240
3
1241
sage: G.commutator().order()
1242
3
1243
sage: G.frattini_subgroup() == G.center()
1244
True
1245
sage: G.center().order()
1246
3
1247
1248
TESTS::
1249
1250
sage: G = SplitMetacyclicGroup(3,2.5)
1251
Traceback (most recent call last):
1252
...
1253
TypeError: both p and m must be integers
1254
1255
sage: G = SplitMetacyclicGroup(4,3)
1256
Traceback (most recent call last):
1257
...
1258
ValueError: p must be prime, 4 is not prime
1259
1260
sage: G = SplitMetacyclicGroup(2,2)
1261
Traceback (most recent call last):
1262
...
1263
ValueError: if prime is 2, the exponent must be greater than 3, not 2
1264
1265
sage: G = SplitMetacyclicGroup(11,2)
1266
Traceback (most recent call last):
1267
...
1268
ValueError: if prime is odd, the exponent must be greater than 2, not 2
1269
1270
REFERENCES:
1271
1272
.. [GORENSTEIN] Daniel Gorenstein, Finite Groups (New York: Chelsea Publishing, 1980)
1273
1274
AUTHOR:
1275
1276
- Kevin Halasz (2012-8-7)
1277
1278
"""
1279
1280
if not isinstance(p, Integer) or not isinstance(m, Integer):
1281
raise TypeError('both p and m must be integers')
1282
1283
if not p in Primes():
1284
raise ValueError('p must be prime, %s is not prime' % p)
1285
1286
if p == 2 and m <= 3:
1287
raise ValueError('if prime is 2, the exponent must be greater than 3, not %s' % m)
1288
1289
if p%2 == 1 and m <= 2:
1290
raise ValueError('if prime is odd, the exponent must be greater than 2, not %s' % m)
1291
1292
self.p = p
1293
self.m = m
1294
1295
# x is created with list, rather than cycle, notation
1296
x = range(2, p**(m-1)+1)
1297
x.append(1)
1298
# y is also created with list notation, where the list
1299
# used is equivalent to the cycle notation representation of
1300
# x^(1+p^(m-2)). This technique is inspired by exercise 5.30
1301
# Judson's "Abstract Algebra" (abstract.pugetsound.edu).
1302
y = [1]
1303
point = 1
1304
for i in range(p**(m-1)-1):
1305
next = (point + 1 + p**(m-2))%(p**(m-1))
1306
if next == 0:
1307
next = p**(m-1)
1308
y.append(next)
1309
point = next
1310
PermutationGroup_unique.__init__(self, gens = [x,y])
1311
1312
def _repr_(self):
1313
"""
1314
EXAMPLES::
1315
1316
sage: G = SplitMetacyclicGroup(7,4);G
1317
The split metacyclic group of order 7 ^ 4
1318
"""
1319
return 'The split metacyclic group of order %s ^ %s'%(self.p,self.m)
1320
1321
class SemidihedralGroup(PermutationGroup_unique):
1322
def __init__(self,m):
1323
r"""
1324
The semidihedral group of order `2^m`.
1325
1326
INPUT:
1327
1328
- ``m`` - a positive integer; the power of 2 that is the
1329
group's order
1330
1331
OUTPUT:
1332
1333
The semidihedral group of order `2^m`. These groups can be
1334
thought of as a semidirect product of `C_{2^{m-1}}` with
1335
`C_2`, where the nontrivial element of `C_2` is sent to
1336
the element of the automorphism group of `C_{2^{m-1}}` that
1337
sends elements to their `-1+2^{m-2}` th power. Thus, the
1338
group has the presentation:
1339
1340
.. MATH::
1341
1342
\langle x, y\mid x^{2^{m-1}}, y^{2}, y^{-1}xy=x^{-1+2^{m-2}} \rangle
1343
1344
This family is notable because it is made up of non-abelian
1345
2-groups that all contain cyclic subgroups of index 2. It
1346
is one of only four such families.
1347
1348
EXAMPLES:
1349
1350
In [GORENSTEIN1980]_ it is shown that the semidihedral groups
1351
have center of order 2. It is also shown that they have a
1352
Frattini subgroup equal to their commutator, which is a
1353
cyclic subgroup of order `2^{m-2}`. ::
1354
1355
sage: G = SemidihedralGroup(12)
1356
sage: G.order() == 2^12
1357
True
1358
sage: G.commutator() == G.frattini_subgroup()
1359
True
1360
sage: G.commutator().order() == 2^10
1361
True
1362
sage: G.commutator().is_cyclic()
1363
True
1364
sage: G.center().order()
1365
2
1366
1367
sage: G = SemidihedralGroup(4)
1368
sage: len([H for H in G.subgroups() if H.is_cyclic() and H.order() == 8])
1369
1
1370
sage: G.gens()
1371
[(2,4)(3,7)(6,8), (1,2,3,4,5,6,7,8)]
1372
sage: x = G.gens()[1]; y = G.gens()[0]
1373
sage: x.order() == 2^3; y.order() == 2
1374
True
1375
True
1376
sage: y*x*y == x^(-1+2^2)
1377
True
1378
1379
TESTS::
1380
1381
sage: G = SemidihedralGroup(4.4)
1382
Traceback (most recent call last):
1383
...
1384
TypeError: m must be an integer, not 4.40000000000000
1385
1386
sage: G = SemidihedralGroup(-5)
1387
Traceback (most recent call last):
1388
...
1389
ValueError: the exponent must be greater than 3, not -5
1390
1391
REFERENCES:
1392
1393
.. [GORENSTEIN1980] Daniel Gorenstein, Finite Groups (New York: Chelsea Publishing, 1980)
1394
1395
AUTHOR:
1396
1397
- Kevin Halasz (2012-8-7)
1398
1399
"""
1400
if not isinstance(m, Integer):
1401
raise TypeError('m must be an integer, not %s' % m)
1402
1403
if m <= 3:
1404
raise ValueError('the exponent must be greater than 3, not %s' % m)
1405
1406
self.m = m
1407
1408
# x is created with list, rather than cycle, notation
1409
x = range(2, 2**(m-1)+1)
1410
x.append(1)
1411
# y is also created with list notation, where the list
1412
# used is equivalent to the cycle notation representation of
1413
# x^(1+p^(m-2)). This technique is inspired by exercise 5.30
1414
# Judson's "Abstract Algebra" (abstract.pugetsound.edu).
1415
y = [1]
1416
k = 1
1417
for i in range(2**(m-1)-1):
1418
next = (k - 1 + 2**(m-2))%(2**(m-1))
1419
if next == 0:
1420
next = 2**(m-1)
1421
y.append(next)
1422
k = next
1423
PermutationGroup_unique.__init__(self, gens = [x,y])
1424
1425
def _repr_(self):
1426
r"""
1427
EXAMPLES::
1428
1429
sage: G = SemidihedralGroup(6); G
1430
The semidiheral group of order 64
1431
"""
1432
return 'The semidiheral group of order %s'%(2**self.m)
1433
1434
class MathieuGroup(PermutationGroup_unique):
1435
def __init__(self, n):
1436
"""
1437
The Mathieu group of degree $n$.
1438
1439
INPUT:
1440
n -- a positive integer in {9, 10, 11, 12, 21, 22, 23, 24}.
1441
1442
OUTPUT:
1443
-- the Mathieu group of degree n, as a permutation group
1444
1445
.. note::
1446
This group is also available via ``groups.permutation.Mathieu()``.
1447
1448
EXAMPLES::
1449
1450
sage: G = MathieuGroup(12)
1451
sage: G
1452
Mathieu group of degree 12 and order 95040 as a permutation group
1453
1454
TESTS::
1455
1456
sage: G.category()
1457
Category of finite permutation groups
1458
sage: TestSuite(G).run(skip=["_test_enumerated_set_contains", "_test_enumerated_set_iter_list"])
1459
1460
sage: groups.permutation.Mathieu(9)
1461
Mathieu group of degree 9 and order 72 as a permutation group
1462
1463
Note: this is a fairly big group, so we skip some tests that
1464
currently require to list all the elements of the group,
1465
because there is no proper iterator yet.
1466
"""
1467
n = Integer(n)
1468
self._n = n
1469
if not(n in [9, 10, 11, 12, 21, 22, 23, 24]):
1470
raise ValueError("argument must belong to {9, 10, 11, 12, 21, 22, 23, 24}.")
1471
id = 'MathieuGroup(%s)'%n
1472
PermutationGroup_generic.__init__(self, gap_group=id)
1473
1474
def _repr_(self):
1475
"""
1476
EXAMPLES::
1477
1478
sage: G = MathieuGroup(12); G
1479
Mathieu group of degree 12 and order 95040 as a permutation group
1480
"""
1481
return "Mathieu group of degree %s and order %s as a permutation group"%(self._n,self.order())
1482
1483
class TransitiveGroup(PermutationGroup_unique):
1484
def __init__(self, d, n):
1485
"""
1486
The transitive group from the GAP tables of transitive groups.
1487
1488
INPUT:
1489
d -- non-negative integer; the degree
1490
n -- positive integer; the index of the group in the GAP database, starting at 1
1491
1492
1493
OUTPUT:
1494
the n-th transitive group of degree d
1495
1496
.. note::
1497
This group is also available via ``groups.permutation.Transitive()``.
1498
1499
EXAMPLES::
1500
1501
sage: TransitiveGroup(0,1)
1502
Transitive group number 1 of degree 0
1503
sage: TransitiveGroup(1,1)
1504
Transitive group number 1 of degree 1
1505
sage: G = TransitiveGroup(5, 2); G # optional - database_gap
1506
Transitive group number 2 of degree 5
1507
sage: G.gens() # optional - database_gap
1508
[(1,2,3,4,5), (1,4)(2,3)]
1509
1510
sage: G.category() # optional - database_gap
1511
Category of finite permutation groups
1512
1513
.. warning:: this follows GAP's naming convention of indexing
1514
the transitive groups starting from ``1``::
1515
1516
sage: TransitiveGroup(5,0) # optional - database_gap
1517
Traceback (most recent call last):
1518
...
1519
ValueError: Index n must be in {1,..,5}
1520
1521
.. warning:: only transitive groups of "small" degree are
1522
available in GAP's database::
1523
1524
sage: TransitiveGroup(31,1) # optional - database_gap
1525
Traceback (most recent call last):
1526
...
1527
NotImplementedError: Only the transitive groups of order less than 30 are available in GAP's database
1528
1529
TESTS::
1530
1531
1532
sage: groups.permutation.Transitive(1, 1)
1533
Transitive group number 1 of degree 1
1534
1535
sage: TestSuite(TransitiveGroup(0,1)).run()
1536
sage: TestSuite(TransitiveGroup(1,1)).run()
1537
sage: TestSuite(TransitiveGroup(5,2)).run()# optional - database_gap
1538
1539
sage: TransitiveGroup(1,5) # optional - database_gap
1540
Traceback (most recent call last):
1541
...
1542
ValueError: Index n must be in {1,..,1}
1543
"""
1544
d = Integer(d)
1545
n = Integer(n)
1546
if d < 0:
1547
raise ValueError("Degree d must not be negative")
1548
max_n = TransitiveGroups(d).cardinality()
1549
if n > max_n or n <= 0:
1550
raise ValueError("Index n must be in {1,..,%s}" % max_n)
1551
gap_group = 'Group([()])' if d in [0,1] else 'TransitiveGroup(%s,%s)'%(d,n)
1552
try:
1553
PermutationGroup_generic.__init__(self, gap_group=gap_group)
1554
except RuntimeError:
1555
from sage.misc.misc import verbose
1556
verbose("Warning: Computing with TransitiveGroups requires the optional database_gap package. Please install it.", level=0)
1557
1558
self._d = d
1559
self._n = n
1560
self._domain = range(1, d+1)
1561
1562
def _repr_(self):
1563
"""
1564
EXAMPLES::
1565
1566
sage: G = TransitiveGroup(1,1); G
1567
Transitive group number 1 of degree 1
1568
"""
1569
return "Transitive group number %s of degree %s"%(self._n, self._d)
1570
1571
def TransitiveGroups(d=None):
1572
"""
1573
INPUT:
1574
1575
- ``d`` -- an integer (optional)
1576
1577
Returns the set of all transitive groups of a given degree
1578
``d`` up to isomorphisms. If ``d`` is not specified, it returns the set of all
1579
transitive groups up to isomorphisms.
1580
1581
Warning: TransitiveGroups requires the optional GAP database
1582
package. Please install it with ``sage -i database_gap``.
1583
1584
EXAMPLES::
1585
1586
sage: TransitiveGroups(3)
1587
Transitive Groups of degree 3
1588
sage: TransitiveGroups(7)
1589
Transitive Groups of degree 7
1590
sage: TransitiveGroups(8)
1591
Transitive Groups of degree 8
1592
1593
sage: TransitiveGroups()
1594
Transitive Groups
1595
1596
.. warning:: in practice, the database currently only contains
1597
transitive groups up to degree 30::
1598
1599
sage: TransitiveGroups(31).cardinality() # optional - database_gap
1600
Traceback (most recent call last):
1601
...
1602
NotImplementedError: Only the transitive groups of order less than 30 are available in GAP's database
1603
1604
"""
1605
if d == None:
1606
return TransitiveGroupsAll()
1607
else:
1608
d = Integer(d)
1609
if d < 0:
1610
raise ValueError("A transitive group acts on a non negative integer number of positions")
1611
return TransitiveGroupsOfDegree(d)
1612
1613
class TransitiveGroupsAll(DisjointUnionEnumeratedSets):
1614
"""
1615
The infinite set of all transitive groups up to isomorphisms.
1616
1617
EXAMPLES::
1618
1619
sage: L = TransitiveGroups(); L
1620
Transitive Groups
1621
sage: L.category()
1622
Category of infinite enumerated sets
1623
sage: L.cardinality()
1624
+Infinity
1625
1626
sage: p = L.__iter__() # optional - database_gap
1627
sage: (p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next()) # optional - database_gap
1628
(Transitive group number 1 of degree 0, Transitive group number 1 of degree 1, Transitive group number 1 of degree 2, Transitive group number 1 of degree 3, Transitive group number 2 of degree 3, Transitive group number 1 of degree 4, Transitive group number 2 of degree 4, Transitive group number 3 of degree 4)
1629
1630
TESTS::
1631
1632
sage: TestSuite(TransitiveGroups()).run() # optional - database_gap # long time
1633
"""
1634
def __init__(self):
1635
"""
1636
TESTS::
1637
1638
sage: S = TransitiveGroups() # optional - database_gap
1639
sage: S.category() # optional - database_gap
1640
Category of infinite enumerated sets
1641
"""
1642
DisjointUnionEnumeratedSets.__init__(self, Family(NonNegativeIntegers(), lambda i: TransitiveGroups(i)) )
1643
1644
def _repr_(self):
1645
"""
1646
TESTS::
1647
1648
sage: TransitiveGroups() # optional - database_gap # indirect doctest
1649
Transitive Groups
1650
"""
1651
return "Transitive Groups"
1652
1653
def __contains__(self, G):
1654
r"""
1655
EXAMPLES::
1656
1657
sage: TransitiveGroup(5,2) in TransitiveGroups() # optional - database_gap
1658
True
1659
sage: TransitiveGroup(6,5) in TransitiveGroups() # optional - database_gap
1660
True
1661
sage: 1 in TransitiveGroups() # optional - database_gap
1662
False
1663
"""
1664
return isinstance(G,TransitiveGroup)
1665
1666
class TransitiveGroupsOfDegree(CachedRepresentation, Parent):
1667
"""
1668
The set of all transitive groups of a given (small) degree up to isomorphisms.
1669
1670
EXAMPLES::
1671
1672
sage: S = TransitiveGroups(4); S # optional - database_gap
1673
Transitive Groups of degree 4
1674
sage: list(S) # optional - database_gap
1675
[Transitive group number 1 of degree 4, Transitive group number 2 of degree 4, Transitive group number 3 of degree 4, Transitive group number 4 of degree 4, Transitive group number 5 of degree 4]
1676
1677
sage: TransitiveGroups(5).an_element() # optional - database_gap
1678
Transitive group number 1 of degree 5
1679
1680
We write the cardinality of all transitive groups of degree 5::
1681
1682
sage: for G in TransitiveGroups(5): # optional - database_gap
1683
... print G.cardinality()
1684
5
1685
10
1686
20
1687
60
1688
120
1689
1690
TESTS::
1691
1692
sage: TestSuite(TransitiveGroups(3)).run() # optional - database_gap
1693
1694
1695
"""
1696
def __init__(self, n):
1697
"""
1698
TESTS::
1699
1700
sage: S = TransitiveGroups(4) # optional - database_gap
1701
sage: S.category() # optional - database_gap
1702
Category of finite enumerated sets
1703
"""
1704
self._degree = n
1705
Parent.__init__(self, category = FiniteEnumeratedSets())
1706
1707
def _repr_(self):
1708
"""
1709
TESTS::
1710
1711
sage: TransitiveGroups(6) # optional - database_gap
1712
Transitive Groups of degree 6
1713
"""
1714
return "Transitive Groups of degree %s"%(self._degree)
1715
1716
def __contains__(self, G):
1717
r"""
1718
EXAMPLES::
1719
1720
sage: TransitiveGroup(6,5) in TransitiveGroups(4) # optional - database_gap
1721
False
1722
sage: TransitiveGroup(4,3) in TransitiveGroups(4) # optional - database_gap
1723
True
1724
sage: 1 in TransitiveGroups(4) # optional - database_gap
1725
False
1726
"""
1727
if isinstance(G,TransitiveGroup):
1728
return G._d == self._degree
1729
else:
1730
False
1731
1732
def __getitem__(self, n):
1733
r"""
1734
INPUT:
1735
1736
- ``n`` -- a positive integer
1737
1738
Returns the `n`-th transitive group of a given degree.
1739
1740
EXAMPLES::
1741
1742
sage: TransitiveGroups(5)[3] # optional - database_gap
1743
Transitive group number 3 of degree 5
1744
1745
.. warning:: this follows GAP's naming convention of indexing
1746
the transitive groups starting from ``1``::
1747
1748
sage: TransitiveGroups(5)[0] # optional - database_gap
1749
Traceback (most recent call last):
1750
...
1751
ValueError: Index n must be in {1,..,5}
1752
"""
1753
return TransitiveGroup(self._degree, n)
1754
1755
def __iter__(self):
1756
"""
1757
EXAMPLES::
1758
1759
sage: list(TransitiveGroups(5)) # indirect doctest # optional - database_gap
1760
[Transitive group number 1 of degree 5, Transitive group number 2 of degree 5, Transitive group number 3 of degree 5, Transitive group number 4 of degree 5, Transitive group number 5 of degree 5]
1761
"""
1762
for n in xrange(1, self.cardinality() + 1):
1763
yield self[n]
1764
1765
@cached_method
1766
def cardinality(self):
1767
r"""
1768
Returns the cardinality of ``self``, that is the number of
1769
transitive groups of a given degree.
1770
1771
EXAMPLES::
1772
1773
sage: TransitiveGroups(0).cardinality() # optional - database_gap
1774
1
1775
sage: TransitiveGroups(2).cardinality() # optional - database_gap
1776
1
1777
sage: TransitiveGroups(7).cardinality() # optional - database_gap
1778
7
1779
sage: TransitiveGroups(12).cardinality() # optional - database_gap
1780
301
1781
sage: [TransitiveGroups(i).cardinality() for i in range(11)] # optional - database_gap
1782
[1, 1, 1, 2, 5, 5, 16, 7, 50, 34, 45]
1783
1784
.. warning::
1785
1786
The database_gap contains all transitive groups
1787
up to degree 30::
1788
1789
sage: TransitiveGroups(31).cardinality() # optional - database_gap
1790
Traceback (most recent call last):
1791
...
1792
NotImplementedError: Only the transitive groups of order less than 30 are available in GAP's database
1793
1794
TESTS::
1795
1796
sage: type(TransitiveGroups(12).cardinality()) # optional - database_gap
1797
<type 'sage.rings.integer.Integer'>
1798
sage: type(TransitiveGroups(0).cardinality())
1799
<type 'sage.rings.integer.Integer'>
1800
"""
1801
# gap.NrTransitiveGroups(0) fails, so Sage needs to handle this
1802
1803
# While we are at it, and since Sage also handles the
1804
# transitive group of degree 1, we may as well handle 1
1805
if self._degree <= 1:
1806
return Integer(1)
1807
else:
1808
try:
1809
return Integer(gap.NrTransitiveGroups(gap(self._degree)))
1810
except RuntimeError:
1811
from sage.misc.misc import verbose
1812
verbose("Warning: TransitiveGroups requires the GAP database package. Please install it with ``sage -i database_gap``.", level=0)
1813
except TypeError:
1814
raise NotImplementedError("Only the transitive groups of order less than 30 are available in GAP's database")
1815
1816
class PrimitiveGroup(PermutationGroup_unique):
1817
"""
1818
The primitive group from the GAP tables of primitive groups.
1819
1820
INPUT:
1821
1822
- ``d`` -- non-negative integer. the degree of the group.
1823
1824
- ``n`` -- positive integer. the index of the group in the GAP
1825
database, starting at 1
1826
1827
OUTPUT:
1828
1829
The ``n``-th primitive group of degree ``d``.
1830
1831
EXAMPLES::
1832
1833
sage: PrimitiveGroup(0,1)
1834
Trivial group
1835
sage: PrimitiveGroup(1,1)
1836
Trivial group
1837
sage: G = PrimitiveGroup(5, 2); G # optional - database_gap
1838
D(2*5)
1839
sage: G.gens() # optional - database_gap
1840
[(2,4)(3,5), (1,2,3,5,4)]
1841
sage: G.category() # optional - database_gap
1842
Category of finite permutation groups
1843
1844
.. warning::
1845
1846
this follows GAP's naming convention of indexing the primitive
1847
groups starting from ``1``::
1848
1849
sage: PrimitiveGroup(5,0) # optional - database_gap
1850
Traceback (most recent call last):
1851
...
1852
ValueError: Index n must be in {1,..,5}
1853
1854
Only primitive groups of "small" degree are available in GAP's
1855
database::
1856
1857
sage: PrimitiveGroup(2500,1) # optional - database_gap
1858
Traceback (most recent call last):
1859
...
1860
NotImplementedError: Only the primitive groups of degree less
1861
than 2500 are available in GAP's database
1862
"""
1863
1864
def __init__(self, d, n):
1865
"""
1866
The Python constructor.
1867
1868
INPUT/OUTPUT:
1869
1870
See :class:`PrimitiveGroup`.
1871
1872
TESTS::
1873
1874
sage: TestSuite(PrimitiveGroup(0,1)).run()
1875
sage: TestSuite(PrimitiveGroup(1,1)).run()
1876
sage: TestSuite(PrimitiveGroup(5,2)).run() # optional - database_gap
1877
sage: PrimitiveGroup(6,5) # optional - database_gap
1878
Traceback (most recent call last):
1879
...
1880
ValueError: Index n must be in {1,..,4}
1881
"""
1882
d = Integer(d)
1883
n = Integer(n)
1884
if d < 0:
1885
raise ValueError("Degree d must not be negative")
1886
max_n = PrimitiveGroups(d).cardinality()
1887
if n > max_n or n <= 0:
1888
raise ValueError("Index n must be in {1,..,%s}" % max_n)
1889
if d in [0,1]:
1890
gap_group = gap.Group("[()]")
1891
self._pretty_name = "Trivial group"
1892
else:
1893
gap_group = gap.PrimitiveGroup(d, n)
1894
self._pretty_name = gap_group.str()
1895
try:
1896
PermutationGroup_generic.__init__(self, gap_group=gap_group)
1897
except RuntimeError:
1898
from sage.misc.misc import verbose
1899
verbose("Warning: Computing with PrimitiveGroups requires the optional database_gap package. Please install it.", level=0)
1900
1901
self._d = d
1902
self._n = n
1903
self._domain = range(1, d+1)
1904
1905
def _repr_(self):
1906
"""
1907
Return a string representation.
1908
1909
OUTPUT:
1910
1911
String.
1912
1913
EXAMPLES::
1914
1915
sage: G = PrimitiveGroup(5,1); G # optional - database_gap
1916
C(5)
1917
"""
1918
return self._pretty_name
1919
1920
def group_primitive_id(self):
1921
"""
1922
Return the index of this group in the GAP database of primitive groups.
1923
1924
Requires "optional" database_gap package.
1925
1926
OUTPUT:
1927
1928
A positive integer, following GAP's conventions.
1929
1930
EXAMPLES::
1931
1932
sage: G = PrimitiveGroup(5,2); G.group_primitive_id() # optional - database_gap
1933
2
1934
"""
1935
return self._n
1936
1937
def PrimitiveGroups(d=None):
1938
"""
1939
Return the set of all primitive groups of a given degree ``d``
1940
1941
INPUT:
1942
1943
- ``d`` -- an integer (optional)
1944
1945
OUTPUT:
1946
1947
The set of all primitive groups of a given degree ``d`` up to
1948
isomorphisms using GAP. If ``d`` is not specified, it returns the
1949
set of all primitive groups up to isomorphisms stored in GAP.
1950
1951
.. attention::
1952
1953
PrimitiveGroups requires the optional GAP database
1954
package. Please install it with
1955
``install_package(`database_gap')``.
1956
1957
EXAMPLES::
1958
1959
sage: PrimitiveGroups(3)
1960
Primitive Groups of degree 3
1961
sage: PrimitiveGroups(7)
1962
Primitive Groups of degree 7
1963
sage: PrimitiveGroups(8)
1964
Primitive Groups of degree 8
1965
sage: PrimitiveGroups()
1966
Primitive Groups
1967
1968
The database currently only contains primitive groups up to degree
1969
2499::
1970
1971
sage: PrimitiveGroups(2500).cardinality() # optional - database_gap
1972
Traceback (most recent call last):
1973
...
1974
NotImplementedError: Only the primitive groups of degree less
1975
than 2500 are available in GAP's database
1976
1977
TODO:
1978
1979
This enumeration helper could be extended based on
1980
``PrimitiveGroupsIterator`` in GAP. This method allows to
1981
enumerate groups with specified properties such as transitivity,
1982
solvability, ..., without creating all groups.
1983
"""
1984
if d == None:
1985
return PrimitiveGroupsAll()
1986
else:
1987
d = Integer(d)
1988
if d < 0:
1989
raise ValueError("A primitive group acts on a non negative integer number of positions")
1990
return PrimitiveGroupsOfDegree(d)
1991
1992
1993
class PrimitiveGroupsAll(DisjointUnionEnumeratedSets):
1994
"""
1995
The infinite set of all primitive groups up to isomorphisms.
1996
1997
EXAMPLES::
1998
1999
sage: L = PrimitiveGroups(); L
2000
Primitive Groups
2001
sage: L.category()
2002
Category of infinite enumerated sets
2003
sage: L.cardinality()
2004
+Infinity
2005
2006
sage: p = L.__iter__() # optional - database_gap
2007
sage: (p.next(), p.next(), p.next(), p.next(), # optional - database_gap
2008
... p.next(), p.next(), p.next(), p.next())
2009
(Trivial group, Trivial group, S(2), A(3), S(3), A(4), S(4), C(5))
2010
2011
TESTS::
2012
2013
sage: TestSuite(PrimitiveGroups()).run() # optional - database_gap # long time
2014
"""
2015
def __init__(self):
2016
"""
2017
TESTS::
2018
2019
sage: S = PrimitiveGroups() # optional - database_gap
2020
sage: S.category() # optional - database_gap
2021
Category of infinite enumerated sets
2022
"""
2023
DisjointUnionEnumeratedSets.__init__(self, Family(NonNegativeIntegers(), lambda i: PrimitiveGroups(i)) )
2024
2025
def _repr_(self):
2026
"""
2027
Return a string representation.
2028
2029
OUTPUT:
2030
2031
String.
2032
2033
TESTS::
2034
2035
sage: PrimitiveGroups() # optional - database_gap # indirect doctest
2036
Primitive Groups
2037
"""
2038
return "Primitive Groups"
2039
2040
def __contains__(self, G):
2041
r"""
2042
Test whether `G` is in ``self``.
2043
2044
INPUT:
2045
2046
- `G` -- anything.
2047
2048
OUTPUT:
2049
2050
Boolean.
2051
2052
EXAMPLES::
2053
2054
sage: PrimitiveGroup(5,2) in PrimitiveGroups() # optional - database_gap
2055
True
2056
sage: PrimitiveGroup(6,4) in PrimitiveGroups() # optional - database_gap
2057
True
2058
sage: 1 in PrimitiveGroups() # optional - database_gap
2059
False
2060
"""
2061
return isinstance(G,PrimitiveGroup)
2062
2063
class PrimitiveGroupsOfDegree(CachedRepresentation, Parent):
2064
"""
2065
The set of all primitive groups of a given degree up to isomorphisms.
2066
2067
EXAMPLES::
2068
2069
sage: S = PrimitiveGroups(5); S # optional - database_gap
2070
Primitive Groups of degree 5
2071
sage: S.list() # optional - database_gap
2072
[C(5), D(2*5), AGL(1, 5), A(5), S(5)]
2073
sage: S.an_element() # optional - database_gap
2074
C(5)
2075
2076
We write the cardinality of all primitive groups of degree 5::
2077
2078
sage: for G in PrimitiveGroups(5): # optional - database_gap
2079
... print G.cardinality()
2080
5
2081
10
2082
20
2083
60
2084
120
2085
2086
TESTS::
2087
2088
sage: TestSuite(PrimitiveGroups(3)).run() # optional - database_gap
2089
"""
2090
def __init__(self, n):
2091
"""
2092
TESTS::
2093
2094
sage: S = PrimitiveGroups(4) # optional - database_gap
2095
sage: S.category() # optional - database_gap
2096
Category of finite enumerated sets
2097
"""
2098
self._degree = n
2099
Parent.__init__(self, category = FiniteEnumeratedSets())
2100
2101
def _repr_(self):
2102
"""
2103
Return a string representation.
2104
2105
OUTPUT:
2106
2107
String.
2108
2109
TESTS::
2110
2111
sage: PrimitiveGroups(6) # optional - database_gap
2112
Primitive Groups of degree 6
2113
"""
2114
return "Primitive Groups of degree %s"%(self._degree)
2115
2116
def __contains__(self, G):
2117
r"""
2118
Test whether `G` is in ``self``.
2119
2120
INPUT:
2121
2122
- `G` -- anything.
2123
2124
OUTPUT:
2125
2126
Boolean.
2127
2128
EXAMPLES::
2129
2130
sage: PrimitiveGroup(6,4) in PrimitiveGroups(4) # optional - database_gap
2131
False
2132
sage: PrimitiveGroup(4,2) in PrimitiveGroups(4) # optional - database_gap
2133
True
2134
sage: 1 in PrimitiveGroups(4) # optional - database_gap
2135
False
2136
"""
2137
if isinstance(G,PrimitiveGroup):
2138
return G._d == self._degree
2139
else:
2140
False
2141
2142
def __getitem__(self, n):
2143
r"""
2144
Return the `n`-th primitive group of a given degree.
2145
2146
INPUT:
2147
2148
- ``n`` -- a positive integer
2149
2150
EXAMPLES::
2151
2152
sage: PrimitiveGroups(5)[3] # optional - database_gap
2153
AGL(1, 5)
2154
2155
.. warning::
2156
2157
this follows GAP's naming convention of indexing the
2158
primitive groups starting from ``1``::
2159
2160
sage: PrimitiveGroups(5)[0] # optional - database_gap
2161
Traceback (most recent call last):
2162
...
2163
ValueError: Index n must be in {1,..,5}
2164
"""
2165
return PrimitiveGroup(self._degree, n)
2166
2167
def __iter__(self):
2168
"""
2169
EXAMPLES::
2170
2171
sage: list(PrimitiveGroups(5)) # indirect doctest # optional - database_gap
2172
[C(5), D(2*5), AGL(1, 5), A(5), S(5)]
2173
"""
2174
for n in xrange(1, self.cardinality() + 1):
2175
yield self[n]
2176
2177
@cached_method
2178
def cardinality(self):
2179
r"""
2180
Return the cardinality of ``self``.
2181
2182
OUTPUT:
2183
2184
An integer. The number of primitive groups of a given degree
2185
up to isomorphism.
2186
2187
EXAMPLES::
2188
2189
sage: PrimitiveGroups(0).cardinality() # optional - database_gap
2190
1
2191
sage: PrimitiveGroups(2).cardinality() # optional - database_gap
2192
1
2193
sage: PrimitiveGroups(7).cardinality() # optional - database_gap
2194
7
2195
sage: PrimitiveGroups(12).cardinality() # optional - database_gap
2196
6
2197
sage: [PrimitiveGroups(i).cardinality() for i in range(11)] # optional - database_gap
2198
[1, 1, 1, 2, 2, 5, 4, 7, 7, 11, 9]
2199
2200
The database_gap contains all primitive groups up to degree
2201
2499::
2202
2203
sage: PrimitiveGroups(2500).cardinality() # optional - database_gap
2204
Traceback (most recent call last):
2205
...
2206
NotImplementedError: Only the primitive groups of degree less than
2207
2500 are available in GAP's database
2208
2209
TESTS::
2210
2211
sage: type(PrimitiveGroups(12).cardinality()) # optional - database_gap
2212
<type 'sage.rings.integer.Integer'>
2213
sage: type(PrimitiveGroups(0).cardinality())
2214
<type 'sage.rings.integer.Integer'>
2215
"""
2216
# gap.NrPrimitiveGroups(0) fails, so Sage needs to handle this
2217
# While we are at it, and since Sage also handles the
2218
# primitive group of degree 1, we may as well handle 1
2219
if self._degree <= 1:
2220
return Integer(1)
2221
elif self._degree >= 2500:
2222
raise NotImplementedError("Only the primitive groups of degree less than 2500 are available in GAP's database")
2223
else:
2224
try:
2225
return Integer(gap.NrPrimitiveGroups(gap(self._degree)))
2226
except RuntimeError:
2227
from sage.misc.misc import verbose
2228
verbose("Warning: PrimitiveGroups requires the GAP database package. Please install it with ``sage -i database_gap``.", level=0)
2229
2230
2231
class PermutationGroup_plg(PermutationGroup_unique):
2232
def base_ring(self):
2233
"""
2234
EXAMPLES::
2235
2236
sage: G = PGL(2,3)
2237
sage: G.base_ring()
2238
Finite Field of size 3
2239
2240
sage: G = PSL(2,3)
2241
sage: G.base_ring()
2242
Finite Field of size 3
2243
"""
2244
return self._base_ring
2245
2246
def matrix_degree(self):
2247
"""
2248
EXAMPLES::
2249
2250
sage: G = PSL(2,3)
2251
sage: G.matrix_degree()
2252
2
2253
"""
2254
return self._n
2255
2256
class PGL(PermutationGroup_plg):
2257
def __init__(self, n, q, name='a'):
2258
"""
2259
The projective general linear groups over GF(q).
2260
2261
INPUT:
2262
n -- positive integer; the degree
2263
q -- prime power; the size of the ground field
2264
name -- (default: 'a') variable name of indeterminate of finite field GF(q)
2265
2266
OUTPUT:
2267
PGL(n,q)
2268
2269
.. note::
2270
This group is also available via ``groups.permutation.PGL()``.
2271
2272
EXAMPLES::
2273
2274
sage: G = PGL(2,3); G
2275
Permutation Group with generators [(3,4), (1,2,4)]
2276
sage: print G
2277
The projective general linear group of degree 2 over Finite Field of size 3
2278
sage: G.base_ring()
2279
Finite Field of size 3
2280
sage: G.order()
2281
24
2282
2283
sage: G = PGL(2, 9, 'b'); G
2284
Permutation Group with generators [(3,10,9,8,4,7,6,5), (1,2,4)(5,6,8)(7,9,10)]
2285
sage: G.base_ring()
2286
Finite Field in b of size 3^2
2287
2288
sage: G.category()
2289
Category of finite permutation groups
2290
sage: TestSuite(G).run()
2291
2292
TESTS::
2293
2294
sage: groups.permutation.PGL(2, 3)
2295
Permutation Group with generators [(3,4), (1,2,4)]
2296
"""
2297
id = 'Group([()])' if n == 1 else 'PGL(%s,%s)'%(n,q)
2298
PermutationGroup_generic.__init__(self, gap_group=id)
2299
self._q = q
2300
self._base_ring = GF(q, name=name)
2301
self._n = n
2302
2303
def __str__(self):
2304
"""
2305
EXAMPLES::
2306
2307
sage: G = PGL(2,3); G
2308
Permutation Group with generators [(3,4), (1,2,4)]
2309
sage: print G
2310
The projective general linear group of degree 2 over Finite Field of size 3
2311
"""
2312
return "The projective general linear group of degree %s over %s"%(self._n, self.base_ring())
2313
2314
class PSL(PermutationGroup_plg):
2315
def __init__(self, n, q, name='a'):
2316
"""
2317
The projective special linear groups over GF(q).
2318
2319
INPUT:
2320
2321
- n -- positive integer; the degree
2322
- q -- either a prime power (the size of the ground field) or a finite field
2323
- name -- (default: 'a') variable name of indeterminate of finite field GF(q)
2324
2325
OUTPUT:
2326
2327
the group PSL(n,q)
2328
2329
.. note::
2330
2331
This group is also available via ``groups.permutation.PSL()``.
2332
2333
EXAMPLES::
2334
2335
sage: G = PSL(2,3); G
2336
Permutation Group with generators [(2,3,4), (1,2)(3,4)]
2337
sage: G.order()
2338
12
2339
sage: G.base_ring()
2340
Finite Field of size 3
2341
sage: print G
2342
The projective special linear group of degree 2 over Finite Field of size 3
2343
2344
We create two groups over nontrivial finite fields::
2345
2346
sage: G = PSL(2, 4, 'b'); G
2347
Permutation Group with generators [(3,4,5), (1,2,3)]
2348
sage: G.base_ring()
2349
Finite Field in b of size 2^2
2350
sage: G = PSL(2, 8); G
2351
Permutation Group with generators [(3,8,6,4,9,7,5), (1,2,3)(4,7,5)(6,9,8)]
2352
sage: G.base_ring()
2353
Finite Field in a of size 2^3
2354
2355
sage: G.category()
2356
Category of finite permutation groups
2357
sage: TestSuite(G).run()
2358
2359
TESTS::
2360
2361
sage: groups.permutation.PSL(2, 3)
2362
Permutation Group with generators [(2,3,4), (1,2)(3,4)]
2363
2364
Check that :trac:`7424` is handled::
2365
2366
sage: PSL(2, GF(7,'x'))
2367
Permutation Group with generators [(3,7,5)(4,8,6), (1,2,6)(3,4,8)]
2368
sage: PSL(2, GF(3))
2369
Permutation Group with generators [(2,3,4), (1,2)(3,4)]
2370
sage: PSL(2, QQ)
2371
Traceback (most recent call last):
2372
...
2373
ValueError: q must be a prime power or a finite field
2374
"""
2375
from sage.categories.finite_fields import FiniteFields
2376
if q in FiniteFields():
2377
name = q.gen()
2378
q = q.cardinality()
2379
if not(q in NonNegativeIntegers()):
2380
raise ValueError('q must be a prime power or a finite field')
2381
if n == 1:
2382
id = 'Group([()])'
2383
else:
2384
id = 'PSL(%s,%s)' % (n, q)
2385
PermutationGroup_generic.__init__(self, gap_group=id)
2386
self._q = q
2387
self._base_ring = GF(q, name=name)
2388
self._n = n
2389
2390
def __str__(self):
2391
"""
2392
EXAMPLES::
2393
2394
sage: G = PSL(2,3)
2395
sage: print G
2396
The projective special linear group of degree 2 over Finite Field of size 3
2397
"""
2398
return "The projective special linear group of degree %s over %s"%(self._n, self.base_ring())
2399
2400
def ramification_module_decomposition_hurwitz_curve(self):
2401
"""
2402
Helps compute the decomposition of the ramification module
2403
for the Hurwitz curves X (over CC say) with automorphism group
2404
G = PSL(2,q), q a "Hurwitz prime" (ie, p is $\pm 1 \pmod 7$).
2405
Using this computation and Borne's formula helps determine the
2406
G-module structure of the RR spaces of equivariant
2407
divisors can be determined explicitly.
2408
2409
The output is a list of integer multiplicities: [m1,...,mn],
2410
where n is the number of conj classes of G=PSL(2,p) and mi is the
2411
multiplicity of pi_i in the ramification module of a
2412
Hurwitz curve with automorphism group G.
2413
Here IrrRepns(G) = [pi_1,...,pi_n] (in the order listed in the
2414
output of self.character_table()).
2415
2416
REFERENCE: David Joyner, Amy Ksir, Roger Vogeler,
2417
"Group representations on Riemann-Roch spaces of some
2418
Hurwitz curves," preprint, 2006.
2419
2420
EXAMPLES::
2421
2422
sage: G = PSL(2,13)
2423
sage: G.ramification_module_decomposition_hurwitz_curve() #random
2424
[0, 7, 7, 12, 12, 12, 13, 15, 14]
2425
2426
This means, for example, that the trivial representation does not
2427
occur in the ramification module of a Hurwitz curve with automorphism
2428
group PSL(2,13), since the trivial representation is listed first
2429
and that entry has multiplicity 0. The "randomness" is due to the
2430
fact that GAP randomly orders the conjugacy classes of the same order
2431
in the list of all conjugacy classes. Similarly, there is some
2432
randomness to the ordering of the characters.
2433
2434
If you try to use this function on a group PSL(2,q) where q is
2435
not a (smallish) "Hurwitz prime", an error message will be printed.
2436
"""
2437
if self.matrix_degree()!=2:
2438
raise ValueError("Degree must be 2.")
2439
F = self.base_ring()
2440
q = F.order()
2441
from sage.misc.misc import SAGE_EXTCODE
2442
gapcode = SAGE_EXTCODE + '/gap/joyner/hurwitz_crv_rr_sp.gap'
2443
gap.eval('Read("'+gapcode+'")')
2444
mults = gap.eval("ram_module_hurwitz("+str(q)+")")
2445
return eval(mults)
2446
2447
def ramification_module_decomposition_modular_curve(self):
2448
"""
2449
Helps compute the decomposition of the ramification module
2450
for the modular curve X(p) (over CC say) with automorphism group G = PSL(2,q),
2451
q a prime > 5. Using this computation and Borne's formula helps determine the
2452
G-module structure of the RR spaces of equivariant
2453
divisors can be determined explicitly.
2454
2455
The output is a list of integer multiplicities: [m1,...,mn],
2456
where n is the number of conj classes of G=PSL(2,p) and mi is the
2457
multiplicity of pi_i in the ramification module of a
2458
modular curve with automorphism group G.
2459
Here IrrRepns(G) = [pi_1,...,pi_n] (in the order listed in the
2460
output of self.character_table()).
2461
2462
REFERENCE: D. Joyner and A. Ksir, 'Modular representations
2463
on some Riemann-Roch spaces of modular curves
2464
$X(N)$', Computational Aspects of Algebraic Curves,
2465
(Editor: T. Shaska) Lecture Notes in Computing, WorldScientific,
2466
2005.)
2467
2468
EXAMPLES::
2469
2470
sage: G = PSL(2,7)
2471
sage: G.ramification_module_decomposition_modular_curve() ## random
2472
[0, 4, 3, 6, 7, 8]
2473
2474
This means, for example, that the trivial representation does not
2475
occur in the ramification module of X(7), since the trivial representation
2476
is listed first and that entry has multiplicity 0. The "randomness" is due to the
2477
fact that GAP randomly orders the conjugacy classes of the same order
2478
in the list of all conjugacy classes. Similarly, there is some
2479
randomness to the ordering of the characters.
2480
"""
2481
if self.matrix_degree()!=2:
2482
raise ValueError("Degree must be 2.")
2483
F = self.base_ring()
2484
q = F.order()
2485
from sage.misc.misc import SAGE_EXTCODE
2486
gapcode = SAGE_EXTCODE + '/gap/joyner/modular_crv_rr_sp.gap'
2487
gap.eval('Read("'+gapcode+'")')
2488
mults = gap.eval("ram_module_X("+str(q)+")")
2489
return eval(mults)
2490
2491
class PSp(PermutationGroup_plg):
2492
def __init__(self, n, q, name='a'):
2493
"""
2494
The projective symplectic linear groups over GF(q).
2495
2496
INPUT:
2497
n -- positive integer; the degree
2498
q -- prime power; the size of the ground field
2499
name -- (default: 'a') variable name of indeterminate of finite field GF(q)
2500
2501
OUTPUT:
2502
PSp(n,q)
2503
2504
.. note::
2505
This group is also available via ``groups.permutation.PSp()``.
2506
2507
EXAMPLES::
2508
2509
sage: G = PSp(2,3); G
2510
Permutation Group with generators [(2,3,4), (1,2)(3,4)]
2511
sage: G.order()
2512
12
2513
sage: G = PSp(4,3); G
2514
Permutation Group with generators [(3,4)(6,7)(9,10)(12,13)(17,20)(18,21)(19,22)(23,32)(24,33)(25,34)(26,38)(27,39)(28,40)(29,35)(30,36)(31,37), (1,5,14,17,27,22,19,36,3)(2,6,32)(4,7,23,20,37,13,16,26,40)(8,24,29,30,39,10,33,11,34)(9,15,35)(12,25,38)(21,28,31)]
2515
sage: G.order()
2516
25920
2517
sage: print G
2518
The projective symplectic linear group of degree 4 over Finite Field of size 3
2519
sage: G.base_ring()
2520
Finite Field of size 3
2521
2522
sage: G = PSp(2, 8, name='alpha'); G
2523
Permutation Group with generators [(3,8,6,4,9,7,5), (1,2,3)(4,7,5)(6,9,8)]
2524
sage: G.base_ring()
2525
Finite Field in alpha of size 2^3
2526
2527
TESTS::
2528
2529
sage: groups.permutation.PSp(2, 3)
2530
Permutation Group with generators [(2,3,4), (1,2)(3,4)]
2531
"""
2532
if n%2 == 1:
2533
raise TypeError("The degree n must be even")
2534
else:
2535
id = 'PSp(%s,%s)'%(n,q)
2536
PermutationGroup_generic.__init__(self, gap_group=id)
2537
self._q = q
2538
self._base_ring = GF(q, name=name)
2539
self._n = n
2540
2541
def __str__(self):
2542
"""
2543
EXAMPLES::
2544
2545
sage: G = PSp(4,3)
2546
sage: print G
2547
The projective symplectic linear group of degree 4 over Finite Field of size 3
2548
"""
2549
return "The projective symplectic linear group of degree %s over %s"%(self._n, self.base_ring())
2550
2551
PSP = PSp
2552
2553
class PermutationGroup_pug(PermutationGroup_plg):
2554
def field_of_definition(self):
2555
"""
2556
EXAMPLES::
2557
2558
sage: PSU(2,3).field_of_definition()
2559
Finite Field in a of size 3^2
2560
"""
2561
return self._field_of_definition
2562
2563
class PSU(PermutationGroup_pug):
2564
def __init__(self, n, q, name='a'):
2565
"""
2566
The projective special unitary groups over GF(q).
2567
2568
INPUT:
2569
n -- positive integer; the degree
2570
q -- prime power; the size of the ground field
2571
name -- (default: 'a') variable name of indeterminate of finite field GF(q)
2572
OUTPUT:
2573
PSU(n,q)
2574
2575
.. note::
2576
This group is also available via ``groups.permutation.PSU()``.
2577
2578
EXAMPLES::
2579
2580
sage: PSU(2,3)
2581
The projective special unitary group of degree 2 over Finite Field of size 3
2582
2583
sage: G = PSU(2, 8, name='alpha'); G
2584
The projective special unitary group of degree 2 over Finite Field in alpha of size 2^3
2585
sage: G.base_ring()
2586
Finite Field in alpha of size 2^3
2587
2588
TESTS::
2589
2590
sage: groups.permutation.PSU(2, 3)
2591
The projective special unitary group of degree 2 over Finite Field of size 3
2592
"""
2593
id = 'PSU(%s,%s)'%(n,q)
2594
PermutationGroup_generic.__init__(self, gap_group=id)
2595
self._q = q
2596
self._base_ring = GF(q, name=name)
2597
self._field_of_definition = GF(q**2, name)
2598
self._n = n
2599
2600
def _repr_(self):
2601
"""
2602
EXAMPLES::
2603
2604
sage: PSU(2,3)
2605
The projective special unitary group of degree 2 over Finite Field of size 3
2606
2607
"""
2608
return "The projective special unitary group of degree %s over %s"%(self._n, self.base_ring())
2609
2610
class PGU(PermutationGroup_pug):
2611
def __init__(self, n, q, name='a'):
2612
"""
2613
The projective general unitary groups over GF(q).
2614
2615
INPUT:
2616
n -- positive integer; the degree
2617
q -- prime power; the size of the ground field
2618
name -- (default: 'a') variable name of indeterminate of finite field GF(q)
2619
2620
OUTPUT:
2621
PGU(n,q)
2622
2623
.. note::
2624
This group is also available via ``groups.permutation.PGU()``.
2625
2626
EXAMPLES::
2627
2628
sage: PGU(2,3)
2629
The projective general unitary group of degree 2 over Finite Field of size 3
2630
2631
sage: G = PGU(2, 8, name='alpha'); G
2632
The projective general unitary group of degree 2 over Finite Field in alpha of size 2^3
2633
sage: G.base_ring()
2634
Finite Field in alpha of size 2^3
2635
2636
TESTS::
2637
2638
sage: groups.permutation.PGU(2, 3)
2639
The projective general unitary group of degree 2 over Finite Field of size 3
2640
"""
2641
id = 'PGU(%s,%s)'%(n,q)
2642
PermutationGroup_generic.__init__(self, gap_group=id)
2643
self._q = q
2644
self._base_ring = GF(q, name=name)
2645
self._field_of_definition = GF(q**2, name)
2646
self._n = n
2647
2648
def _repr_(self):
2649
"""
2650
EXAMPLES::
2651
2652
sage: PGU(2,3)
2653
The projective general unitary group of degree 2 over Finite Field of size 3
2654
2655
"""
2656
return "The projective general unitary group of degree %s over %s"%(self._n, self.base_ring())
2657
2658
2659
class SuzukiGroup(PermutationGroup_unique):
2660
def __init__(self, q, name='a'):
2661
r"""
2662
The Suzuki group over GF(q),
2663
$^2 B_2(2^{2k+1}) = Sz(2^{2k+1})$.
2664
2665
A wrapper for the GAP function SuzukiGroup.
2666
2667
INPUT:
2668
q -- 2^n, an odd power of 2; the size of the ground
2669
field. (Strictly speaking, n should be greater than 1, or
2670
else this group os not simple.)
2671
name -- (default: 'a') variable name of indeterminate of
2672
finite field GF(q)
2673
2674
OUTPUT:
2675
2676
- A Suzuki group.
2677
2678
.. note::
2679
This group is also available via ``groups.permutation.Suzuki()``.
2680
2681
EXAMPLES::
2682
2683
sage: SuzukiGroup(8)
2684
Permutation Group with generators [(1,2)(3,10)(4,42)(5,18)(6,50)(7,26)(8,58)(9,34)(12,28)(13,45)(14,44)(15,23)(16,31)(17,21)(19,39)(20,38)(22,25)(24,61)(27,60)(29,65)(30,55)(32,33)(35,52)(36,49)(37,59)(40,54)(41,62)(43,53)(46,48)(47,56)(51,63)(57,64),
2685
(1,28,10,44)(3,50,11,42)(4,43,53,64)(5,9,39,52)(6,36,63,13)(7,51,60,57)(8,33,37,16)(12,24,55,29)(14,30,48,47)(15,19,61,54)(17,59,22,62)(18,23,34,31)(20,38,49,25)(21,26,45,58)(27,32,41,65)(35,46,40,56)]
2686
sage: print SuzukiGroup(8)
2687
The Suzuki group over Finite Field in a of size 2^3
2688
2689
sage: G = SuzukiGroup(32, name='alpha')
2690
sage: G.order()
2691
32537600
2692
sage: G.order().factor()
2693
2^10 * 5^2 * 31 * 41
2694
sage: G.base_ring()
2695
Finite Field in alpha of size 2^5
2696
2697
TESTS::
2698
2699
sage: groups.permutation.Suzuki(8)
2700
Permutation Group with generators [(1,2)(3,10)(4,42)(5,18)(6,50)(7,26)(8,58)(9,34)(12,28)(13,45)(14,44)(15,23)(16,31)(17,21)(19,39)(20,38)(22,25)(24,61)(27,60)(29,65)(30,55)(32,33)(35,52)(36,49)(37,59)(40,54)(41,62)(43,53)(46,48)(47,56)(51,63)(57,64),
2701
(1,28,10,44)(3,50,11,42)(4,43,53,64)(5,9,39,52)(6,36,63,13)(7,51,60,57)(8,33,37,16)(12,24,55,29)(14,30,48,47)(15,19,61,54)(17,59,22,62)(18,23,34,31)(20,38,49,25)(21,26,45,58)(27,32,41,65)(35,46,40,56)]
2702
2703
REFERENCES:
2704
2705
- http://en.wikipedia.org/wiki/Group_of_Lie_type\#Suzuki-Ree_groups
2706
"""
2707
q = Integer(q)
2708
from sage.rings.arith import valuation
2709
t = valuation(q, 2)
2710
if 2**t != q or is_even(t):
2711
raise ValueError("The ground field size %s must be an odd power of 2." % q)
2712
id = 'SuzukiGroup(IsPermGroup,%s)'%q
2713
PermutationGroup_generic.__init__(self, gap_group=id)
2714
self._q = q
2715
self._base_ring = GF(q, name=name)
2716
2717
def base_ring(self):
2718
"""
2719
EXAMPLES::
2720
2721
sage: G = SuzukiGroup(32, name='alpha')
2722
sage: G.base_ring()
2723
Finite Field in alpha of size 2^5
2724
"""
2725
return self._base_ring
2726
2727
def __str__(self):
2728
"""
2729
EXAMPLES::
2730
2731
sage: G = SuzukiGroup(32, name='alpha')
2732
sage: print G
2733
The Suzuki group over Finite Field in alpha of size 2^5
2734
2735
"""
2736
return "The Suzuki group over %s"%self.base_ring()
2737
2738