Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/groups/group.pyx
8814 views
1
"""
2
Base class for groups
3
"""
4
5
#*****************************************************************************
6
# Copyright (C) 2005 William Stein <[email protected]>
7
#
8
# Distributed under the terms of the GNU General Public License (GPL)
9
#
10
# This code is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
# General Public License for more details.
14
#
15
# The full text of the GPL is available at:
16
#
17
# http://www.gnu.org/licenses/
18
#*****************************************************************************
19
20
import random
21
22
from sage.structure.parent cimport Parent
23
from sage.rings.infinity import infinity
24
from sage.rings.integer_ring import ZZ
25
26
def is_Group(x):
27
"""
28
Return whether ``x`` is a group object.
29
30
INPUT:
31
32
- ``x`` -- anything.
33
34
OUTPUT:
35
36
Boolean.
37
38
EXAMPLES::
39
40
sage: F.<a,b> = FreeGroup()
41
sage: from sage.groups.group import is_Group
42
sage: is_Group(F)
43
True
44
sage: is_Group("a string")
45
False
46
"""
47
from sage.groups.old import Group as OldGroup
48
return isinstance(x, (Group, OldGroup))
49
50
51
cdef class Group(Parent):
52
"""
53
Base class for all groups
54
55
TESTS::
56
57
sage: from sage.groups.group import Group
58
sage: G = Group()
59
sage: TestSuite(G).run(skip = ["_test_an_element",\
60
"_test_associativity",\
61
"_test_elements",\
62
"_test_elements_eq_reflexive",\
63
"_test_elements_eq_symmetric",\
64
"_test_elements_eq_transitive",\
65
"_test_elements_neq",\
66
"_test_inverse",\
67
"_test_one",\
68
"_test_pickling",\
69
"_test_prod",\
70
"_test_some_elements"])
71
"""
72
def __init__(self, base=None, gens=None, category=None):
73
"""
74
The Python constructor
75
76
TESTS::
77
78
sage: from sage.groups.group import Group
79
sage: G = Group()
80
sage: G.category()
81
Category of groups
82
sage: G = Group(category=Groups()) # todo: do the same test with some subcategory of Groups when there will exist one
83
sage: G.category()
84
Category of groups
85
sage: G = Group(category = CommutativeAdditiveGroups())
86
Traceback (most recent call last):
87
...
88
ValueError: (Category of commutative additive groups,) is not a subcategory of Category of groups
89
sage: G._repr_option('element_is_atomic')
90
False
91
92
Check for #8119::
93
94
sage: G = SymmetricGroup(2)
95
sage: h = hash(G)
96
sage: G.rename('S2')
97
sage: h == hash(G)
98
True
99
"""
100
from sage.categories.groups import Groups
101
if category is None:
102
category = Groups()
103
else:
104
if not isinstance(category, tuple):
105
category = (category,)
106
if not any(cat.is_subcategory(Groups()) for cat in category):
107
raise ValueError("%s is not a subcategory of %s"%(category, Groups()))
108
Parent.__init__(self, base=base, gens=gens, category=category)
109
110
def __contains__(self, x):
111
r"""
112
Test whether `x` defines a group element.
113
114
INPUT:
115
116
- ``x`` -- anything.
117
118
OUTPUT:
119
120
Boolean.
121
122
EXAMPLES::
123
124
sage: from sage.groups.group import Group
125
sage: G = Group()
126
sage: 4 in G #indirect doctest
127
Traceback (most recent call last):
128
...
129
NotImplementedError
130
"""
131
try:
132
self(x)
133
except TypeError:
134
return False
135
return True
136
137
def is_abelian(self):
138
"""
139
Test whether this group is abelian.
140
141
EXAMPLES::
142
143
sage: from sage.groups.group import Group
144
sage: G = Group()
145
sage: G.is_abelian()
146
Traceback (most recent call last):
147
...
148
NotImplementedError
149
"""
150
raise NotImplementedError
151
152
def is_commutative(self):
153
r"""
154
Test whether this group is commutative.
155
156
This is an alias for is_abelian, largely to make groups work
157
well with the Factorization class.
158
159
(Note for developers: Derived classes should override is_abelian, not
160
is_commutative.)
161
162
EXAMPLE::
163
164
sage: SL(2, 7).is_commutative()
165
False
166
"""
167
return self.is_abelian()
168
169
def order(self):
170
"""
171
Returns the number of elements of this group, which is either a
172
positive integer or infinity.
173
174
EXAMPLES::
175
176
sage: from sage.groups.group import Group
177
sage: G = Group()
178
sage: G.order()
179
Traceback (most recent call last):
180
...
181
NotImplementedError
182
"""
183
raise NotImplementedError
184
185
def is_finite(self):
186
"""
187
Returns True if this group is finite.
188
189
EXAMPLES::
190
191
sage: from sage.groups.group import Group
192
sage: G = Group()
193
sage: G.is_finite()
194
Traceback (most recent call last):
195
...
196
NotImplementedError
197
"""
198
return self.order() != infinity
199
200
def is_multiplicative(self):
201
"""
202
Returns True if the group operation is given by \* (rather than
203
+).
204
205
Override for additive groups.
206
207
EXAMPLES::
208
209
sage: from sage.groups.group import Group
210
sage: G = Group()
211
sage: G.is_multiplicative()
212
True
213
"""
214
return True
215
216
def _an_element_(self):
217
"""
218
Return an element
219
220
OUTPUT:
221
222
An element of the group.
223
224
EXAMPLES:
225
226
sage: G = AbelianGroup([2,3,4,5])
227
sage: G.an_element()
228
f0*f1*f2*f3
229
"""
230
from sage.misc.misc import prod
231
return prod(self.gens())
232
233
def random_element(self, bound=None):
234
"""
235
Return a random element of this group.
236
237
EXAMPLES::
238
239
sage: from sage.groups.group import Group
240
sage: G = Group()
241
sage: G.random_element()
242
Traceback (most recent call last):
243
...
244
NotImplementedError
245
"""
246
raise NotImplementedError
247
248
def quotient(self, H):
249
"""
250
Return the quotient of this group by the normal subgroup
251
`H`.
252
253
EXAMPLES::
254
255
sage: from sage.groups.group import Group
256
sage: G = Group()
257
sage: G.quotient(G)
258
Traceback (most recent call last):
259
...
260
NotImplementedError
261
"""
262
raise NotImplementedError
263
264
cdef class AbelianGroup(Group):
265
"""
266
Generic abelian group.
267
"""
268
def is_abelian(self):
269
"""
270
Return True.
271
272
EXAMPLES::
273
274
sage: from sage.groups.group import AbelianGroup
275
sage: G = AbelianGroup()
276
sage: G.is_abelian()
277
True
278
"""
279
return True
280
281
cdef class FiniteGroup(Group):
282
"""
283
Generic finite group.
284
"""
285
286
def __init__(self, base=None, gens=None, category=None):
287
"""
288
The Python constructor
289
290
TESTS::
291
292
sage: from sage.groups.group import FiniteGroup
293
sage: G = FiniteGroup()
294
sage: G.category()
295
Category of finite groups
296
"""
297
from sage.categories.finite_groups import FiniteGroups
298
if category is None:
299
category = FiniteGroups()
300
else:
301
if not isinstance(category, tuple):
302
category = (category,)
303
if not any(cat.is_subcategory(FiniteGroups()) for cat in category):
304
raise ValueError("%s is not a subcategory of %s"%(category, FiniteGroups()))
305
Parent.__init__(self, base=base, gens=gens, category=category)
306
307
def is_finite(self):
308
"""
309
Return True.
310
311
EXAMPLES::
312
313
sage: from sage.groups.group import FiniteGroup
314
sage: G = FiniteGroup()
315
sage: G.is_finite()
316
True
317
"""
318
return True
319
320
def cayley_graph(self, connecting_set=None):
321
"""
322
Return the Cayley graph for this finite group.
323
324
INPUT:
325
326
- ``connecting_set`` -- (optional) list of elements to use for
327
edges, default is the stored generators
328
329
OUTPUT:
330
331
The Cayley graph as a Sage DiGraph object. To plot the graph
332
with with different colors
333
334
EXAMPLES::
335
336
sage: D4 = DihedralGroup(4); D4
337
Dihedral group of order 8 as a permutation group
338
sage: G = D4.cayley_graph()
339
sage: show(G, color_by_label=True, edge_labels=True)
340
sage: A5 = AlternatingGroup(5); A5
341
Alternating group of order 5!/2 as a permutation group
342
sage: G = A5.cayley_graph()
343
sage: G.show3d(color_by_label=True, edge_size=0.01, edge_size2=0.02, vertex_size=0.03)
344
sage: G.show3d(vertex_size=0.03, edge_size=0.01, edge_size2=0.02, vertex_colors={(1,1,1):G.vertices()}, bgcolor=(0,0,0), color_by_label=True, xres=700, yres=700, iterations=200) # long time (less than a minute)
345
sage: G.num_edges()
346
120
347
sage: G = A5.cayley_graph(connecting_set=[A5.gens()[0]])
348
sage: G.num_edges()
349
60
350
sage: g=PermutationGroup([(i+1,j+1) for i in range(5) for j in range(5) if j!=i])
351
sage: g.cayley_graph(connecting_set=[(1,2),(2,3)])
352
Digraph on 120 vertices
353
354
sage: s1 = SymmetricGroup(1); s = s1.cayley_graph(); s.vertices()
355
[()]
356
357
AUTHORS:
358
359
- Bobby Moretti (2007-08-10)
360
- Robert Miller (2008-05-01): editing
361
"""
362
if connecting_set is None:
363
connecting_set = self.gens()
364
else:
365
if any(g not in self for g in connecting_set):
366
raise ValueError("Each element of the connecting set must be in the group!")
367
connecting_set = [self(g) for g in connecting_set]
368
from sage.graphs.all import DiGraph
369
arrows = {}
370
for x in self:
371
arrows[x] = {}
372
for g in connecting_set:
373
xg = x*g # cache the multiplication
374
if not xg == x:
375
arrows[x][xg] = g
376
377
return DiGraph(arrows, implementation='networkx')
378
379
380