Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/rings/function_field/function_field.py
4036 views
1
r"""
2
Function Fields
3
4
AUTHORS:
5
6
- William Stein (2010): initial version
7
8
- Robert Bradshaw (2010-05-30): added is_finite()
9
10
- Julian Rueth (2011-06-08): fixed hom(), extension()
11
12
- Maarten Derickx (2011-09-11): added doctests
13
14
- Julian Rueth (2011-09-14): use @cached_method
15
16
EXAMPLES:
17
18
We create an extension of a rational function fields, and do some
19
simple arithmetic in it::
20
21
sage: K.<x> = FunctionField(GF(5^2,'a')); K
22
Rational function field in x over Finite Field in a of size 5^2
23
sage: R.<y> = K[]
24
sage: L.<y> = K.extension(y^3 - (x^3 + 2*x*y + 1/x)); L
25
Function field in y defined by y^3 + 3*x*y + (4*x^4 + 4)/x
26
sage: y^2
27
y^2
28
sage: y^3
29
2*x*y + (x^4 + 1)/x
30
sage: a = 1/y; a
31
(4*x/(4*x^4 + 4))*y^2 + 2*x^2/(4*x^4 + 4)
32
sage: a * y
33
1
34
35
We next make an extension of the above function field, illustrating
36
that arithmetic with a tower of 3 fields is fully supported::
37
38
sage: S.<t> = L[]
39
sage: M.<t> = L.extension(t^2 - x*y)
40
sage: M
41
Function field in t defined by t^2 + 4*x*y
42
sage: t^2
43
x*y
44
sage: 1/t
45
((1/(x^4 + 1))*y^2 + 2*x/(4*x^4 + 4))*t
46
sage: M.base_field()
47
Function field in y defined by y^3 + 3*x*y + (4*x^4 + 4)/x
48
sage: M.base_field().base_field()
49
Rational function field in x over Finite Field in a of size 5^2
50
51
TESTS::
52
53
sage: TestSuite(K).run()
54
sage: TestSuite(L).run() # long time (8s on sage.math, 2012)
55
sage: TestSuite(M).run() # long time (52s on sage.math, 2012)
56
57
The following two test suites do not pass ``_test_elements`` yet since
58
``R.an_element()`` has a ``_test_category`` method wich it should not have.
59
It is not the fault of the function field code so this will
60
be fixed in another ticket::
61
62
sage: TestSuite(R).run(skip = '_test_elements')
63
sage: TestSuite(S).run(skip = '_test_elements')
64
"""
65
#*****************************************************************************
66
# Copyright (C) 2010 William Stein <[email protected]>
67
# Copyright (C) 2010 Robert Bradshaw <[email protected]>
68
# Copyright (C) 2011 Julian Rueth <[email protected]>
69
# Copyright (C) 2011 Maarten Derickx <[email protected]>
70
#
71
# Distributed under the terms of the GNU General Public License (GPL)
72
# as published by the Free Software Foundation; either version 2 of
73
# the License, or (at your option) any later version.
74
# http://www.gnu.org/licenses/
75
#*****************************************************************************
76
77
from sage.rings.ring import Field
78
from function_field_element import FunctionFieldElement, FunctionFieldElement_rational, FunctionFieldElement_polymod
79
80
from sage.misc.cachefunc import cached_method
81
82
from sage.categories.function_fields import FunctionFields
83
CAT = FunctionFields()
84
85
def is_FunctionField(x):
86
"""
87
Return True if ``x`` is of function field type.
88
89
EXAMPLES::
90
91
sage: from sage.rings.function_field.function_field import is_FunctionField
92
sage: is_FunctionField(QQ)
93
False
94
sage: is_FunctionField(FunctionField(QQ,'t'))
95
True
96
"""
97
if isinstance(x, FunctionField): return True
98
return x in FunctionFields()
99
100
class FunctionField(Field):
101
"""
102
The abstract base class for all function fields.
103
104
EXAMPLES::
105
106
sage: K.<x> = FunctionField(QQ)
107
sage: isinstance(K, sage.rings.function_field.function_field.FunctionField)
108
True
109
"""
110
def some_elements(self):
111
"""
112
Return a list of elements in the function field.
113
114
EXAMPLES::
115
116
sage: K.<x> = FunctionField(QQ)
117
sage: elements = K.some_elements()
118
sage: elements # random output
119
[(x - 3/2)/(x^2 - 12/5*x + 1/18)]
120
sage: False in [e in K for e in elements]
121
False
122
"""
123
return [self.random_element(), self.random_element(), self.random_element()]
124
125
def characteristic(self):
126
"""
127
Return the characteristic of this function field.
128
129
EXAMPLES::
130
131
sage: K.<x> = FunctionField(QQ)
132
sage: K.characteristic()
133
0
134
sage: K.<x> = FunctionField(GF(7))
135
sage: K.characteristic()
136
7
137
sage: R.<y> = K[]
138
sage: L.<y> = K.extension(y^2-x)
139
sage: L.characteristic()
140
7
141
"""
142
return self.constant_base_field().characteristic()
143
144
def is_finite(self):
145
"""
146
Return whether this function field is finite, which it is not.
147
148
EXAMPLES::
149
150
sage: R.<t> = FunctionField(QQ)
151
sage: R.is_finite()
152
False
153
sage: R.<t> = FunctionField(GF(7))
154
sage: R.is_finite()
155
False
156
"""
157
return False
158
159
def extension(self, f, names=None):
160
"""
161
Create an extension L = K[y]/(f(y)) of a function field,
162
defined by a univariate polynomial in one variable over this
163
function field K.
164
165
INPUT:
166
167
- ``f`` -- a univariate polynomial over self
168
- ``names`` -- None or string or length-1 tuple
169
170
OUTPUT:
171
172
- a function field
173
174
EXAMPLES::
175
176
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
177
sage: K.extension(y^5 - x^3 - 3*x + x*y)
178
Function field in y defined by y^5 + x*y - x^3 - 3*x
179
180
A nonintegral defining polynomial::
181
182
sage: K.<t> = FunctionField(QQ); R.<y> = K[]
183
sage: K.extension(y^3 + (1/t)*y + t^3/(t+1))
184
Function field in y defined by y^3 + 1/t*y + t^3/(t + 1)
185
186
The defining polynomial need not be monic or integral::
187
188
sage: K.extension(t*y^3 + (1/t)*y + t^3/(t+1))
189
Function field in y defined by t*y^3 + 1/t*y + t^3/(t + 1)
190
"""
191
from constructor import FunctionField_polymod as FunctionField_polymod_Constructor
192
return FunctionField_polymod_Constructor(f, names)
193
194
def order_with_basis(self, basis, check=True):
195
"""
196
Return the order with given basis over the maximal order of
197
the base field.
198
199
INPUT:
200
201
- ``basis`` -- a list of elements of self
202
- ``check`` -- bool (default: True); if True, check that
203
the basis is really linearly independent and that the
204
module it spans is closed under multiplication, and
205
contains the identity element.
206
207
OUTPUT:
208
209
- an order in this function field
210
211
EXAMPLES::
212
213
sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<y> = K.extension(y^3 + x^3 + 4*x + 1)
214
sage: O = L.order_with_basis([1, y, y^2]); O
215
Order in Function field in y defined by y^3 + x^3 + 4*x + 1
216
sage: O.basis()
217
(1, y, y^2)
218
219
Note that 1 does not need to be an element of the basis, as long it is in the module spanned by it::
220
221
sage: O = L.order_with_basis([1+y, y, y^2]); O
222
Order in Function field in y defined by y^3 + x^3 + 4*x + 1
223
sage: O.basis()
224
(y + 1, y, y^2)
225
226
The following error is raised when the module spanned by the basis is not closed under multiplication::
227
228
sage: O = L.order_with_basis([1, x^2 + x*y, (2/3)*y^2]); O
229
Traceback (most recent call last):
230
...
231
ValueError: The module generated by basis [1, x*y + x^2, 2/3*y^2] must be closed under multiplication
232
233
and this happens when the identity is not in the module spanned by the basis::
234
235
sage: O = L.order_with_basis([x, x^2 + x*y, (2/3)*y^2])
236
Traceback (most recent call last):
237
...
238
ValueError: The identity element must be in the module spanned by basis [x, x*y + x^2, 2/3*y^2]
239
"""
240
from function_field_order import FunctionFieldOrder_basis
241
return FunctionFieldOrder_basis([self(a) for a in basis], check=check)
242
243
def order(self, x, check=True):
244
"""
245
Return the order in this function field generated over the
246
maximal order by x or the elements of x if x is a list.
247
248
INPUT:
249
250
- ``x`` -- element of self, or a list of elements of self
251
- ``check`` -- bool (default: True); if True, check that
252
x really generates an order
253
254
EXAMPLES::
255
256
sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<y> = K.extension(y^3 + x^3 + 4*x + 1)
257
sage: O = L.order(y); O
258
Order in Function field in y defined by y^3 + x^3 + 4*x + 1
259
sage: O.basis()
260
(1, y, y^2)
261
262
sage: Z = K.order(x); Z
263
Order in Rational function field in x over Rational Field
264
sage: Z.basis()
265
(1,)
266
267
Orders with multiple generators, not yet supported::
268
269
sage: Z = K.order([x,x^2]); Z
270
Traceback (most recent call last):
271
...
272
NotImplementedError
273
"""
274
if not isinstance(x, (list, tuple)):
275
x = [x]
276
if len(x) == 1:
277
g = x[0]
278
basis = [self(1)]
279
for i in range(self.degree()-1):
280
basis.append(basis[-1]*g)
281
else:
282
raise NotImplementedError
283
return self.order_with_basis(basis, check=check)
284
285
def _coerce_map_from_(self, R):
286
"""
287
Return True if there is a coerce map from R to self.
288
289
EXAMPLES::
290
291
sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<y> = K.extension(y^3 + x^3 + 4*x + 1)
292
sage: L.equation_order()
293
Order in Function field in y defined by y^3 + x^3 + 4*x + 1
294
sage: L._coerce_map_from_(L.equation_order())
295
True
296
sage: L._coerce_map_from_(GF(7))
297
False
298
"""
299
from function_field_order import FunctionFieldOrder
300
if isinstance(R, FunctionFieldOrder) and R.fraction_field() == self:
301
return True
302
return False
303
304
class FunctionField_polymod(FunctionField):
305
"""
306
A function field defined by a univariate polynomial, as an
307
extension of the base field.
308
309
EXAMPLES:
310
311
We make a function field defined by a degree 5 polynomial over the
312
rational function field over the rational numbers::
313
314
sage: K.<x> = FunctionField(QQ)
315
sage: R.<y> = K[]
316
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L
317
Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
318
319
We next make a function field over the above nontrivial function
320
field L::
321
322
sage: S.<z> = L[]
323
sage: M.<z> = L.extension(z^2 + y*z + y); M
324
Function field in z defined by z^2 + y*z + y
325
sage: 1/z
326
((x/(-x^4 - 1))*y^4 - 2*x^2/(-x^4 - 1))*z - 1
327
sage: z * (1/z)
328
1
329
330
We drill down the tower of function fields::
331
332
sage: M.base_field()
333
Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
334
sage: M.base_field().base_field()
335
Rational function field in x over Rational Field
336
sage: M.base_field().base_field().constant_field()
337
Rational Field
338
sage: M.constant_base_field()
339
Rational Field
340
341
.. WARNING::
342
343
It is not checked if the polynomial used to define this function field is irreducible
344
Hence it is not guaranteed that this object really is a field!
345
This is illustrated below.
346
347
::
348
349
sage: K.<x>=FunctionField(QQ)
350
sage: R.<y> = K[]
351
sage: L.<y>=K.extension(x^2-y^2)
352
sage: (y-x)*(y+x)
353
0
354
sage: 1/(y-x)
355
1
356
sage: y-x==0; y+x==0
357
False
358
False
359
"""
360
def __init__(self, polynomial, names,
361
element_class = FunctionFieldElement_polymod,
362
category=CAT):
363
"""
364
Create a function field defined as an extension of another
365
function field by adjoining a root of a univariate polynomial.
366
367
INPUT:
368
369
- ``polynomial`` -- a univariate polynomial over a function field
370
- ``names`` -- variable names (as a tuple of length 1 or string)
371
- ``category`` -- a category (defaults to category of function fields)
372
373
EXAMPLES::
374
375
We create an extension of a function field::
376
377
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
378
sage: L = K.extension(y^5 - x^3 - 3*x + x*y); L
379
Function field in y defined by y^5 + x*y - x^3 - 3*x
380
381
Note the type::
382
383
sage: type(L)
384
<class 'sage.rings.function_field.function_field.FunctionField_polymod_with_category'>
385
386
We can set the variable name, which doesn't have to be y::
387
388
sage: L.<w> = K.extension(y^5 - x^3 - 3*x + x*y); L
389
Function field in w defined by y^5 + x*y - x^3 - 3*x
390
"""
391
from sage.rings.polynomial.all import is_Polynomial
392
if polynomial.parent().ngens()>1 or not is_Polynomial(polynomial):
393
raise TypeError, "polynomial must be univariate a polynomial"
394
if names is None:
395
names = (polynomial.variable_name(), )
396
if polynomial.degree() <= 0:
397
raise ValueError, "polynomial must have positive degree"
398
base_field = polynomial.base_ring()
399
if not isinstance(base_field, FunctionField):
400
raise TypeError, "polynomial must be over a FunctionField"
401
self._element_class = element_class
402
self._element_init_pass_parent = False
403
self._base_field = base_field
404
self._polynomial = polynomial
405
406
Field.__init__(self, base_field,
407
names=names, category = category)
408
409
self._hash = hash(polynomial)
410
self._ring = self._polynomial.parent()
411
self._populate_coercion_lists_(coerce_list=[base_field, self._ring])
412
self._gen = self(self._ring.gen())
413
414
def __reduce__(self):
415
"""
416
Returns the arguments which were used to create this instance. The rationale for this is explained in the documentation of ``UniqueRepresentation``.
417
418
EXAMPLES::
419
420
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
421
sage: L = K.extension(y^2-x)
422
sage: clazz,args = L.__reduce__()
423
sage: clazz(*args)
424
Function field in y defined by y^2 - x
425
"""
426
from constructor import FunctionField_polymod as FunctionField_polymod_Constructor
427
return FunctionField_polymod_Constructor, (self._polynomial, self._names)
428
429
def __hash__(self):
430
"""
431
Return hash of this function field.
432
433
EXAMPLES::
434
435
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
436
sage: L = K.extension(y^5 - x^3 - 3*x + x*y); hash(L)
437
3183366741743088279 # 64-bit
438
2003022487 # 32-bit
439
"""
440
return self._hash
441
442
def monic_integral_model(self, names):
443
"""
444
Return a function field isomorphic to self, but with defining
445
polynomial that is monic and integral over the base field.
446
447
INPUT:
448
449
- ``names`` -- name of the generator of the new field this function constructs
450
451
EXAMPLES::
452
453
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
454
sage: L.<y> = K.extension(x^2*y^5 - 1/x); L
455
Function field in y defined by x^2*y^5 - 1/x
456
sage: A, from_A, to_A = L.monic_integral_model('z')
457
sage: A
458
Function field in z defined by y^5 - x^12
459
sage: from_A
460
Morphism of function fields defined by z |--> x^3*y
461
sage: to_A
462
Morphism of function fields defined by y |--> 1/x^3*z
463
sage: to_A(y)
464
1/x^3*z
465
sage: from_A(to_A(y))
466
y
467
sage: from_A(to_A(1/y))
468
x^3*y^4
469
sage: from_A(to_A(1/y)) == 1/y
470
True
471
"""
472
g, d = self._make_monic_integral(self.polynomial())
473
R = self.base_field()
474
K = R.extension(g, names=names)
475
to_K = self.hom(K.gen() / d)
476
from_K = K.hom(self.gen() * d)
477
return K, from_K, to_K
478
479
def _make_monic_integral(self, f):
480
r"""
481
Let y be a root of ``f``. This function returns a monic
482
integral polynomial g and an element d of the base field such
483
that g(y*d)=0.
484
485
EXAMPLES::
486
487
sage: K.<x> = FunctionField(QQ); R.<y> = K[];
488
sage: L.<y> = K.extension(x^2*y^5 - 1/x)
489
sage: g, d = L._make_monic_integral(L.polynomial()); g,d
490
(y^5 - x^12, x^3)
491
sage: (y*d).is_integral()
492
True
493
sage: g.is_monic()
494
True
495
sage: g(y*d)
496
0
497
"""
498
R = f.base_ring()
499
if not isinstance(R, RationalFunctionField):
500
raise NotImplementedError
501
502
# make f monic
503
n = f.degree()
504
c = f.leading_coefficient()
505
if c != 1:
506
f = f / c
507
508
# find lcm of denominators
509
from sage.rings.arith import lcm
510
# would be good to replace this by minimal...
511
d = lcm([b.denominator() for b in f.list() if b])
512
if d != 1:
513
x = f.parent().gen()
514
g = (d**n) * f(x/d)
515
else:
516
g = f
517
return g, d
518
519
def constant_field(self):
520
"""
521
Return the algebraic closure of the constant field of the base
522
field in this function field.
523
524
EXAMPLES::
525
526
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
527
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
528
sage: L.constant_field()
529
Traceback (most recent call last):
530
...
531
NotImplementedError
532
"""
533
raise NotImplementedError
534
535
def constant_base_field(self):
536
"""
537
Return the constant field of the base rational function field.
538
539
EXAMPLES::
540
541
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
542
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L
543
Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
544
sage: L.constant_base_field()
545
Rational Field
546
sage: S.<z> = L[]
547
sage: M.<z> = L.extension(z^2 - y)
548
sage: M.constant_base_field()
549
Rational Field
550
"""
551
return self.base_field().constant_base_field()
552
553
def degree(self):
554
"""
555
Return the degree of this function field over its base
556
function field.
557
558
EXAMPLES::
559
560
sage: K.<x> = FunctionField(QQ)
561
sage: R.<y> = K[]
562
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L
563
Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
564
sage: L.degree()
565
5
566
"""
567
return self._polynomial.degree()
568
569
def _repr_(self):
570
"""
571
Return string representation of this function field.
572
573
EXAMPLES::
574
575
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
576
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
577
sage: L._repr_()
578
'Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x'
579
"""
580
return "Function field in %s defined by %s"%(self.variable_name(), self._polynomial)
581
582
def base_field(self):
583
"""
584
Return the base field of this function field. This function
585
field is presented as L = K[y]/(f(y)), and the base field is
586
by definition the field K.
587
588
EXAMPLES::
589
590
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
591
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
592
sage: L.base_field()
593
Rational function field in x over Rational Field
594
"""
595
return self._base_field
596
597
def random_element(self, *args, **kwds):
598
"""
599
Create a random element of this function field. Parameters
600
are passed onto the random_element method of the base_field.
601
602
EXAMPLES::
603
604
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
605
sage: L.<y> = K.extension(y^2 - (x^2 + x))
606
sage: L.random_element() # random
607
((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)
608
"""
609
return self(self._ring.random_element(degree=self.degree(), *args, **kwds))
610
611
def polynomial(self):
612
"""
613
Return the univariate polynomial that defines this function
614
field, i.e., the polynomial f(y) so that this function field
615
is of the form K[y]/(f(y)).
616
617
EXAMPLES::
618
619
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
620
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
621
sage: L.polynomial()
622
y^5 - 2*x*y + (-x^4 - 1)/x
623
"""
624
return self._polynomial
625
626
def polynomial_ring(self):
627
"""
628
Return the polynomial ring used to represent elements of this
629
function field. If we view this function field as being presented
630
as K[y]/(f(y)), then this function returns the ring K[y].
631
632
EXAMPLES::
633
634
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
635
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
636
sage: L.polynomial_ring()
637
Univariate Polynomial Ring in y over Rational function field in x over Rational Field
638
"""
639
return self._ring
640
641
@cached_method
642
def vector_space(self):
643
"""
644
Return a vector space V and isomorphisms self --> V and V --> self.
645
646
This function allows us to identify the elements of self with
647
elements of a vector space over the base field, which is
648
useful for representation and arithmetic with orders, ideals,
649
etc.
650
651
OUTPUT:
652
653
- ``V`` -- a vector space over base field
654
- ``from_V`` -- an isomorphism from V to self
655
- ``to_V`` -- an isomorphism from self to V
656
657
EXAMPLES:
658
659
We define a function field::
660
661
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
662
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L
663
Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
664
665
We get the vector spaces, and maps back and forth::
666
667
sage: V, from_V, to_V = L.vector_space()
668
sage: V
669
Vector space of dimension 5 over Rational function field in x over Rational Field
670
sage: from_V
671
Isomorphism morphism:
672
From: Vector space of dimension 5 over Rational function field in x over Rational Field
673
To: Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
674
sage: to_V
675
Isomorphism morphism:
676
From: Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
677
To: Vector space of dimension 5 over Rational function field in x over Rational Field
678
679
We convert an element of the vector space back to the function field::
680
681
sage: from_V(V.1)
682
y
683
684
We define an interesting element of the function field::
685
686
sage: a = 1/L.0; a
687
(-x/(-x^4 - 1))*y^4 + 2*x^2/(-x^4 - 1)
688
689
We convert it to the vector space, and get a vector over the base field::
690
691
sage: to_V(a)
692
(2*x^2/(-x^4 - 1), 0, 0, 0, -x/(-x^4 - 1))
693
694
We convert to and back, and get the same element::
695
696
sage: from_V(to_V(a)) == a
697
True
698
699
In the other direction::
700
701
sage: v = x*V.0 + (1/x)*V.1
702
sage: to_V(from_V(v)) == v
703
True
704
705
And we show how it works over an extension of an extension field::
706
707
sage: R2.<z> = L[]; M.<z> = L.extension(z^2 -y)
708
sage: M.vector_space()
709
(Vector space of dimension 2 over Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x, Isomorphism morphism:
710
From: Vector space of dimension 2 over Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
711
To: Function field in z defined by z^2 - y, Isomorphism morphism:
712
From: Function field in z defined by z^2 - y
713
To: Vector space of dimension 2 over Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x)
714
"""
715
V = self.base_field()**self.degree()
716
from maps import MapVectorSpaceToFunctionField, MapFunctionFieldToVectorSpace
717
from_V = MapVectorSpaceToFunctionField(V, self)
718
to_V = MapFunctionFieldToVectorSpace(self, V)
719
return (V, from_V, to_V)
720
721
def maximal_order(self):
722
"""
723
Return the maximal_order of self. If we view self as L =
724
K[y]/(f(y)), then this is the ring of elements of L that are
725
integral over K.
726
727
EXAMPLES:
728
729
This is not yet implemented...::
730
731
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
732
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
733
sage: L.maximal_order()
734
Traceback (most recent call last):
735
...
736
NotImplementedError
737
"""
738
raise NotImplementedError
739
740
def _element_constructor_(self, x):
741
r"""
742
Make ``x`` into an element of this function field, possibly not canonically.
743
744
INPUT:
745
746
- ``x`` -- the element
747
748
OUTPUT:
749
750
``x``, as an element of this function field
751
752
TESTS::
753
754
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
755
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
756
sage: L._element_constructor_(L.polynomial_ring().gen())
757
y
758
"""
759
if x.parent() is self._ring:
760
return FunctionFieldElement_polymod(self, x)
761
if isinstance(x, FunctionFieldElement):
762
return FunctionFieldElement_polymod(self, self._ring(x.element()))
763
return FunctionFieldElement_polymod(self, self._ring(x))
764
765
def gen(self, n=0):
766
"""
767
Return the ``n``-th generator of this function field. By default ``n`` is 0; any other
768
value of ``n`` leads to an error. The generator is the class of y, if we view
769
self as being presented as K[y]/(f(y)).
770
771
EXAMPLES::
772
773
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
774
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
775
sage: L.gen()
776
y
777
sage: L.gen(1)
778
Traceback (most recent call last):
779
...
780
IndexError: Only one generator.
781
"""
782
if n != 0: raise IndexError, "Only one generator."
783
return self._gen
784
785
def ngens(self):
786
"""
787
Return the number of generators of this function field over
788
its base field. This is by definition 1.
789
790
EXAMPLES::
791
792
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
793
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
794
sage: L.ngens()
795
1
796
"""
797
return 1
798
799
def equation_order(self):
800
"""
801
If we view self as being presented as K[y]/(f(y)), then this
802
function returns the order generated by the class of y. If f
803
is not monic, then :meth:`_make_monic_integral` is called, and instead we
804
get the order generated by some integral multiple of a root of f.
805
806
EXAMPLES::
807
808
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
809
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
810
sage: O = L.equation_order()
811
sage: O.basis()
812
(1, x*y, x^2*y^2, x^3*y^3, x^4*y^4)
813
814
We try an example, in which the defining polynomial is not
815
monic and is not integral::
816
817
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
818
sage: L.<y> = K.extension(x^2*y^5 - 1/x); L
819
Function field in y defined by x^2*y^5 - 1/x
820
sage: O = L.equation_order()
821
sage: O.basis()
822
(1, x^3*y, x^6*y^2, x^9*y^3, x^12*y^4)
823
"""
824
d = self._make_monic_integral(self.polynomial())[1]
825
return self.order(d*self.gen(), check=False)
826
827
def hom(self, im_gens, base_morphism=None):
828
"""
829
Create a homomorphism from self to another function field.
830
831
INPUT:
832
833
- ``im_gens`` -- a list of images of the generators of self
834
and of successive base rings.
835
836
- ``base_morphism`` -- (default: None) a homomorphism of
837
the base ring, after the im_gens are used. Thus if
838
im_gens has length 2, then base_morphism should be a morphism
839
from self.base_ring().base_ring().
840
841
EXAMPLES:
842
843
We create a rational function field, and a quadratic extension of it::
844
845
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
846
sage: L.<y> = K.extension(y^2 - x^3 - 1)
847
848
We make the field automorphism that sends y to -y::
849
850
sage: f = L.hom(-y); f
851
Morphism of function fields defined by y |--> -y
852
853
Evaluation works::
854
855
sage: f(y*x - 1/x)
856
-x*y - 1/x
857
858
We try to define an invalid morphism::
859
860
sage: f = L.hom(y+1)
861
Traceback (most recent call last):
862
...
863
ValueError: invalid morphism
864
865
We make a morphism of the base rational function field::
866
867
sage: phi = K.hom(x+1); phi
868
Morphism of function fields defined by x |--> x + 1
869
sage: phi(x^3 - 3)
870
x^3 + 3*x^2 + 3*x - 2
871
sage: (x+1)^3-3
872
x^3 + 3*x^2 + 3*x - 2
873
874
We make a morphism by specifying where the generators and the
875
base generators go::
876
877
sage: L.hom([-y, x])
878
Morphism of function fields defined by y |--> -y, x |--> x
879
880
The usage of the keyword base_morphism is not implemented yet::
881
882
sage: L.hom([-y, x-1], base_morphism=phi)
883
Traceback (most recent call last):
884
...
885
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.
886
887
We make another extension of a rational function field::
888
889
sage: K2.<t> = FunctionField(QQ); R2.<w> = K2[]
890
sage: L2.<w> = K2.extension((4*w)^2 - (t+1)^3 - 1)
891
892
We define a morphism, by giving the images of generators::
893
894
sage: f = L.hom([4*w, t+1]); f
895
Morphism of function fields defined by y |--> 4*w, x |--> t + 1
896
897
Evaluation works, as expected::
898
899
sage: f(y+x)
900
4*w + t + 1
901
sage: f(x*y + x/(x^2+1))
902
(4*t + 4)*w + (t + 1)/(t^2 + 2*t + 2)
903
904
We make another extension of a rational function field::
905
906
sage: K3.<yy> = FunctionField(QQ); R3.<xx> = K3[]
907
sage: L3.<xx> = K3.extension(yy^2 - xx^3 - 1)
908
909
This is the function field L with the generators exchanged. We define a morphism to L::
910
911
sage: g = L3.hom([x,y]); g
912
Morphism of function fields defined by xx |--> x, yy |--> y
913
"""
914
if base_morphism is not None:
915
raise 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."
916
917
if not isinstance(im_gens, (list,tuple)):
918
im_gens = [im_gens]
919
if len(im_gens) == 0:
920
raise ValueError, "no images specified"
921
922
if len(im_gens) > 1:
923
base_morphism = self.base_field().hom(im_gens[1:], base_morphism)
924
925
# the codomain of this morphism is the field containing all the im_gens
926
codomain = im_gens[0].parent();
927
if base_morphism is not None:
928
if base_morphism.codomain().has_coerce_map_from(codomain):
929
codomain = base_morphism.codomain();
930
931
from maps import FunctionFieldMorphism_polymod
932
return FunctionFieldMorphism_polymod(self.Hom(codomain), im_gens[0], base_morphism)
933
934
class RationalFunctionField(FunctionField):
935
"""
936
A rational function field K(t) in one variable, over an arbitrary
937
base field.
938
939
EXAMPLES::
940
941
sage: K.<t> = FunctionField(GF(3)); K
942
Rational function field in t over Finite Field of size 3
943
sage: K.gen()
944
t
945
sage: 1/t + t^3 + 5
946
(t^4 + 2*t + 1)/t
947
948
There are various ways to get at the underlying fields and rings
949
associated to a rational function field::
950
951
sage: K.<t> = FunctionField(GF(7))
952
sage: K.base_field()
953
Rational function field in t over Finite Field of size 7
954
sage: K.field()
955
Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7
956
sage: K.constant_field()
957
Finite Field of size 7
958
sage: K.maximal_order()
959
Maximal order in Rational function field in t over Finite Field of size 7
960
961
We define a morphism::
962
963
sage: K.<t> = FunctionField(QQ)
964
sage: L = FunctionField(QQ, 'tbar') # give variable name as second input
965
sage: K.hom(L.gen())
966
Morphism of function fields defined by t |--> tbar
967
"""
968
def __init__(self, constant_field, names,
969
element_class = FunctionFieldElement_rational,
970
category=CAT):
971
"""
972
Create a rational function field in one variable.
973
974
INPUT:
975
976
- ``constant_field`` -- an arbitrary field
977
- ``names`` -- a string or tuple of length 1
978
- ``category`` -- default: FunctionFields()
979
980
EXAMPLES::
981
982
sage: K.<t> = FunctionField(CC); K
983
Rational function field in t over Complex Field with 53 bits of precision
984
sage: K.category()
985
Category of function fields
986
sage: FunctionField(QQ[I], 'alpha')
987
Rational function field in alpha over Number Field in I with defining polynomial x^2 + 1
988
989
Must be over a field::
990
991
sage: FunctionField(ZZ, 't')
992
Traceback (most recent call last):
993
...
994
TypeError: constant_field must be a field
995
"""
996
if names is None:
997
raise ValueError, "variable name must be specified"
998
elif not isinstance(names, tuple):
999
names = (names, )
1000
if not constant_field.is_field():
1001
raise TypeError, "constant_field must be a field"
1002
self._element_class = element_class
1003
self._element_init_pass_parent = False
1004
Field.__init__(self, self, names=names, category = category)
1005
R = constant_field[names[0]]
1006
self._hash = hash((constant_field, names))
1007
self._constant_field = constant_field
1008
self._ring = R
1009
self._field = R.fraction_field()
1010
self._populate_coercion_lists_(coerce_list=[self._field])
1011
self._gen = self(R.gen())
1012
1013
def __reduce__(self):
1014
"""
1015
Returns the arguments which were used to create this instance. The rationale for this is explained in the documentation of ``UniqueRepresentation``.
1016
1017
EXAMPLES::
1018
1019
sage: K.<x> = FunctionField(QQ)
1020
sage: clazz,args = K.__reduce__()
1021
sage: clazz(*args)
1022
Rational function field in x over Rational Field
1023
"""
1024
from constructor import FunctionField
1025
return FunctionField, (self._constant_field, self._names)
1026
1027
def __hash__(self):
1028
"""
1029
Return hash of this function field.
1030
1031
EXAMPLES::
1032
1033
sage: K.<t> = FunctionField(QQ)
1034
sage: hash(K)
1035
502145503910697533 # 64-bit
1036
-500688323 # 32-bit
1037
"""
1038
return self._hash
1039
1040
def _repr_(self):
1041
"""
1042
Return string representation of this function field.
1043
1044
EXAMPLES::
1045
1046
sage: K.<t> = FunctionField(QQ)
1047
sage: K._repr_()
1048
'Rational function field in t over Rational Field'
1049
"""
1050
return "Rational function field in %s over %s"%(
1051
self.variable_name(), self._constant_field)
1052
1053
def _element_constructor_(self, x):
1054
r"""
1055
Coerce ``x`` into an element of this function field, possibly not canonically.
1056
1057
INPUT:
1058
1059
- ``x`` -- the element
1060
1061
OUTPUT:
1062
1063
``x``, as an element of this function field
1064
1065
EXAMPLES::
1066
1067
sage: K.<t> = FunctionField(QQ)
1068
sage: a = K._element_constructor_(K.maximal_order().gen()); a
1069
t
1070
sage: a.parent()
1071
Rational function field in t over Rational Field
1072
1073
"""
1074
if x.parent() is self._field:
1075
return FunctionFieldElement_rational(self, x)
1076
if isinstance(x, FunctionFieldElement):
1077
return FunctionFieldElement_rational(self, self._field(x.element()))
1078
if x.parent() is self.polynomial_ring():
1079
return x[0]
1080
return FunctionFieldElement_rational(self, self._field(x))
1081
1082
def _to_bivariate_polynomial(self, f):
1083
"""
1084
Convert ``f`` from a univariate polynomial over the rational function
1085
field into a bivariate polynomial and a denominator.
1086
1087
INPUT:
1088
1089
- ``f`` -- a univariate polynomial over self.
1090
1091
OUTPUT:
1092
1093
- bivariate polynomial, denominator
1094
1095
EXAMPLES::
1096
1097
sage: R.<t> = FunctionField(GF(7))
1098
sage: S.<X> = R[]
1099
sage: f = (1/t)*(X^4 - 1/t^2)*(X^3 - t^3)
1100
sage: R._to_bivariate_polynomial(f)
1101
(X^7*t^2 - X^4*t^5 - X^3 + t^3, t^3)
1102
"""
1103
v = f.list()
1104
from sage.rings.arith import LCM
1105
denom = LCM([a.denominator() for a in v])
1106
S = denom.parent()
1107
x,t = S.base_ring()['%s,%s'%(f.parent().variable_name(),self.variable_name())].gens()
1108
phi = S.hom([t])
1109
return sum([phi((denom * v[i]).numerator()) * x**i for i in range(len(v))]), denom
1110
1111
def _factor_univariate_polynomial(self, f, proof=True):
1112
"""
1113
Factor the univariate polynomial ``f`` over self.
1114
1115
EXAMPLES::
1116
1117
We do a factorization over the function field over the rationals::
1118
1119
sage: R.<t> = FunctionField(QQ)
1120
sage: S.<X> = R[]
1121
sage: f = (1/t)*(X^4 - 1/t^2)*(X^3 - t^3)
1122
sage: f.factor() # indirect doctest
1123
(1/t) * (X - t) * (X^2 - 1/t) * (X^2 + 1/t) * (X^2 + t*X + t^2)
1124
sage: f.factor().prod() == f
1125
True
1126
1127
We do a factorization over a finite prime field::
1128
1129
sage: R.<t> = FunctionField(GF(7))
1130
sage: S.<X> = R[]
1131
sage: f = (1/t)*(X^4 - 1/t^2)*(X^3 - t^3)
1132
sage: f.factor()
1133
(1/t) * (X + 3*t) * (X + 5*t) * (X + 6*t) * (X^2 + 1/t) * (X^2 + 6/t)
1134
sage: f.factor().prod() == f
1135
True
1136
1137
Factoring over a function field over a non-prime finite field::
1138
1139
sage: k.<a> = GF(9)
1140
sage: R.<t> = FunctionField(k)
1141
sage: S.<X> = R[]
1142
sage: f = (1/t)*(X^3 - a*t^3)
1143
sage: f.factor()
1144
(1/t) * (X + (a + 2)*t)^3
1145
sage: f.factor().prod() == f
1146
True
1147
"""
1148
F, d = self._to_bivariate_polynomial(f)
1149
fac = F.factor()
1150
x = f.parent().gen()
1151
t = f.parent().base_ring().gen()
1152
phi = F.parent().hom([x, t])
1153
v = [(phi(P),e) for P, e in fac]
1154
unit = phi(fac.unit())/d
1155
w = []
1156
for a, e in v:
1157
c = a.leading_coefficient()
1158
a = a/c
1159
unit *= (c**e)
1160
w.append((a,e))
1161
from sage.structure.factorization import Factorization
1162
return Factorization(w, unit=unit)
1163
1164
@cached_method
1165
def polynomial_ring(self, var='x'):
1166
"""
1167
Return a polynomial ring in one variable over this rational function field.
1168
1169
INPUT:
1170
1171
- ``var`` -- a string (default: 'x')
1172
1173
EXAMPLES::
1174
1175
sage: K.<x> = FunctionField(QQ)
1176
sage: K.polynomial_ring()
1177
Univariate Polynomial Ring in x over Rational function field in x over Rational Field
1178
sage: K.polynomial_ring('T')
1179
Univariate Polynomial Ring in T over Rational function field in x over Rational Field
1180
"""
1181
return self[var]
1182
1183
@cached_method
1184
def vector_space(self):
1185
"""
1186
Return a vector space V and isomorphisms self --> V and V --> self.
1187
1188
OUTPUT:
1189
1190
- ``V`` -- a vector space over the rational numbers
1191
- ``from_V`` -- an isomorphism from V to self
1192
- ``to_V`` -- an isomorphism from self to V
1193
1194
EXAMPLES::
1195
1196
sage: K.<x> = FunctionField(QQ)
1197
sage: K.vector_space()
1198
(Vector space of dimension 1 over Rational function field in x over Rational Field, Isomorphism morphism:
1199
From: Vector space of dimension 1 over Rational function field in x over Rational Field
1200
To: Rational function field in x over Rational Field, Isomorphism morphism:
1201
From: Rational function field in x over Rational Field
1202
To: Vector space of dimension 1 over Rational function field in x over Rational Field)
1203
"""
1204
V = self.base_field()**1
1205
from maps import MapVectorSpaceToFunctionField, MapFunctionFieldToVectorSpace
1206
from_V = MapVectorSpaceToFunctionField(V, self)
1207
to_V = MapFunctionFieldToVectorSpace(self, V)
1208
return (V, from_V, to_V)
1209
1210
def random_element(self, *args, **kwds):
1211
"""
1212
Create a random element of this rational function field.
1213
Parameters are passed onto the random_element method of the
1214
underlying fraction field.
1215
1216
EXAMPLES::
1217
1218
sage: FunctionField(QQ,'alpha').random_element()
1219
(-1/2*alpha^2 - 4)/(-12*alpha^2 + 1/2*alpha - 1/95)
1220
"""
1221
return self(self._field.random_element(*args, **kwds))
1222
1223
def degree(self):
1224
"""
1225
Return the degree over the base field of this rational
1226
function field. Since the base field is the rational function
1227
field itself, the degree is 1.
1228
1229
EXAMPLES::
1230
1231
sage: K.<t> = FunctionField(QQ)
1232
sage: K.degree()
1233
1
1234
"""
1235
from sage.rings.integer_ring import ZZ
1236
return ZZ(1)
1237
1238
def gen(self, n=0):
1239
"""
1240
Return the ``n``-th generator of this function field. If ``n`` is not
1241
0, then an IndexError is raised.
1242
1243
EXAMPLES::
1244
1245
sage: K.<t> = FunctionField(QQ); K.gen()
1246
t
1247
sage: K.gen().parent()
1248
Rational function field in t over Rational Field
1249
sage: K.gen(1)
1250
Traceback (most recent call last):
1251
...
1252
IndexError: Only one generator.
1253
"""
1254
if n != 0:
1255
raise IndexError, "Only one generator."
1256
return self._gen
1257
1258
def ngens(self):
1259
"""
1260
Return the number of generators, which is 1.
1261
1262
EXAMPLES::
1263
1264
sage: K.<t> = FunctionField(QQ)
1265
sage: K.ngens()
1266
1
1267
"""
1268
return 1
1269
1270
def base_field(self):
1271
"""
1272
Return the base field of this rational function field, which is just
1273
this function field itself.
1274
1275
EXAMPLES::
1276
1277
sage: K.<t> = FunctionField(GF(7))
1278
sage: K.base_field()
1279
Rational function field in t over Finite Field of size 7
1280
"""
1281
return self
1282
1283
def hom(self, im_gens, base_morphism=None):
1284
"""
1285
Create a homomorphism from self to another function field.
1286
1287
INPUT:
1288
1289
- ``im_gens`` -- exactly one element of some function field
1290
- ``base_morphism`` -- ignored
1291
1292
OUTPUT:
1293
1294
- a map between function fields
1295
1296
EXAMPLES:
1297
1298
We make a map from a rational function field to itself::
1299
1300
sage: K.<x> = FunctionField(GF(7))
1301
sage: K.hom( (x^4 + 2)/x)
1302
Morphism of function fields defined by x |--> (x^4 + 2)/x
1303
1304
We construct a map from a rational function field into a
1305
non-rational extension field::
1306
1307
sage: K.<x> = FunctionField(GF(7)); R.<y> = K[]
1308
sage: L.<y> = K.extension(y^3 + 6*x^3 + x)
1309
sage: f = K.hom(y^2 + y + 2); f
1310
Morphism of function fields defined by x |--> y^2 + y + 2
1311
sage: f(x)
1312
y^2 + y + 2
1313
sage: f(x^2)
1314
5*y^2 + (x^3 + 6*x + 4)*y + 2*x^3 + 5*x + 4
1315
"""
1316
from sage.structure.category_object import CategoryObject
1317
if isinstance(im_gens, CategoryObject):
1318
return self.Hom(im_gens).natural_map()
1319
if not isinstance(im_gens, (list,tuple)):
1320
im_gens = [im_gens]
1321
if len(im_gens) != 1:
1322
raise ValueError, "there must be exactly one generator"
1323
x = im_gens[0]
1324
from maps import FunctionFieldMorphism_rational
1325
return FunctionFieldMorphism_rational(self.Hom(x.parent()), x)
1326
1327
def field(self):
1328
"""
1329
Return the underlying field, forgetting the function field
1330
structure.
1331
1332
EXAMPLES::
1333
1334
sage: K.<t> = FunctionField(GF(7))
1335
sage: K.field()
1336
Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7
1337
"""
1338
return self._field
1339
1340
@cached_method
1341
def maximal_order(self):
1342
"""
1343
Return the maximal order of this function field. Since this
1344
is a rational function field it is of the form K(t), and the
1345
maximal order is by definition K[t].
1346
1347
EXAMPLES::
1348
1349
sage: K.<t> = FunctionField(QQ)
1350
sage: K.maximal_order()
1351
Maximal order in Rational function field in t over Rational Field
1352
sage: K.equation_order()
1353
Maximal order in Rational function field in t over Rational Field
1354
"""
1355
from function_field_order import FunctionFieldOrder_rational
1356
return FunctionFieldOrder_rational(self)
1357
1358
equation_order = maximal_order
1359
1360
def constant_base_field(self):
1361
"""
1362
Return the field that this rational function field is a
1363
transcendental extension of.
1364
1365
EXAMPLES::
1366
1367
sage: K.<t> = FunctionField(QQ)
1368
sage: K.constant_field()
1369
Rational Field
1370
1371
"""
1372
return self._constant_field
1373
1374
constant_field = constant_base_field
1375
1376