コード例 #1
0
def find_elliptic_curve(k, lT):
    '''
    Find elliptic curve with given trace mod l.

    INPUT:

    - ``k`` -- a base field,

    - ``lT`` -- a pair of an integer and a set of candidates for the trace.

    EXAMPLES::
    
        sage: from ellrains import find_elliptic_curve
        sage: lT = (229,[2])
        sage: find_elliptic_curve(GF(5), lT)
        Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 5
    '''
    l, T = lT
    L = GF(l)

    for j in k:
        # Don't mess with complicated cases
        if j == k(0) or j == k(1728):
            continue

        E = EllipticCurve(j = j)
        t = L(E.trace_of_frobenius())
        if t in T:
            return E
        elif -t in T:
            return E.quadratic_twist()

    return None
コード例 #2
0
    def __init__(self, A, C=None):
        """
        Cy² = Cx³ + Ax + Cx
        """

        # Internally, we represent it as a Sage elliptic curve.
        a = A / C if C is not None else A
        self.ec = EllipticCurve([0, a._sage(), 0, 1, 0])
コード例 #3
0
def test_semi_stable_frobenius_polynomial_t():
    # an example where the frobenius polynomial depends on the purely ramified extension
    # we make
    x = polygen(QQ)
    K = QQ.extension(x - 1, "one")
    E = EllipticCurve(K, [49, 343])
    assert E.discriminant() == -(2**4) * 31 * 7**6
    assert E.j_invariant() == K(2**8 * 3**3) / 31
    f1 = semi_stable_frobenius_polynomial(E, K * 7, 1)
    f2 = semi_stable_frobenius_polynomial(E, K * 7, -1)(x=-x)
    assert f1 == f2
コード例 #4
0
    def __scale_by_periods_only__(self):
        r"""
        If we fail to scale with ``_find_scaling_L_ratio``, we drop here
        to try and find the scaling by the quotient of the
        periods to the `X_0`-optimal curve. The resulting ``_scaling``
        is not guaranteed to be correct, but could well be.

        EXAMPLES::

            sage: E = EllipticCurve('19a1')
            sage: m = E.modular_symbol(sign=+1)
            sage: m.__scale_by_periods_only__()
            Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by -1, 2 or -2.
            sage: m._scaling
            1

            sage: E = EllipticCurve('19a2')
            sage: m = E.modular_symbol(sign=+1)
            sage: m._scaling
            3/2
            sage: m.__scale_by_periods_only__()
            Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by -1, 2 or -2.
            sage: m._scaling
            3
        """
        # we only do this inside the cremona-tables.
        try:
            crla = parse_cremona_label(self._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:
            print(
                "Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by -1, 2 or -2."
            )
            cr0 = Integer(crla[0]).str() + crla[1] + '1'
            E0 = EllipticCurve(cr0)
            if self._sign == 1:
                q = E0.period_lattice().basis()[0] / self._E.period_lattice(
                ).basis()[0]
            else:
                q = E0.period_lattice().basis()[1].imag(
                ) / self._E.period_lattice().basis()[1].imag()
                if E0.real_components() == 1:
                    q *= 2
                if self._E.real_components() == 1:
                    q /= 2
            q = ZZ(int(round(q * 200))) / 200
            verbose('scale modular symbols by %s' % q)
            self._scaling = q
コード例 #5
0
ファイル: util.py プロジェクト: mmasdeu/shp
def getcoords(E, u, prec=20, R=None):
    if R is None:
        R = u.parent()
        u = R(u)
    p = R.prime()
    jE = E.j_invariant()

    # Calculate the Tate parameter
    E4 = EisensteinForms(weight=4).basis()[0]
    Delta = CuspForms(weight=12).basis()[0]
    j = (E4.q_expansion(prec + 7)) ** 3 / Delta.q_expansion(prec + 7)
    qE = (1 / j).power_series().reversion()(R(1 / jE))

    # Normalize the period by appropriate powers of qE
    un = u * qE ** (-(u.valuation() / qE.valuation()).floor())

    precn = (prec / qE.valuation()).floor() + 4
    # formulas in Silverman II (Advanced Topics in the Arithmetic of Elliptic curves, p. 425)
    xx = un / (1 - un) ** 2 + sum(
        [
            qE ** n * un / (1 - qE ** n * un) ** 2
            + qE ** n / un / (1 - qE ** n / un) ** 2
            - 2 * qE ** n / (1 - qE ** n) ** 2
            for n in range(1, precn)
        ]
    )
    yy = un ** 2 / (1 - un) ** 3 + sum(
        [
            qE ** (2 * n) * un ** 2 / (1 - qE ** n * un) ** 3
            - qE ** n / un / (1 - qE ** n / un) ** 3
            + qE ** n / (1 - qE ** n) ** 2
            for n in range(1, precn)
        ]
    )

    sk = lambda q, k, pprec: sum([n ** k * q ** n / (1 - q ** n) for n in range(1, pprec + 1)])
    n = qE.valuation()
    precp = ((prec + 4) / n).floor() + 2

    tate_a4 = -5 * sk(qE, 3, precp)
    tate_a6 = (tate_a4 - 7 * sk(qE, 5, precp)) / 12
    Eq = EllipticCurve([R(1), R(0), R(0), tate_a4, tate_a6])

    C2 = (Eq.c4() * E.c6()) / (Eq.c6() * E.c4())

    C = R(C2).square_root()
    s = (C - R(E.a1())) / R(2)
    r = (s * (C - s) - R(E.a2())) / 3
    t = (r * (2 * s - C) - R(E.a3())) / 2

    return (r + C2 * xx, t + s * C2 * xx + C * C2 * yy)
コード例 #6
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 +-1 or +-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)

        """

        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
            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
        self._e *= self._scaling
コード例 #7
0
    def curve(self, prec=20):
        r"""
        Returns the `p`-adic elliptic curve of the form `y^2+x y = x^3 + s_4 x+s_6`.
        This curve with split multiplicative reduction is isomorphic to the given curve
        over the algebraic closure of `\QQ_p`.

        INPUT:

        - ``prec`` - the `p`-adic precision, default is 20.

        EXAMPLES::

            sage: eq = EllipticCurve('130a1').tate_curve(5)
            sage: eq.curve(prec=5)
            Elliptic Curve defined by y^2 + (1+O(5^5))*x*y  = x^3 +
            (2*5^4+5^5+2*5^6+5^7+3*5^8+O(5^9))*x + (2*5^3+5^4+2*5^5+5^7+O(5^8)) over 5-adic
            Field with capped relative precision 5
        """
        try:
            Eq = self.__curve
            if Eq.a6().absolute_precision() >= prec:
                return Eq
        except AttributeError:
            pass

        qE = self.parameter(prec=prec)
        n = qE.valuation()
        precp = (prec / n).floor() + 2
        R = qE.parent()

        tate_a4 = -5 * self.__sk(3, precp)
        tate_a6 = (tate_a4 - 7 * self.__sk(5, precp)) / 12
        Eq = EllipticCurve([R(1), R(0), R(0), tate_a4, tate_a6])
        self.__curve = Eq
        return Eq
コード例 #8
0
class EC(object):
    def __init__(self, A, C=None):
        """
        Cy² = Cx³ + Ax + Cx
        """

        # Internally, we represent it as a Sage elliptic curve.
        a = A / C if C is not None else A
        self.ec = EllipticCurve([0, a._sage(), 0, 1, 0])

    def j(self):
        j = self.ec.j_invariant()
        return GF(j.parent().characteristic(), *j.polynomial().list())

    def point(self, x):
        return Point(self, x)

    def four_isogeny(self, gen):
        pass

    def three_isogeny(self, gen):
        pass

    def secret_isogeny(self, gen):
        pass

    def __repr__(self):
        return repr(self.ec)

    def _sage(self):
        return self.ec
コード例 #9
0
ファイル: ell_modular_symbols.py プロジェクト: drupel/sage
    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 +-1 or +-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)

        """

        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
            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
        self._e *= self._scaling
コード例 #10
0
ファイル: ell_modular_symbols.py プロジェクト: drupel/sage
    def __scale_by_periods_only__(self):
        r"""
        If we fail to scale with ``_find_scaling_L_ratio``, we drop here
        to try and find the scaling by the quotient of the
        periods to the `X_0`-optimal curve. The resulting ``_scaling``
        is not guaranteed to be correct, but could well be.

        EXAMPLES::

            sage: E = EllipticCurve('19a1')
            sage: m = E.modular_symbol(sign=+1)
            sage: m.__scale_by_periods_only__()
            Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by -1, 2 or -2.
            sage: m._scaling
            1

            sage: E = EllipticCurve('19a2')
            sage: m = E.modular_symbol(sign=+1)
            sage: m._scaling
            3/2
            sage: m.__scale_by_periods_only__()
            Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by -1, 2 or -2.
            sage: m._scaling
            3
        """
        # we only do this inside the cremona-tables.
        try :
            crla = parse_cremona_label(self._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 :
            print("Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by -1, 2 or -2.")
            cr0 = Integer(crla[0]).str() + crla[1] + '1'
            E0 = EllipticCurve(cr0)
            if self._sign == 1:
                q = E0.period_lattice().basis()[0]/self._E.period_lattice().basis()[0]
            else:
                q = E0.period_lattice().basis()[1].imag()/self._E.period_lattice().basis()[1].imag()
                if E0.real_components() == 1:
                    q *= 2
                if self._E.real_components() == 1:
                    q /= 2
            q = ZZ(int(round(q*200)))/200
            verbose('scale modular symbols by %s'%q)
            self._scaling = q
コード例 #11
0
ファイル: curve.py プロジェクト: zackdarpinian/RandomProjects
    def weierstrass(self) :
        '''
        INPUT:

        OUTPUT:
        * E the elliptic curve in Weierstrass model (y^2 = x^3+a*x+b)
        '''
        return EllipticCurve(self.Fp2, [1-(self.a**2)/3, self.a*(2*(self.a**2)/9-1)/3])
コード例 #12
0
ファイル: util.py プロジェクト: mmasdeu/shp
def getcoords(E, u, prec=20, R=None):
    if R is None:
        R = u.parent()
        u = R(u)
    p = R.prime()
    jE = E.j_invariant()

    # Calculate the Tate parameter
    E4 = EisensteinForms(weight=4).basis()[0]
    Delta = CuspForms(weight=12).basis()[0]
    j = (E4.q_expansion(prec + 7))**3 / Delta.q_expansion(prec + 7)
    qE = (1 / j).power_series().reversion()(R(1 / jE))

    # Normalize the period by appropriate powers of qE
    un = u * qE**(-(u.valuation() / qE.valuation()).floor())

    precn = (prec / qE.valuation()).floor() + 4
    # formulas in Silverman II (Advanced Topics in the Arithmetic of Elliptic curves, p. 425)
    xx = un / (1 - un)**2 + sum([
        qE**n * un / (1 - qE**n * un)**2 + qE**n / un /
        (1 - qE**n / un)**2 - 2 * qE**n / (1 - qE**n)**2
        for n in range(1, precn)
    ])
    yy = un**2 / (1 - un)**3 + sum([
        qE**(2 * n) * un**2 / (1 - qE**n * un)**3 - qE**n / un /
        (1 - qE**n / un)**3 + qE**n / (1 - qE**n)**2 for n in range(1, precn)
    ])

    sk = lambda q, k, pprec: sum(
        [n**k * q**n / (1 - q**n) for n in range(1, pprec + 1)])
    n = qE.valuation()
    precp = ((prec + 4) / n).floor() + 2

    tate_a4 = -5 * sk(qE, 3, precp)
    tate_a6 = (tate_a4 - 7 * sk(qE, 5, precp)) / 12
    Eq = EllipticCurve([R(1), R(0), R(0), tate_a4, tate_a6])

    C2 = (Eq.c4() * E.c6()) / (Eq.c6() * E.c4())

    C = R(C2).square_root()
    s = (C - R(E.a1())) / R(2)
    r = (s * (C - s) - R(E.a2())) / 3
    t = (r * (2 * s - C) - R(E.a3())) / 2

    return (r + C2 * xx, t + s * C2 * xx + C * C2 * yy)
コード例 #13
0
def reduction(E: EllipticCurve_number_field, p: NumberFieldFractionalIdeal):
    if not E.has_good_reduction(p):
        raise ValueError(f"The curve must have good reduction at the place.")
    Ep = E.local_data(p).minimal_model()
    K = E.base_ring()
    Fp = K.residue_field(p)
    Fp2 = GF(Fp.order(), "abar", modulus=Fp.modulus())
    iso = Fp.hom([Fp2.gen(0)], Fp2)
    Ebar = EllipticCurve([iso(Fp(ai)) for ai in Ep.ainvs()])
    return Ebar
コード例 #14
0
ファイル: sm2_util.py プロジェクト: kunxian-xia/SM2
def EC_group_new(p, a_bin, b_bin, xG_bin, yG_bin, h):
    F = GF(p)
    a, b = F(a_bin), F(b_bin)
    C = EllipticCurve(F, [a, b])

    # create base point
    xG, yG = F(xG_bin), F(yG_bin)
    G = C(xG, yG)
    n = G.order()

    return (p, C, n, h, G)
コード例 #15
0
    def change_iso_curve(self, a):
        """
        INPUT:
        * a the montgomery a coefficient of the target curve
        OUTPUT:
        * the point P seen in the new curve
        """
        a1 = self.curve.Fp2(self.curve.a)
        if (a**2 - 4) * (a1**2 - 3)**3 != (a1**2 - 4) * (a**2 - 3)**3:
            # i.e if  256*(a1**2 - 3)**3/(a1**2 - 4) != 256*(a**2 - 3)**3/(a**2 - 4)
            raise RuntimeError('the curves are not isomorphic.')
        E_a1 = EllipticCurve(self.curve.Fp2, [0, a1, 0, 1, 0])
        E_a = EllipticCurve(self.curve.Fp2, [0, a, 0, 1, 0])
        xP = self.x / self.z
        yP = sqrt(xP**3 + a1 * xP**2 + xP)

        P_ws = E_a1(xP, yP)
        iso = E_a1.isomorphism_to(E_a)
        curve_target = copy(self.curve)
        curve_target.a = a
        return Point(iso(P_ws)[0], 1, curve_target)
コード例 #16
0
    def __init__(self, Elabel, modulus, number):
        """
        tensor product of an elliptic curve E over Q and a
        Dirichlet character chi given by a modulus and a number.

        (more to come)
        """
        self.modulus = modulus
        self.number = number
        self.Elabel = Elabel

        C = lmfdb.base.getDBConnection()
        Edata = C.elliptic_curves.curves.find_one({'lmfdb_label': Elabel})
        if Edata is None:
            raise ValueError
        ainvs = [int(a) for a in Edata['ainvs']]
        E = EllipticCurve(ainvs)
        cremona_label = Edata['label']
        lmfdb_label = Edata['lmfdb_label']

        args = {'type':'Dirichlet', 'modulus':modulus, 'number':number}
        chi = WebDirichletCharacter(**args)
        chi = chi.H[number]

        #chi_sage = chi.chi.sage_character().primitive_character()
        chi = chi.primitive_character()

        NE = E.conductor()
        Nchi = chi.conductor()
        # test hypothesis
        if not NE.gcd(Nchi ** 2).is_squarefree():
            raise ValueError

        self.E = E
        self.chi = chi
        self.NE = NE
        self.Nchi = Nchi
        self.N = self.conductor()
コード例 #17
0
ファイル: ell_tate_curve.py プロジェクト: swewers/mein_sage
    def curve(self, prec=20):
        r"""
        Return the `p`-adic elliptic curve of the form
        `y^2+x y = x^3 + s_4 x+s_6`.

        This curve with split multiplicative reduction is isomorphic
        to the given curve over the algebraic closure of `\QQ_p`.

        INPUT:

        - ``prec`` -- the `p`-adic precision, default is 20.

        EXAMPLES::

            sage: eq = EllipticCurve('130a1').tate_curve(5)
            sage: eq.curve(prec=5)
            Elliptic Curve defined by y^2 + (1+O(5^5))*x*y  = x^3 +
            (2*5^4+5^5+2*5^6+5^7+3*5^8+O(5^9))*x +
            (2*5^3+5^4+2*5^5+5^7+O(5^8)) over 5-adic
            Field with capped relative precision 5
        """

        Eq = getattr(self, "__curve", None)
        if Eq and Eq.a6().precision_relative() >= prec:
            return Eq.change_ring(Qp(self._p, prec))

        qE = self.parameter(prec=prec)
        precp = prec + 2
        tate_a4 = -5 * self.__sk(3, precp)
        tate_a6 = (tate_a4 - 7 * self.__sk(5, precp)) / 12
        R = qE.parent()
        Eq = EllipticCurve(
            [R.one(), R.zero(),
             R.zero(), R(tate_a4),
             R(tate_a6)])
        self.__curve = Eq
        return Eq
コード例 #18
0
def galois_rep_from_path(p):
    C = getDBConnection()

    if p[0] == 'EllipticCurve':
        # create the sage elliptic curve then create Galois rep object
        data = C.elliptic_curves.curves.find_one({'lmfdb_label': p[2]})
        ainvs = [int(a) for a in data['ainvs']]
        E = EllipticCurve(ainvs)
        return GaloisRepresentation(E)

    elif (p[0] == 'Character' and p[1] == 'Dirichlet'):
        dirichletArgs = {
            'type': 'Dirichlet',
            'modulus': int(p[2]),
            'number': int(p[3])
        }
        chi = WebDirichletCharacter(**dirichletArgs)
        return GaloisRepresentation(chi)

    elif (p[0] == 'ModularForm'):
        N = int(p[4])
        k = int(p[5])
        chi = p[6]  # this should be zero; TODO check this is the case
        label = p[7]  # this is a, b, c, etc.; chooses the galois orbit
        embedding = p[8]  # this is the embedding of that galois orbit
        form = WebNewForm(N, k, chi=chi, label=label)
        return GaloisRepresentation([form, ZZ(embedding)])

    elif (p[0] == 'ArtinRepresentation'):
        dim = p[1]
        conductor = p[2]
        index = p[3]
        rho = ArtinRepresentation(dim, conductor, index)
        return GaloisRepresentation(rho)
    else:
        return
コード例 #19
0
 def compareXWithWeierstrass(self, other):
     '''
     INPUT:
     * other a point of an elliptic curve of SageMath object EllipticCurve
     OUTPUT:
     * True of False if self corresponds to a point on a Weierstrass curve with the same x-coordinate as other
     '''
     field = self.curve.Fp2
     selfW = self.weierstrass()
     if selfW.curve() != other.curve():
         # we are in an isomorphic curve
         # let's move to the right one
         a1, b1 = selfW.curve().a4(), selfW.curve().a6()
         C2 = EllipticCurve(field, [
             field(other.curve().a4().polynomial().list()),
             field(other.curve().a6().polynomial().list())
         ])
         iso = WeierstrassIsomorphism(E=selfW.curve(), F=C2)
         selfW = iso(selfW)
     x = field(selfW[0].polynomial().list())
     z = field(selfW[2].polynomial().list())
     X = field(other[0].polynomial().list())
     Z = field(other[2].polynomial().list())
     return x * Z == z * X
コード例 #20
0
ファイル: curve_enumerator.py プロジェクト: williamstein/CBH
    def two_selmer(self,curves,rank=True,reduced=False,
                   output_filename="rank_output.txt",problems_filename="rank_problems.txt",\
                   return_data=True,print_timing=True):
        r"""
        Compute rank or size of two-Selmer for a list of curves ordered by height.

        INPUT:
 
            - ``curves``            -- A list of height/a-invariant tuples of
              curves, as returned by the coefficients_over_height_range() method.
              Each tuple is of the form
              (H, [a1,a2,a3,a4,a6]) where
              H is the height of the curve, and
              [a1,...,a6] the curve's a-invariants

            - ``rank``              -- (Default True) Compute the rank versus size
              of the curve's 2-Selmer group. If True, rank is computed; if set to
              False size (i.e. 2^rank) is computed instead.

            - ``reduced``           -- (Default False) Compute full 2-Selmer or
              reduced 2-Selmer. If True, full 2-Selmer is computed; if False, the
              reduced group rank/size (i.e. 2-Selmer rank - 2-torsion rank or
              2^(2-Selmer rank - 2-torsion rank) as per whether 'rank' is set to
              True or False) is computed.

            - ``output_filename``   -- String, the name of the file to which the
              output will be saved. Each line of the save file describes a
              single curve, and consists of seven tab-separated integers:
              the first is the height of the curve; the following five are
              the curve's a-invariants, and the final integer is the curve's rank.
            - ``problems_filename`` -- String: the file name to which problem
              curves will be written. These are curves for which rank could not
              be computed. Write format is the same as above, except rank is
              omitted at the end.

            - ``return_data``       -- (Default True): If set to False, the data
              is not returned at the end of computation; only written to file.

            - ``print_timing``      -- (Default True): If set to False, wall time
              of total computation will not be printed.

        OUTPUT:

            - Writes data to file. Each line of the written file consists of seven
              tab separated entries of the form
              H, a1, a2, a3, a4, a6, d
              H: The curve's height
              a1,...,a6: The curve's a-invariants
              d: The computed datum for that curve

            - (only if return_data==True) A list consisting of two lists:
              The first is a list of triples of the form
              (H, (a1,a2,a3,a4,a6), d)
              where the entries are as above.
              The second is a list of curve for which the datum could not be provably
              computed; each entry of this list is just a pair consisting of height
              and a-invariants.

        EXAMPLES::

            sage: from sage.schemes.elliptic_curves.curve_enumerator import *
            sage: C = CurveEnumerator(family="short_weierstrass")
            sage: L = C.coefficients_over_height_range(0,4)
            sage: R = C.two_selmer(L,rank=True,return_data=True,print_timing=False)
            sage: R[1]
            []
            sage: for r in R[0]: print(r)
            ....: 
            (4, [0, 0, 0, -1, -2], 1)
            (4, [0, 0, 0, -1, 2], 0)
            (4, [0, 0, 0, 0, -2], 1)
            (4, [0, 0, 0, 0, 2], 1)
            (4, [0, 0, 0, 1, -2], 1)
            (4, [0, 0, 0, 1, 2], 1)
            sage: R = C.two_selmer(L,rank=False,return_data=True,print_timing=False)
            sage: for r in R[0]: print(r)
            ....: 
            (4, [0, 0, 0, -1, -2], 2)
            (4, [0, 0, 0, -1, 2], 1)
            (4, [0, 0, 0, 0, -2], 2)
            (4, [0, 0, 0, 0, 2], 2)
            (4, [0, 0, 0, 1, -2], 2)
            (4, [0, 0, 0, 1, 2], 2)
            sage: R = C.two_selmer(L,reduced=True,print_timing=False)
            sage: for r in R[0]: print(r)
            ....: 
            (4, [0, 0, 0, -1, -2], 1)
            (4, [0, 0, 0, -1, 2], 0)
            (4, [0, 0, 0, 0, -2], 1)
            (4, [0, 0, 0, 0, 2], 1)
            (4, [0, 0, 0, 1, -2], 0)
            (4, [0, 0, 0, 1, 2], 0)
            sage: R = C.two_selmer(L,rank=False,reduced=True,print_timing=False)
            sage: for r in R[0]: print(r)
            ....: 
            (4, [0, 0, 0, -1, -2], 2)
            (4, [0, 0, 0, -1, 2], 1)
            (4, [0, 0, 0, 0, -2], 2)
            (4, [0, 0, 0, 0, 2], 2)
            (4, [0, 0, 0, 1, -2], 1)
            (4, [0, 0, 0, 1, 2], 1)
        """
        if print_timing:
            t = time.time()

        out_file = open(output_filename, "w")
        prob_file = open(problems_filename, "w")
        if return_data:
            output = []
            problems = []
        for C in curves:
            # Attempt to compute datum and write curve+datum to file
            try:
                E = EllipticCurve(C[1])

                d = E.selmer_rank()
                if reduced:
                    d -= E.two_torsion_rank()
                if not rank:
                    d = 2**d

                out_file.write(str(C[0]) + "\t")
                for a in C[1]:
                    out_file.write(str(a) + "\t")
                out_file.write(str(d) + "\n")
                out_file.flush()

                if return_data:
                    output.append((C[0], C[1], d))
            # Write to problem file if fail
            except:
                prob_file.write(str(C[0]) + "\t")
                for a in C[1]:
                    prob_file.write(str(a) + "\t")
                prob_file.write("\n")
                prob_file.flush()

                if return_data:
                    problems.append(C)
        out_file.close()
        prob_file.close()

        if print_timing:
            print(time.time() - t)
        if return_data:
            return output, problems
コード例 #21
0
ファイル: curve_enumerator.py プロジェクト: williamstein/CBH
    def rank(self,curves,output_filename="rank_output.txt",\
             problems_filename="rank_problems.txt",\
             return_data=True,use_database=True,use_only_mwrank=False,\
             print_timing=True):
        r"""
        Compute the algebraic rank for a list of curves ordered by height.

        INPUT:
 
            - ``curves``            -- A list of height/a-invariant tuples of
              curves, as returned by the coefficients_over_height_range() method
              Each tuple is of the form
              (H, [a1,a2,a3,a4,a6]) where
              H is the height of the curve, and
              [a1,...,a6] the curve's a-invariants

            - ``output_filename``   -- String, the name of the file to which the
              output will be saved. Each line of the save file describes a
              single curve, and consists of seven tab-separated integers:
              the first is the height of the curve; the following five are
              the curve's a-invariants, and the final integer is the curve's rank.

            - ``problems_filename`` -- String: the file name to which problem
              curves will be written. These are curves for which rank could not
              be computed. Write format is the same as above, except rank is
              omitted at the end.

            - ``return_data``       -- (Default True): If set to False, the data
              is not returned at the end of computation; only written to file.

            - ``use_database``      -- (Default True): If set to False, the 
              Cremona database is not used to look up curve ranks.

            - ``use_only_mwrank``   -- (Default False): If set to True, will not
              try to use analytic methods to compute rank before consulting the
              Cremona database

            - ``print_timing``      -- (Default True): If set to False, wall time
              of total computation will not be printed.

        OUTPUT:

            - Writes data to file. Each line of the written file consists of seven
              tab separated entries of the form
              H, a1, a2, a3, a4, a6, d
              H: The curve's height
              a1,...,a6: The curve's a-invariants
              d: The computed datum for that curve

            - (only if return_data==True) A list consisting of two lists:
              The first is a list of triples of the form
              (H, (a1,a2,a3,a4,a6), d)
              where the entries are as above.
              The second is a list of curve for which the datum could not be provably
              computed; each entry of this list is just a pair consisting of height
              and a-invariants.

        EXAMPLES::

            sage: from sage.schemes.elliptic_curves.curve_enumerator import *
            sage: C = CurveEnumerator(family="short_weierstrass")
            sage: L = C.coefficients_over_height_range(0,4)
            sage: R = C.rank(L,return_data=True,print_timing=False)
            sage: R[1]
            []
            sage: for r in R[0]: print(r)
            ....: 
            (1, [0, 0, 0, -1, 0], 0)
            (1, [0, 0, 0, 1, 0], 0)
            (1, [0, 0, 0, 0, -1], 0)
            (1, [0, 0, 0, 0, 1], 0)
            (1, [0, 0, 0, -1, -1], 0)
            (1, [0, 0, 0, -1, 1], 1)
            (1, [0, 0, 0, 1, -1], 1)
            (1, [0, 0, 0, 1, 1], 1)
            (4, [0, 0, 0, -1, -2], 1)
            (4, [0, 0, 0, -1, 2], 0)
            (4, [0, 0, 0, 0, -2], 1)
            (4, [0, 0, 0, 0, 2], 1)
            (4, [0, 0, 0, 1, -2], 0)
            (4, [0, 0, 0, 1, 2], 0)
        """
        if print_timing:
            t = time.time()

        out_file = open(output_filename, "w")
        prob_file = open(problems_filename, "w")
        if return_data:
            output = []
            problems = []
        for C in curves:
            # Attempt to compute rank and write curve+rank to file
            try:
                E = EllipticCurve(C[1])
                d = E.rank(use_database=use_database,
                           only_use_mwrank=use_only_mwrank)
                out_file.write(str(C[0]) + "\t")
                for a in C[1]:
                    out_file.write(str(a) + "\t")
                out_file.write(str(d) + "\n")
                out_file.flush()

                if return_data:
                    output.append((C[0], C[1], d))
            # Write to problem file if fail
            except:
                prob_file.write(str(C[0]) + "\t")
                for a in C[1]:
                    prob_file.write(str(a) + "\t")
                prob_file.write("\n")
                prob_file.flush()

                if return_data:
                    problems.append(C)
        out_file.close()
        prob_file.close()

        if print_timing:
            print(time.time() - t)
        if return_data:
            return output, problems
コード例 #22
0
def is_Q_curve(E, maxp=100, certificate=False, verbose=False):
    r"""
    Return whether ``E`` is a `\QQ`-curve, with optional certificate.

    INPUT:

    - ``E`` (elliptic curve) -- an elliptic curve over a number field.

    - ``maxp`` (int, default 100): bound on primes used for checking
      necessary local conditions.  The result will not depend on this,
      but using a larger value may return ``False`` faster.

    - ``certificate`` (bool, default ``False``): if ``True`` then a
      second value is returned giving a certificate for the
      `\QQ`-curve property.

    OUTPUT:

    If ``certificate`` is ``False``: either ``True`` (if `E` is a
    `\QQ`-curve), or ``False``.

    If ``certificate`` is ``True``: a tuple consisting of a boolean
    flag as before and a certificate, defined as follows:

    - when the flag is ``True``, so `E` is a `\QQ`-curve:

        - either {'CM':`D`} where `D` is a negative discriminant, when
          `E` has potential CM with discriminant `D`;

        - otherwise {'CM': `0`, 'core_poly': `f`, 'rho': `\rho`, 'r':
          `r`, 'N': `N`}, when `E` is a non-CM `\QQ`-curve, where the
          core polynomial `f` is an irreducible monic polynomial over
          `QQ` of degree `2^\rho`, all of whose roots are
          `j`-invariants of curves isogenous to `E`, the core level
          `N` is a square-free integer with `r` prime factors which is
          the LCM of the degrees of the isogenies between these
          conjugates.  For example, if there exists a curve `E'`
          isogenous to `E` with `j(E')=j\in\QQ`, then the certificate
          is {'CM':0, 'r':0, 'rho':0, 'core_poly': x-j, 'N':1}.

    - when the flag is ``False``, so `E` is not a `\QQ`-curve, the
      certificate is a prime `p` such that the reductions of `E` at
      the primes dividing `p` are inconsistent with the property of
      being a `\QQ`-curve.  See the ALGORITHM section for details.

    ALGORITHM:

    See [CrNa2020]_ for details.

    1. If `E` has rational `j`-invariant, or has CM, then return
    ``True``.

    2. Replace `E` by a curve defined over `K=\QQ(j(E))`. Let `N` be
    the conductor norm.

    3. For all primes `p\mid N` check that the valuations of `j` at
    all `P\mid p` are either all negative or all non-negative; if not,
    return ``False``.

    4. For `p\le maxp`, `p\not\mid N`, check that either `E` is
    ordinary mod `P` for all `P\mid p`, or `E` is supersingular mod
    `P` for all `P\mid p`; if neither, return ``False``.  If all are
    ordinary, check that the integers `a_P(E)^2-4N(P)` have the same
    square-free part; if not, return ``False``.

    5. Compute the `K`-isogeny class of `E` using the "heuristic"
    option (which is faster, but not guaranteed to be complete).
    Check whether the set of `j`-invariants of curves in the class of
    `2`-power degree contains a complete Galois orbit.  If so, return
    ``True``.

    6. Otherwise repeat step 4 for more primes, and if still
    undecided, repeat Step 5 without the "heuristic" option, to get
    the complete `K`-isogeny class (which will probably be no bigger
    than before).  Now return ``True`` if the set of `j`-invariants of
    curves in the class contains a complete Galois orbit, otherwise
    return ``False``.

    EXAMPLES:

    A non-CM curve over `\QQ` and a CM curve over `\QQ` are both
    trivially `\QQ`-curves::

        sage: from sage.schemes.elliptic_curves.Qcurves import is_Q_curve
        sage: E = EllipticCurve([1,2,3,4,5])
        sage: flag, cert = is_Q_curve(E, certificate=True)
        sage: flag
        True
        sage: cert
        {'CM': 0, 'N': 1, 'core_poly': x, 'r': 0, 'rho': 0}

        sage: E = EllipticCurve(j=8000)
        sage: flag, cert = is_Q_curve(E, certificate=True)
        sage: flag
        True
        sage: cert
        {'CM': -8}

    A non-`\QQ`-curve over a quartic field.  The local data at bad
    primes above `3` is inconsistent::

        sage: from sage.schemes.elliptic_curves.Qcurves import is_Q_curve
        sage: R.<x> = PolynomialRing(QQ)
        sage: K.<a> = NumberField(R([3, 0, -5, 0, 1]))
        sage: E = EllipticCurve([K([-3,-4,1,1]),K([4,-1,-1,0]),K([-2,0,1,0]),K([-621,778,138,-178]),K([9509,2046,-24728,10380])])
        sage: is_Q_curve(E, certificate=True, verbose=True)
        Checking whether Elliptic Curve defined by y^2 + (a^3+a^2-4*a-3)*x*y + (a^2-2)*y = x^3 + (-a^2-a+4)*x^2 + (-178*a^3+138*a^2+778*a-621)*x + (10380*a^3-24728*a^2+2046*a+9509) over Number Field in a with defining polynomial x^4 - 5*x^2 + 3 is a Q-curve
        No: inconsistency at the 2 primes dividing 3
        - potentially multiplicative: [True, False]
        (False, 3)

    A non-`\QQ`-curve over a quadratic field.  The local data at bad
    primes is consistent, but the local test at good primes above `13`
    is not::

        sage: K.<a> = NumberField(R([-10, 0, 1]))
        sage: E = EllipticCurve([K([0,1]),K([-1,-1]),K([0,0]),K([-236,40]),K([-1840,464])])
        sage: is_Q_curve(E, certificate=True, verbose=True)
        Checking whether Elliptic Curve defined by y^2 + a*x*y = x^3 + (-a-1)*x^2 + (40*a-236)*x + (464*a-1840) over Number Field in a with defining polynomial x^2 - 10 is a Q-curve
        Applying local tests at good primes above p<=100
        No: inconsistency at the 2 ordinary primes dividing 13
        - Frobenius discriminants mod squares: [-1, -3]
        No: local test at p=13 failed
        (False, 13)

    A quadratic `\QQ`-curve with CM discriminant `-15` (`j`-invariant not in `\QQ`)::

        sage: from sage.schemes.elliptic_curves.Qcurves import is_Q_curve
        sage: R.<x> = PolynomialRing(QQ)
        sage: K.<a> = NumberField(R([-1, -1, 1]))
        sage: E = EllipticCurve([K([1,0]),K([-1,0]),K([0,1]),K([0,-2]),K([0,1])])
        sage: is_Q_curve(E, certificate=True, verbose=True)
        Checking whether Elliptic Curve defined by y^2 + x*y + a*y = x^3 + (-1)*x^2 + (-2*a)*x + a over Number Field in a with defining polynomial x^2 - x - 1 is a Q-curve
        Yes: E is CM (discriminant -15)
        (True, {'CM': -15})

    An example over `\QQ(\sqrt{2},\sqrt{3})`.  The `j`-invariant is in
    `\QQ(\sqrt{6})`, so computations will be done over that field, and
    in fact there is an isogenous curve with rational `j`, so we have
    a so-called rational `\QQ`-curve::

        sage: K.<a> = NumberField(R([1, 0, -4, 0, 1]))
        sage: E = EllipticCurve([K([-2,-4,1,1]),K([0,1,0,0]),K([0,1,0,0]),K([-4780,9170,1265,-2463]),K([163923,-316598,-43876,84852])])
        sage: flag, cert = is_Q_curve(E, certificate=True)
        sage: flag
        True
        sage: cert
        {'CM': 0, 'N': 1, 'core_degs': [1], 'core_poly': x - 85184/3, 'r': 0, 'rho': 0}

    Over the same field, a so-called strict `\QQ`-curve which is not
    isogenous to one with rational `j`, but whose core field is
    quadratic. In fact the isogeny class over `K` consists of `6`
    curves, four with conjugate quartic `j`-invariants and `2` with
    quadratic conjugate `j`-invariants in `\QQ(\sqrt{3})` (but which
    are not base-changes from the quadratic subfield)::

        sage: E = EllipticCurve([K([0,-3,0,1]),K([1,4,0,-1]),K([0,0,0,0]),K([-2,-16,0,4]),K([-19,-32,4,8])])
        sage: flag, cert = is_Q_curve(E, certificate=True)
        sage: flag
        True
        sage: cert
        {'CM': 0,
        'N': 2,
        'core_degs': [1, 2],
        'core_poly': x^2 - 840064*x + 1593413632,
        'r': 1,
        'rho': 1}

    """
    from sage.rings.number_field.number_field_base import is_NumberField

    if verbose:
        print("Checking whether {} is a Q-curve".format(E))

    try:
        assert is_NumberField(E.base_field())
    except (AttributeError, AssertionError):
        raise TypeError(
            "{} must be an elliptic curve defined over a number field in is_Q_curve()"
        )

    from sage.rings.integer_ring import ZZ
    from sage.arith.functions import lcm
    from sage.libs.pari import pari
    from sage.rings.number_field.number_field import NumberField
    from sage.schemes.elliptic_curves.constructor import EllipticCurve
    from sage.schemes.elliptic_curves.cm import cm_j_invariants_and_orders, is_cm_j_invariant

    # Step 1

    # all curves with rational j-invariant are Q-curves:
    jE = E.j_invariant()
    if jE in QQ:
        if verbose:
            print("Yes: j(E) is in QQ")
        if certificate:
            # test for CM
            for d, f, j in cm_j_invariants_and_orders(QQ):
                if jE == j:
                    return True, {'CM': d * f**2}
            # else not CM
            return True, {
                'CM': ZZ(0),
                'r': ZZ(0),
                'rho': ZZ(0),
                'N': ZZ(1),
                'core_poly': polygen(QQ)
            }
        else:
            return True

    # CM curves are Q-curves:
    flag, df = is_cm_j_invariant(jE)
    if flag:
        d, f = df
        D = d * f**2
        if verbose:
            print("Yes: E is CM (discriminant {})".format(D))
        if certificate:
            return True, {'CM': D}
        else:
            return True

    # Step 2: replace E by a curve defined over Q(j(E)):

    K = E.base_field()
    jpoly = jE.minpoly()
    if jpoly.degree() < K.degree():
        if verbose:
            print("switching to smaller base field: j's minpoly is {}".format(
                jpoly))
        f = pari(jpoly).polredbest().sage({'x': jpoly.parent().gen()})
        K2 = NumberField(f, 'b')
        jE = jpoly.roots(K2)[0][0]
        if verbose:
            print("New j is {} over {}, with minpoly {}".format(
                jE, K2, jE.minpoly()))
        #assert jE.minpoly()==jpoly
        E = EllipticCurve(j=jE)
        K = K2
        if verbose:
            print("New test curve is {}".format(E))

    # Step 3: check primes of bad reduction

    NN = E.conductor().norm()
    for p in NN.support():
        Plist = K.primes_above(p)
        if len(Plist) < 2:
            continue
        # pot_mult = potential multiplicative reduction
        pot_mult = [jE.valuation(P) < 0 for P in Plist]
        consistent = all(pot_mult) or not any(pot_mult)
        if not consistent:
            if verbose:
                print("No: inconsistency at the {} primes dividing {}".format(
                    len(Plist), p))
                print("  - potentially multiplicative: {}".format(pot_mult))
            if certificate:
                return False, p
            else:
                return False

    # Step 4 check: primes P of good reduction above p<=B:

    if verbose:
        print("Applying local tests at good primes above p<={}".format(maxp))

    res4, p = Step4Test(E, B=maxp, oldB=0, verbose=verbose)
    if not res4:
        if verbose:
            print("No: local test at p={} failed".format(p))
        if certificate:
            return False, p
        else:
            return False

    if verbose:
        print("...all local tests pass for p<={}".format(maxp))

    # Step 5: compute the (partial) K-isogeny class of E and test the
    # set of j-invariants in the class:

    C = E.isogeny_class(algorithm='heuristic', minimal_models=False)
    jC = [E2.j_invariant() for E2 in C]
    centrejpols = conjugacy_test(jC, verbose=verbose)
    if centrejpols:
        if verbose:
            print(
                "Yes: the isogeny class contains a complete conjugacy class of j-invariants"
            )
        if certificate:
            for f in centrejpols:
                rho = f.degree().valuation(2)
                centre_indices = [i for i, j in enumerate(jC) if f(j) == 0]
                M = C.matrix()
                core_degs = [M[centre_indices[0], i] for i in centre_indices]
                level = lcm(core_degs)
                if level.is_squarefree():
                    r = len(level.prime_divisors())
                    cert = {
                        'CM': ZZ(0),
                        'core_poly': f,
                        'rho': rho,
                        'r': r,
                        'N': level,
                        'core_degs': core_degs
                    }
                    return True, cert
            print("No central curve found")
        else:
            return True

    # Now we are undecided.  This can happen if either (1) E is not a
    # Q-curve but we did not use enough primes in Step 4 to detect
    # this, or (2) E is a Q-curve but in Step 5 we did not compute the
    # complete isogeny class.  Case (2) is most unlikely since the
    # heuristic bound used in computing isogeny classes means that we
    # have all isogenous curves linked to E by an isogeny of degree
    # supported on primes<1000.

    # We first rerun Step 4 with a larger bound.

    xmaxp = 10 * maxp
    if verbose:
        print(
            "Undecided after first round, so we apply more local tests, up to {}"
            .format(xmaxp))

    res4, p = Step4Test(E, B=xmaxp, oldB=maxp, verbose=verbose)
    if not res4:
        if verbose:
            print("No: local test at p={} failed".format(p))
        if certificate:
            return False, p
        else:
            return False

    # Now we rerun Step 5 using a rigorous computation of the complete
    # isogeny class.  This will probably contain no more curves than
    # before, in which case -- since we already tested that the set of
    # j-invariants does not contain a complete Galois conjugacy class
    # -- we can deduce that E is not a Q-curve.

    if verbose:
        print("...all local tests pass for p<={}".format(xmaxp))
        print("We now compute the complete isogeny class...")

    Cfull = E.isogeny_class(minimal_models=False)
    jCfull = [E2.j_invariant() for E2 in Cfull]

    if len(jC) == len(jCfull):
        if verbose:
            print("...and find that we already had the complete class:so No")
        if certificate:
            return False, 0
        else:
            return False
    if verbose:
        print(
            "...and find that the class contains {} curves, not just the {} we computed originally"
            .format(len(jCfull), len(jC)))
    centrejpols = conjugacy_test(jCfull, verbose=verbose)
    if cert:
        if verbose:
            print(
                "Yes: the isogeny class contains a complete conjugacy class of j-invariants"
            )
        if certificate:
            return True, centrejpols
        else:
            return True
    if verbose:
        print(
            "No: the isogeny class does *not* contain a complete conjugacy class of j-invariants"
        )
    if certificate:
        return False, 0
    else:
        return False
コード例 #23
0
ファイル: curve_enumerator.py プロジェクト: williamstein/CBH
    def rank(self,curves,output_filename="rank_output.txt",\
             problems_filename="rank_problems.txt",\
             return_data=True,use_database=True,use_only_mwrank=False,\
             print_timing=True):
        r"""
        Compute the algebraic rank for a list of curves ordered by height.

        INPUT:
 
            - ``curves``            -- A list of height/a-invariant tuples of
              curves, as returned by the coefficients_over_height_range() method
              Each tuple is of the form
              (H, [a1,a2,a3,a4,a6]) where
              H is the height of the curve, and
              [a1,...,a6] the curve's a-invariants

            - ``output_filename``   -- String, the name of the file to which the
              output will be saved. Each line of the save file describes a
              single curve, and consists of seven tab-separated integers:
              the first is the height of the curve; the following five are
              the curve's a-invariants, and the final integer is the curve's rank.

            - ``problems_filename`` -- String: the file name to which problem
              curves will be written. These are curves for which rank could not
              be computed. Write format is the same as above, except rank is
              omitted at the end.

            - ``return_data``       -- (Default True): If set to False, the data
              is not returned at the end of computation; only written to file.

            - ``use_database``      -- (Default True): If set to False, the 
              Cremona database is not used to look up curve ranks.

            - ``use_only_mwrank``   -- (Default False): If set to True, will not
              try to use analytic methods to compute rank before consulting the
              Cremona database

            - ``print_timing``      -- (Default True): If set to False, wall time
              of total computation will not be printed.

        OUTPUT:

            - Writes data to file. Each line of the written file consists of seven
              tab separated entries of the form
              H, a1, a2, a3, a4, a6, d
              H: The curve's height
              a1,...,a6: The curve's a-invariants
              d: The computed datum for that curve

            - (only if return_data==True) A list consisting of two lists:
              The first is a list of triples of the form
              (H, (a1,a2,a3,a4,a6), d)
              where the entries are as above.
              The second is a list of curve for which the datum could not be provably
              computed; each entry of this list is just a pair consisting of height
              and a-invariants.

        EXAMPLES::

            sage: from sage.schemes.elliptic_curves.curve_enumerator import *
            sage: C = CurveEnumerator(family="short_weierstrass")
            sage: L = C.coefficients_over_height_range(0,4)
            sage: R = C.rank(L,return_data=True,print_timing=False)
            sage: R[1]
            []
            sage: for r in R[0]: print(r)
            ....: 
            (1, [0, 0, 0, -1, 0], 0)
            (1, [0, 0, 0, 1, 0], 0)
            (1, [0, 0, 0, 0, -1], 0)
            (1, [0, 0, 0, 0, 1], 0)
            (1, [0, 0, 0, -1, -1], 0)
            (1, [0, 0, 0, -1, 1], 1)
            (1, [0, 0, 0, 1, -1], 1)
            (1, [0, 0, 0, 1, 1], 1)
            (4, [0, 0, 0, -1, -2], 1)
            (4, [0, 0, 0, -1, 2], 0)
            (4, [0, 0, 0, 0, -2], 1)
            (4, [0, 0, 0, 0, 2], 1)
            (4, [0, 0, 0, 1, -2], 0)
            (4, [0, 0, 0, 1, 2], 0)
        """
        if print_timing:
            t = time.time()

        out_file  = open(output_filename,"w")
        prob_file = open(problems_filename,"w")
        if return_data:
            output = []
            problems = []
        for C in curves:
            # Attempt to compute rank and write curve+rank to file
            try:
                E = EllipticCurve(C[1])
                d = E.rank(use_database=use_database,only_use_mwrank=use_only_mwrank)
                out_file.write(str(C[0])+"\t")
                for a in C[1]:
                    out_file.write(str(a)+"\t")
                out_file.write(str(d)+"\n")
                out_file.flush()

                if return_data:
                    output.append((C[0],C[1],d))
            # Write to problem file if fail
            except:
                prob_file.write(str(C[0])+"\t")
                for a in C[1]:
                    prob_file.write(str(a)+"\t")
                prob_file.write("\n")
                prob_file.flush()

                if return_data:
                    problems.append(C)
        out_file.close()
        prob_file.close()

        if print_timing:
            print(time.time()-t)
        if return_data:
            return output,problems
コード例 #24
0
ファイル: curve_enumerator.py プロジェクト: williamstein/CBH
    def two_selmer(self,curves,rank=True,reduced=False,
                   output_filename="rank_output.txt",problems_filename="rank_problems.txt",\
                   return_data=True,print_timing=True):
        r"""
        Compute rank or size of two-Selmer for a list of curves ordered by height.

        INPUT:
 
            - ``curves``            -- A list of height/a-invariant tuples of
              curves, as returned by the coefficients_over_height_range() method.
              Each tuple is of the form
              (H, [a1,a2,a3,a4,a6]) where
              H is the height of the curve, and
              [a1,...,a6] the curve's a-invariants

            - ``rank``              -- (Default True) Compute the rank versus size
              of the curve's 2-Selmer group. If True, rank is computed; if set to
              False size (i.e. 2^rank) is computed instead.

            - ``reduced``           -- (Default False) Compute full 2-Selmer or
              reduced 2-Selmer. If True, full 2-Selmer is computed; if False, the
              reduced group rank/size (i.e. 2-Selmer rank - 2-torsion rank or
              2^(2-Selmer rank - 2-torsion rank) as per whether 'rank' is set to
              True or False) is computed.

            - ``output_filename``   -- String, the name of the file to which the
              output will be saved. Each line of the save file describes a
              single curve, and consists of seven tab-separated integers:
              the first is the height of the curve; the following five are
              the curve's a-invariants, and the final integer is the curve's rank.
            - ``problems_filename`` -- String: the file name to which problem
              curves will be written. These are curves for which rank could not
              be computed. Write format is the same as above, except rank is
              omitted at the end.

            - ``return_data``       -- (Default True): If set to False, the data
              is not returned at the end of computation; only written to file.

            - ``print_timing``      -- (Default True): If set to False, wall time
              of total computation will not be printed.

        OUTPUT:

            - Writes data to file. Each line of the written file consists of seven
              tab separated entries of the form
              H, a1, a2, a3, a4, a6, d
              H: The curve's height
              a1,...,a6: The curve's a-invariants
              d: The computed datum for that curve

            - (only if return_data==True) A list consisting of two lists:
              The first is a list of triples of the form
              (H, (a1,a2,a3,a4,a6), d)
              where the entries are as above.
              The second is a list of curve for which the datum could not be provably
              computed; each entry of this list is just a pair consisting of height
              and a-invariants.

        EXAMPLES::

            sage: from sage.schemes.elliptic_curves.curve_enumerator import *
            sage: C = CurveEnumerator(family="short_weierstrass")
            sage: L = C.coefficients_over_height_range(0,4)
            sage: R = C.two_selmer(L,rank=True,return_data=True,print_timing=False)
            sage: R[1]
            []
            sage: for r in R[0]: print(r)
            ....: 
            (4, [0, 0, 0, -1, -2], 1)
            (4, [0, 0, 0, -1, 2], 0)
            (4, [0, 0, 0, 0, -2], 1)
            (4, [0, 0, 0, 0, 2], 1)
            (4, [0, 0, 0, 1, -2], 1)
            (4, [0, 0, 0, 1, 2], 1)
            sage: R = C.two_selmer(L,rank=False,return_data=True,print_timing=False)
            sage: for r in R[0]: print(r)
            ....: 
            (4, [0, 0, 0, -1, -2], 2)
            (4, [0, 0, 0, -1, 2], 1)
            (4, [0, 0, 0, 0, -2], 2)
            (4, [0, 0, 0, 0, 2], 2)
            (4, [0, 0, 0, 1, -2], 2)
            (4, [0, 0, 0, 1, 2], 2)
            sage: R = C.two_selmer(L,reduced=True,print_timing=False)
            sage: for r in R[0]: print(r)
            ....: 
            (4, [0, 0, 0, -1, -2], 1)
            (4, [0, 0, 0, -1, 2], 0)
            (4, [0, 0, 0, 0, -2], 1)
            (4, [0, 0, 0, 0, 2], 1)
            (4, [0, 0, 0, 1, -2], 0)
            (4, [0, 0, 0, 1, 2], 0)
            sage: R = C.two_selmer(L,rank=False,reduced=True,print_timing=False)
            sage: for r in R[0]: print(r)
            ....: 
            (4, [0, 0, 0, -1, -2], 2)
            (4, [0, 0, 0, -1, 2], 1)
            (4, [0, 0, 0, 0, -2], 2)
            (4, [0, 0, 0, 0, 2], 2)
            (4, [0, 0, 0, 1, -2], 1)
            (4, [0, 0, 0, 1, 2], 1)
        """
        if print_timing:
            t = time.time()

        out_file  = open(output_filename,"w")
        prob_file = open(problems_filename,"w")
        if return_data:
            output = []
            problems = []
        for C in curves:
            # Attempt to compute datum and write curve+datum to file
            try:
                E = EllipticCurve(C[1])

                d = E.selmer_rank()
                if reduced:
                    d -= E.two_torsion_rank()
                if not rank:
                    d = 2**d

                out_file.write(str(C[0])+"\t")
                for a in C[1]:
                    out_file.write(str(a)+"\t")
                out_file.write(str(d)+"\n")
                out_file.flush()

                if return_data:
                    output.append((C[0],C[1],d))
            # Write to problem file if fail
            except:
                prob_file.write(str(C[0])+"\t")
                for a in C[1]:
                    prob_file.write(str(a)+"\t")
                prob_file.write("\n")
                prob_file.flush()

                if return_data:
                    problems.append(C)
        out_file.close()
        prob_file.close()

        if print_timing:
            print(time.time()-t)
        if return_data:
            return output,problems
コード例 #25
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)
コード例 #26
0
def find_elliptic_curve(k, K, m_t):
    '''
    INPUT: 

    - ``k`` -- a base field

    - ``K`` -- an extension of K of degree n.

    - ``m_t`` -- a list of tuple containing a integer and a set of candidates 
      for the trace.

    OUTPUT: 
    
    - An elliptic curve defined over k with the required properties.

    - An integer case, depending on the value of the j-invariant of said 
      elliptic curve.

    - An integer m statisfying the properties described in isom_elliptic which 
      we will be using to compute Gaussian periods.

    ..NOTE::

        The case j = 0 or 1728 are not implemented yet. They shall raise 
        NotImplementedError.

    EXAMPLES:
    
    sage: R.<X> = PolynomialRing(GF(5))

    sage: f = R.irreducible_element(19, algorithm = 'random')

    sage: K = GF(5**19, names = 'x', modulus = f)

    sage: m_t = [(229,{0, 1, 3})]

    sage: find_elliptic(GF(5), K, m_t)

    (Elliptic Curve defined by y^2 = x^3 + x + 2 over Finite Field of size 5,
    0,
    229)

    ALGORITHM:

    TODO : Doc is deprecated, to be redone.

    Function that finds an elliptic curve with the required charateristics, 
    those given in the function isom_elliptic.

    First, we have to determine if m is composite, a prime power or a power of 
    p, the characteristic of the base field. The first case is not implemented 
    yet. 
    We also note that the m given should satisfies several conditions based
    on the characteristic and the degree of K. See the docstrings of 
    isom_elliptic for more information.

    - If m is a power of p, the charateristic of the base field k, then we shall
      proceed as follow :

        We pick a random curve E/k and we set down t = Tr_k(Fr_E), for the
        curve to be what we want, we need :

          - t not zero,
          - (Z/m)* = <t> x S or #<t> = n 
          - m divides #E/K but not #E/L, for any intermediate extension L 
            of K/k; so we can construct points of order m such that their 
            abscissas or ordinates span exactly K. Or that we haven't any point
            of order m in any sub-extension.

        Then we test those conditions for both E and its quadratic twist, if one
        of them meet the requirements, we return it and its trace. If no 
        elliptic curves are found an error is returned.

    - If m is primer power, then we shall proceed as follow :

        We have m = l^r, for l a prime. For this method to work, we need l to 
        be an Elkies prime. A prime l is an Elkies prime for an elliptic curve 
        if the charateristic polynomial of the aforesaid elliptic curve splits 
        in GF(l).

        For now, we pick a random curve E/k and for it to work, if we set down 
        t = Tr_k(Fr_E), we need the following :

          - We have x**2 - tx + q = (x - a)(x - b) mod m, meaning the polynomial
            splits in Z/m,
          - (Z/m)* = <a> x S, with #<a> = n, 
          - ord_m(a) < ord_m(b),
          - m divides #E/K but not #E/L, for any intermediate extension L 
            of K/k; so we can construct points of order m such that their 
            abscissas or ordinates span exactly K.

        Once again, we test all that for both E and its quadratic twist; if one 
        them meet the requirements, we return it, its trace and a tuple
        containing the root a and t mod m. If none are found, there is 
        something wrong.


    - If m is composite, TODO.
    '''
    p = k.characteristic()
    q = k.cardinality()
    n = K.degree()
    m = m_t[0]
    S_t = m_t[1]
    compteur = 0

    #We start by the special cases j = 1728, 0
    E_j1728 = EllipticCurve(j = k(1728))

    if q%4 != 1:
        # If q != 1 mod 4, then there's no 4th root of unity, then magically
        # all the quartic twist are already in k and the trace is 0. We just
        # have to test the only curve y² = x³ + x.
        compteur += 1
        if 0 in S_t:
            return E_j1728, 0, compteur
    else:
        # If q = 1 mod 4, then the trace is not 0, and we have to try four
        # trace to see which is the best candidate.
        g = k.unit_gens()[0]
        c = g**((q-1)/4)
        t = E_j1728.trace_of_frobenius()
        L = [(t*(c**i).lift(), g**i) for i in range(4)]

        for i in range(4):
            compteur += 1
            if Integers(m)(L[i][0]) in S_t:
                # E, case, t
                return E_j1728.quartic_twist(L[i][1]), 1, compteur

    E_j0 = EllipticCurve(j = k(0))

    if q%6 != 1:
        # Same as before, if q != 1 mod 6, there's no 6th root of unity in
        # GF(q) and the trace is 0 (that's pretty quick reasoning.. :D).
        # Justification will come later.
        compteur += 1
        if 0 in S_t:
            return E_j0, 0, compteur
    else:
        g = k.unit_gens()[0]
        c = g**((q-1)/6)
        t = E_j0.trace_of_frobenius()
        L = [(t*(c**i).lift(), g**i) for i in range(6)]

        for l in L:
            if Integers(m)(l[0]) in S_t:
                return E_j0.sextic_twist(l[1]), 2, compteur

    # General case
    for j in k:
        if j == 0 or j == k(1728):
            continue

        E = EllipticCurve(j = j)
        t = E.trace_of_frobenius()
        L = [(t, E), (-t, E.quadratic_twist())]

        for l in L:
            compteur +=1
            if Integers(m)(l[0]) in S_t:
                return l[1], 0, compteur

    # If no elliptic curve has been found.
    return None, -1
コード例 #27
0
ファイル: Rainselliptic.py プロジェクト: brieulle/Rains-pinch
def find_elliptic_curve(k, K, m_t):
    '''
    INPUT: 

    - ``k`` -- a base field,

    - ``K`` -- an extension of K of degree n,

    - ``m_t`` -- a list of tuple containing an integer and a set of candidates 
      for the trace.

    OUTPUT: 
    
    - An elliptic curve defined over k with the required properties.

    - An integer case, depending on the value of the j-invariant or the 
      the supersingularity of said elliptic curve.

    EXAMPLES:
    
    sage: R.<X> = PolynomialRing(GF(5))

    sage: f = R.irreducible_element(19, algorithm = 'random')

    sage: K = GF(5**19, names = 'x', modulus = f)

    sage: m_t = (229,{2})

    sage: find_elliptic_curve(GF(5), K, m_t)

    (Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 5, 1)

    ALGORITHM:

    The goal is to pick an elliptic curve of which the trace of its Frobenius 
    t is among the right class modulo m, the ones in S_t. We do that in order to
    have point of order m only on E/GF(q^n) or above, since then the abscissas 
    of a point of order m will span GF(q^n) and we'll be able to compute the 
    elliptic periods as it was planned.

    We start by looking at the two special cases j = 1728 or 0. If q is not 1 
    modulo 4 and 3 respectively, then the curves are supersingular (t = 0) and 
    if 0 is among the good traces, they are to be treated like the other 
    curves.

    If for j = 0 we have q = 1 mod 3, then we have to tests E(j = 0) and all of
    its sextic twists. Once again if t is in S_t, then we return the right 
    curves and the case 2 to compute the periods accordingly.

    If for j = 1728 we have q = 1 mod 4, then we have to tests  E(j = 1728) and
    all of its quartic twists. If one the trace is in S_t, we return the right 
    curves and the case 1.

    If j != 0 and 1728, then we tests all the elements of GF(q) to find the 
    right curve. For each j we test if t or -t is in S_t and return the curve 
    accordingly plus the case 0.

    If no curves are found, we return None and the case -1, which will raise an
    runtimeError in the main function.
    '''
    p = k.characteristic()
    q = k.cardinality()
    m = m_t[0]
    S_t = m_t[1]

    #We start by the special cases j = 1728, 0
    E_j1728 = EllipticCurve(j = k(1728))

    if q%4 != 1:
        # If q != 1 mod 4, then there's no 4th root of unity, then magically
        # all the quartic twist are already in k and the trace is 0. We just
        # have to test the only curve y� = x� + x.
        if 0 in S_t:
            return E_j1728, 0
    else:
        # If q = 1 mod 4, then the trace is not 0, and we have to try four
        # trace to see which is the best candidate.
        g = k.unit_gens()[0]
        c = g**((q-1)/4)
        t = E_j1728.trace_of_frobenius()
        L = [(t*(c**i).centerlift(), g**i) for i in range(4)]

        for i in range(4):
            if Integers(m)(L[i][0]) in S_t:
                # E, case, t
                return E_j1728.quartic_twist(L[i][1]), 1

    E_j0 = EllipticCurve(j = k(0))

    if q%3 != 1:
        # Same as before, if q != 1 mod 6, there's no 6th root of unity in
        # GF(q) and the trace is 0 (that's pretty quick reasoning.. :D).
        # Justification will come later. Since q = 1 mod 2, if q = 1 mod 3
        # then q = 1 mod 6.
        if 0 in S_t:
            return E_j0, 0
    else:
        g = k.unit_gens()[0]
        c = g**((q-1)/6)
        t = E_j0.trace_of_frobenius()
        L = [(t*(c**i).centerlift(), g**i) for i in range(6)]

        for l in L:
            if Integers(m)(l[0]) in S_t:
                return E_j0.sextic_twist(l[1]), 2

    # General case
    for j in k:
        if j == 0 or j == k(1728):
            continue

        E = EllipticCurve(j = j)
        t = E.trace_of_frobenius()
        L = [(t, E), (-t, E.quadratic_twist())]

        for l in L:
            if Integers(m)(l[0]) in S_t:
                return l[1], 0

    # If no elliptic curve has been found.
    return None, -1
コード例 #28
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/2)
            sage: E = EllipticCurve('11a2')
            sage: m = sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1,normalize='period')
            sage: m._e
            (1, 5/2)
            sage: E = EllipticCurve('121b2')
            sage: m = sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1,normalize='period')
            sage: m._e
            (0, 0, 0, 11/2, 11/2, 11/2, 11/2, -3, 3/2, 1/2, -1, 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((q * 200).round()) / 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
コード例 #29
0
ファイル: ell_modular_symbols.py プロジェクト: mcognetta/sage
    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
コード例 #30
0
ファイル: ell_torsion.py プロジェクト: swewers/mein_sage
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