Path: blob/master/sage/rings/function_field/function_field.py
4036 views
r"""1Function Fields23AUTHORS:45- William Stein (2010): initial version67- Robert Bradshaw (2010-05-30): added is_finite()89- Julian Rueth (2011-06-08): fixed hom(), extension()1011- Maarten Derickx (2011-09-11): added doctests1213- Julian Rueth (2011-09-14): use @cached_method1415EXAMPLES:1617We create an extension of a rational function fields, and do some18simple arithmetic in it::1920sage: K.<x> = FunctionField(GF(5^2,'a')); K21Rational function field in x over Finite Field in a of size 5^222sage: R.<y> = K[]23sage: L.<y> = K.extension(y^3 - (x^3 + 2*x*y + 1/x)); L24Function field in y defined by y^3 + 3*x*y + (4*x^4 + 4)/x25sage: y^226y^227sage: y^3282*x*y + (x^4 + 1)/x29sage: a = 1/y; a30(4*x/(4*x^4 + 4))*y^2 + 2*x^2/(4*x^4 + 4)31sage: a * y3213334We next make an extension of the above function field, illustrating35that arithmetic with a tower of 3 fields is fully supported::3637sage: S.<t> = L[]38sage: M.<t> = L.extension(t^2 - x*y)39sage: M40Function field in t defined by t^2 + 4*x*y41sage: t^242x*y43sage: 1/t44((1/(x^4 + 1))*y^2 + 2*x/(4*x^4 + 4))*t45sage: M.base_field()46Function field in y defined by y^3 + 3*x*y + (4*x^4 + 4)/x47sage: M.base_field().base_field()48Rational function field in x over Finite Field in a of size 5^24950TESTS::5152sage: TestSuite(K).run()53sage: TestSuite(L).run() # long time (8s on sage.math, 2012)54sage: TestSuite(M).run() # long time (52s on sage.math, 2012)5556The following two test suites do not pass ``_test_elements`` yet since57``R.an_element()`` has a ``_test_category`` method wich it should not have.58It is not the fault of the function field code so this will59be fixed in another ticket::6061sage: TestSuite(R).run(skip = '_test_elements')62sage: TestSuite(S).run(skip = '_test_elements')63"""64#*****************************************************************************65# Copyright (C) 2010 William Stein <[email protected]>66# Copyright (C) 2010 Robert Bradshaw <[email protected]>67# Copyright (C) 2011 Julian Rueth <[email protected]>68# Copyright (C) 2011 Maarten Derickx <[email protected]>69#70# Distributed under the terms of the GNU General Public License (GPL)71# as published by the Free Software Foundation; either version 2 of72# the License, or (at your option) any later version.73# http://www.gnu.org/licenses/74#*****************************************************************************7576from sage.rings.ring import Field77from function_field_element import FunctionFieldElement, FunctionFieldElement_rational, FunctionFieldElement_polymod7879from sage.misc.cachefunc import cached_method8081from sage.categories.function_fields import FunctionFields82CAT = FunctionFields()8384def is_FunctionField(x):85"""86Return True if ``x`` is of function field type.8788EXAMPLES::8990sage: from sage.rings.function_field.function_field import is_FunctionField91sage: is_FunctionField(QQ)92False93sage: is_FunctionField(FunctionField(QQ,'t'))94True95"""96if isinstance(x, FunctionField): return True97return x in FunctionFields()9899class FunctionField(Field):100"""101The abstract base class for all function fields.102103EXAMPLES::104105sage: K.<x> = FunctionField(QQ)106sage: isinstance(K, sage.rings.function_field.function_field.FunctionField)107True108"""109def some_elements(self):110"""111Return a list of elements in the function field.112113EXAMPLES::114115sage: K.<x> = FunctionField(QQ)116sage: elements = K.some_elements()117sage: elements # random output118[(x - 3/2)/(x^2 - 12/5*x + 1/18)]119sage: False in [e in K for e in elements]120False121"""122return [self.random_element(), self.random_element(), self.random_element()]123124def characteristic(self):125"""126Return the characteristic of this function field.127128EXAMPLES::129130sage: K.<x> = FunctionField(QQ)131sage: K.characteristic()1320133sage: K.<x> = FunctionField(GF(7))134sage: K.characteristic()1357136sage: R.<y> = K[]137sage: L.<y> = K.extension(y^2-x)138sage: L.characteristic()1397140"""141return self.constant_base_field().characteristic()142143def is_finite(self):144"""145Return whether this function field is finite, which it is not.146147EXAMPLES::148149sage: R.<t> = FunctionField(QQ)150sage: R.is_finite()151False152sage: R.<t> = FunctionField(GF(7))153sage: R.is_finite()154False155"""156return False157158def extension(self, f, names=None):159"""160Create an extension L = K[y]/(f(y)) of a function field,161defined by a univariate polynomial in one variable over this162function field K.163164INPUT:165166- ``f`` -- a univariate polynomial over self167- ``names`` -- None or string or length-1 tuple168169OUTPUT:170171- a function field172173EXAMPLES::174175sage: K.<x> = FunctionField(QQ); R.<y> = K[]176sage: K.extension(y^5 - x^3 - 3*x + x*y)177Function field in y defined by y^5 + x*y - x^3 - 3*x178179A nonintegral defining polynomial::180181sage: K.<t> = FunctionField(QQ); R.<y> = K[]182sage: K.extension(y^3 + (1/t)*y + t^3/(t+1))183Function field in y defined by y^3 + 1/t*y + t^3/(t + 1)184185The defining polynomial need not be monic or integral::186187sage: K.extension(t*y^3 + (1/t)*y + t^3/(t+1))188Function field in y defined by t*y^3 + 1/t*y + t^3/(t + 1)189"""190from constructor import FunctionField_polymod as FunctionField_polymod_Constructor191return FunctionField_polymod_Constructor(f, names)192193def order_with_basis(self, basis, check=True):194"""195Return the order with given basis over the maximal order of196the base field.197198INPUT:199200- ``basis`` -- a list of elements of self201- ``check`` -- bool (default: True); if True, check that202the basis is really linearly independent and that the203module it spans is closed under multiplication, and204contains the identity element.205206OUTPUT:207208- an order in this function field209210EXAMPLES::211212sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<y> = K.extension(y^3 + x^3 + 4*x + 1)213sage: O = L.order_with_basis([1, y, y^2]); O214Order in Function field in y defined by y^3 + x^3 + 4*x + 1215sage: O.basis()216(1, y, y^2)217218Note that 1 does not need to be an element of the basis, as long it is in the module spanned by it::219220sage: O = L.order_with_basis([1+y, y, y^2]); O221Order in Function field in y defined by y^3 + x^3 + 4*x + 1222sage: O.basis()223(y + 1, y, y^2)224225The following error is raised when the module spanned by the basis is not closed under multiplication::226227sage: O = L.order_with_basis([1, x^2 + x*y, (2/3)*y^2]); O228Traceback (most recent call last):229...230ValueError: The module generated by basis [1, x*y + x^2, 2/3*y^2] must be closed under multiplication231232and this happens when the identity is not in the module spanned by the basis::233234sage: O = L.order_with_basis([x, x^2 + x*y, (2/3)*y^2])235Traceback (most recent call last):236...237ValueError: The identity element must be in the module spanned by basis [x, x*y + x^2, 2/3*y^2]238"""239from function_field_order import FunctionFieldOrder_basis240return FunctionFieldOrder_basis([self(a) for a in basis], check=check)241242def order(self, x, check=True):243"""244Return the order in this function field generated over the245maximal order by x or the elements of x if x is a list.246247INPUT:248249- ``x`` -- element of self, or a list of elements of self250- ``check`` -- bool (default: True); if True, check that251x really generates an order252253EXAMPLES::254255sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<y> = K.extension(y^3 + x^3 + 4*x + 1)256sage: O = L.order(y); O257Order in Function field in y defined by y^3 + x^3 + 4*x + 1258sage: O.basis()259(1, y, y^2)260261sage: Z = K.order(x); Z262Order in Rational function field in x over Rational Field263sage: Z.basis()264(1,)265266Orders with multiple generators, not yet supported::267268sage: Z = K.order([x,x^2]); Z269Traceback (most recent call last):270...271NotImplementedError272"""273if not isinstance(x, (list, tuple)):274x = [x]275if len(x) == 1:276g = x[0]277basis = [self(1)]278for i in range(self.degree()-1):279basis.append(basis[-1]*g)280else:281raise NotImplementedError282return self.order_with_basis(basis, check=check)283284def _coerce_map_from_(self, R):285"""286Return True if there is a coerce map from R to self.287288EXAMPLES::289290sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<y> = K.extension(y^3 + x^3 + 4*x + 1)291sage: L.equation_order()292Order in Function field in y defined by y^3 + x^3 + 4*x + 1293sage: L._coerce_map_from_(L.equation_order())294True295sage: L._coerce_map_from_(GF(7))296False297"""298from function_field_order import FunctionFieldOrder299if isinstance(R, FunctionFieldOrder) and R.fraction_field() == self:300return True301return False302303class FunctionField_polymod(FunctionField):304"""305A function field defined by a univariate polynomial, as an306extension of the base field.307308EXAMPLES:309310We make a function field defined by a degree 5 polynomial over the311rational function field over the rational numbers::312313sage: K.<x> = FunctionField(QQ)314sage: R.<y> = K[]315sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L316Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x317318We next make a function field over the above nontrivial function319field L::320321sage: S.<z> = L[]322sage: M.<z> = L.extension(z^2 + y*z + y); M323Function field in z defined by z^2 + y*z + y324sage: 1/z325((x/(-x^4 - 1))*y^4 - 2*x^2/(-x^4 - 1))*z - 1326sage: z * (1/z)3271328329We drill down the tower of function fields::330331sage: M.base_field()332Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x333sage: M.base_field().base_field()334Rational function field in x over Rational Field335sage: M.base_field().base_field().constant_field()336Rational Field337sage: M.constant_base_field()338Rational Field339340.. WARNING::341342It is not checked if the polynomial used to define this function field is irreducible343Hence it is not guaranteed that this object really is a field!344This is illustrated below.345346::347348sage: K.<x>=FunctionField(QQ)349sage: R.<y> = K[]350sage: L.<y>=K.extension(x^2-y^2)351sage: (y-x)*(y+x)3520353sage: 1/(y-x)3541355sage: y-x==0; y+x==0356False357False358"""359def __init__(self, polynomial, names,360element_class = FunctionFieldElement_polymod,361category=CAT):362"""363Create a function field defined as an extension of another364function field by adjoining a root of a univariate polynomial.365366INPUT:367368- ``polynomial`` -- a univariate polynomial over a function field369- ``names`` -- variable names (as a tuple of length 1 or string)370- ``category`` -- a category (defaults to category of function fields)371372EXAMPLES::373374We create an extension of a function field::375376sage: K.<x> = FunctionField(QQ); R.<y> = K[]377sage: L = K.extension(y^5 - x^3 - 3*x + x*y); L378Function field in y defined by y^5 + x*y - x^3 - 3*x379380Note the type::381382sage: type(L)383<class 'sage.rings.function_field.function_field.FunctionField_polymod_with_category'>384385We can set the variable name, which doesn't have to be y::386387sage: L.<w> = K.extension(y^5 - x^3 - 3*x + x*y); L388Function field in w defined by y^5 + x*y - x^3 - 3*x389"""390from sage.rings.polynomial.all import is_Polynomial391if polynomial.parent().ngens()>1 or not is_Polynomial(polynomial):392raise TypeError, "polynomial must be univariate a polynomial"393if names is None:394names = (polynomial.variable_name(), )395if polynomial.degree() <= 0:396raise ValueError, "polynomial must have positive degree"397base_field = polynomial.base_ring()398if not isinstance(base_field, FunctionField):399raise TypeError, "polynomial must be over a FunctionField"400self._element_class = element_class401self._element_init_pass_parent = False402self._base_field = base_field403self._polynomial = polynomial404405Field.__init__(self, base_field,406names=names, category = category)407408self._hash = hash(polynomial)409self._ring = self._polynomial.parent()410self._populate_coercion_lists_(coerce_list=[base_field, self._ring])411self._gen = self(self._ring.gen())412413def __reduce__(self):414"""415Returns the arguments which were used to create this instance. The rationale for this is explained in the documentation of ``UniqueRepresentation``.416417EXAMPLES::418419sage: K.<x> = FunctionField(QQ); R.<y> = K[]420sage: L = K.extension(y^2-x)421sage: clazz,args = L.__reduce__()422sage: clazz(*args)423Function field in y defined by y^2 - x424"""425from constructor import FunctionField_polymod as FunctionField_polymod_Constructor426return FunctionField_polymod_Constructor, (self._polynomial, self._names)427428def __hash__(self):429"""430Return hash of this function field.431432EXAMPLES::433434sage: K.<x> = FunctionField(QQ); R.<y> = K[]435sage: L = K.extension(y^5 - x^3 - 3*x + x*y); hash(L)4363183366741743088279 # 64-bit4372003022487 # 32-bit438"""439return self._hash440441def monic_integral_model(self, names):442"""443Return a function field isomorphic to self, but with defining444polynomial that is monic and integral over the base field.445446INPUT:447448- ``names`` -- name of the generator of the new field this function constructs449450EXAMPLES::451452sage: K.<x> = FunctionField(QQ); R.<y> = K[]453sage: L.<y> = K.extension(x^2*y^5 - 1/x); L454Function field in y defined by x^2*y^5 - 1/x455sage: A, from_A, to_A = L.monic_integral_model('z')456sage: A457Function field in z defined by y^5 - x^12458sage: from_A459Morphism of function fields defined by z |--> x^3*y460sage: to_A461Morphism of function fields defined by y |--> 1/x^3*z462sage: to_A(y)4631/x^3*z464sage: from_A(to_A(y))465y466sage: from_A(to_A(1/y))467x^3*y^4468sage: from_A(to_A(1/y)) == 1/y469True470"""471g, d = self._make_monic_integral(self.polynomial())472R = self.base_field()473K = R.extension(g, names=names)474to_K = self.hom(K.gen() / d)475from_K = K.hom(self.gen() * d)476return K, from_K, to_K477478def _make_monic_integral(self, f):479r"""480Let y be a root of ``f``. This function returns a monic481integral polynomial g and an element d of the base field such482that g(y*d)=0.483484EXAMPLES::485486sage: K.<x> = FunctionField(QQ); R.<y> = K[];487sage: L.<y> = K.extension(x^2*y^5 - 1/x)488sage: g, d = L._make_monic_integral(L.polynomial()); g,d489(y^5 - x^12, x^3)490sage: (y*d).is_integral()491True492sage: g.is_monic()493True494sage: g(y*d)4950496"""497R = f.base_ring()498if not isinstance(R, RationalFunctionField):499raise NotImplementedError500501# make f monic502n = f.degree()503c = f.leading_coefficient()504if c != 1:505f = f / c506507# find lcm of denominators508from sage.rings.arith import lcm509# would be good to replace this by minimal...510d = lcm([b.denominator() for b in f.list() if b])511if d != 1:512x = f.parent().gen()513g = (d**n) * f(x/d)514else:515g = f516return g, d517518def constant_field(self):519"""520Return the algebraic closure of the constant field of the base521field in this function field.522523EXAMPLES::524525sage: K.<x> = FunctionField(QQ); R.<y> = K[]526sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))527sage: L.constant_field()528Traceback (most recent call last):529...530NotImplementedError531"""532raise NotImplementedError533534def constant_base_field(self):535"""536Return the constant field of the base rational function field.537538EXAMPLES::539540sage: K.<x> = FunctionField(QQ); R.<y> = K[]541sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L542Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x543sage: L.constant_base_field()544Rational Field545sage: S.<z> = L[]546sage: M.<z> = L.extension(z^2 - y)547sage: M.constant_base_field()548Rational Field549"""550return self.base_field().constant_base_field()551552def degree(self):553"""554Return the degree of this function field over its base555function field.556557EXAMPLES::558559sage: K.<x> = FunctionField(QQ)560sage: R.<y> = K[]561sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L562Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x563sage: L.degree()5645565"""566return self._polynomial.degree()567568def _repr_(self):569"""570Return string representation of this function field.571572EXAMPLES::573574sage: K.<x> = FunctionField(QQ); R.<y> = K[]575sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))576sage: L._repr_()577'Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x'578"""579return "Function field in %s defined by %s"%(self.variable_name(), self._polynomial)580581def base_field(self):582"""583Return the base field of this function field. This function584field is presented as L = K[y]/(f(y)), and the base field is585by definition the field K.586587EXAMPLES::588589sage: K.<x> = FunctionField(QQ); R.<y> = K[]590sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))591sage: L.base_field()592Rational function field in x over Rational Field593"""594return self._base_field595596def random_element(self, *args, **kwds):597"""598Create a random element of this function field. Parameters599are passed onto the random_element method of the base_field.600601EXAMPLES::602603sage: K.<x> = FunctionField(QQ); R.<y> = K[]604sage: L.<y> = K.extension(y^2 - (x^2 + x))605sage: L.random_element() # random606((x^2 - x + 2/3)/(x^2 + 1/3*x - 1))*y^2 + ((-1/4*x^2 + 1/2*x - 1)/(-5/2*x + 2/3))*y + (-1/2*x^2 - 4)/(-12*x^2 + 1/2*x - 1/95)607"""608return self(self._ring.random_element(degree=self.degree(), *args, **kwds))609610def polynomial(self):611"""612Return the univariate polynomial that defines this function613field, i.e., the polynomial f(y) so that this function field614is of the form K[y]/(f(y)).615616EXAMPLES::617618sage: K.<x> = FunctionField(QQ); R.<y> = K[]619sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))620sage: L.polynomial()621y^5 - 2*x*y + (-x^4 - 1)/x622"""623return self._polynomial624625def polynomial_ring(self):626"""627Return the polynomial ring used to represent elements of this628function field. If we view this function field as being presented629as K[y]/(f(y)), then this function returns the ring K[y].630631EXAMPLES::632633sage: K.<x> = FunctionField(QQ); R.<y> = K[]634sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))635sage: L.polynomial_ring()636Univariate Polynomial Ring in y over Rational function field in x over Rational Field637"""638return self._ring639640@cached_method641def vector_space(self):642"""643Return a vector space V and isomorphisms self --> V and V --> self.644645This function allows us to identify the elements of self with646elements of a vector space over the base field, which is647useful for representation and arithmetic with orders, ideals,648etc.649650OUTPUT:651652- ``V`` -- a vector space over base field653- ``from_V`` -- an isomorphism from V to self654- ``to_V`` -- an isomorphism from self to V655656EXAMPLES:657658We define a function field::659660sage: K.<x> = FunctionField(QQ); R.<y> = K[]661sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L662Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x663664We get the vector spaces, and maps back and forth::665666sage: V, from_V, to_V = L.vector_space()667sage: V668Vector space of dimension 5 over Rational function field in x over Rational Field669sage: from_V670Isomorphism morphism:671From: Vector space of dimension 5 over Rational function field in x over Rational Field672To: Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x673sage: to_V674Isomorphism morphism:675From: Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x676To: Vector space of dimension 5 over Rational function field in x over Rational Field677678We convert an element of the vector space back to the function field::679680sage: from_V(V.1)681y682683We define an interesting element of the function field::684685sage: a = 1/L.0; a686(-x/(-x^4 - 1))*y^4 + 2*x^2/(-x^4 - 1)687688We convert it to the vector space, and get a vector over the base field::689690sage: to_V(a)691(2*x^2/(-x^4 - 1), 0, 0, 0, -x/(-x^4 - 1))692693We convert to and back, and get the same element::694695sage: from_V(to_V(a)) == a696True697698In the other direction::699700sage: v = x*V.0 + (1/x)*V.1701sage: to_V(from_V(v)) == v702True703704And we show how it works over an extension of an extension field::705706sage: R2.<z> = L[]; M.<z> = L.extension(z^2 -y)707sage: M.vector_space()708(Vector space of dimension 2 over Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x, Isomorphism morphism:709From: Vector space of dimension 2 over Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x710To: Function field in z defined by z^2 - y, Isomorphism morphism:711From: Function field in z defined by z^2 - y712To: Vector space of dimension 2 over Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x)713"""714V = self.base_field()**self.degree()715from maps import MapVectorSpaceToFunctionField, MapFunctionFieldToVectorSpace716from_V = MapVectorSpaceToFunctionField(V, self)717to_V = MapFunctionFieldToVectorSpace(self, V)718return (V, from_V, to_V)719720def maximal_order(self):721"""722Return the maximal_order of self. If we view self as L =723K[y]/(f(y)), then this is the ring of elements of L that are724integral over K.725726EXAMPLES:727728This is not yet implemented...::729730sage: K.<x> = FunctionField(QQ); R.<y> = K[]731sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))732sage: L.maximal_order()733Traceback (most recent call last):734...735NotImplementedError736"""737raise NotImplementedError738739def _element_constructor_(self, x):740r"""741Make ``x`` into an element of this function field, possibly not canonically.742743INPUT:744745- ``x`` -- the element746747OUTPUT:748749``x``, as an element of this function field750751TESTS::752753sage: K.<x> = FunctionField(QQ); R.<y> = K[]754sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))755sage: L._element_constructor_(L.polynomial_ring().gen())756y757"""758if x.parent() is self._ring:759return FunctionFieldElement_polymod(self, x)760if isinstance(x, FunctionFieldElement):761return FunctionFieldElement_polymod(self, self._ring(x.element()))762return FunctionFieldElement_polymod(self, self._ring(x))763764def gen(self, n=0):765"""766Return the ``n``-th generator of this function field. By default ``n`` is 0; any other767value of ``n`` leads to an error. The generator is the class of y, if we view768self as being presented as K[y]/(f(y)).769770EXAMPLES::771772sage: K.<x> = FunctionField(QQ); R.<y> = K[]773sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))774sage: L.gen()775y776sage: L.gen(1)777Traceback (most recent call last):778...779IndexError: Only one generator.780"""781if n != 0: raise IndexError, "Only one generator."782return self._gen783784def ngens(self):785"""786Return the number of generators of this function field over787its base field. This is by definition 1.788789EXAMPLES::790791sage: K.<x> = FunctionField(QQ); R.<y> = K[]792sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))793sage: L.ngens()7941795"""796return 1797798def equation_order(self):799"""800If we view self as being presented as K[y]/(f(y)), then this801function returns the order generated by the class of y. If f802is not monic, then :meth:`_make_monic_integral` is called, and instead we803get the order generated by some integral multiple of a root of f.804805EXAMPLES::806807sage: K.<x> = FunctionField(QQ); R.<y> = K[]808sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))809sage: O = L.equation_order()810sage: O.basis()811(1, x*y, x^2*y^2, x^3*y^3, x^4*y^4)812813We try an example, in which the defining polynomial is not814monic and is not integral::815816sage: K.<x> = FunctionField(QQ); R.<y> = K[]817sage: L.<y> = K.extension(x^2*y^5 - 1/x); L818Function field in y defined by x^2*y^5 - 1/x819sage: O = L.equation_order()820sage: O.basis()821(1, x^3*y, x^6*y^2, x^9*y^3, x^12*y^4)822"""823d = self._make_monic_integral(self.polynomial())[1]824return self.order(d*self.gen(), check=False)825826def hom(self, im_gens, base_morphism=None):827"""828Create a homomorphism from self to another function field.829830INPUT:831832- ``im_gens`` -- a list of images of the generators of self833and of successive base rings.834835- ``base_morphism`` -- (default: None) a homomorphism of836the base ring, after the im_gens are used. Thus if837im_gens has length 2, then base_morphism should be a morphism838from self.base_ring().base_ring().839840EXAMPLES:841842We create a rational function field, and a quadratic extension of it::843844sage: K.<x> = FunctionField(QQ); R.<y> = K[]845sage: L.<y> = K.extension(y^2 - x^3 - 1)846847We make the field automorphism that sends y to -y::848849sage: f = L.hom(-y); f850Morphism of function fields defined by y |--> -y851852Evaluation works::853854sage: f(y*x - 1/x)855-x*y - 1/x856857We try to define an invalid morphism::858859sage: f = L.hom(y+1)860Traceback (most recent call last):861...862ValueError: invalid morphism863864We make a morphism of the base rational function field::865866sage: phi = K.hom(x+1); phi867Morphism of function fields defined by x |--> x + 1868sage: phi(x^3 - 3)869x^3 + 3*x^2 + 3*x - 2870sage: (x+1)^3-3871x^3 + 3*x^2 + 3*x - 2872873We make a morphism by specifying where the generators and the874base generators go::875876sage: L.hom([-y, x])877Morphism of function fields defined by y |--> -y, x |--> x878879The usage of the keyword base_morphism is not implemented yet::880881sage: L.hom([-y, x-1], base_morphism=phi)882Traceback (most recent call last):883...884NotImplementedError: Function field homorphisms with optional argument base_morphism are not implemented yet. Please specify the images of the generators of the base fields manually.885886We make another extension of a rational function field::887888sage: K2.<t> = FunctionField(QQ); R2.<w> = K2[]889sage: L2.<w> = K2.extension((4*w)^2 - (t+1)^3 - 1)890891We define a morphism, by giving the images of generators::892893sage: f = L.hom([4*w, t+1]); f894Morphism of function fields defined by y |--> 4*w, x |--> t + 1895896Evaluation works, as expected::897898sage: f(y+x)8994*w + t + 1900sage: f(x*y + x/(x^2+1))901(4*t + 4)*w + (t + 1)/(t^2 + 2*t + 2)902903We make another extension of a rational function field::904905sage: K3.<yy> = FunctionField(QQ); R3.<xx> = K3[]906sage: L3.<xx> = K3.extension(yy^2 - xx^3 - 1)907908This is the function field L with the generators exchanged. We define a morphism to L::909910sage: g = L3.hom([x,y]); g911Morphism of function fields defined by xx |--> x, yy |--> y912"""913if base_morphism is not None:914raise NotImplementedError, "Function field homorphisms with optional argument base_morphism are not implemented yet. Please specify the images of the generators of the base fields manually."915916if not isinstance(im_gens, (list,tuple)):917im_gens = [im_gens]918if len(im_gens) == 0:919raise ValueError, "no images specified"920921if len(im_gens) > 1:922base_morphism = self.base_field().hom(im_gens[1:], base_morphism)923924# the codomain of this morphism is the field containing all the im_gens925codomain = im_gens[0].parent();926if base_morphism is not None:927if base_morphism.codomain().has_coerce_map_from(codomain):928codomain = base_morphism.codomain();929930from maps import FunctionFieldMorphism_polymod931return FunctionFieldMorphism_polymod(self.Hom(codomain), im_gens[0], base_morphism)932933class RationalFunctionField(FunctionField):934"""935A rational function field K(t) in one variable, over an arbitrary936base field.937938EXAMPLES::939940sage: K.<t> = FunctionField(GF(3)); K941Rational function field in t over Finite Field of size 3942sage: K.gen()943t944sage: 1/t + t^3 + 5945(t^4 + 2*t + 1)/t946947There are various ways to get at the underlying fields and rings948associated to a rational function field::949950sage: K.<t> = FunctionField(GF(7))951sage: K.base_field()952Rational function field in t over Finite Field of size 7953sage: K.field()954Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7955sage: K.constant_field()956Finite Field of size 7957sage: K.maximal_order()958Maximal order in Rational function field in t over Finite Field of size 7959960We define a morphism::961962sage: K.<t> = FunctionField(QQ)963sage: L = FunctionField(QQ, 'tbar') # give variable name as second input964sage: K.hom(L.gen())965Morphism of function fields defined by t |--> tbar966"""967def __init__(self, constant_field, names,968element_class = FunctionFieldElement_rational,969category=CAT):970"""971Create a rational function field in one variable.972973INPUT:974975- ``constant_field`` -- an arbitrary field976- ``names`` -- a string or tuple of length 1977- ``category`` -- default: FunctionFields()978979EXAMPLES::980981sage: K.<t> = FunctionField(CC); K982Rational function field in t over Complex Field with 53 bits of precision983sage: K.category()984Category of function fields985sage: FunctionField(QQ[I], 'alpha')986Rational function field in alpha over Number Field in I with defining polynomial x^2 + 1987988Must be over a field::989990sage: FunctionField(ZZ, 't')991Traceback (most recent call last):992...993TypeError: constant_field must be a field994"""995if names is None:996raise ValueError, "variable name must be specified"997elif not isinstance(names, tuple):998names = (names, )999if not constant_field.is_field():1000raise TypeError, "constant_field must be a field"1001self._element_class = element_class1002self._element_init_pass_parent = False1003Field.__init__(self, self, names=names, category = category)1004R = constant_field[names[0]]1005self._hash = hash((constant_field, names))1006self._constant_field = constant_field1007self._ring = R1008self._field = R.fraction_field()1009self._populate_coercion_lists_(coerce_list=[self._field])1010self._gen = self(R.gen())10111012def __reduce__(self):1013"""1014Returns the arguments which were used to create this instance. The rationale for this is explained in the documentation of ``UniqueRepresentation``.10151016EXAMPLES::10171018sage: K.<x> = FunctionField(QQ)1019sage: clazz,args = K.__reduce__()1020sage: clazz(*args)1021Rational function field in x over Rational Field1022"""1023from constructor import FunctionField1024return FunctionField, (self._constant_field, self._names)10251026def __hash__(self):1027"""1028Return hash of this function field.10291030EXAMPLES::10311032sage: K.<t> = FunctionField(QQ)1033sage: hash(K)1034502145503910697533 # 64-bit1035-500688323 # 32-bit1036"""1037return self._hash10381039def _repr_(self):1040"""1041Return string representation of this function field.10421043EXAMPLES::10441045sage: K.<t> = FunctionField(QQ)1046sage: K._repr_()1047'Rational function field in t over Rational Field'1048"""1049return "Rational function field in %s over %s"%(1050self.variable_name(), self._constant_field)10511052def _element_constructor_(self, x):1053r"""1054Coerce ``x`` into an element of this function field, possibly not canonically.10551056INPUT:10571058- ``x`` -- the element10591060OUTPUT:10611062``x``, as an element of this function field10631064EXAMPLES::10651066sage: K.<t> = FunctionField(QQ)1067sage: a = K._element_constructor_(K.maximal_order().gen()); a1068t1069sage: a.parent()1070Rational function field in t over Rational Field10711072"""1073if x.parent() is self._field:1074return FunctionFieldElement_rational(self, x)1075if isinstance(x, FunctionFieldElement):1076return FunctionFieldElement_rational(self, self._field(x.element()))1077if x.parent() is self.polynomial_ring():1078return x[0]1079return FunctionFieldElement_rational(self, self._field(x))10801081def _to_bivariate_polynomial(self, f):1082"""1083Convert ``f`` from a univariate polynomial over the rational function1084field into a bivariate polynomial and a denominator.10851086INPUT:10871088- ``f`` -- a univariate polynomial over self.10891090OUTPUT:10911092- bivariate polynomial, denominator10931094EXAMPLES::10951096sage: R.<t> = FunctionField(GF(7))1097sage: S.<X> = R[]1098sage: f = (1/t)*(X^4 - 1/t^2)*(X^3 - t^3)1099sage: R._to_bivariate_polynomial(f)1100(X^7*t^2 - X^4*t^5 - X^3 + t^3, t^3)1101"""1102v = f.list()1103from sage.rings.arith import LCM1104denom = LCM([a.denominator() for a in v])1105S = denom.parent()1106x,t = S.base_ring()['%s,%s'%(f.parent().variable_name(),self.variable_name())].gens()1107phi = S.hom([t])1108return sum([phi((denom * v[i]).numerator()) * x**i for i in range(len(v))]), denom11091110def _factor_univariate_polynomial(self, f, proof=True):1111"""1112Factor the univariate polynomial ``f`` over self.11131114EXAMPLES::11151116We do a factorization over the function field over the rationals::11171118sage: R.<t> = FunctionField(QQ)1119sage: S.<X> = R[]1120sage: f = (1/t)*(X^4 - 1/t^2)*(X^3 - t^3)1121sage: f.factor() # indirect doctest1122(1/t) * (X - t) * (X^2 - 1/t) * (X^2 + 1/t) * (X^2 + t*X + t^2)1123sage: f.factor().prod() == f1124True11251126We do a factorization over a finite prime field::11271128sage: R.<t> = FunctionField(GF(7))1129sage: S.<X> = R[]1130sage: f = (1/t)*(X^4 - 1/t^2)*(X^3 - t^3)1131sage: f.factor()1132(1/t) * (X + 3*t) * (X + 5*t) * (X + 6*t) * (X^2 + 1/t) * (X^2 + 6/t)1133sage: f.factor().prod() == f1134True11351136Factoring over a function field over a non-prime finite field::11371138sage: k.<a> = GF(9)1139sage: R.<t> = FunctionField(k)1140sage: S.<X> = R[]1141sage: f = (1/t)*(X^3 - a*t^3)1142sage: f.factor()1143(1/t) * (X + (a + 2)*t)^31144sage: f.factor().prod() == f1145True1146"""1147F, d = self._to_bivariate_polynomial(f)1148fac = F.factor()1149x = f.parent().gen()1150t = f.parent().base_ring().gen()1151phi = F.parent().hom([x, t])1152v = [(phi(P),e) for P, e in fac]1153unit = phi(fac.unit())/d1154w = []1155for a, e in v:1156c = a.leading_coefficient()1157a = a/c1158unit *= (c**e)1159w.append((a,e))1160from sage.structure.factorization import Factorization1161return Factorization(w, unit=unit)11621163@cached_method1164def polynomial_ring(self, var='x'):1165"""1166Return a polynomial ring in one variable over this rational function field.11671168INPUT:11691170- ``var`` -- a string (default: 'x')11711172EXAMPLES::11731174sage: K.<x> = FunctionField(QQ)1175sage: K.polynomial_ring()1176Univariate Polynomial Ring in x over Rational function field in x over Rational Field1177sage: K.polynomial_ring('T')1178Univariate Polynomial Ring in T over Rational function field in x over Rational Field1179"""1180return self[var]11811182@cached_method1183def vector_space(self):1184"""1185Return a vector space V and isomorphisms self --> V and V --> self.11861187OUTPUT:11881189- ``V`` -- a vector space over the rational numbers1190- ``from_V`` -- an isomorphism from V to self1191- ``to_V`` -- an isomorphism from self to V11921193EXAMPLES::11941195sage: K.<x> = FunctionField(QQ)1196sage: K.vector_space()1197(Vector space of dimension 1 over Rational function field in x over Rational Field, Isomorphism morphism:1198From: Vector space of dimension 1 over Rational function field in x over Rational Field1199To: Rational function field in x over Rational Field, Isomorphism morphism:1200From: Rational function field in x over Rational Field1201To: Vector space of dimension 1 over Rational function field in x over Rational Field)1202"""1203V = self.base_field()**11204from maps import MapVectorSpaceToFunctionField, MapFunctionFieldToVectorSpace1205from_V = MapVectorSpaceToFunctionField(V, self)1206to_V = MapFunctionFieldToVectorSpace(self, V)1207return (V, from_V, to_V)12081209def random_element(self, *args, **kwds):1210"""1211Create a random element of this rational function field.1212Parameters are passed onto the random_element method of the1213underlying fraction field.12141215EXAMPLES::12161217sage: FunctionField(QQ,'alpha').random_element()1218(-1/2*alpha^2 - 4)/(-12*alpha^2 + 1/2*alpha - 1/95)1219"""1220return self(self._field.random_element(*args, **kwds))12211222def degree(self):1223"""1224Return the degree over the base field of this rational1225function field. Since the base field is the rational function1226field itself, the degree is 1.12271228EXAMPLES::12291230sage: K.<t> = FunctionField(QQ)1231sage: K.degree()123211233"""1234from sage.rings.integer_ring import ZZ1235return ZZ(1)12361237def gen(self, n=0):1238"""1239Return the ``n``-th generator of this function field. If ``n`` is not12400, then an IndexError is raised.12411242EXAMPLES::12431244sage: K.<t> = FunctionField(QQ); K.gen()1245t1246sage: K.gen().parent()1247Rational function field in t over Rational Field1248sage: K.gen(1)1249Traceback (most recent call last):1250...1251IndexError: Only one generator.1252"""1253if n != 0:1254raise IndexError, "Only one generator."1255return self._gen12561257def ngens(self):1258"""1259Return the number of generators, which is 1.12601261EXAMPLES::12621263sage: K.<t> = FunctionField(QQ)1264sage: K.ngens()126511266"""1267return 112681269def base_field(self):1270"""1271Return the base field of this rational function field, which is just1272this function field itself.12731274EXAMPLES::12751276sage: K.<t> = FunctionField(GF(7))1277sage: K.base_field()1278Rational function field in t over Finite Field of size 71279"""1280return self12811282def hom(self, im_gens, base_morphism=None):1283"""1284Create a homomorphism from self to another function field.12851286INPUT:12871288- ``im_gens`` -- exactly one element of some function field1289- ``base_morphism`` -- ignored12901291OUTPUT:12921293- a map between function fields12941295EXAMPLES:12961297We make a map from a rational function field to itself::12981299sage: K.<x> = FunctionField(GF(7))1300sage: K.hom( (x^4 + 2)/x)1301Morphism of function fields defined by x |--> (x^4 + 2)/x13021303We construct a map from a rational function field into a1304non-rational extension field::13051306sage: K.<x> = FunctionField(GF(7)); R.<y> = K[]1307sage: L.<y> = K.extension(y^3 + 6*x^3 + x)1308sage: f = K.hom(y^2 + y + 2); f1309Morphism of function fields defined by x |--> y^2 + y + 21310sage: f(x)1311y^2 + y + 21312sage: f(x^2)13135*y^2 + (x^3 + 6*x + 4)*y + 2*x^3 + 5*x + 41314"""1315from sage.structure.category_object import CategoryObject1316if isinstance(im_gens, CategoryObject):1317return self.Hom(im_gens).natural_map()1318if not isinstance(im_gens, (list,tuple)):1319im_gens = [im_gens]1320if len(im_gens) != 1:1321raise ValueError, "there must be exactly one generator"1322x = im_gens[0]1323from maps import FunctionFieldMorphism_rational1324return FunctionFieldMorphism_rational(self.Hom(x.parent()), x)13251326def field(self):1327"""1328Return the underlying field, forgetting the function field1329structure.13301331EXAMPLES::13321333sage: K.<t> = FunctionField(GF(7))1334sage: K.field()1335Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 71336"""1337return self._field13381339@cached_method1340def maximal_order(self):1341"""1342Return the maximal order of this function field. Since this1343is a rational function field it is of the form K(t), and the1344maximal order is by definition K[t].13451346EXAMPLES::13471348sage: K.<t> = FunctionField(QQ)1349sage: K.maximal_order()1350Maximal order in Rational function field in t over Rational Field1351sage: K.equation_order()1352Maximal order in Rational function field in t over Rational Field1353"""1354from function_field_order import FunctionFieldOrder_rational1355return FunctionFieldOrder_rational(self)13561357equation_order = maximal_order13581359def constant_base_field(self):1360"""1361Return the field that this rational function field is a1362transcendental extension of.13631364EXAMPLES::13651366sage: K.<t> = FunctionField(QQ)1367sage: K.constant_field()1368Rational Field13691370"""1371return self._constant_field13721373constant_field = constant_base_field137413751376