Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/rings/laurent_series_ring.py
8817 views
1
"""
2
Laurent Series Rings
3
4
EXAMPLES::
5
6
sage: R = LaurentSeriesRing(QQ, "x")
7
sage: R.base_ring()
8
Rational Field
9
sage: S = LaurentSeriesRing(GF(17)['x'], 'y')
10
sage: S
11
Laurent Series Ring in y over Univariate Polynomial Ring in x over
12
Finite Field of size 17
13
sage: S.base_ring()
14
Univariate Polynomial Ring in x over Finite Field of size 17
15
"""
16
17
import weakref
18
19
import laurent_series_ring_element
20
import power_series_ring
21
import polynomial
22
import commutative_ring
23
import integral_domain
24
import field
25
26
from sage.structure.parent_gens import ParentWithGens
27
from sage.libs.pari.all import pari_gen
28
29
from sage.structure.category_object import check_default_category
30
from sage.categories.fields import Fields
31
from sage.categories.complete_discrete_valuation import CompleteDiscreteValuationFields
32
33
laurent_series = {}
34
def LaurentSeriesRing(base_ring, name=None, names=None, default_prec=20, sparse=False):
35
"""
36
EXAMPLES::
37
38
sage: R = LaurentSeriesRing(QQ, 'x'); R
39
Laurent Series Ring in x over Rational Field
40
sage: x = R.0
41
sage: g = 1 - x + x^2 - x^4 +O(x^8); g
42
1 - x + x^2 - x^4 + O(x^8)
43
sage: g = 10*x^(-3) + 2006 - 19*x + x^2 - x^4 +O(x^8); g
44
10*x^-3 + 2006 - 19*x + x^2 - x^4 + O(x^8)
45
46
You can also use more mathematical notation when the base is a
47
field::
48
49
sage: Frac(QQ[['x']])
50
Laurent Series Ring in x over Rational Field
51
sage: Frac(GF(5)['y'])
52
Fraction Field of Univariate Polynomial Ring in y over Finite Field of size 5
53
54
Here the fraction field is not just the Laurent series ring, so you
55
can't use the ``Frac`` notation to make the Laurent
56
series ring.
57
58
::
59
60
sage: Frac(ZZ[['t']])
61
Fraction Field of Power Series Ring in t over Integer Ring
62
63
Laurent series rings are determined by their variable and the base
64
ring, and are globally unique.
65
66
::
67
68
sage: K = Qp(5, prec = 5)
69
sage: L = Qp(5, prec = 200)
70
sage: R.<x> = LaurentSeriesRing(K)
71
sage: S.<y> = LaurentSeriesRing(L)
72
sage: R is S
73
False
74
sage: T.<y> = LaurentSeriesRing(Qp(5,prec=200))
75
sage: S is T
76
True
77
sage: W.<y> = LaurentSeriesRing(Qp(5,prec=199))
78
sage: W is T
79
False
80
"""
81
if not names is None: name = names
82
if name is None:
83
raise TypeError, "You must specify the name of the indeterminate of the Laurent series ring."
84
85
global laurent_series
86
key = (base_ring, name, default_prec, sparse)
87
if laurent_series.has_key(key):
88
x = laurent_series[key]()
89
if x != None: return x
90
91
if isinstance(base_ring, field.Field):
92
R = LaurentSeriesRing_field(base_ring, name, default_prec, sparse)
93
elif isinstance(base_ring, integral_domain.IntegralDomain):
94
R = LaurentSeriesRing_domain(base_ring, name, default_prec, sparse)
95
elif isinstance(base_ring, commutative_ring.CommutativeRing):
96
R = LaurentSeriesRing_generic(base_ring, name, default_prec, sparse)
97
else:
98
raise TypeError, "base_ring must be a commutative ring"
99
laurent_series[key] = weakref.ref(R)
100
return R
101
102
def is_LaurentSeriesRing(x):
103
"""
104
TESTS::
105
106
sage: from sage.rings.laurent_series_ring import is_LaurentSeriesRing
107
sage: K.<q> = LaurentSeriesRing(QQ)
108
sage: is_LaurentSeriesRing(K)
109
True
110
"""
111
return isinstance(x, LaurentSeriesRing_generic)
112
113
class LaurentSeriesRing_generic(commutative_ring.CommutativeRing):
114
"""
115
Univariate Laurent Series Ring
116
117
EXAMPLES::
118
119
sage: K, q = LaurentSeriesRing(CC, 'q').objgen(); K
120
Laurent Series Ring in q over Complex Field with 53 bits of precision
121
sage: loads(K.dumps()) == K
122
True
123
sage: P = QQ[['x']]
124
sage: F = Frac(P)
125
sage: TestSuite(F).run()
126
127
When the base ring `k` is a field, the ring `k((x))` is a CDVF, that is
128
a field equipped with a discrete valuation for which it is complete.
129
The appropriate (sub)category is automatically set in this case::
130
131
sage: k = GF(11)
132
sage: R.<x> = k[[]]
133
sage: F = Frac(R)
134
sage: F.category()
135
Category of complete discrete valuation fields
136
sage: TestSuite(F).run()
137
"""
138
139
def __init__(self, base_ring, name=None, default_prec=20, sparse=False, category=None):
140
"""
141
Initialization
142
143
EXAMPLES::
144
145
sage: K.<q> = LaurentSeriesRing(QQ,default_prec=4); K
146
Laurent Series Ring in q over Rational Field
147
sage: 1 / (q-q^2)
148
q^-1 + 1 + q + q^2 + O(q^3)
149
"""
150
commutative_ring.CommutativeRing.__init__(self, base_ring, names=name,
151
category=getattr(self, '_default_category', Fields()))
152
self._polynomial_ring = polynomial.polynomial_ring_constructor.PolynomialRing(self.base_ring(),
153
self.variable_name(),
154
sparse=sparse)
155
self._power_series_ring = power_series_ring.PowerSeriesRing(self.base_ring(),
156
self.variable_name(),
157
default_prec=default_prec,
158
sparse=sparse)
159
160
def base_extend(self, R):
161
"""
162
Returns the laurent series ring over R in the same variable as
163
self, assuming there is a canonical coerce map from the base ring
164
of self to R.
165
166
EXAMPLES::
167
168
sage: K.<x> = LaurentSeriesRing(QQ, default_prec=4)
169
sage: K.base_extend(QQ['t'])
170
Laurent Series Ring in x over Univariate Polynomial Ring in t over Rational Field
171
"""
172
if R.has_coerce_map_from(self.base_ring()):
173
return self.change_ring(R)
174
else:
175
raise TypeError, "no valid base extension defined"
176
177
def change_ring(self, R):
178
"""
179
EXAMPLES::
180
181
sage: K.<x> = LaurentSeriesRing(QQ, default_prec=4)
182
sage: R = K.change_ring(ZZ); R
183
Laurent Series Ring in x over Integer Ring
184
sage: R.default_prec()
185
4
186
"""
187
return LaurentSeriesRing(R, self.variable_name(), default_prec=self.default_prec(), sparse=self.is_sparse())
188
189
def is_sparse(self):
190
"""
191
EXAMPLES::
192
193
sage: K.<x> = LaurentSeriesRing(QQ, sparse=True)
194
sage: K.is_sparse()
195
True
196
"""
197
return self.power_series_ring().is_sparse()
198
199
def is_field(self, proof = True):
200
"""
201
A Laurent series ring is a field if and only if the base ring is a field.
202
203
TESTS::
204
205
sage: LaurentSeriesRing(QQ,'t').is_field()
206
True
207
sage: LaurentSeriesRing(ZZ,'t').is_field()
208
False
209
"""
210
return self.base_ring().is_field()
211
212
def is_dense(self):
213
"""
214
EXAMPLES::
215
216
sage: K.<x> = LaurentSeriesRing(QQ, sparse=True)
217
sage: K.is_dense()
218
False
219
"""
220
return self.power_series_ring().is_dense()
221
222
def __reduce__(self):
223
"""
224
TESTS::
225
226
sage: K.<q> = LaurentSeriesRing(QQ,default_prec=4)
227
sage: L = loads(dumps(K))
228
sage: L.default_prec()
229
4
230
"""
231
return self.__class__, (self.base_ring(), self.variable_name(), self.default_prec(), self.is_sparse())
232
233
def _repr_(self):
234
"""
235
EXAMPLES::
236
237
sage: LaurentSeriesRing(QQ,'q') # indirect doctest
238
Laurent Series Ring in q over Rational Field
239
sage: LaurentSeriesRing(ZZ,'t',sparse=True)
240
Sparse Laurent Series Ring in t over Integer Ring
241
"""
242
s = "Laurent Series Ring in %s over %s"%(self.variable_name(), self.base_ring())
243
if self.is_sparse():
244
s = 'Sparse ' + s
245
return s
246
247
def __call__(self, x, n=0):
248
r"""
249
Coerces the element x into this Laurent series ring.
250
251
INPUT:
252
253
254
- ``x`` - the element to coerce
255
256
- ``n`` - the result of the coercion will be
257
multiplied by `t^n` (default: 0)
258
259
260
EXAMPLES::
261
262
sage: R.<u> = LaurentSeriesRing(Qp(5, 10))
263
sage: S.<t> = LaurentSeriesRing(RationalField())
264
sage: print R(t + t^2 + O(t^3))
265
(1 + O(5^10))*u + (1 + O(5^10))*u^2 + O(u^3)
266
267
Note that coercing an element into its own parent just produces
268
that element again (since Laurent series are immutable)::
269
270
sage: u is R(u)
271
True
272
273
Rational functions are accepted::
274
275
sage: I = sqrt(-1)
276
sage: K.<I> = QQ[I]
277
sage: P.<t> = PolynomialRing(K)
278
sage: L.<u> = LaurentSeriesRing(QQ[I])
279
sage: L((t*I)/(t^3+I*2*t))
280
1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 +
281
1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 +
282
1/1024*I*u^18 + O(u^20)
283
284
::
285
286
sage: L(t*I) / L(t^3+I*2*t)
287
1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 +
288
1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 +
289
1/1024*I*u^18 + O(u^20)
290
291
Various conversions from PARI (see also #2508)::
292
293
sage: L.<q> = LaurentSeriesRing(QQ)
294
sage: L.set_default_prec(10)
295
sage: L(pari('1/x'))
296
q^-1
297
sage: L(pari('poltchebi(5)'))
298
5*q - 20*q^3 + 16*q^5
299
sage: L(pari('poltchebi(5) - 1/x^4'))
300
-q^-4 + 5*q - 20*q^3 + 16*q^5
301
sage: L(pari('1/poltchebi(5)'))
302
1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + O(q^9)
303
sage: L(pari('poltchebi(5) + O(x^40)'))
304
5*q - 20*q^3 + 16*q^5 + O(q^40)
305
sage: L(pari('poltchebi(5) - 1/x^4 + O(x^40)'))
306
-q^-4 + 5*q - 20*q^3 + 16*q^5 + O(q^40)
307
sage: L(pari('1/poltchebi(5) + O(x^10)'))
308
1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + 8192/125*q^9 + O(q^10)
309
sage: L(pari('1/poltchebi(5) + O(x^10)'), -10) # Multiply by q^-10
310
1/5*q^-11 + 4/5*q^-9 + 64/25*q^-7 + 192/25*q^-5 + 2816/125*q^-3 + 8192/125*q^-1 + O(1)
311
sage: L(pari('O(x^-10)'))
312
O(q^-10)
313
"""
314
from sage.rings.fraction_field_element import is_FractionFieldElement
315
from sage.rings.polynomial.polynomial_element import is_Polynomial
316
from sage.rings.polynomial.multi_polynomial_element import is_MPolynomial
317
318
if isinstance(x, laurent_series_ring_element.LaurentSeries) and n==0 and self is x.parent():
319
return x # ok, since Laurent series are immutable (no need to make a copy)
320
elif isinstance(x, pari_gen):
321
t = x.type()
322
if t == "t_RFRAC": # Rational function
323
x = self(self.polynomial_ring()(x.numerator())) / \
324
self(self.polynomial_ring()(x.denominator()))
325
return (x << n)
326
elif t == "t_SER": # Laurent series
327
n += x._valp()
328
bigoh = n + x.length()
329
x = self(self.polynomial_ring()(x.Vec()))
330
return (x << n).add_bigoh(bigoh)
331
else: # General case, pretend to be a polynomial
332
return self(self.polynomial_ring()(x)) << n
333
elif is_FractionFieldElement(x) and \
334
(x.base_ring() is self.base_ring() or x.base_ring() == self.base_ring()) and \
335
(is_Polynomial(x.numerator()) or is_MPolynomial(x.numerator())):
336
x = self(x.numerator())/self(x.denominator())
337
return (x << n)
338
else:
339
return laurent_series_ring_element.LaurentSeries(self, x, n)
340
341
def _coerce_impl(self, x):
342
"""
343
Return canonical coercion of x into self.
344
345
Rings that canonically coerce to this power series ring R:
346
347
- R itself
348
349
- Any laurent series ring in the same variable whose base ring
350
canonically coerces to the base ring of R.
351
352
- Any ring that canonically coerces to the power series ring
353
over the base ring of R.
354
355
- Any ring that canonically coerces to the base ring of R
356
357
EXAMPLES::
358
359
sage: R.<t> = LaurentSeriesRing(ZZ)
360
sage: S.<t> = PowerSeriesRing(QQ)
361
sage: R.has_coerce_map_from(S) # indirect doctest
362
False
363
sage: R.has_coerce_map_from(R)
364
True
365
sage: R.<t> = LaurentSeriesRing(QQ['x'])
366
sage: R.has_coerce_map_from(S)
367
True
368
sage: R.has_coerce_map_from(QQ['t'])
369
True
370
sage: R.has_coerce_map_from(ZZ['x']['t'])
371
True
372
sage: R.has_coerce_map_from(ZZ['t']['x'])
373
False
374
sage: R.has_coerce_map_from(ZZ['x'])
375
True
376
"""
377
try:
378
P = x.parent()
379
if is_LaurentSeriesRing(P):
380
if P.variable_name() == self.variable_name():
381
if self.has_coerce_map_from(P.base_ring()):
382
return self(x)
383
else:
384
raise TypeError, "no natural map between bases of power series rings"
385
except AttributeError:
386
pass
387
388
return self._coerce_try(x, [self.power_series_ring(), self.base_ring()])
389
390
def __cmp__(self, other):
391
"""
392
Compare this Laurent series ring to something else.
393
394
Laurent series rings are considered equal if the base ring, variable
395
names, and default truncation precision are the same.
396
397
First the base rings are compared, then the variable names, then
398
the default precision.
399
400
EXAMPLES::
401
402
sage: R.<t> = LaurentSeriesRing(ZZ)
403
sage: S.<t> = LaurentSeriesRing(ZZ)
404
sage: R is S
405
True
406
sage: R == S
407
True
408
sage: S.<t> = LaurentSeriesRing(ZZ, default_prec=10)
409
sage: R == S
410
False
411
sage: LaurentSeriesRing(ZZ,'t') == LaurentSeriesRing(QQ,'t')
412
False
413
sage: LaurentSeriesRing(QQ,'t') == 5
414
False
415
"""
416
if not isinstance(other, LaurentSeriesRing_generic):
417
return cmp(type(self),type(other))
418
c = cmp(self.base_ring(), other.base_ring())
419
if c: return c
420
c = cmp(self.variable_name(), other.variable_name())
421
if c: return c
422
c = cmp(self.default_prec(), other.default_prec())
423
if c: return c
424
return 0
425
426
427
def _is_valid_homomorphism_(self, codomain, im_gens):
428
"""
429
EXAMPLES::
430
431
sage: R.<x> = LaurentSeriesRing(GF(17))
432
sage: S.<y> = LaurentSeriesRing(GF(19))
433
sage: R.hom([y], S) # indirect doctest
434
Traceback (most recent call last):
435
...
436
TypeError: images do not define a valid homomorphism
437
sage: f = R.hom(x+x^3,R)
438
sage: f(x^2)
439
x^2 + 2*x^4 + x^6
440
"""
441
## NOTE: There are no ring homomorphisms from the ring of
442
## all formal power series to most rings, e.g, the p-adic
443
## field, since you can always (mathematically!) construct
444
## some power series that doesn't converge.
445
## Note that 0 is not a *ring* homomorphism.
446
from power_series_ring import is_PowerSeriesRing
447
if is_PowerSeriesRing(codomain) or is_LaurentSeriesRing(codomain):
448
return im_gens[0].valuation() > 0 and codomain.has_coerce_map_from(self.base_ring())
449
return False
450
451
def characteristic(self):
452
"""
453
EXAMPLES::
454
455
sage: R.<x> = LaurentSeriesRing(GF(17))
456
sage: R.characteristic()
457
17
458
"""
459
return self.base_ring().characteristic()
460
461
def residue_field(self):
462
"""
463
Return the residue field of this Laurent series field
464
if it is a complete discrete valuation field (i.e. if
465
the base ring is a field, in which base it is also the
466
residue field).
467
468
EXAMPLES::
469
470
sage: R.<x> = LaurentSeriesRing(GF(17))
471
sage: R.residue_field()
472
Finite Field of size 17
473
474
sage: R.<x> = LaurentSeriesRing(ZZ)
475
sage: R.residue_field()
476
Traceback (most recent call last):
477
...
478
TypeError: The base ring is not a field
479
"""
480
if self.base_ring().is_field():
481
return self.base_ring()
482
else:
483
raise TypeError("The base ring is not a field")
484
485
def set_default_prec(self, n):
486
"""
487
Sets the default precision.
488
489
This operation should be discouraged: parents should be
490
immutable and this function may be deprecated in the future.
491
492
TESTS::
493
494
sage: R.<x> = LaurentSeriesRing(QQ)
495
sage: R.set_default_prec(3)
496
sage: 1/(x^5-x^7)
497
x^-5 + x^-3 + O(x^-2)
498
"""
499
self.power_series_ring().set_default_prec(n)
500
501
def default_prec(self):
502
"""
503
Sets the precision to which exact elements are truncated when
504
necessary (most frequently when inverting)
505
506
EXAMPLES::
507
508
sage: R.<x> = LaurentSeriesRing(QQ, default_prec=5)
509
sage: R.default_prec()
510
5
511
"""
512
return self.power_series_ring().default_prec()
513
514
def is_exact(self):
515
"""
516
Laurent series rings are inexact.
517
518
EXAMPLES::
519
520
sage: R = LaurentSeriesRing(QQ, "x")
521
sage: R.is_exact()
522
False
523
"""
524
return False
525
526
def gen(self, n=0):
527
"""
528
EXAMPLES::
529
530
sage: R = LaurentSeriesRing(QQ, "x")
531
sage: R.gen()
532
x
533
"""
534
if n != 0:
535
raise IndexError, "Generator n not defined."
536
try:
537
return self.__generator
538
except AttributeError:
539
self.__generator = laurent_series_ring_element.LaurentSeries(self, [0,1])
540
return self.__generator
541
542
def uniformizer(self):
543
"""
544
Return a uniformizer of this Laurent series field if it is
545
a discrete valuation field (i.e. if the base ring is actually
546
a field). Otherwise, an error is raised.
547
548
EXAMPLES::
549
550
sage: R.<t> = LaurentSeriesRing(QQ)
551
sage: R.uniformizer()
552
t
553
554
sage: R.<t> = LaurentSeriesRing(ZZ)
555
sage: R.uniformizer()
556
Traceback (most recent call last):
557
...
558
TypeError: The base ring is not a field
559
"""
560
if self.base_ring().is_field():
561
return self.gen()
562
else:
563
raise TypeError("The base ring is not a field")
564
565
def ngens(self):
566
"""
567
Laurent series rings are univariate.
568
569
EXAMPLES::
570
571
sage: R = LaurentSeriesRing(QQ, "x")
572
sage: R.ngens()
573
1
574
"""
575
return 1
576
577
def polynomial_ring(self):
578
r"""
579
If this is the Laurent series ring `R((t))`, return the
580
polynomial ring `R[t]`.
581
582
EXAMPLES::
583
584
sage: R = LaurentSeriesRing(QQ, "x")
585
sage: R.polynomial_ring()
586
Univariate Polynomial Ring in x over Rational Field
587
"""
588
return self._polynomial_ring
589
590
def laurent_polynomial_ring(self):
591
r"""
592
If this is the Laurent series ring `R((t))`, return the Laurent
593
polynomial ring `R[t,1/t]`.
594
595
EXAMPLES::
596
597
sage: R = LaurentSeriesRing(QQ, "x")
598
sage: R.laurent_polynomial_ring()
599
Univariate Laurent Polynomial Ring in x over Rational Field
600
"""
601
try:
602
return self.__laurent_polynomial_ring
603
except AttributeError:
604
self.__laurent_polynomial_ring = polynomial.laurent_polynomial_ring.LaurentPolynomialRing( \
605
self.base_ring(), self.variable_name(), sparse=self.is_sparse())
606
return self.__laurent_polynomial_ring
607
608
def power_series_ring(self):
609
r"""
610
If this is the Laurent series ring `R((t))`, return the
611
power series ring `R[[t]]`.
612
613
EXAMPLES::
614
615
sage: R = LaurentSeriesRing(QQ, "x")
616
sage: R.power_series_ring()
617
Power Series Ring in x over Rational Field
618
"""
619
return self._power_series_ring
620
621
class LaurentSeriesRing_domain(LaurentSeriesRing_generic, integral_domain.IntegralDomain):
622
def __init__(self, base_ring, name=None, default_prec=20, sparse=False):
623
"""
624
Initialization
625
626
TESTS::
627
628
sage: TestSuite(LaurentSeriesRing(ZZ,'t')).run()
629
"""
630
LaurentSeriesRing_generic.__init__(self, base_ring, name, default_prec, sparse)
631
632
class LaurentSeriesRing_field(LaurentSeriesRing_generic, field.Field):
633
_default_category = CompleteDiscreteValuationFields()
634
635
def __init__(self, base_ring, name=None, default_prec=20, sparse=False):
636
"""
637
Initialization
638
639
TESTS::
640
641
sage: TestSuite(LaurentSeriesRing(QQ,'t')).run()
642
"""
643
LaurentSeriesRing_generic.__init__(self, base_ring, name, default_prec, sparse)
644
645
646