Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/groups/abelian_gps/abelian_group_element.py
4079 views
1
"""
2
Abelian group elements
3
4
AUTHORS:
5
6
- David Joyner (2006-02); based on free_abelian_monoid_element.py, written by David Kohel.
7
8
- David Joyner (2006-05); bug fix in order
9
10
- David Joyner (2006-08); bug fix+new method in pow for negatives+fixed corresponding examples.
11
12
- David Joyner (2009-02): Fixed bug in order.
13
14
EXAMPLES: Recall an example from abelian groups.
15
16
::
17
18
sage: F = AbelianGroup(5,[4,5,5,7,8],names = list("abcde"))
19
sage: (a,b,c,d,e) = F.gens()
20
sage: x = a*b^2*e*d^20*e^12
21
sage: x
22
a*b^2*d^6*e^5
23
sage: x = a^10*b^12*c^13*d^20*e^12
24
sage: x
25
a^2*b^2*c^3*d^6*e^4
26
sage: y = a^13*b^19*c^23*d^27*e^72
27
sage: y
28
a*b^4*c^3*d^6
29
sage: x*y
30
a^3*b*c*d^5*e^4
31
sage: x.list()
32
[2, 2, 3, 6, 4]
33
34
It is important to note that lists are mutable and the returned
35
list is not a copy. As a result, reassignment of an element of the
36
list changes the object.
37
38
::
39
40
sage: x.list()[0] = 3
41
sage: x.list()
42
[3, 2, 3, 6, 4]
43
sage: x
44
a^3*b^2*c^3*d^6*e^4
45
"""
46
47
###########################################################################
48
# Copyright (C) 2006 William Stein <[email protected]>
49
# Copyright (C) 2006 David Joyner
50
#
51
# Distributed under the terms of the GNU General Public License (GPL)
52
# http://www.gnu.org/licenses/
53
###########################################################################
54
55
56
from sage.rings.integer import Integer
57
from sage.structure.element import MultiplicativeGroupElement
58
from sage.rings.infinity import infinity
59
from sage.rings.arith import LCM, GCD
60
61
def is_AbelianGroupElement(x):
62
"""
63
Return true if x is an abelian group element, i.e., an element of
64
type AbelianGroupElement.
65
66
EXAMPLES: Though the integer 3 is in the integers, and the integers
67
have an abelian group structure, 3 is not an AbelianGroupElement::
68
69
sage: from sage.groups.abelian_gps.abelian_group_element import is_AbelianGroupElement
70
sage: is_AbelianGroupElement(3)
71
False
72
sage: F = AbelianGroup(5, [3,4,5,8,7], 'abcde')
73
sage: is_AbelianGroupElement(F.0)
74
True
75
"""
76
return isinstance(x, AbelianGroupElement)
77
78
class AbelianGroupElement(MultiplicativeGroupElement):
79
def __init__(self, F, x):
80
"""
81
Create the element x of the AbelianGroup F.
82
83
EXAMPLES::
84
85
sage: F = AbelianGroup(5, [3,4,5,8,7], 'abcde')
86
sage: a, b, c, d, e = F.gens()
87
sage: a^2 * b^3 * a^2 * b^-4
88
a*b^3
89
sage: b^-11
90
b
91
sage: a^-11
92
a
93
sage: a*b in F
94
True
95
"""
96
MultiplicativeGroupElement.__init__(self, F)
97
self.__repr = None
98
n = F.ngens()
99
if isinstance(x, (int, Integer)) and x == 1:
100
self.__element_vector = [ 0 for i in range(n) ]
101
elif isinstance(x, list):
102
if len(x) != n:
103
raise IndexError, \
104
"Argument length (= %s) must be %s."%(len(x), n)
105
self.__element_vector = x
106
else:
107
raise TypeError, "Argument x (= %s) is of wrong type."%x
108
109
def _repr_(self):
110
"""
111
EXAMPLES::
112
113
sage: AbelianGroupElement(AbelianGroup(1, [1], names='e'),[0])
114
1
115
sage: AbelianGroupElement(AbelianGroup(3, [2,3,4], names='e'),[1,2,3])
116
e0*e1^2*e2^3
117
"""
118
s = ""
119
A = self.parent()
120
n = A.ngens()
121
x = A.variable_names()
122
v = self.__element_vector
123
for i in range(n):
124
if v[i] == 0:
125
continue
126
elif v[i] == 1:
127
if len(s) > 0: s += "*"
128
s += "%s"%x[i]
129
else:
130
if len(s) > 0: s += "*"
131
s += "%s^%s"%(x[i],v[i])
132
if len(s) == 0: s = str(1)
133
return s
134
135
def _div_(self, y):
136
"""
137
TESTS::
138
139
sage: G.<a,b> = AbelianGroup(2)
140
sage: a/b
141
a*b^-1
142
"""
143
return self*y.inverse()
144
145
def _mul_(self, y):
146
#Same as _mul_ in FreeAbelianMonoidElement except that the
147
#exponents get reduced mod the invariant.
148
149
M = self.parent()
150
n = M.ngens()
151
invs = M.invariants()
152
z = M(1)
153
xelt = self.__element_vector
154
yelt = y.__element_vector
155
zelt = [ xelt[i]+yelt[i] for i in range(len(xelt)) ]
156
if len(invs) >= n:
157
L = []
158
for i in range(len(xelt)):
159
if invs[i]!=0:
160
L.append(zelt[i]%invs[i])
161
if invs[i]==0:
162
L.append(zelt[i])
163
z.__element_vector = L
164
if len(invs) < n:
165
L1 = []
166
for i in range(len(invs)):
167
if invs[i]!=0:
168
L1.append(zelt[i]%invs[i])
169
if invs[i]==0:
170
L1.append(zelt[i])
171
L2 = [ zelt[i] for i in range(len(invs),len(xelt)) ]
172
z.__element_vector = L1+L2
173
return z
174
175
def __pow__(self, _n):
176
"""
177
requires that len(invs) = n
178
"""
179
n = int(_n)
180
if n != _n:
181
raise TypeError, "Argument n (= %s) must be an integer."%n
182
M = self.parent()
183
N = M.ngens()
184
invs = M.invariants()
185
z = M(1)
186
for i in xrange(len(invs)):
187
if invs[i] == 0:
188
z.__element_vector[i] = self.__element_vector[i]*n
189
else:
190
z.__element_vector[i] = (self.__element_vector[i]*n)%invs[i]
191
return z
192
193
def inverse(self):
194
"""
195
Returns the inverse element.
196
197
EXAMPLE::
198
199
sage: G.<a,b> = AbelianGroup(2)
200
sage: a^-1
201
a^-1
202
sage: a.list()
203
[1, 0]
204
sage: a.inverse().list()
205
[-1, 0]
206
sage: a.inverse()
207
a^-1
208
"""
209
new_list = [-1*n for n in self.list()]
210
par_inv = self.parent().invariants()
211
for i in xrange(len(par_inv)):
212
if par_inv[i] != 0 and new_list[i] < 0:
213
while new_list[i] < 0:
214
new_list[i] += abs(par_inv[i])
215
return AbelianGroupElement(self.parent(), new_list)
216
217
def as_permutation(self):
218
r"""
219
Return the element of the permutation group G (isomorphic to the
220
abelian group A) associated to a in A.
221
222
EXAMPLES::
223
224
sage: G = AbelianGroup(3,[2,3,4],names="abc"); G
225
Multiplicative Abelian Group isomorphic to C2 x C3 x C4
226
sage: a,b,c=G.gens()
227
sage: Gp = G.permutation_group(); Gp
228
Permutation Group with generators [(1,3,2,4)(5,7,6,8)(9,11,10,12)(13,15,14,16)(17,19,18,20)(21,23,22,24), (1,5,9)(2,6,10)(3,7,11)(4,8,12)(13,17,21)(14,18,22)(15,19,23)(16,20,24), (1,13)(2,14)(3,15)(4,16)(5,17)(6,18)(7,19)(8,20)(9,21)(10,22)(11,23)(12,24)]
229
sage: a.as_permutation()
230
(1,13)(2,14)(3,15)(4,16)(5,17)(6,18)(7,19)(8,20)(9,21)(10,22)(11,23)(12,24)
231
sage: ap = a.as_permutation(); ap
232
(1,13)(2,14)(3,15)(4,16)(5,17)(6,18)(7,19)(8,20)(9,21)(10,22)(11,23)(12,24)
233
sage: ap in Gp
234
True
235
"""
236
from sage.groups.perm_gps.permgroup import PermutationGroup
237
from sage.interfaces.all import gap
238
G = self.parent()
239
invs = G.invariants()
240
s1 = 'A:=AbelianGroup(%s)'%invs
241
gap.eval(s1)
242
s2 = 'phi:=IsomorphismPermGroup(A)'
243
gap.eval(s2)
244
s3 = "gens := GeneratorsOfGroup(A)"
245
gap.eval(s3)
246
L = self.list()
247
gap.eval("L1:="+str(L))
248
s4 = "L2:=List([1..%s], i->gens[i]^L1[i]);"%len(L)
249
gap.eval(s4)
250
pg = gap.eval("Image(phi,Product(L2))")
251
Gp = G.permutation_group()
252
gp = Gp(pg)
253
return gp
254
255
def list(self):
256
"""
257
Return (a reference to) the underlying list used to represent this
258
element. If this is a word in an abelian group on `n`
259
generators, then this is a list of nonnegative integers of length
260
`n`.
261
262
EXAMPLES::
263
264
sage: F = AbelianGroup(5, [3,4,5,8,7], 'abcde')
265
sage: (a, b, c, d, e) = F.gens()
266
sage: a.list()
267
[1, 0, 0, 0, 0]
268
"""
269
return self.__element_vector
270
271
def __cmp__(self,other):
272
if (self.list() != other.list()):
273
return -1
274
return 0
275
276
def order(self):
277
"""
278
Returns the (finite) order of this element or Infinity if this
279
element does not have finite order.
280
281
EXAMPLES::
282
283
sage: F = AbelianGroup(3,[7,8,9]); F
284
Multiplicative Abelian Group isomorphic to C7 x C8 x C9
285
sage: F.gens()[2].order()
286
9
287
sage: a,b,c = F.gens()
288
sage: (b*c).order()
289
72
290
sage: G = AbelianGroup(3,[7,8,9])
291
sage: type((G.0 * G.1).order())==Integer
292
True
293
"""
294
M = self.parent()
295
if self == M(1):
296
return Integer(1)
297
invs = M.invariants()
298
if self in M.gens():
299
o = invs[list(M.gens()).index(self)]
300
if o == 0:
301
return infinity
302
return o
303
L = list(self.list())
304
N = LCM([invs[i]//GCD(invs[i],L[i]) for i in range(len(invs)) if L[i]!=0])
305
if N == 0:
306
return infinity
307
else:
308
return Integer(N)
309
310
def random_element(self):
311
"""
312
Return a random element of this dual group.
313
"""
314
if not(self.is_finite()):
315
raise NotImplementedError, "Only implemented for finite groups"
316
gens = self.gens()
317
g = gens[0]**0
318
for i in range(len(gens)):
319
g = g*gens[i]**(random(gens[i].order()))
320
return g
321
322
323
324
def word_problem(self, words):
325
"""
326
TODO - this needs a rewrite - see stuff in the matrix_grp
327
directory.
328
329
G and H are abelian groups, g in G, H is a subgroup of G generated
330
by a list (words) of elements of G. If self is in H, return the
331
expression for self as a word in the elements of (words).
332
333
This function does not solve the word problem in Sage. Rather
334
it pushes it over to GAP, which has optimized (non-deterministic)
335
algorithms for the word problem.
336
337
.. warning::
338
339
Don't use E (or other GAP-reserved letters) as a generator
340
name.
341
342
EXAMPLE::
343
344
sage: G = AbelianGroup(2,[2,3], names="xy")
345
sage: x,y = G.gens()
346
sage: x.word_problem([x,y])
347
[[x, 1]]
348
sage: y.word_problem([x,y])
349
[[y, 1]]
350
sage: v = (y*x).word_problem([x,y]); v #random
351
[[x, 1], [y, 1]]
352
sage: prod([x^i for x,i in v]) == y*x
353
True
354
355
"""
356
from sage.groups.abelian_gps.abelian_group import AbelianGroup, word_problem
357
return word_problem(words,self)
358
359