Moved logic for computing matrix out of h1_element
This commit is contained in:
parent
6fd6176ff8
commit
9a51dfff7c
|
@ -57,7 +57,7 @@ def canonical_bundle(K):
|
|||
sage: L == trivial_bundle(K)
|
||||
True
|
||||
"""
|
||||
pi,_ = function_field_utility.safe_uniformizer(K)
|
||||
pi = function_field_utility.safe_uniformizers(K)[0]
|
||||
return VectorBundle(K, pi.differential().divisor())
|
||||
|
||||
def _euclid(a,b):
|
||||
|
|
|
@ -2,6 +2,9 @@ r"""
|
|||
Implementations of all sort of algorithms for function field that are not
|
||||
yet implemented in Sage.
|
||||
|
||||
A lot of code for the FunctionFieldCompletionCustom class comes directly
|
||||
from the sage source, and was written by Kwankyu Lee.
|
||||
|
||||
REFERENCE:
|
||||
.. [Coh00] H. Cohen
|
||||
Advanced topics in computational number theory
|
||||
|
@ -18,7 +21,9 @@ r"""
|
|||
###########################################################################
|
||||
|
||||
from sage.matrix.constructor import matrix
|
||||
from sage.rings.infinity import Infinity
|
||||
from sage.categories.map import Map
|
||||
from sage.modules.free_module_element import vector
|
||||
from sage.rings.infinity import infinity
|
||||
from copy import copy
|
||||
from sage.misc.cachefunc import cached_function
|
||||
from sage.misc.misc_c import prod
|
||||
|
@ -30,6 +35,7 @@ from sage.rings.function_field.function_field_rational\
|
|||
from sage.rings.function_field.order_rational\
|
||||
import FunctionFieldMaximalOrderInfinite_rational
|
||||
from sage.rings.function_field.order import FunctionFieldOrderInfinite
|
||||
from sage.rings.function_field.ideal import FunctionFieldIdealInfinite
|
||||
|
||||
@cached_function
|
||||
def all_infinite_places(K):
|
||||
|
@ -60,7 +66,7 @@ def infinite_valuation(a):
|
|||
1
|
||||
"""
|
||||
if a == 0:
|
||||
return Infinity
|
||||
return infinity
|
||||
return a.denominator().degree() - a.numerator().degree()
|
||||
|
||||
|
||||
|
@ -82,7 +88,7 @@ def infinite_mod(a,i):
|
|||
|
||||
def infinite_integral_matrix(mat):
|
||||
r"""
|
||||
Return an matrix with coefficient in the infinite maximal order and its denominator.
|
||||
Return a matrix with coefficient in the infinite maximal order and its denominator.
|
||||
|
||||
INPUT:
|
||||
|
||||
|
@ -289,55 +295,296 @@ def infinite_approximation(places,valuations,residues):
|
|||
|
||||
|
||||
@cached_function
|
||||
def safe_uniformizer(K):
|
||||
def safe_uniformizers(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: from vector_bundle.function_field_utility import safe_uniformizers
|
||||
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]
|
||||
sage: pis = safe_uniformizers(K)
|
||||
sage: all([(pi.valuation(place) == 1 and i == j) or (pi.valuation(place) == 0 and i != j) for (i,pi) in enumerate(pis) for (j, place) in enumerate(places)])
|
||||
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(
|
||||
return [infinite_approximation(
|
||||
places,
|
||||
[2] + ([1]*(n-1)),
|
||||
[places[0].local_uniformizer()] + ([1]*(n-1))),
|
||||
places[0])
|
||||
[2 if p == place else 1 for p in places],
|
||||
[place.local_uniformizer() if p == place else 1 for p in places])
|
||||
for place in places]
|
||||
|
||||
|
||||
class FunctionFieldCompletionCustom(Map):
|
||||
"""
|
||||
Completions on function fields.
|
||||
|
||||
Allows for choice of uniformizer.
|
||||
|
||||
INPUT:
|
||||
|
||||
- ``field`` -- function field
|
||||
|
||||
- ``place`` -- place of the function field
|
||||
|
||||
- ``pi`` -- a local uniformizer at place
|
||||
|
||||
- ``name`` -- string for the name of the series variable
|
||||
|
||||
- ``prec`` -- positive integer; default precision
|
||||
|
||||
- ``gen_name`` -- string; name of the generator of the residue
|
||||
field; used only when place is non-rational
|
||||
|
||||
EXAMPLES::
|
||||
|
||||
sage: from vector_bundle.function_field_utility import FunctionFieldCompletionCustom
|
||||
sage: K.<x> = FunctionField(GF(2)); _.<Y> = K[]
|
||||
sage: L.<y> = K.extension(Y^2 + Y + x + 1/x)
|
||||
sage: p = L.places_finite()[0]
|
||||
sage: m = FunctionFieldCompletionCustom(L,p)
|
||||
sage: m
|
||||
Completion map:
|
||||
From: Function field in y defined by y^2 + y + (x^2 + 1)/x
|
||||
To: Laurent Series Ring in s over Finite Field of size 2
|
||||
sage: m(x)
|
||||
s^2 + s^3 + s^4 + s^5 + s^7 + s^8 + s^9 + s^10 + s^12 + s^13
|
||||
+ s^15 + s^16 + s^17 + s^19 + O(s^22)
|
||||
sage: m(y)
|
||||
s^-1 + 1 + s^3 + s^5 + s^7 + s^9 + s^13 + s^15 + s^17 + O(s^19)
|
||||
sage: m(x*y) == m(x) * m(y)
|
||||
True
|
||||
sage: m(x+y) == m(x) + m(y)
|
||||
True
|
||||
|
||||
The variable name of the series can be supplied. If the place is not
|
||||
rational such that the residue field is a proper extension of the constant
|
||||
field, you can also specify the generator name of the extension::
|
||||
|
||||
sage: p2 = L.places_finite(2)[0]
|
||||
sage: p2
|
||||
Place (x^2 + x + 1, x*y + 1)
|
||||
sage: m2 = FunctionFieldCompletionCustom(L, p2, name='t', gen_name='b')
|
||||
sage: m2(x)
|
||||
(b + 1) + t + t^2 + t^4 + t^8 + t^16 + O(t^20)
|
||||
sage: m2(y)
|
||||
b + b*t + b*t^3 + b*t^4 + (b + 1)*t^5 + (b + 1)*t^7 + b*t^9 + b*t^11
|
||||
+ b*t^12 + b*t^13 + b*t^15 + b*t^16 + (b + 1)*t^17 + (b + 1)*t^19 + O(t^20)
|
||||
|
||||
The choice of local uniformizer used for the expansion can be supplied.
|
||||
|
||||
sage: from vector_bundle.function_field_utility import safe_uniformizers
|
||||
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**-5 - 1)
|
||||
sage: pi = safe_uniformizers(K)[0]
|
||||
sage: place = all_infinite_places(K)[0]
|
||||
sage: f = 1 / (1-pi)
|
||||
sage: m3 = FunctionFieldCompletionCustom(K, place, pi)
|
||||
sage: m3(f)
|
||||
1 + s + s^2 + s^3 + s^4 + s^5 + s^6 + s^7 + s^8 + s^9 + s^10 + s^11 +
|
||||
s^12 + s^13 + s^14 + s^15 + s^16 + s^17 + s^18 + s^19 + O(s^20)
|
||||
"""
|
||||
def __init__(self, field, place, pi=None, name=None, prec=None, gen_name=None):
|
||||
"""
|
||||
Initialize.
|
||||
|
||||
EXAMPLES::
|
||||
|
||||
sage: # needs sage.rings.finite_rings sage.rings.function_field
|
||||
sage: K.<x> = FunctionField(GF(2)); _.<Y> = K[]
|
||||
sage: L.<y> = K.extension(Y^2 + Y + x + 1/x)
|
||||
sage: p = L.places_finite()[0]
|
||||
sage: m = L.completion(p)
|
||||
sage: m
|
||||
Completion map:
|
||||
From: Function field in y defined by y^2 + y + (x^2 + 1)/x
|
||||
To: Laurent Series Ring in s over Finite Field of size 2
|
||||
"""
|
||||
if name is None:
|
||||
name = 's' # default
|
||||
|
||||
if gen_name is None:
|
||||
gen_name = 'a' # default
|
||||
|
||||
k, from_k, to_k = place.residue_field(name=gen_name)
|
||||
|
||||
self._place = place
|
||||
if pi is None:
|
||||
self._pi = place.local_uniformizer()
|
||||
else:
|
||||
self._pi = pi
|
||||
|
||||
self._gen_name = gen_name
|
||||
|
||||
if prec is infinity:
|
||||
from sage.rings.lazy_series_ring import LazyLaurentSeriesRing
|
||||
codomain = LazyLaurentSeriesRing(k, name)
|
||||
self._precision = infinity
|
||||
else: # prec < infinity:
|
||||
# if prec is None, the Laurent series ring provides default precision
|
||||
from sage.rings.laurent_series_ring import LaurentSeriesRing
|
||||
codomain = LaurentSeriesRing(k, name=name, default_prec=prec)
|
||||
self._precision = codomain.default_prec()
|
||||
|
||||
Map.__init__(self, field, codomain)
|
||||
|
||||
def _repr_type(self) -> str:
|
||||
"""
|
||||
Return a string containing the type of the map.
|
||||
|
||||
EXAMPLES::
|
||||
|
||||
sage: # needs sage.rings.finite_rings sage.rings.function_field
|
||||
sage: K.<x> = FunctionField(GF(2)); _.<Y> = K[]
|
||||
sage: L.<y> = K.extension(Y^2 + Y + x + 1/x)
|
||||
sage: p = L.places_finite()[0]
|
||||
sage: m = L.completion(p)
|
||||
sage: m # indirect doctest
|
||||
Completion map:
|
||||
From: Function field in y defined by y^2 + y + (x^2 + 1)/x
|
||||
To: Laurent Series Ring in s over Finite Field of size 2
|
||||
"""
|
||||
return 'Completion'
|
||||
|
||||
def _call_(self, f):
|
||||
"""
|
||||
Call the completion for f
|
||||
|
||||
EXAMPLES::
|
||||
|
||||
sage: # needs sage.rings.finite_rings sage.rings.function_field
|
||||
sage: K.<x> = FunctionField(GF(2)); _.<Y> = K[]
|
||||
sage: L.<y> = K.extension(Y^2 + Y + x + 1/x)
|
||||
sage: p = L.places_finite()[0]
|
||||
sage: m = L.completion(p)
|
||||
sage: m(y)
|
||||
s^-1 + 1 + s^3 + s^5 + s^7 + s^9 + s^13 + s^15 + s^17 + O(s^19)
|
||||
"""
|
||||
if f.is_zero():
|
||||
return self.codomain().zero()
|
||||
if self._precision is infinity:
|
||||
return self._expand_lazy(f)
|
||||
else:
|
||||
return self._expand(f, prec=None)
|
||||
|
||||
def _call_with_args(self, f, args, kwds):
|
||||
"""
|
||||
Call the completion with ``args`` and ``kwds``.
|
||||
|
||||
EXAMPLES::
|
||||
|
||||
sage: # needs sage.rings.finite_rings sage.rings.function_field
|
||||
sage: K.<x> = FunctionField(GF(2)); _.<Y> = K[]
|
||||
sage: L.<y> = K.extension(Y^2 + Y + x + 1/x)
|
||||
sage: p = L.places_finite()[0]
|
||||
sage: m = L.completion(p)
|
||||
sage: m(x+y, 10) # indirect doctest
|
||||
s^-1 + 1 + s^2 + s^4 + s^8 + O(s^9)
|
||||
"""
|
||||
if f.is_zero():
|
||||
return self.codomain().zero()
|
||||
if self._precision is infinity:
|
||||
return self._expand_lazy(f, *args, **kwds)
|
||||
else:
|
||||
return self._expand(f, *args, **kwds)
|
||||
|
||||
def _expand(self, f, prec=None):
|
||||
"""
|
||||
Return the Laurent series expansion of f with precision ``prec``.
|
||||
|
||||
INPUT:
|
||||
|
||||
- ``f`` -- element of the function field
|
||||
|
||||
- ``prec`` -- positive integer; relative precision of the series
|
||||
|
||||
EXAMPLES::
|
||||
|
||||
sage: # needs sage.rings.finite_rings sage.rings.function_field
|
||||
sage: K.<x> = FunctionField(GF(2)); _.<Y> = K[]
|
||||
sage: L.<y> = K.extension(Y^2 + Y + x + 1/x)
|
||||
sage: p = L.places_finite()[0]
|
||||
sage: m = L.completion(p)
|
||||
sage: m(x, prec=20) # indirect doctest
|
||||
s^2 + s^3 + s^4 + s^5 + s^7 + s^8 + s^9 + s^10 + s^12 + s^13 + s^15
|
||||
+ s^16 + s^17 + s^19 + O(s^22)
|
||||
"""
|
||||
if prec is None:
|
||||
prec = self._precision
|
||||
|
||||
place = self._place
|
||||
F = place.function_field()
|
||||
der = F.higher_derivation()
|
||||
|
||||
k, from_k, to_k = place.residue_field(name=self._gen_name)
|
||||
sep = self._pi
|
||||
|
||||
val = f.valuation(place)
|
||||
e = f * sep**(-val)
|
||||
|
||||
coeffs = [to_k(der._derive(e, i, sep)) for i in range(prec)]
|
||||
return self.codomain()(coeffs, val).add_bigoh(prec + val)
|
||||
|
||||
def _expand_lazy(self, f):
|
||||
"""
|
||||
Return the lazy Laurent series expansion of ``f``.
|
||||
|
||||
INPUT:
|
||||
|
||||
- ``f`` -- element of the function field
|
||||
|
||||
EXAMPLES::
|
||||
|
||||
sage: # needs sage.rings.finite_rings sage.rings.function_field
|
||||
sage: K.<x> = FunctionField(GF(2)); _.<Y> = K[]
|
||||
sage: L.<y> = K.extension(Y^2 + Y + x + 1/x)
|
||||
sage: p = L.places_finite()[0]
|
||||
sage: m = L.completion(p, prec=infinity)
|
||||
sage: e = m(x); e
|
||||
s^2 + s^3 + s^4 + s^5 + s^7 + s^8 + ...
|
||||
sage: e.coefficient(99) # indirect doctest
|
||||
0
|
||||
sage: e.coefficient(100)
|
||||
1
|
||||
"""
|
||||
place = self._place
|
||||
F = place.function_field()
|
||||
der = F.higher_derivation()
|
||||
|
||||
k, from_k, to_k = place.residue_field(name=self._gen_name)
|
||||
sep = self._pi
|
||||
|
||||
val = f.valuation(place)
|
||||
e = f * sep**(-val)
|
||||
|
||||
def coeff(s, n):
|
||||
return to_k(der._derive(e, n - val, sep))
|
||||
|
||||
return self.codomain().series(coeff, valuation=val)
|
||||
|
||||
def default_precision(self):
|
||||
"""
|
||||
Return the default precision.
|
||||
|
||||
EXAMPLES::
|
||||
|
||||
sage: # needs sage.rings.finite_rings sage.rings.function_field
|
||||
sage: K.<x> = FunctionField(GF(2)); _.<Y> = K[]
|
||||
sage: L.<y> = K.extension(Y^2 + Y + x + 1/x)
|
||||
sage: p = L.places_finite()[0]
|
||||
sage: m = L.completion(p)
|
||||
sage: m.default_precision()
|
||||
20
|
||||
"""
|
||||
return self._precision
|
||||
|
||||
def local_expansion(place,pi,f):
|
||||
r"""
|
||||
|
@ -359,26 +606,7 @@ def local_expansion(place,pi,f):
|
|||
|
||||
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
|
||||
|
@ -574,22 +802,50 @@ def euclidean_step(ideal_a, ideal_b, a, b, d=None):
|
|||
return s/a, t/b
|
||||
|
||||
|
||||
def finite_integral_quotient(left, right):
|
||||
return (left.numerator()*right.denominator()) // (left.denominator())*(right.numerator())
|
||||
|
||||
|
||||
def infinite_integral_quotient(left, right):
|
||||
if left == 0:
|
||||
return 0
|
||||
r = left / right
|
||||
x = left.parent().gen()
|
||||
return x**(r.denominator().degree() - r.numerator().degree())
|
||||
|
||||
|
||||
def hnf_reduction_mod_ideal(ideal, elem):
|
||||
r"""
|
||||
Reduce an element of a function field \(K\) modulo an ideal of a maximal
|
||||
order of K
|
||||
"""
|
||||
if isinstance(ideal, FunctionFieldIdealInfinite):
|
||||
quotient = infinite_integral_quotient
|
||||
hnf = infinite_ideal_hnf(ideal)
|
||||
else:
|
||||
quotient = finite_integral_quotient
|
||||
hnf = ideal.hnf()
|
||||
n = hnf.ncols()
|
||||
basis = ideal.base_ring().basis()
|
||||
basis_matrix = matrix([e.list() for e in basis]).transpose()**-1
|
||||
y = basis_matrix * matrix(n,1,elem.list())
|
||||
for i in range(n - 1, -1, -1):
|
||||
q = quotient(y[i,0],hnf[i,i])
|
||||
y -= q * hnf[:,i]
|
||||
y = sum([y[i,0]*e for i, e in enumerate(basis)])
|
||||
return y
|
||||
|
||||
|
||||
def pseudo_hermite_form(ideals, mat, include_zero_cols=True, transformation=False):
|
||||
r"""
|
||||
Return the hermite form of the pseudo-matrix ``(ideals, mat)`` with
|
||||
coefficients in a function field and ideals in a maximal order.
|
||||
|
||||
If the maximal order is infinite, the ideals of the pseudo-matrix output
|
||||
are all trivial.
|
||||
|
||||
WARNING:
|
||||
|
||||
Uses the opposite convention from sage for hermite forms, aligns with
|
||||
Cohen's book instead.
|
||||
|
||||
The final reduction step is not implemented as having triangular matrices
|
||||
is enough for our purposes.
|
||||
|
||||
ALGORITHM:
|
||||
|
||||
- Algorithm 1.4.7 from [Coh00]_
|
||||
|
@ -604,8 +860,8 @@ def pseudo_hermite_form(ideals, mat, include_zero_cols=True, transformation=Fals
|
|||
sage: mat = matrix(K, [[1, x, y],[2, x+1, y+1]])
|
||||
sage: h_ideals, h, u = pseudo_hermite_form(ideals, mat, transformation=True)
|
||||
sage: h
|
||||
[ 0 1 (2*x + 5)*y + 4*x]
|
||||
[ 0 0 1]
|
||||
[ 0 1 3*x^3 + 4*x]
|
||||
[ 0 0 1]
|
||||
sage: h == mat * u
|
||||
True
|
||||
sage: all([u[i,j] in ideals[i] * h_ideals[j]^-1 for i in range(3) for j in range(3)])
|
||||
|
@ -622,6 +878,9 @@ def pseudo_hermite_form(ideals, mat, include_zero_cols=True, transformation=Fals
|
|||
j = k-1
|
||||
for i in range(n-1, -1, -1):
|
||||
#Check zero
|
||||
if not h[i,:]:
|
||||
j -= 1
|
||||
continue
|
||||
m = [h[i,m] == 0 for m in range(j, -1, -1)].index(False)
|
||||
h[:,m], h[:,j] = h[:,j], h[:,m]
|
||||
U[:,m], U[:,j] = U[:,j], U[:,m]
|
||||
|
@ -641,9 +900,12 @@ def pseudo_hermite_form(ideals, mat, include_zero_cols=True, transformation=Fals
|
|||
U[:, m], U[:, j] = U[:, m] - h[i, m]*U[:, j], u*U[:, m] + v*U[:, j]
|
||||
h[:, m], h[:, j] = h[:, m] - h[i, m]*h[:, j], u*h[:, m] + v*h[:, j]
|
||||
h_ideals[m], h_ideals[j] = h_ideals[m] * h_ideals[j] * partial**-1, partial
|
||||
#Final reduction of row i
|
||||
#Not implemented for the moment since we only need triangular matrices
|
||||
#for our current purposes.
|
||||
#Row reduction step
|
||||
for m in range(j+1,k):
|
||||
ideal = h_ideals[m]**-1 * h_ideals[j]
|
||||
q = h[i, m] - hnf_reduction_mod_ideal(ideal, h[i, m])
|
||||
U[:, m] -= q*U[:, j]
|
||||
h[:, m] -= q*h[:, j]
|
||||
j -=1
|
||||
if not include_zero_cols:
|
||||
h = h[:,k-n:]
|
||||
|
@ -652,3 +914,103 @@ def pseudo_hermite_form(ideals, mat, include_zero_cols=True, transformation=Fals
|
|||
if transformation:
|
||||
return h_ideals, h, U
|
||||
return h_ideals, h
|
||||
|
||||
def hermite_form_infinite_polymod(mat, include_zero_cols=True, transformation=False):
|
||||
r"""
|
||||
Return the hermite normal form of mat.
|
||||
|
||||
EXAMPLES ::
|
||||
sage: from vector_bundle.function_field_utility import hermite_form_infinite_polymod
|
||||
sage: from vector_bundle.function_field_utility import all_infinite_places
|
||||
sage: F.<x> = FunctionField(GF(7))
|
||||
sage: R.<y> = F[]
|
||||
sage: K.<y> = F.extension(y^2 - x^3 - x)
|
||||
sage: mat = matrix(K,[[1,x^-1,y^-1],[2,(x+1)^-1,(y+1)^-1]])
|
||||
sage: h, u = hermite_form_infinite_polymod(mat, transformation=True)
|
||||
sage: h
|
||||
[ 0 (4*x + 1)/(x^2 + x) (4*x^2 + 6)/x^2]
|
||||
[ 0 0 1]
|
||||
sage: h == mat * u
|
||||
True
|
||||
sage: O = K.maximal_order_infinite()
|
||||
sage: all([c in O for c in u.list()])
|
||||
True
|
||||
sage: all([u.determinant().valuation(place) == 0 for place in all_infinite_places(K)])
|
||||
True
|
||||
"""
|
||||
K = mat.base_ring()
|
||||
O = K.maximal_order_infinite()
|
||||
pis = safe_uniformizers(K)
|
||||
places = all_infinite_places(K)
|
||||
mins = [min([m.valuation(place) for m in mat.list()]) for place in places]
|
||||
den = prod([pi**min(-m,0) for pi, m in zip(pis, mins)])
|
||||
h = den*mat
|
||||
k = mat.ncols()
|
||||
n = mat.nrows()
|
||||
U = identity_matrix(K,k)
|
||||
j = k-1
|
||||
for i in range(n-1, -1, -1):
|
||||
if not h[i,:]:
|
||||
continue
|
||||
min_vals = [min([h[i,m].valuation(place) for m in range(j+1)])
|
||||
for place in places]
|
||||
gcd = prod([pi**m for pi, m in zip(pis, min_vals)])
|
||||
#put gcd on the diagonal
|
||||
ideals = [O.ideal(h[i,m]/gcd) for m in range(j+1)]
|
||||
coefs = infinite_order_xgcd(ideals)
|
||||
m = [c == 0 for c in coefs].index(False)
|
||||
U[:,j], U[:, m] = gcd*sum([c/h[i,m]*U[:,m]
|
||||
for m,c in enumerate(coefs)]), U[:, j]
|
||||
h[:,j], h[:, m] = gcd*sum([c/h[i,m]*h[:,m]
|
||||
for m,c in enumerate(coefs)]), h[:, j]
|
||||
assert(all([u in O for u in U.list()]))
|
||||
#eliminate coefficients left of diagonal
|
||||
for m in range(j):
|
||||
c = h[i,m]/h[i,j]
|
||||
U[:,m] -= c*U[:,j]
|
||||
h[:,m] -= c*h[:,j]
|
||||
assert(all([u in O for u in U.list()]))
|
||||
#reduce coefficients right of diagonal
|
||||
for m in range(j+1,k):
|
||||
ideal = O.ideal(h[i,j])
|
||||
q = (h[i, m] - hnf_reduction_mod_ideal(ideal,h[i, m]))/h[i,j]
|
||||
U[:,m] -= q*U[:,j]
|
||||
h[:,m] -= q*h[:,j]
|
||||
j-=1
|
||||
h /= den
|
||||
if not include_zero_cols:
|
||||
h = h[:,k-n:]
|
||||
U = U[:,k-n:]
|
||||
if transformation:
|
||||
return h, U
|
||||
return h
|
||||
|
||||
|
||||
def full_rank_matrix_in_completion(mat, place=None, pi=None):
|
||||
r"""
|
||||
Return a full rank matrix with coefficients in the constant base field.
|
||||
|
||||
Its columns are concatenations of expansions of the coefficients in the
|
||||
columns of mat.
|
||||
"""
|
||||
K = mat.base_ring()
|
||||
k = K.constant_base_field()
|
||||
s = mat.ncols()
|
||||
r = mat.nrows()
|
||||
if place is None:
|
||||
if isinstance(K, RationalFunctionField):
|
||||
place = K.gen().zeros()[0]
|
||||
else:
|
||||
place = K.get_place(1)
|
||||
Kp = FunctionFieldCompletionCustom(K, place, pi, prec=infinity, name="pi", gen_name="b")
|
||||
exps = [[Kp(c) for c in row] for row in mat]
|
||||
vals = [min([mat[i,j].valuation(place) for j in range(s)])
|
||||
for i in range(r)]
|
||||
ell = 0
|
||||
N = matrix(k,0,s)
|
||||
while N.rank() < s:
|
||||
for i in range(r):
|
||||
row = [exps[i][j].coefficient(vals[i] + ell) for j in range(s)]
|
||||
N = insert_row(N, (i+1)*(ell+1) - 1, row)
|
||||
ell += 1
|
||||
return N
|
||||
|
|
|
@ -922,7 +922,7 @@ class VectorBundle(SageObject):
|
|||
|
||||
OUTPUT:
|
||||
|
||||
- ''res'' -- vector of elements of K such that the corresponding infinite répartition vectorcorresponds to form under Serre duality with respect to _safe_uniformizer(self._function_field).differential().
|
||||
- ''res'' -- vector of elements of K such that the corresponding infinite répartition vectorcorresponds to form under Serre duality with respect to ``safe_uniformizers(self._function_field)[0].differential()``.
|
||||
|
||||
EXAMPLES ::
|
||||
|
||||
|
@ -941,44 +941,38 @@ class VectorBundle(SageObject):
|
|||
form = [1] + [0] * (s-1)
|
||||
r = self.rank()
|
||||
places = function_field_utility.all_infinite_places(K)
|
||||
pi_0, place_0 = function_field_utility.safe_uniformizer(K)
|
||||
if not place_0 == places[0]:
|
||||
raise ValueError('Something went wrong with the order of infinite'
|
||||
+ ' places of the function field')
|
||||
pi_0 = function_field_utility.safe_uniformizers(K)[0]
|
||||
place_0 = places[0]
|
||||
k,from_k,to_k = place_0.residue_field()
|
||||
form = vector([function_field_utility.invert_trace(
|
||||
k, K.constant_base_field(), c) for c in form])
|
||||
dual_matrix = matrix([h1_dual_bundle._matrix_to_vector(mat)
|
||||
for mat in h1_dual]).transpose()
|
||||
zero_rows = [i for i, row in enumerate(dual_matrix) if row == 0]
|
||||
exps = [[function_field_utility.local_expansion(place_0,
|
||||
pi_0,dual_matrix[i, j])
|
||||
for j in range(s)]
|
||||
for i in range(r)]
|
||||
min_vals = [[min([dual_matrix[i, j].valuation(place) for j in range(s)])
|
||||
for i in range(r)]
|
||||
for place in places]
|
||||
ell = 0
|
||||
n_matrix = matrix(k,0,s,[])
|
||||
while n_matrix.rank() < s:
|
||||
for i in range(r):
|
||||
row = [exps[i][j](min_vals[0][i] + ell) for j in range(s)]
|
||||
n_matrix = function_field_utility.insert_row(
|
||||
n_matrix, (i+1)*(ell+1) - 1, row)
|
||||
ell +=1
|
||||
n_matrix = function_field_utility.full_rank_matrix_in_completion(
|
||||
dual_matrix,
|
||||
place_0,
|
||||
pi_0)
|
||||
ell = n_matrix.nrows() // dual_matrix.nrows()
|
||||
ell_pow = k.cardinality() ** integer_ceil(logb(ell,k.cardinality()))
|
||||
res = n_matrix.solve_left(form)
|
||||
min_vals = [[min([c.valuation(place) for c in dual_matrix.list()])]
|
||||
for place in places]
|
||||
pi = function_field_utility.infinite_approximation(
|
||||
places,
|
||||
[1] + [integer_ceil(-min(min_val)/ell) for min_val in min_vals[1:]],
|
||||
[1] + [integer_ceil(-min_val/ell) for min_val in min_vals[1:]],
|
||||
[1] + [0]*(len(places)-1))**ell_pow
|
||||
res = [function_field_utility.infinite_approximation(
|
||||
places,
|
||||
[1] + [0]*(len(places)-1),
|
||||
[a] + [0]*(len(places)-1))**ell_pow
|
||||
for a in res]
|
||||
min_vals_0 = [0 if i in zero_rows
|
||||
else min([dual_matrix[i,j].valuation(place_0)
|
||||
for j in range(s)])
|
||||
for i in range(r)]
|
||||
return [pi
|
||||
* pi_0**(-min_vals[0][i]-1)
|
||||
* pi_0**(-min_vals_0[i]-1)
|
||||
* sum([pi_0**(-j) * res[i*ell + j] for j in range(ell)])
|
||||
if not i in zero_rows else 0
|
||||
for i in range(r)]
|
||||
|
@ -1049,14 +1043,18 @@ class VectorBundle(SageObject):
|
|||
for mat in ext_dual]
|
||||
return ext_group.extension(form)
|
||||
|
||||
def is_isomorphic_to(self, other):
|
||||
def _isomorphism_to_large_field(self, other, proba=10^-20):
|
||||
r"""
|
||||
Checks whether self is isomorphic to other
|
||||
Return an isomorphism from self to other if it exists and None otherwise.
|
||||
|
||||
ALGORITHM:
|
||||
May fail to find an isomorphism with probability less than proba.This
|
||||
only works if the constant base field is larger than
|
||||
``len(self.end().h0())``.
|
||||
"""
|
||||
|
||||
Computes the space of global homomorphisms and looks for
|
||||
an invertible matrix. Can probably be improved.
|
||||
def isomorphism_to(self, other):
|
||||
r"""
|
||||
Return an isomorphism from self to other if it exists and None otherwise
|
||||
|
||||
EXAMPLES ::
|
||||
|
||||
|
@ -1066,10 +1064,5 @@ class VectorBundle(SageObject):
|
|||
sage: K.<y> = F.extension(y^4 - x^-2 - 1)
|
||||
sage: triv = trivial_bundle(K)
|
||||
sage: can = canonical_bundle(K)
|
||||
sage: triv.is_isomorphic_to(can)
|
||||
True
|
||||
sage: triv.isomorphism_to(can)
|
||||
"""
|
||||
mat_basis = self.hom(other).h0()
|
||||
k = self._function_field.constant_base_field()
|
||||
return any([sum([(c*mat).is_unit() for c, mat in zip(vec, mat_basis)])
|
||||
for vec in ProjectiveSpace(len(mat_basis)-1, k)])
|
||||
|
|
Loading…
Reference in New Issue