added manual and tests for polydifferential forms

This commit is contained in:
jgarnek 2024-01-29 10:37:21 +00:00
parent a8e8dbbaa3
commit 4533eec102
5 changed files with 126 additions and 11 deletions

View File

@ -110,7 +110,7 @@ Rx.<x> = PolynomialRing(F)
f = x^3 + x
C = superelliptic(f, 2)
f1 = C.x^2*C_super.y
f1 = C.x^2*C.y
f2 = C.x^3
AS = as_cover(C, [f1, f2], prec=1000)
```
@ -149,7 +149,7 @@ One can decompose it into indecomposable $(\mathbb Z/p)^2$-modules, using
print(magma_module_decomposition(A, B))
```
Note that this won't work for large genus of AS, as it uses free Magma with limited input.
Note that this won't work for large genus of AS, as it uses free Magma with limited input. You may however use it with argument *text=True*, to obtain Magma command on output.
One can also look for magical elements:
@ -157,6 +157,71 @@ One can also look for magical elements:
print(AS.magical_element())
```
## Polydifferential forms on abelian covers
For any $(\mathbb Z/p)^n$\-cover as above, one can define a polydifferential form (i.e. a section of $\Omega^{\otimes n}$) as follows:
```
F = GF(3)
Rx.<x> = PolynomialRing(F)
f = x^3 + x
C = superelliptic(f, 2)
AS = as_cover(C, [C.x^2*C.y, C.x^3], prec=1000)
omega = as_polyform(AS.x^5, 3) # the first argument is a function on AS, the second is the multiplicity of polyform
print(omega)
print(omega.expansion_at_infty())
```
Using the command *holo_polydifferentials_basis* one may compute the basis of $H^0(\Omega^{\otimes n})$:
```
p = 5
F = GF(p)
Rx.<x> = PolynomialRing(F)
C = superelliptic(x, 1)
AS = as_cover(C, [C.x^8], prec = 200)
print(AS.holo_polydifferentials_basis(2, threshold = 15)) #we increase the threshold if needed, see below
```
The class *as_symmetric_product_forms* may be used to define an element of $\textrm{Sym}^n \, H^0(\Omega_X)$. The command *as_symmetric_power_basis* returns a basis of $\textrm{Sym}^n \, H^0(\Omega_X)$.
```
p = 5
F = GF(p)
Rx.<x> = PolynomialRing(F)
C = superelliptic(x, 1)
AS = as_cover(C, [C.x^8], prec = 200)
omega = as_symmetric_product_forms([[2, AS.dx, AS.z[0]*AS.dx], [-1, AS.x*AS.dx, AS.z[0]*AS.dx]])
#note that the argument is a list of lists (first coefficient, then forms that occur in the given simple tensor)
print(omega)
print(as_symmetric_power_basis(AS, 2))
```
The method *canonical_ideal* computes the elements of $\textrm{Sym}^n \, H^0(\Omega_X)$ that are in the kernel of the multiplication map with codomain in $H^0(\Omega_X^{\otimes n})$ (i.e. the n-th homogeneous part of the canonical ideal). The method *canonical_ideal_polynomials* computes the corresponding polynomials and *group_action_canonical_ideal* the matrices of the group action on the n-th homogeneous part of the canonical ideal.
```
p = 5
F = GF(p)
Rx.<x> = PolynomialRing(F)
C = superelliptic(x, 1)
AS = as_cover(C, [C.x^8], prec = 200)
print(AS.canonical_ideal(2, threshold = 15))
print(AS.canonical_ideal_polynomials(2, threshold = 15))
print(AS.group_action_canonical_ideal(2, threshold = 15))
```
## Quaternion covers
Some of the above methods are also implemented for quaternion covers in characteristic $2$. Those are defined by the equations $z_0^2 + z_0 = f_0, z_1^2 + z_1 = f_1, z_2^2 + z_2 = f_2 + z_0f_0 + z_1 (f_0 + f_1)$. The arguments of *quaternion_cover* are: the covered superelliptic curve $C$ and the functions $f_0$, $f_1$, $f_2$ on $C$.
```
p = 2
F.<a> = GF(p^2)
Rx.<x> = PolynomialRing(F)
C = superelliptic(x, 1)
Q = quaternion_cover(C, [C.x^3, a*C.x^3, 0*C.x], prec = 300)
print(Q)
print(Q.genus())
print(Q.holomorphic_differentials_basis())
print(Q.canonical_ideal_polynomials(2))
Qi, Qj = QuaternionGroup().gens()
omega = Q.z[2]*Q.dx
print(omega.group_action(Qi), omega.group_action(Qj))
```
## Common errors:
1. *Increase precision.* - Increase the *prec* argument of the curve.

View File

@ -1,5 +1,6 @@
class as_polyform:
def __init__(self, form, mult):
'''Elements of H^0(Ω^⊗n). Usage: mult is n, form should be as_function.'''
self.form = form
self.curve = form.curve
self.mult = mult
@ -28,6 +29,7 @@ class as_polyform:
def as_holo_polydifferentials_basis(AS, mult, threshold = 8):
'''Give the basis of H^0(Ω^⊗n) for n = mult.'''
v = AS.dx.valuation()
result = AS.at_most_poles(mult*v, threshold=threshold)
result = [as_polyform(omega, mult) for omega in result]
@ -40,6 +42,7 @@ def as_holo_polydifferentials_basis(AS, mult, threshold = 8):
as_cover.holo_polydifferentials_basis = as_holo_polydifferentials_basis
def as_symmetric_power_basis(AS, n, threshold = 8):
'''Give the basis of H^0(Ω)^⊙n for n = mult.'''
g = AS.genus()
B0 = AS.holomorphic_differentials_basis(threshold=threshold)
from itertools import product
@ -57,6 +60,7 @@ def as_symmetric_power_basis(AS, n, threshold = 8):
return result
def as_canonical_ideal(AS, n, threshold=8):
'''Return the n-th homogeneous part of the canonical ideal.'''
B0 = AS.holomorphic_differentials_basis(threshold=threshold)
F = AS.base_ring
g = AS.genus()
@ -83,13 +87,14 @@ def as_canonical_ideal(AS, n, threshold=8):
as_cover.canonical_ideal = as_canonical_ideal
def as_canonical_ideal_polynomials(AS, n, threshold=8):
'''Return the polynomials defining n-th homogeneous part of the canonical ideal.'''
return [a.polynomial() for a in AS.canonical_ideal(n, threshold=threshold)]
as_cover.canonical_ideal_polynomials = as_canonical_ideal_polynomials
class as_symmetric_product_forms:
def __init__(self, forms_and_coeffs):
'''Elements of forms_and_coeffs are of the form [coeff, form1, ..., formn]'''
'''Elements of forms_and_coeffs are of the form [coeff, form_1, ..., form_n]'''
self.n = len(forms_and_coeffs[0]) - 1
forms_and_coeffs1 = []
for atuple in forms_and_coeffs:
@ -148,6 +153,7 @@ class as_symmetric_product_forms:
return as_symmetric_product_forms(aux_tuples)
def multiply(self):
'''The map H^0(Ω)^⊙n ---> H^0(Ω^⊗n)'''
n = self.n
AS = self.curve
RxyzQ, Rxyz, x, y, z = AS.fct_field
@ -163,6 +169,7 @@ class as_symmetric_product_forms:
return result
def polynomial(self):
'''Return the associated polynomial.'''
AS = self.curve
F = AS.base_ring
g = AS.genus()
@ -193,6 +200,7 @@ def non_decreasing(L):
return all(x<=y for x, y in zip(L, L[1:]))
def as_matrices_group_action_canonical_ideal(AS, mult, threshold = 8):
'''Return the group action matrices for the n-th homogeneous part of the canonical ideal.'''
K = as_canonical_ideal(AS, mult, threshold = threshold)
n = AS.height
F = AS.base_ring
@ -205,4 +213,6 @@ def as_matrices_group_action_canonical_ideal(AS, mult, threshold = 8):
for i in range(r):
M[i, :] = vector(linear_representation_polynomials(K_group_action_polynomials[i], K_polynomials))
matrices += [M]
return matrices
return matrices
as_cover.group_action_canonical_ideal = as_matrices_group_action_canonical_ideal

View File

@ -0,0 +1,27 @@
p = 2
F = GF(p)
Rx.<x> = PolynomialRing(F)
C = superelliptic(x, 1)
AS = as_cover(C, [C.x^3, C.x^5], prec = 200)
B = AS.holo_polydifferentials_basis(3)
print(len(B) == (2 * 3 - 1) * (AS.genus() - 1)) #is the dimension as predicted by Riemann--Roch?
I2 = AS.canonical_ideal_polynomials(2)
R = I2[0].parent() #ring, to which the polynomials belong
J2 = R.ideal(I2) #ideal defined by the set I
print(J2.is_prime(), len(R.gens()) - J2.dimension() - 1)
I3 = AS.canonical_ideal_polynomials(3)
J3 = R.ideal(I2 + I3)
print(J3.is_prime(), len(R.gens()) - J3.dimension() - 1)
p = 5
F = GF(p)
Rx.<x> = PolynomialRing(F)
C = superelliptic(x, 1)
AS = as_cover(C, [C.x^8], prec = 200)
I2 = AS.canonical_ideal_polynomials(2, threshold=15)
R = I2[0].parent() #ring, to which the polynomials belong
J2 = R.ideal(I2) #ideal defined by the set I
print(J2.is_prime(), len(R.gens()) - J2.dimension() - 1)
I3 = AS.canonical_ideal_polynomials(3, threshold=20)
J3 = R.ideal(I2 + I3)
print(J3.is_prime(), len(R.gens()) - J3.dimension() - 1)

View File

@ -0,0 +1,12 @@
p = 2
F.<a> = GF(p^2)
Rx.<x> = PolynomialRing(F)
C = superelliptic(x, 1)
Q = quaternion_cover(C, [C.x^3, a*C.x^3, 0*C.x], prec = 300)
print(Q.genus() == len(Q.holomorphic_differentials_basis()))
I2 = Q.canonical_ideal_polynomials(2)
R = I2[0].parent() #ring, to which the polynomials belong
J2 = R.ideal(I2) #ideal defined by the set I
print(J2.is_prime(), len(R.gens()) - J2.dimension() - 1)
A, B = quaternion_matrices_group_action_canonical_ideal(Q, 2)
print(A * B == B^3*A, A^2 == B^2, A^4 == identity_matrix(A.dimensions()[0]))

View File

@ -27,11 +27,12 @@
#load('as_covers/tests/diffn_test.sage')
#print("Cartier test:")
#load('as_covers/tests/cartier_test.sage')
print("Decomposition into g0, g8/ omega0, omega8 test:")
load('superelliptic_drw/tests/decomposition_into_g0_g8_tests.sage')
print("Auxilliary decomposition test:")
load('superelliptic_drw/tests/auxilliary_decompositions_test.sage')
print("Superelliptic de Rham-Witt test:")
load('superelliptic_drw/tests/superelliptic_drw_tests.sage')
print("Polydifferentials test:")
load('as_covers/tests/as_polyforms_test.sage')
#print("Decomposition into g0, g8/ omega0, omega8 test:")
#load('superelliptic_drw/tests/decomposition_into_g0_g8_tests.sage')
#print("Auxilliary decomposition test:")
#load('superelliptic_drw/tests/auxilliary_decompositions_test.sage')
#print("Superelliptic de Rham-Witt test:")
#load('superelliptic_drw/tests/superelliptic_drw_tests.sage')