Example #1
0
 def F(z,level = 0,method = 'moments'):
     R = PolynomialRing(z.parent(),'x,y').fraction_field()
     Rx = PolynomialRing(z.parent(),'x1').fraction_field()
     x1 = Rx.gen()
     subst = R.hom([x1,z],codomain = Rx)
     x,y = R.gens()
     center = self.parent()._source._BT.find_containing_affinoid(z)
     zbar = z.trace()-z
     f = R(1)/(x-y)
     k = self.parent()._n+2
     V = [f]
     for ii in range(order):
         V = [v.derivative(y) for v in V]+[k/(y-zbar)*v for v in V]
         k += 2
     return sum([self.integrate(subst(v),center,level,method) for v in V])
Example #2
0
 def F(z):
     R=PolynomialRing(z.parent(),'x,y').fraction_field()
     Rx=PolynomialRing(z.parent(),'x1').fraction_field()
     x1=Rx.gen()
     subst=R.hom([x1,z],codomain=Rx)
     x,y=R.gens()
     center=self._parent._X._BT.find_containing_affinoid(z)
     zbar=z.trace()-z
     f=R(1)/(x-y)
     k=self._parent._k
     V=[f]
     for ii in range(order):
         V=[v.derivative(y) for v in V]+[k/(y-zbar)*v for v in V]
         k+=2
     return sum([self.riemann_sum(subst(v),center,level) for v in V])
    def _forward_image(self, f, check=True):
        r"""
        Compute the forward image of this subscheme by the morphism ``f``.

        The forward image is computed through elimination and ``f`` must be
        a morphism for this to be well defined.
        In particular, let $X = V(h_1,\ldots, h_t)$ and define the ideal
        $I = (h_1,\ldots,h_t,y_0-f_0(\bar{x}), \ldots, y_n-f_n(\bar{x}))$.
        Then the elimination ideal $I_{n+1} = I \cap K[y_0,\ldots,y_n]$ is a homogeneous
        ideal and $self(X) = V(I_{n+1})$.

        INPUT:

        - ``f`` -- a map whose domain contains ``self``

        - ``check`` -- Boolean, if `False` no input checking is done

        OUTPUT:

         - a subscheme in the codomain of ``f``.

        EXAMPLES::

            sage: PS.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: H = End(PS)
            sage: f = H([x^2, y^2-2*z^2, z^2])
            sage: X = PS.subscheme(y-2*z)
            sage: X._forward_image(f)
            Closed subscheme of Projective Space of dimension 2 over Rational Field
            defined by:
              y - 2*z

        ::

            sage: set_verbose(None)
            sage: PS.<x,y,z,w> = ProjectiveSpace(ZZ, 3)
            sage: H = End(PS)
            sage: f = H([y^2, x^2, w^2, z^2])
            sage: X = PS.subscheme([z^2+y*w, x-w])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 3 over Integer Ring
            defined by:
              y - z,
              x*z - w^2

        ::

            sage: PS.<x,y,z,w> = ProjectiveSpace(CC, 3)
            sage: H = End(PS)
            sage: f = H([x^2 + y^2, y^2, z^2-y^2, w^2])
            sage: X = PS.subscheme([z-2*w])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 3 over Complex Field
            with 53 bits of precision defined by:
              y + z + (-4.00000000000000)*w

        ::

            sage: R.<t> = PolynomialRing(QQ)
            sage: P.<x,y,z> = ProjectiveSpace(FractionField(R), 2)
            sage: H = End(P)
            sage: f = H([x^2 + 2*y*z, t^2*y^2, z^2])
            sage: f([t^2*y-z])
            Closed subscheme of Projective Space of dimension 2 over Fraction Field
            of Univariate Polynomial Ring in t over Rational Field defined by:
              y + (-1/t^2)*z

        ::

            sage: set_verbose(-1)
            sage: PS.<x,y,z> = ProjectiveSpace(Qp(3), 2)
            sage: H = End(PS)
            sage: f = H([x^2,2*y^2,z^2])
            sage: X = PS.subscheme([2*x-y,z])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 2 over 3-adic Field
            with capped relative precision 20 defined by:
              z,
              x + (1 + 3^2 + 3^4 + 3^6 + 3^8 + 3^10 + 3^12 + 3^14 + 3^16 + 3^18 +
            O(3^20))*y

        ::

            sage: R.<y0,y1,y2,y3> = PolynomialRing(QQ)
            sage: P.<x,y,z> = ProjectiveSpace(FractionField(R), 2)
            sage: H = End(P)
            sage: f = H([y0*x^2+y1*z^2, y2*y^2+y3*z^2, z^2])
            sage: X = P.subscheme(x*z)
            sage: X._forward_image(f)
            Closed subscheme of Projective Space of dimension 2 over Fraction Field
            of Multivariate Polynomial Ring in y0, y1, y2, y3 over Rational Field
            defined by:
              x*z + (-y1)*z^2

            ::

            sage: P2.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: P5.<z0,z1,z2,z3,z4,z5> = ProjectiveSpace(QQ, 5)
            sage: H = Hom(P2, P5)
            sage: f = H([x^2,x*y,x*z,y^2,y*z,z^2]) #Veronese map
            sage: X = P2.subscheme([])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 5 over Rational Field
            defined by:
              -z4^2 + z3*z5,
              -z2*z4 + z1*z5,
              -z2*z3 + z1*z4,
              -z2^2 + z0*z5,
              -z1*z2 + z0*z4,
              -z1^2 + z0*z3

            ::

            sage: P2.<x,y,z>=ProjectiveSpace(QQ, 2)
            sage: P3.<u,v,w,t>=ProjectiveSpace(QQ, 3)
            sage: H = Hom(P2, P3)
            sage: X = P2.subscheme([x-y,x-z])
            sage: f = H([x^2,y^2,z^2,x*y])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 3 over Rational Field
            defined by:
              w - t,
              v - t,
              u - t

            ::

            sage: P1.<u,v> = ProjectiveSpace(QQ, 1)
            sage: P2.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: H = Hom(P2,P1)
            sage: f = H([x^2,y*z])
            sage: X = P2.subscheme([x-y])
            sage: f(X)
            Traceback (most recent call last):
            ...
            TypeError: map must be a morphism

            ::

            sage: PS.<x,y,z> = ProjectiveSpace(ZZ, 2)
            sage: H = End(PS)
            sage: f = H([x^3, x*y^2, x*z^2])
            sage: X = PS.subscheme([x-y])
            sage: X._forward_image(f)
            Traceback (most recent call last):
            ...
            TypeError: map must be a morphism

        ::

            sage: PS.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: P1.<u,v> = ProjectiveSpace(QQ, 1)
            sage: Y = P1.subscheme([u-v])
            sage: H = End(PS)
            sage: f = H([x^2, y^2, z^2])
            sage: Y._forward_image(f)
            Traceback (most recent call last):
            ...
            TypeError: subscheme must be in ambient space of domain of map
        """
        dom = f.domain()
        codom = f.codomain()
        if check:
            if not f.is_morphism():
                raise TypeError("map must be a morphism")
            if self.ambient_space() != dom:
                raise TypeError(
                    "subscheme must be in ambient space of domain of map")
        CR_dom = dom.coordinate_ring()
        CR_codom = codom.coordinate_ring()
        n = CR_dom.ngens()
        m = CR_codom.ngens()
        #can't call eliminate if the base ring is polynomial so we do it ourselves
        #with a lex ordering
        R = PolynomialRing(f.base_ring(), n + m, 'tempvar', order='lex')
        Rvars = R.gens()[0:n]
        phi = CR_dom.hom(Rvars, R)
        zero = n * [0]
        psi = R.hom(zero + list(CR_codom.gens()), CR_codom)
        #set up ideal
        L = R.ideal([phi(t) for t in self.defining_polynomials()] +
                    [R.gen(n + i) - phi(f[i]) for i in range(m)])
        G = L.groebner_basis()  #eliminate
        newL = []
        #get only the elimination ideal portion
        for i in range(len(G) - 1, 0, -1):
            v = G[i].variables()
            if all(Rvars[j] not in v for j in range(n)):
                newL.append(psi(G[i]))
        return (codom.subscheme(newL))
    def Chow_form(self):
        r"""
        Returns the Chow form associated to this subscheme.

        For a `k`-dimensional subvariety of `\mathbb{P}^N` of degree `D`.
        The `(N-k-1)`-dimensional projective linear subspaces of `\mathbb{P}^N`
        meeting `X` form a hypersurface in the Grassmannian `G(N-k-1,N)`.
        The homogeneous form of degree `D` defining this hypersurface in Plucker
        coordinates is called the Chow form of `X`.

        The base ring needs to be a number field, finite field, or `\QQbar`.

        ALGORITHM:

        For a `k`-dimension subscheme `X` consider the `k+1` linear forms
        `l_i = u_{i0}x_0 + \cdots + u_{in}x_n`. Let `J` be the ideal in the
        polynomial ring `K[x_i,u_{ij}]` defined by the equations of `X` and the `l_i`.
        Let `J'` be the saturation of `J` with respect to the irrelevant ideal of
        the ambient projective space of `X`. The elimination ideal `I = J' \cap K[u_{ij}]`
        is a principal ideal, let `R` be its generator. The Chow form is obtained by
        writing `R` as a polynomial in Plucker coordinates (i.e. bracket polynomials).
        [DalbecSturmfels]_.

        OUTPUT: a homogeneous polynomial.

        REFERENCES:

        .. [DalbecSturmfels] J. Dalbec and B. Sturmfels. Invariant methods in discrete and computational geometry,
           chapter Introduction to Chow forms, pages 37-58. Springer Netherlands, 1994.

        EXAMPLES::

            sage: P.<x0,x1,x2,x3> = ProjectiveSpace(GF(17), 3)
            sage: X = P.subscheme([x3+x1,x2-x0,x2-x3])
            sage: X.Chow_form()
            t0 - t1 + t2 + t3

        ::

            sage: P.<x0,x1,x2,x3> = ProjectiveSpace(QQ,3)
            sage: X = P.subscheme([x3^2 -101*x1^2 - 3*x2*x0])
            sage: X.Chow_form()
            t0^2 - 101*t2^2 - 3*t1*t3

        ::

            sage: P.<x0,x1,x2,x3>=ProjectiveSpace(QQ,3)
            sage: X = P.subscheme([x0*x2-x1^2, x0*x3-x1*x2, x1*x3-x2^2])
            sage: Ch = X.Chow_form(); Ch
            t2^3 + 2*t2^2*t3 + t2*t3^2 - 3*t1*t2*t4 - t1*t3*t4 + t0*t4^2 + t1^2*t5
            sage: Y = P.subscheme_from_Chow_form(Ch, 1); Y
            Closed subscheme of Projective Space of dimension 3 over Rational Field
            defined by:
              x2^2*x3 - x1*x3^2,
              -x2^3 + x0*x3^2,
              -x2^2*x3 + x1*x3^2,
              x1*x2*x3 - x0*x3^2,
              3*x1*x2^2 - 3*x0*x2*x3,
              -2*x1^2*x3 + 2*x0*x2*x3,
              -3*x1^2*x2 + 3*x0*x1*x3,
              x1^3 - x0^2*x3,
              x2^3 - x1*x2*x3,
              -3*x1*x2^2 + 2*x1^2*x3 + x0*x2*x3,
              2*x0*x2^2 - 2*x0*x1*x3,
              3*x1^2*x2 - 2*x0*x2^2 - x0*x1*x3,
              -x0*x1*x2 + x0^2*x3,
              -x0*x1^2 + x0^2*x2,
              -x1^3 + x0*x1*x2,
              x0*x1^2 - x0^2*x2
            sage: I = Y.defining_ideal()
            sage: I.saturation(I.ring().ideal(list(I.ring().gens())))[0]
            Ideal (x2^2 - x1*x3, x1*x2 - x0*x3, x1^2 - x0*x2) of Multivariate
            Polynomial Ring in x0, x1, x2, x3 over Rational Field
        """
        I = self.defining_ideal()
        P = self.ambient_space()
        R = P.coordinate_ring()
        N = P.dimension() + 1
        d = self.dimension()
        # create the ring for the generic linear hyperplanes
        # u0x0 + u1x1 + ...
        SS = PolynomialRing(R.base_ring(), 'u', N * (d + 1), order='lex')
        vars = SS.variable_names() + R.variable_names()
        S = PolynomialRing(R.base_ring(), vars, order='lex')
        n = S.ngens()
        newcoords = [S.gen(n - N + t) for t in range(N)]
        # map the generators of the subscheme into the ring with the hyperplane variables
        phi = R.hom(newcoords, S)
        phi(self.defining_polynomials()[0])
        # create the dim(X)+1 linear hyperplanes
        l = []
        for i in range(d + 1):
            t = 0
            for j in range(N):
                t += S.gen(N * i + j) * newcoords[j]
            l.append(t)
        # intersect the hyperplanes with X
        J = phi(I) + S.ideal(l)
        # saturate the ideal with respect to the irrelevant ideal
        J2 = J.saturation(S.ideal([phi(u) for u in R.gens()]))[0]
        # eliminate the original variables to be left with the hyperplane coefficients 'u'
        E = J2.elimination_ideal(newcoords)
        # create the plucker coordinates
        D = binomial(N, N - d - 1)  #number of plucker coordinates
        tvars = [str('t') + str(i) for i in range(D)]  #plucker coordinates
        T = PolynomialRing(R.base_ring(),
                           tvars + list(S.variable_names()),
                           order='lex')
        L = []
        coeffs = [
            T.gen(i) for i in range(0 + len(tvars),
                                    N * (d + 1) + len(tvars))
        ]
        M = matrix(T, d + 1, N, coeffs)
        i = 0
        for c in M.minors(d + 1):
            L.append(T.gen(i) - c)
            i += 1
        # create the ideal that we can use for eliminating to get a polynomial
        # in the plucker coordinates (brackets)
        br = T.ideal(L)
        # create a mapping into a polynomial ring over the plucker coordinates
        # and the hyperplane coefficients
        psi = S.hom(coeffs + [0 for _ in range(N)], T)
        E2 = T.ideal([psi(u) for u in E.gens()] + br)
        # eliminate the hyperplane coefficients
        CH = E2.elimination_ideal(coeffs)
        # CH should be a principal ideal, but because of the relations among
        # the plucker coordinates, the elimination will probably have several generators

        # get the relations among the plucker coordinates
        rel = br.elimination_ideal(coeffs)
        # reduce CH with respect to the relations
        reduced = []
        for f in CH.gens():
            reduced.append(f.reduce(rel))
        # find the principal generator

        # polynomial ring in just the plucker coordinates
        T2 = PolynomialRing(R.base_ring(), tvars)
        alp = T.hom(tvars + (N * (d + 1) + N) * [0], T2)
        # get the degrees of the reduced generators of CH
        degs = [u.degree() for u in reduced]
        mind = max(degs)
        # need the smallest degree form that did not reduce to 0
        for d in degs:
            if d < mind and d > 0:
                mind = d
        ind = degs.index(mind)
        CF = reduced[ind]  #this should be the Chow form of X
        # check that it is correct (i.e., it is a principal generator for CH + the relations)
        rel2 = rel + [CF]
        assert all(f in rel2
                   for f in CH.gens()), "did not find a principal generator"
        return alp(CF)
Example #5
0
    def segre_embedding(self, PP=None):
        r"""
        Return the Segre embedding of this subscheme into the appropriate projective
        space.

        INPUT:

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

        OUTPUT:

        Hom from this subscheme to the appropriate subscheme of projective space

        EXAMPLES::

            sage: X.<x,y,z,w,u,v> = ProductProjectiveSpaces([2,2], QQ)
            sage: P = ProjectiveSpace(QQ,8,'t')
            sage: L = (-w - v)*x + (-w*y - u*z)
            sage: Q = (-u*w - v^2)*x^2 + ((-w^2 - u*w + (-u*v - u^2))*y + (-w^2 - u*v)*z)*x + \
            ((-w^2 - u*w - u^2)*y^2 + (-u*w - v^2)*z*y + (-w^2 + (-v - u)*w)*z^2)
            sage: W = X.subscheme([L,Q])
            sage: phi = W.segre_embedding(P)
            sage: phi.codomain().ambient_space() == P
            True

        ::

            sage: PP.<x,y,u,v,s,t> = ProductProjectiveSpaces([1,1,1], CC)
            sage: PP.subscheme([]).segre_embedding()
            Scheme morphism:
              From: Closed subscheme of Product of projective spaces P^1 x P^1 x P^1
            over Complex Field with 53 bits of precision defined by:
              (no polynomials)
              To:   Closed subscheme of Projective Space of dimension 7 over Complex
            Field with 53 bits of precision defined by:
              -u5*u6 + u4*u7,
              -u3*u6 + u2*u7,
              -u3*u4 + u2*u5,
              -u3*u5 + u1*u7,
              -u3*u4 + u1*u6,
              -u3*u4 + u0*u7,
              -u2*u4 + u0*u6,
              -u1*u4 + u0*u5,
              -u1*u2 + u0*u3
              Defn: Defined by sending (x : y , u : v , s : t) to
                    (x*u*s : x*u*t : x*v*s : x*v*t : y*u*s : y*u*t : y*v*s : y*v*t).

        ::

            sage: PP.<x,y,z,u,v,s,t> = ProductProjectiveSpaces([2,1,1], ZZ)
            sage: PP.subscheme([x^3, u-v, s^2-t^2]).segre_embedding()
            Scheme morphism:
              From: Closed subscheme of Product of projective spaces P^2 x P^1 x P^1
            over Integer Ring defined by:
              x^3,
              u - v,
              s^2 - t^2
              To:   Closed subscheme of Projective Space of dimension 11 over
            Integer Ring defined by:
              u10^2 - u11^2,
              u9 - u11,
              u8 - u10,
              -u7*u10 + u6*u11,
              u6*u10 - u7*u11,
              u6^2 - u7^2,
              u5 - u7,
              u4 - u6,
              u3^3,
              -u3*u10 + u2*u11,
              u2*u10 - u3*u11,
              -u3*u6 + u2*u7,
              u2*u6 - u3*u7,
              u2*u3^2,
              u2^2 - u3^2,
              u1 - u3,
              u0 - u2
              Defn: Defined by sending (x : y : z , u : v , s : t) to
                    (x*u*s : x*u*t : x*v*s : x*v*t : y*u*s : y*u*t : y*v*s : y*v*t :
            z*u*s : z*u*t : z*v*s : z*v*t).
        """
        AS = self.ambient_space()
        CR = AS.coordinate_ring()
        N = AS.dimension_relative_components()
        M = prod([n + 1 for n in N]) - 1

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

        #set-up the elimination for the segre embedding
        mapping = []
        k = AS.ngens()
        index = AS.num_components() * [0]
        for count in range(M + 1):
            mapping.append(
                R.gen(k + count) -
                prod([CR(AS[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()[:AS.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()[AS.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 = AS.num_components() * [0]
        for count in range(M + 1):
            mapping.append(
                prod([CR(AS[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
Example #6
0
    def homogenize(self,n,newvar='h'):
        r"""
        Return the homogenization of ``self``. If ``self.domain()`` is a subscheme, the domain of
        the homogenized map is the projective embedding of ``self.domain()``

        INPUT:

        - ``newvar`` -- the name of the homogenization variable (only used when ``self.domain()`` is affine space)

        - ``n`` -- the n-th projective embedding into projective space

        OUTPUT:

        - :class:`SchemMorphism_polynomial_projective_space`

        EXAMPLES::

            sage: A.<x,y>=AffineSpace(ZZ,2)
            sage: H=Hom(A,A)
            sage: f=H([(x^2-2)/x^5,y^2])
            sage: f.homogenize(2,'z')
            Scheme endomorphism of Projective Space of dimension 2 over Integer Ring
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x^2*z^5 - 2*z^7 : x^5*y^2 : x^5*z^2)

        ::

            sage: A.<x,y>=AffineSpace(CC,2)
            sage: H=Hom(A,A)
            sage: f=H([(x^2-2)/(x*y),y^2-x])
            sage: f.homogenize(0,'z')
            Scheme endomorphism of Projective Space of dimension 2 over Complex
            Field with 53 bits of precision
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x*y*z^2 : x^2*z^2 + (-2.00000000000000)*z^4 : x*y^3 - x^2*y*z)

        ::

            sage: A.<x,y>=AffineSpace(ZZ,2)
            sage: X=A.subscheme([x-y^2])
            sage: H=Hom(X,X)
            sage: f=H([9*y^2,3*y])
            sage: f.homogenize(2)
            Scheme endomorphism of Closed subscheme of Projective Space of dimension 2 over Integer Ring defined by:
              -x1^2 + x0*x2
              Defn: Defined on coordinates by sending (x0 : x1 : x2) to
                    (9*x0*x2 : 3*x1*x2 : x2^2)

        ::

            sage: R.<t>=PolynomialRing(ZZ)
            sage: A.<x,y>=AffineSpace(R,2)
            sage: H=Hom(A,A)
            sage: f=H([(x^2-2)/y,y^2-x])
            sage: f.homogenize(0,'z')
            Scheme endomorphism of Projective Space of dimension 2 over Univariate
            Polynomial Ring in t over Integer Ring
              Defn: Defined on coordinates by sending (x : y : z) to
                    (y*z^2 : x^2*z + (-2)*z^3 : y^3 - x*y*z)
        """
        A=self.domain()
        B=self.codomain()
        N=A.ambient_space().dimension_relative()
        NB=B.ambient_space().dimension_relative()
        Vars=list(A.ambient_space().variable_names())+[newvar]
        S=PolynomialRing(A.base_ring(),Vars)
        try:
            l=lcm([self[i].denominator() for i in range(N)])
        except Exception:  #no lcm
            l=prod([self[i].denominator() for i in range(N)])

        from sage.rings.polynomial.polynomial_ring import PolynomialRing_general
        from sage.rings.polynomial.multi_polynomial_ring_generic import MPolynomialRing_generic
        if self.domain().base_ring()==RealField() or self.domain().base_ring()==ComplexField():
            F=[S(((self[i]*l).numerator())._maxima_().divide(self[i].denominator())[0].sage()) for i in range(N)]
        elif isinstance(self.domain().base_ring(),(PolynomialRing_general,MPolynomialRing_generic)):
            F=[S(((self[i]*l).numerator())._maxima_().divide(self[i].denominator())[0].sage()) for i in range(N)]
        else:
            F=[S(self[i]*l) for i in range(N)]
        F.insert(n,S(l))
        d=max([F[i].degree() for i in range(N+1)])
        F=[F[i].homogenize(newvar)*S.gen(N)**(d-F[i].degree()) for i in range(N+1)]
        from sage.schemes.affine.affine_space import is_AffineSpace
        if is_AffineSpace(A)==True:
            from sage.schemes.projective.projective_space import ProjectiveSpace
            X=ProjectiveSpace(A.base_ring(),NB,Vars)
        else:
            X=A.projective_embedding(n).codomain()
            phi=S.hom(X.ambient_space().gens(),X.ambient_space().coordinate_ring())
            F=[phi(f) for f in F]
        H=Hom(X,X)
        return(H(F))
    def _forward_image(self, f, check = True):
        """
        Compute the forward image of this subscheme by the morphism ``f``.

        The forward image is computed through elimination and ``f`` must be
        a morphism for this to be well defined.
        In particular, let $X = V(h_1,\ldots, h_t)$ and define the ideal
        $I = (h_1,\ldots,h_t,y_0-f_0(\bar{x}), \ldots, y_n-f_n(\bar{x}))$.
        Then the elimination ideal $I_{n+1} = I \cap K[y_0,\ldots,y_n]$ is a homogeneous
        ideal and $self(X) = V(I_{n+1})$.

        INPUT:

        - ``f`` -- a map whose domain contains ``self``

        - ``check`` -- Boolean, if `False` no input checking is done

        OUTPUT:

         - a subscheme in the codomain of ``f``.

        EXAMPLES::

            sage: PS.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: H = End(PS)
            sage: f = H([x^2, y^2-2*z^2, z^2])
            sage: X = PS.subscheme(y-2*z)
            sage: X._forward_image(f)
            Closed subscheme of Projective Space of dimension 2 over Rational Field
            defined by:
              y - 2*z

        ::

            sage: set_verbose(None)
            sage: PS.<x,y,z,w> = ProjectiveSpace(ZZ, 3)
            sage: H = End(PS)
            sage: f = H([y^2, x^2, w^2, z^2])
            sage: X = PS.subscheme([z^2+y*w, x-w])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 3 over Integer Ring
            defined by:
              y - z,
              x*z - w^2

        ::

            sage: PS.<x,y,z,w> = ProjectiveSpace(CC, 3)
            sage: H = End(PS)
            sage: f = H([x^2 + y^2, y^2, z^2-y^2, w^2])
            sage: X = PS.subscheme([z-2*w])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 3 over Complex Field
            with 53 bits of precision defined by:
              y + z + (-4.00000000000000)*w

        ::

            sage: R.<t> = PolynomialRing(QQ)
            sage: P.<x,y,z> = ProjectiveSpace(FractionField(R), 2)
            sage: H = End(P)
            sage: f = H([x^2 + 2*y*z, t^2*y^2, z^2])
            sage: f([t^2*y-z])
            Closed subscheme of Projective Space of dimension 2 over Fraction Field
            of Univariate Polynomial Ring in t over Rational Field defined by:
              y + (-1/t^2)*z

        ::

            sage: set_verbose(-1)
            sage: PS.<x,y,z> = ProjectiveSpace(Qp(3), 2)
            sage: H = End(PS)
            sage: f = H([x^2,2*y^2,z^2])
            sage: X = PS.subscheme([2*x-y,z])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 2 over 3-adic Field
            with capped relative precision 20 defined by:
              z,
              x + (1 + 3^2 + 3^4 + 3^6 + 3^8 + 3^10 + 3^12 + 3^14 + 3^16 + 3^18 +
            O(3^20))*y

        ::

            sage: R.<y0,y1,y2,y3> = PolynomialRing(QQ)
            sage: P.<x,y,z> = ProjectiveSpace(FractionField(R), 2)
            sage: H = End(P)
            sage: f = H([y0*x^2+y1*z^2, y2*y^2+y3*z^2, z^2])
            sage: X = P.subscheme(x*z)
            sage: X._forward_image(f)
            Closed subscheme of Projective Space of dimension 2 over Fraction Field
            of Multivariate Polynomial Ring in y0, y1, y2, y3 over Rational Field
            defined by:
              x*z + (-y1)*z^2

            ::

            sage: P2.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: P5.<z0,z1,z2,z3,z4,z5> = ProjectiveSpace(QQ, 5)
            sage: H = Hom(P2, P5)
            sage: f = H([x^2,x*y,x*z,y^2,y*z,z^2]) #Veronese map
            sage: X = P2.subscheme([])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 5 over Rational Field
            defined by:
              -z4^2 + z3*z5,
              -z2*z4 + z1*z5,
              -z2*z3 + z1*z4,
              -z2^2 + z0*z5,
              -z1*z2 + z0*z4,
              -z1^2 + z0*z3

            ::

            sage: P2.<x,y,z>=ProjectiveSpace(QQ, 2)
            sage: P3.<u,v,w,t>=ProjectiveSpace(QQ, 3)
            sage: H = Hom(P2, P3)
            sage: X = P2.subscheme([x-y,x-z])
            sage: f = H([x^2,y^2,z^2,x*y])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 3 over Rational Field
            defined by:
              w - t,
              v - t,
              u - t

            ::

            sage: P1.<u,v> = ProjectiveSpace(QQ, 1)
            sage: P2.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: H = Hom(P2,P1)
            sage: f = H([x^2,y*z])
            sage: X = P2.subscheme([x-y])
            sage: f(X)
            Traceback (most recent call last):
            ...
            TypeError: map must be a morphism

            ::

            sage: PS.<x,y,z> = ProjectiveSpace(ZZ, 2)
            sage: H = End(PS)
            sage: f = H([x^3, x*y^2, x*z^2])
            sage: X = PS.subscheme([x-y])
            sage: X._forward_image(f)
            Traceback (most recent call last):
            ...
            TypeError: map must be a morphism

        ::

            sage: PS.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: P1.<u,v> = ProjectiveSpace(QQ, 1)
            sage: Y = P1.subscheme([u-v])
            sage: H = End(PS)
            sage: f = H([x^2, y^2, z^2])
            sage: Y._forward_image(f)
            Traceback (most recent call last):
            ...
            TypeError: subscheme must be in ambient space of domain of map
        """
        dom = f.domain()
        codom = f.codomain()
        if check:
            if not f.is_morphism():
                raise TypeError("map must be a morphism")
            if self.ambient_space() != dom:
                raise TypeError("subscheme must be in ambient space of domain of map")
        CR_dom = dom.coordinate_ring()
        CR_codom = codom.coordinate_ring()
        n = CR_dom.ngens()
        m = CR_codom.ngens()
        #can't call eliminate if the base ring is polynomial so we do it ourselves
        #with a lex ordering
        R = PolynomialRing(f.base_ring(), n+m, 'tempvar', order = 'lex')
        Rvars = R.gens()[0 : n]
        phi = CR_dom.hom(Rvars,R)
        zero = n*[0]
        psi = R.hom(zero + list(CR_codom.gens()),CR_codom)
        #set up ideal
        L = R.ideal([phi(t) for t in self.defining_polynomials()] + [R.gen(n+i) - phi(f[i]) for i in range(m)])
        G = L.groebner_basis() #eliminate
        newL = []
        #get only the elimination ideal portion
        for i in range (len(G)-1,0,-1):
            v = G[i].variables()
            if all([Rvars[j] not in v for j in range(n)]):
                newL.append(psi(G[i]))
        return(codom.subscheme(newL))
    def Chow_form(self):
        r"""
        Returns the Chow form associated to this subscheme.

        For a `k`-dimensional subvariety of `\mathbb{P}^N` of degree `D`.
        The `(N-k-1)`-dimensional projective linear subspaces of `\mathbb{P}^N`
        meeting `X` form a hypersurface in the Grassmannian `G(N-k-1,N)`.
        The homogeneous form of degree `D` defining this hypersurface in Plucker
        coordinates is called the Chow form of `X`.

        The base ring needs to be a number field, finite field, or `\QQbar`.

        ALGORITHM:

        For a `k`-dimension subscheme `X` consider the `k+1` linear forms
        `l_i = u_{i0}x_0 + \cdots + u_{in}x_n`. Let `J` be the ideal in the
        polynomial ring `K[x_i,u_{ij}]` defined by the equations of `X` and the `l_i`.
        Let `J'` be the saturation of `J` with respect to the irrelevant ideal of
        the ambient projective space of `X`. The elimination ideal `I = J' \cap K[u_{ij}]`
        is a principal ideal, let `R` be its generator. The Chow form is obtained by
        writing `R` as a polynomial in Plucker coordinates (i.e. bracket polynomials).
        [DalbecSturmfels]_.

        OUTPUT: a homogeneous polynomial.

        REFERENCES:

        .. [DalbecSturmfels] J. Dalbec and B. Sturmfels. Invariant methods in discrete and computational geometry,
           chapter Introduction to Chow forms, pages 37-58. Springer Netherlands, 1994.

        EXAMPLES::

            sage: P.<x0,x1,x2,x3> = ProjectiveSpace(GF(17), 3)
            sage: X = P.subscheme([x3+x1,x2-x0,x2-x3])
            sage: X.Chow_form()
            t0 - t1 + t2 + t3

        ::

            sage: P.<x0,x1,x2,x3> = ProjectiveSpace(QQ,3)
            sage: X = P.subscheme([x3^2 -101*x1^2 - 3*x2*x0])
            sage: X.Chow_form()
            t0^2 - 101*t2^2 - 3*t1*t3

        ::

            sage: P.<x0,x1,x2,x3>=ProjectiveSpace(QQ,3)
            sage: X = P.subscheme([x0*x2-x1^2, x0*x3-x1*x2, x1*x3-x2^2])
            sage: Ch = X.Chow_form(); Ch
            t2^3 + 2*t2^2*t3 + t2*t3^2 - 3*t1*t2*t4 - t1*t3*t4 + t0*t4^2 + t1^2*t5
            sage: Y = P.subscheme_from_Chow_form(Ch, 1); Y
            Closed subscheme of Projective Space of dimension 3 over Rational Field
            defined by:
              x2^2*x3 - x1*x3^2,
              -x2^3 + x0*x3^2,
              -x2^2*x3 + x1*x3^2,
              x1*x2*x3 - x0*x3^2,
              3*x1*x2^2 - 3*x0*x2*x3,
              -2*x1^2*x3 + 2*x0*x2*x3,
              -3*x1^2*x2 + 3*x0*x1*x3,
              x1^3 - x0^2*x3,
              x2^3 - x1*x2*x3,
              -3*x1*x2^2 + 2*x1^2*x3 + x0*x2*x3,
              2*x0*x2^2 - 2*x0*x1*x3,
              3*x1^2*x2 - 2*x0*x2^2 - x0*x1*x3,
              -x0*x1*x2 + x0^2*x3,
              -x0*x1^2 + x0^2*x2,
              -x1^3 + x0*x1*x2,
              x0*x1^2 - x0^2*x2
            sage: I = Y.defining_ideal()
            sage: I.saturation(I.ring().ideal(list(I.ring().gens())))[0]
            Ideal (x2^2 - x1*x3, x1*x2 - x0*x3, x1^2 - x0*x2) of Multivariate
            Polynomial Ring in x0, x1, x2, x3 over Rational Field
        """
        I = self.defining_ideal()
        P = self.ambient_space()
        R = P.coordinate_ring()
        N = P.dimension()+1
        d = self.dimension()
        #create the ring for the generic linear hyperplanes
        # u0x0 + u1x1 + ...
        SS = PolynomialRing(R.base_ring(), 'u', N*(d+1), order='lex')
        vars = SS.variable_names() + R.variable_names()
        S = PolynomialRing(R.base_ring(), vars, order='lex')
        n = S.ngens()
        newcoords = [S.gen(n-N+t) for t in range(N)]
        #map the generators of the subscheme into the ring with the hyperplane variables
        phi = R.hom(newcoords,S)
        phi(self.defining_polynomials()[0])
        #create the dim(X)+1 linear hyperplanes
        l = []
        for i in range(d+1):
            t = 0
            for j in range(N):
                t += S.gen(N*i + j)*newcoords[j]
            l.append(t)
        #intersect the hyperplanes with X
        J = phi(I) + S.ideal(l)
        #saturate the ideal with respect to the irrelevant ideal
        J2 = J.saturation(S.ideal([phi(t) for t in R.gens()]))[0]
        #eliminate the original variables to be left with the hyperplane coefficients 'u'
        E = J2.elimination_ideal(newcoords)
        #create the plucker coordinates
        D = binomial(N,N-d-1) #number of plucker coordinates
        tvars = [str('t') + str(i) for i in range(D)] #plucker coordinates
        T = PolynomialRing(R.base_ring(), tvars+list(S.variable_names()), order='lex')
        L = []
        coeffs = [T.gen(i) for i in range(0+len(tvars), N*(d+1)+len(tvars))]
        M = matrix(T,d+1,N,coeffs)
        i = 0
        for c in M.minors(d+1):
            L.append(T.gen(i)-c)
            i += 1
        #create the ideal that we can use for eliminating to get a polynomial
        #in the plucker coordinates (brackets)
        br = T.ideal(L)
        #create a mapping into a polynomial ring over the plucker coordinates
        #and the hyperplane coefficients
        psi = S.hom(coeffs + [0 for i in range(N)],T)
        E2 = T.ideal([psi(u) for u in E.gens()] +br)
        #eliminate the hyperplane coefficients
        CH = E2.elimination_ideal(coeffs)
        #CH should be a principal ideal, but because of the relations among
        #the plucker coordinates, the elimination will probably have several generators

        #get the relations among the plucker coordinates
        rel = br.elimination_ideal(coeffs)
        #reduce CH with respect to the relations
        reduced = []
        for f in CH.gens():
            reduced.append(f.reduce(rel))
        #find the principal generator

        #polynomial ring in just the plucker coordinates
        T2 = PolynomialRing(R.base_ring(), tvars)
        alp = T.hom(tvars + (N*(d+1) +N)*[0], T2)
        #get the degrees of the reduced generators of CH
        degs = [u.degree() for u in reduced]
        mind = max(degs)
        #need the smallest degree form that did not reduce to 0
        for d in degs:
            if d < mind and d >0:
                mind = d
        ind = degs.index(mind)
        CF = reduced[ind] #this should be the Chow form of X
        #check that it is correct (i.e., it is a principal generator for CH + the relations)
        rel2 = rel + [CF]
        assert all([f in rel2 for f in CH.gens()]), "did not find a principal generator"
        return(alp(CF))
Example #9
0
    def homogenize(self,n,newvar='h'):
        r"""
        Return the homogenization of ``self``. If ``self.domain()`` is a subscheme, the domain of
        the homogenized map is the projective embedding of ``self.domain()``. The domain and codomain
        can be homogenized at different coordinates: ``n[0]`` for the domain and ``n[1]`` for the codomain.

        INPUT:

        - ``newvar`` -- the name of the homogenization variable (only used when ``self.domain()`` is affine space)

        - ``n`` -- a tuple of nonnegative integers. If ``n`` is an integer, then the two values of
            the tuple are assumed to be the same.

        OUTPUT:

        - :class:`SchemMorphism_polynomial_projective_space`

        EXAMPLES::

            sage: A.<x,y>=AffineSpace(ZZ,2)
            sage: H=Hom(A,A)
            sage: f=H([(x^2-2)/x^5,y^2])
            sage: f.homogenize(2,'z')
            Scheme endomorphism of Projective Space of dimension 2 over Integer Ring
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x^2*z^5 - 2*z^7 : x^5*y^2 : x^5*z^2)

        ::

            sage: A.<x,y>=AffineSpace(CC,2)
            sage: H=Hom(A,A)
            sage: f=H([(x^2-2)/(x*y),y^2-x])
            sage: f.homogenize((2,0),'z')
            Scheme endomorphism of Projective Space of dimension 2 over Complex
            Field with 53 bits of precision
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x*y*z^2 : x^2*z^2 + (-2.00000000000000)*z^4 : x*y^3 - x^2*y*z)

        ::

            sage: A.<x,y>=AffineSpace(ZZ,2)
            sage: X=A.subscheme([x-y^2])
            sage: H=Hom(X,X)
            sage: f=H([9*y^2,3*y])
            sage: f.homogenize(2)
            Scheme endomorphism of Closed subscheme of Projective Space of dimension 2 over Integer Ring defined by:
              -x1^2 + x0*x2
              Defn: Defined on coordinates by sending (x0 : x1 : x2) to
                    (9*x0*x2 : 3*x1*x2 : x2^2)

        ::

            sage: R.<t>=PolynomialRing(ZZ)
            sage: A.<x,y>=AffineSpace(R,2)
            sage: H=Hom(A,A)
            sage: f=H([(x^2-2)/y,y^2-x])
            sage: f.homogenize((2,0),'z')
            Scheme endomorphism of Projective Space of dimension 2 over Univariate
            Polynomial Ring in t over Integer Ring
              Defn: Defined on coordinates by sending (x : y : z) to
                    (y*z^2 : x^2*z + (-2)*z^3 : y^3 - x*y*z)

        ::

            sage: A.<x>=AffineSpace(QQ,1)
            sage: H=End(A)
            sage: f=H([x^2-1])
            sage: f.homogenize((1,0),'y')
            Scheme endomorphism of Projective Space of dimension 1 over Rational
            Field
              Defn: Defined on coordinates by sending (x : y) to
                    (y^2 : x^2 - y^2)
        """
        A=self.domain()
        B=self.codomain()
        N=A.ambient_space().dimension_relative()
        NB=B.ambient_space().dimension_relative()

        #it is possible to homogenize the domain and codomain at different coordinates
        if isinstance(n,(tuple,list)):
            ind=tuple(n)
        else:
            ind=(n,n)

        #homogenize the domain
        Vars=list(A.ambient_space().variable_names())
        Vars.insert(ind[0],newvar)
        S=PolynomialRing(A.base_ring(),Vars)

        #find the denominators if a rational function
        try:
            l=lcm([self[i].denominator() for i in range(N)])
        except Exception:  #no lcm
            l=prod([self[i].denominator() for i in range(N)])

        from sage.rings.polynomial.polynomial_ring import PolynomialRing_general
        from sage.rings.polynomial.multi_polynomial_ring_generic import MPolynomialRing_generic
        if self.domain().base_ring()==RealField() or self.domain().base_ring()==ComplexField():
            F=[S(((self[i]*l).numerator())._maxima_().divide(self[i].denominator())[0].sage()) for i in range(N)]
        elif isinstance(self.domain().base_ring(),(PolynomialRing_general,MPolynomialRing_generic)):
            F=[S(((self[i]*l).numerator())._maxima_().divide(self[i].denominator())[0].sage()) for i in range(N)]
        else:
            F=[S(self[i]*l) for i in range(N)]

        #homogenize the codomain
        F.insert(ind[1],S(l))
        d=max([F[i].degree() for i in range(N+1)])
        F=[F[i].homogenize(newvar)*S.gen(N)**(d-F[i].degree()) for i in range(N+1)]
        from sage.schemes.affine.affine_space import is_AffineSpace
        if is_AffineSpace(A)==True:
            from sage.schemes.projective.projective_space import ProjectiveSpace
            X=ProjectiveSpace(A.base_ring(),NB,Vars)
        else:
            X=A.projective_embedding(ind[1]).codomain()
            phi=S.hom(X.ambient_space().gens(),X.ambient_space().coordinate_ring())
            F=[phi(f) for f in F]
        H=Hom(X,X)
        return(H(F))
Example #10
0
    def homogenize(self, n, newvar='h'):
        r"""
        Return the homogenization of ``self``. If ``self.domain()`` is a subscheme, the domain of
        the homogenized map is the projective embedding of ``self.domain()``

        INPUT:

        - ``newvar`` -- the name of the homogenization variable (only used when ``self.domain()`` is affine space)

        - ``n`` -- the n-th projective embedding into projective space

        OUTPUT:

        - :class:`SchemMorphism_polynomial_projective_space`

        EXAMPLES::

            sage: A.<x,y>=AffineSpace(ZZ,2)
            sage: H=Hom(A,A)
            sage: f=H([(x^2-2)/x^5,y^2])
            sage: f.homogenize(2,'z')
            Scheme endomorphism of Projective Space of dimension 2 over Integer Ring
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x^2*z^5 - 2*z^7 : x^5*y^2 : x^5*z^2)

        ::

            sage: A.<x,y>=AffineSpace(CC,2)
            sage: H=Hom(A,A)
            sage: f=H([(x^2-2)/(x*y),y^2-x])
            sage: f.homogenize(0,'z')
            Scheme endomorphism of Projective Space of dimension 2 over Complex
            Field with 53 bits of precision
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x*y*z^2 : x^2*z^2 + (-2.00000000000000)*z^4 : x*y^3 - x^2*y*z)

        ::

            sage: A.<x,y>=AffineSpace(ZZ,2)
            sage: X=A.subscheme([x-y^2])
            sage: H=Hom(X,X)
            sage: f=H([9*y^2,3*y])
            sage: f.homogenize(2)
            Scheme endomorphism of Closed subscheme of Projective Space of dimension 2 over Integer Ring defined by:
              -x1^2 + x0*x2
              Defn: Defined on coordinates by sending (x0 : x1 : x2) to
                    (9*x0*x2 : 3*x1*x2 : x2^2)

        ::

            sage: R.<t>=PolynomialRing(ZZ)
            sage: A.<x,y>=AffineSpace(R,2)
            sage: H=Hom(A,A)
            sage: f=H([(x^2-2)/y,y^2-x])
            sage: f.homogenize(0,'z')
            Scheme endomorphism of Projective Space of dimension 2 over Univariate
            Polynomial Ring in t over Integer Ring
              Defn: Defined on coordinates by sending (x : y : z) to
                    (y*z^2 : x^2*z + (-2)*z^3 : y^3 - x*y*z)
        """
        A = self.domain()
        B = self.codomain()
        N = A.ambient_space().dimension_relative()
        NB = B.ambient_space().dimension_relative()
        Vars = list(A.ambient_space().variable_names()) + [newvar]
        S = PolynomialRing(A.base_ring(), Vars)
        try:
            l = lcm([self[i].denominator() for i in range(N)])
        except Exception:  #no lcm
            l = prod([self[i].denominator() for i in range(N)])

        from sage.rings.polynomial.polynomial_ring import PolynomialRing_general
        from sage.rings.polynomial.multi_polynomial_ring_generic import MPolynomialRing_generic
        if self.domain().base_ring() == RealField() or self.domain().base_ring(
        ) == ComplexField():
            F = [
                S(((self[i] * l).numerator())._maxima_().divide(
                    self[i].denominator())[0].sage()) for i in range(N)
            ]
        elif isinstance(self.domain().base_ring(),
                        (PolynomialRing_general, MPolynomialRing_generic)):
            F = [
                S(((self[i] * l).numerator())._maxima_().divide(
                    self[i].denominator())[0].sage()) for i in range(N)
            ]
        else:
            F = [S(self[i] * l) for i in range(N)]
        F.insert(n, S(l))
        d = max([F[i].degree() for i in range(N + 1)])
        F = [
            F[i].homogenize(newvar) * S.gen(N)**(d - F[i].degree())
            for i in range(N + 1)
        ]
        from sage.schemes.affine.affine_space import is_AffineSpace
        if is_AffineSpace(A) == True:
            from sage.schemes.projective.projective_space import ProjectiveSpace
            X = ProjectiveSpace(A.base_ring(), NB, Vars)
        else:
            X = A.projective_embedding(n).codomain()
            phi = S.hom(X.ambient_space().gens(),
                        X.ambient_space().coordinate_ring())
            F = [phi(f) for f in F]
        H = Hom(X, X)
        return (H(F))
Example #11
0
def make_function_field(K):
    r"""
    Return the function field isomorphic to this field, an isomorphism,
    and its inverse.

    INPUT:

    - ``K`` -- a field

    OUTPUT: A triple `(F,\phi,\psi)`, where `F` is a rational function field,
    `\phi:K\to F` is a field isomorphism and `\psi` the inverse of `\phi`.

    It is assumed that `K` is either the fraction field of a polynomial ring
    over a finite field `k`, or a finite simple extension of such a field.

    In the first case, `F=k_1(x)` is a rational function field over a finite
    field `k_1`, where `k_1` as an *absolute* finite field isomorphic to `k`.
    In the second case, `F` is a finite simple extension of a rational function
    field as in the first case.

    """
    from mclf.curves.smooth_projective_curves import make_finite_field
    from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
    from sage.categories.function_fields import FunctionFields

    if hasattr(K, "modulus") or hasattr(K, "polynomial"):
        # we hope that K is a simple finite extension of a field which is
        # isomorphic to a rational function field
        K_base = K.base_field()
        F_base, phi_base, psi_base = make_function_field(K_base)
        if hasattr(K, "modulus"):
            G = K.modulus()
        else:
            G = K.polynomial()
        R = G.parent()
        R_new = PolynomialRing(F_base, R.variable_name())
        G_new = R_new([phi_base(c) for c in G.list()])
        assert G_new.is_irreducible(), "G must be irreducible!"
        # F = F_base.extension(G_new, R.variable_name())
        F = F_base.extension(G_new, 'y')
        # phi0 = R.hom(F.gen(), F)
        # to construct phi:K=K_0[x]/(G) --> F=F_0[y]/(G),
        # we first 'map' from K to K_0[x]
        phi = K.hom(R.gen(), R, check=False)
        # then from K_0[x] to F_0[y]
        psi = R.hom(phi_base, R_new)
        # then from F_0[y] to F = F_0[y]/(G)
        phi = phi.post_compose(psi.post_compose(R_new.hom(F.gen(), F)))
        psi = F.hom(K.gen(), psi_base)
        return F, phi, psi
    else:
        # we hope that K is isomorphic to a rational function field over a
        # finite field
        if K in FunctionFields():
            # K is already a function field
            k = K.constant_base_field()
            k_new, phi_base, psi_base = make_finite_field(k)
            F = FunctionField(k_new, K.variable_name())
            phi = K.hom(F.gen(), phi_base)
            psi = F.hom(K.gen(), psi_base)
            return F, phi, psi
        elif hasattr(K, "function_field"):
            F1 = K.function_field()
            phi1 = F1.coerce_map_from(K)
            psi1 = F1.hom(K.gen())
            F, phi2, psi2 = make_function_field(F1)
            phi = phi1.post_compose(phi2)
            psi = psi2.post_compose(psi1)
            return F, phi, psi
        else:
            raise NotImplementedError