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