Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/rings/fraction_field.py
8817 views
1
"""
2
Fraction Field of Integral Domains
3
4
AUTHORS:
5
6
- William Stein (with input from David Joyner, David Kohel, and Joe
7
Wetherell)
8
9
- Burcin Erocal
10
11
EXAMPLES:
12
13
Quotienting is a constructor for an element of the fraction field::
14
15
sage: R.<x> = QQ[]
16
sage: (x^2-1)/(x+1)
17
x - 1
18
sage: parent((x^2-1)/(x+1))
19
Fraction Field of Univariate Polynomial Ring in x over Rational Field
20
21
The GCD is not taken (since it doesn't converge sometimes) in the
22
inexact case::
23
24
sage: Z.<z> = CC[]
25
sage: I = CC.gen()
26
sage: (1+I+z)/(z+0.1*I)
27
(z + 1.00000000000000 + I)/(z + 0.100000000000000*I)
28
sage: (1+I*z)/(z+1.1)
29
(I*z + 1.00000000000000)/(z + 1.10000000000000)
30
31
TESTS::
32
33
sage: F = FractionField(IntegerRing())
34
sage: F == loads(dumps(F))
35
True
36
37
::
38
39
sage: F = FractionField(PolynomialRing(RationalField(),'x'))
40
sage: F == loads(dumps(F))
41
True
42
43
::
44
45
sage: F = FractionField(PolynomialRing(IntegerRing(),'x'))
46
sage: F == loads(dumps(F))
47
True
48
49
::
50
51
sage: F = FractionField(PolynomialRing(RationalField(),2,'x'))
52
sage: F == loads(dumps(F))
53
True
54
"""
55
56
#*****************************************************************************
57
#
58
# Sage: System for Algebra and Geometry Experimentation
59
#
60
# Copyright (C) 2005 William Stein <[email protected]>
61
#
62
# Distributed under the terms of the GNU General Public License (GPL)
63
#
64
# This code is distributed in the hope that it will be useful,
65
# but WITHOUT ANY WARRANTY; without even the implied warranty of
66
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
67
# General Public License for more details.
68
#
69
# The full text of the GPL is available at:
70
#
71
# http://www.gnu.org/licenses/
72
#*****************************************************************************
73
74
import ring
75
import field
76
import fraction_field_element
77
import sage.misc.latex as latex
78
from sage.misc.cachefunc import cached_method
79
80
from sage.structure.parent import Parent
81
from sage.structure.coerce_maps import CallableConvertMap
82
from sage.categories.basic import QuotientFields
83
84
def FractionField(R, names=None):
85
"""
86
Create the fraction field of the integral domain ``R``.
87
88
INPUT:
89
90
- ``R`` -- an integral domain
91
92
- ``names`` -- ignored
93
94
EXAMPLES:
95
96
We create some example fraction fields::
97
98
sage: FractionField(IntegerRing())
99
Rational Field
100
sage: FractionField(PolynomialRing(RationalField(),'x'))
101
Fraction Field of Univariate Polynomial Ring in x over Rational Field
102
sage: FractionField(PolynomialRing(IntegerRing(),'x'))
103
Fraction Field of Univariate Polynomial Ring in x over Integer Ring
104
sage: FractionField(PolynomialRing(RationalField(),2,'x'))
105
Fraction Field of Multivariate Polynomial Ring in x0, x1 over Rational Field
106
107
Dividing elements often implicitly creates elements of the fraction
108
field::
109
110
sage: x = PolynomialRing(RationalField(), 'x').gen()
111
sage: f = x/(x+1)
112
sage: g = x**3/(x+1)
113
sage: f/g
114
1/x^2
115
sage: g/f
116
x^2
117
118
The input must be an integral domain::
119
120
sage: Frac(Integers(4))
121
Traceback (most recent call last):
122
...
123
TypeError: R must be an integral domain.
124
"""
125
if not ring.is_Ring(R):
126
raise TypeError, "R must be a ring"
127
if not R.is_integral_domain():
128
raise TypeError, "R must be an integral domain."
129
return R.fraction_field()
130
131
def is_FractionField(x):
132
"""
133
Test whether or not ``x`` inherits from :class:`FractionField_generic`.
134
135
EXAMPLES::
136
137
sage: from sage.rings.fraction_field import is_FractionField
138
sage: is_FractionField(Frac(ZZ['x']))
139
True
140
sage: is_FractionField(QQ)
141
False
142
"""
143
return isinstance(x, FractionField_generic)
144
145
class FractionField_generic(field.Field):
146
"""
147
The fraction field of an integral domain.
148
"""
149
def __init__(self, R,
150
element_class=fraction_field_element.FractionFieldElement,
151
category=QuotientFields()):
152
"""
153
Create the fraction field of the integral domain ``R``.
154
155
INPUT:
156
157
- ``R`` -- an integral domain
158
159
EXAMPLES::
160
161
sage: Frac(QQ['x'])
162
Fraction Field of Univariate Polynomial Ring in x over Rational Field
163
sage: Frac(QQ['x,y']).variable_names()
164
('x', 'y')
165
sage: category(Frac(QQ['x']))
166
Category of quotient fields
167
"""
168
self._R = R
169
self._element_class = element_class
170
self._element_init_pass_parent = False
171
Parent.__init__(self, base=R, names=R._names, category=category)
172
173
def __reduce__(self):
174
"""
175
For pickling.
176
177
TESTS::
178
179
sage: K = Frac(QQ['x'])
180
sage: loads(dumps(K)) is K
181
True
182
"""
183
return FractionField, (self._R,)
184
185
def _coerce_map_from_(self, S):
186
"""
187
Return ``True`` if elements of ``S`` can be coerced into this
188
fraction field.
189
190
This fraction field has coercions from:
191
192
- itself
193
- any fraction field where the base ring coerces to the base
194
ring of this fraction field
195
- any ring that coerces to the base ring of this fraction field
196
197
EXAMPLES::
198
199
sage: F = QQ['x,y'].fraction_field()
200
sage: F.has_coerce_map_from(F) # indirect doctest
201
True
202
203
::
204
205
sage: F.has_coerce_map_from(ZZ['x,y'].fraction_field())
206
True
207
208
::
209
210
sage: F.has_coerce_map_from(ZZ['x,y,z'].fraction_field())
211
False
212
213
::
214
215
sage: F.has_coerce_map_from(ZZ)
216
True
217
218
Test coercions::
219
220
sage: F.coerce(1)
221
1
222
sage: F.coerce(int(1))
223
1
224
sage: F.coerce(1/2)
225
1/2
226
227
::
228
229
sage: K = ZZ['x,y'].fraction_field()
230
sage: x,y = K.gens()
231
sage: F.coerce(F.gen())
232
x
233
sage: F.coerce(x)
234
x
235
sage: F.coerce(x/y)
236
x/y
237
sage: L = ZZ['x'].fraction_field()
238
sage: K.coerce(L.gen())
239
x
240
241
We demonstrate that :trac:`7958` is resolved in the case of
242
number fields::
243
244
sage: _.<x> = ZZ[]
245
sage: K.<a> = NumberField(x^5-3*x^4+2424*x^3+2*x-232)
246
sage: R.<b> = K.ring_of_integers()
247
sage: S.<y> = R[]
248
sage: F = FractionField(S)
249
sage: F(1/a)
250
(a^4 - 3*a^3 + 2424*a^2 + 2)/232
251
252
Some corner cases have been known to fail in the past (:trac:`5917`)::
253
254
sage: F1 = FractionField( QQ['a'] )
255
sage: R12 = F1['x','y']
256
sage: R12('a')
257
a
258
sage: F1(R12(F1('a')))
259
a
260
261
sage: F2 = FractionField( QQ['a','b'] )
262
sage: R22 = F2['x','y']
263
sage: R22('a')
264
a
265
sage: F2(R22(F2('a')))
266
a
267
268
"""
269
from sage.rings.integer_ring import ZZ
270
from sage.rings.rational_field import QQ
271
from sage.rings.number_field.number_field_base import NumberField
272
273
# The case ``S`` being `\QQ` requires special handling since `\QQ` is
274
# not implemented as a ``FractionField_generic``.
275
if S is QQ and self._R.has_coerce_map_from(ZZ):
276
return CallableConvertMap(S, self, \
277
lambda x: self._element_class(self, x.numerator(),
278
x.denominator()), parent_as_first_arg=False)
279
280
# Number fields also need to be handled separately.
281
if isinstance(S, NumberField):
282
return CallableConvertMap(S, self, \
283
self._number_field_to_frac_of_ring_of_integers, \
284
parent_as_first_arg=False)
285
286
if isinstance(S, FractionField_generic) and \
287
self._R.has_coerce_map_from(S.ring()):
288
return CallableConvertMap(S, self, \
289
lambda x: self._element_class(self, x.numerator(),
290
x.denominator()), parent_as_first_arg=False)
291
292
if self._R.has_coerce_map_from(S):
293
return CallableConvertMap(S, self, self._element_class,
294
parent_as_first_arg=True)
295
296
return None
297
298
def _number_field_to_frac_of_ring_of_integers(self, x):
299
r"""
300
Return the number field element ``x`` as an element of ``self``,
301
explicitly treating the numerator of ``x`` as an element of the ring
302
of integers and the denominator as an integer.
303
304
INPUT:
305
306
- ``x`` -- Number field element
307
308
OUTPUT:
309
310
- Element of ``self``
311
312
TEST:
313
314
We demonstrate that :trac:`7958` is resolved in the case of
315
number fields::
316
317
sage: _.<x> = ZZ[]
318
sage: K.<a> = NumberField(x^5-3*x^4+2424*x^3+2*x-232)
319
sage: R.<b> = K.ring_of_integers()
320
sage: S.<y> = R[]
321
sage: F = FractionField(S) # indirect doctest
322
sage: F(1/a)
323
(a^4 - 3*a^3 + 2424*a^2 + 2)/232
324
"""
325
f = x.polynomial() # Polynomial over QQ
326
d = f.denominator() # Integer
327
return self._element_class(self, numerator=d*x, denominator=d)
328
329
def is_field(self, proof = True):
330
"""
331
Return ``True``, since the fraction field is a field.
332
333
EXAMPLES::
334
335
sage: Frac(ZZ).is_field()
336
True
337
"""
338
return True
339
340
def is_finite(self):
341
"""
342
Tells whether this fraction field is finite.
343
344
.. NOTE::
345
346
A fraction field is finite if and only if the associated
347
integral domain is finite.
348
349
EXAMPLE::
350
351
sage: Frac(QQ['a','b','c']).is_finite()
352
False
353
354
"""
355
return self._R.is_finite()
356
357
def base_ring(self):
358
"""
359
Return the base ring of ``self``; this is the base ring of the ring
360
which this fraction field is the fraction field of.
361
362
EXAMPLES::
363
364
sage: R = Frac(ZZ['t'])
365
sage: R.base_ring()
366
Integer Ring
367
"""
368
return self._R.base_ring()
369
370
def characteristic(self):
371
"""
372
Return the characteristic of this fraction field.
373
374
EXAMPLES::
375
376
sage: R = Frac(ZZ['t'])
377
sage: R.base_ring()
378
Integer Ring
379
sage: R = Frac(ZZ['t']); R.characteristic()
380
0
381
sage: R = Frac(GF(5)['w']); R.characteristic()
382
5
383
"""
384
return self._R.characteristic()
385
386
def _repr_(self):
387
"""
388
Return a string representation of ``self``.
389
390
EXAMPLES::
391
392
sage: Frac(ZZ['x']) # indirect doctest
393
Fraction Field of Univariate Polynomial Ring in x over Integer Ring
394
"""
395
return "Fraction Field of %s"%self._R
396
397
def _latex_(self):
398
"""
399
Return a latex representation of ``self``.
400
401
EXAMPLES::
402
403
sage: latex(Frac(GF(7)['x,y,z'])) # indirect doctest
404
\mathrm{Frac}(\Bold{F}_{7}[x, y, z])
405
"""
406
return "\\mathrm{Frac}(%s)"%latex.latex(self._R)
407
408
def _magma_init_(self, magma):
409
"""
410
Return a string representation of ``self`` in the given magma instance.
411
412
EXAMPLES::
413
414
sage: QQ['x'].fraction_field()._magma_init_(magma) # optional - magma
415
'SageCreateWithNames(FieldOfFractions(SageCreateWithNames(PolynomialRing(_sage_ref...),["x"])),["x"])'
416
sage: GF(9,'a')['x,y,z'].fraction_field()._magma_init_(magma) # optional - magma
417
'SageCreateWithNames(FieldOfFractions(SageCreateWithNames(PolynomialRing(_sage_ref...,3,"grevlex"),["x","y","z"])),["x","y","z"])'
418
419
``_magma_init_`` gets called implicitly below::
420
421
sage: magma(QQ['x,y'].fraction_field()) # optional - magma
422
Multivariate rational function field of rank 2 over Rational Field
423
Variables: x, y
424
sage: magma(ZZ['x'].fraction_field()) # optional - magma
425
Univariate rational function field over Integer Ring
426
Variables: x
427
428
Verify that conversion is being properly cached::
429
430
sage: k = Frac(QQ['x,z']) # optional - magma
431
sage: magma(k) is magma(k) # optional - magma
432
True
433
"""
434
s = 'FieldOfFractions(%s)'%self.ring()._magma_init_(magma)
435
return magma._with_names(s, self.variable_names())
436
437
def ring(self):
438
"""
439
Return the ring that this is the fraction field of.
440
441
EXAMPLES::
442
443
sage: R = Frac(QQ['x,y'])
444
sage: R
445
Fraction Field of Multivariate Polynomial Ring in x, y over Rational Field
446
sage: R.ring()
447
Multivariate Polynomial Ring in x, y over Rational Field
448
"""
449
return self._R
450
451
@cached_method
452
def is_exact(self):
453
"""
454
Return if ``self`` is exact which is if the underlying ring is exact.
455
456
EXAMPLES::
457
458
sage: Frac(ZZ['x']).is_exact()
459
True
460
sage: Frac(CDF['x']).is_exact()
461
False
462
"""
463
return self.ring().is_exact()
464
465
def _element_constructor_(self, x, y=1, coerce=True):
466
"""
467
Construct an element of this fraction field.
468
469
EXAMPLES::
470
471
sage: F = QQ['x,y'].fraction_field()
472
sage: F._element_constructor_(1)
473
1
474
sage: F._element_constructor_(F.gen(0)/F.gen(1))
475
x/y
476
sage: F._element_constructor_('1 + x/y')
477
(x + y)/y
478
479
::
480
481
sage: K = ZZ['x,y'].fraction_field()
482
sage: x,y = K.gens()
483
484
::
485
486
sage: F._element_constructor_(x/y)
487
x/y
488
489
TESTS:
490
491
The next example failed before :trac:`4376`::
492
493
sage: K(pari((x + 1)/(x^2 + x + 1)))
494
(x + 1)/(x^2 + x + 1)
495
496
These examples failed before :trac:`11368`::
497
498
sage: R.<x, y, z> = PolynomialRing(QQ)
499
sage: S = R.fraction_field()
500
sage: S(pari((x + y)/y))
501
(x + y)/y
502
503
sage: S(pari(x + y + 1/z))
504
(x*z + y*z + 1)/z
505
506
"""
507
Element = self._element_class
508
if isinstance(x, Element) and y == 1:
509
if x.parent() is self:
510
return x
511
else:
512
return Element(self, x.numerator(), x.denominator())
513
elif isinstance(x, basestring):
514
try:
515
from sage.misc.sage_eval import sage_eval
516
x = sage_eval(x, self.gens_dict_recursive())
517
y = sage_eval(str(y), self.gens_dict_recursive())
518
return self._element_constructor_(x, y)
519
except NameError:
520
raise TypeError("unable to convert string")
521
522
try:
523
return Element(self, x, y, coerce=coerce)
524
except (TypeError, ValueError):
525
if y == 1:
526
from sage.symbolic.expression import Expression
527
if isinstance(x, Expression):
528
return Element(self, x.numerator(), x.denominator())
529
from sage.libs.pari.all import pari_gen
530
if isinstance(x, pari_gen):
531
t = x.type()
532
if t == 't_RFRAC':
533
return Element(self, x.numerator(), x.denominator())
534
elif t == 't_POL':
535
# This recursive approach is needed because PARI
536
# represents multivariate polynomials as iterated
537
# univariate polynomials (see the above examples).
538
# Below, v is the variable with highest priority,
539
# and the x[i] are rational functions in the
540
# remaining variables.
541
v = self(x.variable())
542
return sum(self(x[i]) * v**i for i in xrange(x.poldegree() + 1))
543
raise
544
545
def construction(self):
546
"""
547
EXAMPLES::
548
549
sage: Frac(ZZ['x']).construction()
550
(FractionField, Univariate Polynomial Ring in x over Integer Ring)
551
sage: K = Frac(GF(3)['t'])
552
sage: f, R = K.construction()
553
sage: f(R)
554
Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 3
555
sage: f(R) == K
556
True
557
"""
558
from sage.categories.pushout import FractionField
559
return FractionField(), self.ring()
560
561
def __cmp__(self, other):
562
"""
563
EXAMPLES::
564
565
sage: Frac(ZZ['x']) == Frac(ZZ['x'])
566
True
567
sage: Frac(ZZ['x']) == Frac(QQ['x'])
568
False
569
sage: Frac(ZZ['x']) == Frac(ZZ['y'])
570
False
571
sage: Frac(ZZ['x']) == QQ['x']
572
False
573
"""
574
if not isinstance(other, FractionField_generic):
575
return cmp(type(self), type(other))
576
return cmp(self._R, other._R)
577
578
def ngens(self):
579
"""
580
This is the same as for the parent object.
581
582
EXAMPLES::
583
584
sage: R = Frac(PolynomialRing(QQ,'z',10)); R
585
Fraction Field of Multivariate Polynomial Ring in z0, z1, z2, z3, z4, z5, z6, z7, z8, z9 over Rational Field
586
sage: R.ngens()
587
10
588
"""
589
return self._R.ngens()
590
591
def gen(self, i=0):
592
"""
593
Return the ``i``-th generator of ``self``.
594
595
EXAMPLES::
596
597
sage: R = Frac(PolynomialRing(QQ,'z',10)); R
598
Fraction Field of Multivariate Polynomial Ring in z0, z1, z2, z3, z4, z5, z6, z7, z8, z9 over Rational Field
599
sage: R.0
600
z0
601
sage: R.gen(3)
602
z3
603
sage: R.3
604
z3
605
"""
606
x = self._R.gen(i)
607
one = self._R.one_element()
608
r = self._element_class(self, x, one, coerce=False, reduce=False)
609
return r
610
611
def _is_valid_homomorphism_(self, codomain, im_gens):
612
"""
613
Check if the homomorphism defined by sending generators of this
614
fraction field to ``im_gens`` in ``codomain`` is valid.
615
616
EXAMPLES::
617
618
sage: F = QQ['x,y'].fraction_field()
619
sage: x,y = F.gens()
620
sage: F._is_valid_homomorphism_(F, [y,x])
621
True
622
sage: R = ZZ['x']; x = R.gen()
623
sage: F._is_valid_homomorphism_(R, [x, x])
624
False
625
626
TESTS::
627
628
sage: F._is_valid_homomorphism_(ZZ, [])
629
False
630
631
Test homomorphisms::
632
633
sage: phi = F.hom([2*y, x])
634
sage: phi(x+y)
635
x + 2*y
636
sage: phi(x/y)
637
2*y/x
638
"""
639
if len(im_gens) != self.ngens():
640
return False
641
# it is enough to check if elements of the base ring coerce to
642
# the codomain
643
if codomain.has_coerce_map_from(self.base_ring()):
644
return True
645
return False
646
647
def random_element(self, *args, **kwds):
648
"""
649
Returns a random element in this fraction field.
650
651
EXAMPLES::
652
653
sage: F = ZZ['x'].fraction_field()
654
sage: F.random_element()
655
(2*x - 8)/(-x^2 + x)
656
657
::
658
659
sage: F.random_element(degree=5)
660
(-12*x^5 - 2*x^4 - x^3 - 95*x^2 + x + 2)/(-x^5 + x^4 - x^3 + x^2)
661
"""
662
return self._element_class(self, self._R.random_element(*args, **kwds),
663
self._R._random_nonzero_element(*args, **kwds),
664
coerce = False, reduce=True)
665
666
class FractionField_1poly_field(FractionField_generic):
667
"""
668
The fraction field of a univariate polynomial ring over a field.
669
670
Many of the functions here are included for coherence with number fields.
671
"""
672
def __init__(self, R,
673
element_class=fraction_field_element.FractionFieldElement_1poly_field):
674
"""
675
Just changes the default for ``element_class``.
676
677
EXAMPLES::
678
679
sage: R.<t> = QQ[]; K = R.fraction_field()
680
sage: K._element_class
681
<class 'sage.rings.fraction_field_element.FractionFieldElement_1poly_field'>
682
"""
683
FractionField_generic.__init__(self, R, element_class)
684
685
def ring_of_integers(self):
686
"""
687
Returns the ring of integers in this fraction field.
688
689
EXAMPLES::
690
691
sage: K = FractionField(GF(5)['t'])
692
sage: K.ring_of_integers()
693
Univariate Polynomial Ring in t over Finite Field of size 5
694
"""
695
return self._R
696
697
def maximal_order(self):
698
"""
699
Returns the maximal order in this fraction field.
700
701
EXAMPLES::
702
703
sage: K = FractionField(GF(5)['t'])
704
sage: K.maximal_order()
705
Univariate Polynomial Ring in t over Finite Field of size 5
706
"""
707
return self._R
708
709
def class_number(self):
710
"""
711
Here for compatibility with number fields and function fields.
712
713
EXAMPLES::
714
715
sage: R.<t> = GF(5)[]; K = R.fraction_field()
716
sage: K.class_number()
717
1
718
"""
719
return 1
720
721