Example #1
0
    def descend_to(self, K, f=None):
        r"""
        Given a subfield `K` and an elliptic curve self defined over a field `L`,
        this function determines whether there exists an elliptic curve over `K`
        which is isomorphic over `L` to self. If one exists, it finds it.

        INPUT:

        - `K` -- a subfield of the base field of self.
        - `f` -- an embedding of `K` into the base field of self.

        OUTPUT:

        Either an elliptic curve defined over `K` which is isomorphic to self
        or None if no such curve exists.

        .. NOTE::

            This only works over number fields and QQ.

        EXAMPLES::

            sage: E = EllipticCurve([1,2,3,4,5])
            sage: E.descend_to(ZZ)
            Traceback (most recent call last):
            ...
            TypeError: Input must be a field.

        ::

            sage: F.<b> = QuadraticField(23)
            sage: G.<a> = F.extension(x^3+5)
            sage: E = EllipticCurve(j=1728*b).change_ring(G)
            sage: E.descend_to(F)
            Elliptic Curve defined by y^2 = x^3 + (8957952*b-206032896)*x + (-247669456896*b+474699792384) over Number Field in b with defining polynomial x^2 - 23

        ::

            sage: L.<a> = NumberField(x^4 - 7)
            sage: K.<b> = NumberField(x^2 - 7)
            sage: E = EllipticCurve([a^6,0])
            sage: E.descend_to(K)
            Elliptic Curve defined by y^2 = x^3 + 1296/49*b*x over Number Field in b with defining polynomial x^2 - 7

        ::

            sage: K.<a> = QuadraticField(17)
            sage: E = EllipticCurve(j = 2*a)
            sage: print E.descend_to(QQ)
            None
        """
        if not K.is_field():
            raise TypeError, "Input must be a field."
        if self.base_field()==K:
            return self
        j = self.j_invariant()
        from sage.rings.all import QQ
        if K == QQ:
            f = QQ.embeddings(self.base_field())[0]
            if j in QQ:
                jbase = QQ(j)
            else:
                return None
        elif f == None:
            embeddings = K.embeddings(self.base_field())
            if len(embeddings) == 0:
                raise TypeError, "Input must be a subfield of the base field of the curve."
            for g in embeddings:
                try:
                    jbase = g.preimage(j)
                    f = g
                    break
                except StandardError:
                    pass
            if f == None:
                return None
        else:
            try:
                jbase = f.preimage(j)
            except StandardError:
                return None
        E = EllipticCurve(j=jbase)
        E2 = EllipticCurve(self.base_field(), [f(a) for a in E.a_invariants()])
        if jbase==0:
            d = self.is_sextic_twist(E2)
            if d == 1:
                return E
            if d == 0:
                return None
            Etwist = E2.sextic_twist(d)
        elif jbase==1728:
            d = self.is_quartic_twist(E2)
            if d == 1:
                return E
            if d == 0:
                return None
            Etwist = E2.quartic_twist(d)
        else:
            d = self.is_quadratic_twist(E2)
            if d == 1:
                return E
            if d == 0:
                return None
            Etwist = E2.quadratic_twist(d)
        if Etwist.is_isomorphic(self):
            try:
                Eout = EllipticCurve(K, [f.preimage(a) for a in Etwist.a_invariants()])
            except StandardError:
                return None
            else:
                return Eout
Example #2
0
    def descend_to(self, K, f=None):
        r"""
        Given a subfield `K` and an elliptic curve self defined over a field `L`,
        this function determines whether there exists an elliptic curve over `K`
        which is isomorphic over `L` to self. If one exists, it finds it.

        INPUT:

        - `K` -- a subfield of the base field of self.
        - `f` -- an embedding of `K` into the base field of self.

        OUTPUT:

        Either an elliptic curve defined over `K` which is isomorphic to self
        or None if no such curve exists.

        .. NOTE::

            This only works over number fields and QQ.

        EXAMPLES::

            sage: E = EllipticCurve([1,2,3,4,5])
            sage: E.descend_to(ZZ)
            Traceback (most recent call last):
            ...
            TypeError: Input must be a field.

        ::

            sage: F.<b> = QuadraticField(23)
            sage: G.<a> = F.extension(x^3+5)
            sage: E = EllipticCurve(j=1728*b).change_ring(G)
            sage: E.descend_to(F)
            Elliptic Curve defined by y^2 = x^3 + (8957952*b-206032896)*x + (-247669456896*b+474699792384) over Number Field in b with defining polynomial x^2 - 23

        ::

            sage: L.<a> = NumberField(x^4 - 7)
            sage: K.<b> = NumberField(x^2 - 7)
            sage: E = EllipticCurve([a^6,0])
            sage: E.descend_to(K)
            Elliptic Curve defined by y^2 = x^3 + 1296/49*b*x over Number Field in b with defining polynomial x^2 - 7

        ::

            sage: K.<a> = QuadraticField(17)
            sage: E = EllipticCurve(j = 2*a)
            sage: print E.descend_to(QQ)
            None
        """
        if not K.is_field():
            raise TypeError, "Input must be a field."
        if self.base_field() == K:
            return self
        j = self.j_invariant()
        from sage.rings.all import QQ
        if K == QQ:
            f = QQ.embeddings(self.base_field())[0]
            if j in QQ:
                jbase = QQ(j)
            else:
                return None
        elif f == None:
            embeddings = K.embeddings(self.base_field())
            if len(embeddings) == 0:
                raise TypeError, "Input must be a subfield of the base field of the curve."
            for g in embeddings:
                try:
                    jbase = g.preimage(j)
                    f = g
                    break
                except StandardError:
                    pass
            if f == None:
                return None
        else:
            try:
                jbase = f.preimage(j)
            except StandardError:
                return None
        E = EllipticCurve(j=jbase)
        E2 = EllipticCurve(self.base_field(), [f(a) for a in E.a_invariants()])
        if jbase == 0:
            d = self.is_sextic_twist(E2)
            if d == 1:
                return E
            if d == 0:
                return None
            Etwist = E2.sextic_twist(d)
        elif jbase == 1728:
            d = self.is_quartic_twist(E2)
            if d == 1:
                return E
            if d == 0:
                return None
            Etwist = E2.quartic_twist(d)
        else:
            d = self.is_quadratic_twist(E2)
            if d == 1:
                return E
            if d == 0:
                return None
            Etwist = E2.quadratic_twist(d)
        if Etwist.is_isomorphic(self):
            try:
                Eout = EllipticCurve(
                    K, [f.preimage(a) for a in Etwist.a_invariants()])
            except StandardError:
                return None
            else:
                return Eout