Ejemplo n.º 1
0
    def segre_embedding(self, PP=None, var='u'):
        r"""
        Return the Segre embedding of this space into the appropriate
        projective space.

        INPUT:

        -  ``PP`` -- (default: ``None``) ambient image projective space;
            this is constructed if it is not given.

        - ``var`` -- string, variable name of the image projective space, default `u` (optional).

        OUTPUT:

        Hom -- from this space to the appropriate subscheme of projective space.

        .. TODO::

            Cartesian products with more than two components.

        EXAMPLES::

            sage: X.<y0,y1,y2,y3,y4,y5> = ProductProjectiveSpaces(ZZ, [2, 2])
            sage: phi = X.segre_embedding(); phi
            Scheme morphism:
              From: Product of projective spaces P^2 x P^2 over Integer Ring
              To:   Closed subscheme of Projective Space of dimension 8 over Integer Ring defined by:
              -u5*u7 + u4*u8,
              -u5*u6 + u3*u8,
              -u4*u6 + u3*u7,
              -u2*u7 + u1*u8,
              -u2*u4 + u1*u5,
              -u2*u6 + u0*u8,
              -u1*u6 + u0*u7,
              -u2*u3 + u0*u5,
              -u1*u3 + u0*u4
              Defn: Defined by sending (y0 : y1 : y2 , y3 : y4 : y5) to
                    (y0*y3 : y0*y4 : y0*y5 : y1*y3 : y1*y4 : y1*y5 : y2*y3 : y2*y4 : y2*y5).

            ::

            sage: T = ProductProjectiveSpaces([1, 2], CC, 'z')
            sage: T.segre_embedding()
            Scheme morphism:
              From: Product of projective spaces P^1 x P^2 over Complex Field with 53 bits of precision
              To:   Closed subscheme of Projective Space of dimension 5 over Complex Field with 53 bits of precision defined by:
              -u2*u4 + u1*u5,
              -u2*u3 + u0*u5,
              -u1*u3 + u0*u4
              Defn: Defined by sending (z0 : z1 , z2 : z3 : z4) to
                    (z0*z2 : z0*z3 : z0*z4 : z1*z2 : z1*z3 : z1*z4).

            ::

            sage: T = ProductProjectiveSpaces([1, 2, 1], QQ, 'z')
            sage: T.segre_embedding()
            Scheme morphism:
              From: Product of projective spaces P^1 x P^2 x P^1 over Rational Field
              To:   Closed subscheme of Projective Space of dimension 11 over
            Rational Field defined by:
              -u9*u10 + u8*u11,
              -u7*u10 + u6*u11,
              -u7*u8 + u6*u9,
              -u5*u10 + u4*u11,
              -u5*u8 + u4*u9,
              -u5*u6 + u4*u7,
              -u5*u9 + u3*u11,
              -u5*u8 + u3*u10,
              -u5*u8 + u2*u11,
              -u4*u8 + u2*u10,
              -u3*u8 + u2*u9,
              -u3*u6 + u2*u7,
              -u3*u4 + u2*u5,
              -u5*u7 + u1*u11,
              -u5*u6 + u1*u10,
              -u3*u7 + u1*u9,
              -u3*u6 + u1*u8,
              -u5*u6 + u0*u11,
              -u4*u6 + u0*u10,
              -u3*u6 + u0*u9,
              -u2*u6 + u0*u8,
              -u1*u6 + u0*u7,
              -u1*u4 + u0*u5,
              -u1*u2 + u0*u3
              Defn: Defined by sending (z0 : z1 , z2 : z3 : z4 , z5 : z6) to
                    (z0*z2*z5 : z0*z2*z6 : z0*z3*z5 : z0*z3*z6 : z0*z4*z5 : z0*z4*z6
            : z1*z2*z5 : z1*z2*z6 : z1*z3*z5 : z1*z3*z6 : z1*z4*z5 : z1*z4*z6).
        """
        N = self._dims
        M = prod([n + 1 for n in N]) - 1
        CR = self.coordinate_ring()

        vars = list(self.coordinate_ring().variable_names()) + [
            var + str(i) for i in range(M + 1)
        ]
        R = PolynomialRing(self.base_ring(),
                           self.ngens() + M + 1,
                           vars,
                           order='lex')

        #set-up the elimination for the segre embedding
        mapping = []
        k = self.ngens()
        index = self.num_components() * [0]
        for count in range(M + 1):
            mapping.append(
                R.gen(k + count) -
                prod([CR(self[i].gen(index[i])) for i in range(len(index))]))
            for i in range(len(index) - 1, -1, -1):
                if index[i] == N[i]:
                    index[i] = 0
                else:
                    index[i] += 1
                    break  #only increment once

        #change the defining ideal of the subscheme into the variables
        I = R.ideal(list(self.defining_polynomials()) + mapping)
        J = I.groebner_basis()
        s = set(R.gens()[:self.ngens()])
        n = len(J) - 1
        L = []
        while s.isdisjoint(J[n].variables()):
            L.append(J[n])
            n = n - 1

        #create new subscheme
        if PP is None:
            PS = ProjectiveSpace(self.base_ring(), M,
                                 R.variable_names()[self.ngens():])
            Y = PS.subscheme(L)
        else:
            if PP.dimension_relative() != M:
                raise ValueError(
                    "projective Space %s must be dimension %s") % (PP, M)
            S = PP.coordinate_ring()
            psi = R.hom([0] * k + list(S.gens()), S)
            L = [psi(l) for l in L]
            Y = PP.subscheme(L)

        #create embedding for points
        mapping = []
        index = self.num_components() * [0]
        for count in range(M + 1):
            mapping.append(
                prod([CR(self[i].gen(index[i])) for i in range(len(index))]))
            for i in range(len(index) - 1, -1, -1):
                if index[i] == N[i]:
                    index[i] = 0
                else:
                    index[i] += 1
                    break  #only increment once
        phi = self.hom(mapping, Y)

        return phi
Ejemplo n.º 2
0
def rational_type(f, n=ZZ(3), base_ring=ZZ):
    r"""
    Return the basic analytic properties that can be determined
    directly from the specified rational function ``f``
    which is interpreted as a representation of an
    element of a FormsRing for the Hecke Triangle group
    with parameter ``n`` and the specified ``base_ring``.

    In particular the following degree of the generators is assumed:

    `deg(1) := (0, 1)`
    `deg(x) := (4/(n-2), 1)`
    `deg(y) := (2n/(n-2), -1)`
    `deg(z) := (2, -1)`

    The meaning of homogeneous elements changes accordingly.

    INPUT:

    - ``f``               - A rational function in ``x,y,z,d`` over ``base_ring``.
    - ``n``               - An integer greater or equal to ``3`` corresponding
                           to the ``HeckeTriangleGroup`` with that parameter
                           (default: ``3``).
    - ``base_ring```      - The base ring of the corresponding forms ring, resp.
                            polynomial ring (default: ``ZZ``).

    OUTPUT:
    
    A tuple ``(elem, h**o, k, ep, analytic_type)`` describing the basic
    analytic properties of ``f`` (with the interpretation indicated above).
    
    - ``elem``            - ``True`` if ``f`` has a homogeneous denominator.
    - ``h**o``            - ``True`` if ``f`` also has a homogeneous numerator.
    - ``k``               - ``None`` if ``f`` is not homogeneneous, otherwise
                            the weight of ``f`` (which is the first component
                            of its degree).
    - ``ep``              - ``None`` if ``f`` is not homogeneous, otherwise
                            the multiplier of ``f`` (which is the second component
                            of its degree)
    - ``analytic_type``   - The ``AnalyticType`` of ``f``.

    For the zero function the degree ``(0, 1)`` is choosen.

    This function is (heavily) used to determine the type of elements
    and to check if the element really is contained in its parent.


    EXAMPLES::

        sage: (x,y,z,d) = var("x,y,z,d")

        sage: rational_type(0, n=4)
        (True, True, 0, 1, zero)

        sage: rational_type(1, n=12)
        (True, True, 0, 1, modular)

        sage: rational_type(x^3 - y^2)
        (True, True, 12, 1, cuspidal)

        sage: rational_type(x * z, n=7)
        (True, True, 14/5, -1, quasi modular)

        sage: rational_type(1/(x^3 - y^2) + z/d)
        (True, False, None, None, quasi weakly holomorphic modular)

        sage: rational_type(x^3/(x^3 - y^2))
        (True, True, 0, 1, weakly holomorphic modular)

        sage: rational_type(1/(x + z))
        (False, False, None, None, None)

        sage: rational_type(1/x + 1/z)
        (True, False, None, None, quasi meromorphic modular)

        sage: rational_type(d/x, n=10)
        (True, True, -1/2, 1, meromorphic modular)

        sage: rational_type(1.1 * z * (x^8-y^2), n=8, base_ring=CC)
        (True, True, 22/3, -1, quasi cuspidal)
    """

    from analytic_type import AnalyticType
    AT = AnalyticType()

    # Determine whether f is zero
    if (f == 0):
        #       elem, h**o, k,     ep,    analytic_type
        return (True, True, QQ(0), ZZ(1), AT([]))
 
    analytic_type = AT(["quasi", "mero"])

    R          = PolynomialRing(base_ring,'x,y,z,d')
    F          = FractionField(R)
    (x,y,z,d)  = R.gens()
    R2         = PolynomialRing(PolynomialRing(base_ring, 'd'), 'x,y,z')
    dhom       = R.hom( R2.gens() + (R2.base().gen(),), R2)

    f          = F(f)
    n          = ZZ(n)

    num        = R(f.numerator())
    denom      = R(f.denominator())
    hom_num    = R(   num.subs(x=x**4, y=y**(2*n), z=z**(2*(n-2))) )
    hom_denom  = R( denom.subs(x=x**4, y=y**(2*n), z=z**(2*(n-2))) )
    ep_num     = set([ZZ(1) - 2*(( sum([g.exponents()[0][m] for m in [1,2]]) )%2) for g in   dhom(num).monomials()])
    ep_denom   = set([ZZ(1) - 2*(( sum([g.exponents()[0][m] for m in [1,2]]) )%2) for g in dhom(denom).monomials()])

    # Determine whether the denominator of f is homogeneous
    if (len(ep_denom) == 1 and dhom(hom_denom).is_homogeneous()):
        elem = True
    else:
        #       elem,  h**o,  k,    ep,   analytic_type
        return (False, False, None, None, None)


    # Determine whether f is homogeneous
    if (len(ep_num) == 1 and dhom(hom_num).is_homogeneous()):
        h**o   = True
        weight = (dhom(hom_num).degree() - dhom(hom_denom).degree()) / (n-2)
        ep     = ep_num.pop() / ep_denom.pop()
    # TODO: decompose f (resp. its degrees) into homogeneous parts
    else:
        h**o   = False
        weight = None
        ep     = None

    # Note that we intentially leave out the d-factor!
    finf_pol = x**n-y**2

    # Determine whether f is modular
    if not ( (num.degree(z) > 0) or (denom.degree(z) > 0) ):
        analytic_type = analytic_type.reduce_to("mero")

    # Determine whether f is holomorphic
    if (dhom(denom).is_constant()):
        analytic_type = analytic_type.reduce_to(["quasi", "holo"])
        # Determine whether f is cuspidal in the sense that finf divides it...
        # Bug in singular: finf_pol.dividess(1.0) fails over RR
        if (not dhom(num).is_constant()) and finf_pol.divides(num):
            analytic_type = analytic_type.reduce_to(["quasi", "cusp"])
    else:
        # -> because of a bug with singular in case some cases
        try:
            while (finf_pol.divides(denom)):
                # a simple "denom /= finf_pol" is strangely not enough for non-exact rings
                denom = denom.quo_rem(finf_pol)[0]
                denom = R(denom)
        except TypeError:
            pass

        # Determine whether f is weakly holomorphic in the sense that at most powers of finf occur in denom
        if (dhom(denom).is_constant()):
            analytic_type = analytic_type.reduce_to(["quasi", "weak"])

    return (elem, h**o, weight, ep, analytic_type)
Ejemplo n.º 3
0
    def segre_embedding(self, PP=None, var='u'):
        r"""
        Return the Segre embedding of ``self`` into the appropriate
        projective space.

        INPUT:

        -  ``PP`` -- (default: ``None``) ambient image projective space;
            this is constructed if it is not given.

        - ``var`` -- string, variable name of the image projective space, default `u` (optional)

        OUTPUT:

        Hom -- from ``self`` to the appropriate subscheme of projective space

        .. TODO::

            Cartesian products with more than two components

        EXAMPLES::

            sage: X.<y0,y1,y2,y3,y4,y5> = ProductProjectiveSpaces(ZZ,[2,2])
            sage: phi = X.segre_embedding(); phi
            Scheme morphism:
              From: Product of projective spaces P^2 x P^2 over Integer Ring
              To:   Closed subscheme of Projective Space of dimension 8 over Integer Ring defined by:
              -u5*u7 + u4*u8,
              -u5*u6 + u3*u8,
              -u4*u6 + u3*u7,
              -u2*u7 + u1*u8,
              -u2*u4 + u1*u5,
              -u2*u6 + u0*u8,
              -u1*u6 + u0*u7,
              -u2*u3 + u0*u5,
              -u1*u3 + u0*u4
              Defn: Defined by sending (y0 : y1 : y2 , y3 : y4 : y5) to
                    (y0*y3 : y0*y4 : y0*y5 : y1*y3 : y1*y4 : y1*y5 : y2*y3 : y2*y4 : y2*y5).

            ::

            sage: T = ProductProjectiveSpaces([1,2],CC,'z')
            sage: T.segre_embedding()
            Scheme morphism:
              From: Product of projective spaces P^1 x P^2 over Complex Field with 53 bits of precision
              To:   Closed subscheme of Projective Space of dimension 5 over Complex Field with 53 bits of precision defined by:
              -u2*u4 + u1*u5,
              -u2*u3 + u0*u5,
              -u1*u3 + u0*u4
              Defn: Defined by sending (z0 : z1 , z2 : z3 : z4) to
                    (z0*z2 : z0*z3 : z0*z4 : z1*z2 : z1*z3 : z1*z4).
        """
        N = self._dims
        if len(N) > 2:
            raise NotImplementedError("Cannot have more than two components.")
        M = (N[0]+1)*(N[1]+1)-1

        vars = list(self.coordinate_ring().variable_names()) + [var + str(i) for i in range(M+1)]
        R = PolynomialRing(self.base_ring(),self.ngens()+M+1, vars, order='lex')

        #set-up the elimination for the segre embedding
        mapping = []
        k = self.ngens()
        for i in range(N[0]+1):
            for j in range(N[0]+1,N[0]+N[1]+2):
                mapping.append(R.gen(k)-R(self.gen(i)*self.gen(j)))
                k+=1

        #change the defining ideal of the subscheme into the variables
        I = R.ideal(list(self.defining_polynomials()) + mapping)
        J = I.groebner_basis()
        s = set(R.gens()[:self.ngens()])
        n = len(J)-1
        L = []
        while s.isdisjoint(J[n].variables()):
            L.append(J[n])
            n = n-1

        #create new subscheme
        if PP is None:
            PS = ProjectiveSpace(self.base_ring(),M,R.gens()[self.ngens():])
            Y = PS.subscheme(L)
        else:
            if PP.dimension_relative()!= M:
                raise ValueError("Projective Space %s must be dimension %s")%(PP, M)
            S = PP.coordinate_ring()
            psi = R.hom([0]*(N[0]+N[1]+2) + list(S.gens()),S)
            L = [psi(l) for l in L]
            Y = PP.subscheme(L)

        #create embedding for points
        mapping = []
        for i in range(N[0]+1):
            for j in range(N[0]+1,N[0]+N[1]+2):
                mapping.append(self.gen(i)*self.gen(j))
        phi = self.hom(mapping,Y)

        return phi
Ejemplo n.º 4
0
def rational_type(f, n=ZZ(3), base_ring=ZZ):
    r"""
    Return the basic analytic properties that can be determined
    directly from the specified rational function ``f``
    which is interpreted as a representation of an
    element of a FormsRing for the Hecke Triangle group
    with parameter ``n`` and the specified ``base_ring``.

    In particular the following degree of the generators is assumed:

    `deg(1) := (0, 1)`
    `deg(x) := (4/(n-2), 1)`
    `deg(y) := (2n/(n-2), -1)`
    `deg(z) := (2, -1)`

    The meaning of homogeneous elements changes accordingly.

    INPUT:

    - ``f``              -- A rational function in ``x,y,z,d`` over ``base_ring``.

    - ``n``              -- An integer greater or equal to `3` corresponding
                            to the ``HeckeTriangleGroup`` with that parameter
                            (default: `3`).

    - ``base_ring``      -- The base ring of the corresponding forms ring, resp.
                            polynomial ring (default: ``ZZ``).

    OUTPUT:

    A tuple ``(elem, h**o, k, ep, analytic_type)`` describing the basic
    analytic properties of `f` (with the interpretation indicated above).

    - ``elem``           -- ``True`` if `f` has a homogeneous denominator.

    - ``h**o``           -- ``True`` if `f` also has a homogeneous numerator.

    - ``k``              -- ``None`` if `f` is not homogeneous, otherwise
                            the weight of `f` (which is the first component
                            of its degree).

    - ``ep``             -- ``None`` if `f` is not homogeneous, otherwise
                            the multiplier of `f` (which is the second component
                            of its degree)

    - ``analytic_type``  -- The ``AnalyticType`` of `f`.

    For the zero function the degree `(0, 1)` is choosen.

    This function is (heavily) used to determine the type of elements
    and to check if the element really is contained in its parent.


    EXAMPLES::

        sage: from sage.modular.modform_hecketriangle.constructor import rational_type
        sage: (x,y,z,d) = var("x,y,z,d")

        sage: rational_type(0, n=4)
        (True, True, 0, 1, zero)

        sage: rational_type(1, n=12)
        (True, True, 0, 1, modular)

        sage: rational_type(x^3 - y^2)
        (True, True, 12, 1, cuspidal)

        sage: rational_type(x * z, n=7)
        (True, True, 14/5, -1, quasi modular)

        sage: rational_type(1/(x^3 - y^2) + z/d)
        (True, False, None, None, quasi weakly holomorphic modular)

        sage: rational_type(x^3/(x^3 - y^2))
        (True, True, 0, 1, weakly holomorphic modular)

        sage: rational_type(1/(x + z))
        (False, False, None, None, None)

        sage: rational_type(1/x + 1/z)
        (True, False, None, None, quasi meromorphic modular)

        sage: rational_type(d/x, n=10)
        (True, True, -1/2, 1, meromorphic modular)

        sage: rational_type(1.1 * z * (x^8-y^2), n=8, base_ring=CC)
        (True, True, 22/3, -1, quasi cuspidal)

        sage: rational_type(x-y^2, n=infinity)
        (True, True, 4, 1, modular)

        sage: rational_type(x*(x-y^2), n=infinity)
        (True, True, 8, 1, cuspidal)

        sage: rational_type(1/x, n=infinity)
        (True, True, -4, 1, weakly holomorphic modular)
    """

    from .analytic_type import AnalyticType
    AT = AnalyticType()

    # Determine whether f is zero
    if (f == 0):
        #       elem, h**o, k,     ep,    analytic_type
        return (True, True, QQ(0), ZZ(1), AT([]))

    analytic_type = AT(["quasi", "mero"])

    R = PolynomialRing(base_ring, 'x,y,z,d')
    F = FractionField(R)
    (x, y, z, d) = R.gens()
    R2 = PolynomialRing(PolynomialRing(base_ring, 'd'), 'x,y,z')
    dhom = R.hom(R2.gens() + (R2.base().gen(), ), R2)

    f = F(f)

    num = R(f.numerator())
    denom = R(f.denominator())
    ep_num = set([
        ZZ(1) - 2 * ((sum([g.exponents()[0][m] for m in [1, 2]])) % 2)
        for g in dhom(num).monomials()
    ])
    ep_denom = set([
        ZZ(1) - 2 * ((sum([g.exponents()[0][m] for m in [1, 2]])) % 2)
        for g in dhom(denom).monomials()
    ])

    if (n == infinity):
        hom_num = R(num.subs(x=x**4, y=y**2, z=z**2))
        hom_denom = R(denom.subs(x=x**4, y=y**2, z=z**2))
    else:
        n = ZZ(n)
        hom_num = R(num.subs(x=x**4, y=y**(2 * n), z=z**(2 * (n - 2))))
        hom_denom = R(denom.subs(x=x**4, y=y**(2 * n), z=z**(2 * (n - 2))))

    # Determine whether the denominator of f is homogeneous
    if (len(ep_denom) == 1 and dhom(hom_denom).is_homogeneous()):
        elem = True
    else:
        #       elem,  h**o,  k,    ep,   analytic_type
        return (False, False, None, None, None)

    # Determine whether f is homogeneous
    if (len(ep_num) == 1 and dhom(hom_num).is_homogeneous()):
        h**o = True
        if (n == infinity):
            weight = (dhom(hom_num).degree() - dhom(hom_denom).degree())
        else:
            weight = (dhom(hom_num).degree() - dhom(hom_denom).degree()) / (n -
                                                                            2)
        ep = ep_num.pop() / ep_denom.pop()
    # TODO: decompose f (resp. its degrees) into homogeneous parts
    else:
        h**o = False
        weight = None
        ep = None

    # Note that we intentionally leave out the d-factor!
    if (n == infinity):
        finf_pol = (x - y**2)
    else:
        finf_pol = x**n - y**2

    # Determine whether f is modular
    if not ((num.degree(z) > 0) or (denom.degree(z) > 0)):
        analytic_type = analytic_type.reduce_to("mero")

    # Determine whether f is holomorphic
    if (dhom(denom).is_constant()):
        analytic_type = analytic_type.reduce_to(["quasi", "holo"])
        # Determine whether f is cuspidal in the sense that finf divides it...
        # Bug in singular: finf_pol.divides(1.0) fails over RR
        if (not dhom(num).is_constant() and finf_pol.divides(num)):
            if (n != infinity or x.divides(num)):
                analytic_type = analytic_type.reduce_to(["quasi", "cusp"])
    else:
        # -> Because of a bug with singular in some cases
        try:
            while (finf_pol.divides(denom)):
                # a simple "denom /= finf_pol" is strangely not enough for non-exact rings
                # and dividing would/may result with an element of the quotient ring of the polynomial ring
                denom = denom.quo_rem(finf_pol)[0]
                denom = R(denom)
            if (n == infinity):
                while (x.divides(denom)):
                    # a simple "denom /= x" is strangely not enough for non-exact rings
                    # and dividing would/may result with an element of the quotient ring of the polynomial ring
                    denom = denom.quo_rem(x)[0]
                    denom = R(denom)
        except TypeError:
            pass

        # Determine whether f is weakly holomorphic in the sense that at most powers of finf occur in denom
        if (dhom(denom).is_constant()):
            analytic_type = analytic_type.reduce_to(["quasi", "weak"])

    return (elem, h**o, weight, ep, analytic_type)
Ejemplo n.º 5
0
    def segre_embedding(self, PP=None, var='u'):
        r"""
        Return the Segre embedding of this space into the appropriate
        projective space.

        INPUT:

        -  ``PP`` -- (default: ``None``) ambient image projective space;
            this is constructed if it is not given.

        - ``var`` -- string, variable name of the image projective space, default `u` (optional).

        OUTPUT:

        Hom -- from this space to the appropriate subscheme of projective space.

        .. TODO::

            Cartesian products with more than two components.

        EXAMPLES::

            sage: X.<y0,y1,y2,y3,y4,y5> = ProductProjectiveSpaces(ZZ, [2, 2])
            sage: phi = X.segre_embedding(); phi
            Scheme morphism:
              From: Product of projective spaces P^2 x P^2 over Integer Ring
              To:   Closed subscheme of Projective Space of dimension 8 over Integer Ring defined by:
              -u5*u7 + u4*u8,
              -u5*u6 + u3*u8,
              -u4*u6 + u3*u7,
              -u2*u7 + u1*u8,
              -u2*u4 + u1*u5,
              -u2*u6 + u0*u8,
              -u1*u6 + u0*u7,
              -u2*u3 + u0*u5,
              -u1*u3 + u0*u4
              Defn: Defined by sending (y0 : y1 : y2 , y3 : y4 : y5) to
                    (y0*y3 : y0*y4 : y0*y5 : y1*y3 : y1*y4 : y1*y5 : y2*y3 : y2*y4 : y2*y5).

            ::

            sage: T = ProductProjectiveSpaces([1, 2], CC, 'z')
            sage: T.segre_embedding()
            Scheme morphism:
              From: Product of projective spaces P^1 x P^2 over Complex Field with 53 bits of precision
              To:   Closed subscheme of Projective Space of dimension 5 over Complex Field with 53 bits of precision defined by:
              -u2*u4 + u1*u5,
              -u2*u3 + u0*u5,
              -u1*u3 + u0*u4
              Defn: Defined by sending (z0 : z1 , z2 : z3 : z4) to
                    (z0*z2 : z0*z3 : z0*z4 : z1*z2 : z1*z3 : z1*z4).

            ::

            sage: T = ProductProjectiveSpaces([1, 2, 1], QQ, 'z')
            sage: T.segre_embedding()
            Scheme morphism:
              From: Product of projective spaces P^1 x P^2 x P^1 over Rational Field
              To:   Closed subscheme of Projective Space of dimension 11 over
            Rational Field defined by:
              -u9*u10 + u8*u11,
              -u7*u10 + u6*u11,
              -u7*u8 + u6*u9,
              -u5*u10 + u4*u11,
              -u5*u8 + u4*u9,
              -u5*u6 + u4*u7,
              -u5*u9 + u3*u11,
              -u5*u8 + u3*u10,
              -u5*u8 + u2*u11,
              -u4*u8 + u2*u10,
              -u3*u8 + u2*u9,
              -u3*u6 + u2*u7,
              -u3*u4 + u2*u5,
              -u5*u7 + u1*u11,
              -u5*u6 + u1*u10,
              -u3*u7 + u1*u9,
              -u3*u6 + u1*u8,
              -u5*u6 + u0*u11,
              -u4*u6 + u0*u10,
              -u3*u6 + u0*u9,
              -u2*u6 + u0*u8,
              -u1*u6 + u0*u7,
              -u1*u4 + u0*u5,
              -u1*u2 + u0*u3
              Defn: Defined by sending (z0 : z1 , z2 : z3 : z4 , z5 : z6) to
                    (z0*z2*z5 : z0*z2*z6 : z0*z3*z5 : z0*z3*z6 : z0*z4*z5 : z0*z4*z6
            : z1*z2*z5 : z1*z2*z6 : z1*z3*z5 : z1*z3*z6 : z1*z4*z5 : z1*z4*z6).
        """
        N = self._dims
        M = prod([n+1 for n in N]) - 1
        CR = self.coordinate_ring()

        vars = list(self.coordinate_ring().variable_names()) + [var + str(i) for i in range(M+1)]
        R = PolynomialRing(self.base_ring(), self.ngens()+M+1, vars, order='lex')

        #set-up the elimination for the segre embedding
        mapping = []
        k = self.ngens()
        index = self.num_components()*[0]
        for count in range(M + 1):
            mapping.append(R.gen(k+count)-prod([CR(self[i].gen(index[i])) for i in range(len(index))]))
            for i in range(len(index)-1, -1, -1):
                if index[i] == N[i]:
                    index[i] = 0
                else:
                    index[i] += 1
                    break #only increment once

        #change the defining ideal of the subscheme into the variables
        I = R.ideal(list(self.defining_polynomials()) + mapping)
        J = I.groebner_basis()
        s = set(R.gens()[:self.ngens()])
        n = len(J)-1
        L = []
        while s.isdisjoint(J[n].variables()):
            L.append(J[n])
            n = n-1

        #create new subscheme
        if PP is None:
            PS = ProjectiveSpace(self.base_ring(), M, R.variable_names()[self.ngens():])
            Y = PS.subscheme(L)
        else:
            if PP.dimension_relative() != M:
                raise ValueError("projective Space %s must be dimension %s")%(PP, M)
            S = PP.coordinate_ring()
            psi = R.hom([0]*k + list(S.gens()), S)
            L = [psi(l) for l in L]
            Y = PP.subscheme(L)

        #create embedding for points
        mapping = []
        index = self.num_components()*[0]
        for count in range(M + 1):
            mapping.append(prod([CR(self[i].gen(index[i])) for i in range(len(index))]))
            for i in range(len(index)-1, -1, -1):
                if index[i] == N[i]:
                    index[i] = 0
                else:
                    index[i] += 1
                    break #only increment once
        phi = self.hom(mapping, Y)

        return phi