def EllipticCurve_from_cubic(F, P): r""" Construct an elliptic curve from a ternary cubic with a rational point. INPUT: - ``F`` -- a homogeneous cubic in three variables with rational coefficients (either as a polynomial ring element or as a string) defining a smooth plane cubic curve. - ``P`` -- a 3-tuple `(x,y,z)` defining a projective point on the curve `F=0`. OUTPUT: (elliptic curve) An elliptic curve (in minimal Weierstrass form) isomorphic to the curve `F=0`. .. note:: USES MAGMA - This function will not work on computers that do not have magma installed. TO DO: implement this without using MAGMA. For a more general version, see the function ``EllipticCurve_from_plane_curve()``. EXAMPLES: First we find that the Fermat cubic is isomorphic to the curve with Cremona label 27a1:: sage: E = EllipticCurve_from_cubic('x^3 + y^3 + z^3', [1,-1,0]) # optional - magma sage: E # optional - magma Elliptic Curve defined by y^2 + y = x^3 - 7 over Rational Field sage: E.cremona_label() # optional - magma '27a1' Next we find the minimal model and conductor of the Jacobian of the Selmer curve. :: sage: E = EllipticCurve_from_cubic('u^3 + v^3 + 60*w^3', [1,-1,0]) # optional - magma sage: E # optional - magma Elliptic Curve defined by y^2 = x^3 - 24300 over Rational Field sage: E.conductor() # optional - magma 24300 """ from sage.interfaces.all import magma cmd = "P<%s,%s,%s> := ProjectivePlane(RationalField());" % SR( F).variables() magma.eval(cmd) cmd = 'aInvariants(MinimalModel(EllipticCurve(Curve(Scheme(P, %s)),P!%s)));' % ( F, P) s = magma.eval(cmd) return EllipticCurve(rings.RationalField(), eval(s))
def EllipticCurve_from_c4c6(c4, c6): """ Return an elliptic curve with given `c_4` and `c_6` invariants. EXAMPLES:: sage: E = EllipticCurve_from_c4c6(17, -2005) sage: E Elliptic Curve defined by y^2 = x^3 - 17/48*x + 2005/864 over Rational Field sage: E.c_invariants() (17, -2005) """ try: K = c4.parent() except AttributeError: K = rings.RationalField() if K not in _Fields: K = K.fraction_field() return EllipticCurve([-K(c4) / K(48), -K(c6) / K(864)])
def coefficients_from_j(j, minimal_twist=True): """ Return Weierstrass coefficients `(a_1, a_2, a_3, a_4, a_6)` for an elliptic curve with given `j`-invariant. INPUT: See :func:`EllipticCurve_from_j`. EXAMPLES:: sage: from sage.schemes.elliptic_curves.constructor import coefficients_from_j sage: coefficients_from_j(0) [0, 0, 1, 0, 0] sage: coefficients_from_j(1728) [0, 0, 0, -1, 0] sage: coefficients_from_j(1) [1, 0, 0, 36, 3455] The ``minimal_twist`` parameter (ignored except over `\\QQ` and True by default) controls whether or not a minimal twist is computed:: sage: coefficients_from_j(100) [0, 1, 0, 3392, 307888] sage: coefficients_from_j(100, minimal_twist=False) [0, 0, 0, 488400, -530076800] """ try: K = j.parent() except AttributeError: K = rings.RationalField() if K not in _Fields: K = K.fraction_field() char = K.characteristic() if char == 2: if j == 0: return Sequence([0, 0, 1, 0, 0], universe=K) else: return Sequence([1, 0, 0, 0, 1 / j], universe=K) if char == 3: if j == 0: return Sequence([0, 0, 0, 1, 0], universe=K) else: return Sequence([0, j, 0, 0, -j**2], universe=K) if K is rings.RationalField(): # we construct the minimal twist, i.e. the curve with minimal # conductor with this j_invariant: if j == 0: return Sequence([0, 0, 1, 0, 0], universe=K) # 27a3 if j == 1728: return Sequence([0, 0, 0, -1, 0], universe=K) # 32a2 if not minimal_twist: k = j - 1728 return Sequence([0, 0, 0, -3 * j * k, -2 * j * k**2], universe=K) n = j.numerator() m = n - 1728 * j.denominator() a4 = -3 * n * m a6 = -2 * n * m**2 # Now E=[0,0,0,a4,a6] has j-invariant j=n/d from sage.sets.set import Set for p in Set(n.prime_divisors() + m.prime_divisors()): e = min(a4.valuation(p) // 2, a6.valuation(p) // 3) if e > 0: p = p**e a4 /= p**2 a6 /= p**3 # Now E=[0,0,0,a4,a6] is minimal at all p != 2,3 tw = [-1, 2, -2, 3, -3, 6, -6] E1 = EllipticCurve([0, 0, 0, a4, a6]) Elist = [E1] + [E1.quadratic_twist(t) for t in tw] Elist.sort(key=lambda E: E.conductor()) return Sequence(Elist[0].ainvs()) # defaults for all other fields: if j == 0: return Sequence([0, 0, 0, 0, 1], universe=K) if j == 1728: return Sequence([0, 0, 0, 1, 0], universe=K) k = j - 1728 return Sequence([0, 0, 0, -3 * j * k, -2 * j * k**2], universe=K)
def EllipticCurve_from_j(j, minimal_twist=True): """ Return an elliptic curve with given `j`-invariant. INPUT: - ``j`` -- an element of some field. - ``minimal_twist`` (boolean, default True) -- If True and ``j`` is in `\QQ`, the curve returned is a minimal twist, i.e. has minimal conductor. If `j` is not in `\QQ` this parameter is ignored. OUTPUT: An elliptic curve with `j`-invariant `j`. EXAMPLES:: sage: E = EllipticCurve_from_j(0); E; E.j_invariant(); E.label() Elliptic Curve defined by y^2 + y = x^3 over Rational Field 0 '27a3' sage: E = EllipticCurve_from_j(1728); E; E.j_invariant(); E.label() Elliptic Curve defined by y^2 = x^3 - x over Rational Field 1728 '32a2' sage: E = EllipticCurve_from_j(1); E; E.j_invariant() Elliptic Curve defined by y^2 + x*y = x^3 + 36*x + 3455 over Rational Field 1 The ``minimal_twist`` parameter (ignored except over `\QQ` and True by default) controls whether or not a minimal twist is computed:: sage: EllipticCurve_from_j(100) Elliptic Curve defined by y^2 = x^3 + x^2 + 3392*x + 307888 over Rational Field sage: _.conductor() 33129800 sage: EllipticCurve_from_j(100, minimal_twist=False) Elliptic Curve defined by y^2 = x^3 + 488400*x - 530076800 over Rational Field sage: _.conductor() 298168200 Since computing the minimal twist requires factoring both `j` and `j-1728` the following example would take a long time without setting ``minimal_twist`` to False:: sage: E = EllipticCurve_from_j(2^256+1,minimal_twist=False) sage: E.j_invariant() == 2^256+1 True """ try: K = j.parent() except AttributeError: K = rings.RationalField() if K not in _Fields: K = K.fraction_field() char = K.characteristic() if char == 2: if j == 0: return EllipticCurve(K, [0, 0, 1, 0, 0]) else: return EllipticCurve(K, [1, 0, 0, 0, 1 / j]) if char == 3: if j == 0: return EllipticCurve(K, [0, 0, 0, 1, 0]) else: return EllipticCurve(K, [0, j, 0, 0, -j**2]) if K is rings.RationalField(): # we construct the minimal twist, i.e. the curve with minimal # conductor with this j_invariant: if j == 0: return EllipticCurve(K, [0, 0, 1, 0, 0]) # 27a3 if j == 1728: return EllipticCurve(K, [0, 0, 0, -1, 0]) # 32a2 if not minimal_twist: k = j - 1728 return EllipticCurve(K, [0, 0, 0, -3 * j * k, -2 * j * k**2]) n = j.numerator() m = n - 1728 * j.denominator() a4 = -3 * n * m a6 = -2 * n * m**2 # Now E=[0,0,0,a4,a6] has j-invariant j=n/d from sage.sets.set import Set for p in Set(n.prime_divisors() + m.prime_divisors()): e = min(a4.valuation(p) // 2, a6.valuation(p) // 3) if e > 0: p = p**e a4 /= p**2 a6 /= p**3 # Now E=[0,0,0,a4,a6] is minimal at all p != 2,3 tw = [-1, 2, -2, 3, -3, 6, -6] E1 = EllipticCurve([0, 0, 0, a4, a6]) Elist = [E1] + [E1.quadratic_twist(t) for t in tw] crv_cmp = lambda E, F: cmp(E.conductor(), F.conductor()) Elist.sort(cmp=crv_cmp) return Elist[0] # defaults for all other fields: if j == 0: return EllipticCurve(K, [0, 0, 0, 0, 1]) if j == 1728: return EllipticCurve(K, [0, 0, 0, 1, 0]) k = j - 1728 return EllipticCurve(K, [0, 0, 0, -3 * j * k, -2 * j * k**2])
def EllipticCurve_from_plane_curve(C, P): r""" Construct an elliptic curve from a smooth plane cubic with a rational point. INPUT: - ``C`` -- a plane curve of genus one. - ``P`` -- a 3-tuple `(x,y,z)` defining a projective point on the curve ``C``. OUTPUT: (elliptic curve) An elliptic curve (in minimal Weierstrass form) isomorphic to ``C``. .. note:: USES MAGMA - This function will not work on computers that do not have magma installed. TO DO: implement this without using MAGMA. EXAMPLES: First we check that the Fermat cubic is isomorphic to the curve with Cremona label '27a1':: sage: x,y,z=PolynomialRing(QQ,3,'xyz').gens() # optional - magma sage: C=Curve(x^3+y^3+z^3) # optional - magma sage: P=C(1,-1,0) # optional - magma sage: E=EllipticCurve_from_plane_curve(C,P) # optional - magma sage: E # optional - magma Elliptic Curve defined by y^2 + y = x^3 - 7 over Rational Field sage: E.label() # optional - magma '27a1' Now we try a quartic example:: sage: u,v,w=PolynomialRing(QQ,3,'uvw').gens() # optional - magma sage: C=Curve(u^4+u^2*v^2-w^4) # optional - magma sage: P=C(1,0,1) # optional - magma sage: E=EllipticCurve_from_plane_curve(C,P) # optional - magma sage: E # optional - magma Elliptic Curve defined by y^2 = x^3 + 4*x over Rational Field sage: E.label() # optional - magma '32a1' """ from sage.interfaces.all import magma if C.genus() != 1: raise TypeError, "The curve C must have genus 1" elif P.parent() != C.point_set(C.base_ring()): raise TypeError, "The point P must be on the curve C" dp = C.defining_polynomial() x, y, z = dp.parent().variable_names() cmd = "PR<%s,%s,%s>:=ProjectivePlane(RationalField());" % (x, y, z) magma.eval(cmd) cmd = 'CC:=Curve(PR, %s);' % (dp) magma.eval(cmd) cmd = 'aInvariants(MinimalModel(EllipticCurve(CC,CC!%s)));' % ( [P[0], P[1], P[2]]) s = magma.eval(cmd) return EllipticCurve(rings.RationalField(), eval(s))
def EllipticCurve_from_j(j): """ Return an elliptic curve with given `j`-invariant. EXAMPLES:: sage: E = EllipticCurve_from_j(0); E; E.j_invariant(); E.label() Elliptic Curve defined by y^2 + y = x^3 over Rational Field 0 '27a3' sage: E = EllipticCurve_from_j(1728); E; E.j_invariant(); E.label() Elliptic Curve defined by y^2 = x^3 - x over Rational Field 1728 '32a2' sage: E = EllipticCurve_from_j(1); E; E.j_invariant() Elliptic Curve defined by y^2 + x*y = x^3 + 36*x + 3455 over Rational Field 1 """ try: K = j.parent() except AttributeError: K = rings.RationalField() if not rings.is_Field(K): K = K.fraction_field() char=K.characteristic() if char==2: if j == 0: return EllipticCurve(K, [ 0, 0, 1, 0, 0 ]) else: return EllipticCurve(K, [ 1, 0, 0, 0, 1/j ]) if char == 3: if j==0: return EllipticCurve(K, [ 0, 0, 0, 1, 0 ]) else: return EllipticCurve(K, [ 0, j, 0, 0, -j**2 ]) if K is rings.RationalField(): # we construct the minimal twist, i.e. the curve with minimal # conductor with this j_invariant: if j == 0: return EllipticCurve(K, [ 0, 0, 1, 0, 0 ]) # 27a3 if j == 1728: return EllipticCurve(K, [ 0, 0, 0, -1, 0 ]) # 32a2 n = j.numerator() m = n-1728*j.denominator() a4 = -3*n*m a6 = -2*n*m**2 # Now E=[0,0,0,a4,a6] has j-invariant j=n/d from sage.sets.set import Set for p in Set(n.prime_divisors()+m.prime_divisors()): e = min(a4.valuation(p)//2,a6.valuation(p)//3) if e>0: p = p**e a4 /= p**2 a6 /= p**3 # Now E=[0,0,0,a4,a6] is minimal at all p != 2,3 tw = [-1,2,-2,3,-3,6,-6] E1 = EllipticCurve([0,0,0,a4,a6]) Elist = [E1] + [E1.quadratic_twist(t) for t in tw] crv_cmp = lambda E,F: cmp(E.conductor(),F.conductor()) Elist.sort(cmp=crv_cmp) return Elist[0] # defaults for all other fields: if j == 0: return EllipticCurve(K, [ 0, 0, 0, 0, 1 ]) if j == 1728: return EllipticCurve(K, [ 0, 0, 0, 1, 0 ]) k=j-1728 return EllipticCurve(K, [0,0,0,-3*j*k, -2*j*k**2])