def curve_over_ram_extn(self, deg): r""" Returns self over $\Q_p(p^(1/deg))$ INPUT: - deg: the degree of the ramified extension OUTPUT: self over $\Q_p(p^(1/deg))$ EXAMPLES:: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x) sage: K = Qp(11,5) sage: HK = H.change_ring(K) sage: HL = HK.curve_over_ram_extn(2) sage: HL Hyperelliptic Curve over Eisenstein Extension of 11-adic Field with capped relative precision 5 in a defined by (1 + O(11^5))*x^2 + (O(11^6))*x + (10*11 + 10*11^2 + 10*11^3 + 10*11^4 + 10*11^5 + O(11^6)) defined by (1 + O(a^10))*y^2 = (1 + O(a^10))*x^5 + (10 + 8*a^2 + 10*a^4 + 10*a^6 + 10*a^8 + O(a^10))*x^3 + (7 + a^2 + O(a^10))*x^2 + (7 + 3*a^2 + O(a^10))*x AUTHOR: - Jennifer Balakrishnan """ from sage.schemes.hyperelliptic_curves.constructor import HyperellipticCurve K = self.base_ring() p = K.prime() A = PolynomialRing(QQ, "x") x = A.gen() J = K.extension(x ** deg - p, names="a") pol = self.hyperelliptic_polynomials()[0] H = HyperellipticCurve(A(pol)) HJ = H.change_ring(J) self._curve_over_ram_extn = HJ self._curve_over_ram_extn._curve_over_Qp = self return HJ
def curve_over_ram_extn(self, deg): r""" Return ``self`` over `\QQ_p(p^(1/deg))`. INPUT: - deg: the degree of the ramified extension OUTPUT: ``self`` over `\QQ_p(p^(1/deg))` EXAMPLES:: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x) sage: K = Qp(11,5) sage: HK = H.change_ring(K) sage: HL = HK.curve_over_ram_extn(2) sage: HL Hyperelliptic Curve over Eisenstein Extension in a defined by x^2 - 11 with capped relative precision 10 over 11-adic Field defined by (1 + O(a^10))*y^2 = (1 + O(a^10))*x^5 + (10 + 8*a^2 + 10*a^4 + 10*a^6 + 10*a^8 + O(a^10))*x^3 + (7 + a^2 + O(a^10))*x^2 + (7 + 3*a^2 + O(a^10))*x AUTHOR: - Jennifer Balakrishnan """ from sage.schemes.hyperelliptic_curves.constructor import HyperellipticCurve K = self.base_ring() p = K.prime() A = PolynomialRing(QQ, 'x') x = A.gen() J = K.extension(x**deg - p, names='a') pol = self.hyperelliptic_polynomials()[0] H = HyperellipticCurve(A(pol)) HJ = H.change_ring(J) self._curve_over_ram_extn = HJ self._curve_over_ram_extn._curve_over_Qp = self return HJ
def coleman_integrals_on_basis(self, P, Q, algorithm=None): r""" Computes the Coleman integrals `\{\int_P^Q x^i dx/2y \}_{i=0}^{2g-1}` INPUT: - P point on self - Q point on self - algorithm (optional) = None (uses Frobenius) or teichmuller (uses Teichmuller points) OUTPUT: the Coleman integrals `\{\int_P^Q x^i dx/2y \}_{i=0}^{2g-1}` EXAMPLES:: sage: K = pAdicField(11, 5) sage: x = polygen(K) sage: C = HyperellipticCurve(x^5 + 33/16*x^4 + 3/4*x^3 + 3/8*x^2 - 1/4*x + 1/16) sage: P = C.lift_x(2) sage: Q = C.lift_x(3) sage: C.coleman_integrals_on_basis(P, Q) (10*11 + 6*11^3 + 2*11^4 + O(11^5), 11 + 9*11^2 + 7*11^3 + 9*11^4 + O(11^5), 3 + 10*11 + 5*11^2 + 9*11^3 + 4*11^4 + O(11^5), 3 + 11 + 5*11^2 + 4*11^4 + O(11^5)) sage: C.coleman_integrals_on_basis(P, Q, algorithm='teichmuller') (10*11 + 6*11^3 + 2*11^4 + O(11^5), 11 + 9*11^2 + 7*11^3 + 9*11^4 + O(11^5), 3 + 10*11 + 5*11^2 + 9*11^3 + 4*11^4 + O(11^5), 3 + 11 + 5*11^2 + 4*11^4 + O(11^5)) :: sage: K = pAdicField(11,5) sage: x = polygen(K) sage: C = HyperellipticCurve(x^5 + 33/16*x^4 + 3/4*x^3 + 3/8*x^2 - 1/4*x + 1/16) sage: P = C.lift_x(11^(-2)) sage: Q = C.lift_x(3*11^(-2)) sage: C.coleman_integrals_on_basis(P, Q) (3*11^3 + 7*11^4 + 4*11^5 + 7*11^6 + 5*11^7 + O(11^8), 3*11 + 10*11^2 + 8*11^3 + 9*11^4 + 7*11^5 + O(11^6), 4*11^-1 + 2 + 6*11 + 6*11^2 + 7*11^3 + O(11^4), 11^-3 + 6*11^-2 + 2*11^-1 + 2 + O(11^2)) :: sage: R = C(0,1/4) sage: a = C.coleman_integrals_on_basis(P,R) # long time (7s on sage.math, 2011) sage: b = C.coleman_integrals_on_basis(R,Q) # long time (9s on sage.math, 2011) sage: c = C.coleman_integrals_on_basis(P,Q) # long time sage: a+b == c # long time True :: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^3-10*x+9) sage: K = Qp(5,8) sage: HK = H.change_ring(K) sage: S = HK(1,0) sage: P = HK(0,3) sage: T = HK(0,1,0) sage: Q = HK.lift_x(5^-2) sage: R = HK.lift_x(4*5^-2) sage: HK.coleman_integrals_on_basis(S,P) (2*5^2 + 5^4 + 5^5 + 3*5^6 + 3*5^7 + 2*5^8 + O(5^9), 5 + 2*5^2 + 4*5^3 + 2*5^4 + 3*5^6 + 4*5^7 + 2*5^8 + O(5^9)) sage: HK.coleman_integrals_on_basis(T,P) (2*5^2 + 5^4 + 5^5 + 3*5^6 + 3*5^7 + 2*5^8 + O(5^9), 5 + 2*5^2 + 4*5^3 + 2*5^4 + 3*5^6 + 4*5^7 + 2*5^8 + O(5^9)) sage: HK.coleman_integrals_on_basis(P,S) == -HK.coleman_integrals_on_basis(S,P) True sage: HK.coleman_integrals_on_basis(S,Q) (4*5 + 4*5^2 + 4*5^3 + O(5^4), 5^-1 + O(5^3)) sage: HK.coleman_integrals_on_basis(Q,R) (4*5 + 2*5^2 + 2*5^3 + 2*5^4 + 5^5 + 5^6 + 5^7 + 3*5^8 + O(5^9), 2*5^-1 + 4 + 4*5 + 4*5^2 + 4*5^3 + 2*5^4 + 3*5^5 + 2*5^6 + O(5^7)) sage: HK.coleman_integrals_on_basis(S,R) == HK.coleman_integrals_on_basis(S,Q) + HK.coleman_integrals_on_basis(Q,R) True sage: HK.coleman_integrals_on_basis(T,T) (0, 0) sage: HK.coleman_integrals_on_basis(S,T) (0, 0) AUTHORS: - Robert Bradshaw (2007-03): non-Weierstrass points - Jennifer Balakrishnan and Robert Bradshaw (2010-02): Weierstrass points """ import sage.schemes.hyperelliptic_curves.monsky_washnitzer as monsky_washnitzer from sage.misc.profiler import Profiler prof = Profiler() prof("setup") K = self.base_ring() p = K.prime() prec = K.precision_cap() g = self.genus() dim = 2 * g V = VectorSpace(K, dim) #if P or Q is Weierstrass, use the Frobenius algorithm if self.is_weierstrass(P): if self.is_weierstrass(Q): return V(0) else: PP = None QQ = Q TP = None TQ = self.frobenius(Q) elif self.is_weierstrass(Q): PP = P QQ = None TQ = None TP = self.frobenius(P) elif self.is_same_disc(P, Q): return self.tiny_integrals_on_basis(P, Q) elif algorithm == 'teichmuller': prof("teichmuller") PP = TP = self.teichmuller(P) QQ = TQ = self.teichmuller(Q) evalP, evalQ = TP, TQ else: prof("frobPQ") TP = self.frobenius(P) TQ = self.frobenius(Q) PP, QQ = P, Q prof("tiny integrals") if TP is None: P_to_TP = V(0) else: if TP is not None: TPv = (TP[0]**g / TP[1]).valuation() xTPv = TP[0].valuation() else: xTPv = TPv = +Infinity if TQ is not None: TQv = (TQ[0]**g / TQ[1]).valuation() xTQv = TQ[0].valuation() else: xTQv = TQv = +Infinity offset = (2 * g - 1) * max(TPv, TQv) if offset == +Infinity: offset = (2 * g - 1) * min(TPv, TQv) if (offset > prec and (xTPv < 0 or xTQv < 0) and (self.residue_disc(P) == self.change_ring(GF(p))(0, 1, 0) or self.residue_disc(Q) == self.change_ring(GF(p))(0, 1, 0))): newprec = offset + prec K = pAdicField(p, newprec) A = PolynomialRing(RationalField(), 'x') f = A(self.hyperelliptic_polynomials()[0]) from sage.schemes.hyperelliptic_curves.constructor import HyperellipticCurve self = HyperellipticCurve(f).change_ring(K) xP = P[0] xPv = xP.valuation() xPnew = K( sum(c * p**(xPv + i) for i, c in enumerate(xP.expansion()))) PP = P = self.lift_x(xPnew) TP = self.frobenius(P) xQ = Q[0] xQv = xQ.valuation() xQnew = K( sum(c * p**(xQv + i) for i, c in enumerate(xQ.expansion()))) QQ = Q = self.lift_x(xQnew) TQ = self.frobenius(Q) V = VectorSpace(K, dim) P_to_TP = V(self.tiny_integrals_on_basis(P, TP)) if TQ is None: TQ_to_Q = V(0) else: TQ_to_Q = V(self.tiny_integrals_on_basis(TQ, Q)) prof("mw calc") try: M_frob, forms = self._frob_calc except AttributeError: M_frob, forms = self._frob_calc = monsky_washnitzer.matrix_of_frobenius_hyperelliptic( self) prof("eval f") R = forms[0].base_ring() try: prof("eval f %s" % R) if PP is None: L = [-f(R(QQ[0]), R(QQ[1])) for f in forms] ##changed elif QQ is None: L = [f(R(PP[0]), R(PP[1])) for f in forms] else: L = [ f(R(PP[0]), R(PP[1])) - f(R(QQ[0]), R(QQ[1])) for f in forms ] except ValueError: prof("changing rings") forms = [f.change_ring(self.base_ring()) for f in forms] prof("eval f %s" % self.base_ring()) if PP is None: L = [-f(QQ[0], QQ[1]) for f in forms] ##changed elif QQ is None: L = [f(PP[0], PP[1]) for f in forms] else: L = [f(PP[0], PP[1]) - f(QQ[0], QQ[1]) for f in forms] b = V(L) if PP is None: b -= TQ_to_Q elif QQ is None: b -= P_to_TP elif algorithm != 'teichmuller': b -= P_to_TP + TQ_to_Q prof("lin alg") M_sys = matrix(K, M_frob).transpose() - 1 TP_to_TQ = M_sys**(-1) * b prof("done") # print prof if algorithm == 'teichmuller': return P_to_TP + TP_to_TQ + TQ_to_Q else: return TP_to_TQ
def HyperellipticCurve_from_invariants(i, reduced=True, precision=None, algorithm='default'): r""" Returns a hyperelliptic curve with the given Igusa-Clebsch invariants up to scaling. The output is a curve over the field in which the Igusa-Clebsch invariants are given. The output curve is unique up to isomorphism over the algebraic closure. If no such curve exists over the given field, then raise a ValueError. INPUT: - ``i`` - list or tuple of length 4 containing the four Igusa-Clebsch invariants: I2,I4,I6,I10. - ``reduced`` - Boolean (default = True) If True, tries to reduce the polynomial defining the hyperelliptic curve using the function :func:`reduce_polynomial` (see the :func:`reduce_polynomial` documentation for more details). - ``precision`` - integer (default = None) Which precision for real and complex numbers should the reduction use. This only affects the reduction, not the correctness. If None, the algorithm uses the default 53 bit precision. - ``algorithm`` - ``'default'`` or ``'magma'``. If set to ``'magma'``, uses Magma to parameterize Mestre's conic (needs Magma to be installed). OUTPUT: A hyperelliptic curve object. EXAMPLES: Examples over the rationals:: sage: HyperellipticCurve_from_invariants([3840,414720,491028480,2437709561856]) Traceback (most recent call last): ... NotImplementedError: Reduction of hyperelliptic curves not yet implemented. See trac #14755 and #14756. sage: HyperellipticCurve_from_invariants([3840,414720,491028480,2437709561856],reduced = False) Hyperelliptic Curve over Rational Field defined by y^2 = -46656*x^6 + 46656*x^5 - 19440*x^4 + 4320*x^3 - 540*x^2 + 4410*x - 1 sage: HyperellipticCurve_from_invariants([21, 225/64, 22941/512, 1]) Traceback (most recent call last): ... NotImplementedError: Reduction of hyperelliptic curves not yet implemented. See trac #14755 and #14756. An example over a finite field:: sage: HyperellipticCurve_from_invariants([GF(13)(1),3,7,5]) Hyperelliptic Curve over Finite Field of size 13 defined by y^2 = 8*x^5 + 5*x^4 + 5*x^2 + 9*x + 3 An example over a number field:: sage: K = QuadraticField(353, 'a') sage: H = HyperellipticCurve_from_invariants([21, 225/64, 22941/512, 1], reduced = false) sage: f = K['x'](H.hyperelliptic_polynomials()[0]) If the Mestre Conic defined by the Igusa-Clebsch invariants has no rational points, then there exists no hyperelliptic curve over the base field with the given invariants.:: sage: HyperellipticCurve_from_invariants([1,2,3,4]) Traceback (most recent call last): ... ValueError: No such curve exists over Rational Field as there are no rational points on Projective Conic Curve over Rational Field defined by -2572155000*u^2 - 317736000*u*v + 1250755459200*v^2 + 2501510918400*u*w + 39276887040*v*w + 2736219686912*w^2 Mestre's algorithm only works for generic curves of genus two, so another algorithm is needed for those curves with extra automorphism. See also :trac:`12199`:: sage: P.<x> = QQ[] sage: C = HyperellipticCurve(x^6+1) sage: i = C.igusa_clebsch_invariants() sage: HyperellipticCurve_from_invariants(i) Traceback (most recent call last): ... TypeError: F (=0) must have degree 2 Igusa-Clebsch invariants also only work over fields of characteristic different from 2, 3, and 5, so another algorithm will be needed for fields of those characteristics. See also :trac:`12200`:: sage: P.<x> = GF(3)[] sage: HyperellipticCurve(x^6+x+1).igusa_clebsch_invariants() Traceback (most recent call last): ... NotImplementedError: Invariants of binary sextics/genus 2 hyperelliptic curves not implemented in characteristics 2, 3, and 5 sage: HyperellipticCurve_from_invariants([GF(5)(1),1,0,1]) Traceback (most recent call last): ... ZeroDivisionError: Inverse does not exist. ALGORITHM: This is Mestre's algorithm [M1991]_. Our implementation is based on the formulae on page 957 of [LY2001]_, cross-referenced with [W1999]_ to correct typos. First construct Mestre's conic using the :func:`Mestre_conic` function. Parametrize the conic if possible. Let `f_1, f_2, f_3` be the three coordinates of the parametrization of the conic by the projective line, and change them into one variable by letting `F_i = f_i(t, 1)`. Note that each `F_i` has degree at most 2. Then construct a sextic polynomial `f = \sum_{0<=i,j,k<=3}{c_{ijk}*F_i*F_j*F_k}`, where `c_{ijk}` are defined as rational functions in the invariants (see the source code for detailed formulae for `c_{ijk}`). The output is the hyperelliptic curve `y^2 = f`. REFERENCES: .. [LY2001] \K. Lauter and T. Yang, "Computing genus 2 curves from invariants on the Hilbert moduli space", Journal of Number Theory 131 (2011), pages 936 - 958 .. [M1991] \J.-F. Mestre, "Construction de courbes de genre 2 a partir de leurs modules", in Effective methods in algebraic geometry (Castiglioncello, 1990), volume 94 of Progr. Math., pages 313 - 334 .. [W1999] \P. van Wamelen, Pari-GP code, section "thecubic" https://www.math.lsu.edu/~wamelen/Genus2/FindCurve/igusa2curve.gp """ from sage.structure.sequence import Sequence i = Sequence(i) k = i.universe() try: k = k.fraction_field() except (TypeError, AttributeError, NotImplementedError): pass MConic, x, y, z = Mestre_conic(i, xyz=True) if k.is_finite(): reduced = False t = k['t'].gen() if algorithm == 'magma': from sage.interfaces.all import magma from sage.misc.sage_eval import sage_eval if MConic.has_rational_point(algorithm='magma'): parametrization = [l.replace('$.1', 't').replace('$.2', 'u') \ for l in str(magma(MConic).Parametrization()).splitlines()[4:7]] [F1, F2, F3] = [sage_eval(p, locals={'t':t,'u':1,'a':k.gen()}) \ for p in parametrization] else: raise ValueError("No such curve exists over %s as there are no " \ "rational points on %s" % (k, MConic)) else: if MConic.has_rational_point(): parametrization = MConic.parametrization(morphism=False)[0] [F1, F2, F3] = [p(t, 1) for p in parametrization] else: raise ValueError("No such curve exists over %s as there are no " \ "rational points on %s" % (k, MConic)) # setting the cijk from Mestre's algorithm c111 = 12 * x * y - 2 * y / 3 - 4 * z c112 = -18 * x**3 - 12 * x * y - 36 * y**2 - 2 * z c113 = -9 * x**3 - 36 * x**2 * y - 4 * x * y - 6 * x * z - 18 * y**2 c122 = c113 c123 = -54 * x**4 - 36 * x**2 * y - 36 * x * y**2 - 6 * x * z - 4 * y**2 - 24 * y * z c133 = -27*x**4/2 - 72*x**3*y - 6*x**2*y - 9*x**2*z - 39*x*y**2 - \ 36*y**3 - 2*y*z c222 = -27 * x**4 - 18 * x**2 * y - 6 * x * y**2 - 8 * y**2 / 3 + 2 * y * z c223 = 9 * x**3 * y - 27 * x**2 * z + 6 * x * y**2 + 18 * y**3 - 8 * y * z c233 = -81 * x**5 / 2 - 27 * x**3 * y - 9 * x**2 * y**2 - 4 * x * y**2 + 3 * x * y * z - 6 * z**2 c333 = 27*x**4*y/2 - 27*x**3*z/2 + 9*x**2*y**2 + 3*x*y**3 - 6*x*y*z + \ 4*y**3/3 - 10*y**2*z # writing out the hyperelliptic curve polynomial f = c111*F1**3 + c112*F1**2*F2 + c113*F1**2*F3 + c122*F1*F2**2 + \ c123*F1*F2*F3 + c133*F1*F3**2 + c222*F2**3 + c223*F2**2*F3 + \ c233*F2*F3**2 + c333*F3**3 try: f = f * f.denominator() # clear the denominator except (AttributeError, TypeError): pass if reduced: raise NotImplementedError("Reduction of hyperelliptic curves not " \ "yet implemented. " \ "See trac #14755 and #14756.") return HyperellipticCurve(f)