Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/groups/abelian_gps/element_base.py
8815 views
1
"""
2
Base class for abelian group elements
3
4
This is the base class for both
5
:mod:`~sage.groups.abelian_gps.abelian_group_element` and
6
:mod:`~sage.groups.abelian_gps.dual_abelian_group_element`.
7
8
As always, elements are immutable once constructed.
9
"""
10
11
12
###########################################################################
13
# Copyright (C) 2006 William Stein <[email protected]>
14
# Copyright (C) 2006 David Joyner <[email protected]>
15
# Copyright (C) 2012 Volker Braun <[email protected]>
16
#
17
# Distributed under the terms of the GNU General Public License (GPL)
18
# http://www.gnu.org/licenses/
19
###########################################################################
20
21
from sage.structure.element import MultiplicativeGroupElement
22
from sage.misc.cachefunc import cached_method
23
from sage.rings.arith import GCD, LCM
24
from sage.rings.integer import Integer
25
from sage.rings.integer_ring import ZZ
26
from sage.rings.infinity import infinity
27
28
29
class AbelianGroupElementBase(MultiplicativeGroupElement):
30
"""
31
Base class for abelian group elements
32
33
The group element is defined by a tuple whose ``i``-th entry is an
34
integer in the range from 0 (inclusively) to ``G.gen(i).order()``
35
(exclusively) if the `i`-th generator is of finite order, and an
36
arbitrary integer if the `i`-th generator is of infinte order.
37
38
INPUT:
39
40
- ``exponents`` -- ``1`` or a list/tuple/iterable of integers. The
41
exponent vector (with respect to the parent generators) defining
42
the group element.
43
44
- ``parent`` -- Abelian group. The parent of the group element.
45
46
EXAMPLES::
47
48
sage: F = AbelianGroup(3,[7,8,9])
49
sage: Fd = F.dual_group(names="ABC")
50
sage: A,B,C = Fd.gens()
51
sage: A*B^-1 in Fd
52
True
53
"""
54
55
def __init__(self, parent, exponents):
56
"""
57
Create an element.
58
59
EXAMPLES::
60
61
sage: F = AbelianGroup(3,[7,8,9])
62
sage: Fd = F.dual_group(names="ABC")
63
sage: A,B,C = Fd.gens()
64
sage: A*B^-1 in Fd
65
True
66
"""
67
MultiplicativeGroupElement.__init__(self, parent)
68
n = parent.ngens()
69
if exponents == 1:
70
self._exponents = tuple( ZZ.zero() for i in range(n) )
71
else:
72
self._exponents = tuple( ZZ(e) for e in exponents )
73
if len(self._exponents) != n:
74
raise IndexError('argument length (= %s) must be %s.'%(len(exponents), n))
75
76
def exponents(self):
77
"""
78
The exponents of the generators defining the group element.
79
80
OUTPUT:
81
82
A tuple of integers for an abelian group element. The integer
83
can be arbitrary if the corresponding generator has infinite
84
order. If the generator is of finite order, the integer is in
85
the range from 0 (inclusive) to the order (exclusive).
86
87
EXAMPLES::
88
89
sage: F.<a,b,c,f> = AbelianGroup([7,8,9,0])
90
sage: (a^3*b^2*c).exponents()
91
(3, 2, 1, 0)
92
sage: F([3, 2, 1, 0])
93
a^3*b^2*c
94
sage: (c^42).exponents()
95
(0, 0, 6, 0)
96
sage: (f^42).exponents()
97
(0, 0, 0, 42)
98
"""
99
return self._exponents
100
101
def list(self):
102
"""
103
Return a copy of the exponent vector.
104
105
Use :meth:`exponents` instead.
106
107
OUTPUT:
108
109
The underlying coordinates used to represent this element. If
110
this is a word in an abelian group on `n` generators, then
111
this is a list of nonnegative integers of length `n`.
112
113
EXAMPLES::
114
115
sage: F = AbelianGroup(5,[2, 3, 5, 7, 8], names="abcde")
116
sage: a,b,c,d,e = F.gens()
117
sage: Ad = F.dual_group(names="ABCDE")
118
sage: A,B,C,D,E = Ad.gens()
119
sage: (A*B*C^2*D^20*E^65).exponents()
120
(1, 1, 2, 6, 1)
121
sage: X = A*B*C^2*D^2*E^-6
122
sage: X.exponents()
123
(1, 1, 2, 2, 2)
124
"""
125
# to be deprecated (really, return a list??). Use exponents() instead.
126
return list(self._exponents)
127
128
def _repr_(self):
129
"""
130
Return a string representation of ``self``.
131
132
OUTPUT:
133
134
String.
135
136
EXAMPLES::
137
138
sage: G = AbelianGroup([2])
139
sage: G.gen(0)._repr_()
140
'f'
141
sage: G.one()._repr_()
142
'1'
143
"""
144
s = ""
145
G = self.parent()
146
for v_i, x_i in zip(self.exponents(), G.variable_names()):
147
if v_i == 0:
148
continue
149
if len(s) > 0:
150
s += '*'
151
if v_i == 1:
152
s += str(x_i)
153
else:
154
s += str(x_i) + '^' + str(v_i)
155
if s:
156
return s
157
else:
158
return '1'
159
160
def __cmp__(self, other):
161
"""
162
Compare ``self`` and ``other``.
163
164
OUTPUT:
165
166
``-1``, ``0``, or ``+1``
167
168
EXAMPLES::
169
170
sage: G.<a,b> = AbelianGroup([2,3])
171
sage: cmp(a,b)
172
1
173
174
sage: Gd.<A,B> = G.dual_group()
175
sage: cmp(A,B)
176
1
177
"""
178
return cmp(self._exponents, other._exponents)
179
180
@cached_method
181
def order(self):
182
"""
183
Return the order of this element.
184
185
OUTPUT:
186
187
An integer or ``infinity``.
188
189
EXAMPLES::
190
191
sage: F = AbelianGroup(3,[7,8,9])
192
sage: Fd = F.dual_group()
193
sage: A,B,C = Fd.gens()
194
sage: (B*C).order()
195
72
196
197
sage: F = AbelianGroup(3,[7,8,9]); F
198
Multiplicative Abelian group isomorphic to C7 x C8 x C9
199
sage: F.gens()[2].order()
200
9
201
sage: a,b,c = F.gens()
202
sage: (b*c).order()
203
72
204
sage: G = AbelianGroup(3,[7,8,9])
205
sage: type((G.0 * G.1).order())==Integer
206
True
207
"""
208
M = self.parent()
209
order = M.gens_orders()
210
L = self.exponents()
211
N = LCM([order[i]/GCD(order[i],L[i]) for i in range(len(order)) if L[i]!=0])
212
if N == 0:
213
return infinity
214
else:
215
return ZZ(N)
216
217
multiplicative_order = order
218
219
def _div_(left, right):
220
"""
221
Divide ``left`` and ``right``
222
223
TESTS::
224
225
sage: G.<a,b> = AbelianGroup(2)
226
sage: a/b
227
a*b^-1
228
sage: a._div_(b)
229
a*b^-1
230
"""
231
G = left.parent()
232
assert G is right.parent()
233
exponents = [ (x-y)%order if order!=0 else x-y
234
for x, y, order in
235
zip(left._exponents, right._exponents, G.gens_orders()) ]
236
return G.element_class(G, exponents)
237
238
def _mul_(left, right):
239
"""
240
Multiply ``left`` and ``right``
241
242
TESTS::
243
244
sage: G.<a,b> = AbelianGroup(2)
245
sage: a*b
246
a*b
247
sage: a._mul_(b)
248
a*b
249
"""
250
G = left.parent()
251
assert G is right.parent()
252
exponents = [ (x+y)%order if order!=0 else x+y
253
for x, y, order in
254
zip(left._exponents, right._exponents, G.gens_orders()) ]
255
return G.element_class(G, exponents)
256
257
def __pow__(self, n):
258
"""
259
Exponentiate ``self``
260
261
TESTS::
262
263
sage: G.<a,b> = AbelianGroup(2)
264
sage: a^3
265
a^3
266
"""
267
m = Integer(n)
268
if n != m:
269
raise TypeError('argument n (= '+str(n)+') must be an integer.')
270
G = self.parent()
271
exponents = [ (m*e) % order if order!=0 else m*e
272
for e,order in zip(self._exponents, G.gens_orders()) ]
273
return G.element_class(G, exponents)
274
275
def inverse(self):
276
"""
277
Returns the inverse element.
278
279
EXAMPLE::
280
281
sage: G.<a,b> = AbelianGroup([0,5])
282
sage: a.inverse()
283
a^-1
284
sage: a.__invert__()
285
a^-1
286
sage: a^-1
287
a^-1
288
sage: ~a
289
a^-1
290
sage: (a*b).exponents()
291
(1, 1)
292
sage: (a*b).inverse().exponents()
293
(-1, 4)
294
"""
295
G = self.parent()
296
exponents = [ (-e)%order if order!=0 else -e
297
for e,order in zip(self._exponents, G.gens_orders()) ]
298
return G.element_class(G, exponents)
299
300
__invert__ = inverse
301
302
def is_trivial(self):
303
"""
304
Test whether ``self`` is the trivial group element ``1``.
305
306
OUTPUT:
307
308
Boolean.
309
310
EXAMPLES::
311
312
sage: G.<a,b> = AbelianGroup([0,5])
313
sage: (a^5).is_trivial()
314
False
315
sage: (b^5).is_trivial()
316
True
317
"""
318
return all(e==0 for e in self._exponents)
319
320