Path: blob/master/src/sage/schemes/toric/weierstrass_covering.py
8820 views
r"""1Map to the Weierstrass form of a toric elliptic curve.23There are 16 reflexive polygons in 2-d. Each defines a toric Fano4variety, which (since it is 2-d) has a unique crepant resolution to a smooth5toric surface. An anticanonical hypersurface defines a genus one curve6`C` in this ambient space, with Jacobian elliptic curve `J(C)` which7can be defined by the Weierstrass model `y^2 = x^3 + f x + g`. The8coefficients `f` and `g` can be computed with the9:mod:`~sage.schemes.toric.weierstrass` module. The purpose of this10model is to give an explicit rational map `C \to J(C)`. This is an11`n^2`-cover, where `n` is the minimal multi-section of `C`.1213Since it is technically often easier to deal with polynomials than14with fractions, we return the rational map in terms of homogeneous15coordinates. That is, the ambient space for the Weierstrass model is16the weighted projective space `\mathbb{P}^2[2,3,1]` with homogeneous17coordinates `[X:Y:Z] = [\lambda^2 X, \lambda^3 Y, \lambda Z]`. The18homogenized Weierstrass equation is1920.. math::2122Y^2 = X^3 + f X Z^4 + g Z^62324EXAMPLES::2526sage: R.<x,y> = QQ[]27sage: cubic = x^3 + y^3 + 128sage: f, g = WeierstrassForm(cubic); (f,g)29(0, -27/4)3031That is, this hypersurface `C \in \mathbb{P}^2` has a Weierstrass32equation `Y^2 = X^3 + 0 \cdot X Z^4 - \frac{27}{4} Z^6` where33`[X:Y:Z]` are projective coordinates on `\mathbb{P}^2[2,3,1]`. The34form of the map `C\to J(C)` is::3536sage: X,Y,Z = WeierstrassForm(cubic, transformation=True); (X,Y,Z)37(-x^3*y^3 - x^3 - y^3,381/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,39x*y)4041Note that plugging in `[X:Y:Z]` to the Weierstrass equation is a42complicated polynomial, but contains the hypersurface equation as a43factor::4445sage: -Y^2 + X^3 + f*X*Z^4 + g*Z^646-1/4*x^12*y^6 - 1/2*x^9*y^9 - 1/4*x^6*y^12 + 1/2*x^12*y^347- 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^348- 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^349- 7/2*x^3*y^6 - 1/2*y^9 - 1/4*x^6 + 1/2*x^3*y^3 - 1/4*y^650sage: cubic.divides(-Y^2 + X^3 + f*X*Z^4 + g*Z^6)51True5253If you prefer you can also use homogeneous coordinates for `C \in54\mathbb{P}^2` ::5556sage: R.<x,y,z> = QQ[]57sage: cubic = x^3 + y^3 + z^358sage: f, g = WeierstrassForm(cubic); (f,g)59(0, -27/4)60sage: X,Y,Z = WeierstrassForm(cubic, transformation=True)61sage: cubic.divides(-Y^2 + X^3 + f*X*Z^4 + g*Z^6)62True6364The 16 toric surfaces corresponding to the 16 reflexive polygons can65all be blown down to `\mathbb{P}^2`, `\mathbb{P}^1\times\mathbb{P}^1`,66or `\mathbb{P}^{2}[1,1,2]`. Their (and hence in all 16 cases)67anticanonical hypersurface can equally be brought into Weierstrass68form. For example, here is an anticanonical hypersurface in69`\mathbb{P}^{2}[1,1,2]` ::7071sage: P2_112 = toric_varieties.P2_112()72sage: C = P2_112.anticanonical_hypersurface(coefficients=[1]*4); C73Closed subscheme of 2-d CPR-Fano toric variety74covered by 3 affine patches defined by:75z0^4 + z2^4 + z0*z1*z2 + z1^276sage: eq = C.defining_polynomials()[0]77sage: f, g = WeierstrassForm(eq)78sage: X,Y,Z = WeierstrassForm(eq, transformation=True)79sage: (-Y^2 + X^3 + f*X*Z^4 + g*Z^6).reduce(C.defining_ideal())8008182Finally, you sometimes have to manually specify the variables to83use. This is either because the equation is degenerate or because it84contains additional variables that you want to treat as coefficients::8586sage: R.<a, x,y,z> = QQ[]87sage: cubic = x^3 + y^3 + z^3 + a*x*y*z88sage: f, g = WeierstrassForm(cubic, variables=[x,y,z])89sage: X,Y,Z = WeierstrassForm(cubic, variables=[x,y,z], transformation=True)90sage: cubic.divides(-Y^2 + X^3 + f*X*Z^4 + g*Z^6)91True9293REFERENCES:9495.. [AnEtAl]96An, Sang Yook et al:97Jacobians of Genus One Curves,98Journal of Number Theory 90 (2002), pp.304--315,99http://www.math.arizona.edu/~wmc/Research/JacobianFinal.pdf100"""101102########################################################################103# Copyright (C) 2012 Volker Braun <[email protected]>104#105# Distributed under the terms of the GNU General Public License (GPL)106#107# http://www.gnu.org/licenses/108########################################################################109110from sage.rings.all import ZZ111from sage.modules.all import vector112from sage.rings.all import invariant_theory113from sage.schemes.toric.weierstrass import (114_partial_discriminant,115_check_polynomial_P2,116_check_polynomial_P1xP1,117_check_polynomial_P2_112,118)119120121######################################################################122123def WeierstrassMap(polynomial, variables=None):124r"""125Return the Weierstrass form of an anticanonical hypersurface.126127You should use128:meth:`sage.schemes.toric.weierstrass.WeierstrassForm` with129``transformation=True`` to get the transformation. This function130is only for internal use.131132INPUT:133134- ``polynomial`` -- a polynomial. The toric hypersurface135equation. Can be either a cubic, a biquadric, or the136hypersurface in `\mathbb{P}^2[1,1,2]`. The equation need not be137in any standard form, only its Newton polyhedron is used.138139- ``variables`` -- a list of variables of the parent polynomial140ring or ``None`` (default). In the latter case, all variables141are taken to be polynomial ring variables. If a subset of142polynomial ring variables are given, the Weierstrass form is143determined over the function field generated by the remaining144variables.145146OUTPUT:147148A triple `(X,Y,Z)` of polynomials defining a rational map of the149toric hypersurface to its Weierstrass form in150`\mathbb{P}^2[2,3,1]`. That is, the triple satisfies151152.. math::153154Y^2 = X^3 + f X Z^4 + g Z^6155156when restricted to the toric hypersurface.157158EXAMPLES::159160sage: R.<x,y,z> = QQ[]161sage: cubic = x^3 + y^3 + z^3162sage: X,Y,Z = WeierstrassForm(cubic, transformation=True); (X,Y,Z)163(-x^3*y^3 - x^3*z^3 - y^3*z^3,1641/2*x^6*y^3 - 1/2*x^3*y^6 - 1/2*x^6*z^3 + 1/2*y^6*z^3165+ 1/2*x^3*z^6 - 1/2*y^3*z^6,166x*y*z)167sage: f, g = WeierstrassForm(cubic); (f,g)168(0, -27/4)169sage: cubic.divides(-Y^2 + X^3 + f*X*Z^4 + g*Z^6)170True171172Only the affine span of the Newton polytope of the polynomial173matters. For example::174175sage: WeierstrassForm(cubic.subs(z=1), transformation=True)176(-x^3*y^3 - x^3 - y^3,1771/2*x^6*y^3 - 1/2*x^3*y^6 - 1/2*x^6178+ 1/2*y^6 + 1/2*x^3 - 1/2*y^3,179x*y)180sage: WeierstrassForm(x * cubic, transformation=True)181(-x^3*y^3 - x^3*z^3 - y^3*z^3,1821/2*x^6*y^3 - 1/2*x^3*y^6 - 1/2*x^6*z^3 + 1/2*y^6*z^3183+ 1/2*x^3*z^6 - 1/2*y^3*z^6,184x*y*z)185186This allows you to work with either homogeneous or inhomogeneous187variables. For example, here is the del Pezzo surface of degree 8::188189sage: dP8 = toric_varieties.dP8()190sage: dP8.inject_variables()191Defining t, x, y, z192sage: WeierstrassForm(x*y^2 + y^2*z + t^2*x^3 + t^2*z^3, transformation=True)193(-1/27*t^4*x^6 - 2/27*t^4*x^5*z - 5/27*t^4*x^4*z^2194- 8/27*t^4*x^3*z^3 - 5/27*t^4*x^2*z^4 - 2/27*t^4*x*z^5195- 1/27*t^4*z^6 - 4/81*t^2*x^4*y^2 - 4/81*t^2*x^3*y^2*z196- 4/81*t^2*x*y^2*z^3 - 4/81*t^2*y^2*z^4 - 2/81*x^2*y^4197- 4/81*x*y^4*z - 2/81*y^4*z^2,1980,1991/3*t^2*x^2*z + 1/3*t^2*x*z^2 - 1/9*x*y^2 - 1/9*y^2*z)200sage: WeierstrassForm(x*y^2 + y^2 + x^3 + 1, transformation=True)201(-1/27*x^6 - 4/81*x^4*y^2 - 2/81*x^2*y^4 - 2/27*x^5202- 4/81*x^3*y^2 - 4/81*x*y^4 - 5/27*x^4 - 2/81*y^4 - 8/27*x^3203- 4/81*x*y^2 - 5/27*x^2 - 4/81*y^2 - 2/27*x - 1/27,2040,205-1/9*x*y^2 + 1/3*x^2 - 1/9*y^2 + 1/3*x)206207By specifying only certain variables we can compute the208Weierstrass form over the function field generated by the209remaining variables. For example, here is a cubic over `\QQ[a]` ::210211sage: R.<a, x,y,z> = QQ[]212sage: cubic = x^3 + a*y^3 + a^2*z^3213sage: WeierstrassForm(cubic, variables=[x,y,z], transformation=True)214(-a^9*y^3*z^3 - a^8*x^3*z^3 - a^7*x^3*y^3,215-1/2*a^14*y^3*z^6 + 1/2*a^13*y^6*z^3 + 1/2*a^13*x^3*z^6216- 1/2*a^11*x^3*y^6 - 1/2*a^11*x^6*z^3 + 1/2*a^10*x^6*y^3,217a^3*x*y*z)218219TESTS::220221sage: for P in ReflexivePolytopes(2):222....: S = ToricVariety(FaceFan(P))223....: p = sum( (-S.K()).sections_monomials() )224....: f, g = WeierstrassForm(p)225....: X,Y,Z = WeierstrassForm(p, transformation=True)226....: print P, p.divides(-Y^2 + X^3 + f*X*Z^4 + g*Z^6)227Reflexive polytope 0: 2-dimensional, 3 vertices. True228Reflexive polytope 1: 2-dimensional, 3 vertices. True229Reflexive polytope 2: 2-dimensional, 4 vertices. True230Reflexive polytope 3: 2-dimensional, 4 vertices. True231Reflexive polytope 4: 2-dimensional, 4 vertices. True232Reflexive polytope 5: 2-dimensional, 5 vertices. True233Reflexive polytope 6: 2-dimensional, 3 vertices. True234Reflexive polytope 7: 2-dimensional, 4 vertices. True235Reflexive polytope 8: 2-dimensional, 5 vertices. True236Reflexive polytope 9: 2-dimensional, 6 vertices. True237Reflexive polytope 10: 2-dimensional, 4 vertices. True238Reflexive polytope 11: 2-dimensional, 5 vertices. True239Reflexive polytope 12: 2-dimensional, 3 vertices. True240Reflexive polytope 13: 2-dimensional, 4 vertices. True241Reflexive polytope 14: 2-dimensional, 4 vertices. True242Reflexive polytope 15: 2-dimensional, 3 vertices. True243"""244if variables is None:245variables = polynomial.variables()246# switch to suitable inhomogeneous coordinates247from sage.geometry.polyhedron.ppl_lattice_polygon import (248polar_P2_polytope, polar_P1xP1_polytope, polar_P2_112_polytope )249from sage.schemes.toric.weierstrass import Newton_polygon_embedded250newton_polytope, polynomial_aff, variables_aff = \251Newton_polygon_embedded(polynomial, variables)252polygon = newton_polytope.embed_in_reflexive_polytope('polytope')253# Compute the map in inhomogeneous coordinates254if polygon is polar_P2_polytope():255X,Y,Z = WeierstrassMap_P2(polynomial_aff, variables_aff)256elif polygon is polar_P1xP1_polytope():257X,Y,Z = WeierstrassMap_P1xP1(polynomial_aff, variables_aff)258elif polygon is polar_P2_112_polytope():259X,Y,Z = WeierstrassMap_P2_112(polynomial_aff, variables_aff)260else:261assert False, 'Newton polytope is not contained in a reflexive polygon'262# homogenize again263R = polynomial.parent()264x = R.gens().index(variables_aff[0])265y = R.gens().index(variables_aff[1])266hom = newton_polytope.embed_in_reflexive_polytope('hom')267def homogenize(inhomog, degree):268e = tuple(hom._A * vector(ZZ,[inhomog[x], inhomog[y]]) + degree * hom._b)269result = list(inhomog)270for i, var in enumerate(variables):271result[R.gens().index(var)] = e[i]272result = vector(ZZ, result)273result.set_immutable()274return result275X_dict = dict( (homogenize(e,2), v) for e,v in X.dict().iteritems() )276Y_dict = dict( (homogenize(e,3), v) for e,v in Y.dict().iteritems() )277Z_dict = dict( (homogenize(e,1), v) for e,v in Z.dict().iteritems() )278# shift to non-negative exponents if necessary279min_deg = [0]*R.ngens()280for var in variables:281i = R.gens().index(var)282min_X = min([ e[i] for e in X_dict ]) if len(X_dict)>0 else 0283min_Y = min([ e[i] for e in Y_dict ]) if len(Y_dict)>0 else 0284min_Z = min([ e[i] for e in Z_dict ]) if len(Z_dict)>0 else 0285min_deg[i] = min( min_X/2, min_Y/3, min_Z )286min_deg = vector(min_deg)287X_dict = dict( (tuple(e-2*min_deg), v) for e,v in X_dict.iteritems() )288Y_dict = dict( (tuple(e-3*min_deg), v) for e,v in Y_dict.iteritems() )289Z_dict = dict( (tuple(e-1*min_deg), v) for e,v in Z_dict.iteritems() )290return (R(X_dict), R(Y_dict), R(Z_dict))291292293######################################################################294#295# Weierstrass form of cubic in P^2296#297######################################################################298299def WeierstrassMap_P2(polynomial, variables=None):300r"""301Map a cubic to its Weierstrass form302303Input/output is the same as :func:`WeierstrassMap`, except that304the input polynomial must be a cubic in `\mathbb{P}^2`,305306.. math::307308\begin{split}309p(x,y) =&\;310a_{30} x^{3} + a_{21} x^{2} y + a_{12} x y^{2} +311a_{03} y^{3} + a_{20} x^{2} +312\\ &\;313a_{11} x y +314a_{02} y^{2} + a_{10} x + a_{01} y + a_{00}315\end{split}316317EXAMPLES::318319sage: from sage.schemes.toric.weierstrass import WeierstrassForm_P2320sage: from sage.schemes.toric.weierstrass_covering import WeierstrassMap_P2321sage: R.<x,y,z> = QQ[]322sage: equation = x^3+y^3+z^3+x*y*z323sage: f, g = WeierstrassForm_P2(equation)324sage: X,Y,Z = WeierstrassMap_P2(equation)325sage: equation.divides(-Y^2 + X^3 + f*X*Z^4 + g*Z^6)326True327328sage: from sage.schemes.toric.weierstrass import WeierstrassForm_P2329sage: from sage.schemes.toric.weierstrass_covering import WeierstrassMap_P2330sage: R.<x,y> = QQ[]331sage: equation = x^3+y^3+1332sage: f, g = WeierstrassForm_P2(equation)333sage: X,Y,Z = WeierstrassMap_P2(equation)334sage: equation.divides(-Y^2 + X^3 + f*X*Z^4 + g*Z^6)335True336"""337x,y,z = _check_polynomial_P2(polynomial, variables)338cubic = invariant_theory.ternary_cubic(polynomial, x,y,z)339H = cubic.Hessian()340Theta = cubic.Theta_covariant()341J = cubic.J_covariant()342F = polynomial.parent().base_ring()343return (Theta, J/F(2), H)344345346######################################################################347#348# Weierstrass form of biquadric in P1 x P1349#350######################################################################351352def WeierstrassMap_P1xP1(polynomial, variables=None):353r"""354Map an anticanonical hypersurface in355`\mathbb{P}^1 \times \mathbb{P}^1` into Weierstrass form.356357Input/output is the same as :func:`WeierstrassMap`, except that358the input polynomial must be a standard anticanonical hypersurface359in the toric surface `\mathbb{P}^1 \times \mathbb{P}^1`:360361EXAMPLES::362363sage: from sage.schemes.toric.weierstrass_covering import WeierstrassMap_P1xP1364sage: from sage.schemes.toric.weierstrass import WeierstrassForm_P1xP1365sage: R.<x0,x1,y0,y1,a>= QQ[]366sage: biquadric = ( x0^2*y0^2 + x1^2*y0^2 + x0^2*y1^2 + x1^2*y1^2 +367....: a * x0*x1*y0*y1*5 )368sage: f, g = WeierstrassForm_P1xP1(biquadric, [x0, x1, y0, y1]); (f,g)369(-625/48*a^4 + 25/3*a^2 - 16/3, 15625/864*a^6 - 625/36*a^4 - 100/9*a^2 + 128/27)370sage: X, Y, Z = WeierstrassMap_P1xP1(biquadric, [x0, x1, y0, y1])371sage: (-Y^2 + X^3 + f*X*Z^4 + g*Z^6).reduce(R.ideal(biquadric))3720373374sage: R = PolynomialRing(QQ, 'x,y,s,t', order='lex')375sage: R.inject_variables()376Defining x, y, s, t377sage: equation = ( s^2*(x^2+2*x*y+3*y^2) + s*t*(4*x^2+5*x*y+6*y^2)378....: + t^2*(7*x^2+8*x*y+9*y^2) )379sage: X, Y, Z = WeierstrassMap_P1xP1(equation, [x,y,s,t])380sage: f, g = WeierstrassForm_P1xP1(equation, variables=[x,y,s,t])381sage: (-Y^2 + X^3 + f*X*Z^4 + g*Z^6).reduce(R.ideal(equation))3820383384sage: R = PolynomialRing(QQ, 'x,s', order='lex')385sage: R.inject_variables()386Defining x, s387sage: equation = s^2*(x^2+2*x+3) + s*(4*x^2+5*x+6) + (7*x^2+8*x+9)388sage: X, Y, Z = WeierstrassMap_P1xP1(equation)389sage: f, g = WeierstrassForm_P1xP1(equation)390sage: (-Y^2 + X^3 + f*X*Z^4 + g*Z^6).reduce(R.ideal(equation))3910392"""393x,y,s,t = _check_polynomial_P1xP1(polynomial, variables)394a00 = polynomial.coefficient({s:2})395V = polynomial.coefficient({s:1})396U = - _partial_discriminant(polynomial, s, t) / 4397Q = invariant_theory.binary_quartic(U, x, y)398g = Q.g_covariant()399h = Q.h_covariant()400if t is None:401t = 1402return ( 4*g*t**2, 4*h*t**3, (a00*s+V/2) )403404405######################################################################406#407# Weierstrass form of anticanonical hypersurface in WP2[1,1,2]408#409######################################################################410411def WeierstrassMap_P2_112(polynomial, variables=None):412r"""413Map an anticanonical hypersurface in `\mathbb{P}^2[1,1,2]` into Weierstrass form.414415Input/output is the same as :func:`WeierstrassMap`, except that416the input polynomial must be a standard anticanonical hypersurface417in weighted projective space `\mathbb{P}^2[1,1,2]`:418419.. math::420421\begin{split}422p(x,y) =&\;423a_{40} x^4 +424a_{30} x^3 +425a_{21} x^2 y +426a_{20} x^2 +427\\ &\;428a_{11} x y +429a_{02} y^2 +430a_{10} x +431a_{01} y +432a_{00}433\end{split}434435EXAMPLES::436437sage: from sage.schemes.toric.weierstrass_covering import WeierstrassMap_P2_112438sage: from sage.schemes.toric.weierstrass import WeierstrassForm_P2_112439sage: R = PolynomialRing(QQ, 'x,y,a0,a1,a2,a3,a4', order='lex')440sage: R.inject_variables()441Defining x, y, a0, a1, a2, a3, a4442sage: equation = y^2 + a0*x^4 + 4*a1*x^3 + 6*a2*x^2 + 4*a3*x + a4443sage: X, Y, Z = WeierstrassMap_P2_112(equation, [x,y])444sage: f, g = WeierstrassForm_P2_112(equation, variables=[x,y])445sage: (-Y^2 + X^3 + f*X*Z^4 + g*Z^6).reduce(R.ideal(equation))4460447448Another example, this time in homogeneous coordinates::449450sage: fan = Fan(rays=[(1,0),(0,1),(-1,-2),(0,-1)],cones=[[0,1],[1,2],[2,3],[3,0]])451sage: P112.<x,y,z,t> = ToricVariety(fan)452sage: (-P112.K()).sections_monomials()453(z^4*t^2, x*z^3*t^2, x^2*z^2*t^2, x^3*z*t^2,454x^4*t^2, y*z^2*t, x*y*z*t, x^2*y*t, y^2)455sage: C_eqn = sum(_)456sage: C = P112.subscheme(C_eqn)457sage: WeierstrassForm_P2_112(C_eqn, [x,y,z,t])458(-97/48, 17/864)459sage: X, Y, Z = WeierstrassMap_P2_112(C_eqn, [x,y,z,t])460sage: (-Y^2 + X^3 - 97/48*X*Z^4 + 17/864*Z^6).reduce(C.defining_ideal())4610462"""463x,y,z,t = _check_polynomial_P2_112(polynomial, variables)464a00 = polynomial.coefficient({y:2})465V = polynomial.coefficient({y:1})466U = - _partial_discriminant(polynomial, y, t) / 4467Q = invariant_theory.binary_quartic(U, x, z)468g = Q.g_covariant()469h = Q.h_covariant()470if t is None:471t = 1472return ( 4*g*t**2, 4*h*t**3, (a00*y+V/2) )473474475