コード例 #1
0
    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
コード例 #2
0
    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
コード例 #3
0
    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
コード例 #4
0
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)