Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/modules/fg_pid/fgp_element.py
4045 views
1
r"""
2
Elements of finitely generated modules over a PID
3
4
AUTHOR:
5
- William Stein, 2009
6
"""
7
8
####################################################################################
9
# Copyright (C) 2009 William Stein <[email protected]>
10
#
11
# Distributed under the terms of the GNU General Public License (GPL)
12
#
13
# This code is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
# General Public License for more details.
17
#
18
# The full text of the GPL is available at:
19
#
20
# http://www.gnu.org/licenses/
21
####################################################################################
22
23
from sage.structure.element import ModuleElement
24
25
# This adds extra maybe-not-necessary checks in the code, but could
26
# slow things down. It can impact what happens in more than just this
27
# file.
28
DEBUG=True
29
30
31
class FGP_Element(ModuleElement):
32
"""
33
An element of a finitely generated module over a PID.
34
35
INPUT:
36
37
- ``parent`` -- parent module M
38
39
- ``x`` -- element of M.V()
40
41
EXAMPLES::
42
43
sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
44
sage: Q = V/W
45
sage: x = Q(V.0-V.1); x #indirect doctest
46
(0, 3)
47
sage: isinstance(x, sage.modules.fg_pid.fgp_element.FGP_Element)
48
True
49
sage: type(x)
50
<class 'sage.modules.fg_pid.fgp_element.FGP_Module_class_with_category.element_class'>
51
sage: x is Q(x)
52
True
53
sage: x.parent() is Q
54
True
55
56
TESTS::
57
58
sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2]); Q = V/W
59
sage: loads(dumps(Q.0)) == Q.0
60
True
61
"""
62
def __init__(self, parent, x, check=DEBUG):
63
"""
64
INPUT:
65
66
- ``parent`` -- parent module M
67
68
- ``x`` -- element of M.V()
69
70
- ``check`` -- (default: True) if True, verify that x in M.V()
71
72
EXAMPLES::
73
74
sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
75
sage: Q = V/W
76
sage: x = Q(V.0-V.1); type(x)
77
<class 'sage.modules.fg_pid.fgp_element.FGP_Module_class_with_category.element_class'>
78
sage: isinstance(x,sage.modules.fg_pid.fgp_element.FGP_Element)
79
True
80
81
For full documentation, see :class:`FGP_Element`.
82
"""
83
if check: assert x in parent.V(), 'The argument x='+str(x)+' is not in the covering module!'
84
ModuleElement.__init__(self, parent)
85
self._x = x
86
87
def lift(self):
88
"""
89
Lift self to an element of V, where the parent of self is the quotient module V/W.
90
91
EXAMPLES::
92
93
sage: V = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
94
sage: Q = V/W; Q
95
Finitely generated module V/W over Integer Ring with invariants (4, 12)
96
sage: Q.0
97
(1, 0)
98
sage: Q.1
99
(0, 1)
100
sage: Q.0.lift()
101
(0, 0, 1)
102
sage: Q.1.lift()
103
(0, 2, 0)
104
sage: x = Q(V.0); x
105
(0, 4)
106
sage: x.lift()
107
(1/2, 0, 0)
108
sage: x == 4*Q.1
109
True
110
sage: x.lift().parent() == V
111
True
112
113
A silly version of the integers modulo 100::
114
115
sage: A = (ZZ^1)/span([[100]], ZZ); A
116
Finitely generated module V/W over Integer Ring with invariants (100)
117
sage: x = A([5]); x
118
(5)
119
sage: v = x.lift(); v
120
(5)
121
sage: v.parent()
122
Ambient free module of rank 1 over the principal ideal domain Integer Ring
123
"""
124
return self._x
125
126
127
def __neg__(self):
128
"""
129
EXAMPLES::
130
131
sage: V1 = ZZ^2; W1 = V1.span([[1,2],[3,4]]); A1 = V1/W1; A1
132
Finitely generated module V/W over Integer Ring with invariants (2)
133
sage: -A1.0
134
(1)
135
sage: -A1.0 == A1.0 # order 2
136
True
137
"""
138
P = self.parent()
139
return P.element_class(P, self._x.__neg__())
140
141
142
def _add_(self, other):
143
"""
144
EXAMPLES::
145
146
sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
147
sage: Q = V/W; Q
148
Finitely generated module V/W over Integer Ring with invariants (4, 12)
149
sage: x = Q.0; x
150
(1, 0)
151
sage: y = Q.1; y
152
(0, 1)
153
sage: x + y # indirect doctest
154
(1, 1)
155
sage: x + x + x + x
156
(0, 0)
157
sage: x + 0
158
(1, 0)
159
sage: 0 + x
160
(1, 0)
161
162
We test canonical coercion from V and W.
163
164
sage: Q.0 + V.0
165
(1, 4)
166
sage: V.0 + Q.0
167
(1, 4)
168
sage: W.0 + Q.0
169
(1, 0)
170
sage: W.0 + Q.0 == Q.0
171
True
172
"""
173
P = self.parent()
174
return P.element_class(P, self._x + other._x)
175
176
177
def _sub_(self, other):
178
"""
179
EXAMPLES::
180
181
sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
182
sage: Q = V/W; Q
183
Finitely generated module V/W over Integer Ring with invariants (4, 12)
184
sage: x = Q.0; x
185
(1, 0)
186
sage: y = Q.1; y
187
(0, 1)
188
sage: x - y # indirect doctest
189
(1, 11)
190
sage: x - x
191
(0, 0)
192
"""
193
P = self.parent()
194
return P.element_class(P, self._x - other._x)
195
196
197
def _rmul_(self, c):
198
"""
199
Multiplication by a scalar from the left (``self`` is on the right).
200
201
INPUT:
202
203
- ``c`` -- an element of ``self.parent().base_ring()``.
204
205
OUTPUT:
206
207
The product ``c * self`` as a new instance of a module
208
element.
209
210
EXAMPLES::
211
212
sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
213
sage: Q = V/W; Q
214
Finitely generated module V/W over Integer Ring with invariants (4, 12)
215
sage: x = Q.0; x
216
(1, 0)
217
sage: 2 * x # indirect doctest
218
(2, 0)
219
sage: x._rmul_(4)
220
(0, 0)
221
sage: V = V.base_extend(QQ); W = V.span([2*V.0+4*V.1])
222
sage: Q = V/W; Q
223
Vector space quotient V/W of dimension 2 over Rational Field where
224
V: Vector space of degree 3 and dimension 3 over Rational Field
225
Basis matrix:
226
[1 0 0]
227
[0 1 0]
228
[0 0 1]
229
W: Vector space of degree 3 and dimension 1 over Rational Field
230
Basis matrix:
231
[1 2 0]
232
sage: x = Q.0; x
233
(1, 0)
234
sage: (1/2) * x # indirect doctest
235
(1/2, 0)
236
sage: x._rmul_(1/4)
237
(1/4, 0)
238
"""
239
# print "_rmul_"
240
P = self.parent()
241
return P.element_class(P, self._x._rmul_(c))
242
243
def _lmul_(self, s):
244
"""
245
Multiplication by a scalar from the right (``self`` is on the left).
246
247
INPUT:
248
249
- ``c`` -- an element of ``self.parent().base_ring()``.
250
251
OUTPUT:
252
253
The product ``self * c`` as a new instance of a module
254
element.
255
256
EXAMPLES::
257
258
sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
259
sage: Q = V/W; Q
260
Finitely generated module V/W over Integer Ring with invariants (4, 12)
261
sage: x = Q.0; x
262
(1, 0)
263
sage: x * 2 # indirect doctest
264
(2, 0)
265
sage: x._lmul_(4)
266
(0, 0)
267
sage: V = V.base_extend(QQ); W = V.span([2*V.0+4*V.1])
268
sage: Q = V/W; Q
269
Vector space quotient V/W of dimension 2 over Rational Field where
270
V: Vector space of degree 3 and dimension 3 over Rational Field
271
Basis matrix:
272
[1 0 0]
273
[0 1 0]
274
[0 0 1]
275
W: Vector space of degree 3 and dimension 1 over Rational Field
276
Basis matrix:
277
[1 2 0]
278
sage: x = Q.0; x
279
(1, 0)
280
sage: x * (1/2) # indirect doctest
281
(1/2, 0)
282
sage: x._lmul_(1/4)
283
(1/4, 0)
284
"""
285
# print '_lmul_'
286
P = self.parent()
287
return P.element_class(P, self._x._lmul_(s))
288
289
290
def _repr_(self):
291
"""
292
293
EXAMPLES::
294
295
sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
296
sage: Q = V/W
297
sage: Q(V.1)._repr_()
298
'(0, 1)'
299
"""
300
return self.vector().__repr__()
301
302
303
def __getitem__(self, *args):
304
"""
305
EXAMPLES::
306
307
sage: V = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
308
sage: Q = V/W; Q
309
Finitely generated module V/W over Integer Ring with invariants (4, 12)
310
sage: x = Q.0 + 3*Q.1; x
311
(1, 3)
312
sage: x[0]
313
1
314
sage: x[1]
315
3
316
sage: x[-1]
317
3
318
"""
319
return self.vector().__getitem__(*args)
320
321
def vector(self):
322
"""
323
EXAMPLES::
324
325
sage: V = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
326
sage: Q = V/W; Q
327
Finitely generated module V/W over Integer Ring with invariants (4, 12)
328
sage: x = Q.0 + 3*Q.1; x
329
(1, 3)
330
sage: x.vector()
331
(1, 3)
332
sage: tuple(x)
333
(1, 3)
334
sage: list(x)
335
[1, 3]
336
sage: x.vector().parent()
337
Ambient free module of rank 2 over the principal ideal domain Integer Ring
338
"""
339
try: return self.__vector
340
except AttributeError:
341
self.__vector = self.parent().coordinate_vector(self, reduce=True)
342
return self.__vector
343
344
345
def __cmp__(self, right):
346
"""
347
Compare self and right.
348
349
EXAMPLES::
350
351
sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
352
sage: Q = V/W; Q
353
Finitely generated module V/W over Integer Ring with invariants (4, 12)
354
sage: x = Q.0; x
355
(1, 0)
356
sage: y = Q.1; y
357
(0, 1)
358
sage: x == y
359
False
360
sage: x == x
361
True
362
sage: x + x == 2*x
363
True
364
"""
365
return cmp(self.vector(), right.vector())
366
367
def additive_order(self):
368
"""
369
Return the additive order of this element.
370
371
EXAMPLES::
372
373
sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
374
sage: Q = V/W; Q
375
Finitely generated module V/W over Integer Ring with invariants (4, 12)
376
sage: Q.0.additive_order()
377
4
378
sage: Q.1.additive_order()
379
12
380
sage: (Q.0+Q.1).additive_order()
381
12
382
sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1])
383
sage: Q = V/W; Q
384
Finitely generated module V/W over Integer Ring with invariants (12, 0)
385
sage: Q.0.additive_order()
386
12
387
sage: type(Q.0.additive_order())
388
<type 'sage.rings.integer.Integer'>
389
sage: Q.1.additive_order()
390
+Infinity
391
"""
392
Q = self.parent()
393
I = Q.invariants()
394
v = self.vector()
395
396
from sage.rings.all import infinity, lcm, Mod, Integer
397
n = Integer(1)
398
for i, a in enumerate(I):
399
if a == 0:
400
if v[i] != 0:
401
return infinity
402
else:
403
n = lcm(n, Mod(v[i],a).additive_order())
404
return n
405
406