def WeierstrassForm(polynomial, variables=None, transformation=False): r""" 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`` -- a 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 .. MATH:: 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) 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) 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 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) 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) 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) TESTS:: sage: for P in ReflexivePolytopes(2): ....: S = ToricVariety(FaceFan(P)) ....: p = sum((-S.K()).sections_monomials()) ....: print(WeierstrassForm(p)) (-25/48, -1475/864) (-97/48, 17/864) (-25/48, -611/864) (-27/16, 27/32) (47/48, -199/864) (47/48, -71/864) (5/16, -21/32) (23/48, -235/864) (-1/48, 161/864) (-25/48, 253/864) (5/16, 11/32) (-25/48, 125/864) (-67/16, 63/32) (-11/16, 3/32) (-241/48, 3689/864) (215/48, -5291/864) """ if isinstance(polynomial, (list, tuple)): from sage.schemes.toric.weierstrass_higher import WeierstrassForm2 return WeierstrassForm2(polynomial, variables=variables, transformation=transformation) if transformation: from sage.schemes.toric.weierstrass_covering import WeierstrassMap return WeierstrassMap(polynomial, variables=variables) if variables is None: variables = polynomial.variables() from sage.geometry.polyhedron.ppl_lattice_polygon import ( polar_P2_polytope, polar_P1xP1_polytope, polar_P2_112_polytope) newton_polytope, polynomial, variables = \ Newton_polygon_embedded(polynomial, variables) polygon = newton_polytope.embed_in_reflexive_polytope('polytope') if polygon is polar_P2_polytope(): return WeierstrassForm_P2(polynomial, variables) if polygon is polar_P1xP1_polytope(): return WeierstrassForm_P1xP1(polynomial, variables) if polygon is polar_P2_112_polytope(): return WeierstrassForm_P2_112(polynomial, variables) raise ValueError('Newton polytope is not contained in a reflexive polygon')
def WeierstrassForm(polynomial, variables=None, transformation=False): r""" 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`` -- a 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 .. math:: 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) 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) 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 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) 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) 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) TESTS:: sage: for P in ReflexivePolytopes(2): ....: S = ToricVariety(FaceFan(P)) ....: p = sum((-S.K()).sections_monomials()) ....: print WeierstrassForm(p) (-25/48, -1475/864) (-97/48, 17/864) (-25/48, -611/864) (-27/16, 27/32) (47/48, -199/864) (47/48, -71/864) (5/16, -21/32) (23/48, -235/864) (-1/48, 161/864) (-25/48, 253/864) (5/16, 11/32) (-25/48, 125/864) (-67/16, 63/32) (-11/16, 3/32) (-241/48, 3689/864) (215/48, -5291/864) """ if isinstance(polynomial, (list, tuple)): from sage.schemes.toric.weierstrass_higher import WeierstrassForm2 return WeierstrassForm2(polynomial, variables=variables, transformation=transformation) if transformation: from sage.schemes.toric.weierstrass_covering import WeierstrassMap return WeierstrassMap(polynomial, variables=variables) if variables is None: variables = polynomial.variables() from sage.geometry.polyhedron.ppl_lattice_polygon import ( polar_P2_polytope, polar_P1xP1_polytope, polar_P2_112_polytope) newton_polytope, polynomial, variables = \ Newton_polygon_embedded(polynomial, variables) polygon = newton_polytope.embed_in_reflexive_polytope('polytope') if polygon is polar_P2_polytope(): return WeierstrassForm_P2(polynomial, variables) if polygon is polar_P1xP1_polytope(): return WeierstrassForm_P1xP1(polynomial, variables) if polygon is polar_P2_112_polytope(): return WeierstrassForm_P2_112(polynomial, variables) raise ValueError('Newton polytope is not contained in a reflexive polygon')
def WeierstrassMap(polynomial, variables=None): r""" Return the Weierstrass form of an anticanonical hypersurface. You should use :meth:`sage.schemes.toric.weierstrass.WeierstrassForm` with ``transformation=True`` to get the transformation. This function is only for internal use. INPUT: - ``polynomial`` -- a polynomial. The toric hypersurface equation. Can be either a cubic, a biquadric, or the hypersurface in `\mathbb{P}^2[1,1,2]`. The equation need not be in any standard form, only its Newton polyhedron is used. - ``variables`` -- a 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. OUTPUT: A triple `(X,Y,Z)` of polynomials defining a rational map of the toric hypersurface to its Weierstrass form in `\mathbb{P}^2[2,3,1]`. That is, the triple satisfies .. MATH:: Y^2 = X^3 + f X Z^4 + g Z^6 when restricted to the toric hypersurface. EXAMPLES:: sage: R.<x,y,z> = QQ[] sage: cubic = x^3 + y^3 + z^3 sage: X,Y,Z = WeierstrassForm(cubic, transformation=True); (X,Y,Z) (-x^3*y^3 - x^3*z^3 - y^3*z^3, 1/2*x^6*y^3 - 1/2*x^3*y^6 - 1/2*x^6*z^3 + 1/2*y^6*z^3 + 1/2*x^3*z^6 - 1/2*y^3*z^6, x*y*z) sage: f, g = WeierstrassForm(cubic); (f,g) (0, -27/4) sage: cubic.divides(-Y^2 + X^3 + f*X*Z^4 + g*Z^6) True Only the affine span of the Newton polytope of the polynomial matters. For example:: sage: WeierstrassForm(cubic.subs(z=1), transformation=True) (-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) sage: WeierstrassForm(x * cubic, transformation=True) (-x^3*y^3 - x^3*z^3 - y^3*z^3, 1/2*x^6*y^3 - 1/2*x^3*y^6 - 1/2*x^6*z^3 + 1/2*y^6*z^3 + 1/2*x^3*z^6 - 1/2*y^3*z^6, x*y*z) 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, transformation=True) (-1/27*t^4*x^6 - 2/27*t^4*x^5*z - 5/27*t^4*x^4*z^2 - 8/27*t^4*x^3*z^3 - 5/27*t^4*x^2*z^4 - 2/27*t^4*x*z^5 - 1/27*t^4*z^6 - 4/81*t^2*x^4*y^2 - 4/81*t^2*x^3*y^2*z - 4/81*t^2*x*y^2*z^3 - 4/81*t^2*y^2*z^4 - 2/81*x^2*y^4 - 4/81*x*y^4*z - 2/81*y^4*z^2, 0, 1/3*t^2*x^2*z + 1/3*t^2*x*z^2 - 1/9*x*y^2 - 1/9*y^2*z) sage: WeierstrassForm(x*y^2 + y^2 + x^3 + 1, transformation=True) (-1/27*x^6 - 4/81*x^4*y^2 - 2/81*x^2*y^4 - 2/27*x^5 - 4/81*x^3*y^2 - 4/81*x*y^4 - 5/27*x^4 - 2/81*y^4 - 8/27*x^3 - 4/81*x*y^2 - 5/27*x^2 - 4/81*y^2 - 2/27*x - 1/27, 0, -1/9*x*y^2 + 1/3*x^2 - 1/9*y^2 + 1/3*x) 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], transformation=True) (-a^9*y^3*z^3 - a^8*x^3*z^3 - a^7*x^3*y^3, -1/2*a^14*y^3*z^6 + 1/2*a^13*y^6*z^3 + 1/2*a^13*x^3*z^6 - 1/2*a^11*x^3*y^6 - 1/2*a^11*x^6*z^3 + 1/2*a^10*x^6*y^3, a^3*x*y*z) TESTS:: sage: for P in ReflexivePolytopes(2): ....: S = ToricVariety(FaceFan(P)) ....: p = sum( (-S.K()).sections_monomials() ) ....: f, g = WeierstrassForm(p) ....: X,Y,Z = WeierstrassForm(p, transformation=True) ....: assert p.divides(-Y^2 + X^3 + f*X*Z^4 + g*Z^6) """ if variables is None: variables = polynomial.variables() # switch to suitable inhomogeneous coordinates from sage.geometry.polyhedron.ppl_lattice_polygon import ( polar_P2_polytope, polar_P1xP1_polytope, polar_P2_112_polytope ) from sage.schemes.toric.weierstrass import Newton_polygon_embedded newton_polytope, polynomial_aff, variables_aff = \ Newton_polygon_embedded(polynomial, variables) polygon = newton_polytope.embed_in_reflexive_polytope('polytope') # Compute the map in inhomogeneous coordinates if polygon is polar_P2_polytope(): X,Y,Z = WeierstrassMap_P2(polynomial_aff, variables_aff) elif polygon is polar_P1xP1_polytope(): X,Y,Z = WeierstrassMap_P1xP1(polynomial_aff, variables_aff) elif polygon is polar_P2_112_polytope(): X,Y,Z = WeierstrassMap_P2_112(polynomial_aff, variables_aff) else: assert False, 'Newton polytope is not contained in a reflexive polygon' # homogenize again R = polynomial.parent() x = R.gens().index(variables_aff[0]) y = R.gens().index(variables_aff[1]) hom = newton_polytope.embed_in_reflexive_polytope('hom') def homogenize(inhomog, degree): e = tuple(hom._A * vector(ZZ,[inhomog[x], inhomog[y]]) + degree * hom._b) result = list(inhomog) for i, var in enumerate(variables): result[R.gens().index(var)] = e[i] result = vector(ZZ, result) result.set_immutable() return result X_dict = dict((homogenize(e,2), v) for e, v in iteritems(X.dict())) Y_dict = dict((homogenize(e,3), v) for e, v in iteritems(Y.dict())) Z_dict = dict((homogenize(e,1), v) for e, v in iteritems(Z.dict())) # shift to non-negative exponents if necessary min_deg = [0]*R.ngens() for var in variables: i = R.gens().index(var) min_X = min([ e[i] for e in X_dict ]) if len(X_dict)>0 else 0 min_Y = min([ e[i] for e in Y_dict ]) if len(Y_dict)>0 else 0 min_Z = min([ e[i] for e in Z_dict ]) if len(Z_dict)>0 else 0 min_deg[i] = min( min_X/2, min_Y/3, min_Z ) min_deg = vector(min_deg) X_dict = dict((tuple(e-2*min_deg), v) for e, v in iteritems(X_dict)) Y_dict = dict((tuple(e-3*min_deg), v) for e, v in iteritems(Y_dict)) Z_dict = dict((tuple(e-1*min_deg), v) for e, v in iteritems(Z_dict)) return (R(X_dict), R(Y_dict), R(Z_dict))
def WeierstrassForm(polynomial, variables=None): r""" Return the Weierstrass form of an anticanonical hypersurface. INPUT: - ``polynomial`` -- a polynomial. The toric hypersurface equation. Can be either a cubic, a biquadric, or the hypersurface in `\mathbb{P}^2[1,1,2]`. The equation need not be in any standard form, only its Newton polynomial is used. - ``variables`` -- a 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 Weierstras form is determined over the function field generated by the remaining variables. OUTPUT: The pair of coefficients `(f,g)` of the Weierstrass form `y^2 = x^3 + f x + g` of the hypersurface equation. EXAMPLES:: sage: R.<x,y,z> = QQ[] sage: cubic = x^3 + y^3 + z^3 sage: WeierstrassForm(cubic) (0, -27/4) Only the affine span of the Newton polytope of the polynomial matters. For example:: sage: WeierstrassForm(cubic.subs(z=1)) (0, -27/4) sage: WeierstrassForm(x * cubic) (0, -27/4) This allows you to work with either homogeneous or inhomogeneous variables. For exmple, 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) 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) TESTS:: sage: for P in ReflexivePolytopes(2): ....: S = ToricVariety(FaceFan(P)) ....: p = sum((-S.K()).sections_monomials()) ....: print WeierstrassForm(p) (-25/48, -1475/864) (-97/48, 17/864) (-25/48, -611/864) (-27/16, 27/32) (47/48, -199/864) (47/48, -71/864) (5/16, -21/32) (23/48, -235/864) (-1/48, 161/864) (-25/48, 253/864) (5/16, 11/32) (-25/48, 125/864) (-67/16, 63/32) (-11/16, 3/32) (-241/48, 3689/864) (215/48, -5291/864) """ if variables is None: variables = polynomial.variables() from sage.geometry.polyhedron.ppl_lattice_polygon import ( polar_P2_polytope, polar_P1xP1_polytope, polar_P2_112_polytope, ) newton_polytope, polynomial, variables = Newton_polygon_embedded(polynomial, variables) polygon = newton_polytope.embed_in_reflexive_polytope("polytope") if polygon is polar_P2_polytope(): return WeierstrassForm_P2(polynomial, variables) if polygon is polar_P1xP1_polytope(): return WeierstrassForm_P1xP1(polynomial, variables) if polygon is polar_P2_112_polytope(): return WeierstrassForm_P2_112(polynomial, variables) raise ValueError("Newton polytope is not contained in a reflexive polygon")
def WeierstrassMap(polynomial, variables=None): r""" Return the Weierstrass form of an anticanonical hypersurface. You should use :meth:`sage.schemes.toric.weierstrass.WeierstrassForm` with ``transformation=True`` to get the transformation. This function is only for internal use. INPUT: - ``polynomial`` -- a polynomial. The toric hypersurface equation. Can be either a cubic, a biquadric, or the hypersurface in `\mathbb{P}^2[1,1,2]`. The equation need not be in any standard form, only its Newton polyhedron is used. - ``variables`` -- a 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. OUTPUT: A triple `(X,Y,Z)` of polynomials defining a rational map of the toric hypersurface to its Weierstrass form in `\mathbb{P}^2[2,3,1]`. That is, the triple satisfies .. MATH:: Y^2 = X^3 + f X Z^4 + g Z^6 when restricted to the toric hypersurface. EXAMPLES:: sage: R.<x,y,z> = QQ[] sage: cubic = x^3 + y^3 + z^3 sage: X,Y,Z = WeierstrassForm(cubic, transformation=True); (X,Y,Z) (-x^3*y^3 - x^3*z^3 - y^3*z^3, 1/2*x^6*y^3 - 1/2*x^3*y^6 - 1/2*x^6*z^3 + 1/2*y^6*z^3 + 1/2*x^3*z^6 - 1/2*y^3*z^6, x*y*z) sage: f, g = WeierstrassForm(cubic); (f,g) (0, -27/4) sage: cubic.divides(-Y^2 + X^3 + f*X*Z^4 + g*Z^6) True Only the affine span of the Newton polytope of the polynomial matters. For example:: sage: WeierstrassForm(cubic.subs(z=1), transformation=True) (-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) sage: WeierstrassForm(x * cubic, transformation=True) (-x^3*y^3 - x^3*z^3 - y^3*z^3, 1/2*x^6*y^3 - 1/2*x^3*y^6 - 1/2*x^6*z^3 + 1/2*y^6*z^3 + 1/2*x^3*z^6 - 1/2*y^3*z^6, x*y*z) 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, transformation=True) (-1/27*t^4*x^6 - 2/27*t^4*x^5*z - 5/27*t^4*x^4*z^2 - 8/27*t^4*x^3*z^3 - 5/27*t^4*x^2*z^4 - 2/27*t^4*x*z^5 - 1/27*t^4*z^6 - 4/81*t^2*x^4*y^2 - 4/81*t^2*x^3*y^2*z - 4/81*t^2*x*y^2*z^3 - 4/81*t^2*y^2*z^4 - 2/81*x^2*y^4 - 4/81*x*y^4*z - 2/81*y^4*z^2, 0, 1/3*t^2*x^2*z + 1/3*t^2*x*z^2 - 1/9*x*y^2 - 1/9*y^2*z) sage: WeierstrassForm(x*y^2 + y^2 + x^3 + 1, transformation=True) (-1/27*x^6 - 4/81*x^4*y^2 - 2/81*x^2*y^4 - 2/27*x^5 - 4/81*x^3*y^2 - 4/81*x*y^4 - 5/27*x^4 - 2/81*y^4 - 8/27*x^3 - 4/81*x*y^2 - 5/27*x^2 - 4/81*y^2 - 2/27*x - 1/27, 0, -1/9*x*y^2 + 1/3*x^2 - 1/9*y^2 + 1/3*x) 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], transformation=True) (-a^9*y^3*z^3 - a^8*x^3*z^3 - a^7*x^3*y^3, -1/2*a^14*y^3*z^6 + 1/2*a^13*y^6*z^3 + 1/2*a^13*x^3*z^6 - 1/2*a^11*x^3*y^6 - 1/2*a^11*x^6*z^3 + 1/2*a^10*x^6*y^3, a^3*x*y*z) TESTS:: sage: for P in ReflexivePolytopes(2): ....: S = ToricVariety(FaceFan(P)) ....: p = sum( (-S.K()).sections_monomials() ) ....: f, g = WeierstrassForm(p) ....: X,Y,Z = WeierstrassForm(p, transformation=True) ....: assert p.divides(-Y^2 + X^3 + f*X*Z^4 + g*Z^6) """ if variables is None: variables = polynomial.variables() # switch to suitable inhomogeneous coordinates from sage.geometry.polyhedron.ppl_lattice_polygon import ( polar_P2_polytope, polar_P1xP1_polytope, polar_P2_112_polytope) from sage.schemes.toric.weierstrass import Newton_polygon_embedded newton_polytope, polynomial_aff, variables_aff = \ Newton_polygon_embedded(polynomial, variables) polygon = newton_polytope.embed_in_reflexive_polytope('polytope') # Compute the map in inhomogeneous coordinates if polygon is polar_P2_polytope(): X, Y, Z = WeierstrassMap_P2(polynomial_aff, variables_aff) elif polygon is polar_P1xP1_polytope(): X, Y, Z = WeierstrassMap_P1xP1(polynomial_aff, variables_aff) elif polygon is polar_P2_112_polytope(): X, Y, Z = WeierstrassMap_P2_112(polynomial_aff, variables_aff) else: assert False, 'Newton polytope is not contained in a reflexive polygon' # homogenize again R = polynomial.parent() x = R.gens().index(variables_aff[0]) y = R.gens().index(variables_aff[1]) hom = newton_polytope.embed_in_reflexive_polytope('hom') def homogenize(inhomog, degree): e = tuple(hom._A * vector(ZZ, [inhomog[x], inhomog[y]]) + degree * hom._b) result = list(inhomog) for i, var in enumerate(variables): result[R.gens().index(var)] = e[i] result = vector(ZZ, result) result.set_immutable() return result X_dict = dict((homogenize(e, 2), v) for e, v in iteritems(X.dict())) Y_dict = dict((homogenize(e, 3), v) for e, v in iteritems(Y.dict())) Z_dict = dict((homogenize(e, 1), v) for e, v in iteritems(Z.dict())) # shift to non-negative exponents if necessary min_deg = [0] * R.ngens() for var in variables: i = R.gens().index(var) min_X = min([e[i] for e in X_dict]) if len(X_dict) > 0 else 0 min_Y = min([e[i] for e in Y_dict]) if len(Y_dict) > 0 else 0 min_Z = min([e[i] for e in Z_dict]) if len(Z_dict) > 0 else 0 min_deg[i] = min(min_X / 2, min_Y / 3, min_Z) min_deg = vector(min_deg) X_dict = dict((tuple(e - 2 * min_deg), v) for e, v in iteritems(X_dict)) Y_dict = dict((tuple(e - 3 * min_deg), v) for e, v in iteritems(Y_dict)) Z_dict = dict((tuple(e - 1 * min_deg), v) for e, v in iteritems(Z_dict)) return (R(X_dict), R(Y_dict), R(Z_dict))