class superelliptic_form: def __init__(self, C, g): F = C.base_ring Rxy. = PolynomialRing(F, 2) Fxy = FractionField(Rxy) g = Fxy(reduction_form(C, g)) self.form = g self.curve = C def __eq__(self, other): if self.reduce().form == other.reduce().form: return True return False def __add__(self, other): C = self.curve g1 = self.form g2 = other.form g = reduction(C, g1 + g2) return superelliptic_form(C, g) def __sub__(self, other): C = self.curve g1 = self.form g2 = other.form g = reduction(C, g1 - g2) return superelliptic_form(C, g) def __neg__(self): C = self.curve g = self.form return superelliptic_form(C, -g) def __repr__(self): g = self.form if len(str(g)) == 1: return str(g) + ' dx' return '('+str(g) + ') dx' def __rmul__(self, constant): C = self.curve omega = self.form return superelliptic_form(C, constant*omega) def cartier(self): '''Computes Cartier operator on the form. Idea: y^m = f(x) -> y^(p^r - 1) = f(x)^M, where r = ord_p(m), M = (p^r - 1)/m. Thus h(x)/y^j dx = h(x) f(x)^(M*j)/y^(p^r * j) dx. Thus C(h(x)/y^j dx) = 1/y^(p^(r-1)*j) C(h(x) f(x)^(M*j) dx).''' C = self.curve m = C.exponent p = C.characteristic f = C.polynomial F = C.base_ring Rx. = PolynomialRing(F) Fx = FractionField(Rx) FxRy. = PolynomialRing(Fx) Fxy = FractionField(FxRy) result = 0*C.dx mult_order = Integers(m)(p).multiplicative_order() M = Integer((p^(mult_order)-1)/m) for j in range(0, m): fct_j = self.jth_component(j) h = Fx(fct_j*f^(M*j)) h_denom = h.denominator() h *= (h_denom)^(p) h = Rx(h) j1 = (p^(mult_order-1)*j)%m B = floor(p^(mult_order-1)*j/m) P = polynomial_part(p, h) if F.cardinality() != p: d = P.degree() P = sum(P[i].nth_root(p)*x^i for i in range(0, d+1)) result += superelliptic_form(C, P/(f^B*y^(j1)*h_denom)) return result def serre_duality_pairing(self, fct, prec=20): '''Compute Serre duality pairing of the form with a cohomology class in H1(X, OX) represented by function fct.''' result = 0 C = self.curve delta = C.nb_of_pts_at_infty for i in range(delta): result += (fct*self).expansion_at_infty(place=i, prec=prec)[-1] return -result def coordinates(self, basis = 0): """Find coordinates of the given holomorphic form self in terms of the basis forms in a list holo.""" C = self.curve if basis == 0: basis = C.holomorphic_differentials_basis() Fxy, Rxy, x, y = C.fct_field # We need to have only polynomials to use monomial_coefficients in linear_representation_polynomials, # and sometimes basis elements have denominators. Thus we multiply by them. denom = LCM([denominator(omega.form) for omega in basis]) basis = [denom*omega.form for omega in basis] self_with_no_denominator = denom*self.form return linear_representation_polynomials(Rxy(self_with_no_denominator), [Rxy(omega) for omega in basis]) def jth_component(self, j): '''If self = sum_j h_j(x)/y^j dx, output is h_j(x).''' g = self.form C = self.curve m = C.exponent F = C.base_ring Fxy, Rxy, x, y = C.fct_field g = reduction(C, y^m*g) Rx. = PolynomialRing(F) Fx = FractionField(Rx) FxRy. = PolynomialRing(Fx, 1) g = FxRy(g(x = x, y = y1)) if j == 0: return g.monomial_coefficient(y1^(0))/C.polynomial return g.monomial_coefficient(y1^(m-j)) def is_regular_on_U0(self): C = self.curve F = C.base_ring m = C.exponent Rx. = PolynomialRing(F) for j in range(0, m): if self.jth_component(j) not in Rx: return False return True def is_regular_on_Uinfty(self): C = self.curve F = C.base_ring m = C.exponent f = C.polynomial r = f.degree() delta = GCD(m, r) M = m/delta R = r/delta for j in range(1, m): A = self.jth_component(j) d = degree_of_rational_fctn(A, F) if(-d*M + j*R -(M+1)<0): return False return True def expansion_at_infty(self, place = 0, prec=10): g = self.form C = self.curve g = superelliptic_function(C, g) F = C.base_ring Rt. = LaurentSeriesRing(F, default_prec=prec) g = Rt(g.expansion_at_infty(place = place, prec=prec)) return g*C.dx_series[place] def expansion(self, pt, prec = 50): '''Expansion in the completed ring of the point pt. If pt is an integer, it means the corresponding place at infinity.''' if pt in ZZ: return self.expansion_at_infty(place=pt, prec=prec) C = self.curve dx_series = C.x.expansion(pt = pt, prec=prec).derivative() aux_fct = superelliptic_function(C, self.form) return aux_fct.expansion(pt=pt, prec=prec)*dx_series def residue(self, place = 0, prec=30): return self.expansion_at_infty(place = place, prec=prec)[-1] def reduce(self): fct = self.form C = self.curve fct = reduction(C, fct) return superelliptic_form(C, fct) def reduce2(self): fct = self.form C = self.curve m = C.exponent F = C.base_ring Rxy. = PolynomialRing(F, 2) Fxy = FractionField(Rxy) fct = reduction(C, Fxy(y^m*fct)) return superelliptic_form(C, fct/y^m) def int(self): '''Computes an "integral" of a form dg. Idea: y^m = f(x) -> y^(p^r - 1) = f(x)^M, where r = ord_p(m), M = (p^r - 1)/m. Thus h(x)/y^j dx = h(x) f(x)^(M*j)/y^(p^r * j) dx. Thus int(h(x)/y^j dx) = 1/y^(p^(r-1)*j) int(h(x) f(x)^(M*j) dx).''' C = self.curve m = C.exponent p = C.characteristic f = C.polynomial F = C.base_ring Rx. = PolynomialRing(F) Fx = FractionField(Rx) FxRy. = PolynomialRing(Fx) Fxy = FractionField(FxRy) result = 0*C.x mult_order = Integers(m)(p).multiplicative_order() M = Integer((p^(mult_order)-1)/m) for j in range(0, m): fct_j = self.jth_component(j) h = Fx(fct_j*f^(M*j)) h_denom = h.denominator() h *= (h_denom)^(p) h = Rx(h) j1 = (p^(mult_order)*j)%m B = floor(p^(mult_order)*j/m) result += superelliptic_function(C, h.integral()/(f^(B)*y^(j1)*h_denom^p)) return result def inv_cartier(omega): '''If omega is regular, return form eta such that Cartier(eta) = omega''' omega_regular = omega.regular_form() C = omega.curve p = C.characteristic return (omega_regular.dx)^p*C.x^(p-1)*C.dx + (omega_regular.dy)^p*C.y^(p-1)*C.y.diffn() def valuation(self, place = 0): '''Return valuation at i-th place at infinity.''' C = self.curve F = C.base_ring Rt. = LaurentSeriesRing(F) return Rt(self.expansion_at_infty(place = place)).valuation()