Path: blob/master/src/sage/rings/function_field/function_field.py
8820 views
"""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_method1415- Syed Ahmad Lavasani (2011-12-16): added genus(), is_RationalFunctionField()1617EXAMPLES:1819We create an extension of a rational function fields, and do some20simple arithmetic in it::2122sage: K.<x> = FunctionField(GF(5^2,'a')); K23Rational function field in x over Finite Field in a of size 5^224sage: R.<y> = K[]25sage: L.<y> = K.extension(y^3 - (x^3 + 2*x*y + 1/x)); L26Function field in y defined by y^3 + 3*x*y + (4*x^4 + 4)/x27sage: y^228y^229sage: y^3302*x*y + (x^4 + 1)/x31sage: a = 1/y; a32(4*x/(4*x^4 + 4))*y^2 + 2*x^2/(4*x^4 + 4)33sage: a * y3413536We next make an extension of the above function field, illustrating37that arithmetic with a tower of 3 fields is fully supported::3839sage: S.<t> = L[]40sage: M.<t> = L.extension(t^2 - x*y)41sage: M42Function field in t defined by t^2 + 4*x*y43sage: t^244x*y45sage: 1/t46((1/(x^4 + 1))*y^2 + 2*x/(4*x^4 + 4))*t47sage: M.base_field()48Function field in y defined by y^3 + 3*x*y + (4*x^4 + 4)/x49sage: M.base_field().base_field()50Rational function field in x over Finite Field in a of size 5^25152TESTS::5354sage: TestSuite(K).run()55sage: TestSuite(L).run() # long time (8s on sage.math, 2012)56sage: TestSuite(M).run() # long time (52s on sage.math, 2012)5758The following two test suites do not pass ``_test_elements`` yet since59``R.an_element()`` has a ``_test_category`` method wich it should not have.60It is not the fault of the function field code so this will61be fixed in another ticket::6263sage: TestSuite(R).run(skip = '_test_elements')64sage: TestSuite(S).run(skip = '_test_elements')65"""66#*****************************************************************************67# Copyright (C) 2010 William Stein <[email protected]>68# Copyright (C) 2010 Robert Bradshaw <[email protected]>69# Copyright (C) 2011 Julian Rueth <[email protected]>70# Copyright (C) 2011 Maarten Derickx <[email protected]>71#72# Distributed under the terms of the GNU General Public License (GPL)73# as published by the Free Software Foundation; either version 2 of74# the License, or (at your option) any later version.75# http://www.gnu.org/licenses/76#*****************************************************************************7778from sage.rings.ring import Field79from function_field_element import FunctionFieldElement, FunctionFieldElement_rational, FunctionFieldElement_polymod8081from sage.misc.cachefunc import cached_method8283#is needed for genus computation84from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing85from sage.interfaces.all import singular8687from sage.categories.function_fields import FunctionFields88CAT = FunctionFields()8990def is_FunctionField(x):91"""92Return True if ``x`` is of function field type.9394EXAMPLES::9596sage: from sage.rings.function_field.function_field import is_FunctionField97sage: is_FunctionField(QQ)98False99sage: is_FunctionField(FunctionField(QQ,'t'))100True101"""102if isinstance(x, FunctionField): return True103return x in FunctionFields()104105class FunctionField(Field):106"""107The abstract base class for all function fields.108109EXAMPLES::110111sage: K.<x> = FunctionField(QQ)112sage: isinstance(K, sage.rings.function_field.function_field.FunctionField)113True114"""115def some_elements(self):116"""117Return a list of elements in the function field.118119EXAMPLES::120121sage: K.<x> = FunctionField(QQ)122sage: elements = K.some_elements()123sage: elements # random output124[(x - 3/2)/(x^2 - 12/5*x + 1/18)]125sage: False in [e in K for e in elements]126False127"""128return [self.random_element(), self.random_element(), self.random_element()]129130def characteristic(self):131"""132Return the characteristic of this function field.133134EXAMPLES::135136sage: K.<x> = FunctionField(QQ)137sage: K.characteristic()1380139sage: K.<x> = FunctionField(GF(7))140sage: K.characteristic()1417142sage: R.<y> = K[]143sage: L.<y> = K.extension(y^2-x)144sage: L.characteristic()1457146"""147return self.constant_base_field().characteristic()148149def is_finite(self):150"""151Return whether this function field is finite, which it is not.152153EXAMPLES::154155sage: R.<t> = FunctionField(QQ)156sage: R.is_finite()157False158sage: R.<t> = FunctionField(GF(7))159sage: R.is_finite()160False161"""162return False163164def extension(self, f, names=None):165"""166Create an extension L = K[y]/(f(y)) of a function field,167defined by a univariate polynomial in one variable over this168function field K.169170INPUT:171172- ``f`` -- a univariate polynomial over self173- ``names`` -- None or string or length-1 tuple174175OUTPUT:176177- a function field178179EXAMPLES::180181sage: K.<x> = FunctionField(QQ); R.<y> = K[]182sage: K.extension(y^5 - x^3 - 3*x + x*y)183Function field in y defined by y^5 + x*y - x^3 - 3*x184185A nonintegral defining polynomial::186187sage: K.<t> = FunctionField(QQ); R.<y> = K[]188sage: K.extension(y^3 + (1/t)*y + t^3/(t+1))189Function field in y defined by y^3 + 1/t*y + t^3/(t + 1)190191The defining polynomial need not be monic or integral::192193sage: K.extension(t*y^3 + (1/t)*y + t^3/(t+1))194Function field in y defined by t*y^3 + 1/t*y + t^3/(t + 1)195"""196from constructor import FunctionField_polymod as FunctionField_polymod_Constructor197return FunctionField_polymod_Constructor(f, names)198199def order_with_basis(self, basis, check=True):200"""201Return the order with given basis over the maximal order of202the base field.203204INPUT:205206- ``basis`` -- a list of elements of self207- ``check`` -- bool (default: True); if True, check that208the basis is really linearly independent and that the209module it spans is closed under multiplication, and210contains the identity element.211212OUTPUT:213214- an order in this function field215216EXAMPLES::217218sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<y> = K.extension(y^3 + x^3 + 4*x + 1)219sage: O = L.order_with_basis([1, y, y^2]); O220Order in Function field in y defined by y^3 + x^3 + 4*x + 1221sage: O.basis()222(1, y, y^2)223224Note that 1 does not need to be an element of the basis, as long it is in the module spanned by it::225226sage: O = L.order_with_basis([1+y, y, y^2]); O227Order in Function field in y defined by y^3 + x^3 + 4*x + 1228sage: O.basis()229(y + 1, y, y^2)230231The following error is raised when the module spanned by the basis is not closed under multiplication::232233sage: O = L.order_with_basis([1, x^2 + x*y, (2/3)*y^2]); O234Traceback (most recent call last):235...236ValueError: The module generated by basis [1, x*y + x^2, 2/3*y^2] must be closed under multiplication237238and this happens when the identity is not in the module spanned by the basis::239240sage: O = L.order_with_basis([x, x^2 + x*y, (2/3)*y^2])241Traceback (most recent call last):242...243ValueError: The identity element must be in the module spanned by basis [x, x*y + x^2, 2/3*y^2]244"""245from function_field_order import FunctionFieldOrder_basis246return FunctionFieldOrder_basis([self(a) for a in basis], check=check)247248def order(self, x, check=True):249"""250Return the order in this function field generated over the251maximal order by x or the elements of x if x is a list.252253INPUT:254255- ``x`` -- element of self, or a list of elements of self256- ``check`` -- bool (default: True); if True, check that257x really generates an order258259EXAMPLES::260261sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<y> = K.extension(y^3 + x^3 + 4*x + 1)262sage: O = L.order(y); O263Order in Function field in y defined by y^3 + x^3 + 4*x + 1264sage: O.basis()265(1, y, y^2)266267sage: Z = K.order(x); Z268Order in Rational function field in x over Rational Field269sage: Z.basis()270(1,)271272Orders with multiple generators, not yet supported::273274sage: Z = K.order([x,x^2]); Z275Traceback (most recent call last):276...277NotImplementedError278"""279if not isinstance(x, (list, tuple)):280x = [x]281if len(x) == 1:282g = x[0]283basis = [self(1)]284for i in range(self.degree()-1):285basis.append(basis[-1]*g)286else:287raise NotImplementedError288return self.order_with_basis(basis, check=check)289290def _coerce_map_from_(self, R):291"""292Return True if there is a coerce map from R to self.293294EXAMPLES::295296sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<y> = K.extension(y^3 + x^3 + 4*x + 1)297sage: L.equation_order()298Order in Function field in y defined by y^3 + x^3 + 4*x + 1299sage: L._coerce_map_from_(L.equation_order())300True301sage: L._coerce_map_from_(GF(7))302False303"""304from function_field_order import FunctionFieldOrder305if isinstance(R, FunctionFieldOrder) and R.fraction_field() == self:306return True307return False308309class FunctionField_polymod(FunctionField):310"""311A function field defined by a univariate polynomial, as an312extension of the base field.313314EXAMPLES:315316We make a function field defined by a degree 5 polynomial over the317rational function field over the rational numbers::318319sage: K.<x> = FunctionField(QQ)320sage: R.<y> = K[]321sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L322Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x323324We next make a function field over the above nontrivial function325field L::326327sage: S.<z> = L[]328sage: M.<z> = L.extension(z^2 + y*z + y); M329Function field in z defined by z^2 + y*z + y330sage: 1/z331((x/(-x^4 - 1))*y^4 - 2*x^2/(-x^4 - 1))*z - 1332sage: z * (1/z)3331334335We drill down the tower of function fields::336337sage: M.base_field()338Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x339sage: M.base_field().base_field()340Rational function field in x over Rational Field341sage: M.base_field().base_field().constant_field()342Rational Field343sage: M.constant_base_field()344Rational Field345346.. WARNING::347348It is not checked if the polynomial used to define this function field is irreducible349Hence it is not guaranteed that this object really is a field!350This is illustrated below.351352::353354sage: K.<x>=FunctionField(QQ)355sage: R.<y> = K[]356sage: L.<y>=K.extension(x^2-y^2)357sage: (y-x)*(y+x)3580359sage: 1/(y-x)3601361sage: y-x==0; y+x==0362False363False364"""365def __init__(self, polynomial, names,366element_class = FunctionFieldElement_polymod,367category=CAT):368"""369Create a function field defined as an extension of another370function field by adjoining a root of a univariate polynomial.371372INPUT:373374- ``polynomial`` -- a univariate polynomial over a function field375- ``names`` -- variable names (as a tuple of length 1 or string)376- ``category`` -- a category (defaults to category of function fields)377378EXAMPLES::379380We create an extension of a function field::381382sage: K.<x> = FunctionField(QQ); R.<y> = K[]383sage: L = K.extension(y^5 - x^3 - 3*x + x*y); L384Function field in y defined by y^5 + x*y - x^3 - 3*x385386Note the type::387388sage: type(L)389<class 'sage.rings.function_field.function_field.FunctionField_polymod_with_category'>390391We can set the variable name, which doesn't have to be y::392393sage: L.<w> = K.extension(y^5 - x^3 - 3*x + x*y); L394Function field in w defined by y^5 + x*y - x^3 - 3*x395"""396from sage.rings.polynomial.all import is_Polynomial397if polynomial.parent().ngens()>1 or not is_Polynomial(polynomial):398raise TypeError, "polynomial must be univariate a polynomial"399if names is None:400names = (polynomial.variable_name(), )401if polynomial.degree() <= 0:402raise ValueError, "polynomial must have positive degree"403base_field = polynomial.base_ring()404if not isinstance(base_field, FunctionField):405raise TypeError, "polynomial must be over a FunctionField"406self._element_class = element_class407self._element_init_pass_parent = False408self._base_field = base_field409self._polynomial = polynomial410411Field.__init__(self, base_field,412names=names, category = category)413414self._hash = hash(polynomial)415self._ring = self._polynomial.parent()416self._populate_coercion_lists_(coerce_list=[base_field, self._ring])417self._gen = self(self._ring.gen())418419def __reduce__(self):420"""421Returns the arguments which were used to create this instance. The rationale for this is explained in the documentation of ``UniqueRepresentation``.422423EXAMPLES::424425sage: K.<x> = FunctionField(QQ); R.<y> = K[]426sage: L = K.extension(y^2-x)427sage: clazz,args = L.__reduce__()428sage: clazz(*args)429Function field in y defined by y^2 - x430"""431from constructor import FunctionField_polymod as FunctionField_polymod_Constructor432return FunctionField_polymod_Constructor, (self._polynomial, self._names)433434def __hash__(self):435"""436Return hash of this function field.437438EXAMPLES::439440sage: K.<x> = FunctionField(QQ); R.<y> = K[]441sage: L = K.extension(y^5 - x^3 - 3*x + x*y); hash(L)4423183366741743088279 # 64-bit4432003022487 # 32-bit444"""445return self._hash446447def monic_integral_model(self, names):448"""449Return a function field isomorphic to self, but with defining450polynomial that is monic and integral over the base field.451452INPUT:453454- ``names`` -- name of the generator of the new field this function constructs455456EXAMPLES::457458sage: K.<x> = FunctionField(QQ); R.<y> = K[]459sage: L.<y> = K.extension(x^2*y^5 - 1/x); L460Function field in y defined by x^2*y^5 - 1/x461sage: A, from_A, to_A = L.monic_integral_model('z')462sage: A463Function field in z defined by y^5 - x^12464sage: from_A465Morphism of function fields defined by z |--> x^3*y466sage: to_A467Morphism of function fields defined by y |--> 1/x^3*z468sage: to_A(y)4691/x^3*z470sage: from_A(to_A(y))471y472sage: from_A(to_A(1/y))473x^3*y^4474sage: from_A(to_A(1/y)) == 1/y475True476"""477g, d = self._make_monic_integral(self.polynomial())478R = self.base_field()479K = R.extension(g, names=names)480to_K = self.hom(K.gen() / d)481from_K = K.hom(self.gen() * d)482return K, from_K, to_K483484def _make_monic_integral(self, f):485r"""486Let y be a root of ``f``. This function returns a monic487integral polynomial g and an element d of the base field such488that g(y*d)=0.489490EXAMPLES::491492sage: K.<x> = FunctionField(QQ); R.<y> = K[];493sage: L.<y> = K.extension(x^2*y^5 - 1/x)494sage: g, d = L._make_monic_integral(L.polynomial()); g,d495(y^5 - x^12, x^3)496sage: (y*d).is_integral()497True498sage: g.is_monic()499True500sage: g(y*d)5010502"""503R = f.base_ring()504if not isinstance(R, RationalFunctionField):505raise NotImplementedError506507# make f monic508n = f.degree()509c = f.leading_coefficient()510if c != 1:511f = f / c512513# find lcm of denominators514from sage.rings.arith import lcm515# would be good to replace this by minimal...516d = lcm([b.denominator() for b in f.list() if b])517if d != 1:518x = f.parent().gen()519g = (d**n) * f(x/d)520else:521g = f522return g, d523524def constant_field(self):525"""526Return the algebraic closure of the constant field of the base527field in this function field.528529EXAMPLES::530531sage: K.<x> = FunctionField(QQ); R.<y> = K[]532sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))533sage: L.constant_field()534Traceback (most recent call last):535...536NotImplementedError537"""538raise NotImplementedError539540def constant_base_field(self):541"""542Return the constant field of the base rational function field.543544EXAMPLES::545546sage: K.<x> = FunctionField(QQ); R.<y> = K[]547sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L548Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x549sage: L.constant_base_field()550Rational Field551sage: S.<z> = L[]552sage: M.<z> = L.extension(z^2 - y)553sage: M.constant_base_field()554Rational Field555"""556return self.base_field().constant_base_field()557558def degree(self):559"""560Return the degree of this function field over its base561function field.562563EXAMPLES::564565sage: K.<x> = FunctionField(QQ)566sage: R.<y> = K[]567sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L568Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x569sage: L.degree()5705571"""572return self._polynomial.degree()573574def _repr_(self):575"""576Return string representation of this function field.577578EXAMPLES::579580sage: K.<x> = FunctionField(QQ); R.<y> = K[]581sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))582sage: L._repr_()583'Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x'584"""585return "Function field in %s defined by %s"%(self.variable_name(), self._polynomial)586587def base_field(self):588"""589Return the base field of this function field. This function590field is presented as L = K[y]/(f(y)), and the base field is591by definition the field K.592593EXAMPLES::594595sage: K.<x> = FunctionField(QQ); R.<y> = K[]596sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))597sage: L.base_field()598Rational function field in x over Rational Field599"""600return self._base_field601602def random_element(self, *args, **kwds):603"""604Create a random element of this function field. Parameters605are passed onto the random_element method of the base_field.606607EXAMPLES::608609sage: K.<x> = FunctionField(QQ); R.<y> = K[]610sage: L.<y> = K.extension(y^2 - (x^2 + x))611sage: L.random_element() # random612((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)613"""614return self(self._ring.random_element(degree=self.degree(), *args, **kwds))615616def polynomial(self):617"""618Return the univariate polynomial that defines this function619field, i.e., the polynomial f(y) so that this function field620is of the form K[y]/(f(y)).621622EXAMPLES::623624sage: K.<x> = FunctionField(QQ); R.<y> = K[]625sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))626sage: L.polynomial()627y^5 - 2*x*y + (-x^4 - 1)/x628"""629return self._polynomial630631def polynomial_ring(self):632"""633Return the polynomial ring used to represent elements of this634function field. If we view this function field as being presented635as K[y]/(f(y)), then this function returns the ring K[y].636637EXAMPLES::638639sage: K.<x> = FunctionField(QQ); R.<y> = K[]640sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))641sage: L.polynomial_ring()642Univariate Polynomial Ring in y over Rational function field in x over Rational Field643"""644return self._ring645646@cached_method647def vector_space(self):648"""649Return a vector space V and isomorphisms self --> V and V --> self.650651This function allows us to identify the elements of self with652elements of a vector space over the base field, which is653useful for representation and arithmetic with orders, ideals,654etc.655656OUTPUT:657658- ``V`` -- a vector space over base field659- ``from_V`` -- an isomorphism from V to self660- ``to_V`` -- an isomorphism from self to V661662EXAMPLES:663664We define a function field::665666sage: K.<x> = FunctionField(QQ); R.<y> = K[]667sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L668Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x669670We get the vector spaces, and maps back and forth::671672sage: V, from_V, to_V = L.vector_space()673sage: V674Vector space of dimension 5 over Rational function field in x over Rational Field675sage: from_V676Isomorphism morphism:677From: Vector space of dimension 5 over Rational function field in x over Rational Field678To: Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x679sage: to_V680Isomorphism morphism:681From: Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x682To: Vector space of dimension 5 over Rational function field in x over Rational Field683684We convert an element of the vector space back to the function field::685686sage: from_V(V.1)687y688689We define an interesting element of the function field::690691sage: a = 1/L.0; a692(-x/(-x^4 - 1))*y^4 + 2*x^2/(-x^4 - 1)693694We convert it to the vector space, and get a vector over the base field::695696sage: to_V(a)697(2*x^2/(-x^4 - 1), 0, 0, 0, -x/(-x^4 - 1))698699We convert to and back, and get the same element::700701sage: from_V(to_V(a)) == a702True703704In the other direction::705706sage: v = x*V.0 + (1/x)*V.1707sage: to_V(from_V(v)) == v708True709710And we show how it works over an extension of an extension field::711712sage: R2.<z> = L[]; M.<z> = L.extension(z^2 -y)713sage: M.vector_space()714(Vector space of dimension 2 over Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x, Isomorphism morphism:715From: Vector space of dimension 2 over Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x716To: Function field in z defined by z^2 - y, Isomorphism morphism:717From: Function field in z defined by z^2 - y718To: Vector space of dimension 2 over Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x)719"""720V = self.base_field()**self.degree()721from maps import MapVectorSpaceToFunctionField, MapFunctionFieldToVectorSpace722from_V = MapVectorSpaceToFunctionField(V, self)723to_V = MapFunctionFieldToVectorSpace(self, V)724return (V, from_V, to_V)725726def maximal_order(self):727"""728Return the maximal_order of self. If we view self as L =729K[y]/(f(y)), then this is the ring of elements of L that are730integral over K.731732EXAMPLES:733734This is not yet implemented...::735736sage: K.<x> = FunctionField(QQ); R.<y> = K[]737sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))738sage: L.maximal_order()739Traceback (most recent call last):740...741NotImplementedError742"""743raise NotImplementedError744745def _element_constructor_(self, x):746r"""747Make ``x`` into an element of this function field, possibly not canonically.748749INPUT:750751- ``x`` -- the element752753OUTPUT:754755``x``, as an element of this function field756757TESTS::758759sage: K.<x> = FunctionField(QQ); R.<y> = K[]760sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))761sage: L._element_constructor_(L.polynomial_ring().gen())762y763"""764if x.parent() is self._ring:765return FunctionFieldElement_polymod(self, x)766if isinstance(x, FunctionFieldElement):767return FunctionFieldElement_polymod(self, self._ring(x.element()))768return FunctionFieldElement_polymod(self, self._ring(x))769770def gen(self, n=0):771"""772Return the ``n``-th generator of this function field. By default ``n`` is 0; any other773value of ``n`` leads to an error. The generator is the class of y, if we view774self as being presented as K[y]/(f(y)).775776EXAMPLES::777778sage: K.<x> = FunctionField(QQ); R.<y> = K[]779sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))780sage: L.gen()781y782sage: L.gen(1)783Traceback (most recent call last):784...785IndexError: Only one generator.786"""787if n != 0: raise IndexError, "Only one generator."788return self._gen789790def ngens(self):791"""792Return the number of generators of this function field over793its base field. This is by definition 1.794795EXAMPLES::796797sage: K.<x> = FunctionField(QQ); R.<y> = K[]798sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))799sage: L.ngens()8001801"""802return 1803804def equation_order(self):805"""806If we view self as being presented as K[y]/(f(y)), then this807function returns the order generated by the class of y. If f808is not monic, then :meth:`_make_monic_integral` is called, and instead we809get the order generated by some integral multiple of a root of f.810811EXAMPLES::812813sage: K.<x> = FunctionField(QQ); R.<y> = K[]814sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))815sage: O = L.equation_order()816sage: O.basis()817(1, x*y, x^2*y^2, x^3*y^3, x^4*y^4)818819We try an example, in which the defining polynomial is not820monic and is not integral::821822sage: K.<x> = FunctionField(QQ); R.<y> = K[]823sage: L.<y> = K.extension(x^2*y^5 - 1/x); L824Function field in y defined by x^2*y^5 - 1/x825sage: O = L.equation_order()826sage: O.basis()827(1, x^3*y, x^6*y^2, x^9*y^3, x^12*y^4)828"""829d = self._make_monic_integral(self.polynomial())[1]830return self.order(d*self.gen(), check=False)831832def hom(self, im_gens, base_morphism=None):833"""834Create a homomorphism from self to another function field.835836INPUT:837838- ``im_gens`` -- a list of images of the generators of self839and of successive base rings.840841- ``base_morphism`` -- (default: None) a homomorphism of842the base ring, after the im_gens are used. Thus if843im_gens has length 2, then base_morphism should be a morphism844from self.base_ring().base_ring().845846EXAMPLES:847848We create a rational function field, and a quadratic extension of it::849850sage: K.<x> = FunctionField(QQ); R.<y> = K[]851sage: L.<y> = K.extension(y^2 - x^3 - 1)852853We make the field automorphism that sends y to -y::854855sage: f = L.hom(-y); f856Morphism of function fields defined by y |--> -y857858Evaluation works::859860sage: f(y*x - 1/x)861-x*y - 1/x862863We try to define an invalid morphism::864865sage: f = L.hom(y+1)866Traceback (most recent call last):867...868ValueError: invalid morphism869870We make a morphism of the base rational function field::871872sage: phi = K.hom(x+1); phi873Morphism of function fields defined by x |--> x + 1874sage: phi(x^3 - 3)875x^3 + 3*x^2 + 3*x - 2876sage: (x+1)^3-3877x^3 + 3*x^2 + 3*x - 2878879We make a morphism by specifying where the generators and the880base generators go::881882sage: L.hom([-y, x])883Morphism of function fields defined by y |--> -y, x |--> x884885The usage of the keyword base_morphism is not implemented yet::886887sage: L.hom([-y, x-1], base_morphism=phi)888Traceback (most recent call last):889...890NotImplementedError: Function field homorphisms with optional argument base_morphism are not implemented yet. Please specify the images of the generators of the base fields manually.891892We make another extension of a rational function field::893894sage: K2.<t> = FunctionField(QQ); R2.<w> = K2[]895sage: L2.<w> = K2.extension((4*w)^2 - (t+1)^3 - 1)896897We define a morphism, by giving the images of generators::898899sage: f = L.hom([4*w, t+1]); f900Morphism of function fields defined by y |--> 4*w, x |--> t + 1901902Evaluation works, as expected::903904sage: f(y+x)9054*w + t + 1906sage: f(x*y + x/(x^2+1))907(4*t + 4)*w + (t + 1)/(t^2 + 2*t + 2)908909We make another extension of a rational function field::910911sage: K3.<yy> = FunctionField(QQ); R3.<xx> = K3[]912sage: L3.<xx> = K3.extension(yy^2 - xx^3 - 1)913914This is the function field L with the generators exchanged. We define a morphism to L::915916sage: g = L3.hom([x,y]); g917Morphism of function fields defined by xx |--> x, yy |--> y918"""919if base_morphism is not None:920raise 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."921922if not isinstance(im_gens, (list,tuple)):923im_gens = [im_gens]924if len(im_gens) == 0:925raise ValueError, "no images specified"926927if len(im_gens) > 1:928base_morphism = self.base_field().hom(im_gens[1:], base_morphism)929930# the codomain of this morphism is the field containing all the im_gens931codomain = im_gens[0].parent();932if base_morphism is not None:933if base_morphism.codomain().has_coerce_map_from(codomain):934codomain = base_morphism.codomain();935936from maps import FunctionFieldMorphism_polymod937return FunctionFieldMorphism_polymod(self.Hom(codomain), im_gens[0], base_morphism)938939@cached_method940def genus(self):941"""942Return the genus of this function field943For now, the genus is computed using singular944945EXAMPLES::946947sage: K.<x> = FunctionField(QQ); R.<y> = K[]948sage: L.<y> = K.extension(y^3 - (x^3 + 2*x*y + 1/x))949sage: L.genus()9503951"""952# unfortunately singular can not compute the genus with the polynomial_ring()._singular_953# object because genus method only accepts a ring of transdental degree 2 over a prime field954# not a ring of transdental degree 1 over a rational function field of one variable955956if is_RationalFunctionField(self._base_field) and self._base_field.constant_field().is_prime_field():957958#Making the auxiliary ring which only has polynomials with integral coefficients.959tmpAuxRing = PolynomialRing(self._base_field.constant_field(), str(self._base_field.gen())+','+str(self._ring.gen()))960intMinPoly, d = self._make_monic_integral(self._polynomial)961curveIdeal = tmpAuxRing.ideal(intMinPoly)962963singular.lib('normal.lib') #loading genus method in singular964return int(curveIdeal._singular_().genus())965966else:967raise NotImplementedError, "Computation of genus over this rational function field not implemented yet"968969def is_RationalFunctionField(x):970"""971Return True if ``x`` is of rational function field type.972973EXAMPLES::974975sage: from sage.rings.function_field.function_field import is_RationalFunctionField976sage: is_RationalFunctionField(QQ)977False978sage: is_RationalFunctionField(FunctionField(QQ,'t'))979True980"""981if isinstance(x, RationalFunctionField):982return True983# if (x in FunctionFields()):984# return x == x.base_field()985else:986return False987988class RationalFunctionField(FunctionField):989"""990A rational function field K(t) in one variable, over an arbitrary991base field.992993EXAMPLES::994995sage: K.<t> = FunctionField(GF(3)); K996Rational function field in t over Finite Field of size 3997sage: K.gen()998t999sage: 1/t + t^3 + 51000(t^4 + 2*t + 1)/t10011002There are various ways to get at the underlying fields and rings1003associated to a rational function field::10041005sage: K.<t> = FunctionField(GF(7))1006sage: K.base_field()1007Rational function field in t over Finite Field of size 71008sage: K.field()1009Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 71010sage: K.constant_field()1011Finite Field of size 71012sage: K.maximal_order()1013Maximal order in Rational function field in t over Finite Field of size 710141015We define a morphism::10161017sage: K.<t> = FunctionField(QQ)1018sage: L = FunctionField(QQ, 'tbar') # give variable name as second input1019sage: K.hom(L.gen())1020Morphism of function fields defined by t |--> tbar1021"""1022def __init__(self, constant_field, names,1023element_class = FunctionFieldElement_rational,1024category=CAT):1025"""1026Create a rational function field in one variable.10271028INPUT:10291030- ``constant_field`` -- an arbitrary field1031- ``names`` -- a string or tuple of length 11032- ``category`` -- default: FunctionFields()10331034EXAMPLES::10351036sage: K.<t> = FunctionField(CC); K1037Rational function field in t over Complex Field with 53 bits of precision1038sage: K.category()1039Category of function fields1040sage: FunctionField(QQ[I], 'alpha')1041Rational function field in alpha over Number Field in I with defining polynomial x^2 + 110421043Must be over a field::10441045sage: FunctionField(ZZ, 't')1046Traceback (most recent call last):1047...1048TypeError: constant_field must be a field1049"""1050if names is None:1051raise ValueError, "variable name must be specified"1052elif not isinstance(names, tuple):1053names = (names, )1054if not constant_field.is_field():1055raise TypeError, "constant_field must be a field"1056self._element_class = element_class1057self._element_init_pass_parent = False1058Field.__init__(self, self, names=names, category = category)1059R = constant_field[names[0]]1060self._hash = hash((constant_field, names))1061self._constant_field = constant_field1062self._ring = R1063self._field = R.fraction_field()1064self._populate_coercion_lists_(coerce_list=[self._field])1065self._gen = self(R.gen())10661067def __reduce__(self):1068"""1069Returns the arguments which were used to create this instance. The rationale for this is explained in the documentation of ``UniqueRepresentation``.10701071EXAMPLES::10721073sage: K.<x> = FunctionField(QQ)1074sage: clazz,args = K.__reduce__()1075sage: clazz(*args)1076Rational function field in x over Rational Field1077"""1078from constructor import FunctionField1079return FunctionField, (self._constant_field, self._names)10801081def __hash__(self):1082"""1083Return hash of this function field.10841085EXAMPLES::10861087sage: K.<t> = FunctionField(QQ)1088sage: hash(K)1089502145503910697533 # 64-bit1090-500688323 # 32-bit1091"""1092return self._hash10931094def _repr_(self):1095"""1096Return string representation of this function field.10971098EXAMPLES::10991100sage: K.<t> = FunctionField(QQ)1101sage: K._repr_()1102'Rational function field in t over Rational Field'1103"""1104return "Rational function field in %s over %s"%(1105self.variable_name(), self._constant_field)11061107def _element_constructor_(self, x):1108r"""1109Coerce ``x`` into an element of this function field, possibly not canonically.11101111INPUT:11121113- ``x`` -- the element11141115OUTPUT:11161117``x``, as an element of this function field11181119EXAMPLES::11201121sage: K.<t> = FunctionField(QQ)1122sage: a = K._element_constructor_(K.maximal_order().gen()); a1123t1124sage: a.parent()1125Rational function field in t over Rational Field11261127"""1128if x.parent() is self._field:1129return FunctionFieldElement_rational(self, x)1130if isinstance(x, FunctionFieldElement):1131return FunctionFieldElement_rational(self, self._field(x.element()))1132if x.parent() is self.polynomial_ring():1133return x[0]1134return FunctionFieldElement_rational(self, self._field(x))11351136def _to_bivariate_polynomial(self, f):1137"""1138Convert ``f`` from a univariate polynomial over the rational function1139field into a bivariate polynomial and a denominator.11401141INPUT:11421143- ``f`` -- a univariate polynomial over self.11441145OUTPUT:11461147- bivariate polynomial, denominator11481149EXAMPLES::11501151sage: R.<t> = FunctionField(GF(7))1152sage: S.<X> = R[]1153sage: f = (1/t)*(X^4 - 1/t^2)*(X^3 - t^3)1154sage: R._to_bivariate_polynomial(f)1155(X^7*t^2 - X^4*t^5 - X^3 + t^3, t^3)1156"""1157v = f.list()1158from sage.rings.arith import LCM1159denom = LCM([a.denominator() for a in v])1160S = denom.parent()1161x,t = S.base_ring()['%s,%s'%(f.parent().variable_name(),self.variable_name())].gens()1162phi = S.hom([t])1163return sum([phi((denom * v[i]).numerator()) * x**i for i in range(len(v))]), denom11641165def _factor_univariate_polynomial(self, f, proof=True):1166"""1167Factor the univariate polynomial ``f`` over self.11681169EXAMPLES::11701171We do a factorization over the function field over the rationals::11721173sage: R.<t> = FunctionField(QQ)1174sage: S.<X> = R[]1175sage: f = (1/t)*(X^4 - 1/t^2)*(X^3 - t^3)1176sage: f.factor() # indirect doctest1177(1/t) * (X - t) * (X^2 - 1/t) * (X^2 + 1/t) * (X^2 + t*X + t^2)1178sage: f.factor().prod() == f1179True11801181We do a factorization over a finite prime field::11821183sage: R.<t> = FunctionField(GF(7))1184sage: S.<X> = R[]1185sage: f = (1/t)*(X^4 - 1/t^2)*(X^3 - t^3)1186sage: f.factor()1187(1/t) * (X + 3*t) * (X + 5*t) * (X + 6*t) * (X^2 + 1/t) * (X^2 + 6/t)1188sage: f.factor().prod() == f1189True11901191Factoring over a function field over a non-prime finite field::11921193sage: k.<a> = GF(9)1194sage: R.<t> = FunctionField(k)1195sage: S.<X> = R[]1196sage: f = (1/t)*(X^3 - a*t^3)1197sage: f.factor()1198(1/t) * (X + (a + 2)*t)^31199sage: f.factor().prod() == f1200True1201"""1202F, d = self._to_bivariate_polynomial(f)1203fac = F.factor()1204x = f.parent().gen()1205t = f.parent().base_ring().gen()1206phi = F.parent().hom([x, t])1207v = [(phi(P),e) for P, e in fac]1208unit = phi(fac.unit())/d1209w = []1210for a, e in v:1211c = a.leading_coefficient()1212a = a/c1213unit *= (c**e)1214w.append((a,e))1215from sage.structure.factorization import Factorization1216return Factorization(w, unit=unit)12171218@cached_method1219def polynomial_ring(self, var='x'):1220"""1221Return a polynomial ring in one variable over this rational function field.12221223INPUT:12241225- ``var`` -- a string (default: 'x')12261227EXAMPLES::12281229sage: K.<x> = FunctionField(QQ)1230sage: K.polynomial_ring()1231Univariate Polynomial Ring in x over Rational function field in x over Rational Field1232sage: K.polynomial_ring('T')1233Univariate Polynomial Ring in T over Rational function field in x over Rational Field1234"""1235return self[var]12361237@cached_method1238def vector_space(self):1239"""1240Return a vector space V and isomorphisms self --> V and V --> self.12411242OUTPUT:12431244- ``V`` -- a vector space over the rational numbers1245- ``from_V`` -- an isomorphism from V to self1246- ``to_V`` -- an isomorphism from self to V12471248EXAMPLES::12491250sage: K.<x> = FunctionField(QQ)1251sage: K.vector_space()1252(Vector space of dimension 1 over Rational function field in x over Rational Field, Isomorphism morphism:1253From: Vector space of dimension 1 over Rational function field in x over Rational Field1254To: Rational function field in x over Rational Field, Isomorphism morphism:1255From: Rational function field in x over Rational Field1256To: Vector space of dimension 1 over Rational function field in x over Rational Field)1257"""1258V = self.base_field()**11259from maps import MapVectorSpaceToFunctionField, MapFunctionFieldToVectorSpace1260from_V = MapVectorSpaceToFunctionField(V, self)1261to_V = MapFunctionFieldToVectorSpace(self, V)1262return (V, from_V, to_V)12631264def random_element(self, *args, **kwds):1265"""1266Create a random element of this rational function field.1267Parameters are passed onto the random_element method of the1268underlying fraction field.12691270EXAMPLES::12711272sage: FunctionField(QQ,'alpha').random_element()1273(-1/2*alpha^2 - 4)/(-12*alpha^2 + 1/2*alpha - 1/95)1274"""1275return self(self._field.random_element(*args, **kwds))12761277def degree(self):1278"""1279Return the degree over the base field of this rational1280function field. Since the base field is the rational function1281field itself, the degree is 1.12821283EXAMPLES::12841285sage: K.<t> = FunctionField(QQ)1286sage: K.degree()128711288"""1289from sage.rings.integer_ring import ZZ1290return ZZ(1)12911292def gen(self, n=0):1293"""1294Return the ``n``-th generator of this function field. If ``n`` is not12950, then an IndexError is raised.12961297EXAMPLES::12981299sage: K.<t> = FunctionField(QQ); K.gen()1300t1301sage: K.gen().parent()1302Rational function field in t over Rational Field1303sage: K.gen(1)1304Traceback (most recent call last):1305...1306IndexError: Only one generator.1307"""1308if n != 0:1309raise IndexError, "Only one generator."1310return self._gen13111312def ngens(self):1313"""1314Return the number of generators, which is 1.13151316EXAMPLES::13171318sage: K.<t> = FunctionField(QQ)1319sage: K.ngens()132011321"""1322return 113231324def base_field(self):1325"""1326Return the base field of this rational function field, which is just1327this function field itself.13281329EXAMPLES::13301331sage: K.<t> = FunctionField(GF(7))1332sage: K.base_field()1333Rational function field in t over Finite Field of size 71334"""1335return self13361337def hom(self, im_gens, base_morphism=None):1338"""1339Create a homomorphism from self to another function field.13401341INPUT:13421343- ``im_gens`` -- exactly one element of some function field1344- ``base_morphism`` -- ignored13451346OUTPUT:13471348- a map between function fields13491350EXAMPLES:13511352We make a map from a rational function field to itself::13531354sage: K.<x> = FunctionField(GF(7))1355sage: K.hom( (x^4 + 2)/x)1356Morphism of function fields defined by x |--> (x^4 + 2)/x13571358We construct a map from a rational function field into a1359non-rational extension field::13601361sage: K.<x> = FunctionField(GF(7)); R.<y> = K[]1362sage: L.<y> = K.extension(y^3 + 6*x^3 + x)1363sage: f = K.hom(y^2 + y + 2); f1364Morphism of function fields defined by x |--> y^2 + y + 21365sage: f(x)1366y^2 + y + 21367sage: f(x^2)13685*y^2 + (x^3 + 6*x + 4)*y + 2*x^3 + 5*x + 41369"""1370from sage.structure.category_object import CategoryObject1371if isinstance(im_gens, CategoryObject):1372return self.Hom(im_gens).natural_map()1373if not isinstance(im_gens, (list,tuple)):1374im_gens = [im_gens]1375if len(im_gens) != 1:1376raise ValueError, "there must be exactly one generator"1377x = im_gens[0]1378from maps import FunctionFieldMorphism_rational1379return FunctionFieldMorphism_rational(self.Hom(x.parent()), x)13801381def field(self):1382"""1383Return the underlying field, forgetting the function field1384structure.13851386EXAMPLES::13871388sage: K.<t> = FunctionField(GF(7))1389sage: K.field()1390Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 71391"""1392return self._field13931394@cached_method1395def maximal_order(self):1396"""1397Return the maximal order of this function field. Since this1398is a rational function field it is of the form K(t), and the1399maximal order is by definition K[t].14001401EXAMPLES::14021403sage: K.<t> = FunctionField(QQ)1404sage: K.maximal_order()1405Maximal order in Rational function field in t over Rational Field1406sage: K.equation_order()1407Maximal order in Rational function field in t over Rational Field1408"""1409from function_field_order import FunctionFieldOrder_rational1410return FunctionFieldOrder_rational(self)14111412equation_order = maximal_order14131414def constant_base_field(self):1415"""1416Return the field that this rational function field is a1417transcendental extension of.14181419EXAMPLES::14201421sage: K.<t> = FunctionField(QQ)1422sage: K.constant_field()1423Rational Field14241425"""1426return self._constant_field14271428constant_field = constant_base_field14291430def genus(self):1431"""1432Return the genus of this function field1433This is always equal 0 for a rational function field14341435EXAMPLES::14361437sage: K.<x> = FunctionField(QQ);1438sage: K.genus()143901440"""1441return 01442144314441445