Exemplo n.º 1
0
    def sigma(self, prec=10):
        """
        EXAMPLES::

            sage: E = EllipticCurve('14a')
            sage: F = E.formal_group()
            sage: F.sigma(5)
            t + 1/2*t^2 + (1/2*c + 1/3)*t^3 + (3/4*c + 3/4)*t^4 + O(t^5)
        """
        a1,a2,a3,a4,a6 = self.curve().ainvs()

        k = self.curve().base_ring()
        fl = self.log(prec)
        R = rings.PolynomialRing(k,'c'); c = R.gen()
        F = fl.reverse()

        S = rings.LaurentSeriesRing(R,'z')
        c = S(c)
        z = S.gen()
        F = F(z + O(z**prec))
        wp = self.x()(F)
        e2 = 12*c - a1**2 - 4*a2
        g = (1/z**2 - wp + e2/12).power_series()
        h = g.integral().integral()
        sigma_of_z = z.power_series() * h.exp()

        T = rings.PowerSeriesRing(R,'t')
        fl = fl(T.gen()+O(T.gen()**prec))
        sigma_of_t = sigma_of_z(fl)
        return sigma_of_t
Exemplo n.º 2
0
def EllipticCurve_from_cubic(F, P, morphism=True):
    r"""
    Construct an elliptic curve from a ternary cubic with a rational point.

    If you just want the Weierstrass form and are not interested in
    the morphism then it is easier to use
    :func:`~sage.schemes.elliptic_curves.jacobian.Jacobian`
    instead. This will construct the same elliptic curve but you don't
    have to supply the point ``P``.

    INPUT:

    - ``F`` -- a homogeneous cubic in three variables with rational
      coefficients, as a polynomial ring element, defining a smooth
      plane cubic curve.

    - ``P`` -- a 3-tuple `(x,y,z)` defining a projective point on the
      curve `F=0`. Need not be a flex, but see caveat on output.

    - ``morphism`` -- boolean (default: ``True``). Whether to return
      the morphism or just the elliptic curve.

    OUTPUT:

    An elliptic curve in long Weierstrass form isomorphic to the curve
    `F=0`.

    If ``morphism=True`` is passed, then a birational equivalence
    between F and the Weierstrass curve is returned. If the point
    happens to be a flex, then this is an isomorphism.

    EXAMPLES:

    First we find that the Fermat cubic is isomorphic to the curve
    with Cremona label 27a1::

        sage: R.<x,y,z> = QQ[]
        sage: cubic = x^3+y^3+z^3
        sage: P = [1,-1,0]
        sage: E = EllipticCurve_from_cubic(cubic, P, morphism=False); E
        Elliptic Curve defined by y^2 + 2*x*y + 1/3*y = x^3 - x^2 - 1/3*x - 1/27 over Rational Field
        sage: E.cremona_label()
        '27a1'
        sage: EllipticCurve_from_cubic(cubic, [0,1,-1], morphism=False).cremona_label()
        '27a1'
        sage: EllipticCurve_from_cubic(cubic, [1,0,-1], morphism=False).cremona_label()
        '27a1'

    Next we find the minimal model and conductor of the Jacobian of the
    Selmer curve::

        sage: R.<a,b,c> = QQ[]
        sage: cubic = a^3+b^3+60*c^3
        sage: P = [1,-1,0]
        sage: E = EllipticCurve_from_cubic(cubic, P, morphism=False);  E
        Elliptic Curve defined by y^2 + 2*x*y + 20*y = x^3 - x^2 - 20*x - 400/3 over Rational Field
        sage: E.minimal_model()
        Elliptic Curve defined by y^2 = x^3 - 24300 over Rational Field
        sage: E.conductor()
        24300

    We can also get the birational equivalence to and from the
    Weierstrass form. We start with an example where ``P`` is a flex
    and the equivalence is an isomorphism::

        sage: f = EllipticCurve_from_cubic(cubic, P, morphism=True)
        sage: f
        Scheme morphism:
          From: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:
                a^3 + b^3 + 60*c^3
          To:   Elliptic Curve defined by y^2 + 2*x*y + 20*y = x^3 - x^2 - 20*x - 400/3
                over Rational Field
          Defn: Defined on coordinates by sending (a : b : c) to
                (-c : -b + c : 1/20*a + 1/20*b)

        sage: finv = f.inverse();  finv
        Scheme morphism:
          From: Elliptic Curve defined by y^2 + 2*x*y + 20*y = x^3 - x^2 - 20*x - 400/3
                over Rational Field
          To:   Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:
          a^3 + b^3 + 60*c^3
          Defn: Defined on coordinates by sending (x : y : z) to
                (x + y + 20*z : -x - y : -x)

    We verify that `f` maps the chosen point `P=(1,-1,0)` on the cubic
    to the origin of the elliptic curve::

        sage: f([1,-1,0])
        (0 : 1 : 0)
        sage: finv([0,1,0])
        (-1 : 1 : 0)

    To verify the output, we plug in the polynomials to check that
    this indeed transforms the cubic into Weierstrass form::

        sage: cubic(finv.defining_polynomials()) * finv.post_rescaling()
        -x^3 + x^2*z + 2*x*y*z + y^2*z + 20*x*z^2 + 20*y*z^2 + 400/3*z^3

        sage: E.defining_polynomial()(f.defining_polynomials()) * f.post_rescaling()
        a^3 + b^3 + 60*c^3

    If the point is not a flex then the cubic can not be transformed
    to a Weierstrass equation by a linear transformation. The general
    birational transformation is quadratic::

        sage: cubic =  a^3+7*b^3+64*c^3
        sage: P = [2,2,-1]
        sage: f = EllipticCurve_from_cubic(cubic, P, morphism=True)
        sage: E = f.codomain();  E
        Elliptic Curve defined by y^2 - 722*x*y - 21870000*y = x^3
        + 23579*x^2 over Rational Field
        sage: E.minimal_model()
        Elliptic Curve defined by y^2 + y = x^3 - 331 over Rational Field

        sage: f
        Scheme morphism:
          From: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:
                a^3 + 7*b^3 + 64*c^3
          To:   Elliptic Curve defined by y^2 - 722*x*y - 21870000*y =
                x^3 + 23579*x^2 over Rational Field
          Defn: Defined on coordinates by sending (a : b : c) to
                (-5/112896*a^2 - 17/40320*a*b - 1/1280*b^2 - 29/35280*a*c
                 - 13/5040*b*c - 4/2205*c^2 :
                 -4055/112896*a^2 - 4787/40320*a*b - 91/1280*b^2 - 7769/35280*a*c
                 - 1993/5040*b*c - 724/2205*c^2 :
                 1/4572288000*a^2 + 1/326592000*a*b + 1/93312000*b^2 + 1/142884000*a*c
                 + 1/20412000*b*c + 1/17860500*c^2)

        sage: finv = f.inverse();  finv
        Scheme morphism:
          From: Elliptic Curve defined by y^2 - 722*x*y - 21870000*y =
                x^3 + 23579*x^2 over Rational Field
          To:   Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:
                a^3 + 7*b^3 + 64*c^3
          Defn: Defined on coordinates by sending (x : y : z) to
                (2*x^2 + 227700*x*z - 900*y*z :
                 2*x^2 - 32940*x*z + 540*y*z :
                 -x^2 - 56520*x*z - 180*y*z)

        sage: cubic(finv.defining_polynomials()) * finv.post_rescaling()
        -x^3 - 23579*x^2*z - 722*x*y*z + y^2*z - 21870000*y*z^2

        sage: E.defining_polynomial()(f.defining_polynomials()) * f.post_rescaling()
        a^3 + 7*b^3 + 64*c^3

    TESTS::

        sage: R.<x,y,z> = QQ[]
        sage: cubic = x^2*y + 4*x*y^2 + x^2*z + 8*x*y*z + 4*y^2*z + 9*x*z^2 + 9*y*z^2
        sage: EllipticCurve_from_cubic(cubic, [1,-1,1], morphism=False)
        Elliptic Curve defined by y^2 - 882*x*y - 2560000*y = x^3 - 127281*x^2 over Rational Field
    """
    import sage.matrix.all as matrix

    # check the input
    R = F.parent()
    if not is_MPolynomialRing(R):
        raise TypeError('equation must be a polynomial')
    if R.ngens() != 3:
        raise TypeError('equation must be a polynomial in three variables')
    if not F.is_homogeneous():
        raise TypeError('equation must be a homogeneous polynomial')
    K = F.parent().base_ring()
    try:
        P = [K(c) for c in P]
    except TypeError:
        raise TypeError('cannot convert %s into %s' % (P, K))
    if F(P) != 0:
        raise ValueError('%s is not a point on %s' % (P, F))
    if len(P) != 3:
        raise TypeError('%s is not a projective point' % P)
    x, y, z = R.gens()

    # First case: if P = P2 then P is a flex
    P2 = chord_and_tangent(F, P)
    if are_projectively_equivalent(P, P2, base_ring=K):
        # find the tangent to F in P
        dx = K(F.derivative(x)(P))
        dy = K(F.derivative(y)(P))
        dz = K(F.derivative(z)(P))
        # find a second point Q on the tangent line but not on the cubic
        for tangent in [[dy, -dx, K.zero()], [dz, K.zero(), -dx],
                        [K.zero(), -dz, dx]]:
            tangent = projective_point(tangent)
            Q = [tangent[0] + P[0], tangent[1] + P[1], tangent[2] + P[2]]
            F_Q = F(Q)
            if F_Q != 0:  # At most one further point may accidentally be on the cubic
                break
        assert F_Q != 0
        # pick linearly independent third point
        for third_point in [(1, 0, 0), (0, 1, 0), (0, 0, 1)]:
            M = matrix.matrix(K, [Q, P, third_point]).transpose()
            if M.is_invertible():
                break
        F2 = R(M.act_on_polynomial(F))
        # scale and dehomogenise
        a = K(F2.coefficient(x**3))
        F3 = F2 / a
        b = K(F3.coefficient(y * y * z))
        S = rings.PolynomialRing(K, 'x,y,z')
        # elliptic curve coordinates
        X, Y, Z = S.gen(0), S.gen(1), S(-1 / b) * S.gen(2)
        F4 = F3(X, Y, Z)
        E = EllipticCurve(F4.subs(z=1))
        if not morphism:
            return E
        inv_defining_poly = [
            M[i, 0] * X + M[i, 1] * Y + M[i, 2] * Z for i in range(3)
        ]
        inv_post = -1 / a
        M = M.inverse()
        trans_x, trans_y, trans_z = [
            M[i, 0] * x + M[i, 1] * y + M[i, 2] * z for i in range(3)
        ]
        fwd_defining_poly = [trans_x, trans_y, -b * trans_z]
        fwd_post = -a

    # Second case: P is not a flex, then P, P2, P3 are different
    else:
        P3 = chord_and_tangent(F, P2)
        # send P, P2, P3 to (1:0:0), (0:1:0), (0:0:1) respectively
        M = matrix.matrix(K, [P, P2, P3]).transpose()
        F2 = M.act_on_polynomial(F)
        # substitute x = U^2, y = V*W, z = U*W, and rename (x,y,z)=(U,V,W)
        F3 = F2.substitute({x: x**2, y: y * z, z: x * z}) // (x**2 * z)
        # scale and dehomogenise
        a = K(F3.coefficient(x**3))
        F4 = F3 / a
        b = K(F4.coefficient(y * y * z))
        # change to a polynomial in only two variables
        S = rings.PolynomialRing(K, 'x,y,z')
        # elliptic curve coordinates
        X, Y, Z = S.gen(0), S.gen(1), S(-1 / b) * S.gen(2)
        F5 = F4(X, Y, Z)
        E = EllipticCurve(F5.subs(z=1))
        if not morphism:
            return E
        inv_defining_poly = [
            M[i, 0] * X * X + M[i, 1] * Y * Z + M[i, 2] * X * Z
            for i in range(3)
        ]
        inv_post = -1 / a / (X**2) / Z
        M = M.inverse()
        trans_x, trans_y, trans_z = [(M[i, 0] * x + M[i, 1] * y + M[i, 2] * z)
                                     for i in range(3)]
        fwd_defining_poly = [
            trans_x * trans_z, trans_x * trans_y, -b * trans_z * trans_z
        ]
        fwd_post = -a / (trans_x * trans_z * trans_z)

    # Construct the morphism
    from sage.schemes.projective.projective_space import ProjectiveSpace
    P2 = ProjectiveSpace(2, K, names=[str(_) for _ in R.gens()])
    cubic = P2.subscheme(F)
    from sage.schemes.elliptic_curves.weierstrass_transform import \
        WeierstrassTransformationWithInverse
    return WeierstrassTransformationWithInverse(cubic, E, fwd_defining_poly,
                                                fwd_post, inv_defining_poly,
                                                inv_post)
Exemplo n.º 3
0
def chord_and_tangent(F, P):
    """
    Use the chord and tangent method to get another point on a cubic.

    INPUT:

    - ``F`` -- a homogeneous cubic in three variables with rational
      coefficients, as a polynomial ring element, defining a smooth
      plane cubic curve.

    - ``P`` -- a 3-tuple `(x,y,z)` defining a projective point on the
      curve `F=0`.

    OUTPUT:

    Another point satisfying the equation ``F``.

    EXAMPLES::

        sage: R.<x,y,z> = QQ[]
        sage: from sage.schemes.elliptic_curves.constructor import chord_and_tangent
        sage: F = x^3+y^3+60*z^3
        sage: chord_and_tangent(F, [1,-1,0])
        [1, -1, 0]

        sage: F = x^3+7*y^3+64*z^3
        sage: p0 = [2,2,-1]
        sage: p1 = chord_and_tangent(F, p0);  p1
        [-5, 3, -1]
        sage: p2 = chord_and_tangent(F, p1);  p2
        [1265, -183, -314]

    TESTS::

        sage: F(p2)
        0
        sage: list(map(type, p2))
        [<type 'sage.rings.rational.Rational'>,
         <type 'sage.rings.rational.Rational'>,
         <type 'sage.rings.rational.Rational'>]

    See :trac:`16068`::

        sage: F = x**3 - 4*x**2*y - 65*x*y**2 + 3*x*y*z - 76*y*z**2
        sage: chord_and_tangent(F, [0, 1, 0])
        [0, 0, -1]
    """
    # check the input
    R = F.parent()
    if not is_MPolynomialRing(R):
        raise TypeError('equation must be a polynomial')
    if R.ngens() != 3:
        raise TypeError('%s is not a polynomial in three variables' % F)
    if not F.is_homogeneous():
        raise TypeError('%s is not a homogeneous polynomial' % F)
    x, y, z = R.gens()
    if len(P) != 3:
        raise TypeError('%s is not a projective point' % P)
    K = R.base_ring()
    try:
        P = [K(c) for c in P]
    except TypeError:
        raise TypeError('cannot coerce %s into %s' % (P, K))
    if F(P) != 0:
        raise ValueError('%s is not a point on %s' % (P, F))

    # find the tangent to F in P
    dx = K(F.derivative(x)(P))
    dy = K(F.derivative(y)(P))
    dz = K(F.derivative(z)(P))
    # if dF/dy(P) = 0, change variables so that dF/dy != 0
    if dy == 0:
        if dx != 0:
            g = F.substitute({x: y, y: x})
            Q = [P[1], P[0], P[2]]
            R = chord_and_tangent(g, Q)
            return [R[1], R[0], R[2]]
        elif dz != 0:
            g = F.substitute({y: z, z: y})
            Q = [P[0], P[2], P[1]]
            R = chord_and_tangent(g, Q)
            return [R[0], R[2], R[1]]
        else:
            raise ValueError('%s is singular at %s' % (F, P))

    # t will be our choice of parmeter of the tangent plane
    #     dx*(x-P[0]) + dy*(y-P[1]) + dz*(z-P[2])
    # through the point P
    t = rings.PolynomialRing(K, 't').gen(0)
    Ft = F(dy * t + P[0], -dx * t + P[1], P[2])
    if Ft == 0:  # (dy, -dx, 0) is projectively equivalent to P
        # then (0, -dz, dy) is not projectively equivalent to P
        g = F.substitute({x: z, z: x})
        Q = [P[2], P[1], P[0]]
        R = chord_and_tangent(g, Q)
        return [R[2], R[1], R[0]]
    # Ft has a double zero at t=0 by construction, which we now remove
    Ft = Ft // t**2

    # first case: the third point is at t=infinity
    if Ft.is_constant():
        return projective_point([dy, -dx, K(0)])
    # second case: the third point is at finite t
    else:
        assert Ft.degree() == 1
        t0 = Ft.roots()[0][0]
        return projective_point([dy * t0 + P[0], -dx * t0 + P[1], P[2]])
Exemplo n.º 4
0
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#                  http://www.gnu.org/licenses/
#*****************************************************************************

import math

import sage.modular.hecke.all as hecke
import sage.rings.all as rings
from sage.arith.all import kronecker, next_prime
from sage.matrix.matrix_space import MatrixSpace
from sage.modular.arithgroup.all import Gamma0
from sage.libs.pari.all import pari
from sage.misc.misc import verbose

ZZy = rings.PolynomialRing(rings.ZZ, 'y')


def Phi2_quad(J3, ssJ1, ssJ2):
    r"""
    This function returns a certain quadratic polynomial over a finite
    field in indeterminate J3.

    The roots of the polynomial along with ssJ1 are the
    neighboring/2-isogenous supersingular j-invariants of ssJ2.

    INPUT:

    - ``J3`` -- indeterminate of a univariate polynomial ring defined over a finite
      field with p^2 elements where p is a prime number