2022-11-18 15:00:34 +01:00
|
|
|
class superelliptic:
|
|
|
|
"""Class of a superelliptic curve. Given a polynomial f(x) with coefficient field F, it constructs
|
|
|
|
the curve y^m = f(x)"""
|
2023-03-30 17:49:22 +02:00
|
|
|
def __init__(self, f, m, prec = 100):
|
2022-11-18 15:00:34 +01:00
|
|
|
Rx = f.parent()
|
|
|
|
x = Rx.gen()
|
|
|
|
F = Rx.base()
|
|
|
|
Rx.<x> = PolynomialRing(F)
|
|
|
|
Rxy.<x, y> = PolynomialRing(F, 2)
|
|
|
|
Fxy = FractionField(Rxy)
|
|
|
|
self.polynomial = Rx(f)
|
|
|
|
self.exponent = m
|
|
|
|
self.base_ring = F
|
|
|
|
self.characteristic = F.characteristic()
|
2023-02-23 12:26:25 +01:00
|
|
|
self.fct_field = Fxy, Rxy, x, y
|
2022-11-18 15:00:34 +01:00
|
|
|
r = Rx(f).degree()
|
|
|
|
delta = GCD(r, m)
|
2023-02-13 13:05:48 +01:00
|
|
|
self.nb_of_pts_at_infty = delta
|
|
|
|
self.x = superelliptic_function(self, Rxy(x))
|
|
|
|
self.y = superelliptic_function(self, Rxy(y))
|
|
|
|
self.dx = superelliptic_form(self, Rxy(1))
|
|
|
|
self.one = superelliptic_function(self, Rxy(1))
|
2023-03-30 17:49:22 +02:00
|
|
|
# We compute now expansions at infinity of x and y.
|
|
|
|
Rt.<t> = LaurentSeriesRing(F, default_prec=prec)
|
|
|
|
RptW.<W> = PolynomialRing(Rt)
|
|
|
|
RptWQ = FractionField(RptW)
|
|
|
|
Rxy.<x, y> = PolynomialRing(F)
|
|
|
|
RxyQ = FractionField(Rxy)
|
|
|
|
delta, a, b = xgcd(m, r)
|
|
|
|
a = -a
|
|
|
|
M = m/delta
|
|
|
|
R = r/delta
|
|
|
|
while a<0:
|
|
|
|
a += R
|
|
|
|
b += M
|
|
|
|
g = (x^r*f(x = 1/x))
|
|
|
|
gW = RptWQ(g(x = t^M * W^b)) - W^(delta)
|
|
|
|
self.x_series = []
|
|
|
|
self.y_series = []
|
|
|
|
self.dx_series = []
|
|
|
|
for place in range(delta):
|
|
|
|
ww = naive_hensel(gW, F, start = root_of_unity(F, delta)^place, prec = prec)
|
|
|
|
xx = Rt(1/(t^M*ww^b))
|
|
|
|
yy = 1/(t^R*ww^a)
|
|
|
|
self.x_series += [xx]
|
|
|
|
self.y_series += [yy]
|
|
|
|
self.dx_series += [xx.derivative()]
|
2022-11-18 15:00:34 +01:00
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
f = self.polynomial
|
|
|
|
m = self.exponent
|
|
|
|
F = self.base_ring
|
|
|
|
return 'Superelliptic curve with the equation y^' + str(m) + ' = ' + str(f)+' over ' + str(F)
|
2023-02-13 18:11:13 +01:00
|
|
|
|
2022-11-18 15:00:34 +01:00
|
|
|
#Auxilliary algorithm that returns the basis of holomorphic differentials
|
|
|
|
#of the curve and (as a second argument) the list of pairs (i, j)
|
|
|
|
#such that x^i dx/y^j is holomorphic.
|
|
|
|
def basis_holomorphic_differentials_degree(self):
|
|
|
|
f = self.polynomial
|
|
|
|
m = self.exponent
|
|
|
|
r = f.degree()
|
|
|
|
delta = GCD(r, m)
|
|
|
|
F = self.base_ring
|
|
|
|
Rx.<x> = PolynomialRing(F)
|
|
|
|
Rxy.<x, y> = PolynomialRing(F, 2)
|
|
|
|
Fxy = FractionField(Rxy)
|
|
|
|
#########basis of holomorphic differentials and de Rham
|
|
|
|
|
|
|
|
basis_holo = []
|
|
|
|
degrees0 = {}
|
|
|
|
k = 0
|
|
|
|
|
|
|
|
for j in range(1, m):
|
|
|
|
for i in range(1, r):
|
|
|
|
if (r*j - m*i >= delta):
|
|
|
|
basis_holo += [superelliptic_form(self, Fxy(x^(i-1)/y^j))]
|
|
|
|
degrees0[k] = (i-1, j)
|
|
|
|
k = k+1
|
|
|
|
|
|
|
|
return(basis_holo, degrees0)
|
|
|
|
|
|
|
|
#Returns the basis of holomorphic differentials using the previous algorithm.
|
|
|
|
def holomorphic_differentials_basis(self):
|
|
|
|
basis_holo, degrees0 = self.basis_holomorphic_differentials_degree()
|
|
|
|
return basis_holo
|
|
|
|
#Returns the list of pairs (i, j) such that x^i dx/y^j is holomorphic.
|
|
|
|
def degrees_holomorphic_differentials(self):
|
|
|
|
basis_holo, degrees0 = self.basis_holomorphic_differentials_degree()
|
|
|
|
return degrees0
|
|
|
|
|
|
|
|
def basis_de_rham_degrees(self):
|
|
|
|
f = self.polynomial
|
|
|
|
m = self.exponent
|
|
|
|
r = f.degree()
|
|
|
|
delta = GCD(r, m)
|
|
|
|
F = self.base_ring
|
|
|
|
Rx.<x> = PolynomialRing(F)
|
|
|
|
Rxy.<x, y> = PolynomialRing(F, 2)
|
|
|
|
Fxy = FractionField(Rxy)
|
|
|
|
basis_holo = self.holomorphic_differentials_basis()
|
|
|
|
basis = []
|
|
|
|
#First g_X elements of basis are holomorphic differentials.
|
|
|
|
for k in range(0, len(basis_holo)):
|
|
|
|
basis += [superelliptic_cech(self, basis_holo[k], superelliptic_function(self, 0))]
|
|
|
|
|
|
|
|
## Next elements do not come from holomorphic differentials.
|
|
|
|
t = len(basis)
|
|
|
|
degrees0 = {}
|
|
|
|
degrees1 = {}
|
|
|
|
for j in range(1, m):
|
|
|
|
for i in range(1, r):
|
|
|
|
if (r*(m-j) - m*i >= delta):
|
|
|
|
s = Rx(m-j)*Rx(x)*Rx(f.derivative()) - Rx(m)*Rx(i)*f
|
|
|
|
psi = Rx(cut(s, i))
|
|
|
|
basis += [superelliptic_cech(self, superelliptic_form(self, Fxy(psi/y^j)), superelliptic_function(self, Fxy(m*y^(m-j)/x^i)))]
|
|
|
|
degrees0[t] = (psi.degree(), j)
|
|
|
|
degrees1[t] = (-i, m-j)
|
|
|
|
t += 1
|
|
|
|
return basis, degrees0, degrees1
|
|
|
|
|
|
|
|
def de_rham_basis(self):
|
|
|
|
basis, degrees0, degrees1 = self.basis_de_rham_degrees()
|
|
|
|
return basis
|
|
|
|
|
|
|
|
def degrees_de_rham0(self):
|
|
|
|
basis, degrees0, degrees1 = self.basis_de_rham_degrees()
|
|
|
|
return degrees0
|
|
|
|
|
|
|
|
def degrees_de_rham1(self):
|
|
|
|
basis, degrees0, degrees1 = self.basis_de_rham_degrees()
|
|
|
|
return degrees1
|
|
|
|
|
|
|
|
def is_smooth(self):
|
|
|
|
f = self.polynomial
|
|
|
|
if f.discriminant() == 0:
|
|
|
|
return 0
|
|
|
|
return 1
|
|
|
|
|
|
|
|
def genus(self):
|
|
|
|
r = self.polynomial.degree()
|
|
|
|
m = self.exponent
|
|
|
|
delta = GCD(r, m)
|
|
|
|
return 1/2*((r-1)*(m-1) - delta + 1)
|
|
|
|
|
|
|
|
def verschiebung_matrix(self):
|
|
|
|
basis = self.de_rham_basis()
|
|
|
|
g = self.genus()
|
|
|
|
p = self.characteristic
|
|
|
|
F = self.base_ring
|
|
|
|
M = matrix(F, 2*g, 2*g)
|
|
|
|
for i in range(0, len(basis)):
|
|
|
|
w = basis[i]
|
|
|
|
v = w.verschiebung().coordinates()
|
|
|
|
M[i, :] = v
|
|
|
|
return M
|
|
|
|
|
2023-02-13 18:11:13 +01:00
|
|
|
def dr_frobenius_matrix(self):
|
2022-11-18 15:00:34 +01:00
|
|
|
basis = self.de_rham_basis()
|
|
|
|
g = self.genus()
|
|
|
|
p = self.characteristic
|
|
|
|
F = self.base_ring
|
|
|
|
M = matrix(F, 2*g, 2*g)
|
|
|
|
|
|
|
|
for i in range(0, len(basis)):
|
|
|
|
w = basis[i]
|
|
|
|
v = w.frobenius().coordinates()
|
|
|
|
M[i, :] = v
|
|
|
|
return M
|
|
|
|
|
|
|
|
def cartier_matrix(self):
|
|
|
|
basis = self.holomorphic_differentials_basis()
|
|
|
|
g = self.genus()
|
|
|
|
p = self.characteristic
|
|
|
|
F = self.base_ring
|
|
|
|
M = matrix(F, g, g)
|
|
|
|
for i in range(0, len(basis)):
|
|
|
|
w = basis[i]
|
|
|
|
v = w.cartier().coordinates()
|
2023-02-23 12:26:25 +01:00
|
|
|
M[:, i] = vector(v)
|
|
|
|
return M
|
2022-11-18 15:00:34 +01:00
|
|
|
|
2023-02-13 18:11:13 +01:00
|
|
|
def frobenius_matrix(self, prec=20):
|
|
|
|
g = self.genus()
|
|
|
|
F = self.base_ring
|
|
|
|
p = F.characteristic()
|
|
|
|
M = matrix(F, g, g)
|
2023-02-24 17:57:49 +01:00
|
|
|
for i, f in enumerate(self.cohomology_of_structure_sheaf_basis()):
|
2023-02-13 18:11:13 +01:00
|
|
|
M[i, :] = vector((f^p).coordinates(prec=prec))
|
|
|
|
M = M.transpose()
|
|
|
|
return M
|
|
|
|
|
2023-02-23 12:26:25 +01:00
|
|
|
def p_rank(self):
|
|
|
|
if self.exponent != 2:
|
|
|
|
raise ValueError('No implemented yet.')
|
|
|
|
f = self.polynomial()
|
|
|
|
F = self.base_ring
|
|
|
|
Rt.<t> = PolynomialRing(F)
|
|
|
|
f = Rt(f)
|
|
|
|
H = HyperellipticCurve(f, 0)
|
|
|
|
return H.p_rank()
|
2022-11-18 15:00:34 +01:00
|
|
|
|
|
|
|
def a_number(self):
|
2023-02-23 12:26:25 +01:00
|
|
|
g = self.genus()
|
2022-11-18 15:00:34 +01:00
|
|
|
return g - self.cartier_matrix().rank()
|
|
|
|
|
|
|
|
def final_type(self, test = 0):
|
|
|
|
Fr = self.frobenius_matrix()
|
|
|
|
V = self.verschiebung_matrix()
|
|
|
|
p = self.characteristic
|
|
|
|
return flag(Fr, V, p, test)
|
2023-02-13 18:11:13 +01:00
|
|
|
|
2023-02-24 17:57:49 +01:00
|
|
|
def cohomology_of_structure_sheaf_basis(self):
|
2023-02-13 18:11:13 +01:00
|
|
|
'''Basis of cohomology of structure sheaf H1(X, OX).'''
|
|
|
|
m = self.exponent
|
|
|
|
f = self.polynomial
|
|
|
|
r = f.degree()
|
|
|
|
F = self.base_ring
|
|
|
|
delta = self.nb_of_pts_at_infty
|
|
|
|
Rx.<x> = PolynomialRing(F)
|
|
|
|
Rxy.<x, y> = PolynomialRing(F, 2)
|
|
|
|
Fxy = FractionField(Rxy)
|
|
|
|
basis = []
|
|
|
|
for j in range(1, m):
|
2023-03-23 18:45:28 +01:00
|
|
|
for i in range(1, r):
|
|
|
|
if (r*(m-j) - m*i >= delta):
|
|
|
|
basis += [superelliptic_function(self, Fxy(m*y^(m-j)/x^i))]
|
2023-02-13 18:11:13 +01:00
|
|
|
return basis
|
2022-11-18 15:00:34 +01:00
|
|
|
|
2023-03-24 12:27:05 +01:00
|
|
|
def uniformizer(self):
|
|
|
|
m = self.exponent
|
|
|
|
r = self.polynomial.degree()
|
|
|
|
delta, a, b = xgcd(m, r)
|
|
|
|
a = -a
|
|
|
|
M = m/delta
|
|
|
|
R = r/delta
|
|
|
|
while a<0:
|
|
|
|
a += R
|
|
|
|
b += M
|
|
|
|
return (C.x)^a/(C.y)^b
|
|
|
|
|
2023-11-29 11:13:36 +01:00
|
|
|
def reduction(C, g):
|
2023-03-24 12:27:05 +01:00
|
|
|
'''Auxilliary. Given a superelliptic curve C : y^m = f(x) and a polynomial g(x, y)
|
|
|
|
it replaces repeteadly all y^m's in g(x, y) by f(x). As a result
|
2023-03-24 20:42:29 +01:00
|
|
|
you obtain sum_{i = 0}^{m-1} y^i g_i(x).'''
|
2023-11-29 11:13:36 +01:00
|
|
|
p = C.characteristic
|
|
|
|
F = C.base_ring
|
|
|
|
Rxy.<x, y> = PolynomialRing(F, 2)
|
|
|
|
Fxy = FractionField(Rxy)
|
|
|
|
f = C.polynomial
|
2022-11-18 15:00:34 +01:00
|
|
|
r = f.degree()
|
2023-11-29 11:13:36 +01:00
|
|
|
m = C.exponent
|
2022-11-18 15:00:34 +01:00
|
|
|
g = Fxy(g)
|
|
|
|
g1 = g.numerator()
|
|
|
|
g2 = g.denominator()
|
|
|
|
|
2023-11-29 11:13:36 +01:00
|
|
|
Rx.<x1> = PolynomialRing(F)
|
2022-11-18 15:00:34 +01:00
|
|
|
Fx = FractionField(Rx)
|
2023-11-29 11:13:36 +01:00
|
|
|
FxRy.<y1> = PolynomialRing(Fx)
|
|
|
|
(A, B, C) = xgcd(FxRy(g2(x=x1, y=y1)), y1^m - FxRy(f(x=x1)))
|
|
|
|
g = FxRy(FxRy(g1(x=x1, y=y1))*B/A)
|
2022-11-18 15:00:34 +01:00
|
|
|
|
2023-11-29 11:13:36 +01:00
|
|
|
while(g.degree(y1) >= m):
|
|
|
|
d = g.degree(y1)
|
2022-11-18 15:00:34 +01:00
|
|
|
G = coff(g, d)
|
|
|
|
i = floor(d/m)
|
2023-11-29 11:13:36 +01:00
|
|
|
g = g - G*y1^d + Rx(f(x=x1)^i) * y1^(d%m) *G
|
2023-11-29 15:41:39 +01:00
|
|
|
x, y = Fxy.gens()
|
|
|
|
h = Fxy(g(x1 = x, y1 = y))
|
|
|
|
return(h)
|
2022-11-18 15:00:34 +01:00
|
|
|
|
|
|
|
def reduction_form(C, g):
|
2023-11-29 09:50:29 +01:00
|
|
|
'''Auxilliary. Given a superelliptic curve C : y^m = f(x) and a polynomial g(x, y)
|
|
|
|
it replaces repeteadly all y^m's in g(x, y) by f(x). As a result
|
|
|
|
you obtain sum_{i = 0}^{m-1} g_i(x)/y^i. This is needed for reduction of
|
|
|
|
superelliptic forms.'''
|
2022-11-18 15:00:34 +01:00
|
|
|
F = C.base_ring
|
|
|
|
Rxy.<x, y> = PolynomialRing(F, 2)
|
|
|
|
Fxy = FractionField(Rxy)
|
|
|
|
f = C.polynomial
|
|
|
|
r = f.degree()
|
|
|
|
m = C.exponent
|
|
|
|
g = reduction(C, g)
|
|
|
|
|
2023-11-29 11:13:36 +01:00
|
|
|
Rx.<x1> = PolynomialRing(F)
|
2022-11-18 15:00:34 +01:00
|
|
|
Fx = FractionField(Rx)
|
2023-11-29 11:13:36 +01:00
|
|
|
FxRy.<y1> = PolynomialRing(Fx)
|
|
|
|
g1 = FxRy(0)
|
|
|
|
g = FxRy(g(x = x1, y=y1))
|
2022-11-18 15:00:34 +01:00
|
|
|
for j in range(0, m):
|
|
|
|
if j==0:
|
2024-01-09 10:48:05 +01:00
|
|
|
G = Fx(coff(g, 0))
|
2023-11-29 15:41:39 +01:00
|
|
|
g1 += FxRy(G)
|
2022-11-18 15:00:34 +01:00
|
|
|
else:
|
|
|
|
G = coff(g, j)
|
2023-11-29 11:13:36 +01:00
|
|
|
g1 += y1^(j-m)*FxRy(f(x=x1)*G)
|
|
|
|
g1 = Fxy(g1(x1 = x, y1 = y))
|
2022-11-18 15:00:34 +01:00
|
|
|
return(g1)
|