vector-bundles-sagemath/vector_bundle/function_field_utility.py

467 lines
15 KiB
Python

###########################################################################
# Copyright (C) 2024 Mickaël Montessinos (mickael.montessinos@mif.vu.lt),#
# #
# Distributed under the terms of the GNU General Public License (GPL) #
# either version 3, or (at your option) any later version #
# #
# http://www.gnu.org/licenses/ #
###########################################################################
from sage.matrix.constructor import matrix
from sage.rings.infinity import Infinity
from copy import copy
from sage.misc.cachefunc import cached_function
from sage.misc.misc_c import prod
from sage.matrix.constructor import matrix
from sage.matrix.special import block_matrix, elementary_matrix,\
identity_matrix
from sage.rings.function_field.function_field_rational\
import RationalFunctionField
from sage.rings.function_field.order_rational\
import FunctionFieldMaximalOrderInfinite_rational
@cached_function
def all_infinite_places(K):
r"""
Return a list of the infinite places of K of all degrees
INPUT:
- ``K`` -- FunctionField
"""
if isinstance(K,RationalFunctionField):
return [K.gen().poles()[0]]
deg = K.degree()
return sum([K.places_infinite(degree = deg) for deg in range(1, deg + 1)],
[])
def infinite_valuation(a):
r"""
Returns the valuation -deg of an element of a rational function field
The degree method returns the "height" of the element.
EXAMPLES:
sage: from vector_bundle.function_field_utility import infinite_valuation
sage: F.<x> = FunctionField(GF(3))
sage: infinite_valuation(x**-1 + x**-2)
1
"""
if a == 0:
return Infinity
return a.denominator().degree() - a.numerator().degree()
def infinite_mod(a,i):
r"""
Returns a mod x**-i
EXAMPLES:
sage: from vector_bundle.function_field_utility import infinite_mod
sage: K.<x> = FunctionField(GF(3))
sage: infinite_mod(x**-1 + x**-3,2)
1/x
"""
x = a.parent().gen()
b = a * x**(i-1)
return x**(1-i) * (b.numerator() // b.denominator())
def infinite_integral_matrix(mat):
r"""
Return an matrix with coefficient in the infinite maximal order and its denominator.
INPUT:
- ``mat`` -- Matrix with coefficients in a rational function field K
OUTPUT:
- ``int_mat`` -- Matrix with coefficients in K.maximal_order_infinite()
- ``den`` -- Element of K.maximal_order_infinite such that mat = int_mat/den
EXAMPLES:
sage: from vector_bundle.function_field_utility import infinite_integral_matrix
sage: F.<x> = FunctionField(GF(11))
sage: mat = matrix([[x, 1], [x**-1, 2]])
sage: infinite_integral_matrix(mat)
(
[ 1 1/x]
[1/x^2 2/x], 1/x
)
"""
K = mat[0,0].parent()
if isinstance(K,FunctionFieldMaximalOrderInfinite_rational):
return mat,1
if not isinstance(K,RationalFunctionField):
raise ValueError('mat must have coefficients in a rational function'
+ 'field or its infinite maximal order')
x = K.gen()
R = K.maximal_order_infinite()
den = x**min([infinite_valuation(e) for e in mat.list()])
int_mat = matrix(R,mat.nrows(),mat.ncols(),(den*mat).list())
return int_mat, den
def infinite_hermite_form(mat,include_zero_cols=True,transformation=False):
r"""
Return the hermite form of a matrix with coefficient in a rational infinite maximal order.
EXAMPLE:
sage: from vector_bundle.function_field_utility import infinite_hermite_form
sage: K.<x> = FunctionField(GF(3))
sage: R = K.maximal_order_infinite()
sage: mat = matrix(R,[[1, x**-1, x**-2, (x**3+1) / x**3], [(2*x+2) / (x**3+2), x**-2, (x**2+2) / (x**4+1), 1]])
sage: H,T = infinite_hermite_form(mat,transformation=True); H
[0 0 1 0]
[0 0 0 1]
sage: mat*T == H
True
TESTS:
sage: F.<x> = FunctionField(GF(3))
sage: R = F.maximal_order_infinite()
sage: mat = matrix(R,[[x**-1, 0, 2, 1], [0, x**-1, 1, 1], [0, 0, 1, 0], [0, 0, 0, 1]])
sage: infinite_hermite_form(mat) == mat
True
"""
R = mat.base_ring()
if not isinstance(R,FunctionFieldMaximalOrderInfinite_rational):
raise ValueError('mat must have base ring a rational infinite maximal'
+ ' order.')
n = mat.nrows()
r = mat.ncols()
x = R.function_field().gen()
H = copy(mat)
T = identity_matrix(R,r)
#First, make mat upper triangular with diagonal coefficient of the form
#x**-k.
for i in range(1,n+1):
degs = [infinite_valuation(H[-i,j]) for j in range(r+1-i)]
d0 = min(degs)
j0 = degs.index(d0)
E = elementary_matrix(R,r,row1=j0,row2=r-i)
T *= E
H *= E
E = elementary_matrix(R,r,row1=r-i,scale=(x**d0 * H[-i,-i])**-1)
T *= E
H *= E
for j in range(r-i):
E = elementary_matrix(R,r,row1=r-i,row2=j,scale=-H[-i,j]/H[-i,-i])
T *= E
H *= E
for i in range(2,n+1):
d = infinite_valuation(H[-i,-i])
for j in range(1,i):
E = elementary_matrix(
R,r,row1=r-i,row2=r-j,
scale=(infinite_mod(H[-i,-j],d)-H[-i,-j])/H[-i,-i])
T *= E
H *= E
if not include_zero_cols:
H = H[:,r-n:]
if transformation:
return H,T
return H
def infinite_ideal_hnf(I,transformation=False):
r"""
Return the Hermite form of an ideal of the infinite maximal order.
"""
O = I.ring()
K = O.function_field()
x = K.gen()
F = K.base_field()
R = F.maximal_order_infinite()
n = K.degree()
order_basis = O.basis()
order_matrix = matrix(R,[gen.list() for gen in O.basis()]).transpose()
ideal_basis = I.gens_over_base();
ideal_matrix = order_matrix**-1 * matrix(F,[gen.list()
for gen in ideal_basis]).transpose()
mat,den = infinite_integral_matrix(ideal_matrix)
#This is awkward but if transformation is False, hnf,U = ().hermite_form()
#will unpack the matrix.
if transformation:
hnf,U = infinite_hermite_form(mat, transformation=True)
return hnf/den,U
hnf = infinite_hermite_form(mat)
return hnf/den
def infinite_order_xgcd(ideals):
r"""
Performs the extended gcd algorithm for ideals in the infinite order.
INPUT:
- ``ideals`` -- list of ideals over the infinite maximal order of a function field
OUTPUT:
- ``coeffs`` --- list of elements of the function field such that as[i] in ideals[i] and sum(as) = 1
ALGORITHM:
Proposition 1.3.7 from [Coh00]
EXAMPLES:
sage: from vector_bundle.function_field_utility import infinite_order_xgcd
sage: F.<x> = FunctionField(GF(3))
sage: R.<y> = F[]
sage: K.<y> = F.extension(y**2 - x**-5 - 1)
sage: primes = [p.prime_ideal() for p in K.places_infinite()]; len(primes)
2
sage: a = infinite_order_xgcd(primes); a
[2*y + 2, y + 2]
sage: sum(a)
1
sage: all([a[i] in primes[i] for i in range(2)])
True
"""
order_basis = ideals[0].ring().basis()
if order_basis[0] != 1:
raise ValueError('The first element of the basis of the order should'
+ ' be 1.')
n = len(order_basis)
k = len(ideals)
y = ideals[0].ring().function_field().gen()
ideals_hnf = [infinite_ideal_hnf(I) for I in ideals]
ideals_bases = [[sum([order_basis[i]*mat[i,j] for i in range(n)])
for j in range(n)]
for mat in ideals_hnf]
C = block_matrix([ideals_hnf])
C, den = infinite_integral_matrix(C)
H,U = infinite_hermite_form(C, include_zero_cols=False, transformation=True)
if not (H/den).is_one():
raise ValueError("The ideals should be coprime.")
v = U[:,-n].list()
return [sum([ideals_bases[i][j]*v[n*i+j] for j in range(n)]) for i in range(k)]
def infinite_approximation(places,valuations,residues):
r"""
Return a in the function field of places such that
(a - residues[i]) has valuation at least valuations[i] at places[i].
INPUT:
- ``places`` -- list of FunctionFieldPlace. Infinite places only.
- ``valuations`` -- list of integers of same length as places.
- ``residues`` -- list of elements of the function field.
ALGORITHM:
Proposition 1.3.11 from [Coh00]
"""
if len(places) == 1:
return residues[0]
valuations = [max(0,val) for val in valuations]
primes = [place.prime_ideal() for place in places]
I = prod([prime**(val+1) for prime, val in zip(primes, valuations)])
ideals = [I * prime**(-val-1)
for prime, val in zip(primes, valuations)]
coefficients = infinite_order_xgcd(ideals)
return sum([c * res for c,res in zip(coefficients,residues)])
@cached_function
def safe_uniformizer(K):
r"""
Return a safe uniformizer and an infinite place of self._function_field
A uniformizer is safe if its valuation at other infinite places is 0.
EXAMPLES:
sage: from vector_bundle.function_field_utility import safe_uniformizer
sage: F.<x> = FunctionField(GF(3))
sage: R.<y> = F[]
sage: K.<y> = F.extension(y^2 - x**-5 - 1)
sage: places = K.places_infinite()
sage: pi, place = safe_uniformizer(K); pi
((2*x + 1)/x)*y + (2*x + 2)/x
sage: place == places[0]
True
sage: pi.valuation(place)
1
sage: pi.valuation(places[1])
0
TESTS:
sage: from vector_bundle.function_field_utility import all_infinite_places
sage: F.<x> = FunctionField(GF(3))
sage: R.<y> = F[]
sage: K.<y> = F.extension(y^2 + x + 2)
sage: places = K.places_infinite()
sage: pi, place = safe_uniformizer(K); pi
1/x*y
sage: place == places[0]
True
sage: pi.valuation(place)
1
sage: R.<y> = F[]
sage: K.<y> = F.extension(y^4 + (2*x^2 + 2)/x^2)
sage: pi, _ = safe_uniformizer(K)
sage: [pi.valuation(place) for place in all_infinite_places(K)]
[1, 0, 0]
sage: safe_uniformizer(F)
(1/x, Place (1/x))
"""
places = all_infinite_places(K)
n = len(places)
return (infinite_approximation(
places,
[2] + ([1]*(n-1)),
[places[0].local_uniformizer()] + ([1]*(n-1))),
places[0])
def local_expansion(place,pi,f):
r"""
Return a function giving the i-th coefficient of the expansion of f.
This uses code from sage.rings.function_field.maps.FunctionFieldCompletion.
While somewhat redundant, it adds the possibility to chose the uniformizer
with respect to which the expansion is computed.
INPUT:
- ``place`` -- FunctionFieldPlace; the place at which to expand
- ``pi`` -- The uniformizer giving variable for the power series
- ``f`` -- The function to expand
OUTPUT:
- a function taking as input an integer i and returning the coefficient of degree i
EXAMPLES:
sage: from vector_bundle.function_field_utility import local_expansion
sage: from vector_bundle.function_field_utility import safe_uniformizer
sage: F.<x> = FunctionField(GF(3))
sage: R.<y> = F[]
sage: K.<y> = F.extension(y^2 - x**-5 - 1)
sage: pi, place = safe_uniformizer(K)
sage: f = 1 / (1-pi)
sage: exp = local_expansion(place, pi, f)
sage: all([exp(i) == 1 for i in range(20)])
True
"""
if f == 0:
return lambda i : 0
K = place.function_field()
der = K.higher_derivation()
k, _, to_k = place.residue_field()
val = f.valuation(place)
e = f * pi**(-val)
return lambda i : to_k(der._derive(e, i - val, pi)) if i >= val else 0
def residue(place,pi,f):
r"""
Return the residue of constant répartition f at place with respect
to local uniformizer pi.
"""
if pi.valuation(place) != 1:
raise ValueError('pi must be a local uniformizer at place')
k, _, _ = place.residue_field()
kc = place.function_field().constant_base_field()
exp = local_expansion(place,pi,f)
high_res = exp(-1)
return k.over(kc)(high_res).trace()
def invert_trace(field,base,target):
r"""
Find an element of trace 1 over base in field.
EXAMPLES:
sage: from vector_bundle.function_field_utility import invert_trace
sage: base = GF(9)
sage: field = GF(9**3)
sage: a = invert_trace(field, base, 1); a
2*z6^4 + 2*z6^3 + z6 + 1
sage: field.over(base)(a).trace()
1
"""
if field == base:
if target not in field:
raise ValueError('Since field = base, target should be an element'
+ ' of field')
return target
as_ext = field.over(base)
d = as_ext.degree(base)
t = as_ext.gen()
i = [(t**j).trace() != 0 for j in range(d)].index(True)
return field(target * t**i/((t**i).trace()))
def insert_row(mat,i,row):
r"""
Return matrix mat with row inserted in ith position.
EXAMPLES:
sage: from vector_bundle.function_field_utility import insert_row
sage: mat = matrix(GF(3), 2, 2, [1, 2, 2, 1])
sage: insert_row(mat, 1, [0, 1])
[1 2]
[0 1]
[2 1]
"""
return matrix([mat[j] for j in range(i)]
+ [row]
+ [mat[j] for j in range(i,mat.nrows())])
def norm(v):
r"""
Return the norm of vector v: the maximal degree of its coefficients.
Input:
- v -- vector with coefficients in a RationalFunctionField
EXAMPLES:
sage: from vector_bundle.function_field_utility import norm
sage: R.<x> = GF(3)[]
sage: v = vector([x^3 + 3 + 1, x^2])
sage: norm(v)
3
"""
return max([c.degree() for c in v.list()])
def smallest_norm_first(mat,i = 0,norms=[]):
r"""
Swap rows of M so that the i-th row has smaller norm than rows below.
INPUT:
``mat`` -- matrix with coefficients in a RationalFunctionField
``i`` -- integer (default: `0`)
EXAMPLES:
sage: from vector_bundle.function_field_utility import smallest_norm_first
sage: R.<x> = GF(3)[]
sage: mat = matrix([[1, 1], [x^2, x^3], [1, x]])
sage: smallest_norm_first(mat, 1)
[0, 1, 3]
sage: mat
[ 1 1]
[ 1 x]
[x^2 x^3]
"""
if norms == []:
norms = [norm(row) for row in mat]
j = norms[i:].index(min(norms[i:]))
mat.swap_rows(i,i+j)
n = norms[i]
norms[i] = norms[j+i]
norms[j+i] = n
return norms