Esempio n. 1
0
def Jacobian_of_equation(polynomial, variables=None, curve=None):
    r"""
    Construct the Jacobian of a genus-one curve given by a polynomial.

    INPUT:

    - ``F`` -- a polynomial defining a plane curve of genus one. May
      be homogeneous or inhomogeneous.

    - ``variables`` -- list of two or three variables or ``None``
      (default). The inhomogeneous or homogeneous coordinates. By
      default, all variables in the polynomial are used.

    - ``curve`` -- the genus-one curve defined by ``polynomial`` or #
      ``None`` (default). If specified, suitable morphism from the
      jacobian elliptic curve to the curve is returned.

    OUTPUT:

    An elliptic curve in short Weierstrass form isomorphic to the
    curve ``polynomial=0``. If the optional argument ``curve`` is
    specified, a rational multicover from the Jacobian elliptic curve
    to the genus-one curve is returned.

    EXAMPLES::

        sage: R.<a,b,c> = QQ[]
        sage: f = a^3+b^3+60*c^3
        sage: Jacobian(f)
        Elliptic Curve defined by y^2 = x^3 - 24300 over Rational Field
        sage: Jacobian(f.subs(c=1))
        Elliptic Curve defined by y^2 = x^3 - 24300 over Rational Field

    If we specify the domain curve the birational covering is returned::

        sage: h = Jacobian(f, curve=Curve(f));  h
        Scheme morphism:
          From: Projective Plane Curve over Rational Field defined by a^3 + b^3 + 60*c^3
          To:   Elliptic Curve defined by y^2 = x^3 - 24300 over Rational Field
          Defn: Defined on coordinates by sending (a : b : c) to
                (-216000*a^4*b^4*c - 12960000*a^4*b*c^4 - 12960000*a*b^4*c^4 :
                108000*a^6*b^3 - 108000*a^3*b^6 - 6480000*a^6*c^3 + 6480000*b^6*c^3 + 388800000*a^3*c^6 - 388800000*b^3*c^6 :
                216000*a^3*b^3*c^3)

        sage: h([1,-1,0])
        (0 : 1 : 0)

    Plugging in the polynomials defining `h` allows us to verify that
    it is indeed a rational morphism to the elliptic curve::

        sage: E = h.codomain()
        sage: E.defining_polynomial()(h.defining_polynomials()).factor()
        (2519424000000000) * c^3 * b^3 * a^3 * (a^3 + b^3 + 60*c^3) *
        (a^9*b^6 + a^6*b^9 - 120*a^9*b^3*c^3 + 900*a^6*b^6*c^3 - 120*a^3*b^9*c^3 +
        3600*a^9*c^6 + 54000*a^6*b^3*c^6 + 54000*a^3*b^6*c^6 + 3600*b^9*c^6 +
        216000*a^6*c^9 - 432000*a^3*b^3*c^9 + 216000*b^6*c^9)


    By specifying the variables, we can also construct an elliptic
    curve over a polynomial ring::

        sage: R.<u,v,t> = QQ[]
        sage: Jacobian(u^3+v^3+t, variables=[u,v])
        Elliptic Curve defined by y^2 = x^3 + (-27/4*t^2) over
        Multivariate Polynomial Ring in u, v, t over Rational Field

    TESTS::

        sage: from sage.schemes.elliptic_curves.jacobian import Jacobian_of_equation
        sage: Jacobian_of_equation(f, variables=[a,b,c])
        Elliptic Curve defined by y^2 = x^3 - 24300 over Rational Field
    """
    from sage.schemes.toric.weierstrass import WeierstrassForm
    f, g = WeierstrassForm(polynomial, variables=variables)
    try:
        K = polynomial.base_ring()
        f = K(f)
        g = K(g)
    except (TypeError, ValueError):
        pass
    E = EllipticCurve([f, g])
    if curve is None:
        return E
    X, Y, Z = WeierstrassForm(polynomial, variables=variables, transformation=True)
    from sage.schemes.elliptic_curves.weierstrass_transform import WeierstrassTransformation
    return WeierstrassTransformation(curve, E, [X*Z, Y, Z**3], 1)
Esempio n. 2
0
    def _find_scaling_period(self):
        r"""
        Uses the integral period map of the modular symbol implementation in sage
        in order to determine the scaling. The resulting modular symbol is correct
        only for the `X_0`-optimal curve, at least up to a possible factor +- a
        power of 2.

        EXAMPLES::

            sage: E = EllipticCurve('11a1')
            sage: m = sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1,normalize='period')
            sage: m._e
            (1/5, 1)
            sage: E = EllipticCurve('11a2')
            sage: m = sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1,normalize='period')
            sage: m._e
            (1, 5)
            sage: E = EllipticCurve('121b2')
            sage: m = sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1,normalize='period')
            sage: m._e
            (0, 11/2, 0, 11/2, 11/2, 0, 0, -3, 2, 1/2, -1, 3/2)

        TESTS::

            sage: E = EllipticCurve('19a1')
            sage: m = E.modular_symbol(sign=+1, implementation='sage', normalize='none')
            sage: m._find_scaling_period()
            sage: m._scaling
            1

            sage: E = EllipticCurve('19a2')
            sage: m = E.modular_symbol(sign=+1, implementation='sage', normalize='none')
            sage: m._scaling
            1
            sage: m._find_scaling_period()
            sage: m._scaling
            3
        """
        P = self._modsym.integral_period_mapping()
        self._e = P.matrix().transpose().row(0)
        self._e /= 2
        E = self._E
        try:
            crla = parse_cremona_label(E.label())
        except RuntimeError:  # raised when curve is outside of the table
            print(
                "Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by a rational number."
            )
            self._scaling = 1
        else:
            cr0 = Integer(crla[0]).str() + crla[1] + '1'
            E0 = EllipticCurve(cr0)
            if self._sign == 1:
                q = E0.period_lattice().basis()[0] / E.period_lattice().basis(
                )[0]
            else:
                q = E0.period_lattice().basis()[1].imag() / E.period_lattice(
                ).basis()[1].imag()
                if E0.real_components() == 1:
                    q *= 2
                if E.real_components() == 1:
                    q /= 2
            q = QQ(int(round(q * 200))) / 200
            verbose('scale modular symbols by %s' % q)
            self._scaling = q
        c = self(0)  #  required, to change base point from oo to 0
        if c < 0:
            c *= -1
            self._scaling *= -1
        self._at_zero = c
        self._e *= self._scaling
Esempio n. 3
0
def torsion_bound(E, number_of_places=20):
    r"""
    Return an upper bound on the order of the torsion subgroup.

    INPUT:

    - ``E`` -- an elliptic curve over `\QQ` or a number field

    - ``number_of_places`` (positive integer, default = 20) -- the
        number of places that will be used to find the bound

    OUTPUT:

    (integer) An upper bound on the torsion order.

    ALGORITHM:

    An upper bound on the order of the torsion group of the elliptic
    curve is obtained by counting points modulo several primes of good
    reduction. Note that the upper bound returned by this function is
    a multiple of the order of the torsion group, and in general will
    be greater than the order.

    To avoid nontrivial arithmetic in the base field (in particular,
    to avoid having to compute the maximal order) we only use prime
    `P` above rational primes `p` which do not divide the discriminant
    of the equation order.

    EXAMPLES::

        sage: CDB = CremonaDatabase()
        sage: from sage.schemes.elliptic_curves.ell_torsion import torsion_bound
        sage: [torsion_bound(E) for E in CDB.iter([14])]
        [6, 6, 6, 6, 6, 6]
        sage: [E.torsion_order() for E in CDB.iter([14])]
        [6, 6, 2, 6, 2, 6]

    An example over a relative number field (see :trac:`16011`)::

        sage: R.<x> = QQ[]
        sage: F.<a> = QuadraticField(5)
        sage: K.<b> = F.extension(x^2-3)
        sage: E = EllipticCurve(K,[0,0,0,b,1])
        sage: E.torsion_subgroup().order()
        1

    An example of a base-change curve from `\QQ` to a degree 16 field::

        sage: from sage.schemes.elliptic_curves.ell_torsion import torsion_bound
        sage: f = PolynomialRing(QQ,'x')([5643417737593488384,0,
        ....:     -11114515801179776,0,-455989850911004,0,379781901872,
        ....:     0,14339154953,0,-1564048,0,-194542,0,-32,0,1])
        sage: K = NumberField(f,'a')
        sage: E = EllipticCurve(K, [1, -1, 1, 824579, 245512517])
        sage: torsion_bound(E)
        16
        sage: E.torsion_subgroup().invariants()
        (4, 4)
    """
    from sage.rings.all import ZZ, GF
    from sage.schemes.elliptic_curves.constructor import EllipticCurve

    K = E.base_field()

    # Special case K = QQ

    if K is RationalField():
        bound = ZZ.zero()
        k = 0
        p = ZZ(2)  # so we start with 3
        E = E.integral_model()
        disc_E = E.discriminant()

        while k < number_of_places:
            p = p.next_prime()
            if p.divides(disc_E):
                continue
            k += 1
            Fp = GF(p)
            new_bound = E.reduction(p).cardinality()
            bound = bound.gcd(new_bound)
            if bound == 1:
                return bound
        return bound

    # In case K is a relative extension we absolutize:

    absK = K.absolute_field('a_')
    f = absK.defining_polynomial()
    abs_map = absK.structure()[1]

    # Ensure f is monic and in ZZ[x]

    f = f.monic()
    den = f.denominator()
    if den != 1:
        x = f.parent().gen()
        n = f.degree()
        f = den**n * f(x / den)
    disc_f = f.discriminant()
    d = K.absolute_degree()

    # Now f is monic in ZZ[x] of degree d and defines the extension K = Q(a)

    # Make sure that we have a model for E with coefficients in ZZ[a]

    E = E.integral_model()
    disc_E = E.discriminant().norm()
    ainvs = [abs_map(c) for c in E.a_invariants()]

    bound = ZZ.zero()
    k = 0
    p = ZZ(2)  # so we start with 3

    try:  # special case, useful for base-changes from QQ
        ainvs = [ZZ(ai) for ai in ainvs]
        while k < number_of_places:
            p = p.next_prime()
            if p.divides(disc_E) or p.divides(disc_f):
                continue
            k += 1
            for fi, ei in f.factor_mod(p):
                di = fi.degree()
                Fp = GF(p)
                new_bound = EllipticCurve(
                    Fp, ainvs).cardinality(extension_degree=di)
                bound = bound.gcd(new_bound)
                if bound == 1:
                    return bound
        return bound
    except (ValueError, TypeError):
        pass

    # General case

    while k < number_of_places:
        p = p.next_prime()
        if p.divides(disc_E) or p.divides(disc_f):
            continue
        k += 1
        for fi, ei in f.factor_mod(p):
            di = fi.degree()
            Fq = GF(p**di)
            ai = fi.roots(Fq, multiplicities=False)[0]

            def red(c):
                return Fq.sum(Fq(c[j]) * ai**j for j in range(d))

            new_bound = EllipticCurve([red(c) for c in ainvs]).cardinality()
            bound = bound.gcd(new_bound)
            if bound == 1:
                return bound
    return bound