Exemplo n.º 1
0
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')
Exemplo n.º 2
0
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')
Exemplo n.º 3
0
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))
Exemplo n.º 4
0
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")
Exemplo n.º 5
0
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))