Weierstrass form of a toric elliptic curve

There are 16 reflexive polygons in the plane, see ReflexivePolytopes(). Each of them defines a toric Fano variety. And each of them has a unique crepant resolution to a smooth toric surface (Section 10.4 in [CLS2011]) by subdividing the face fan. An anticanonical hypersurface defines an elliptic curve in this ambient space, which we call a toric elliptic curve. The purpose of this module is to write an anticanonical hypersurface equation in the short Weierstrass form \(y^2 = x^3 + f x + g\). This works over any base ring as long as its characteristic \(\not= 2,3\).

For an analogous treatment of elliptic curves defined as complete intersection in higher dimensional toric varieties, see the module weierstrass_higher.

Technically, this module computes the Weierstrass form of the Jacobian of the elliptic curve. This is why you will never have to specify the origin (or zero section) in the following.

It turns out [Bra2011] that the anticanonical hypersurface equation of any one of the above 16 toric surfaces is a specialization (that is, set one or more of the coefficients to zero) of the following three cases. In inhomogeneous coordinates, they are

  • Cubic in \(\mathbb{P}^2\):

    \[\begin{split}\begin{split} p(x,y) =&\; a_{30} x^{3} + a_{21} x^{2} y + a_{12} x y^{2} + a_{03} y^{3} + a_{20} x^{2} + \\ &\; a_{11} x y + a_{02} y^{2} + a_{10} x + a_{01} y + a_{00} \end{split}\end{split}\]
  • Biquadric in \(\mathbb{P}^1\times \mathbb{P}^1\):

    \[\begin{split}\begin{split} p(x,y) =&\; a_{22} x^2 y^2 + a_{21} x^2 y + a_{20} x^2 + a_{12} x y^2 + \\ &\; a_{11} x y + x a_{10} + y^2 a_{02} + y a_{01} + a_{00} \end{split}\end{split}\]
  • Anticanonical hypersurface in weighted projective space \(\mathbb{P}^2[1,1,2]\):

    \[\begin{split}\begin{split} p(x,y) =&\; a_{40} x^4 + a_{30} x^3 + a_{21} x^2 y + a_{20} x^2 + \\ &\; a_{11} x y + a_{02} y^2 + a_{10} x + a_{01} y + a_{00} \end{split}\end{split}\]

EXAMPLES:

The main functionality is provided by WeierstrassForm(), which brings each of the above hypersurface equations into Weierstrass form:

sage: R.<x,y> = QQ[]
sage: cubic = x^3 + y^3 + 1
sage: WeierstrassForm(cubic)
(0, -27/4)
sage: WeierstrassForm(x^4 + y^2 + 1)
(-4, 0)
sage: WeierstrassForm(x^2*y^2 + x^2 + y^2 + 1)
(-16/3, 128/27)
>>> from sage.all import *
>>> R = QQ['x, y']; (x, y,) = R._first_ngens(2)
>>> cubic = x**Integer(3) + y**Integer(3) + Integer(1)
>>> WeierstrassForm(cubic)
(0, -27/4)
>>> WeierstrassForm(x**Integer(4) + y**Integer(2) + Integer(1))
(-4, 0)
>>> WeierstrassForm(x**Integer(2)*y**Integer(2) + x**Integer(2) + y**Integer(2) + Integer(1))
(-16/3, 128/27)
R.<x,y> = QQ[]
cubic = x^3 + y^3 + 1
WeierstrassForm(cubic)
WeierstrassForm(x^4 + y^2 + 1)
WeierstrassForm(x^2*y^2 + x^2 + y^2 + 1)

Only the affine span of the Newton polytope of the polynomial matters. For example:

sage: R.<x,y,z> = QQ[]
sage: WeierstrassForm(x^3 + y^3 + z^3)
(0, -27/4)
sage: WeierstrassForm(x * cubic)
(0, -27/4)
>>> from sage.all import *
>>> R = QQ['x, y, z']; (x, y, z,) = R._first_ngens(3)
>>> WeierstrassForm(x**Integer(3) + y**Integer(3) + z**Integer(3))
(0, -27/4)
>>> WeierstrassForm(x * cubic)
(0, -27/4)
R.<x,y,z> = QQ[]
WeierstrassForm(x^3 + y^3 + z^3)
WeierstrassForm(x * cubic)

This allows you to work with either homogeneous or inhomogeneous variables. For example, here is the del Pezzo surface of degree 8:

sage: dP8 = toric_varieties.dP8()
sage: dP8.inject_variables()
Defining t, x, y, z
sage: WeierstrassForm(x*y^2 + y^2*z + t^2*x^3 + t^2*z^3)
(-3, -2)
sage: WeierstrassForm(x*y^2 + y^2 + x^3 + 1)
(-3, -2)
>>> from sage.all import *
>>> dP8 = toric_varieties.dP8()
>>> dP8.inject_variables()
Defining t, x, y, z
>>> WeierstrassForm(x*y**Integer(2) + y**Integer(2)*z + t**Integer(2)*x**Integer(3) + t**Integer(2)*z**Integer(3))
(-3, -2)
>>> WeierstrassForm(x*y**Integer(2) + y**Integer(2) + x**Integer(3) + Integer(1))
(-3, -2)
dP8 = toric_varieties.dP8()
dP8.inject_variables()
WeierstrassForm(x*y^2 + y^2*z + t^2*x^3 + t^2*z^3)
WeierstrassForm(x*y^2 + y^2 + x^3 + 1)

By specifying only certain variables we can compute the Weierstrass form over the polynomial ring generated by the remaining variables. For example, here is a cubic over \(\QQ[a]\)

sage: R.<a, x, y, z> = QQ[]
sage: cubic = x^3 + a*y^3 + a^2*z^3
sage: WeierstrassForm(cubic, variables=[x,y,z])
(0, -27/4*a^6)
>>> from sage.all import *
>>> R = QQ['a, x, y, z']; (a, x, y, z,) = R._first_ngens(4)
>>> cubic = x**Integer(3) + a*y**Integer(3) + a**Integer(2)*z**Integer(3)
>>> WeierstrassForm(cubic, variables=[x,y,z])
(0, -27/4*a^6)
R.<a, x, y, z> = QQ[]
cubic = x^3 + a*y^3 + a^2*z^3
WeierstrassForm(cubic, variables=[x,y,z])

REFERENCES:

sage.schemes.toric.weierstrass.Discriminant(polynomial, variables=None)[source]

The discriminant of the elliptic curve.

INPUT:

See WeierstrassForm() for how to specify the input polynomial(s) and variables.

OUTPUT: the discriminant of the elliptic curve

EXAMPLES:

sage: from sage.schemes.toric.weierstrass import Discriminant
sage: R.<x, y, z> = QQ[]
sage: Discriminant(x^3 + y^3 + z^3)
19683/16
sage: Discriminant(x*y*z)
0
sage: R.<w,x,y,z> = QQ[]
sage: quadratic1 = w^2 + x^2 + y^2
sage: quadratic2 = z^2 + w*x
sage: Discriminant([quadratic1, quadratic2])
-1/16
>>> from sage.all import *
>>> from sage.schemes.toric.weierstrass import Discriminant
>>> R = QQ['x, y, z']; (x, y, z,) = R._first_ngens(3)
>>> Discriminant(x**Integer(3) + y**Integer(3) + z**Integer(3))
19683/16
>>> Discriminant(x*y*z)
0
>>> R = QQ['w, x, y, z']; (w, x, y, z,) = R._first_ngens(4)
>>> quadratic1 = w**Integer(2) + x**Integer(2) + y**Integer(2)
>>> quadratic2 = z**Integer(2) + w*x
>>> Discriminant([quadratic1, quadratic2])
-1/16
from sage.schemes.toric.weierstrass import Discriminant
R.<x, y, z> = QQ[]
Discriminant(x^3 + y^3 + z^3)
Discriminant(x*y*z)
R.<w,x,y,z> = QQ[]
quadratic1 = w^2 + x^2 + y^2
quadratic2 = z^2 + w*x
Discriminant([quadratic1, quadratic2])
sage.schemes.toric.weierstrass.Newton_polygon_embedded(polynomial, variables)[source]

Embed the Newton polytope of the polynomial in one of the three maximal reflexive polygons.

This function is a helper for WeierstrassForm()

INPUT:

Same as WeierstrassForm() with only a single polynomial passed.

OUTPUT:

A tuple \((\Delta, P, (x,y))\) where

  • \(\Delta\) is the Newton polytope of polynomial.

  • \(P(x,y)\) equals the input polynomial but with redefined variables such that its Newton polytope is \(\Delta\).

EXAMPLES:

sage: from sage.schemes.toric.weierstrass import Newton_polygon_embedded
sage: R.<x,y,z> = QQ[]
sage: cubic = x^3 + y^3 + z^3
sage: Newton_polygon_embedded(cubic, [x,y,z])
(A 2-dimensional lattice polytope in ZZ^3 with 3 vertices,
 x^3 + y^3 + 1,
 (x, y))

sage: R.<a, x,y,z> = QQ[]
sage: cubic = x^3 + a*y^3 + a^2*z^3
sage: Newton_polygon_embedded(cubic, variables=[x,y,z])
(A 2-dimensional lattice polytope in ZZ^3 with 3 vertices,
 a^2*x^3 + y^3 + a,
 (x, y))

sage: R.<s,t,x,y> = QQ[]
sage: biquadric = (s+t)^2 * (x+y)^2
sage: Newton_polygon_embedded(biquadric, [s,t,x,y])
(A 2-dimensional lattice polytope in ZZ^4 with 4 vertices,
 s^2*t^2 + 2*s^2*t + 2*s*t^2 + s^2 + 4*s*t + t^2 + 2*s + 2*t + 1,
 (s, t))
>>> from sage.all import *
>>> from sage.schemes.toric.weierstrass import Newton_polygon_embedded
>>> R = QQ['x, y, z']; (x, y, z,) = R._first_ngens(3)
>>> cubic = x**Integer(3) + y**Integer(3) + z**Integer(3)
>>> Newton_polygon_embedded(cubic, [x,y,z])
(A 2-dimensional lattice polytope in ZZ^3 with 3 vertices,
 x^3 + y^3 + 1,
 (x, y))

>>> R = QQ['a, x, y, z']; (a, x, y, z,) = R._first_ngens(4)
>>> cubic = x**Integer(3) + a*y**Integer(3) + a**Integer(2)*z**Integer(3)
>>> Newton_polygon_embedded(cubic, variables=[x,y,z])
(A 2-dimensional lattice polytope in ZZ^3 with 3 vertices,
 a^2*x^3 + y^3 + a,
 (x, y))

>>> R = QQ['s, t, x, y']; (s, t, x, y,) = R._first_ngens(4)
>>> biquadric = (s+t)**Integer(2) * (x+y)**Integer(2)
>>> Newton_polygon_embedded(biquadric, [s,t,x,y])
(A 2-dimensional lattice polytope in ZZ^4 with 4 vertices,
 s^2*t^2 + 2*s^2*t + 2*s*t^2 + s^2 + 4*s*t + t^2 + 2*s + 2*t + 1,
 (s, t))
from sage.schemes.toric.weierstrass import Newton_polygon_embedded
R.<x,y,z> = QQ[]
cubic = x^3 + y^3 + z^3
Newton_polygon_embedded(cubic, [x,y,z])
R.<a, x,y,z> = QQ[]
cubic = x^3 + a*y^3 + a^2*z^3
Newton_polygon_embedded(cubic, variables=[x,y,z])
R.<s,t,x,y> = QQ[]
biquadric = (s+t)^2 * (x+y)^2
Newton_polygon_embedded(biquadric, [s,t,x,y])
sage.schemes.toric.weierstrass.Newton_polytope_vars_coeffs(polynomial, variables)[source]

Return the Newton polytope in the given variables.

INPUT:

See WeierstrassForm() for how to specify the input polynomial and variables.

OUTPUT:

A dictionary with keys the integral values of the Newton polytope and values the corresponding coefficient of polynomial.

EXAMPLES:

sage: from sage.schemes.toric.weierstrass import Newton_polytope_vars_coeffs
sage: R.<x,y,z,a30,a21,a12,a03,a20,a11,a02,a10,a01,a00> = QQ[]
sage: p = (a30*x^3 + a21*x^2*y + a12*x*y^2 + a03*y^3 + a20*x^2*z +
....:      a11*x*y*z + a02*y^2*z + a10*x*z^2 + a01*y*z^2 + a00*z^3)
sage: p_data = Newton_polytope_vars_coeffs(p, [x,y,z]);  p_data
{(0, 0, 3): a00,
 (0, 1, 2): a01,
 (0, 2, 1): a02,
 (0, 3, 0): a03,
 (1, 0, 2): a10,
 (1, 1, 1): a11,
 (1, 2, 0): a12,
 (2, 0, 1): a20,
 (2, 1, 0): a21,
 (3, 0, 0): a30}

sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
sage: polytope = LatticePolytope_PPL(list(p_data));  polytope
A 2-dimensional lattice polytope in ZZ^3 with 3 vertices
sage: polytope.vertices()
((0, 0, 3), (3, 0, 0), (0, 3, 0))
sage: polytope.embed_in_reflexive_polytope()
The map A*x+b with A=
[-1 -1]
[ 0  1]
[ 1  0]
b =
(3, 0, 0)
>>> from sage.all import *
>>> from sage.schemes.toric.weierstrass import Newton_polytope_vars_coeffs
>>> R = QQ['x, y, z, a30, a21, a12, a03, a20, a11, a02, a10, a01, a00']; (x, y, z, a30, a21, a12, a03, a20, a11, a02, a10, a01, a00,) = R._first_ngens(13)
>>> p = (a30*x**Integer(3) + a21*x**Integer(2)*y + a12*x*y**Integer(2) + a03*y**Integer(3) + a20*x**Integer(2)*z +
...      a11*x*y*z + a02*y**Integer(2)*z + a10*x*z**Integer(2) + a01*y*z**Integer(2) + a00*z**Integer(3))
>>> p_data = Newton_polytope_vars_coeffs(p, [x,y,z]);  p_data
{(0, 0, 3): a00,
 (0, 1, 2): a01,
 (0, 2, 1): a02,
 (0, 3, 0): a03,
 (1, 0, 2): a10,
 (1, 1, 1): a11,
 (1, 2, 0): a12,
 (2, 0, 1): a20,
 (2, 1, 0): a21,
 (3, 0, 0): a30}

>>> from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
>>> polytope = LatticePolytope_PPL(list(p_data));  polytope
A 2-dimensional lattice polytope in ZZ^3 with 3 vertices
>>> polytope.vertices()
((0, 0, 3), (3, 0, 0), (0, 3, 0))
>>> polytope.embed_in_reflexive_polytope()
The map A*x+b with A=
[-1 -1]
[ 0  1]
[ 1  0]
b =
(3, 0, 0)
from sage.schemes.toric.weierstrass import Newton_polytope_vars_coeffs
R.<x,y,z,a30,a21,a12,a03,a20,a11,a02,a10,a01,a00> = QQ[]
p = (a30*x^3 + a21*x^2*y + a12*x*y^2 + a03*y^3 + a20*x^2*z +
     a11*x*y*z + a02*y^2*z + a10*x*z^2 + a01*y*z^2 + a00*z^3)
p_data = Newton_polytope_vars_coeffs(p, [x,y,z]);  p_data
from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
polytope = LatticePolytope_PPL(list(p_data));  polytope
polytope.vertices()
polytope.embed_in_reflexive_polytope()
sage.schemes.toric.weierstrass.WeierstrassForm(polynomial, variables=None, transformation=False)[source]

Return the Weierstrass form of an elliptic curve inside either inside a toric surface or \(\mathbb{P}^3\).

INPUT:

  • polynomial – either a polynomial or a list of polynomials defining the elliptic curve. A single polynomial can be either a cubic, a biquadric, or the hypersurface in \(\mathbb{P}^2[1,1,2]\). In this case the equation need not be in any standard form, only its Newton polyhedron is used. If two polynomials are passed, they must both be quadratics in \(\mathbb{P}^3\).

  • variables – list of variables of the parent polynomial ring or None (default). In the latter case, all variables are taken to be polynomial ring variables. If a subset of polynomial ring variables are given, the Weierstrass form is determined over the function field generated by the remaining variables.

  • transformation – boolean (default: False); whether to return the new variables that bring polynomial into Weierstrass form

OUTPUT:

The pair of coefficients \((f,g)\) of the Weierstrass form \(y^2 = x^3 + f x + g\) of the hypersurface equation.

If transformation=True, a triple \((X,Y,Z)\) of polynomials defining a rational map of the toric hypersurface or complete intersection in \(\mathbb{P}^3\) to its Weierstrass form in \(\mathbb{P}^2[2,3,1]\) is returned. That is, the triple satisfies

\[Y^2 = X^3 + f X Z^4 + g Z^6\]

when restricted to the toric hypersurface or complete intersection.

EXAMPLES:

sage: R.<x,y,z> = QQ[]
sage: cubic = x^3 + y^3 + z^3
sage: f, g = WeierstrassForm(cubic);  (f, g)
(0, -27/4)
>>> from sage.all import *
>>> R = QQ['x, y, z']; (x, y, z,) = R._first_ngens(3)
>>> cubic = x**Integer(3) + y**Integer(3) + z**Integer(3)
>>> f, g = WeierstrassForm(cubic);  (f, g)
(0, -27/4)
R.<x,y,z> = QQ[]
cubic = x^3 + y^3 + z^3
f, g = WeierstrassForm(cubic);  (f, g)

Same in inhomogeneous coordinates:

sage: R.<x,y> = QQ[]
sage: cubic = x^3 + y^3 + 1
sage: f, g = WeierstrassForm(cubic);  (f, g)
(0, -27/4)

sage: X,Y,Z = WeierstrassForm(cubic, transformation=True);  (X,Y,Z)
(-x^3*y^3 - x^3 - y^3,
 1/2*x^6*y^3 - 1/2*x^3*y^6 - 1/2*x^6 + 1/2*y^6 + 1/2*x^3 - 1/2*y^3,
 x*y)
>>> from sage.all import *
>>> R = QQ['x, y']; (x, y,) = R._first_ngens(2)
>>> cubic = x**Integer(3) + y**Integer(3) + Integer(1)
>>> f, g = WeierstrassForm(cubic);  (f, g)
(0, -27/4)

>>> X,Y,Z = WeierstrassForm(cubic, transformation=True);  (X,Y,Z)
(-x^3*y^3 - x^3 - y^3,
 1/2*x^6*y^3 - 1/2*x^3*y^6 - 1/2*x^6 + 1/2*y^6 + 1/2*x^3 - 1/2*y^3,
 x*y)
R.<x,y> = QQ[]
cubic = x^3 + y^3 + 1
f, g = WeierstrassForm(cubic);  (f, g)
X,Y,Z = WeierstrassForm(cubic, transformation=True);  (X,Y,Z)

Note that plugging in \([X:Y:Z]\) to the Weierstrass equation is a complicated polynomial, but contains the hypersurface equation as a factor:

sage: -Y^2 + X^3 + f*X*Z^4 + g*Z^6
-1/4*x^12*y^6 - 1/2*x^9*y^9 - 1/4*x^6*y^12 + 1/2*x^12*y^3
- 7/2*x^9*y^6 - 7/2*x^6*y^9 + 1/2*x^3*y^12 - 1/4*x^12 - 7/2*x^9*y^3
- 45/4*x^6*y^6 - 7/2*x^3*y^9 - 1/4*y^12 - 1/2*x^9 - 7/2*x^6*y^3
- 7/2*x^3*y^6 - 1/2*y^9 - 1/4*x^6 + 1/2*x^3*y^3 - 1/4*y^6
sage: cubic.divides(-Y^2 + X^3 + f*X*Z^4 + g*Z^6)
True
>>> from sage.all import *
>>> -Y**Integer(2) + X**Integer(3) + f*X*Z**Integer(4) + g*Z**Integer(6)
-1/4*x^12*y^6 - 1/2*x^9*y^9 - 1/4*x^6*y^12 + 1/2*x^12*y^3
- 7/2*x^9*y^6 - 7/2*x^6*y^9 + 1/2*x^3*y^12 - 1/4*x^12 - 7/2*x^9*y^3
- 45/4*x^6*y^6 - 7/2*x^3*y^9 - 1/4*y^12 - 1/2*x^9 - 7/2*x^6*y^3
- 7/2*x^3*y^6 - 1/2*y^9 - 1/4*x^6 + 1/2*x^3*y^3 - 1/4*y^6
>>> cubic.divides(-Y**Integer(2) + X**Integer(3) + f*X*Z**Integer(4) + g*Z**Integer(6))
True
-Y^2 + X^3 + f*X*Z^4 + g*Z^6
cubic.divides(-Y^2 + X^3 + f*X*Z^4 + g*Z^6)

Only the affine span of the Newton polytope of the polynomial matters. For example:

sage: R.<x,y,z> = QQ[]
sage: cubic = x^3 + y^3 + z^3
sage: WeierstrassForm(cubic.subs(z=1))
(0, -27/4)
sage: WeierstrassForm(x * cubic)
(0, -27/4)
>>> from sage.all import *
>>> R = QQ['x, y, z']; (x, y, z,) = R._first_ngens(3)
>>> cubic = x**Integer(3) + y**Integer(3) + z**Integer(3)
>>> WeierstrassForm(cubic.subs(z=Integer(1)))
(0, -27/4)
>>> WeierstrassForm(x * cubic)
(0, -27/4)
R.<x,y,z> = QQ[]
cubic = x^3 + y^3 + z^3
WeierstrassForm(cubic.subs(z=1))
WeierstrassForm(x * cubic)

This allows you to work with either homogeneous or inhomogeneous variables. For example, here is the del Pezzo surface of degree 8:

sage: dP8 = toric_varieties.dP8()
sage: dP8.inject_variables()
Defining t, x, y, z
sage: WeierstrassForm(x*y^2 + y^2*z + t^2*x^3 + t^2*z^3)
(-3, -2)
sage: WeierstrassForm(x*y^2 + y^2 + x^3 + 1)
(-3, -2)
>>> from sage.all import *
>>> dP8 = toric_varieties.dP8()
>>> dP8.inject_variables()
Defining t, x, y, z
>>> WeierstrassForm(x*y**Integer(2) + y**Integer(2)*z + t**Integer(2)*x**Integer(3) + t**Integer(2)*z**Integer(3))
(-3, -2)
>>> WeierstrassForm(x*y**Integer(2) + y**Integer(2) + x**Integer(3) + Integer(1))
(-3, -2)
dP8 = toric_varieties.dP8()
dP8.inject_variables()
WeierstrassForm(x*y^2 + y^2*z + t^2*x^3 + t^2*z^3)
WeierstrassForm(x*y^2 + y^2 + x^3 + 1)

By specifying only certain variables we can compute the Weierstrass form over the function field generated by the remaining variables. For example, here is a cubic over \(\QQ[a]\)

sage: R.<a, x,y,z> = QQ[]
sage: cubic = x^3 + a*y^3 + a^2*z^3
sage: WeierstrassForm(cubic, variables=[x,y,z])
(0, -27/4*a^6)
>>> from sage.all import *
>>> R = QQ['a, x, y, z']; (a, x, y, z,) = R._first_ngens(4)
>>> cubic = x**Integer(3) + a*y**Integer(3) + a**Integer(2)*z**Integer(3)
>>> WeierstrassForm(cubic, variables=[x,y,z])
(0, -27/4*a^6)
R.<a, x,y,z> = QQ[]
cubic = x^3 + a*y^3 + a^2*z^3
WeierstrassForm(cubic, variables=[x,y,z])
sage.schemes.toric.weierstrass.WeierstrassForm_P1xP1(biquadric, variables=None)[source]

Bring a biquadric into Weierstrass form.

Input/output is the same as WeierstrassForm(), except that the input polynomial must be a standard biquadric in \(\mathbb{P}^2\),

\[\begin{split}\begin{split} p(x,y) =&\; a_{40} x^4 + a_{30} x^3 + a_{21} x^2 y + a_{20} x^2 + \\ &\; a_{11} x y + a_{02} y^2 + a_{10} x + a_{01} y + a_{00} \end{split}\end{split}\]

EXAMPLES:

sage: from sage.schemes.toric.weierstrass import WeierstrassForm_P1xP1
sage: R.<x0,x1,y0,y1> = QQ[]
sage: biquadric = (x0^2*y0^2 + x0*x1*y0^2*2 + x1^2*y0^2*3
....:     + x0^2*y0*y1*4 + x0*x1*y0*y1*5 + x1^2*y0*y1*6
....:     + x0^2*y1^2*7 + x0*x1*y1^2*8)
sage: WeierstrassForm_P1xP1(biquadric, [x0, x1, y0, y1])
(1581/16, -3529/32)
>>> from sage.all import *
>>> from sage.schemes.toric.weierstrass import WeierstrassForm_P1xP1
>>> R = QQ['x0, x1, y0, y1']; (x0, x1, y0, y1,) = R._first_ngens(4)
>>> biquadric = (x0**Integer(2)*y0**Integer(2) + x0*x1*y0**Integer(2)*Integer(2) + x1**Integer(2)*y0**Integer(2)*Integer(3)
...     + x0**Integer(2)*y0*y1*Integer(4) + x0*x1*y0*y1*Integer(5) + x1**Integer(2)*y0*y1*Integer(6)
...     + x0**Integer(2)*y1**Integer(2)*Integer(7) + x0*x1*y1**Integer(2)*Integer(8))
>>> WeierstrassForm_P1xP1(biquadric, [x0, x1, y0, y1])
(1581/16, -3529/32)
from sage.schemes.toric.weierstrass import WeierstrassForm_P1xP1
R.<x0,x1,y0,y1> = QQ[]
biquadric = (x0^2*y0^2 + x0*x1*y0^2*2 + x1^2*y0^2*3
    + x0^2*y0*y1*4 + x0*x1*y0*y1*5 + x1^2*y0*y1*6
    + x0^2*y1^2*7 + x0*x1*y1^2*8)
WeierstrassForm_P1xP1(biquadric, [x0, x1, y0, y1])

Since there is no \(x_1^2 y_1^2\) term in biquadric, we can dehomogenize it and get a cubic:

sage: from sage.schemes.toric.weierstrass import WeierstrassForm_P2
sage: WeierstrassForm_P2(biquadric(x0=1,y0=1))
(1581/16, -3529/32)
>>> from sage.all import *
>>> from sage.schemes.toric.weierstrass import WeierstrassForm_P2
>>> WeierstrassForm_P2(biquadric(x0=Integer(1),y0=Integer(1)))
(1581/16, -3529/32)
from sage.schemes.toric.weierstrass import WeierstrassForm_P2
WeierstrassForm_P2(biquadric(x0=1,y0=1))
sage.schemes.toric.weierstrass.WeierstrassForm_P2(polynomial, variables=None)[source]

Bring a cubic into Weierstrass form.

Input/output is the same as WeierstrassForm(), except that the input polynomial must be a standard cubic in \(\mathbb{P}^2\),

\[\begin{split}\begin{split} p(x,y) =&\; a_{30} x^{3} + a_{21} x^{2} y + a_{12} x y^{2} + a_{03} y^{3} + a_{20} x^{2} + \\ &\; a_{11} x y + a_{02} y^{2} + a_{10} x + a_{01} y + a_{00} \end{split}\end{split}\]

EXAMPLES:

sage: from sage.schemes.toric.weierstrass import WeierstrassForm_P2
sage: R.<x,y,z> = QQ[]
sage: WeierstrassForm_P2(x^3 + y^3 + z^3)
(0, -27/4)

sage: R.<x,y,z, a,b> = QQ[]
sage: WeierstrassForm_P2(-y^2*z + x^3 + a*x*z^2 + b*z^3, [x,y,z])
(a, b)
>>> from sage.all import *
>>> from sage.schemes.toric.weierstrass import WeierstrassForm_P2
>>> R = QQ['x, y, z']; (x, y, z,) = R._first_ngens(3)
>>> WeierstrassForm_P2(x**Integer(3) + y**Integer(3) + z**Integer(3))
(0, -27/4)

>>> R = QQ['x, y, z, a, b']; (x, y, z, a, b,) = R._first_ngens(5)
>>> WeierstrassForm_P2(-y**Integer(2)*z + x**Integer(3) + a*x*z**Integer(2) + b*z**Integer(3), [x,y,z])
(a, b)
from sage.schemes.toric.weierstrass import WeierstrassForm_P2
R.<x,y,z> = QQ[]
WeierstrassForm_P2(x^3 + y^3 + z^3)
R.<x,y,z, a,b> = QQ[]
WeierstrassForm_P2(-y^2*z + x^3 + a*x*z^2 + b*z^3, [x,y,z])
sage.schemes.toric.weierstrass.WeierstrassForm_P2_112(polynomial, variables=None)[source]

Bring an anticanonical hypersurface in \(\mathbb{P}^2[1,1,2]\) into Weierstrass form.

Input/output is the same as WeierstrassForm(), except that the input polynomial must be a standard anticanonical hypersurface in weighted projective space \(\mathbb{P}^2[1,1,2]\):

\[\begin{split}\begin{split} p(x,y) =&\; a_{40} x^4 + a_{30} x^3 + a_{21} x^2 y + a_{20} x^2 + \\ &\; a_{11} x y + a_{02} y^2 + a_{10} x + a_{01} y + a_{00} \end{split}\end{split}\]

EXAMPLES:

sage: from sage.schemes.toric.weierstrass import WeierstrassForm_P2_112
sage: fan = Fan(rays=[(1,0),(0,1),(-1,-2),(0,-1)],
....:           cones=[[0,1],[1,2],[2,3],[3,0]])
sage: P112.<x,y,z,t> = ToricVariety(fan)
sage: (-P112.K()).sections_monomials()
(z^4*t^2, x*z^3*t^2, x^2*z^2*t^2, x^3*z*t^2,
 x^4*t^2, y*z^2*t, x*y*z*t, x^2*y*t, y^2)
sage: WeierstrassForm_P2_112(sum(_), [x,y,z,t])
(-97/48, 17/864)
>>> from sage.all import *
>>> from sage.schemes.toric.weierstrass import WeierstrassForm_P2_112
>>> fan = Fan(rays=[(Integer(1),Integer(0)),(Integer(0),Integer(1)),(-Integer(1),-Integer(2)),(Integer(0),-Integer(1))],
...           cones=[[Integer(0),Integer(1)],[Integer(1),Integer(2)],[Integer(2),Integer(3)],[Integer(3),Integer(0)]])
>>> P112 = ToricVariety(fan, names=('x', 'y', 'z', 't',)); (x, y, z, t,) = P112._first_ngens(4)
>>> (-P112.K()).sections_monomials()
(z^4*t^2, x*z^3*t^2, x^2*z^2*t^2, x^3*z*t^2,
 x^4*t^2, y*z^2*t, x*y*z*t, x^2*y*t, y^2)
>>> WeierstrassForm_P2_112(sum(_), [x,y,z,t])
(-97/48, 17/864)
from sage.schemes.toric.weierstrass import WeierstrassForm_P2_112
fan = Fan(rays=[(1,0),(0,1),(-1,-2),(0,-1)],
          cones=[[0,1],[1,2],[2,3],[3,0]])
P112.<x,y,z,t> = ToricVariety(fan)
(-P112.K()).sections_monomials()
WeierstrassForm_P2_112(sum(_), [x,y,z,t])
sage.schemes.toric.weierstrass.j_invariant(polynomial, variables=None)[source]

Return the \(j\)-invariant of the elliptic curve.

INPUT:

See WeierstrassForm() for how to specify the input polynomial(s) and variables.

OUTPUT:

The j-invariant of the (irreducible) cubic. Notable special values:

  • The Fermat cubic: \(j(x^3+y^3+z^3) = 0\)

  • A nodal cubic: \(j(-y^2 + x^2 + x^3) = \infty\)

  • A cuspidal cubic \(y^2=x^3\) has undefined \(j\)-invariant. In this case, a ValueError is raised.

EXAMPLES:

sage: from sage.schemes.toric.weierstrass import j_invariant
sage: R.<x,y,z> = QQ[]
sage: j_invariant(x^3 + y^3 + z^3)
0
sage: j_invariant(-y^2 + x^2 + x^3)
+Infinity
sage: R.<x,y,z, a,b> = QQ[]
sage: j_invariant( -y^2*z + x^3 + a*x*z^2, [x,y,z])
1728
>>> from sage.all import *
>>> from sage.schemes.toric.weierstrass import j_invariant
>>> R = QQ['x, y, z']; (x, y, z,) = R._first_ngens(3)
>>> j_invariant(x**Integer(3) + y**Integer(3) + z**Integer(3))
0
>>> j_invariant(-y**Integer(2) + x**Integer(2) + x**Integer(3))
+Infinity
>>> R = QQ['x, y, z, a, b']; (x, y, z, a, b,) = R._first_ngens(5)
>>> j_invariant( -y**Integer(2)*z + x**Integer(3) + a*x*z**Integer(2), [x,y,z])
1728
from sage.schemes.toric.weierstrass import j_invariant
R.<x,y,z> = QQ[]
j_invariant(x^3 + y^3 + z^3)
j_invariant(-y^2 + x^2 + x^3)
R.<x,y,z, a,b> = QQ[]
j_invariant( -y^2*z + x^3 + a*x*z^2, [x,y,z])