def base_extend(self, R): r""" Return the natural extension of ``self`` over `R` INPUT: - ``R`` -- a field. The new base field. OUTPUT: The Jacobian over the ring `R`. EXAMPLES:: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^3-10*x+9) sage: Jac = H.jacobian(); Jac Jacobian of Hyperelliptic Curve over Rational Field defined by y^2 = x^3 - 10*x + 9 sage: F.<a> = QQ.extension(x^2+1) sage: Jac.base_extend(F) Jacobian of Hyperelliptic Curve over Number Field in a with defining polynomial x^2 + 1 defined by y^2 = x^3 - 10*x + 9 """ if not is_Field(R): raise ValueError('Not a field: '+str(R)) if self.base_ring() is R: return self if not R.has_coerce_map_from(self.base_ring()): raise ValueError('no natural map from the base ring (=%s) to R (=%s)!' % (self.base_ring(), R)) return self.change_ring(R)
def __init__(self, abvar, field_of_definition=QQ): """ A finite subgroup of a modular abelian variety. INPUT: - ``abvar`` - a modular abelian variety - ``field_of_definition`` - a field over which this group is defined. EXAMPLES: This is an abstract base class, so there are no instances of this class itself. :: sage: A = J0(37) sage: G = A.torsion_subgroup(3); G Finite subgroup with invariants [3, 3, 3, 3] over QQ of Abelian variety J0(37) of dimension 2 sage: type(G) <class 'sage.modular.abvar.finite_subgroup.FiniteSubgroup_lattice'> sage: from sage.modular.abvar.finite_subgroup import FiniteSubgroup sage: isinstance(G, FiniteSubgroup) True """ if not is_Field(field_of_definition): raise TypeError, "field_of_definition must be a field" if not abelian_variety.is_ModularAbelianVariety(abvar): raise TypeError, "abvar must be a modular abelian variety" Module_old.__init__(self, ZZ) self.__abvar = abvar self.__field_of_definition = field_of_definition
def base_extend(self, R): r""" Return the natural extension of ``self`` over `R` INPUT: - ``R`` -- a field. The new base field. OUTPUT: The Jacobian over the ring `R`. EXAMPLES:: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^3-10*x+9) sage: Jac = H.jacobian(); Jac Jacobian of Hyperelliptic Curve over Rational Field defined by y^2 = x^3 - 10*x + 9 sage: F.<a> = QQ.extension(x^2+1) sage: Jac.base_extend(F) Jacobian of Hyperelliptic Curve over Number Field in a with defining polynomial x^2 + 1 defined by y^2 = x^3 - 10*x + 9 """ if not is_Field(R): raise ValueError('Not a field: ' + str(R)) if self.base_ring() is R: return self if not R.has_coerce_map_from(self.base_ring()): raise ValueError( 'no natural map from the base ring (=%s) to R (=%s)!' % (self.base_ring(), R)) return self.change_ring(R)
def base_extend(self, S): r""" Returns the conic over ``S`` given by the same equation as ``self``. EXAMPLES:: sage: c = Conic([1, 1, 1]); c Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^2 sage: c.has_rational_point() False sage: d = c.base_extend(QuadraticField(-1, 'i')); d Projective Conic Curve over Number Field in i with defining polynomial x^2 + 1 defined by x^2 + y^2 + z^2 sage: d.rational_point(algorithm = 'rnfisnorm') (i : 1 : 0) """ if is_Field(S): B = self.base_ring() if B == S: return self if not S.has_coerce_map_from(B): raise ValueError, "No natural map from the base ring of self " \ "(= %s) to S (= %s)" % (self, S) from constructor import Conic con = Conic([S(c) for c in self.coefficients()], \ self.variable_names()) if self._rational_point != None: pt = [S(c) for c in Sequence(self._rational_point)] if not pt == [0,0,0]: # The following line stores the point in the cache # if (and only if) there is no point in the cache. pt = con.point(pt) return con return ProjectiveCurve_generic.base_extend(self, 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 not rings.is_Field(K): K = K.fraction_field() return EllipticCurve([-K(c4) / K(48), -K(c6) / K(864)])
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 not rings.is_Field(K): K = K.fraction_field() return EllipticCurve([-K(c4)/K(48), -K(c6)/K(864)])
def __init__(self, C): """ TESTS:: sage: from sage.schemes.jacobians.abstract_jacobian import Jacobian_generic sage: P2.<x, y, z> = ProjectiveSpace(QQ, 2) sage: C = Curve(x^3 + y^3 + z^3) sage: J = Jacobian_generic(C); J Jacobian of Projective Curve over Rational Field defined by x^3 + y^3 + z^3 sage: type(J) <class 'sage.schemes.jacobians.abstract_jacobian.Jacobian_generic_with_category'> Note: this is an abstract parent, so we skip element tests:: sage: TestSuite(J).run(skip =["_test_an_element", "_test_elements", "_test_elements_eq", "_test_some_elements"]) :: sage: Jacobian_generic(ZZ) Traceback (most recent call last): ... TypeError: Argument (=Integer Ring) must be a scheme. sage: Jacobian_generic(P2) Traceback (most recent call last): ... ValueError: C (=Projective Space of dimension 2 over Rational Field) must have dimension 1. sage: P2.<x, y, z> = ProjectiveSpace(Zmod(6), 2) sage: C = Curve(x + y + z) sage: Jacobian_generic(C) Traceback (most recent call last): ... TypeError: C (=Projective Curve over Ring of integers modulo 6 defined by x + y + z) must be defined over a field. """ if not is_Scheme(C): raise TypeError, "Argument (=%s) must be a scheme."%C if not is_Field(C.base_ring()): raise TypeError, "C (=%s) must be defined over a field."%C if C.dimension() != 1: raise ValueError, "C (=%s) must have dimension 1."%C self.__curve = C Scheme.__init__(self, C.base_scheme())
def __init__(self, C): """ TESTS:: sage: from sage.schemes.jacobians.abstract_jacobian import Jacobian_generic sage: P2.<x, y, z> = ProjectiveSpace(QQ, 2) sage: C = Curve(x^3 + y^3 + z^3) sage: J = Jacobian_generic(C); J Jacobian of Projective Curve over Rational Field defined by x^3 + y^3 + z^3 sage: type(J) <class 'sage.schemes.jacobians.abstract_jacobian.Jacobian_generic_with_category'> Note: this is an abstract parent, so we skip element tests:: sage: TestSuite(J).run(skip =["_test_an_element", "_test_elements", "_test_elements_eq", "_test_some_elements"]) :: sage: Jacobian_generic(ZZ) Traceback (most recent call last): ... TypeError: Argument (=Integer Ring) must be a scheme. sage: Jacobian_generic(P2) Traceback (most recent call last): ... ValueError: C (=Projective Space of dimension 2 over Rational Field) must have dimension 1. sage: P2.<x, y, z> = ProjectiveSpace(Zmod(6), 2) sage: C = Curve(x + y + z) sage: Jacobian_generic(C) Traceback (most recent call last): ... TypeError: C (=Projective Curve over Ring of integers modulo 6 defined by x + y + z) must be defined over a field. """ if not is_Scheme(C): raise TypeError, "Argument (=%s) must be a scheme." % C if not is_Field(C.base_ring()): raise TypeError, "C (=%s) must be defined over a field." % C if C.dimension() != 1: raise ValueError, "C (=%s) must have dimension 1." % C self.__curve = C Scheme.__init__(self, C.base_scheme())
def ProjectiveSpace(n, R=None, names='x'): r""" Return projective space of dimension `n` over the ring `R`. EXAMPLES: The dimension and ring can be given in either order. :: sage: ProjectiveSpace(3, QQ) Projective Space of dimension 3 over Rational Field sage: ProjectiveSpace(5, QQ) Projective Space of dimension 5 over Rational Field sage: P = ProjectiveSpace(2, QQ, names='XYZ'); P Projective Space of dimension 2 over Rational Field sage: P.coordinate_ring() Multivariate Polynomial Ring in X, Y, Z over Rational Field The divide operator does base extension. :: sage: ProjectiveSpace(5)/GF(17) Projective Space of dimension 5 over Finite Field of size 17 The default base ring is `\ZZ`. :: sage: ProjectiveSpace(5) Projective Space of dimension 5 over Integer Ring There is also an projective space associated each polynomial ring. :: sage: R = GF(7)['x,y,z'] sage: P = ProjectiveSpace(R); P Projective Space of dimension 2 over Finite Field of size 7 sage: P.coordinate_ring() Multivariate Polynomial Ring in x, y, z over Finite Field of size 7 sage: P.coordinate_ring() is R True Projective spaces are not cached, i.e., there can be several with the same base ring and dimension (to facilitate gluing constructions). """ if is_MPolynomialRing(n) and R is None: A = ProjectiveSpace(n.ngens() - 1, n.base_ring()) A._coordinate_ring = n return A if isinstance(R, (int, long, Integer)): n, R = R, n if R is None: R = ZZ # default is the integers if is_Field(R): if is_FiniteField(R): return ProjectiveSpace_finite_field(n, R, names) if is_RationalField(R): return ProjectiveSpace_rational_field(n, R, names) else: return ProjectiveSpace_field(n, R, names) elif is_CommutativeRing(R): return ProjectiveSpace_ring(n, R, names) else: raise TypeError, "R (=%s) must be a commutative ring" % R
def ProjectiveSpace(n, R=None, names="x"): r""" Return projective space of dimension `n` over the ring `R`. EXAMPLES: The dimension and ring can be given in either order. :: sage: ProjectiveSpace(3, QQ) Projective Space of dimension 3 over Rational Field sage: ProjectiveSpace(5, QQ) Projective Space of dimension 5 over Rational Field sage: P = ProjectiveSpace(2, QQ, names='XYZ'); P Projective Space of dimension 2 over Rational Field sage: P.coordinate_ring() Multivariate Polynomial Ring in X, Y, Z over Rational Field The divide operator does base extension. :: sage: ProjectiveSpace(5)/GF(17) Projective Space of dimension 5 over Finite Field of size 17 The default base ring is `\ZZ`. :: sage: ProjectiveSpace(5) Projective Space of dimension 5 over Integer Ring There is also an projective space associated each polynomial ring. :: sage: R = GF(7)['x,y,z'] sage: P = ProjectiveSpace(R); P Projective Space of dimension 2 over Finite Field of size 7 sage: P.coordinate_ring() Multivariate Polynomial Ring in x, y, z over Finite Field of size 7 sage: P.coordinate_ring() is R True Projective spaces are not cached, i.e., there can be several with the same base ring and dimension (to facilitate gluing constructions). """ if is_MPolynomialRing(n) and R is None: A = ProjectiveSpace(n.ngens() - 1, n.base_ring()) A._coordinate_ring = n return A if isinstance(R, (int, long, Integer)): n, R = R, n if R is None: R = ZZ # default is the integers if is_Field(R): if is_FiniteField(R): return ProjectiveSpace_finite_field(n, R, names) if is_RationalField(R): return ProjectiveSpace_rational_field(n, R, names) else: return ProjectiveSpace_field(n, R, names) elif is_CommutativeRing(R): return ProjectiveSpace_ring(n, R, names) else: raise TypeError, "R (=%s) must be a commutative ring" % R
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])
def EllipticCurve(x=None, y=None, j=None): r""" There are several ways to construct an elliptic curve: .. math:: y^2 + a_1 xy + a_3 y = x^3 + a_2 x^2 + a_4 x + a_6. - EllipticCurve([a1,a2,a3,a4,a6]): Elliptic curve with given a-invariants. The invariants are coerced into the parent of the first element. If all are integers, they are coerced into the rational numbers. - EllipticCurve([a4,a6]): Same as above, but a1=a2=a3=0. - EllipticCurve(label): Returns the elliptic curve over Q from the Cremona database with the given label. The label is a string, such as "11a" or "37b2". The letters in the label *must* be lower case (Cremona's new labeling). - EllipticCurve(R, [a1,a2,a3,a4,a6]): Create the elliptic curve over R with given a-invariants. Here R can be an arbitrary ring. Note that addition need not be defined. - EllipticCurve(j): Return an elliptic curve with j-invariant `j`. Warning: this is deprecated. Use ``EllipticCurve_from_j(j)`` or ``EllipticCurve(j=j)`` instead. In each case above where the input is a list of length 2 or 5, one can instead give a 2 or 5-tuple instead. EXAMPLES: We illustrate creating elliptic curves. :: sage: EllipticCurve([0,0,1,-1,0]) Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field We create a curve from a Cremona label:: sage: EllipticCurve('37b2') Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873*x - 31833 over Rational Field sage: EllipticCurve('5077a') Elliptic Curve defined by y^2 + y = x^3 - 7*x + 6 over Rational Field sage: EllipticCurve('389a') Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field Unicode labels are allowed:: sage: EllipticCurve(u'389a') Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field We create curves over a finite field as follows:: sage: EllipticCurve([GF(5)(0),0,1,-1,0]) Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5 sage: EllipticCurve(GF(5), [0, 0,1,-1,0]) Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5 Elliptic curves over `\ZZ/N\ZZ` with `N` prime are of type "elliptic curve over a finite field":: sage: F = Zmod(101) sage: EllipticCurve(F, [2, 3]) Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 101 sage: E = EllipticCurve([F(2), F(3)]) sage: type(E) <class 'sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field_with_category'> sage: E.category() Category of schemes over Ring of integers modulo 101 In contrast, elliptic curves over `\ZZ/N\ZZ` with `N` composite are of type "generic elliptic curve":: sage: F = Zmod(95) sage: EllipticCurve(F, [2, 3]) Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 95 sage: E = EllipticCurve([F(2), F(3)]) sage: type(E) <class 'sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic_with_category'> sage: E.category() Category of schemes over Ring of integers modulo 95 The following is a curve over the complex numbers:: sage: E = EllipticCurve(CC, [0,0,1,-1,0]) sage: E Elliptic Curve defined by y^2 + 1.00000000000000*y = x^3 + (-1.00000000000000)*x over Complex Field with 53 bits of precision sage: E.j_invariant() 2988.97297297297 We can also create elliptic curves by giving the Weierstrass equation:: sage: x, y = var('x,y') sage: EllipticCurve(y^2 + y == x^3 + x - 9) Elliptic Curve defined by y^2 + y = x^3 + x - 9 over Rational Field sage: R.<x,y> = GF(5)[] sage: EllipticCurve(x^3 + x^2 + 2 - y^2 - y*x) Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 2 over Finite Field of size 5 We can explicitly specify the `j`-invariant:: sage: E = EllipticCurve(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(j=GF(5)(2)); E; E.j_invariant() Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5 2 See trac #6657:: sage: EllipticCurve(GF(144169),j=1728) Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 144169 TESTS:: sage: R = ZZ['u', 'v'] sage: EllipticCurve(R, [1,1]) Elliptic Curve defined by y^2 = x^3 + x + 1 over Multivariate Polynomial Ring in u, v over Integer Ring We create a curve and a point over QQbar (see #6879):: sage: E = EllipticCurve(QQbar,[0,1]) sage: E(0) (0 : 1 : 0) sage: E.base_field() Algebraic Field sage: E = EllipticCurve(RR,[1,2]); E; E.base_field() Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision Real Field with 53 bits of precision sage: EllipticCurve(CC,[3,4]); E; E.base_field() Elliptic Curve defined by y^2 = x^3 + 3.00000000000000*x + 4.00000000000000 over Complex Field with 53 bits of precision Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision Real Field with 53 bits of precision sage: E = EllipticCurve(QQbar,[5,6]); E; E.base_field() Elliptic Curve defined by y^2 = x^3 + 5*x + 6 over Algebraic Field Algebraic Field See trac #6657:: sage: EllipticCurve(3,j=1728) Traceback (most recent call last): ... ValueError: First parameter (if present) must be a ring when j is specified sage: EllipticCurve(GF(5),j=3/5) Traceback (most recent call last): ... ValueError: First parameter must be a ring containing 3/5 If the universe of the coefficients is a general field, the object constructed has type EllipticCurve_field. Otherwise it is EllipticCurve_generic. See trac #9816:: sage: E = EllipticCurve([QQbar(1),3]); E Elliptic Curve defined by y^2 = x^3 + x + 3 over Algebraic Field sage: type(E) <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'> sage: E = EllipticCurve([RR(1),3]); E Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 3.00000000000000 over Real Field with 53 bits of precision sage: type(E) <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'> sage: E = EllipticCurve([i,i]); E Elliptic Curve defined by y^2 = x^3 + I*x + I over Symbolic Ring sage: type(E) <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'> sage: E.category() Category of schemes over Symbolic Ring sage: is_field(SR) True sage: F = FractionField(PolynomialRing(QQ,'t')) sage: t = F.gen() sage: E = EllipticCurve([t,0]); E Elliptic Curve defined by y^2 = x^3 + t*x over Fraction Field of Univariate Polynomial Ring in t over Rational Field sage: type(E) <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'> sage: E.category() Category of schemes over Fraction Field of Univariate Polynomial Ring in t over Rational Field See :trac:`12517`:: sage: E = EllipticCurve([1..5]) sage: EllipticCurve(E.a_invariants()) Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field """ import ell_generic, ell_field, ell_finite_field, ell_number_field, ell_rational_field, ell_padic_field # here to avoid circular includes if j is not None: if not x is None: if rings.is_Ring(x): try: j = x(j) except (ZeroDivisionError, ValueError, TypeError): raise ValueError, "First parameter must be a ring containing %s" % j else: raise ValueError, "First parameter (if present) must be a ring when j is specified" return EllipticCurve_from_j(j) assert x is not None if is_SymbolicEquation(x): x = x.lhs() - x.rhs() if parent(x) is SR: x = x._polynomial_(rings.QQ["x", "y"]) if rings.is_MPolynomial(x) and y is None: f = x if f.degree() != 3: raise ValueError, "Elliptic curves must be defined by a cubic polynomial." if f.degrees() == (3, 2): x, y = f.parent().gens() elif f.degree() == (2, 3): y, x = f.parent().gens() elif len(f.parent().gens()) == 2 or len(f.parent().gens()) == 3 and f.is_homogeneous(): # We'd need a point too... raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented." else: raise ValueError, "Defining polynomial must be a cubic polynomial in two variables." try: if f.coefficient(x ** 3) < 0: f = -f # is there a nicer way to extract the coefficients? a1 = a2 = a3 = a4 = a6 = 0 for coeff, mon in f: if mon == x ** 3: assert coeff == 1 elif mon == x ** 2: a2 = coeff elif mon == x: a4 = coeff elif mon == 1: a6 = coeff elif mon == y ** 2: assert coeff == -1 elif mon == x * y: a1 = -coeff elif mon == y: a3 = -coeff else: assert False return EllipticCurve([a1, a2, a3, a4, a6]) except AssertionError: raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented." if rings.is_Ring(x): if rings.is_RationalField(x): return ell_rational_field.EllipticCurve_rational_field(x, y) elif rings.is_FiniteField(x) or (rings.is_IntegerModRing(x) and x.characteristic().is_prime()): return ell_finite_field.EllipticCurve_finite_field(x, y) elif rings.is_pAdicField(x): return ell_padic_field.EllipticCurve_padic_field(x, y) elif rings.is_NumberField(x): return ell_number_field.EllipticCurve_number_field(x, y) elif rings.is_Field(x): return ell_field.EllipticCurve_field(x, y) return ell_generic.EllipticCurve_generic(x, y) if isinstance(x, unicode): x = str(x) if isinstance(x, str): return ell_rational_field.EllipticCurve_rational_field(x) if rings.is_RingElement(x) and y is None: from sage.misc.misc import deprecation deprecation("'EllipticCurve(j)' is deprecated; use 'EllipticCurve_from_j(j)' or 'EllipticCurve(j=j)' instead.") # Fixed for all characteristics and cases by John Cremona j = x F = j.parent().fraction_field() char = F.characteristic() if char == 2: if j == 0: return EllipticCurve(F, [0, 0, 1, 0, 0]) else: return EllipticCurve(F, [1, 0, 0, 0, 1 / j]) if char == 3: if j == 0: return EllipticCurve(F, [0, 0, 0, 1, 0]) else: return EllipticCurve(F, [0, j, 0, 0, -j ** 2]) if j == 0: return EllipticCurve(F, [0, 0, 0, 0, 1]) if j == 1728: return EllipticCurve(F, [0, 0, 0, 1, 0]) k = j - 1728 return EllipticCurve(F, [0, 0, 0, -3 * j * k, -2 * j * k ** 2]) if not isinstance(x, (list, tuple)): raise TypeError, "invalid input to EllipticCurve constructor" x = Sequence(x) if not (len(x) in [2, 5]): raise ValueError, "sequence of coefficients must have length 2 or 5" R = x.universe() if isinstance(x[0], (rings.Rational, rings.Integer, int, long)): return ell_rational_field.EllipticCurve_rational_field(x, y) elif rings.is_NumberField(R): return ell_number_field.EllipticCurve_number_field(x, y) elif rings.is_pAdicField(R): return ell_padic_field.EllipticCurve_padic_field(x, y) elif rings.is_FiniteField(R) or (rings.is_IntegerModRing(R) and R.characteristic().is_prime()): return ell_finite_field.EllipticCurve_finite_field(x, y) elif rings.is_Field(R): return ell_field.EllipticCurve_field(x, y) return ell_generic.EllipticCurve_generic(x, y)
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])
def EllipticCurve(x=None, y=None, j=None): r""" There are several ways to construct an elliptic curve: .. math:: y^2 + a_1 xy + a_3 y = x^3 + a_2 x^2 + a_4 x + a_6. - EllipticCurve([a1,a2,a3,a4,a6]): Elliptic curve with given a-invariants. The invariants are coerced into the parent of the first element. If all are integers, they are coerced into the rational numbers. - EllipticCurve([a4,a6]): Same as above, but a1=a2=a3=0. - EllipticCurve(label): Returns the elliptic curve over Q from the Cremona database with the given label. The label is a string, such as "11a" or "37b2". The letters in the label *must* be lower case (Cremona's new labeling). - EllipticCurve(R, [a1,a2,a3,a4,a6]): Create the elliptic curve over R with given a-invariants. Here R can be an arbitrary ring. Note that addition need not be defined. - EllipticCurve(j): Return an elliptic curve with j-invariant `j`. Warning: this is deprecated. Use ``EllipticCurve_from_j(j)`` or ``EllipticCurve(j=j)`` instead. In each case above where the input is a list of length 2 or 5, one can instead give a 2 or 5-tuple instead. EXAMPLES: We illustrate creating elliptic curves. :: sage: EllipticCurve([0,0,1,-1,0]) Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field We create a curve from a Cremona label:: sage: EllipticCurve('37b2') Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873*x - 31833 over Rational Field sage: EllipticCurve('5077a') Elliptic Curve defined by y^2 + y = x^3 - 7*x + 6 over Rational Field sage: EllipticCurve('389a') Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field Unicode labels are allowed:: sage: EllipticCurve(u'389a') Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field We create curves over a finite field as follows:: sage: EllipticCurve([GF(5)(0),0,1,-1,0]) Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5 sage: EllipticCurve(GF(5), [0, 0,1,-1,0]) Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5 Elliptic curves over `\ZZ/N\ZZ` with `N` prime are of type "elliptic curve over a finite field":: sage: F = Zmod(101) sage: EllipticCurve(F, [2, 3]) Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 101 sage: E = EllipticCurve([F(2), F(3)]) sage: type(E) <class 'sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field_with_category'> sage: E.category() Category of schemes over Ring of integers modulo 101 In contrast, elliptic curves over `\ZZ/N\ZZ` with `N` composite are of type "generic elliptic curve":: sage: F = Zmod(95) sage: EllipticCurve(F, [2, 3]) Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 95 sage: E = EllipticCurve([F(2), F(3)]) sage: type(E) <class 'sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic_with_category'> sage: E.category() Category of schemes over Ring of integers modulo 95 The following is a curve over the complex numbers:: sage: E = EllipticCurve(CC, [0,0,1,-1,0]) sage: E Elliptic Curve defined by y^2 + 1.00000000000000*y = x^3 + (-1.00000000000000)*x over Complex Field with 53 bits of precision sage: E.j_invariant() 2988.97297297297 We can also create elliptic curves by giving the Weierstrass equation:: sage: x, y = var('x,y') sage: EllipticCurve(y^2 + y == x^3 + x - 9) Elliptic Curve defined by y^2 + y = x^3 + x - 9 over Rational Field sage: R.<x,y> = GF(5)[] sage: EllipticCurve(x^3 + x^2 + 2 - y^2 - y*x) Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 2 over Finite Field of size 5 We can explicitly specify the `j`-invariant:: sage: E = EllipticCurve(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(j=GF(5)(2)); E; E.j_invariant() Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5 2 See trac #6657:: sage: EllipticCurve(GF(144169),j=1728) Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 144169 TESTS:: sage: R = ZZ['u', 'v'] sage: EllipticCurve(R, [1,1]) Elliptic Curve defined by y^2 = x^3 + x + 1 over Multivariate Polynomial Ring in u, v over Integer Ring We create a curve and a point over QQbar (see #6879):: sage: E = EllipticCurve(QQbar,[0,1]) sage: E(0) (0 : 1 : 0) sage: E.base_field() Algebraic Field sage: E = EllipticCurve(RR,[1,2]); E; E.base_field() Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision Real Field with 53 bits of precision sage: EllipticCurve(CC,[3,4]); E; E.base_field() Elliptic Curve defined by y^2 = x^3 + 3.00000000000000*x + 4.00000000000000 over Complex Field with 53 bits of precision Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision Real Field with 53 bits of precision sage: E = EllipticCurve(QQbar,[5,6]); E; E.base_field() Elliptic Curve defined by y^2 = x^3 + 5*x + 6 over Algebraic Field Algebraic Field See trac #6657:: sage: EllipticCurve(3,j=1728) Traceback (most recent call last): ... ValueError: First parameter (if present) must be a ring when j is specified sage: EllipticCurve(GF(5),j=3/5) Traceback (most recent call last): ... ValueError: First parameter must be a ring containing 3/5 If the universe of the coefficients is a general field, the object constructed has type EllipticCurve_field. Otherwise it is EllipticCurve_generic. See trac #9816:: sage: E = EllipticCurve([QQbar(1),3]); E Elliptic Curve defined by y^2 = x^3 + x + 3 over Algebraic Field sage: type(E) <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'> sage: E = EllipticCurve([RR(1),3]); E Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 3.00000000000000 over Real Field with 53 bits of precision sage: type(E) <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'> sage: E = EllipticCurve([i,i]); E Elliptic Curve defined by y^2 = x^3 + I*x + I over Symbolic Ring sage: type(E) <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'> sage: E.category() Category of schemes over Symbolic Ring sage: is_field(SR) True sage: F = FractionField(PolynomialRing(QQ,'t')) sage: t = F.gen() sage: E = EllipticCurve([t,0]); E Elliptic Curve defined by y^2 = x^3 + t*x over Fraction Field of Univariate Polynomial Ring in t over Rational Field sage: type(E) <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'> sage: E.category() Category of schemes over Fraction Field of Univariate Polynomial Ring in t over Rational Field See :trac:`12517`:: sage: E = EllipticCurve([1..5]) sage: EllipticCurve(E.a_invariants()) Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field """ import ell_generic, ell_field, ell_finite_field, ell_number_field, ell_rational_field, ell_padic_field # here to avoid circular includes if j is not None: if not x is None: if rings.is_Ring(x): try: j = x(j) except (ZeroDivisionError, ValueError, TypeError): raise ValueError, "First parameter must be a ring containing %s"%j else: raise ValueError, "First parameter (if present) must be a ring when j is specified" return EllipticCurve_from_j(j) assert x is not None if is_SymbolicEquation(x): x = x.lhs() - x.rhs() if parent(x) is SR: x = x._polynomial_(rings.QQ['x', 'y']) if rings.is_MPolynomial(x) and y is None: f = x if f.degree() != 3: raise ValueError, "Elliptic curves must be defined by a cubic polynomial." if f.degrees() == (3,2): x, y = f.parent().gens() elif f.degree() == (2,3): y, x = f.parent().gens() elif len(f.parent().gens()) == 2 or len(f.parent().gens()) == 3 and f.is_homogeneous(): # We'd need a point too... raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented." else: raise ValueError, "Defining polynomial must be a cubic polynomial in two variables." try: if f.coefficient(x**3) < 0: f = -f # is there a nicer way to extract the coefficients? a1 = a2 = a3 = a4 = a6 = 0 for coeff, mon in f: if mon == x**3: assert coeff == 1 elif mon == x**2: a2 = coeff elif mon == x: a4 = coeff elif mon == 1: a6 = coeff elif mon == y**2: assert coeff == -1 elif mon == x*y: a1 = -coeff elif mon == y: a3 = -coeff else: assert False return EllipticCurve([a1, a2, a3, a4, a6]) except AssertionError: raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented." if rings.is_Ring(x): if rings.is_RationalField(x): return ell_rational_field.EllipticCurve_rational_field(x, y) elif rings.is_FiniteField(x) or (rings.is_IntegerModRing(x) and x.characteristic().is_prime()): return ell_finite_field.EllipticCurve_finite_field(x, y) elif rings.is_pAdicField(x): return ell_padic_field.EllipticCurve_padic_field(x, y) elif rings.is_NumberField(x): return ell_number_field.EllipticCurve_number_field(x, y) elif rings.is_Field(x): return ell_field.EllipticCurve_field(x, y) return ell_generic.EllipticCurve_generic(x, y) if isinstance(x, unicode): x = str(x) if isinstance(x, str): return ell_rational_field.EllipticCurve_rational_field(x) if rings.is_RingElement(x) and y is None: from sage.misc.misc import deprecation deprecation("'EllipticCurve(j)' is deprecated; use 'EllipticCurve_from_j(j)' or 'EllipticCurve(j=j)' instead.") # Fixed for all characteristics and cases by John Cremona j=x F=j.parent().fraction_field() char=F.characteristic() if char==2: if j==0: return EllipticCurve(F, [ 0, 0, 1, 0, 0 ]) else: return EllipticCurve(F, [ 1, 0, 0, 0, 1/j ]) if char==3: if j==0: return EllipticCurve(F, [ 0, 0, 0, 1, 0 ]) else: return EllipticCurve(F, [ 0, j, 0, 0, -j**2 ]) if j == 0: return EllipticCurve(F, [ 0, 0, 0, 0, 1 ]) if j == 1728: return EllipticCurve(F, [ 0, 0, 0, 1, 0 ]) k=j-1728 return EllipticCurve(F, [0,0,0,-3*j*k, -2*j*k**2]) if not isinstance(x, (list, tuple)): raise TypeError, "invalid input to EllipticCurve constructor" x = Sequence(x) if not (len(x) in [2,5]): raise ValueError, "sequence of coefficients must have length 2 or 5" R = x.universe() if isinstance(x[0], (rings.Rational, rings.Integer, int, long)): return ell_rational_field.EllipticCurve_rational_field(x, y) elif rings.is_NumberField(R): return ell_number_field.EllipticCurve_number_field(x, y) elif rings.is_pAdicField(R): return ell_padic_field.EllipticCurve_padic_field(x, y) elif rings.is_FiniteField(R) or (rings.is_IntegerModRing(R) and R.characteristic().is_prime()): return ell_finite_field.EllipticCurve_finite_field(x, y) elif rings.is_Field(R): return ell_field.EllipticCurve_field(x, y) return ell_generic.EllipticCurve_generic(x, y)