Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# -*- coding: utf-8 -*- r""" Fraction Field of Integral Domains
AUTHORS:
- William Stein (with input from David Joyner, David Kohel, and Joe Wetherell)
- Burcin Erocal
- Julian Rüth (2017-06-27): embedding into the field of fractions and its section
EXAMPLES:
Quotienting is a constructor for an element of the fraction field::
sage: R.<x> = QQ[] sage: (x^2-1)/(x+1) x - 1 sage: parent((x^2-1)/(x+1)) Fraction Field of Univariate Polynomial Ring in x over Rational Field
The GCD is not taken (since it doesn't converge sometimes) in the inexact case::
sage: Z.<z> = CC[] sage: I = CC.gen() sage: (1+I+z)/(z+0.1*I) (z + 1.00000000000000 + I)/(z + 0.100000000000000*I) sage: (1+I*z)/(z+1.1) (I*z + 1.00000000000000)/(z + 1.10000000000000)
TESTS::
sage: F = FractionField(IntegerRing()) sage: F == loads(dumps(F)) True
::
sage: F = FractionField(PolynomialRing(RationalField(),'x')) sage: F == loads(dumps(F)) True
::
sage: F = FractionField(PolynomialRing(IntegerRing(),'x')) sage: F == loads(dumps(F)) True
::
sage: F = FractionField(PolynomialRing(RationalField(),2,'x')) sage: F == loads(dumps(F)) True """ # **************************************************************************** # # Sage: System for Algebra and Geometry Experimentation # # Copyright (C) 2005 William Stein <wstein@gmail.com> # 2017 Julian Rüth <julian.rueth@fsfe.org> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # http://www.gnu.org/licenses/ # **************************************************************************** from __future__ import absolute_import from six.moves import range import six
from . import ring from . import fraction_field_element import sage.misc.latex as latex from sage.misc.cachefunc import cached_method
from sage.rings.integer_ring import ZZ from sage.structure.element import Element from sage.structure.richcmp import richcmp from sage.structure.parent import Parent from sage.structure.coerce import py_scalar_to_element from sage.structure.coerce_maps import CallableConvertMap, DefaultConvertMap_unique from sage.categories.basic import QuotientFields, Rings from sage.categories.morphism import Morphism from sage.categories.map import Section
def FractionField(R, names=None): """ Create the fraction field of the integral domain ``R``.
INPUT:
- ``R`` -- an integral domain
- ``names`` -- ignored
EXAMPLES:
We create some example fraction fields::
sage: FractionField(IntegerRing()) Rational Field sage: FractionField(PolynomialRing(RationalField(),'x')) Fraction Field of Univariate Polynomial Ring in x over Rational Field sage: FractionField(PolynomialRing(IntegerRing(),'x')) Fraction Field of Univariate Polynomial Ring in x over Integer Ring sage: FractionField(PolynomialRing(RationalField(),2,'x')) Fraction Field of Multivariate Polynomial Ring in x0, x1 over Rational Field
Dividing elements often implicitly creates elements of the fraction field::
sage: x = PolynomialRing(RationalField(), 'x').gen() sage: f = x/(x+1) sage: g = x**3/(x+1) sage: f/g 1/x^2 sage: g/f x^2
The input must be an integral domain::
sage: Frac(Integers(4)) Traceback (most recent call last): ... TypeError: R must be an integral domain. """ raise TypeError("R must be a ring")
def is_FractionField(x): """ Test whether or not ``x`` inherits from :class:`FractionField_generic`.
EXAMPLES::
sage: from sage.rings.fraction_field import is_FractionField sage: is_FractionField(Frac(ZZ['x'])) True sage: is_FractionField(QQ) False """
class FractionField_generic(ring.Field): """ The fraction field of an integral domain. """ def __init__(self, R, element_class=fraction_field_element.FractionFieldElement, category=QuotientFields()): """ Create the fraction field of the integral domain ``R``.
INPUT:
- ``R`` -- an integral domain
EXAMPLES::
sage: Frac(QQ['x']) Fraction Field of Univariate Polynomial Ring in x over Rational Field sage: Frac(QQ['x,y']).variable_names() ('x', 'y') sage: category(Frac(QQ['x'])) Category of quotient fields """ cat = cat.Infinite() cat = cat.Finite()
def __reduce__(self): """ For pickling.
TESTS::
sage: K = Frac(QQ['x']) sage: loads(dumps(K)) is K True """
def _coerce_map_from_(self, S): """ Return ``True`` if elements of ``S`` can be coerced into this fraction field.
This fraction field has coercions from:
- itself - any fraction field where the base ring coerces to the base ring of this fraction field - any ring that coerces to the base ring of this fraction field
EXAMPLES::
sage: F = QQ['x,y'].fraction_field() sage: F.has_coerce_map_from(F) # indirect doctest True
::
sage: F.has_coerce_map_from(ZZ['x,y'].fraction_field()) True
::
sage: F.has_coerce_map_from(ZZ['x,y,z'].fraction_field()) False
::
sage: F.has_coerce_map_from(ZZ) True
Test coercions::
sage: F.coerce(1) 1 sage: F.coerce(int(1)) 1 sage: F.coerce(1/2) 1/2
::
sage: K = ZZ['x,y'].fraction_field() sage: x,y = K.gens() sage: F.coerce(F.gen()) x sage: F.coerce(x) x sage: F.coerce(x/y) x/y sage: L = ZZ['x'].fraction_field() sage: K.coerce(L.gen()) x
We demonstrate that :trac:`7958` is resolved in the case of number fields::
sage: _.<x> = ZZ[] sage: K.<a> = NumberField(x^5-3*x^4+2424*x^3+2*x-232) sage: R = K.ring_of_integers() sage: S.<y> = R[] sage: F = FractionField(S) sage: F(1/a) (a^4 - 3*a^3 + 2424*a^2 + 2)/232
Some corner cases have been known to fail in the past (:trac:`5917`)::
sage: F1 = FractionField( QQ['a'] ) sage: R12 = F1['x','y'] sage: R12('a') a sage: F1(R12(F1('a'))) a
sage: F2 = FractionField( QQ['a','b'] ) sage: R22 = F2['x','y'] sage: R22('a') a sage: F2(R22(F2('a'))) a
Coercion from Laurent polynomials now works (:trac:`15345`)::
sage: R = LaurentPolynomialRing(ZZ, 'x') sage: T = PolynomialRing(ZZ, 'x') sage: R.gen() + FractionField(T).gen() 2*x sage: 1/(R.gen() + 1) 1/(x + 1)
sage: R = LaurentPolynomialRing(ZZ, 'x,y') sage: FF = FractionField(PolynomialRing(ZZ, 'x,y')) sage: prod(R.gens()) + prod(FF.gens()) 2*x*y sage: 1/(R.gen(0) + R.gen(1)) 1/(x + y) """ LaurentPolynomialRing_generic
# The case ``S`` being `\QQ` requires special handling since `\QQ` is # not implemented as a ``FractionField_generic``.
# Number fields also need to be handled separately. self._number_field_to_frac_of_ring_of_integers, parent_as_first_arg=False)
# special treatment for LaurentPolynomialRings
self._R.has_coerce_map_from(S.ring())):
parent_as_first_arg=True)
def _number_field_to_frac_of_ring_of_integers(self, x): r""" Return the number field element ``x`` as an element of ``self``, explicitly treating the numerator of ``x`` as an element of the ring of integers and the denominator as an integer.
INPUT:
- ``x`` -- Number field element
OUTPUT:
- Element of ``self``
TESTS:
We demonstrate that :trac:`7958` is resolved in the case of number fields::
sage: _.<x> = ZZ[] sage: K.<a> = NumberField(x^5-3*x^4+2424*x^3+2*x-232) sage: R = K.ring_of_integers() sage: S.<y> = R[] sage: F = FractionField(S) # indirect doctest sage: F(1/a) (a^4 - 3*a^3 + 2424*a^2 + 2)/232 """
def is_field(self, proof=True): """ Return ``True``, since the fraction field is a field.
EXAMPLES::
sage: Frac(ZZ).is_field() True """
def is_finite(self): """ Tells whether this fraction field is finite.
.. NOTE::
A fraction field is finite if and only if the associated integral domain is finite.
EXAMPLES::
sage: Frac(QQ['a','b','c']).is_finite() False
"""
def base_ring(self): """ Return the base ring of ``self``.
This is the base ring of the ring which this fraction field is the fraction field of.
EXAMPLES::
sage: R = Frac(ZZ['t']) sage: R.base_ring() Integer Ring """
def characteristic(self): """ Return the characteristic of this fraction field.
EXAMPLES::
sage: R = Frac(ZZ['t']) sage: R.base_ring() Integer Ring sage: R = Frac(ZZ['t']); R.characteristic() 0 sage: R = Frac(GF(5)['w']); R.characteristic() 5 """
def _repr_(self): """ Return a string representation of ``self``.
EXAMPLES::
sage: Frac(ZZ['x']) # indirect doctest Fraction Field of Univariate Polynomial Ring in x over Integer Ring """
def _latex_(self): """ Return a latex representation of ``self``.
EXAMPLES::
sage: latex(Frac(GF(7)['x,y,z'])) # indirect doctest \mathrm{Frac}(\Bold{F}_{7}[x, y, z]) """
def _magma_init_(self, magma): """ Return a string representation of ``self`` in the given magma instance.
EXAMPLES::
sage: QQ['x'].fraction_field()._magma_init_(magma) # optional - magma 'SageCreateWithNames(FieldOfFractions(SageCreateWithNames(PolynomialRing(_sage_ref...),["x"])),["x"])' sage: GF(9,'a')['x,y,z'].fraction_field()._magma_init_(magma) # optional - magma 'SageCreateWithNames(FieldOfFractions(SageCreateWithNames(PolynomialRing(_sage_ref...,3,"grevlex"),["x","y","z"])),["x","y","z"])'
``_magma_init_`` gets called implicitly below::
sage: magma(QQ['x,y'].fraction_field()) # optional - magma Multivariate rational function field of rank 2 over Rational Field Variables: x, y sage: magma(ZZ['x'].fraction_field()) # optional - magma Univariate rational function field over Integer Ring Variables: x
Verify that conversion is being properly cached::
sage: k = Frac(QQ['x,z']) # optional - magma sage: magma(k) is magma(k) # optional - magma True """ s = 'FieldOfFractions(%s)' % self.ring()._magma_init_(magma) return magma._with_names(s, self.variable_names())
def ring(self): """ Return the ring that this is the fraction field of.
EXAMPLES::
sage: R = Frac(QQ['x,y']) sage: R Fraction Field of Multivariate Polynomial Ring in x, y over Rational Field sage: R.ring() Multivariate Polynomial Ring in x, y over Rational Field """
@cached_method def is_exact(self): """ Return if ``self`` is exact which is if the underlying ring is exact.
EXAMPLES::
sage: Frac(ZZ['x']).is_exact() True sage: Frac(CDF['x']).is_exact() False """
def _element_constructor_(self, x, y=None, coerce=True): """ Construct an element of this fraction field.
EXAMPLES::
sage: F = QQ['x,y'].fraction_field() sage: F._element_constructor_(1) 1 sage: F._element_constructor_(F.gen(0)/F.gen(1)) x/y sage: F._element_constructor_('1 + x/y') (x + y)/y
::
sage: K = ZZ['x,y'].fraction_field() sage: x,y = K.gens()
::
sage: F._element_constructor_(x/y) x/y
TESTS:
The next example failed before :trac:`4376`::
sage: K(pari((x + 1)/(x^2 + x + 1))) (x + 1)/(x^2 + x + 1)
These examples failed before :trac:`11368`::
sage: R.<x, y, z> = PolynomialRing(QQ) sage: S = R.fraction_field() sage: S(pari((x + y)/y)) (x + y)/y
sage: S(pari(x + y + 1/z)) (x*z + y*z + 1)/z
This example failed before :trac:`23664`::
sage: P0.<x> = ZZ[] sage: P1.<y> = Frac(P0)[] sage: frac = (x/(x^2 + 1))*y + 1/(x^3 + 1) sage: Frac(ZZ['x,y'])(frac) (x^4*y + x^2 + x*y + 1)/(x^5 + x^3 + x^2 + 1)
Test conversions where `y` is a string but `x` not::
sage: K = ZZ['x,y'].fraction_field() sage: K._element_constructor_(2, 'x+y') 2/(x + y) sage: K._element_constructor_(1, 'z') Traceback (most recent call last): ... TypeError: unable to evaluate 'z' in Fraction Field of Multivariate Polynomial Ring in x, y over Integer Ring
Check that :trac:`17971` is fixed::
sage: A.<a,c> = Frac(PolynomialRing(QQ,'a,c')) sage: B.<d,e> = PolynomialRing(A,'d,e') sage: R.<x> = PolynomialRing(B,'x') sage: (a*d*x^2+a+e+1).resultant(-4*c^2*x+1) a*d + 16*c^4*e + 16*a*c^4 + 16*c^4
Check that :trac:`24539` is fixed::
sage: tau = polygen(QQ, 'tau') sage: R = PolynomialRing(CyclotomicField(2), 'z').fraction_field()( ....: tau/(1+tau)) Traceback (most recent call last): ... TypeError: cannot convert tau/(tau + 1)/1 to an element of Fraction Field of Univariate Polynomial Ring in z over Cyclotomic Field of order 2 and degree 1 """ else:
# This recursive approach is needed because PARI # represents multivariate polynomials as iterated # univariate polynomials (see the above examples). # Below, v is the variable with highest priority, # and the x[i] are rational functions in the # remaining variables.
x0, y0, self))
def construction(self): """ EXAMPLES::
sage: Frac(ZZ['x']).construction() (FractionField, Univariate Polynomial Ring in x over Integer Ring) sage: K = Frac(GF(3)['t']) sage: f, R = K.construction() sage: f(R) Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 3 sage: f(R) == K True """
def __eq__(self, other): """ Check whether ``self`` is equal to ``other``.
EXAMPLES::
sage: Frac(ZZ['x']) == Frac(ZZ['x']) True sage: Frac(ZZ['x']) == Frac(QQ['x']) False sage: Frac(ZZ['x']) == Frac(ZZ['y']) False sage: Frac(ZZ['x']) == QQ['x'] False """
def __ne__(self, other): """ Check whether ``self`` is not equal to ``other``.
EXAMPLES::
sage: Frac(ZZ['x']) != Frac(ZZ['x']) False sage: Frac(ZZ['x']) != Frac(QQ['x']) True sage: Frac(ZZ['x']) != Frac(ZZ['y']) True sage: Frac(ZZ['x']) != QQ['x'] True """
def ngens(self): """ This is the same as for the parent object.
EXAMPLES::
sage: R = Frac(PolynomialRing(QQ,'z',10)); R Fraction Field of Multivariate Polynomial Ring in z0, z1, z2, z3, z4, z5, z6, z7, z8, z9 over Rational Field sage: R.ngens() 10 """
def gen(self, i=0): """ Return the ``i``-th generator of ``self``.
EXAMPLES::
sage: R = Frac(PolynomialRing(QQ,'z',10)); R Fraction Field of Multivariate Polynomial Ring in z0, z1, z2, z3, z4, z5, z6, z7, z8, z9 over Rational Field sage: R.0 z0 sage: R.gen(3) z3 sage: R.3 z3 """
def _is_valid_homomorphism_(self, codomain, im_gens): """ Check if the homomorphism defined by sending generators of this fraction field to ``im_gens`` in ``codomain`` is valid.
EXAMPLES::
sage: F = QQ['x,y'].fraction_field() sage: x,y = F.gens() sage: F._is_valid_homomorphism_(F, [y,x]) True sage: R = ZZ['x']; x = R.gen() sage: F._is_valid_homomorphism_(R, [x, x]) False
TESTS::
sage: F._is_valid_homomorphism_(ZZ, []) False
Test homomorphisms::
sage: phi = F.hom([2*y, x]) sage: phi(x+y) x + 2*y sage: phi(x/y) 2*y/x """ # it is enough to check if elements of the base ring coerce to # the codomain
def random_element(self, *args, **kwds): """ Return a random element in this fraction field.
The arguments are passed to the random generator of the underlying ring.
EXAMPLES::
sage: F = ZZ['x'].fraction_field() sage: F.random_element() # random (2*x - 8)/(-x^2 + x)
::
sage: f = F.random_element(degree=5) sage: f.numerator().degree() 5 sage: f.denominator().degree() 5 """ self._R._random_nonzero_element(*args, **kwds), coerce=False, reduce=True)
def some_elements(self): r""" Return some elements in this field.
EXAMPLES::
sage: R.<x> = QQ[] sage: R.fraction_field().some_elements() [0, 1, x, 2*x, x/(x^2 + 2*x + 1), 1/x^2, ... (2*x^2 + 2)/(x^2 + 2*x + 1), (2*x^2 + 2)/x^3, (2*x^2 + 2)/(x^2 - 1), 2]
"""
class FractionField_1poly_field(FractionField_generic): """ The fraction field of a univariate polynomial ring over a field.
Many of the functions here are included for coherence with number fields. """ def __init__(self, R, element_class=fraction_field_element.FractionFieldElement_1poly_field): """ Just change the default for ``element_class``.
EXAMPLES::
sage: R.<t> = QQ[]; K = R.fraction_field() sage: K._element_class <class 'sage.rings.fraction_field_element.FractionFieldElement_1poly_field'> """
def ring_of_integers(self): """ Return the ring of integers in this fraction field.
EXAMPLES::
sage: K = FractionField(GF(5)['t']) sage: K.ring_of_integers() Univariate Polynomial Ring in t over Finite Field of size 5 """
def maximal_order(self): """ Return the maximal order in this fraction field.
EXAMPLES::
sage: K = FractionField(GF(5)['t']) sage: K.maximal_order() Univariate Polynomial Ring in t over Finite Field of size 5 """
def class_number(self): """ Here for compatibility with number fields and function fields.
EXAMPLES::
sage: R.<t> = GF(5)[]; K = R.fraction_field() sage: K.class_number() 1 """
def _factor_univariate_polynomial(self, f): r""" Return the factorization of ``f`` over this field.
EXAMPLES::
sage: k.<a> = GF(9) sage: K = k['t'].fraction_field() sage: R.<x> = K[] sage: f = x^3 + a sage: f.factor() (x + 2*a + 1)^3
""" # The default implementation would try to convert this element to singular and factor there. # This fails silently over some base fields, see #23642, so we convert # to the function field and factor there.
def function_field(self): r""" Return the isomorphic function field.
EXAMPLES::
sage: R.<t> = GF(5)[] sage: K = R.fraction_field() sage: K.function_field() Rational function field in t over Finite Field of size 5
.. SEEALSO::
:meth:`sage.rings.function_field.RationalFunctionField.field`
"""
def _coerce_map_from_(self, R): r""" Return a coerce map from ``R`` to this field.
EXAMPLES::
sage: R.<t> = GF(5)[] sage: K = R.fraction_field() sage: L = K.function_field() sage: f = K.coerce_map_from(L); f # indirect doctest Isomorphism morphism: From: Rational function field in t over Finite Field of size 5 To: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 sage: f(~L.gen()) 1/t
"""
class FractionFieldEmbedding(DefaultConvertMap_unique): r""" The embedding of an integral domain into its field of fractions.
EXAMPLES::
sage: R.<x> = QQ[] sage: f = R.fraction_field().coerce_map_from(R); f Coercion map: From: Univariate Polynomial Ring in x over Rational Field To: Fraction Field of Univariate Polynomial Ring in x over Rational Field
TESTS::
sage: from sage.rings.fraction_field import FractionFieldEmbedding sage: isinstance(f, FractionFieldEmbedding) True sage: TestSuite(f).run()
Check that :trac:`23185` has been resolved::
sage: R.<x> = QQ[] sage: K.<x> = FunctionField(QQ) sage: R.is_subring(K) True sage: R.is_subring(R.fraction_field()) True
""" def is_surjective(self): r""" Return whether this map is surjective.
EXAMPLES::
sage: R.<x> = QQ[] sage: R.fraction_field().coerce_map_from(R).is_surjective() False
"""
def is_injective(self): r""" Return whether this map is injective.
EXAMPLES:
The map from an integral domain to its fraction field is always injective:
sage: R.<x> = QQ[] sage: R.fraction_field().coerce_map_from(R).is_injective() True
"""
def section(self): r""" Return a section of this map.
EXAMPLES::
sage: R.<x> = QQ[] sage: R.fraction_field().coerce_map_from(R).section() Section map: From: Fraction Field of Univariate Polynomial Ring in x over Rational Field To: Univariate Polynomial Ring in x over Rational Field
"""
def _richcmp_(self, other, op): r""" Compare this element to ``other`` with respect to ``op``.
EXAMPLES::
sage: R.<x> = QQ[] sage: f = R.fraction_field().coerce_map_from(R) sage: S.<y> = GF(2)[] sage: g = S.fraction_field().coerce_map_from(S)
sage: f == g # indirect doctest False sage: f == f True
""" return NotImplemented
def __hash__(self): r""" Return a hash value for this embedding.
EXAMPLES::
sage: R.<x> = QQ[] sage: hash(R.fraction_field().coerce_map_from(R)) == hash(R.fraction_field().coerce_map_from(R)) True
"""
class FractionFieldEmbeddingSection(Section): r""" The section of the embedding of an integral domain into its field of fractions.
EXAMPLES::
sage: R.<x> = QQ[] sage: f = R.fraction_field().coerce_map_from(R).section(); f Section map: From: Fraction Field of Univariate Polynomial Ring in x over Rational Field To: Univariate Polynomial Ring in x over Rational Field
TESTS::
sage: from sage.rings.fraction_field import FractionFieldEmbeddingSection sage: isinstance(f, FractionFieldEmbeddingSection) True sage: TestSuite(f).run()
""" def _call_(self, x, check=True): r""" Evaluate this map at ``x``.
EXAMPLES::
sage: R.<x> = QQ[] sage: K = R.fraction_field() sage: x = K.gen() sage: f = K.coerce_map_from(R).section() sage: f(x) x sage: f(1/x) Traceback (most recent call last): ... TypeError: fraction must have unit denominator
TESTS:
Over inexact rings, we have to take the precision of the denominators into account::
sage: R=ZpCR(2) sage: S.<x> = R[] sage: f = x/S(R(3,absprec=2)) sage: S(f) (1 + 2 + O(2^2))*x
""" # This should probably be a ValueError. # However, too much existing code is expecting this to throw a # TypeError, so we decided to keep it for the time being.
def _call_with_args(self, x, args=(), kwds={}): r""" Evaluation this map at ``x``.
INPUT:
- ``check`` -- whether or not to check
EXAMPLES::
sage: R.<x> = QQ[] sage: K = R.fraction_field() sage: R(K.gen(), check=True) x
""" raise NotImplementedError("__call__ can not be called with additional arguments other than check=True/False")
def _richcmp_(self, other, op): r""" Compare this element to ``other`` with respect to ``op``.
EXAMPLES::
sage: R.<x> = QQ[] sage: f = R.fraction_field().coerce_map_from(R).section() sage: S.<y> = GF(2)[] sage: g = S.fraction_field().coerce_map_from(S).section()
sage: f == g # indirect doctest False sage: f == f True
""" return NotImplemented
def __hash__(self): r""" Return a hash value for this section.
EXAMPLES::
sage: R.<x> = QQ[] sage: hash(R.fraction_field().coerce_map_from(R).section()) == hash(R.fraction_field().coerce_map_from(R).section()) True
""" |