Пример #1
0
    def __init__(self, poly, ambient=None):
        """
        Return the affine hypersurface in the space ambient
        defined by the polynomial poly.

        If ambient is not given, it will be constructed based on
        poly.

        EXAMPLES::

            sage: A.<x, y, z> = AffineSpace(ZZ, 3)
            sage: AffineHypersurface(x*y-z^3, A)
            Affine hypersurface defined by -z^3 + x*y in Affine Space of dimension 3 over Integer Ring

        ::

            sage: A.<x, y, z> = QQ[]
            sage: AffineHypersurface(x*y-z^3)
            Affine hypersurface defined by -z^3 + x*y in Affine Space of dimension 3 over Rational Field

        TESTS::

            sage: H = AffineHypersurface(x*y-z^3)
            sage: H == loads(dumps(H))
            True
        """
        if not is_MPolynomial(poly):
            raise TypeError, "Defining polynomial (= %s) must be a multivariate polynomial" % poly
        if ambient == None:
            R = poly.parent()
            from sage.schemes.affine.affine_space import AffineSpace
            ambient = AffineSpace(R.base_ring(), R.ngens())
            ambient._coordinate_ring = R
        AlgebraicScheme_subscheme_affine.__init__(self, ambient, [poly])
Пример #2
0
    def __init__(self, poly, ambient=None):
        """
        Return the affine hypersurface in the space ambient
        defined by the polynomial poly.

        If ambient is not given, it will be constructed based on
        poly.

        EXAMPLES::

            sage: A.<x, y, z> = AffineSpace(ZZ, 3)
            sage: AffineHypersurface(x*y-z^3, A)
            Affine hypersurface defined by -z^3 + x*y in Affine Space of dimension 3 over Integer Ring

        ::

            sage: A.<x, y, z> = QQ[]
            sage: AffineHypersurface(x*y-z^3)
            Affine hypersurface defined by -z^3 + x*y in Affine Space of dimension 3 over Rational Field

        TESTS::

            sage: H = AffineHypersurface(x*y-z^3)
            sage: H == loads(dumps(H))
            True
        """
        if not is_MPolynomial(poly):
            raise TypeError, "Defining polynomial (= %s) must be a multivariate polynomial"%poly
        if ambient == None:
            R = poly.parent()
            from sage.schemes.affine.affine_space import AffineSpace
            ambient = AffineSpace(R.base_ring(), R.ngens())
            ambient._coordinate_ring = R
        AlgebraicScheme_subscheme_affine.__init__(self, ambient, [poly])
Пример #3
0
    def affine_patch(self, i):
        r"""
        Return the `i^{th}` affine patch of this projective space.
        This is an ambient affine space `\mathbb{A}^n_R,` where
        `R` is the base ring of self, whose "projective embedding"
        map is `1` in the `i^{th}` factor.

        INPUT:

        - ``i`` -- integer between 0 and dimension of self, inclusive.

        OUTPUT:

        - An ambient affine space with fixed projective_embedding map.

        EXAMPLES::

            sage: PP = ProjectiveSpace(5) / QQ
            sage: AA = PP.affine_patch(2)
            sage: AA
            Affine Space of dimension 5 over Rational Field
            sage: AA.projective_embedding()
            Scheme morphism:
              From: Affine Space of dimension 5 over Rational Field
              To:   Projective Space of dimension 5 over Rational Field
              Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to
                    (x0 : x1 : 1 : x2 : x3 : x4)
            sage: AA.projective_embedding(0)
            Scheme morphism:
              From: Affine Space of dimension 5 over Rational Field
              To:   Projective Space of dimension 5 over Rational Field
              Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to
                    (1 : x0 : x1 : x2 : x3 : x4)
        """
        i = int(i)  # implicit type checking
        n = self.dimension_relative()
        if i < 0 or i > n:
            raise ValueError("Argument i (= %s) must be between 0 and %s." %
                             (i, n))
        try:
            return self.__affine_patches[i]
        except AttributeError:
            self.__affine_patches = {}
        except KeyError:
            pass
        from sage.schemes.affine.affine_space import AffineSpace
        AA = AffineSpace(n, self.base_ring(), names='x')
        AA._default_embedding_index = i
        phi = AA.projective_embedding(i, self)
        self.__affine_patches[i] = AA
        return AA
Пример #4
0
    def affine_patch(self, i):
        r"""
        Return the `i^{th}` affine patch of this projective space.
        This is an ambient affine space `\mathbb{A}^n_R,` where
        `R` is the base ring of self, whose "projective embedding"
        map is `1` in the `i^{th}` factor.

        INPUT:

        - ``i`` -- integer between 0 and dimension of self, inclusive.

        OUTPUT:

        - An ambient affine space with fixed projective_embedding map.

        EXAMPLES::

            sage: PP = ProjectiveSpace(5) / QQ
            sage: AA = PP.affine_patch(2)
            sage: AA
            Affine Space of dimension 5 over Rational Field
            sage: AA.projective_embedding()
            Scheme morphism:
              From: Affine Space of dimension 5 over Rational Field
              To:   Projective Space of dimension 5 over Rational Field
              Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to
                    (x0 : x1 : 1 : x2 : x3 : x4)
            sage: AA.projective_embedding(0)
            Scheme morphism:
              From: Affine Space of dimension 5 over Rational Field
              To:   Projective Space of dimension 5 over Rational Field
              Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to
                    (1 : x0 : x1 : x2 : x3 : x4)
        """
        i = int(i)   # implicit type checking
        n = self.dimension_relative()
        if i < 0 or i > n:
            raise ValueError("Argument i (= %s) must be between 0 and %s."%(i, n))
        try:
            return self.__affine_patches[i]
        except AttributeError:
            self.__affine_patches = {}
        except KeyError:
            pass
        from sage.schemes.affine.affine_space import AffineSpace
        AA = AffineSpace(n, self.base_ring(), names='x')
        AA._default_embedding_index = i
        phi = AA.projective_embedding(i, self)
        self.__affine_patches[i] = AA
        return AA
Пример #5
0
    def affine_algebraic_patch(self, cone=None, names=None):
        r"""
        Return the affine patch corresponding to ``cone`` as an affine
        algebraic scheme.

        INPUT:

        - ``cone`` -- a :class:`Cone
          <sage.geometry.cone.ConvexRationalPolyhedralCone>` `\sigma`
          of the fan. It can be omitted for an affine toric variety,
          in which case the single generating cone is used.

        OUTPUT:

        An :class:`affine algebraic subscheme
        <sage.schemes.affine.affine_subscheme.AlgebraicScheme_subscheme_affine>`
        corresponding to the patch `\mathop{Spec}(\sigma^\vee \cap M)`
        associated to the cone `\sigma`.

        See also :meth:`affine_patch`, which expresses the patches as
        subvarieties of affine toric varieties instead.

        REFERENCES:

        ..

            David A. Cox, "The Homogeneous Coordinate Ring of a Toric
            Variety", Lemma 2.2.
            :arxiv:`alg-geom/9210008v2`

        EXAMPLES::

            sage: P2.<x,y,z> = toric_varieties.P2()
            sage: cone = P2.fan().generating_cone(0)
            sage: V = P2.subscheme(x^3+y^3+z^3)
            sage: V.affine_algebraic_patch(cone)
            Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:
              z0^3 + z1^3 + 1

            sage: cone = Cone([(0,1),(2,1)])
            sage: A2Z2.<x,y> = AffineToricVariety(cone)
            sage: A2Z2.affine_algebraic_patch()
            Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:
              -z0*z1 + z2^2
            sage: V = A2Z2.subscheme(x^2+y^2-1)
            sage: patch = V.affine_algebraic_patch();  patch
            Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:
              -z0*z1 + z2^2,
              z0 + z1 - 1
            sage: nbhd_patch = V.neighborhood([1,0]).affine_algebraic_patch();  nbhd_patch
            Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:
              -z0*z1 + z2^2,
              z0 + z1 - 1
            sage: nbhd_patch.embedding_center()
            (0, 1, 0)

        Here we got two defining equations. The first one describes
        the singularity of the ambient space and the second is the
        pull-back of `x^2+y^2-1` ::

            sage: lp = LatticePolytope([(1,0,0),(1,1,0),(1,1,1),(1,0,1),(-2,-1,-1)],
            ....:                      lattice=ToricLattice(3))
            sage: X.<x,y,u,v,t> = CPRFanoToricVariety(Delta_polar=lp)
            sage: Y = X.subscheme(x*v+y*u+t)
            sage: cone = Cone([(1,0,0),(1,1,0),(1,1,1),(1,0,1)])
            sage: Y.affine_algebraic_patch(cone)
            Closed subscheme of Affine Space of dimension 4 over Rational Field defined by:
              z0*z2 - z1*z3,
              z1 + z3 + 1
        """
        from sage.modules.free_module_element import vector
        from sage.misc.misc_c import prod
        ambient = self.ambient_space()
        fan = ambient.fan()
        if cone is None:
            assert ambient.is_affine()
            cone = fan.generating_cone(0)
        else:
            cone = fan.embed(cone)
        # R/I = C[sigma^dual cap M]
        R, I, dualcone = ambient._semigroup_ring(cone, names)

        # inhomogenize the Cox homogeneous polynomial with respect to the given cone
        inhomogenize = dict((ambient.coordinate_ring().gen(i), 1)
                            for i in range(0, fan.nrays())
                            if i not in cone.ambient_ray_indices())
        polynomials = [
            p.subs(inhomogenize) for p in self.defining_polynomials()
        ]

        # map the monomial x^{D_m} to m, see reference.
        n_rho_matrix = cone.rays().matrix()

        def pullback_polynomial(p):
            result = R.zero()
            for coefficient, monomial in p:
                exponent = monomial.exponents()[0]
                exponent = [exponent[i] for i in cone.ambient_ray_indices()]
                exponent = vector(ZZ, exponent)
                m = n_rho_matrix.solve_right(exponent)
                assert all(x in ZZ for x in m), \
                    'The polynomial '+str(p)+' does not define a ZZ-divisor!'
                m_coeffs = dualcone.Hilbert_coefficients(m)
                result += coefficient * prod(
                    R.gen(i)**m_coeffs[i] for i in range(0, R.ngens()))
            return result

        # construct the affine algebraic scheme to use as patch
        polynomials = [pullback_polynomial(_) for _ in polynomials]
        from sage.schemes.affine.affine_space import AffineSpace
        patch_cover = AffineSpace(R)
        polynomials = list(I.gens()) + polynomials
        polynomials = [x for x in polynomials if not x.is_zero()]
        patch = patch_cover.subscheme(polynomials)

        # TODO: If the cone is not smooth, then the coordinate_ring()
        # of the affine toric variety is wrong; it should be the
        # G-invariant part. So we can't construct the embedding
        # morphism in that case.
        if cone.is_smooth():
            x = ambient.coordinate_ring().gens()
            phi = []
            for i in range(0, fan.nrays()):
                if i in cone.ambient_ray_indices():
                    phi.append(pullback_polynomial(x[i]))
                else:
                    phi.append(1)
            patch._embedding_morphism = patch.hom(phi, self)
        else:
            patch._embedding_morphism = (
                NotImplementedError,
                'I only know how to construct embedding morphisms for smooth patches'
            )

        try:
            point = self.embedding_center()
        except AttributeError:
            return patch

        # it remains to find the preimage of point
        # map m to the monomial x^{D_m}, see reference.
        F = ambient.coordinate_ring().fraction_field()
        image = []
        for m in dualcone.Hilbert_basis():
            x_Dm = prod([F.gen(i)**(m * n) for i, n in enumerate(fan.rays())])
            image.append(x_Dm)
        patch._embedding_center = tuple(f(list(point)) for f in image)
        return patch
Пример #6
0
    def affine_patch(self, I, return_embedding=False):
        r"""
        Return the `I^{th}` affine patch of this projective space product
        where ``I`` is a multi-index.

        INPUT:

        - ``I`` -- a list or tuple of positive integers.

        - ``return_embedding`` -- Boolean, if true the projective embedding is also returned.

        OUTPUT:

        - An affine space.

        - An embedding into a product of projective spaces (optional).

        EXAMPLES::

            sage: PP = ProductProjectiveSpaces([2, 2, 2], ZZ, 'x')
            sage: phi = PP.affine_patch([0, 1, 2], True)
            sage: phi.domain()
            Affine Space of dimension 6 over Integer Ring
            sage: phi
            Scheme morphism:
                  From: Affine Space of dimension 6 over Integer Ring
                  To:   Product of projective spaces P^2 x P^2 x P^2 over Integer Ring
                  Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4, x5) to
                        (1 : x0 : x1 , x2 : 1 : x3 , x4 : x5 : 1)
        """
        if not isinstance(I, (list, tuple)):
            raise TypeError(
                'the argument I=%s must be a list or tuple of positive integers'
                % I)
        PP = self.ambient_space()
        N = PP._dims
        if len(I) != len(N):
            raise ValueError('the argument I=%s must have %s entries' %
                             (I, len(N)))
        I = tuple([int(i) for i in I])  # implicit type checking
        for i in range(len(I)):
            if I[i] < 0 or I[i] > N[i]:
                raise ValueError(
                    "argument i (= %s) must be between 0 and %s." %
                    (I[i], N[i]))
        try:
            if return_embedding:
                return self.__affine_patches[I][1]
            else:
                return self.__affine_patches[I][0]
        except AttributeError:
            self.__affine_patches = {}
        except KeyError:
            pass
        from sage.schemes.affine.affine_space import AffineSpace
        AA = AffineSpace(PP.base_ring(), sum(N), 'x')
        v = list(AA.gens())
        index = 0
        for i in range(len(I)):
            v.insert(index + I[i], 1)
            index += N[i] + 1
        phi = AA.hom(v, self)
        self.__affine_patches.update({I: (AA, phi)})
        if return_embedding:
            return phi
        else:
            return AA
Пример #7
0
    def affine_patch(self, i, AA=None):
        r"""
        Return the `i^{th}` affine patch of this projective space.
        This is an ambient affine space `\mathbb{A}^n_R,` where
        `R` is the base ring of self, whose "projective embedding"
        map is `1` in the `i^{th}` factor.

        INPUT:

        - ``i`` -- integer between 0 and dimension of self, inclusive.

        - ``AA`` -- (default: None) ambient affine space, this is constructed
                if it is not given.

        OUTPUT:

        - An ambient affine space with fixed projective_embedding map.

        EXAMPLES::

            sage: PP = ProjectiveSpace(5) / QQ
            sage: AA = PP.affine_patch(2)
            sage: AA
            Affine Space of dimension 5 over Rational Field
            sage: AA.projective_embedding()
            Scheme morphism:
              From: Affine Space of dimension 5 over Rational Field
              To:   Projective Space of dimension 5 over Rational Field
              Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to
                    (x0 : x1 : 1 : x2 : x3 : x4)
            sage: AA.projective_embedding(0)
            Scheme morphism:
              From: Affine Space of dimension 5 over Rational Field
              To:   Projective Space of dimension 5 over Rational Field
              Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to
                    (1 : x0 : x1 : x2 : x3 : x4)

        ::

            sage: P.<x,y> = ProjectiveSpace(QQ,1)
            sage: P.affine_patch(0).projective_embedding(0).codomain() == P
            True
        """
        i = int(i)  # implicit type checking
        n = self.dimension_relative()
        if i < 0 or i > n:
            raise ValueError("Argument i (= %s) must be between 0 and %s." %
                             (i, n))
        try:
            A = self.__affine_patches[i]
            #assume that if you've passed in a new affine space you want to override
            #the existing patch
            if AA is None or A == AA:
                return (A)
        except AttributeError:
            self.__affine_patches = {}
        except KeyError:
            pass
        #if no ith patch exists, we may still be here with AA==None
        if AA == None:
            from sage.schemes.affine.affine_space import AffineSpace
            AA = AffineSpace(n, self.base_ring(), names='x')
        elif AA.dimension_relative() != n:
            raise ValueError("Affine Space must be of the dimension %s" % (n))
        AA._default_embedding_index = i
        phi = AA.projective_embedding(i, self)
        self.__affine_patches[i] = AA
        return AA
Пример #8
0
    def affine_patch(self, I, return_embedding = False):
        r"""
        Return the `I^{th}` affine patch of this projective space product
        where ``I`` is a multi-index.

        INPUT:

        - ``I`` -- a list or tuple of positive integers

        - ``return_embedding`` -- Boolean, if true the projective embedding is also returned

        OUTPUT:

        - An affine space

        - An embedding into a product of projective spaces (optional)

        EXAMPLES::

            sage: PP = ProductProjectiveSpaces([2,2,2], ZZ, 'x')
            sage: phi = PP.affine_patch([0,1,2], True)
            sage: phi.domain()
            Affine Space of dimension 6 over Integer Ring
            sage: phi
            Scheme morphism:
                  From: Affine Space of dimension 6 over Integer Ring
                  To:   Product of projective spaces P^2 x P^2 x P^2 over Integer Ring
                  Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4, x5) to
                        (1 : x0 : x1 , x2 : 1 : x3 , x4 : x5 : 1)
        """
        if not isinstance(I, (list, tuple)):
            raise TypeError('The argument I=%s must be a list or tuple of positive integers'%I)
        PP = self.ambient_space()
        N = PP._dims
        if len(I) != len(N):
            raise ValueError('The argument I=%s must have %s entries'%(I,len(N)))
        I = tuple([int(i) for i in I])   # implicit type checking
        for i in range(len(I)):
            if I[i] < 0 or I[i] > N[i]:
                raise ValueError("Argument i (= %s) must be between 0 and %s."%(I[i], N[i]))
        try:
            if return_embedding:
                return self.__affine_patches[I][1]
            else:
                return self.__affine_patches[I][0]
        except AttributeError:
            self.__affine_patches = {}
        except KeyError:
            pass
        from sage.schemes.affine.affine_space import AffineSpace
        AA = AffineSpace(PP.base_ring(),sum(N),'x')
        v = list(AA.gens())
        index = 0
        for i in range(len(I)):
            v.insert(index+I[i],1)
            index += N[i]+1
        phi = AA.hom(v,self)
        self.__affine_patches.update({I:(AA,phi)})
        if return_embedding:
            return phi
        else:
            return AA
Пример #9
0
def CyclicCover(r, f, names=None, check_smooth=True):
    r"""
    Return the cyclic cover of the projective line given by `y^r = f`, for
    a univariate polynomial `f`.

    INPUT:

    - ``r`` - the order of the cover

    - ``f`` - univariate polynomial if not given, then it defaults to 0.

    - ``names``  (default: ``["x","y"]``) - names for the
       coordinate functions

    - ``check_squarefree`` (default: ``True``) - test if
      the input defines a unramified cover of the projective line.

    .. WARNING::

        When setting ``check_smooth=False`` or using a base ring that is
        not a field, the output curves are not to be trusted. For example, the
        output of ``is_singular`` or ``is_smooth`` only tests smoothness over
        the field of fractions.

    .. NOTE::

        The words "cyclic cover" are usually used for covers of degree
        greater than two.
        We usually refer to smooth double covers of the projective line as
        "hyperelliptic curves" or "elliptic curves" if the genus is one.
        We allow such cases in this implementation, but we highly recommend
        to use the more specific constructors/classes HyperellipticCurve and
        EllipticCurve for a wider range of tools.

    EXAMPLES:

    Basic examples::

        sage: R.<x> = QQ[]
        sage: CyclicCover(2, x^5 + x + 1)
        Cyclic Cover of P^1 over Rational Field defined by y^2 = x^5 + x + 1
        sage: CyclicCover(3, x^5 + x + 1)
        Cyclic Cover of P^1 over Rational Field defined by y^3 = x^5 + x + 1
        sage: CyclicCover(5, x^5 + x + 1)
        Cyclic Cover of P^1 over Rational Field defined by y^5 = x^5 + x + 1
        sage: CyclicCover(15, x^9 + x + 1)
        Cyclic Cover of P^1 over Rational Field defined by y^15 = x^9 + x + 1

        sage: k.<a> = GF(9); R.<x> = k[]
        sage: CyclicCover(5, x^9 + x + 1)
        Cyclic Cover of P^1 over Finite Field in a of size 3^2 defined by y^5 = x^9 + x + 1
        sage: CyclicCover(15, x^9 + x + 1)
        Traceback (most recent call last):
        ...
        ValueError: As the characteristic divides the order of the cover, this model is not smooth.

    We can change the names of the variables in the output::

        sage: k.<a> = GF(9); R.<x> = k[]
        sage: CyclicCover(5, x^9 + x + 1, names = ["A","B"])
        Cyclic Cover of P^1 over Finite Field in a of size 3^2 defined by B^5 = A^9 + A + 1

    Double roots::

        sage: P.<x> = GF(7)[]
        sage: CyclicCover(2,(x^3-x+2)^2*(x^6-1))
        Traceback (most recent call last):
        ...
        ValueError: Not a smooth Cyclic Cover of P^1: singularity in the provided affine patch.

        sage: CyclicCover(2, (x^3-x+2)^2*(x^6-1), check_smooth=False)
        Cyclic Cover of P^1 over Finite Field of size 7 defined by y^2 = x^12 - 2*x^10 - 3*x^9 + x^8 + 3*x^7 + 3*x^6 + 2*x^4 + 3*x^3 - x^2 - 3*x + 3


    Input with integer coefficients creates objects with the integers
    as base ring, but only checks smoothness over `\QQ`, not over Spec(`\ZZ`).
    In other words, it is checked that the discriminant is non-zero, but it is
    not checked whether the discriminant is a unit in `\ZZ^*`.::

        sage: R.<x> = ZZ[]
        sage: CyclicCover(5,(x^3-x+2)*(x^6-1))
        Cyclic Cover of P^1 over Integer Ring defined by y^5 = x^9 - x^7 + 2*x^6 - x^3 + x - 2


    """
    if not is_Polynomial(f):
        raise TypeError("Arguments f (= %s) must be a polynomial" % (f,))
    P = f.parent()
    f = P(f)
    if check_smooth:
        if P(r) == 0:
            raise ValueError(
                "As the characteristic divides the order of the cover, "
                "this model is not smooth."
            )

        try:
            smooth = f.is_squarefree()
        except NotImplementedError as err:
            raise NotImplementedError(
                str(err) + "Use " "check_smooth=False to skip this check."
            )
        if not smooth:
            raise ValueError(
                "Not a smooth Cyclic Cover of P^1: "
                "singularity in the provided affine patch."
            )
    R = P.base_ring()
    if names is None:
        names = ["x", "y"]
    A2 = AffineSpace(2, R, names=names)

    if is_FiniteField(R):
        return CyclicCover_finite_field(A2, r, f, names=names)
    else:
        return CyclicCover_generic(A2, r, f, names=names)
Пример #10
0
def affine_minimal(vp, return_transformation=False, D=None, quick=False):
    r"""
    Determine if given map is affine minimal.

    Given vp a scheme morphism on the projective line over the rationals,
    this procedure determines if `\phi` is minimal. In particular, it determines
    if the map is affine minimal, which is enough to decide if it is minimal
    or not. See Proposition 2.10 in [Bruin-Molnar]_.

    INPUT:

    - ``vp`` -- dynamical system on the projective line

    - ``D`` -- a list of primes, in case one only wants to check minimality
      at those specific primes

    - ``return_transformation`` -- (default: ``False``) boolean; this
      signals a return of the `PGL_2` transformation to conjugate
      this map to the calculated models

    - ``quick`` -- a boolean value. If true the algorithm terminates once
      algorithm determines F/G is not minimal, otherwise algorithm only
      terminates once a minimal model has been found

    OUTPUT:

    - ``newvp`` -- dynamical system on the projective line

    - ``conj`` -- linear fractional transformation which conjugates ``vp`` to ``newvp``

    EXAMPLES::

        sage: PS.<X,Y> = ProjectiveSpace(QQ, 1)
        sage: vp = DynamicalSystem_projective([X^2 + 9*Y^2, X*Y])
        sage: from sage.dynamics.arithmetic_dynamics.endPN_minimal_model import affine_minimal
        sage: affine_minimal(vp, True)
        (
        Dynamical System of Projective Space of dimension 1 over Rational Field
              Defn: Defined on coordinates by sending (X : Y) to
                    (X^2 + Y^2 : X*Y)
        ,
        [3 0]
        [0 1]
        )
    """
    from sage.dynamics.arithmetic_dynamics.affine_ds import DynamicalSystem_affine
    BR = vp.domain().base_ring()
    conj = matrix(BR, 2, 2, 1)
    flag = True
    vp.normalize_coordinates()
    d = vp.degree()

    Affvp = vp.dehomogenize(1)
    R = Affvp.coordinate_ring()
    if R.is_field():
        #want the polynomial ring not the fraction field
        R = R.ring()
    F = R(Affvp[0].numerator())
    G = R(Affvp[0].denominator())
    if R(G.degree()) == 0 or R(F.degree()) == 0:
        raise TypeError(
            "affine minimality is only considered for maps not of the form f or 1/f for a polynomial f"
        )

    z = F.parent().gen(0)
    minF, minG = F, G
    #If the valuation of a prime in the resultant is small enough, we can say the
    #map is affine minimal at that prime without using the local minimality loop. See
    #Theorem 3.2.2 in [Molnar, M.Sc. thesis]
    if d % 2 == 0:
        g = d
    else:
        g = 2 * d
    Res = vp.resultant()

    #Some quantities needed for the local minimization loop, but we compute now
    #since the value is constant, so we do not wish to compute in every local loop.
    #See Theorem 3.3.3 in [Molnar, M.Sc thesis]
    H = F - z * minG
    d1 = F.degree()
    A = AffineSpace(BR, 1, H.parent().variable_name())
    ubRes = DynamicalSystem_affine([H / minG],
                                   domain=A).homogenize(1).resultant()
    #Set the primes to check minimality at, if not already prescribed
    if D is None:
        D = ZZ(Res).prime_divisors()

    #Check minimality at all primes in D. If D is all primes dividing
    #Res(minF/minG), this is enough to show whether minF/minG is minimal or not. See
    #Propositions 3.2.1 and 3.3.7 in [Molnar, M.Sc. thesis].
    for p in D:
        while True:
            if Res.valuation(p) < g:
                #The model is minimal at p
                min = True
            else:
                #The model may not be minimal at p.
                newvp, conj = Min(vp, p, ubRes, conj, all_orbits=False)
                if newvp == vp:
                    min = True
                else:
                    vp = newvp
                    Affvp = vp.dehomogenize(1)
                    min = False
            if min:
                #The model is minimal at p
                break
            elif F == Affvp[0].numerator() and G == Affvp[0].denominator():
                #The model is minimal at p
                break
            else:
                #The model is not minimal at p
                flag = False
                if quick:
                    break
        if quick and not flag:
            break

    if quick:  #only return whether the model is minimal
        return flag

    if return_transformation:
        return vp, conj
    return vp
Пример #11
0
    def __classcall_private__(cls, morphism_or_polys, domain=None):
        r"""
        Return the appropriate dynamical system on an affine scheme.

        TESTS::

            sage: A.<x> = AffineSpace(ZZ,1)
            sage: A1.<z> = AffineSpace(CC,1)
            sage: H = End(A1)
            sage: f2 = H([z^2+1])
            sage: f = DynamicalSystem_affine(f2, A)
            sage: f.domain() is A
            False

        ::

            sage: P1.<x,y> = ProjectiveSpace(QQ,1)
            sage: DynamicalSystem_affine([y, 2*x], domain=P1)
            Traceback (most recent call last):
            ...
            ValueError: "domain" must be an affine scheme
            sage: H = End(P1)
            sage: DynamicalSystem_affine(H([y, 2*x]))
            Traceback (most recent call last):
            ...
            ValueError: "domain" must be an affine scheme
        """
        if isinstance(morphism_or_polys, SchemeMorphism_polynomial):
            morphism = morphism_or_polys
            R = morphism.base_ring()
            polys = list(morphism)
            domain = morphism.domain()
            if not is_AffineSpace(domain) and not isinstance(domain, AlgebraicScheme_subscheme_affine):
                raise ValueError('"domain" must be an affine scheme')
            if domain != morphism_or_polys.codomain():
                raise ValueError('domain and codomain do not agree')
            if R not in Fields():
                return typecall(cls, polys, domain)
            if is_FiniteField(R):
                return DynamicalSystem_affine_finite_field(polys, domain)
            return DynamicalSystem_affine_field(polys, domain)
        elif isinstance(morphism_or_polys,(list, tuple)):
            polys = list(morphism_or_polys)
        else:
            polys = [morphism_or_polys]

        # We now arrange for all of our list entries to lie in the same ring
        # Fraction field case first
        fraction_field = False
        for poly in polys:
            P = poly.parent()
            if is_FractionField(P):
                fraction_field = True
                break
        if fraction_field:
            K = P.base_ring().fraction_field()
            # Replace base ring with its fraction field
            P = P.ring().change_ring(K).fraction_field()
            polys = [P(poly) for poly in polys]
        else:
            # If any of the list entries lies in a quotient ring, we try
            # to lift all entries to a common polynomial ring.
            quotient_ring = False
            for poly in polys:
                P = poly.parent()
                if is_QuotientRing(P):
                    quotient_ring = True
                    break
            if quotient_ring:
                polys = [P(poly).lift() for poly in polys]
            else:
                poly_ring = False
                for poly in polys:
                    P = poly.parent()
                    if is_PolynomialRing(P) or is_MPolynomialRing(P):
                        poly_ring = True
                        break
                if poly_ring:
                    polys = [P(poly) for poly in polys]

        if domain is None:
            f = polys[0]
            CR = f.parent()
            if CR is SR:
                raise TypeError("Symbolic Ring cannot be the base ring")
            if fraction_field:
                CR = CR.ring()
            domain = AffineSpace(CR)

        R = domain.base_ring()
        if R is SR:
            raise TypeError("Symbolic Ring cannot be the base ring")
        if not is_AffineSpace(domain) and not isinstance(domain, AlgebraicScheme_subscheme_affine):
            raise ValueError('"domain" must be an affine scheme')

        if R not in Fields():
            return typecall(cls, polys, domain)
        if is_FiniteField(R):
                return DynamicalSystem_affine_finite_field(polys, domain)
        return DynamicalSystem_affine_field(polys, domain)
Пример #12
0
    def __classcall_private__(cls, morphism_or_polys, domain=None):
        r"""
        Return the appropriate dynamical system on an affine scheme.

        TESTS::

            sage: A.<x> = AffineSpace(ZZ,1)
            sage: A1.<z> = AffineSpace(CC,1)
            sage: H = End(A1)
            sage: f2 = H([z^2+1])
            sage: f = DynamicalSystem_affine(f2, A)
            sage: f.domain() is A
            False

        ::

            sage: P1.<x,y> = ProjectiveSpace(QQ,1)
            sage: DynamicalSystem_affine([y, 2*x], domain=P1)
            Traceback (most recent call last):
            ...
            ValueError: "domain" must be an affine scheme
            sage: H = End(P1)
            sage: DynamicalSystem_affine(H([y, 2*x]))
            Traceback (most recent call last):
            ...
            ValueError: "domain" must be an affine scheme
        """
        if isinstance(morphism_or_polys, SchemeMorphism_polynomial):
            morphism = morphism_or_polys
            R = morphism.base_ring()
            polys = list(morphism)
            domain = morphism.domain()
            if not is_AffineSpace(domain) and not isinstance(
                    domain, AlgebraicScheme_subscheme_affine):
                raise ValueError('"domain" must be an affine scheme')
            if domain != morphism_or_polys.codomain():
                raise ValueError('domain and codomain do not agree')
            if R not in Fields():
                return typecall(cls, polys, domain)
            if is_FiniteField(R):
                return DynamicalSystem_affine_finite_field(polys, domain)
            return DynamicalSystem_affine_field(polys, domain)
        elif isinstance(morphism_or_polys, (list, tuple)):
            polys = list(morphism_or_polys)
        else:
            polys = [morphism_or_polys]

        # We now arrange for all of our list entries to lie in the same ring
        # Fraction field case first
        fraction_field = False
        for poly in polys:
            P = poly.parent()
            if is_FractionField(P):
                fraction_field = True
                break
        if fraction_field:
            K = P.base_ring().fraction_field()
            # Replace base ring with its fraction field
            P = P.ring().change_ring(K).fraction_field()
            polys = [P(poly) for poly in polys]
        else:
            # If any of the list entries lies in a quotient ring, we try
            # to lift all entries to a common polynomial ring.
            quotient_ring = False
            for poly in polys:
                P = poly.parent()
                if is_QuotientRing(P):
                    quotient_ring = True
                    break
            if quotient_ring:
                polys = [P(poly).lift() for poly in polys]
            else:
                poly_ring = False
                for poly in polys:
                    P = poly.parent()
                    if is_PolynomialRing(P) or is_MPolynomialRing(P):
                        poly_ring = True
                        break
                if poly_ring:
                    polys = [P(poly) for poly in polys]

        if domain is None:
            f = polys[0]
            CR = f.parent()
            if CR is SR:
                raise TypeError("Symbolic Ring cannot be the base ring")
            if fraction_field:
                CR = CR.ring()
            domain = AffineSpace(CR)

        R = domain.base_ring()
        if R is SR:
            raise TypeError("Symbolic Ring cannot be the base ring")
        if not is_AffineSpace(domain) and not isinstance(
                domain, AlgebraicScheme_subscheme_affine):
            raise ValueError('"domain" must be an affine scheme')

        if R not in Fields():
            return typecall(cls, polys, domain)
        if is_FiniteField(R):
            return DynamicalSystem_affine_finite_field(polys, domain)
        return DynamicalSystem_affine_field(polys, domain)
Пример #13
0
    def reduce_base_field(self):
        """
        Return this map defined over the field of definition of the coefficients.

        The base field of the map could be strictly larger than
        the field where all of the coefficients are defined. This function
        reduces the base field to the minimal possible. This can be done when
        the base ring is a number field, QQbar, a finite field, or algebraic
        closure of a finite field.

        OUTPUT: A scheme morphism.

        EXAMPLES::

            sage: K.<t> = GF(5^4)
            sage: A.<x> = AffineSpace(K, 1)
            sage: A2.<a,b> = AffineSpace(K, 2)
            sage: H = End(A)
            sage: H2 = Hom(A,A2)
            sage: H3 = Hom(A2,A)
            sage: f = H([x^2 + 2*(t^3 + t^2 + t + 3)])
            sage: f.reduce_base_field()
            Scheme endomorphism of Affine Space of dimension 1 over Finite Field in t2 of size 5^2
              Defn: Defined on coordinates by sending (x) to
                    (x^2 + (2*t2))
            sage: f2 = H2([x^2 + 4, 2*x])
            sage: f2.reduce_base_field()
            Scheme morphism:
              From: Affine Space of dimension 1 over Finite Field of size 5
              To:   Affine Space of dimension 2 over Finite Field of size 5
              Defn: Defined on coordinates by sending (x) to
                    (x^2 - 1, 2*x)
            sage: f3 = H3([a^2 + t*b])
            sage: f3.reduce_base_field()
            Scheme morphism:
              From: Affine Space of dimension 2 over Finite Field in t of size 5^4
              To:   Affine Space of dimension 1 over Finite Field in t of size 5^4
              Defn: Defined on coordinates by sending (a, b) to
                    (a^2 + (t)*b)

        ::

            sage: K.<v> = CyclotomicField(4)
            sage: A.<x> = AffineSpace(K, 1)
            sage: H = End(A)
            sage: f = H([x^2 + v])
            sage: g = f.reduce_base_field();g
            Scheme endomorphism of Affine Space of dimension 1 over Cyclotomic Field of order 4 and degree 2
              Defn: Defined on coordinates by sending (x) to
                (x^2 + (v))
            sage: g.base_ring() is K
            True

        ::

            sage: A.<x> = AffineSpace(QQbar, 1)
            sage: H = End(A)
            sage: f = H([(QQbar(sqrt(2))*x^2 + 1/QQbar(sqrt(3))) / (5*x)])
            sage: f.reduce_base_field()
            Scheme endomorphism of Affine Space of dimension 1 over Number Field in a with defining polynomial y^4 - 4*y^2 + 1 with a = 1.931851652578137?
              Defn: Defined on coordinates by sending (x) to
                    (((a^3 - 3*a)*x^2 + (1/3*a^2 - 2/3))/(5*x))

        ::

            sage: R.<x> = PolynomialRing(QQ)
            sage: A.<x> =AffineSpace(QQbar,1)
            sage: H = End(A)
            sage: f = H([QQbar(3^(1/3))*x^2 + QQbar(sqrt(-2))])
            sage: f.reduce_base_field()
            Scheme endomorphism of Affine Space of dimension 1 over Number
            Field in a with defining polynomial y^6 + 6*y^4 - 6*y^3 + 12*y^2 + 36*y + 17
            with a = 1.442249570307409? + 1.414213562373095?*I
              Defn: Defined on coordinates by sending (x) to
                    ((-48/269*a^5 + 27/269*a^4 - 320/269*a^3 + 468/269*a^2 - 772/269*a
                    - 1092/269)*x^2 + (48/269*a^5 - 27/269*a^4 + 320/269*a^3 - 468/269*a^2
                    + 1041/269*a + 1092/269))

        ::

            sage: R.<x> = PolynomialRing(QQ)
            sage: K.<a> = NumberField(x^3-x+1, embedding=(x^3+x+1).roots(ring=CC)[0][0])
            sage: A.<x> = AffineSpace(K,1)
            sage: A2.<u,v> = AffineSpace(K,2)
            sage: H = Hom(A, A2)
            sage: f = H([x^2 + a*x + 3, 5*x])
            sage: f.reduce_base_field()
            Scheme morphism:
                  From: Affine Space of dimension 1 over Number Field in a with
                  defining polynomial x^3 - x + 1 with a = -1.324717957244746?
                  To:   Affine Space of dimension 2 over Number Field in a with
                  defining polynomial x^3 - x + 1 with a = -1.324717957244746?
                  Defn: Defined on coordinates by sending (x) to
                        (x^2 + (a)*x + 3, 5*x)

        ::

            sage: K.<v> = QuadraticField(2)
            sage: A.<x> =AffineSpace(K,1)
            sage: H = End(A)
            sage: f = H([3*x^2 + x + 1])
            sage: f.reduce_base_field()
            Scheme endomorphism of Affine Space of dimension 1 over Rational Field
              Defn: Defined on coordinates by sending (x) to
                    (3*x^2 + x + 1)

        ::

            sage: K.<t> = GF(5^6)
            sage: A.<x> = AffineSpace(K, 1)
            sage: H = End(A)
            sage: f = H([x^2 + x*(t^3 + 2*t^2 + 4*t) + (t^5 + 3*t^4 + t^2 + 4*t)])
            sage: f.reduce_base_field()
            Scheme endomorphism of Affine Space of dimension 1 over Finite Field in t of size 5^6
              Defn: Defined on coordinates by sending (x) to
                    (x^2 + (t^3 + 2*t^2 - t)*x + (t^5 - 2*t^4 + t^2 - t))
        """
        g = self.homogenize(0).reduce_base_field().dehomogenize(0)
        from sage.schemes.affine.affine_space import AffineSpace
        new_domain = AffineSpace(g.domain().base_ring(),
                                 self.domain().dimension_relative(),
                                 self.domain().variable_names())
        new_codomain = AffineSpace(g.codomain().base_ring(),
                                   self.codomain().dimension_relative(),
                                   self.codomain().variable_names())
        R = new_domain.coordinate_ring()
        H = Hom(new_domain, new_codomain)
        if isinstance(g[0], FractionFieldElement):
            return H([R(G.numerator()) / R(G.denominator()) for G in g])
        return H([R(G) for G in g])
Пример #14
0
    def __classcall_private__(cls, morphism_or_polys, domain=None):
        r"""
        Return the appropriate dynamical system on an affine scheme.

        TESTS::

            sage: A.<x> = AffineSpace(ZZ,1)
            sage: A1.<z> = AffineSpace(CC,1)
            sage: H = End(A1)
            sage: f2 = H([z^2+1])
            sage: f = DynamicalSystem_affine(f2, A)
            sage: f.domain() is A
            False

        ::

            sage: P1.<x,y> = ProjectiveSpace(QQ,1)
            sage: DynamicalSystem_affine([y, 2*x], domain=P1)
            Traceback (most recent call last):
            ...
            ValueError: "domain" must be an affine scheme
            sage: H = End(P1)
            sage: DynamicalSystem_affine(H([y, 2*x]))
            Traceback (most recent call last):
            ...
            ValueError: "domain" must be an affine scheme

        ::

            sage: R.<x,y,z> = QQ[]
            sage: f = DynamicalSystem_affine([x+y+z, y*z])
            Traceback (most recent call last):
            ...
            ValueError: Number of polys does not match dimension of Affine Space of dimension 3 over Rational Field

        ::
            sage: A.<x,y> = AffineSpace(QQ,2)
            sage: f = DynamicalSystem_affine([CC.0*x^2, y^2], domain=A)
            Traceback (most recent call last):
            ...
            TypeError: coefficients of polynomial not in Rational Field
        """
        if isinstance(morphism_or_polys, SchemeMorphism_polynomial):
            morphism = morphism_or_polys
            R = morphism.base_ring()
            polys = list(morphism)
            domain = morphism.domain()
            if not is_AffineSpace(domain) and not isinstance(domain, AlgebraicScheme_subscheme_affine):
                raise ValueError('"domain" must be an affine scheme')
            if domain != morphism_or_polys.codomain():
                raise ValueError('domain and codomain do not agree')
            if R not in Fields():
                return typecall(cls, polys, domain)
            if is_FiniteField(R):
                return DynamicalSystem_affine_finite_field(polys, domain)
            return DynamicalSystem_affine_field(polys, domain)
        elif isinstance(morphism_or_polys,(list, tuple)):
            polys = list(morphism_or_polys)
        else:
            polys = [morphism_or_polys]

        PR = get_coercion_model().common_parent(*polys)         
        fraction_field = any(is_FractionField(poly.parent()) for poly in polys)
        if fraction_field:
            K = PR.base_ring().fraction_field()
            # Replace base ring with its fraction field
            PR = PR.ring().change_ring(K).fraction_field()
            polys = [PR(poly) for poly in polys]
        else:
            quotient_ring = any(is_QuotientRing(poly.parent()) for poly in polys)
            # If any of the list entries lies in a quotient ring, we try
            # to lift all entries to a common polynomial ring.
            if quotient_ring:
                polys = [PR(poly).lift() for poly in polys]
            else:
                polys = [PR(poly) for poly in polys]
        if domain is None:
            if PR is SR:
                raise TypeError("Symbolic Ring cannot be the base ring")
            if fraction_field:
                PR = PR.ring()
            domain = AffineSpace(PR)
        else:
            # Check if we can coerce the given polynomials over the given domain 
            PR = domain.ambient_space().coordinate_ring()
            try:
                if fraction_field:
                    PR = PR.fraction_field()
                polys = [PR(poly) for poly in polys]
            except TypeError:
                raise TypeError('coefficients of polynomial not in {}'.format(domain.base_ring()))
        if len(polys) != domain.ambient_space().coordinate_ring().ngens():
            raise ValueError('Number of polys does not match dimension of {}'.format(domain))
        R = domain.base_ring()
        if R is SR:
            raise TypeError("Symbolic Ring cannot be the base ring")
        if not is_AffineSpace(domain) and not isinstance(domain, AlgebraicScheme_subscheme_affine):
            raise ValueError('"domain" must be an affine scheme')

        if R not in Fields():
            return typecall(cls, polys, domain)
        if is_FiniteField(R):
                return DynamicalSystem_affine_finite_field(polys, domain)
        return DynamicalSystem_affine_field(polys, domain)
Пример #15
0
    def __classcall_private__(cls, morphism_or_polys, domain=None):
        r"""
        Return the appropriate dynamical system on an affine scheme.

        TESTS::

            sage: A.<x> = AffineSpace(ZZ,1)
            sage: A1.<z> = AffineSpace(CC,1)
            sage: H = End(A1)
            sage: f2 = H([z^2+1])
            sage: f = DynamicalSystem_affine(f2, A)
            sage: f.domain() is A
            False

        ::

            sage: P1.<x,y> = ProjectiveSpace(QQ,1)
            sage: DynamicalSystem_affine([y, 2*x], domain=P1)
            Traceback (most recent call last):
            ...
            ValueError: "domain" must be an affine scheme
            sage: H = End(P1)
            sage: DynamicalSystem_affine(H([y, 2*x]))
            Traceback (most recent call last):
            ...
            ValueError: "domain" must be an affine scheme

        ::

            sage: R.<x,y,z> = QQ[]
            sage: f = DynamicalSystem_affine([x+y+z, y*z])
            Traceback (most recent call last):
            ...
            ValueError: Number of polys does not match dimension of Affine Space of dimension 3 over Rational Field

        ::
            sage: A.<x,y> = AffineSpace(QQ,2)
            sage: f = DynamicalSystem_affine([CC.0*x^2, y^2], domain=A)
            Traceback (most recent call last):
            ...
            TypeError: coefficients of polynomial not in Rational Field
        """
        if isinstance(morphism_or_polys, SchemeMorphism_polynomial):
            morphism = morphism_or_polys
            R = morphism.base_ring()
            polys = list(morphism)
            domain = morphism.domain()
            if not is_AffineSpace(domain) and not isinstance(
                    domain, AlgebraicScheme_subscheme_affine):
                raise ValueError('"domain" must be an affine scheme')
            if domain != morphism_or_polys.codomain():
                raise ValueError('domain and codomain do not agree')
            if R not in Fields():
                return typecall(cls, polys, domain)
            if is_FiniteField(R):
                return DynamicalSystem_affine_finite_field(polys, domain)
            return DynamicalSystem_affine_field(polys, domain)
        elif isinstance(morphism_or_polys, (list, tuple)):
            polys = list(morphism_or_polys)
        else:
            polys = [morphism_or_polys]

        PR = get_coercion_model().common_parent(*polys)
        fraction_field = any(is_FractionField(poly.parent()) for poly in polys)
        if fraction_field:
            K = PR.base_ring().fraction_field()
            # Replace base ring with its fraction field
            PR = PR.ring().change_ring(K).fraction_field()
            polys = [PR(poly) for poly in polys]
        else:
            quotient_ring = any(
                is_QuotientRing(poly.parent()) for poly in polys)
            # If any of the list entries lies in a quotient ring, we try
            # to lift all entries to a common polynomial ring.
            if quotient_ring:
                polys = [PR(poly).lift() for poly in polys]
            else:
                polys = [PR(poly) for poly in polys]
        if domain is None:
            if PR is SR:
                raise TypeError("Symbolic Ring cannot be the base ring")
            if fraction_field:
                PR = PR.ring()
            domain = AffineSpace(PR)
        else:
            # Check if we can coerce the given polynomials over the given domain
            PR = domain.ambient_space().coordinate_ring()
            try:
                if fraction_field:
                    PR = PR.fraction_field()
                polys = [PR(poly) for poly in polys]
            except TypeError:
                raise TypeError('coefficients of polynomial not in {}'.format(
                    domain.base_ring()))
        if len(polys) != domain.ambient_space().coordinate_ring().ngens():
            raise ValueError(
                'Number of polys does not match dimension of {}'.format(
                    domain))
        R = domain.base_ring()
        if R is SR:
            raise TypeError("Symbolic Ring cannot be the base ring")
        if not is_AffineSpace(domain) and not isinstance(
                domain, AlgebraicScheme_subscheme_affine):
            raise ValueError('"domain" must be an affine scheme')

        if R not in Fields():
            return typecall(cls, polys, domain)
        if is_FiniteField(R):
            return DynamicalSystem_affine_finite_field(polys, domain)
        return DynamicalSystem_affine_field(polys, domain)
Пример #16
0
    def affine_patch(self, I, return_embedding=False):
        r"""
        Return the `I^{th}` affine patch of this projective scheme
        where 'I' is a multi-index.

        INPUT:

        - ``I`` -- a list or tuple of positive integers

        - ``return_embedding`` -- Boolean, if true the projective embedding is also returned

        OUTPUT:

        - An affine algebraic scheme

        - An embedding into a product of projective space (optional)

        EXAMPLES::

            sage: PP.<x,y,z,w,u,v> = ProductProjectiveSpaces([3,1],QQ)
            sage: W = PP.subscheme([y^2*z-x^3,z^2-w^2,u^3-v^3])
            sage: W.affine_patch([0,1],True)
            (Closed subscheme of Affine Space of dimension 4 over Rational Field defined by:
              x0^2*x1 - 1,
              x1^2 - x2^2,
              x3^3 - 1, Scheme morphism:
              From: Closed subscheme of Affine Space of dimension 4 over Rational Field defined by:
              x0^2*x1 - 1,
              x1^2 - x2^2,
              x3^3 - 1
              To:   Closed subscheme of Product of projective spaces P^3 x P^1 over Rational Field defined by:
              -x^3 + y^2*z,
              z^2 - w^2,
              u^3 - v^3
              Defn: Defined on coordinates by sending (x0, x1, x2, x3) to
                    (1 : x0 : x1 : x2 , x3 : 1))
        """
        if not isinstance(I, (list, tuple)):
            raise TypeError(
                'The argument I=%s must be a list or tuple of positive integers'
                % I)
        PP = self.ambient_space()
        N = PP.dimension_relative_components()
        if len(I) != len(N):
            raise ValueError('The argument I=%s must have %s entries' %
                             (I, len(N)))
        I = tuple([int(i) for i in I])  # implicit type checking
        for i in range(len(I)):
            if I[i] < 0 or I[i] > N[i]:
                raise ValueError(
                    "Argument i (= %s) must be between 0 and %s." %
                    (I[i], N[i]))
        #see if we've already created this affine patch
        try:
            if return_embedding:
                return self.__affine_patches[I]
            else:
                return self.__affine_patches[I][0]
        except AttributeError:
            self.__affine_patches = {}
        except KeyError:
            pass
        AA = AffineSpace(PP.base_ring(), sum(N), 'x')
        v = list(AA.gens())
        # create the projective embedding
        index = 0
        for i in range(len(I)):
            v.insert(index + I[i], 1)
            index += N[i] + 1
        phi = AA.hom(v, self)
        #find the image of the subscheme
        polys = self.defining_polynomials()
        xi = phi.defining_polynomials()
        U = AA.subscheme([f(xi) for f in polys])
        phi = U.hom(v, self)
        self.__affine_patches.update({I: (U, phi)})
        if return_embedding:
            return U, phi
        else:
            return U
Пример #17
0
    def affine_patch(self, i, AA = None):
        r"""
        Return the `i^{th}` affine patch of this projective space.
        This is an ambient affine space `\mathbb{A}^n_R,` where
        `R` is the base ring of self, whose "projective embedding"
        map is `1` in the `i^{th}` factor.

        INPUT:

        - ``i`` -- integer between 0 and dimension of self, inclusive.

        - ``AA`` -- (default: None) ambient affine space, this is constructed
                if it is not given.

        OUTPUT:

        - An ambient affine space with fixed projective_embedding map.

        EXAMPLES::

            sage: PP = ProjectiveSpace(5) / QQ
            sage: AA = PP.affine_patch(2)
            sage: AA
            Affine Space of dimension 5 over Rational Field
            sage: AA.projective_embedding()
            Scheme morphism:
              From: Affine Space of dimension 5 over Rational Field
              To:   Projective Space of dimension 5 over Rational Field
              Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to
                    (x0 : x1 : 1 : x2 : x3 : x4)
            sage: AA.projective_embedding(0)
            Scheme morphism:
              From: Affine Space of dimension 5 over Rational Field
              To:   Projective Space of dimension 5 over Rational Field
              Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to
                    (1 : x0 : x1 : x2 : x3 : x4)

        ::

            sage: P.<x,y> = ProjectiveSpace(QQ,1)
            sage: P.affine_patch(0).projective_embedding(0).codomain() == P
            True
        """
        i = int(i)   # implicit type checking
        n = self.dimension_relative()
        if i < 0 or i > n:
            raise ValueError("Argument i (= %s) must be between 0 and %s."%(i, n))
        try:
            A = self.__affine_patches[i]
            #assume that if you've passed in a new affine space you want to override
            #the existing patch
            if AA is None or A == AA:
                return(A)
        except AttributeError:
            self.__affine_patches = {}
        except KeyError:
            pass
        #if no ith patch exists, we may still be here with AA==None
        if AA == None:
            from sage.schemes.affine.affine_space import AffineSpace
            AA = AffineSpace(n, self.base_ring(), names = 'x')
        elif AA.dimension_relative() != n:
                raise ValueError("Affine Space must be of the dimension %s"%(n))
        AA._default_embedding_index = i
        phi = AA.projective_embedding(i, self)
        self.__affine_patches[i] = AA
        return AA
Пример #18
0
def BM_all_minimal(vp, return_transformation=False, D=None):
    r"""
    Determine a representative in each `SL(2,\ZZ)` orbit with minimal
    resultant.

    This function modifies the Bruin-Molnar algorithm ([BM2012]_) to solve
    in the inequalities as ``<=`` instead of ``<``. Among the list of
    solutions is all conjugations that preserve the resultant. From that
    list the `SL(2,\ZZ)` orbits are identified and one representative from
    each orbit is returned. This function assumes that the given model is
    a minimal model.

    INPUT:

    - ``vp`` -- a minimal model of a dynamical system on the projective line

    - ``return_transformation`` -- (default: ``False``) boolean; this
      signals a return of the ``PGL_2`` transformation to conjugate ``vp``
      to the calculated minimal model

    - ``D`` -- a list of primes, in case one only wants to check minimality
      at those specific primes

    OUTPUT:

    List of pairs ``[f, m]`` where ``f`` is a dynamical system and ``m`` is a
    `2 \times 2` matrix.

    EXAMPLES::

        sage: P.<x,y> = ProjectiveSpace(QQ,1)
        sage: f = DynamicalSystem([x^3 - 13^2*y^3, x*y^2])
        sage: from sage.dynamics.arithmetic_dynamics.endPN_minimal_model import BM_all_minimal
        sage: BM_all_minimal(f)
        [Dynamical System of Projective Space of dimension 1 over Rational Field
           Defn: Defined on coordinates by sending (x : y) to
                 (x^3 - 169*y^3 : x*y^2),
         Dynamical System of Projective Space of dimension 1 over Rational Field
           Defn: Defined on coordinates by sending (x : y) to
                 (13*x^3 - y^3 : x*y^2)]

    ::

        sage: P.<x,y> = ProjectiveSpace(QQ,1)
        sage: f = DynamicalSystem([x^3 - 6^2*y^3, x*y^2])
        sage: from sage.dynamics.arithmetic_dynamics.endPN_minimal_model import BM_all_minimal
        sage: BM_all_minimal(f, D=[3])
        [Dynamical System of Projective Space of dimension 1 over Rational Field
           Defn: Defined on coordinates by sending (x : y) to
                 (x^3 - 36*y^3 : x*y^2),
         Dynamical System of Projective Space of dimension 1 over Rational Field
           Defn: Defined on coordinates by sending (x : y) to
                 (3*x^3 - 4*y^3 : x*y^2)]

    ::

        sage: P.<x,y> = ProjectiveSpace(QQ,1)
        sage: f = DynamicalSystem([x^3 - 4^2*y^3, x*y^2])
        sage: from sage.dynamics.arithmetic_dynamics.endPN_minimal_model import BM_all_minimal
        sage: cl = BM_all_minimal(f, return_transformation=True)
        sage: all(f.conjugate(m) == g for g, m in cl)
        True
    """
    mp = copy(vp)
    mp.normalize_coordinates()
    BR = mp.domain().base_ring()
    MS = MatrixSpace(QQ, 2)
    M_Id = MS.one()
    d = mp.degree()
    F, G = list(mp)  #coordinate polys
    aff_map = mp.dehomogenize(1)
    f, g = aff_map[0].numerator(), aff_map[0].denominator()
    z = aff_map.domain().gen(0)
    dg = f.parent()(g).degree()
    Res = mp.resultant()

    ##### because of how the bound is compute in lemma 3.3
    from sage.dynamics.arithmetic_dynamics.affine_ds import DynamicalSystem_affine
    h = f - z * g
    A = AffineSpace(BR, 1, h.parent().variable_name())
    res = DynamicalSystem_affine([h / g], domain=A).homogenize(1).resultant()

    if D is None:
        D = ZZ(Res).prime_divisors()

    # get the conjugations for each prime independently
    # these are returning (p,k,b) so that the matrix is [p^k,b,0,1]
    all_pM = []
    for p in D:
        # all_orbits used to scale inequalities to equalities
        all_pM.append(Min(mp, p, res, M_Id, all_orbits=True))
        # need the identity for each prime
        if [p, 0, 0] not in all_pM[-1]:
            all_pM[-1].append([p, 0, 0])

    #combine conjugations for all primes
    all_M = [M_Id]
    for prime_data in all_pM:
        #these are (p,k,b) so that the matrix is [p^k,b,0,1]
        new_M = []
        if prime_data:
            p = prime_data[0][0]
            for m in prime_data:
                mat = MS([m[0]**m[1], m[2], 0, 1])
                new_map = mp.conjugate(mat)
                new_map.normalize_coordinates()
                # make sure the resultant didn't change and that it is a different SL(2,ZZ) orbit
                if (mat == M_Id) or (new_map.resultant().valuation(p)
                                     == Res.valuation(p)
                                     and mat.det() not in [1, -1]):
                    new_M.append(m)
        if new_M:
            all_M = [
                m1 * MS([m[0]**m[1], m[2], 0, 1]) for m1 in all_M
                for m in new_M
            ]

    #get all models with same resultant
    all_maps = []
    for M in all_M:
        new_map = mp.conjugate(M)
        new_map.normalize_coordinates()
        if not [new_map, M] in all_maps:
            all_maps.append([new_map, M])

    #Split into conjugacy classes
    #We just keep track of the two matrices that come from
    #the original to get the conjugation that goes between these!!
    classes = []
    for funct, mat in all_maps:
        if not classes:
            classes.append([funct, mat])
        else:
            found = False
            for Func, Mat in classes:
                #get conjugation
                M = mat.inverse() * Mat
                assert funct.conjugate(M) == Func
                if M.det() in [1, -1]:
                    #same SL(2,Z) orbit
                    found = True
                    break
            if found is False:
                classes.append([funct, mat])

    if return_transformation:
        return classes
    else:
        return [funct for funct, matr in classes]
Пример #19
0
    def affine_algebraic_patch(self, cone=None, names=None):
        r"""
        Return the affine patch corresponding to ``cone`` as an affine
        algebraic scheme.

        INPUT:

        - ``cone`` -- a :class:`Cone
          <sage.geometry.cone.ConvexRationalPolyhedralCone>` `\sigma`
          of the fan. It can be omitted for an affine toric variety,
          in which case the single generating cone is used.

        OUTPUT:

        An :class:`affine algebraic subscheme
        <sage.schemes.affine.affine_subscheme.AlgebraicScheme_subscheme_affine>`
        corresponding to the patch `\mathop{Spec}(\sigma^\vee \cap M)`
        associated to the cone `\sigma`.

        See also :meth:`affine_patch`, which expresses the patches as
        subvarieties of affine toric varieties instead.

        REFERENCES:

        ..

            David A. Cox, "The Homogeneous Coordinate Ring of a Toric
            Variety", Lemma 2.2.
            :arxiv:`alg-geom/9210008v2`

        EXAMPLES::

            sage: P2.<x,y,z> = toric_varieties.P2()
            sage: cone = P2.fan().generating_cone(0)
            sage: V = P2.subscheme(x^3+y^3+z^3)
            sage: V.affine_algebraic_patch(cone)
            Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:
              z0^3 + z1^3 + 1

            sage: cone = Cone([(0,1),(2,1)])
            sage: A2Z2.<x,y> = AffineToricVariety(cone)
            sage: A2Z2.affine_algebraic_patch()
            Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:
              -z0*z1 + z2^2
            sage: V = A2Z2.subscheme(x^2+y^2-1)
            sage: patch = V.affine_algebraic_patch();  patch
            Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:
              -z0*z1 + z2^2,
              z0 + z1 - 1
            sage: nbhd_patch = V.neighborhood([1,0]).affine_algebraic_patch();  nbhd_patch
            Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:
              -z0*z1 + z2^2,
              z0 + z1 - 1
            sage: nbhd_patch.embedding_center()
            (0, 1, 0)

        Here we got two defining equations. The first one describes
        the singularity of the ambient space and the second is the
        pull-back of `x^2+y^2-1` ::

            sage: lp = LatticePolytope([(1,0,0),(1,1,0),(1,1,1),(1,0,1),(-2,-1,-1)],
            ....:                      lattice=ToricLattice(3))
            sage: X.<x,y,u,v,t> = CPRFanoToricVariety(Delta_polar=lp)
            sage: Y = X.subscheme(x*v+y*u+t)
            sage: cone = Cone([(1,0,0),(1,1,0),(1,1,1),(1,0,1)])
            sage: Y.affine_algebraic_patch(cone)
            Closed subscheme of Affine Space of dimension 4 over Rational Field defined by:
              z0*z2 - z1*z3,
              z1 + z3 + 1
        """
        from sage.modules.all import vector
        from sage.misc.all import prod
        ambient = self.ambient_space()
        fan = ambient.fan()
        if cone is None:
            assert ambient.is_affine()
            cone = fan.generating_cone(0)
        else:
            cone = fan.embed(cone)
        # R/I = C[sigma^dual cap M]
        R, I, dualcone = ambient._semigroup_ring(cone, names)

        # inhomogenize the Cox homogeneous polynomial with respect to the given cone
        inhomogenize = dict( (ambient.coordinate_ring().gen(i), 1)
                             for i in range(0,fan.nrays())
                             if not i in cone.ambient_ray_indices() )
        polynomials = [ p.subs(inhomogenize) for p in self.defining_polynomials() ]

        # map the monomial x^{D_m} to m, see reference.
        n_rho_matrix = cone.rays().matrix()
        def pullback_polynomial(p):
            result = R.zero()
            for coefficient, monomial in p:
                exponent = monomial.exponents()[0]
                exponent = [ exponent[i] for i in cone.ambient_ray_indices() ]
                exponent = vector(ZZ,exponent)
                m = n_rho_matrix.solve_right(exponent)
                assert all(x in ZZ for x in m), \
                    'The polynomial '+str(p)+' does not define a ZZ-divisor!'
                m_coeffs = dualcone.Hilbert_coefficients(m)
                result += coefficient * prod(R.gen(i)**m_coeffs[i]
                                             for i in range(0,R.ngens()))
            return result

        # construct the affine algebraic scheme to use as patch
        polynomials = [pullback_polynomial(_) for _ in polynomials]
        from sage.schemes.affine.affine_space import AffineSpace
        patch_cover = AffineSpace(R)
        polynomials = list(I.gens()) + polynomials
        polynomials = [x for x in polynomials if not x.is_zero()]
        patch = patch_cover.subscheme(polynomials)

        # TODO: If the cone is not smooth, then the coordinate_ring()
        # of the affine toric variety is wrong; it should be the
        # G-invariant part. So we can't construct the embedding
        # morphism in that case.
        if cone.is_smooth():
            x = ambient.coordinate_ring().gens()
            phi = []
            for i in range(0,fan.nrays()):
                if i in cone.ambient_ray_indices():
                    phi.append(pullback_polynomial(x[i]))
                else:
                    phi.append(1)
            patch._embedding_morphism = patch.hom(phi, self)
        else:
            patch._embedding_morphism = (NotImplementedError,
               'I only know how to construct embedding morphisms for smooth patches')

        try:
            point = self.embedding_center()
        except AttributeError:
            return patch

        # it remains to find the preimage of point
        # map m to the monomial x^{D_m}, see reference.
        F = ambient.coordinate_ring().fraction_field()
        image = []
        for m in dualcone.Hilbert_basis():
            x_Dm = prod([ F.gen(i)**(m*n) for i,n in enumerate(fan.rays()) ])
            image.append(x_Dm)
        patch._embedding_center = tuple( f(list(point)) for f in image )
        return patch