def enum_projective_number_field(X,B):
    """
    Enumerates projective points on scheme ``X`` defined over a number field. Simply checks all of the
    points of absolute height of at most ``B`` and adds those that are on the scheme to the list.

    INPUT:

    - ``X`` - a scheme defined over a number field

    - ``B`` - a real number

    OUTPUT:

     - a list containing the projective points of ``X`` of absolute height up to ``B``,
       sorted.

    EXAMPLES::

        sage: from sage.schemes.projective.projective_rational_point import enum_projective_number_field
        sage: u = QQ['u'].0
        sage: K = NumberField(u^3 - 5,'v')
        sage: P.<x,y,z> = ProjectiveSpace(K, 2)
        sage: X = P.subscheme([x - y])
        sage: enum_projective_number_field(X(K),125)
        [(0 : 0 : 1), (-1 : -1 : 1), (1 : 1 : 1), (-1/5*v^2 : -1/5*v^2 : 1), (-v : -v : 1),
        (1/5*v^2 : 1/5*v^2 : 1), (v : v : 1), (1 : 1 : 0)]

    ::

        sage: u = QQ['u'].0
        sage: K = NumberField(u^2 + 3,'v')
        sage: A.<x,y> = ProjectiveSpace(K,1)
        sage: X=A.subscheme(x-y)
        sage: from sage.schemes.projective.projective_rational_point import enum_projective_number_field
        sage: enum_projective_number_field(X,3)
        [(1 : 1)]
    """
    from sage.schemes.projective.projective_space import is_ProjectiveSpace
    if(is_Scheme(X)):
        if (not is_ProjectiveSpace(X.ambient_space())):
            raise TypeError("Ambient space must be projective space over a number field")
        X = X(X.base_ring())
    else:
        if (not is_ProjectiveSpace(X.codomain().ambient_space())):
            raise TypeError("Codomain must be projective space over a number field")

    R = X.codomain().ambient_space()

    pts = []

    for P in R.points_of_bounded_height(B):
        try:
            pts.append(X(P))
        except TypeError:
            pass
    pts.sort()
    return pts
    def is_morphism(self):
        r"""
        returns ``True`` if self is a morphism (no common zero of defining polynomials).
        The map is a morphism if and only if the ideal generated by the defining polynomials
        is the unit ideal.


        OUTPUT:

        - Boolean

        EXAMPLES::

            sage: P.<x,y>=ProjectiveSpace(QQ,1)
            sage: H=Hom(P,P)
            sage: f=H([x^2+y^2,y^2])
            sage: f.is_morphism()
            True

        ::

            sage: P.<x,y,z>=ProjectiveSpace(RR,2)
            sage: H=Hom(P,P)
            sage: f=H([x*z-y*z,x^2-y^2,z^2])
            sage: f.is_morphism()
            False

        ::

            sage: R.<t>=PolynomialRing(GF(5))
            sage: P.<x,y,z>=ProjectiveSpace(R,2)
            sage: H=Hom(P,P)
            sage: f=H([x*z-t*y^2,x^2-y^2,t*z^2])
            sage: f.is_morphism()
            True
        """
        from sage.schemes.projective.projective_space import is_ProjectiveSpace
        if is_ProjectiveSpace(self.domain())==False or is_ProjectiveSpace(self.codomain())==False:
            raise NotImplementedError
        R=self.coordinate_ring()
        F=self._polys
        if R.base_ring().is_field():
            J=R.ideal(F)
        else:
            S=PolynomialRing(R.base_ring().fraction_field(),R.gens(),R.ngens())
            J=S.ideal([S.coerce(F[i]) for i in range(R.ngens())])
        if J.dimension()>0:
            return False
        else:
            return True
Beispiel #3
0
    def __init__(self, A, X):
        r"""
        Initialization function.

        EXMAPLES::

            sage: P.<x,y,z,w,u> = ProjectiveSpace(GF(7), 4)
            sage: C = Curve([y*u^2 - x^3, z*u^2 - x^3, w*u^2 - x^3, y^3 - x^3], P); C
            Projective Curve over Finite Field of size 7 defined by -x^3 + y*u^2,
            -x^3 + z*u^2, -x^3 + w*u^2, -x^3 + y^3

        ::

            sage: K.<u> = CyclotomicField(11)
            sage: P.<x,y,z,w> = ProjectiveSpace(K, 3)
            sage: C = Curve([y*w - u*z^2 - x^2, x*w - 3*u^2*z*w], P); C
            Projective Curve over Cyclotomic Field of order 11 and degree 10 defined
            by -x^2 + (-u)*z^2 + y*w, x*w + (-3*u^2)*z*w
        """
        if not is_ProjectiveSpace(A):
            raise TypeError("A (=%s) must be a projective space" % A)
        Curve_generic.__init__(self, A, X)
        d = self.dimension()
        if d != 1:
            raise ValueError(
                "defining equations (=%s) define a scheme of dimension %s != 1"
                % (X, d))
def QuarticCurve(F, PP=None, check=False):
    """
    Returns the quartic curve defined by the polynomial F.

    INPUT:

    - F -- a polynomial in three variables, homogeneous of degree 4

    - PP -- a projective plane (default:None)

    - check -- whether to check for smoothness or not (default:False)

    EXAMPLES::

        sage: x,y,z=PolynomialRing(QQ,['x','y','z']).gens()
        sage: QuarticCurve(x**4+y**4+z**4)
        Quartic Curve over Rational Field defined by x^4 + y^4 + z^4

    TESTS::

        sage: QuarticCurve(x**3+y**3)
        Traceback (most recent call last):
        ...
        ValueError: Argument F (=x^3 + y^3) must be a homogeneous polynomial of degree 4

        sage: QuarticCurve(x**4+y**4+z**3)
        Traceback (most recent call last):
        ...
        ValueError: Argument F (=x^4 + y^4 + z^3) must be a homogeneous polynomial of degree 4

        sage: x,y=PolynomialRing(QQ,['x','y']).gens()
        sage: QuarticCurve(x**4+y**4)
        Traceback (most recent call last):
        ...
        ValueError: Argument F (=x^4 + y^4) must be a polynomial in 3 variables

    """
    if not is_MPolynomial(F):
        raise ValueError("Argument F (=%s) must be a multivariate polynomial" %
                         F)
    P = F.parent()
    if not P.ngens() == 3:
        raise ValueError(
            "Argument F (=%s) must be a polynomial in 3 variables" % F)
    if not (F.is_homogeneous() and F.degree() == 4):
        raise ValueError(
            "Argument F (=%s) must be a homogeneous polynomial of degree 4" %
            F)

    if PP is not None:
        if not is_ProjectiveSpace(PP) and PP.dimension == 2:
            raise ValueError(f"Argument PP (={PP}) must be a projective plane")
    else:
        PP = ProjectiveSpace(P)

    if check:
        raise NotImplementedError(
            "Argument checking (for nonsingularity) is not implemented.")

    return QuarticCurve_generic(PP, F)
Beispiel #5
0
    def multiplicity(self):
        r"""
        Return the multiplicity of this point on its codomain.

        Uses the subscheme multiplicity implementation. This point must be a point on
        a projective subscheme.

        OUTPUT: an integer.

        EXAMPLES::

            sage: P.<x,y,z,w,t> = ProjectiveSpace(QQ, 4)
            sage: X = P.subscheme([y^6 - x^3*w^2*t + t^5*w, x^2 - t^2])
            sage: Q1 = X([1,0,2,1,1])
            sage: Q1.multiplicity()
            1
            sage: Q2 = X([0,0,-2,1,0])
            sage: Q2.multiplicity()
            8
        """
        from sage.schemes.projective.projective_space import is_ProjectiveSpace
        if is_ProjectiveSpace(self.codomain()):
            raise TypeError(
                "this point must be a point on a projective subscheme")
        return self.codomain().multiplicity(self)
Beispiel #6
0
    def __init__(self, A, X):
        r"""
        Initialization function.

        EXMAPLES::

            sage: P.<x,y,z,w,u> = ProjectiveSpace(GF(7), 4)
            sage: C = Curve([y*u^2 - x^3, z*u^2 - x^3, w*u^2 - x^3, y^3 - x^3], P); C
            Projective Curve over Finite Field of size 7 defined by -x^3 + y*u^2,
            -x^3 + z*u^2, -x^3 + w*u^2, -x^3 + y^3

        ::

            sage: K.<u> = CyclotomicField(11)
            sage: P.<x,y,z,w> = ProjectiveSpace(K, 3)
            sage: C = Curve([y*w - u*z^2 - x^2, x*w - 3*u^2*z*w], P); C
            Projective Curve over Cyclotomic Field of order 11 and degree 10 defined
            by -x^2 + (-u)*z^2 + y*w, x*w + (-3*u^2)*z*w
        """
        if not is_ProjectiveSpace(A):
            raise TypeError("A (=%s) must be a projective space"%A)
        Curve_generic.__init__(self, A, X)
        d = self.dimension()
        if d != 1:
            raise ValueError("defining equations (=%s) define a scheme of dimension %s != 1"%(X,d))
Beispiel #7
0
 def __init__(self, A, X):
     if not is_ProjectiveSpace(A):
         raise TypeError("A (=%s) must be a projective space"%A)
     Curve_generic_projective.__init__(self, A, X)
     d = self.dimension()
     if d != 1:
         raise ValueError("defining equations (=%s) define a scheme of dimension %s != 1"%(X,d))
    def cyclegraph(self):
        r"""
        returns Digraph of all orbits of self mod `p`. For subschemes, only points on the subscheme whose
        image are also on the subscheme are in the digraph.

        OUTPUT:

        - a digraph

        EXAMPLES::

            sage: P.<x,y>=ProjectiveSpace(GF(13),1)
            sage: H=Hom(P,P)
            sage: f=H([x^2-y^2,y^2])
            sage: f.cyclegraph()
            Looped digraph on 14 vertices

        ::

            sage: P.<x,y,z>=ProjectiveSpace(GF(5^2,'t'),2)
            sage: H=Hom(P,P)
            sage: f=H([x^2+y^2,y^2,z^2+y*z])
            sage: f.cyclegraph()
            Looped digraph on 651 vertices

        ::

            sage: P.<x,y,z>=ProjectiveSpace(GF(7),2)
            sage: X=P.subscheme(x^2-y^2)
            sage: H=Hom(X,X)
            sage: f=H([x^2,y^2,z^2])
            sage: f.cyclegraph()
            Looped digraph on 15 vertices
        """
        if self.domain() != self.codomain():
            raise NotImplementedError("Domain and Codomain must be equal")
        V=[]
        E=[]
        from sage.schemes.projective.projective_space import is_ProjectiveSpace
        if is_ProjectiveSpace(self.domain())==True:
            for P in self.domain():
                V.append(str(P))
                Q=self(P)
                Q.normalize_coordinates()
                E.append([str(Q)])
        else:
            X=self.domain()
            for P in X.ambient_space():
                try:
                    XP=X.point(P)
                    V.append(str(XP))
                    Q=self(XP)
                    Q.normalize_coordinates()
                    E.append([str(Q)])
                except TypeError: #not a point on the scheme
                    pass
        from sage.graphs.digraph import DiGraph
        g=DiGraph(dict(zip(V,E)), loops=True)
        return(g)
Beispiel #9
0
 def __init__(self, A, X):
     if not is_ProjectiveSpace(A):
         raise TypeError, "A (=%s) must be a projective space" % A
     Curve_generic_projective.__init__(self, A, X)
     d = self.dimension()
     if d != 1:
         raise ValueError, "defining equations (=%s) define a scheme of dimension %s != 1" % (
             X, d)
Beispiel #10
0
def QuarticCurve(F, PP=None, check=False):
    """
    Returns the quartic curve defined by the polynomial F.

    INPUT:

    - F -- a polynomial in three variables, homogeneous of degree 4

    - PP -- a projective plane (default:None)

    - check -- whether to check for smoothness or not (default:False)

    EXAMPLES::

        sage: x,y,z=PolynomialRing(QQ,['x','y','z']).gens()
        sage: QuarticCurve(x**4+y**4+z**4)
        Quartic Curve over Rational Field defined by x^4 + y^4 + z^4

    TESTS::

        sage: QuarticCurve(x**3+y**3)
        Traceback (most recent call last):
        ...
        ValueError: Argument F (=x^3 + y^3) must be a homogeneous polynomial of degree 4

        sage: QuarticCurve(x**4+y**4+z**3)
        Traceback (most recent call last):
        ...
        ValueError: Argument F (=x^4 + y^4 + z^3) must be a homogeneous polynomial of degree 4

        sage: x,y=PolynomialRing(QQ,['x','y']).gens()
        sage: QuarticCurve(x**4+y**4)
        Traceback (most recent call last):
        ...
        ValueError: Argument F (=x^4 + y^4) must be a polynomial in 3 variables

    """
    if not is_MPolynomial(F):
        raise ValueError("Argument F (=%s) must be a multivariate polynomial"%F)
    P = F.parent()
    if not P.ngens() == 3:
        raise ValueError("Argument F (=%s) must be a polynomial in 3 variables"%F)
    if not(F.is_homogeneous() and F.degree()==4):
        raise ValueError("Argument F (=%s) must be a homogeneous polynomial of degree 4"%F)

    if not PP is None:
        if not is_ProjectiveSpace(PP) and PP.dimension == 2:
            raise ValueError("Argument PP (=%s) must be a projective plane"%PP)
    else:
        PP = ProjectiveSpace(P)

    if check:
        raise NotImplementedError("Argument checking (for nonsingularity) is not implemented.")

    return QuarticCurve_generic(PP, F)
    def __init__(self, base, ideal=None):
        """
        The Python constructor.

        EXAMPLES::

            sage: Berkovich_Cp_Projective(3)
            Projective Berkovich line over Cp(3) of precision 20
        """
        if base in ZZ:
            if base.is_prime():
                base = ProjectiveSpace(Qp(base), 1)
            else:
                raise ValueError("non-prime passed into Berkovich space")
        if base in NumberFields() or isinstance(base,
                                                sage.rings.abc.pAdicField):
            base = ProjectiveSpace(base, 1)
        if not is_ProjectiveSpace(base):
            try:
                base = ProjectiveSpace(base)
            except:
                raise ValueError(
                    "base of projective Berkovich space must be projective space"
                )
        if not isinstance(base.base_ring(), sage.rings.abc.pAdicField):
            if base.base_ring() not in NumberFields():
                raise ValueError("base of projective Berkovich space must be " + \
                    "projective space over Qp or a number field")
            else:
                if ideal is None:
                    raise ValueError('passed a number field but not an ideal')
                if base.base_ring() is not QQ:
                    if not isinstance(ideal, NumberFieldFractionalIdeal):
                        raise ValueError('ideal was not a number field ideal')
                    if ideal.number_field() != base.base_ring():
                        raise ValueError('passed number field ' + \
                            '%s but ideal was an ideal of %s' %(base.base_ring(), ideal.number_field()))
                    prime = ideal.smallest_integer()
                else:
                    if ideal not in QQ:
                        raise ValueError('ideal was not an element of QQ')
                    prime = ideal
                if not ideal.is_prime():
                    raise ValueError('passed non prime ideal')
                self._base_type = 'number field'
        else:
            prime = base.base_ring().prime()
            ideal = None
            self._base_type = 'padic field'
        if base.dimension_relative() != 1:
            raise ValueError("base of projective Berkovich space must be " + \
                "projective space of dimension 1 over Qp or a number field")
        self._p = prime
        self._ideal = ideal
        Parent.__init__(self, base=base, category=TopologicalSpaces())
Beispiel #12
0
    def _number_field_from_algebraics(self):
        r"""
        Given a projective point defined over ``QQbar``, return the same point, but defined
        over a number field.

        This is only implemented for points of projective space.

        OUTPUT: scheme point

        EXAMPLES::

            sage: R.<x> = PolynomialRing(QQ)
            sage: P.<x,y> = ProjectiveSpace(QQbar,1)
            sage: Q = P([-1/2*QQbar(sqrt(2)) + QQbar(I), 1])
            sage: S = Q._number_field_from_algebraics(); S
            (1/2*a^3 + a^2 - 1/2*a : 1)
            sage: S.codomain()
            Projective Space of dimension 1 over Number Field in a with defining polynomial y^4 + 1 with a = 0.7071067811865475? + 0.7071067811865475?*I

        The following was fixed in :trac:`23808`::

            sage: R.<x> = PolynomialRing(QQ)
            sage: P.<x,y> = ProjectiveSpace(QQbar,1)
            sage: Q = P([-1/2*QQbar(sqrt(2)) + QQbar(I), 1]);Q
            (-0.7071067811865475? + 1*I : 1)
            sage: S = Q._number_field_from_algebraics(); S
            (1/2*a^3 + a^2 - 1/2*a : 1)
            sage: T = S.change_ring(QQbar) # Used to fail
            sage: T
            (-0.7071067811865475? + 1.000000000000000?*I : 1)
            sage: Q[0] == T[0]
            True
        """
        from sage.schemes.projective.projective_space import is_ProjectiveSpace
        if not is_ProjectiveSpace(self.codomain()):
            raise NotImplementedError("not implemented for subschemes")

        # Trac #23808: Keep the embedding info associated with the number field K
        # used below, instead of in the separate embedding map phi which is
        # forgotten.
        K_pre, P, phi = number_field_elements_from_algebraics(list(self))
        if K_pre is QQ:
            K = QQ
        else:
            from sage.rings.number_field.number_field import NumberField
            K = NumberField(K_pre.polynomial(),
                            embedding=phi(K_pre.gen()),
                            name='a')
            psi = K_pre.hom([K.gen()], K)  # Identification of K_pre with K
            P = [psi(p) for p in P]  # The elements of P were elements of K_pre
        from sage.schemes.projective.projective_space import ProjectiveSpace
        PS = ProjectiveSpace(K, self.codomain().dimension_relative(), 'z')
        return PS(P)
    def __classcall_private__(cls, dynamical_system, domain=None):
        """
        Return the approapriate dynamical system on projective Berkovich space over ``Cp``.

        EXAMPLES::

            sage: P1.<x,y> = ProjectiveSpace(Qp(3), 1)
            sage: from sage.dynamics.arithmetic_dynamics.berkovich_ds import DynamicalSystem_Berkovich_projective
            sage: DynamicalSystem_Berkovich_projective([y, x])
            Dynamical system of Projective Berkovich line over Cp(3) of precision 20
            induced by the map
                Defn: Defined on coordinates by sending (x : y) to
                    (y : x)
        """
        if not isinstance(dynamical_system, DynamicalSystem):
            if not isinstance(dynamical_system, DynamicalSystem_projective):
                dynamical_system = DynamicalSystem_projective(dynamical_system)
            else:
                raise TypeError(
                    'affine dynamical system passed to projective constructor')
        R = dynamical_system.base_ring()
        morphism_domain = dynamical_system.domain()
        if not is_ProjectiveSpace(morphism_domain):
            raise TypeError(
                'the domain of dynamical_system must be projective space, not %s'
                % morphism_domain)
        if morphism_domain.dimension_relative() != 1:
            raise ValueError('domain was not relative dimension 1')
        if not isinstance(R, pAdicBaseGeneric):
            if domain is None:
                raise TypeError('dynamical system defined over %s, not p-adic, ' %morphism_domain.base_ring() + \
                    'and domain is None')
            if not isinstance(domain, Berkovich_Cp_Projective):
                raise TypeError(
                    'domain was %s, not a projective Berkovich space over Cp' %
                    domain)
            if domain.base() != morphism_domain:
                raise ValueError('base of domain was %s, with coordinate ring %s ' %(domain.base(), \
                    domain.base().coordinate_ring())+ 'while dynamical_system acts on %s, ' %morphism_domain + \
                        'with coordinate ring %s' %morphism_domain.coordinate_ring())
        else:
            domain = Berkovich_Cp_Projective(morphism_domain)
        return typecall(cls, dynamical_system, domain)
Beispiel #14
0
    def intersection_multiplicity(self, X):
        r"""
        Return the intersection multiplicity of the codomain of this point and ``X`` at this point.

        This uses the intersection_multiplicity implementations for projective/affine subschemes. This
        point must be a point of a projective subscheme.

        INPUT:

        - ``X`` -- a subscheme in the same ambient space as that of the codomain of this point.

        OUTPUT: Integer.

        EXAMPLES::

            sage: P.<x,y,z,w> = ProjectiveSpace(QQ, 3)
            sage: X = P.subscheme([x*z - y^2])
            sage: Y = P.subscheme([x^3 - y*w^2 + z*w^2, x*y - z*w])
            sage: Q1 = X([1/2, 1/4, 1/8, 1])
            sage: Q1.intersection_multiplicity(Y)
            1
            sage: Q2 = X([0,0,0,1])
            sage: Q2.intersection_multiplicity(Y)
            5
            sage: Q3 = X([0,0,1,0])
            sage: Q3.intersection_multiplicity(Y)
            6

        ::

            sage: P.<x,y,z,w> = ProjectiveSpace(QQ, 3)
            sage: X = P.subscheme([x^2 - y^2])
            sage: Q = P([1,1,1,0])
            sage: Q.intersection_multiplicity(X)
            Traceback (most recent call last):
            ...
            TypeError: this point must be a point on a projective subscheme
        """
        from sage.schemes.projective.projective_space import is_ProjectiveSpace
        if is_ProjectiveSpace(self.codomain()):
            raise TypeError(
                "this point must be a point on a projective subscheme")
        return self.codomain().intersection_multiplicity(X, self)
Beispiel #15
0
    def __init__(self, A, f):
        r"""
        Initialization function.

        EXAMPLES::

            sage: P.<x,y,z> = ProjectiveSpace(QQbar, 2)
            sage: C = Curve([y*z - x^2 - QQbar.gen()*z^2], P); C
            Projective Plane Curve over Algebraic Field defined by
            -x^2 + y*z + (-I)*z^2

        ::

            sage: P.<x,y,z> = ProjectiveSpace(GF(5^2, 'v'), 2)
            sage: C = Curve([y^2*z - x*z^2 - z^3], P); C
            Projective Plane Curve over Finite Field in v of size 5^2 defined by y^2*z - x*z^2 - z^3
        """
        if not (is_ProjectiveSpace(A) and A.dimension != 2):
            raise TypeError("Argument A (= %s) must be a projective plane."%A)
        Curve_generic.__init__(self, A, [f])
Beispiel #16
0
    def __init__(self, A, f):
        r"""
        Initialization function.

        EXAMPLES::

            sage: P.<x,y,z> = ProjectiveSpace(QQbar, 2)
            sage: C = Curve([y*z - x^2 - QQbar.gen()*z^2], P); C
            Projective Plane Curve over Algebraic Field defined by
            -x^2 + y*z + (-I)*z^2

        ::

            sage: P.<x,y,z> = ProjectiveSpace(GF(5^2, 'v'), 2)
            sage: C = Curve([y^2*z - x*z^2 - z^3], P); C
            Projective Plane Curve over Finite Field in v of size 5^2 defined by y^2*z - x*z^2 - z^3
        """
        if not (is_ProjectiveSpace(A) and A.dimension != 2):
            raise TypeError("Argument A (= %s) must be a projective plane." %
                            A)
        Curve_generic.__init__(self, A, [f])
Beispiel #17
0
def CurvePointToIdeal(C,P):
    r"""
    Return the vanishing ideal of a point on a curve.

    EXAMPLES::

        sage: x,y = AffineSpace(2, QQ, names='xy').gens()
        sage: C = Curve(y^2 - x^9 - x)
        sage: from sage.schemes.generic.divisor import CurvePointToIdeal
        sage: CurvePointToIdeal(C, (0,0))
        Ideal (x, y) of Multivariate Polynomial Ring in x, y over Rational Field
    """
    A = C.ambient_space()
    R = A.coordinate_ring()
    n = A.ngens()
    x = A.gens()
    polys = [ ]
    m = n-1
    while m > 0 and P[m] == 0:
        m += -1
    if is_ProjectiveSpace(A):
        a_m = P[m]
        x_m = x[m]
        for i in range(m):
            ai = P[i]
            if ai == 0:
                polys.append(x[i])
            else:
                polys.append(a_m*x[i]-ai*x_m)
    elif is_AffineSpace(A):
        for i in range(m+1):
            ai = P[i]
            if ai == 0:
                polys.append(x[i])
            else:
                polys.append(x[i]-ai)
    for i in range(m+1,n):
        polys.append(x[i])
    return R.ideal(polys)
Beispiel #18
0
def CurvePointToIdeal(C, P):
    r"""
    Return the vanishing ideal of a point on a curve.

    EXAMPLES::

        sage: x,y = AffineSpace(2, QQ, names='xy').gens()
        sage: C = Curve(y^2 - x^9 - x)
        sage: from sage.schemes.generic.divisor import CurvePointToIdeal
        sage: CurvePointToIdeal(C, (0,0))
        Ideal (x, y) of Multivariate Polynomial Ring in x, y over Rational Field
    """
    A = C.ambient_space()
    R = A.coordinate_ring()
    n = A.ngens()
    x = A.gens()
    polys = []
    m = n - 1
    while m > 0 and P[m] == 0:
        m += -1
    if is_ProjectiveSpace(A):
        a_m = P[m]
        x_m = x[m]
        for i in range(m):
            ai = P[i]
            if ai == 0:
                polys.append(x[i])
            else:
                polys.append(a_m * x[i] - ai * x_m)
    elif is_AffineSpace(A):
        for i in range(m + 1):
            ai = P[i]
            if ai == 0:
                polys.append(x[i])
            else:
                polys.append(x[i] - ai)
    for i in range(m + 1, n):
        polys.append(x[i])
    return R.ideal(polys)
Beispiel #19
0
    def points(self, **kwds):
        """
        Return some or all rational points of a projective scheme.

        Over a finite field, all points are returned. Over an infinite field, all points satisfying the bound
        are returned. For a zero-dimensional subscheme, all points are returned regardless of whether the base
        ring is a field or not.

        For number fields, this uses the
        Doyle-Krumm algorithm 4 (algorithm 5 for imaginary quadratic) for
        computing algebraic numbers up to a given height [Doyle-Krumm]_.

        The algorithm requires floating point arithmetic, so the user is
        allowed to specify the precision for such calculations.
        Additionally, due to floating point issues, points
        slightly larger than the bound may be returned. This can be controlled
        by lowering the tolerance.

        INPUT:

        - ``bound`` - a real number

        - ``tolerance`` - a rational number in (0,1] used in doyle-krumm algorithm-4

        - ``precision`` - the precision to use for computing the elements of bounded height of number fields.

        OUTPUT:

        - a list of rational points of a projective scheme

        EXAMPLES::

            sage: P.<x,y> = ProjectiveSpace(QQ,1)
            sage: P(QQ).points(bound=4)
            [(-4 : 1), (-3 : 1), (-2 : 1), (-3/2 : 1), (-4/3 : 1), (-1 : 1),
            (-3/4 : 1), (-2/3 : 1), (-1/2 : 1), (-1/3 : 1), (-1/4 : 1), (0 : 1),
            (1/4 : 1), (1/3 : 1), (1/2 : 1), (2/3 : 1), (3/4 : 1), (1 : 0), (1 : 1),
            (4/3 : 1), (3/2 : 1), (2 : 1), (3 : 1), (4 : 1)]

        ::

            sage: u = QQ['u'].0
            sage: K.<v> = NumberField(u^2 + 3)
            sage: P.<x,y,z> = ProjectiveSpace(K,2)
            sage: len(P(K).points(bound=1.8))
            381

        ::

            sage: P1 = ProjectiveSpace(GF(2),1)
            sage: F.<a> = GF(4,'a')
            sage: P1(F).points()
            [(0 : 1), (1 : 0), (1 : 1), (a : 1), (a + 1 : 1)]

        ::

            sage: P.<x,y,z> = ProjectiveSpace(QQ,2)
            sage: E = P.subscheme([(y^3-y*z^2) - (x^3-x*z^2),(y^3-y*z^2) + (x^3-x*z^2)])
            sage: E(P.base_ring()).points()
            [(-1 : -1 : 1), (-1 : 0 : 1), (-1 : 1 : 1), (0 : -1 : 1), (0 : 0 : 1), (0 : 1 : 1),
            (1 : -1 : 1), (1 : 0 : 1), (1 : 1 : 1)]
        """
        B = kwds.pop('bound', 0)
        tol = kwds.pop('tolerance', 1e-2)
        prec = kwds.pop('precision', 53)

        X = self.codomain()
        from sage.schemes.projective.projective_space import is_ProjectiveSpace
        if not is_ProjectiveSpace(X) and X.base_ring() in Fields():
            #Then it must be a subscheme
            dim_ideal = X.defining_ideal().dimension()
            if dim_ideal < 1:  # no points
                return []
            if dim_ideal == 1:  # if X zero-dimensional
                rat_points = set()
                PS = X.ambient_space()
                N = PS.dimension_relative()
                BR = X.base_ring()
                #need a lexicographic ordering for elimination
                R = PolynomialRing(BR, N + 1, PS.variable_names(), order='lex')
                I = R.ideal(X.defining_polynomials())
                I0 = R.ideal(0)
                #Determine the points through elimination
                #This is much faster than using the I.variety() function on each affine chart.
                for k in range(N + 1):
                    #create the elimination ideal for the kth affine patch
                    G = I.substitute({R.gen(k): 1}).groebner_basis()
                    if G != [1]:
                        P = {}
                        #keep track that we know the kth coordinate is 1
                        P.update({R.gen(k): 1})
                        points = [P]
                        #work backwards from solving each equation for the possible
                        #values of the next coordinate
                        for i in range(len(G) - 1, -1, -1):
                            new_points = []
                            good = 0
                            for P in points:
                                #substitute in our dictionary entry that has the values
                                #of coordinates known so far. This results in a single
                                #variable polynomial (by elimination)
                                L = G[i].substitute(P)
                                if L != 0:
                                    L = L.factor()
                                    #the linear factors give the possible rational values of
                                    #this coordinate
                                    for pol, pow in L:
                                        if pol.degree() == 1 and len(
                                                pol.variables()) == 1:
                                            good = 1
                                            r = pol.variables()[0]
                                            varindex = R.gens().index(r)
                                            #add this coordinates information to
                                            #each dictionary entry
                                            P.update({
                                                R.gen(varindex):
                                                -pol.constant_coefficient() /
                                                pol.monomial_coefficient(r)
                                            })
                                            new_points.append(copy(P))
                                else:
                                    new_points.append(P)
                                    good = 1
                            if good:
                                points = new_points
                        #the dictionary entries now have values for all coordinates
                        #they are the rational solutions to the equations
                        #make them into projective points
                        for i in range(len(points)):
                            if len(points[i]) == N + 1 and I.subs(
                                    points[i]) == I0:
                                S = X([
                                    points[i][R.gen(j)] for j in range(N + 1)
                                ])
                                S.normalize_coordinates()
                                rat_points.add(S)
                rat_points = sorted(rat_points)
                return rat_points
        R = self.value_ring()
        if is_RationalField(R):
            if not B > 0:
                raise TypeError("a positive bound B (= %s) must be specified" %
                                B)
            if isinstance(X, AlgebraicScheme_subscheme
                          ):  # sieve should only be called for subschemes
                from sage.schemes.projective.projective_rational_point import sieve
                return sieve(X, B)
            else:
                from sage.schemes.projective.projective_rational_point import enum_projective_rational_field
                return enum_projective_rational_field(self, B)
        elif R in NumberFields():
            if not B > 0:
                raise TypeError("a positive bound B (= %s) must be specified" %
                                B)
            from sage.schemes.projective.projective_rational_point import enum_projective_number_field
            return enum_projective_number_field(self,
                                                bound=B,
                                                tolerance=tol,
                                                precision=prec)
        elif is_FiniteField(R):
            from sage.schemes.projective.projective_rational_point import enum_projective_finite_field
            return enum_projective_finite_field(self.extended_codomain())
        else:
            raise TypeError("unable to enumerate points over %s" % R)
Beispiel #20
0
    def points(self, **kwds):
        """
        Return some or all rational points of a projective scheme.

        For dimension 0 subschemes points are determined through a groebner
        basis calculation. For schemes or subschemes with dimension greater than 1
        points are determined through enumeration up to the specified bound.

        INPUT:

        kwds:

        - ``bound`` - real number (optional, default=0). The bound for the coordinates for
          subschemes with dimension at least 1.

        - ``precision`` - integer (optional, default=53). The precision to use to
          compute the elements of bounded height for number fields.

        - ``point_tolerance`` - positive real number (optional, default=10^(-10)).
          For numerically inexact fields, two points are considered the same
          if their coordinates are within tolerance.

        - ``zero_tolerance`` - positive real number (optional, default=10^(-10)).
          For numerically inexact fields, points are on the subscheme if they
          satisfy the equations to within tolerance.

        - ``tolerance`` - a rational number in (0,1] used in doyle-krumm algorithm-4
          for enumeration over number fields.

        OUTPUT:

        - a list of rational points of a projective scheme

        .. WARNING::
        
            For numerically inexact fields such as ComplexField or RealField the
            list of points returned is very likely to be incomplete. It may also
            contain repeated points due to tolerances.

        EXAMPLES::

            sage: P.<x,y> = ProjectiveSpace(QQ,1)
            sage: P(QQ).points(bound=4)
            [(-4 : 1), (-3 : 1), (-2 : 1), (-3/2 : 1), (-4/3 : 1), (-1 : 1),
            (-3/4 : 1), (-2/3 : 1), (-1/2 : 1), (-1/3 : 1), (-1/4 : 1), (0 : 1),
            (1/4 : 1), (1/3 : 1), (1/2 : 1), (2/3 : 1), (3/4 : 1), (1 : 0), (1 : 1),
            (4/3 : 1), (3/2 : 1), (2 : 1), (3 : 1), (4 : 1)]

        ::

            sage: u = QQ['u'].0
            sage: K.<v> = NumberField(u^2 + 3)
            sage: P.<x,y,z> = ProjectiveSpace(K,2)
            sage: len(P(K).points(bound=1.8))
            381

        ::

            sage: P1 = ProjectiveSpace(GF(2),1)
            sage: F.<a> = GF(4,'a')
            sage: P1(F).points()
            [(0 : 1), (1 : 0), (1 : 1), (a : 1), (a + 1 : 1)]

        ::

            sage: P.<x,y,z> = ProjectiveSpace(QQ,2)
            sage: E = P.subscheme([(y^3-y*z^2) - (x^3-x*z^2),(y^3-y*z^2) + (x^3-x*z^2)])
            sage: E(P.base_ring()).points()
            [(-1 : -1 : 1), (-1 : 0 : 1), (-1 : 1 : 1), (0 : -1 : 1), (0 : 0 : 1), (0 : 1 : 1),
            (1 : -1 : 1), (1 : 0 : 1), (1 : 1 : 1)]

        ::

            sage: P.<x,y,z> = ProjectiveSpace(CC, 2)
            sage: E = P.subscheme([y^3 - x^3 - x*z^2, x*y*z])
            sage: L=E(P.base_ring()).points(); sorted(L, key=str)
            verbose 0 (71: projective_homset.py, points) Warning: computations in the numerical fields are inexact;points may be computed partially or incorrectly.
            [(-0.500000000000000 + 0.866025403784439*I : 1.00000000000000 : 0.000000000000000),
            (-0.500000000000000 - 0.866025403784439*I : 1.00000000000000 : 0.000000000000000),
            (-1.00000000000000*I : 0.000000000000000 : 1.00000000000000),
            (0.000000000000000 : 0.000000000000000 : 1.00000000000000),
            (1.00000000000000 : 1.00000000000000 : 0.000000000000000),
            (1.00000000000000*I : 0.000000000000000 : 1.00000000000000)]
            sage: L[0].codomain()
            Projective Space of dimension 2 over Complex Field with 53 bits of precision

        ::

            sage: P.<x,y,z> = ProjectiveSpace(CDF, 2)
            sage: E = P.subscheme([y^2 + x^2 + z^2, x*y*z])
            sage: len(E(P.base_ring()).points())
            verbose 0 (71: projective_homset.py, points) Warning: computations in the numerical fields are inexact;points may be computed partially or incorrectly.
            6
        """
        from sage.schemes.projective.projective_space import is_ProjectiveSpace
        X = self.codomain()
        if not is_ProjectiveSpace(X) and X.base_ring() in Fields():
            if hasattr(X.base_ring(), 'precision'):
                numerical = True
                verbose(
                    "Warning: computations in the numerical fields are inexact;points may be computed partially or incorrectly.",
                    level=0)
                pt_tol = RR(kwds.pop('point_tolerance', 10**(-10)))
                zero_tol = RR(kwds.pop('zero_tolerance', 10**(-10)))
                if pt_tol <= 0 or zero_tol <= 0:
                    raise ValueError("tolerance must be positive")
            else:
                numerical = False
            #Then it must be a subscheme
            dim_ideal = X.defining_ideal().dimension()
            if dim_ideal < 1:  # no points
                return []
            if dim_ideal == 1:  # if X zero-dimensional
                rat_points = set()
                PS = X.ambient_space()
                N = PS.dimension_relative()
                BR = X.base_ring()
                #need a lexicographic ordering for elimination
                R = PolynomialRing(BR, N + 1, PS.variable_names(), order='lex')
                I = R.ideal(X.defining_polynomials())
                I0 = R.ideal(0)
                #Determine the points through elimination
                #This is much faster than using the I.variety() function on each affine chart.
                for k in range(N + 1):
                    #create the elimination ideal for the kth affine patch
                    G = I.substitute({R.gen(k): 1}).groebner_basis()
                    if G != [1]:
                        P = {}
                        #keep track that we know the kth coordinate is 1
                        P.update({R.gen(k): 1})
                        points = [P]
                        #work backwards from solving each equation for the possible
                        #values of the next coordinate
                        for i in range(len(G) - 1, -1, -1):
                            new_points = []
                            good = 0
                            for P in points:
                                #substitute in our dictionary entry that has the values
                                #of coordinates known so far. This results in a single
                                #variable polynomial (by elimination)
                                L = G[i].substitute(P)
                                if R(L).degree() > 0:
                                    if numerical:
                                        for pol in L.univariate_polynomial(
                                        ).roots(multiplicities=False):
                                            good = 1
                                            r = L.variables()[0]
                                            varindex = R.gens().index(r)
                                            P.update({R.gen(varindex): pol})
                                            new_points.append(copy(P))
                                    else:
                                        L = L.factor()
                                        #the linear factors give the possible rational values of
                                        #this coordinate
                                        for pol, pow in L:
                                            if pol.degree() == 1 and len(
                                                    pol.variables()) == 1:
                                                good = 1
                                                r = pol.variables()[0]
                                                varindex = R.gens().index(r)
                                                #add this coordinates information to
                                                #each dictionary entry
                                                P.update({
                                                    R.gen(varindex):
                                                    -pol.constant_coefficient(
                                                    ) /
                                                    pol.monomial_coefficient(r)
                                                })
                                                new_points.append(copy(P))
                                else:
                                    new_points.append(P)
                                    good = 1
                            if good:
                                points = new_points
                        #the dictionary entries now have values for all coordinates
                        #they are the rational solutions to the equations
                        #make them into projective points
                        for i in range(len(points)):
                            if numerical:
                                if len(points[i]) == N + 1:
                                    S = PS([
                                        points[i][R.gen(j)]
                                        for j in range(N + 1)
                                    ])
                                    S.normalize_coordinates()
                                    if all(
                                            g(list(S)) < zero_tol
                                            for g in X.defining_polynomials()):
                                        rat_points.add(S)
                            else:
                                if len(points[i]) == N + 1 and I.subs(
                                        points[i]) == I0:
                                    S = X([
                                        points[i][R.gen(j)]
                                        for j in range(N + 1)
                                    ])
                                    S.normalize_coordinates()
                                    rat_points.add(S)

                # remove duplicate element using tolerance
                if numerical:
                    dupl_points = list(rat_points)
                    for i in range(len(dupl_points)):
                        u = dupl_points[i]
                        for j in range(i + 1, len(dupl_points)):
                            v = dupl_points[j]
                            if all((u[k] - v[k]).abs() < pt_tol
                                   for k in range(len(u))):
                                rat_points.remove(u)
                                break

                rat_points = sorted(rat_points)
                return rat_points
        R = self.value_ring()
        B = kwds.pop('bound', 0)
        tol = kwds.pop('tolerance', 1e-2)
        prec = kwds.pop('precision', 53)
        if is_RationalField(R):
            if not B > 0:
                raise TypeError("a positive bound B (= %s) must be specified" %
                                B)
            if isinstance(X, AlgebraicScheme_subscheme
                          ):  # sieve should only be called for subschemes
                from sage.schemes.projective.projective_rational_point import sieve
                return sieve(X, B)
            else:
                from sage.schemes.projective.projective_rational_point import enum_projective_rational_field
                return enum_projective_rational_field(self, B)
        elif R in NumberFields():
            if not B > 0:
                raise TypeError("a positive bound B (= %s) must be specified" %
                                B)
            from sage.schemes.projective.projective_rational_point import enum_projective_number_field
            return enum_projective_number_field(self,
                                                bound=B,
                                                tolerance=tol,
                                                precision=prec)
        elif is_FiniteField(R):
            from sage.schemes.projective.projective_rational_point import enum_projective_finite_field
            return enum_projective_finite_field(self.extended_codomain())
        else:
            raise TypeError("unable to enumerate points over %s" % R)
Beispiel #21
0
    def numerical_points(self, F=None, **kwds):
        """
        Return some or all numerical approximations of rational points of a projective scheme.

        This is for dimension 0 subschemes only and the points are determined
        through a groebner calculation over the base ring and then numerically
        approximating the roots of the resulting polynomials. If the base ring
        is a number field, the embedding into ``F`` must be known.

        INPUT:

        ``F`` - numerical ring

        kwds:

        - ``point_tolerance`` - positive real number (optional, default=10^(-10)).
          For numerically inexact fields, two points are considered the same
          if their coordinates are within tolerance.

        - ``zero_tolerance`` - positive real number (optional, default=10^(-10)).
          For numerically inexact fields, points are on the subscheme if they
          satisfy the equations to within tolerance.

        OUTPUT: A list of points in the ambient space.

        .. WARNING::

           For numerically inexact fields the list of points returned may contain repeated
           or be missing points due to tolerance.

        EXAMPLES::

            sage: P.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: E = P.subscheme([y^3 - x^3 - x*z^2, x*y*z])
            sage: L = E(QQ).numerical_points(F=RR); L
            [(0.000000000000000 : 0.000000000000000 : 1.00000000000000),
             (1.00000000000000 : 1.00000000000000 : 0.000000000000000)]
            sage: L[0].codomain()
            Projective Space of dimension 2 over Real Field with 53 bits of precision

        ::

            sage: S.<a> = QQ[]
            sage: K.<v> = NumberField(a^5 - 7, embedding=CC((7)**(1/5)))
            sage: P.<x,y,z> = ProjectiveSpace(K,2)
            sage: X = P.subscheme([x^2 - v^2*z^2, y-v*z])
            sage: len(X(K).numerical_points(F=CDF))
            2

        ::

            sage: P.<x1, x2, x3> = ProjectiveSpace(QQ, 2)
            sage: E = P.subscheme([3000*x1^50 + 9875643*x2^2*x3^48 + 12334545*x2^50, x1 + x2])
            sage: len(E(P.base_ring()).numerical_points(F=CDF, zero_tolerance=1e-6))
            49

        TESTS::

            sage: P.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: E = P.subscheme([y^3 - x^3 - x*z^2, x*y*z])
            sage: E(QQ).numerical_points(F=CDF, point_tolerance=-1)
            Traceback (most recent call last):
            ...
            ValueError: tolerance must be positive

        ::

            sage: P.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: E = P.subscheme([y^3 - x^3 - x*z^2, x*y*z])
            sage: E(QQ).numerical_points(F=CC, zero_tolerance=-1)
            Traceback (most recent call last):
            ...
            ValueError: tolerance must be positive

        ::

            sage: P.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: E = P.subscheme([y^3 - x^3 - x*z^2, x*y*z])
            sage: E(QQ).numerical_points(F=QQbar)
            Traceback (most recent call last):
            ...
            TypeError: F must be a numerical field
        """
        from sage.schemes.projective.projective_space import is_ProjectiveSpace
        if F is None:
            F = CC
        if F not in Fields() or not hasattr(F, 'precision'):
            raise TypeError('F must be a numerical field')
        X = self.codomain()
        if X.base_ring() not in NumberFields():
            raise TypeError('base ring must be a number field')

        PP = X.ambient_space().change_ring(F)
        if not is_ProjectiveSpace(X) and X.base_ring() in Fields():
            #Then it must be a subscheme
            dim_ideal = X.defining_ideal().dimension()
            if dim_ideal < 1:  # no points
                return []
            if dim_ideal == 1:  # if X zero-dimensional
                pt_tol = RR(kwds.pop('point_tolerance', 10**(-10)))
                zero_tol = RR(kwds.pop('zero_tolerance', 10**(-10)))
                if pt_tol <= 0 or zero_tol <= 0:
                    raise ValueError("tolerance must be positive")
                rat_points = set()
                PS = X.ambient_space()
                N = PS.dimension_relative()
                BR = X.base_ring()
                #need a lexicographic ordering for elimination
                R = PolynomialRing(BR, N + 1, PS.variable_names(), order='lex')
                RF = R.change_ring(F)
                I = R.ideal(X.defining_polynomials())
                #Determine the points through elimination
                #This is much faster than using the I.variety() function on each affine chart.
                for k in range(N + 1):
                    #create the elimination ideal for the kth affine patch
                    G = I.substitute({R.gen(k): 1}).groebner_basis()
                    G = [RF(g) for g in G]
                    if G != [1]:
                        P = {}
                        #keep track that we know the kth coordinate is 1
                        P.update({RF.gen(k): 1})
                        points = [P]
                        #work backwards from solving each equation for the possible
                        #values of the next coordinate
                        for i in range(len(G) - 1, -1, -1):
                            new_points = []
                            good = 0
                            for P in points:
                                #substitute in our dictionary entry that has the values
                                #of coordinates known so far. This results in a single
                                #variable polynomial (by elimination)
                                L = G[i].substitute(P)
                                if len(RF(L).variables()) == 1:
                                    for pol in L.univariate_polynomial().roots(
                                            ring=F, multiplicities=False):
                                        r = L.variables()[0]
                                        varindex = RF.gens().index(r)
                                        P.update({RF.gen(varindex): pol})
                                        new_points.append(copy(P))
                                        good = 1
                                else:
                                    new_points.append(P)
                                    good = 1
                            if good:
                                points = new_points
                        #the dictionary entries now have values for all coordinates
                        #they are approximate solutions to the equations
                        #make them into projective points
                        polys = [
                            g.change_ring(F) for g in X.defining_polynomials()
                        ]
                        for i in range(len(points)):
                            if len(points[i]) == N + 1:
                                S = PP([
                                    points[i][RF.gen(j)] for j in range(N + 1)
                                ])
                                S.normalize_coordinates()
                                if all(g(list(S)) < zero_tol for g in polys):
                                    rat_points.add(S)
                        # remove duplicate element using tolerance
                        #since they are normalized we can just compare coefficients
                        dupl_points = list(rat_points)
                        for i in range(len(dupl_points)):
                            u = dupl_points[i]
                            for j in range(i + 1, len(dupl_points)):
                                v = dupl_points[j]
                                if all((u[k] - v[k]).abs() < pt_tol
                                       for k in range(len(u))):
                                    rat_points.remove(u)
                                    break

                rat_points = sorted(rat_points)
                return rat_points
            raise NotImplementedError(
                'numerical approximation of points only for dimension 0 subschemes'
            )
Beispiel #22
0
def Curve(F, A=None):
    """
    Return the plane or space curve defined by ``F``, where
    ``F`` can be either a multivariate polynomial, a list or
    tuple of polynomials, or an algebraic scheme.

    If no ambient space is passed in for ``A``, and if ``F`` is not
    an algebraic scheme, a new ambient space is constructed.

    Also not specifying an ambient space will cause the curve to be defined
    in either affine or projective space based on properties of ``F``. In
    particular, if ``F`` contains a nonhomogenous polynomial, the curve is
    affine, and if ``F`` consists of homogenous polynomials, then the curve
    is projective.

    INPUT:

    - ``F`` -- a multivariate polynomial, or a list or tuple of polynomials, or an algebraic scheme.

    - ``A`` -- (default: None) an ambient space in which to create the curve.

    EXAMPLE: A projective plane curve

    ::

        sage: x,y,z = QQ['x,y,z'].gens()
        sage: C = Curve(x^3 + y^3 + z^3); C
        Projective Plane Curve over Rational Field defined by x^3 + y^3 + z^3
        sage: C.genus()
        1

    EXAMPLE: Affine plane curves

    ::

        sage: x,y = GF(7)['x,y'].gens()
        sage: C = Curve(y^2 + x^3 + x^10); C
        Affine Plane Curve over Finite Field of size 7 defined by x^10 + x^3 + y^2
        sage: C.genus()
        0
        sage: x, y = QQ['x,y'].gens()
        sage: Curve(x^3 + y^3 + 1)
        Affine Plane Curve over Rational Field defined by x^3 + y^3 + 1

    EXAMPLE: A projective space curve

    ::

        sage: x,y,z,w = QQ['x,y,z,w'].gens()
        sage: C = Curve([x^3 + y^3 - z^3 - w^3, x^5 - y*z^4]); C
        Projective Curve over Rational Field defined by x^3 + y^3 - z^3 - w^3, x^5 - y*z^4
        sage: C.genus()
        13

    EXAMPLE: An affine space curve

    ::

        sage: x,y,z = QQ['x,y,z'].gens()
        sage: C = Curve([y^2 + x^3 + x^10 + z^7,  x^2 + y^2]); C
        Affine Curve over Rational Field defined by x^10 + z^7 + x^3 + y^2, x^2 + y^2
        sage: C.genus()
        47

    EXAMPLE: We can also make non-reduced non-irreducible curves.

    ::

        sage: x,y,z = QQ['x,y,z'].gens()
        sage: Curve((x-y)*(x+y))
        Projective Conic Curve over Rational Field defined by x^2 - y^2
        sage: Curve((x-y)^2*(x+y)^2)
        Projective Plane Curve over Rational Field defined by x^4 - 2*x^2*y^2 + y^4

    EXAMPLE: A union of curves is a curve.

    ::

        sage: x,y,z = QQ['x,y,z'].gens()
        sage: C = Curve(x^3 + y^3 + z^3)
        sage: D = Curve(x^4 + y^4 + z^4)
        sage: C.union(D)
        Projective Plane Curve over Rational Field defined by
        x^7 + x^4*y^3 + x^3*y^4 + y^7 + x^4*z^3 + y^4*z^3 + x^3*z^4 + y^3*z^4 + z^7

    The intersection is not a curve, though it is a scheme.

    ::

        sage: X = C.intersection(D); X
        Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:
         x^3 + y^3 + z^3,
         x^4 + y^4 + z^4

    Note that the intersection has dimension `0`.

    ::

        sage: X.dimension()
        0
        sage: I = X.defining_ideal(); I
        Ideal (x^3 + y^3 + z^3, x^4 + y^4 + z^4) of Multivariate Polynomial Ring in x, y, z over Rational Field

    EXAMPLE: In three variables, the defining equation must be
    homogeneous.

    If the parent polynomial ring is in three variables, then the
    defining ideal must be homogeneous.

    ::

        sage: x,y,z = QQ['x,y,z'].gens()
        sage: Curve(x^2+y^2)
        Projective Conic Curve over Rational Field defined by x^2 + y^2
        sage: Curve(x^2+y^2+z)
        Traceback (most recent call last):
        ...
        TypeError: x^2 + y^2 + z is not a homogeneous polynomial

    The defining polynomial must always be nonzero::

        sage: P1.<x,y> = ProjectiveSpace(1,GF(5))
        sage: Curve(0*x)
        Traceback (most recent call last):
        ...
        ValueError: defining polynomial of curve must be nonzero

    ::

        sage: A.<x,y,z> = AffineSpace(QQ, 3)
        sage: C = Curve([y - x^2, z - x^3], A)
        sage: A == C.ambient_space()
        True
    """
    if not A is None:
        if not isinstance(F, (list, tuple)):
            return Curve([F], A)
        if not is_AmbientSpace(A):
            raise TypeError(
                "A (=%s) must be either an affine or projective space" % A)
        if not all([f.parent() == A.coordinate_ring() for f in F]):
            raise TypeError("F (=%s) must be a list or tuple of polynomials of the coordinate ring of " \
            "A (=%s)"%(F, A))
        n = A.dimension_relative()
        if n < 2:
            raise TypeError(
                "A (=%s) must be either an affine or projective space of dimension > 1"
                % A)
        # there is no dimension check when initializing a plane curve, so check here that F consists
        # of a single nonconstant polynomial
        if n == 2:
            if len(F) != 1 or F[0] == 0 or not is_MPolynomial(F[0]):
                raise TypeError(
                    "F (=%s) must consist of a single nonconstant polynomial to define a plane curve"
                    % (F, ))
        if is_AffineSpace(A):
            if n > 2:
                return AffineCurve(A, F)
            k = A.base_ring()
            if is_FiniteField(k):
                if k.is_prime_field():
                    return AffinePlaneCurve_prime_finite_field(A, F[0])
                return AffinePlaneCurve_finite_field(A, F[0])
            return AffinePlaneCurve(A, F[0])
        elif is_ProjectiveSpace(A):
            if not all([f.is_homogeneous() for f in F]):
                raise TypeError(
                    "polynomials defining a curve in a projective space must be homogeneous"
                )
            if n > 2:
                return ProjectiveCurve(A, F)
            k = A.base_ring()
            if is_FiniteField(k):
                if k.is_prime_field():
                    return ProjectivePlaneCurve_prime_finite_field(A, F[0])
                return ProjectivePlaneCurve_finite_field(A, F[0])
            return ProjectivePlaneCurve(A, F[0])

    if is_AlgebraicScheme(F):
        return Curve(F.defining_polynomials(), F.ambient_space())

    if isinstance(F, (list, tuple)):
        if len(F) == 1:
            return Curve(F[0])
        F = Sequence(F)
        P = F.universe()
        if not is_MPolynomialRing(P):
            raise TypeError(
                "universe of F must be a multivariate polynomial ring")

        for f in F:
            if not f.is_homogeneous():
                A = AffineSpace(P.ngens(), P.base_ring())
                A._coordinate_ring = P
                return AffineCurve(A, F)

        A = ProjectiveSpace(P.ngens() - 1, P.base_ring())
        A._coordinate_ring = P
        return ProjectiveCurve(A, F)

    if not is_MPolynomial(F):
        raise TypeError("F (=%s) must be a multivariate polynomial" % F)

    P = F.parent()
    k = F.base_ring()
    if F.parent().ngens() == 2:
        if F == 0:
            raise ValueError("defining polynomial of curve must be nonzero")
        A2 = AffineSpace(2, P.base_ring())
        A2._coordinate_ring = P

        if is_FiniteField(k):
            if k.is_prime_field():
                return AffinePlaneCurve_prime_finite_field(A2, F)
            else:
                return AffinePlaneCurve_finite_field(A2, F)
        else:
            return AffinePlaneCurve(A2, F)

    elif F.parent().ngens() == 3:
        if F == 0:
            raise ValueError("defining polynomial of curve must be nonzero")
        P2 = ProjectiveSpace(2, P.base_ring())
        P2._coordinate_ring = P

        if F.total_degree() == 2 and k.is_field():
            return Conic(F)

        if is_FiniteField(k):
            if k.is_prime_field():
                return ProjectivePlaneCurve_prime_finite_field(P2, F)
            else:
                return ProjectivePlaneCurve_finite_field(P2, F)
        else:
            return ProjectivePlaneCurve(P2, F)

    else:

        raise TypeError("Number of variables of F (=%s) must be 2 or 3" % F)
def enum_projective_finite_field(X):
    """
    Enumerates projective points on scheme ``X`` defined over a finite field.

    INPUT:

    - ``X`` -  a scheme defined over a finite field or a set of abstract
      rational points of such a scheme.

    OUTPUT:

    - a list containing the projective points of ``X`` over the finite field,
      sorted.

    EXAMPLES::

        sage: F = GF(53)
        sage: P.<X,Y,Z> = ProjectiveSpace(2,F)
        sage: from sage.schemes.projective.projective_rational_point import enum_projective_finite_field
        sage: len(enum_projective_finite_field(P(F)))
        2863
        sage: 53^2+53+1
        2863

    ::

        sage: F = GF(9,'a')
        sage: P.<X,Y,Z> = ProjectiveSpace(2,F)
        sage: C = Curve(X^3-Y^3+Z^2*Y)
        sage: enum_projective_finite_field(C(F))
        [(0 : 0 : 1), (0 : 1 : 1), (0 : 2 : 1), (1 : 1 : 0), (a + 1 : 2*a : 1),
        (a + 1 : 2*a + 1 : 1), (a + 1 : 2*a + 2 : 1), (2*a + 2 : a : 1),
        (2*a + 2 : a + 1 : 1), (2*a + 2 : a + 2 : 1)]

    ::

        sage: F = GF(5)
        sage: P2F.<X,Y,Z> = ProjectiveSpace(2,F)
        sage: enum_projective_finite_field(P2F)
        [(0 : 0 : 1), (0 : 1 : 0), (0 : 1 : 1), (0 : 2 : 1), (0 : 3 : 1), (0 : 4 : 1),
        (1 : 0 : 0), (1 : 0 : 1), (1 : 1 : 0), (1 : 1 : 1), (1 : 2 : 1), (1 : 3 : 1),
        (1 : 4 : 1), (2 : 0 : 1), (2 : 1 : 0), (2 : 1 : 1), (2 : 2 : 1), (2 : 3 : 1),
        (2 : 4 : 1), (3 : 0 : 1), (3 : 1 : 0), (3 : 1 : 1), (3 : 2 : 1), (3 : 3 : 1),
        (3 : 4 : 1), (4 : 0 : 1), (4 : 1 : 0), (4 : 1 : 1), (4 : 2 : 1), (4 : 3 : 1),
        (4 : 4 : 1)]

    ALGORITHM:

    Checks all points in projective space to see if they lie on ``X``.

    .. WARNING::

        If ``X`` is defined over an infinite field, this code will not finish!

    AUTHORS:

    - John Cremona and Charlie Turner (06-2010).
    """
    from sage.schemes.projective.projective_space import is_ProjectiveSpace
    if (is_Scheme(X)):
        if (not is_ProjectiveSpace(X.ambient_space())):
            raise TypeError(
                "ambient space must be projective space over a finite")
        X = X(X.base_ring())
    else:
        if (not is_ProjectiveSpace(X.codomain().ambient_space())):
            raise TypeError(
                "codomain must be projective space over a finite field")

    n = X.codomain().ambient_space().ngens() - 1
    F = X.value_ring()
    pts = []
    for k in range(n + 1):
        for c in cartesian_product_iterator([F for _ in range(k)]):
            try:
                pts.append(X(list(c) + [1] + [0] * (n - k)))
            except TypeError:
                pass
    pts.sort()
    return pts
Beispiel #24
0
def enum_projective_number_field(X, **kwds):
    """
    Enumerates projective points on scheme ``X`` defined over a number field.

    Simply checks all of the points of absolute height of at most ``B``
    and adds those that are on the scheme to the list.

    This algorithm computes 2 lists: L containing elements x in `K` such that
    H_k(x) <= B, and a list L' containing elements x in `K` that, due to
    floating point issues,
    may be slightly larger then the bound. This can be controlled
    by lowering the tolerance.

    ALGORITHM:

    This is an implementation of the revised algorithm (Algorithm 4) in
    [DK2013]_. Algorithm 5 is used for imaginary quadratic fields.
    
    INPUT:

    kwds:

    - ``bound`` - a real number

    - ``tolerance`` - a rational number in (0,1] used in doyle-krumm algorithm-4

    - ``precision`` - the precision to use for computing the elements of bounded height of number fields.

    OUTPUT:

     - a list containing the projective points of ``X`` of absolute height up to ``B``,
       sorted.

    EXAMPLES::

        sage: from sage.schemes.projective.projective_rational_point import enum_projective_number_field
        sage: u = QQ['u'].0
        sage: K = NumberField(u^3 - 5,'v')
        sage: P.<x,y,z> = ProjectiveSpace(K, 2)
        sage: X = P.subscheme([x - y])
        sage: enum_projective_number_field(X(K), bound=RR(5^(1/3)), prec=2^10)
        [(0 : 0 : 1), (-1 : -1 : 1), (1 : 1 : 1), (-1/5*v^2 : -1/5*v^2 : 1), (-v : -v : 1),
        (1/5*v^2 : 1/5*v^2 : 1), (v : v : 1), (1 : 1 : 0)]

    ::

        sage: u = QQ['u'].0
        sage: K = NumberField(u^2 + 3, 'v')
        sage: A.<x,y> = ProjectiveSpace(K,1)
        sage: X = A.subscheme(x-y)
        sage: from sage.schemes.projective.projective_rational_point import enum_projective_number_field
        sage: enum_projective_number_field(X, bound=2)
        [(1 : 1)]
    """
    B = kwds.pop('bound')
    tol = kwds.pop('tolerance', 1e-2)
    prec = kwds.pop('precision', 53)
    from sage.schemes.projective.projective_space import is_ProjectiveSpace
    if is_Scheme(X):
        if (not is_ProjectiveSpace(X.ambient_space())):
            raise TypeError(
                "ambient space must be projective space over a number field")
        X = X(X.base_ring())
    else:
        if (not is_ProjectiveSpace(X.codomain().ambient_space())):
            raise TypeError(
                "codomain must be projective space over a number field")

    R = X.codomain().ambient_space()

    pts = []

    for P in R.points_of_bounded_height(bound=B, tolerance=tol,
                                        precision=prec):
        try:
            pts.append(X(P))
        except TypeError:
            pass
    pts.sort()
    return pts
def enum_projective_finite_field(X):
    """
    Enumerates projective points on scheme ``X`` defined over a finite field.

    INPUT:

    - ``X`` -  a scheme defined over a finite field or a set of abstract
      rational points of such a scheme.

    OUTPUT:

    - a list containing the projective points of ``X`` over the finite field,
      sorted.

    EXAMPLES::

        sage: F = GF(53)
        sage: P.<X,Y,Z> = ProjectiveSpace(2,F)
        sage: from sage.schemes.projective.projective_rational_point import enum_projective_finite_field
        sage: len(enum_projective_finite_field(P(F)))
        2863
        sage: 53^2+53+1
        2863

    ::

        sage: F = GF(9,'a')
        sage: P.<X,Y,Z> = ProjectiveSpace(2,F)
        sage: C = Curve(X^3-Y^3+Z^2*Y)
        sage: enum_projective_finite_field(C(F))
        [(0 : 0 : 1), (0 : 1 : 1), (0 : 2 : 1), (1 : 1 : 0), (a + 1 : 2*a : 1),
        (a + 1 : 2*a + 1 : 1), (a + 1 : 2*a + 2 : 1), (2*a + 2 : a : 1),
        (2*a + 2 : a + 1 : 1), (2*a + 2 : a + 2 : 1)]

    ::

        sage: F = GF(5)
        sage: P2F.<X,Y,Z> = ProjectiveSpace(2,F)
        sage: enum_projective_finite_field(P2F)
        [(0 : 0 : 1), (0 : 1 : 0), (0 : 1 : 1), (0 : 2 : 1), (0 : 3 : 1), (0 : 4 : 1),
        (1 : 0 : 0), (1 : 0 : 1), (1 : 1 : 0), (1 : 1 : 1), (1 : 2 : 1), (1 : 3 : 1),
        (1 : 4 : 1), (2 : 0 : 1), (2 : 1 : 0), (2 : 1 : 1), (2 : 2 : 1), (2 : 3 : 1),
        (2 : 4 : 1), (3 : 0 : 1), (3 : 1 : 0), (3 : 1 : 1), (3 : 2 : 1), (3 : 3 : 1),
        (3 : 4 : 1), (4 : 0 : 1), (4 : 1 : 0), (4 : 1 : 1), (4 : 2 : 1), (4 : 3 : 1),
        (4 : 4 : 1)]

    ALGORITHM:

    Checks all points in projective space to see if they lie on X.

    .. WARNING::

        If ``X`` is defined over an infinite field, this code will not finish!

    AUTHORS:

    - John Cremona and Charlie Turner (06-2010).
    """
    from sage.schemes.projective.projective_space import is_ProjectiveSpace
    if(is_Scheme(X)):
        if (not is_ProjectiveSpace(X.ambient_space())):
            raise TypeError("Ambient space must be projective space over a finite")
        X = X(X.base_ring())
    else:
        if (not is_ProjectiveSpace(X.codomain().ambient_space())):
            raise TypeError("Codomain must be projective space over a finite field")

    n = X.codomain().ambient_space().ngens()-1
    F = X.value_ring()
    pts = []
    for k in range(n+1):
        for c in cartesian_product_iterator([F for _ in range(k)]):
            try:
                pts.append(X(list(c)+[1]+[0]*(n-k)))
            except TypeError:
                pass
    pts.sort()
    return pts
def enum_projective_number_field(X,B, prec=53):
    """
    Enumerates projective points on scheme ``X`` defined over a number field. Simply checks all of the
    points of absolute height of at most ``B`` and adds those that are on the scheme to the list.

    INPUT:

    - ``X`` - a scheme defined over a number field

    - ``B`` - a real number

    - ``prec`` - the precision to use for computing the elements of bounded height of number fields

    OUTPUT:

     - a list containing the projective points of ``X`` of absolute height up to ``B``,
       sorted.

    .. WARNING::

       In the current implementation, the output of the [Doyle-Krumm] algorithm
       for elements of bounded height cannot be guaranteed to be correct due to
       the necessity of floating point computations. In some cases, the default
       53-bit precision is considerably lower than would be required for the
       algorithm to generate correct output.

    EXAMPLES::

        sage: from sage.schemes.projective.projective_rational_point import enum_projective_number_field
        sage: u = QQ['u'].0
        sage: K = NumberField(u^3 - 5,'v')
        sage: P.<x,y,z> = ProjectiveSpace(K, 2)
        sage: X = P.subscheme([x - y])
        sage: enum_projective_number_field(X(K), 5^(1/3), prec=2^10)
        [(0 : 0 : 1), (-1 : -1 : 1), (1 : 1 : 1), (-1/5*v^2 : -1/5*v^2 : 1), (-v : -v : 1),
        (1/5*v^2 : 1/5*v^2 : 1), (v : v : 1), (1 : 1 : 0)]

    ::

        sage: u = QQ['u'].0
        sage: K = NumberField(u^2 + 3, 'v')
        sage: A.<x,y> = ProjectiveSpace(K,1)
        sage: X=A.subscheme(x-y)
        sage: from sage.schemes.projective.projective_rational_point import enum_projective_number_field
        sage: enum_projective_number_field(X, 2)
        [(1 : 1)]
    """
    from sage.schemes.projective.projective_space import is_ProjectiveSpace
    if(is_Scheme(X)):
        if (not is_ProjectiveSpace(X.ambient_space())):
            raise TypeError("Ambient space must be projective space over a number field")
        X = X(X.base_ring())
    else:
        if (not is_ProjectiveSpace(X.codomain().ambient_space())):
            raise TypeError("Codomain must be projective space over a number field")

    R = X.codomain().ambient_space()

    pts = []

    for P in R.points_of_bounded_height(B, prec):
        try:
            pts.append(X(P))
        except TypeError:
            pass
    pts.sort()
    return pts
Beispiel #27
0
    def points(self, B=0, prec=53):
        """
        Return some or all rational points of a projective scheme.

        INPUT:

        - ``B`` - integer (optional, default=0). The bound for the
          coordinates.

        - ``prec`` - he precision to use to compute the elements of bounded height for number fields.

        OUTPUT:

        A list of points. Over a finite field, all points are
        returned. Over an infinite field, all points satisfying the
        bound are returned.

        .. WARNING::

           In the current implementation, the output of the [Doyle-Krumm] algorithm
           cannot be guaranteed to be correct due to the necessity of floating point
           computations. In some cases, the default 53-bit precision is
           considerably lower than would be required for the algorithm to
           generate correct output.

        EXAMPLES::

            sage: P.<x,y> = ProjectiveSpace(QQ,1)
            sage: P(QQ).points(4)
            [(-4 : 1), (-3 : 1), (-2 : 1), (-3/2 : 1), (-4/3 : 1), (-1 : 1),
            (-3/4 : 1), (-2/3 : 1), (-1/2 : 1), (-1/3 : 1), (-1/4 : 1), (0 : 1),
            (1/4 : 1), (1/3 : 1), (1/2 : 1), (2/3 : 1), (3/4 : 1), (1 : 0), (1 : 1),
            (4/3 : 1), (3/2 : 1), (2 : 1), (3 : 1), (4 : 1)]

        ::

            sage: u = QQ['u'].0
            sage: K.<v> = NumberField(u^2 + 3)
            sage: P.<x,y,z> = ProjectiveSpace(K,2)
            sage: len(P(K).points(1.8))
            381

        ::

            sage: P1 = ProjectiveSpace(GF(2),1)
            sage: F.<a> = GF(4,'a')
            sage: P1(F).points()
            [(0 : 1), (1 : 0), (1 : 1), (a : 1), (a + 1 : 1)]

        ::

            sage: P.<x,y,z> = ProjectiveSpace(QQ,2)
            sage: E = P.subscheme([(y^3-y*z^2) - (x^3-x*z^2),(y^3-y*z^2) + (x^3-x*z^2)])
            sage: E(P.base_ring()).points()
            [(-1 : -1 : 1), (-1 : 0 : 1), (-1 : 1 : 1), (0 : -1 : 1), (0 : 0 : 1), (0 : 1 : 1),
            (1 : -1 : 1), (1 : 0 : 1), (1 : 1 : 1)]
        """
        X = self.codomain()

        from sage.schemes.projective.projective_space import is_ProjectiveSpace
        if not is_ProjectiveSpace(X) and X.base_ring() in Fields():
            #Then it must be a subscheme
            dim_ideal = X.defining_ideal().dimension()
            if dim_ideal < 1: # no points
                return []
            if dim_ideal == 1: # if X zero-dimensional
                points = set()
                for i in range(X.ambient_space().dimension_relative() + 1):
                    Y = X.affine_patch(i)
                    phi = Y.projective_embedding()
                    aff_points = Y.rational_points()
                    for PP in aff_points:
                        points.add(X.ambient_space()(list(phi(PP))))
                points = sorted(points)
                return points
        R = self.value_ring()
        if is_RationalField(R):
            if not B > 0:
                raise TypeError("a positive bound B (= %s) must be specified"%B)
            from sage.schemes.projective.projective_rational_point import enum_projective_rational_field
            return enum_projective_rational_field(self,B)
        elif R in NumberFields():
            if not B > 0:
                raise TypeError("a positive bound B (= %s) must be specified"%B)
            from sage.schemes.projective.projective_rational_point import enum_projective_number_field
            return enum_projective_number_field(self,B, prec=prec)
        elif is_FiniteField(R):
            from sage.schemes.projective.projective_rational_point import enum_projective_finite_field
            return enum_projective_finite_field(self.extended_codomain())
        else:
            raise TypeError("unable to enumerate points over %s"%R)
Beispiel #28
0
def Curve(F, A=None):
    """
    Return the plane or space curve defined by ``F``, where ``F`` can be either
    a multivariate polynomial, a list or tuple of polynomials, or an algebraic
    scheme.

    If no ambient space is passed in for ``A``, and if ``F`` is not an
    algebraic scheme, a new ambient space is constructed.

    Also not specifying an ambient space will cause the curve to be defined in
    either affine or projective space based on properties of ``F``. In
    particular, if ``F`` contains a nonhomogenous polynomial, the curve is
    affine, and if ``F`` consists of homogenous polynomials, then the curve is
    projective.

    INPUT:

    - ``F`` -- a multivariate polynomial, or a list or tuple of polynomials, or an algebraic scheme.

    - ``A`` -- (default: None) an ambient space in which to create the curve.

    EXAMPLES: A projective plane curve.  ::

        sage: x,y,z = QQ['x,y,z'].gens()
        sage: C = Curve(x^3 + y^3 + z^3); C
        Projective Plane Curve over Rational Field defined by x^3 + y^3 + z^3
        sage: C.genus()
        1

    Affine plane curves.  ::

        sage: x,y = GF(7)['x,y'].gens()
        sage: C = Curve(y^2 + x^3 + x^10); C
        Affine Plane Curve over Finite Field of size 7 defined by x^10 + x^3 + y^2
        sage: C.genus()
        0
        sage: x, y = QQ['x,y'].gens()
        sage: Curve(x^3 + y^3 + 1)
        Affine Plane Curve over Rational Field defined by x^3 + y^3 + 1

    A projective space curve.  ::

        sage: x,y,z,w = QQ['x,y,z,w'].gens()
        sage: C = Curve([x^3 + y^3 - z^3 - w^3, x^5 - y*z^4]); C
        Projective Curve over Rational Field defined by x^3 + y^3 - z^3 - w^3, x^5 - y*z^4
        sage: C.genus()
        13

    An affine space curve.  ::

        sage: x,y,z = QQ['x,y,z'].gens()
        sage: C = Curve([y^2 + x^3 + x^10 + z^7,  x^2 + y^2]); C
        Affine Curve over Rational Field defined by x^10 + z^7 + x^3 + y^2, x^2 + y^2
        sage: C.genus()
        47

    We can also make non-reduced non-irreducible curves.  ::

        sage: x,y,z = QQ['x,y,z'].gens()
        sage: Curve((x-y)*(x+y))
        Projective Conic Curve over Rational Field defined by x^2 - y^2
        sage: Curve((x-y)^2*(x+y)^2)
        Projective Plane Curve over Rational Field defined by x^4 - 2*x^2*y^2 + y^4

    A union of curves is a curve.  ::

        sage: x,y,z = QQ['x,y,z'].gens()
        sage: C = Curve(x^3 + y^3 + z^3)
        sage: D = Curve(x^4 + y^4 + z^4)
        sage: C.union(D)
        Projective Plane Curve over Rational Field defined by
        x^7 + x^4*y^3 + x^3*y^4 + y^7 + x^4*z^3 + y^4*z^3 + x^3*z^4 + y^3*z^4 + z^7

    The intersection is not a curve, though it is a scheme.  ::

        sage: X = C.intersection(D); X
        Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:
         x^3 + y^3 + z^3,
         x^4 + y^4 + z^4

    Note that the intersection has dimension 0.  ::

        sage: X.dimension()
        0
        sage: I = X.defining_ideal(); I
        Ideal (x^3 + y^3 + z^3, x^4 + y^4 + z^4) of Multivariate Polynomial Ring in x, y, z over Rational Field

    If only a polynomial in three variables is given, then it must be
    homogeneous such that a projective curve is constructed.  ::

        sage: x,y,z = QQ['x,y,z'].gens()
        sage: Curve(x^2+y^2)
        Projective Conic Curve over Rational Field defined by x^2 + y^2
        sage: Curve(x^2+y^2+z)
        Traceback (most recent call last):
        ...
        TypeError: x^2 + y^2 + z is not a homogeneous polynomial

    An ambient space can be specified to construct a space curve in an affine
    or a projective space.  ::

        sage: A.<x,y,z> = AffineSpace(QQ, 3)
        sage: C = Curve([y - x^2, z - x^3], A)
        sage: C
        Affine Curve over Rational Field defined by -x^2 + y, -x^3 + z
        sage: A == C.ambient_space()
        True

    The defining polynomial must be nonzero unless the ambient space itself is
    of dimension 1. ::

        sage: P1.<x,y> = ProjectiveSpace(1,GF(5))
        sage: S = P1.coordinate_ring()
        sage: Curve(S(0), P1)
        Projective Line over Finite Field of size 5
        sage: Curve(P1)
        Projective Line over Finite Field of size 5

    ::

        sage: A1.<x> = AffineSpace(1, QQ)
        sage: R = A1.coordinate_ring()
        sage: Curve(R(0), A1)
        Affine Line over Rational Field
        sage: Curve(A1)
        Affine Line over Rational Field

    """
    if A is None:
        if is_AmbientSpace(F) and F.dimension() == 1:
            return Curve(F.coordinate_ring().zero(), F)

        if is_AlgebraicScheme(F):
            return Curve(F.defining_polynomials(), F.ambient_space())

        if isinstance(F, (list, tuple)):
            P = Sequence(F).universe()
            if not is_MPolynomialRing(P):
                raise TypeError("universe of F must be a multivariate polynomial ring")
            for f in F:
                if not f.is_homogeneous():
                    A = AffineSpace(P.ngens(), P.base_ring(), names=P.variable_names())
                    A._coordinate_ring = P
                    break
            else:
                A = ProjectiveSpace(P.ngens()-1, P.base_ring(), names=P.variable_names())
                A._coordinate_ring = P
        elif is_MPolynomial(F): # define a plane curve
            P = F.parent()
            k = F.base_ring()

            if not k.is_field():
                if k.is_integral_domain():  # upgrade to a field
                    P = P.change_ring(k.fraction_field())
                    F = P(F)
                    k = F.base_ring()
                else:
                    raise TypeError("not a multivariate polynomial over a field or an integral domain")

            if F.parent().ngens() == 2:
                if F == 0:
                    raise ValueError("defining polynomial of curve must be nonzero")
                A = AffineSpace(2, P.base_ring(), names=P.variable_names())
                A._coordinate_ring = P
            elif F.parent().ngens() == 3:
                if F == 0:
                    raise ValueError("defining polynomial of curve must be nonzero")

                # special case: construct a conic curve
                if F.total_degree() == 2 and k.is_field():
                    return Conic(k, F)

                A = ProjectiveSpace(2, P.base_ring(), names=P.variable_names())
                A._coordinate_ring = P
            elif F.parent().ngens() == 1:
                if not F.is_zero():
                    raise ValueError("defining polynomial of curve must be zero "
                                     "if the ambient space is of dimension 1")

                A = AffineSpace(1, P.base_ring(), names=P.variable_names())
                A._coordinate_ring = P
            else:
                raise TypeError("number of variables of F (={}) must be 2 or 3".format(F))
            F = [F]
        else:
            raise TypeError("F (={}) must be a multivariate polynomial".format(F))
    else:
        if not is_AmbientSpace(A):
            raise TypeError("ambient space must be either an affine or projective space")
        if not isinstance(F, (list, tuple)):
            F = [F]
        if  not all(f.parent() == A.coordinate_ring() for f in F):
            raise TypeError("need a list of polynomials of the coordinate ring of {}".format(A))

    n = A.dimension_relative()
    if n < 1:
        raise TypeError("ambient space should be an affine or projective space of positive dimension")

    k = A.base_ring()

    if is_AffineSpace(A):
        if n != 2:
            if is_FiniteField(k):
                if A.coordinate_ring().ideal(F).is_prime():
                    return IntegralAffineCurve_finite_field(A, F)
            if k in Fields():
                if k == QQ and A.coordinate_ring().ideal(F).is_prime():
                    return IntegralAffineCurve(A, F)
                return AffineCurve_field(A, F)
            return AffineCurve(A, F)

        if not (len(F) == 1 and F[0] != 0 and F[0].degree() > 0):
            raise TypeError("need a single nonconstant polynomial to define a plane curve")

        F = F[0]
        if is_FiniteField(k):
            if _is_irreducible_and_reduced(F):
                return IntegralAffinePlaneCurve_finite_field(A, F)
            return AffinePlaneCurve_finite_field(A, F)
        if k in Fields():
            if k == QQ and _is_irreducible_and_reduced(F):
                return IntegralAffinePlaneCurve(A, F)
            return AffinePlaneCurve_field(A, F)
        return AffinePlaneCurve(A, F)

    elif is_ProjectiveSpace(A):
        if n != 2:
            if not all(f.is_homogeneous() for f in F):
                raise TypeError("polynomials defining a curve in a projective space must be homogeneous")
            if is_FiniteField(k):
                if A.coordinate_ring().ideal(F).is_prime():
                    return IntegralProjectiveCurve_finite_field(A, F)
            if k in Fields():
                if k == QQ and A.coordinate_ring().ideal(F).is_prime():
                    return IntegralProjectiveCurve(A, F)
                return ProjectiveCurve_field(A, F)
            return ProjectiveCurve(A, F)

        # There is no dimension check when initializing a plane curve, so check
        # here that F consists of a single nonconstant polynomial.
        if not (len(F) == 1 and F[0] != 0 and F[0].degree() > 0):
            raise TypeError("need a single nonconstant polynomial to define a plane curve")

        F = F[0]
        if not F.is_homogeneous():
            raise TypeError("{} is not a homogeneous polynomial".format(F))

        if is_FiniteField(k):
            if _is_irreducible_and_reduced(F):
                return IntegralProjectivePlaneCurve_finite_field(A, F)
            return ProjectivePlaneCurve_finite_field(A, F)
        if k in Fields():
            if k == QQ and _is_irreducible_and_reduced(F):
                return IntegralProjectivePlaneCurve(A, F)
            return ProjectivePlaneCurve_field(A, F)
        return ProjectivePlaneCurve(A, F)

    else:
        raise TypeError('ambient space neither affine nor projective')
Beispiel #29
0
    def points(self, B=0, prec=53):
        """
        Return some or all rational points of a projective scheme.

        INPUT:

        - `B` - integer (optional, default=0). The bound for the
          coordinates.

        - ``prec`` - he precision to use to compute the elements of bounded height for number fields

        OUTPUT:

        A list of points. Over a finite field, all points are
        returned. Over an infinite field, all points satisfying the
        bound are returned.

        .. WARNING::

           In the current implementation, the output of the [Doyle-Krumm] algorithm
           cannot be guaranteed to be correct due to the necessity of floating point
           computations. In some cases, the default 53-bit precision is
           considerably lower than would be required for the algorithm to
           generate correct output.

        EXAMPLES::

            sage: P.<x,y> = ProjectiveSpace(QQ,1)
            sage: P(QQ).points(4)
            [(-4 : 1), (-3 : 1), (-2 : 1), (-3/2 : 1), (-4/3 : 1), (-1 : 1),
            (-3/4 : 1), (-2/3 : 1), (-1/2 : 1), (-1/3 : 1), (-1/4 : 1), (0 : 1),
            (1/4 : 1), (1/3 : 1), (1/2 : 1), (2/3 : 1), (3/4 : 1), (1 : 0), (1 : 1),
            (4/3 : 1), (3/2 : 1), (2 : 1), (3 : 1), (4 : 1)]

        ::

            sage: u = QQ['u'].0
            sage: K.<v> = NumberField(u^2 + 3)
            sage: P.<x,y,z> = ProjectiveSpace(K,2)
            sage: len(P(K).points(1.8))
            381

        ::

            sage: P1 = ProjectiveSpace(GF(2),1)
            sage: F.<a> = GF(4,'a')
            sage: P1(F).points()
            [(0 : 1), (1 : 0), (1 : 1), (a : 1), (a + 1 : 1)]

        ::

            sage: P.<x,y,z> = ProjectiveSpace(QQ,2)
            sage: E = P.subscheme([(y^3-y*z^2) - (x^3-x*z^2),(y^3-y*z^2) + (x^3-x*z^2)])
            sage: E(P.base_ring()).points()
            [(-1 : -1 : 1), (-1 : 0 : 1), (-1 : 1 : 1), (0 : -1 : 1), (0 : 0 : 1), (0 : 1 : 1),
            (1 : -1 : 1), (1 : 0 : 1), (1 : 1 : 1)]
        """
        X = self.codomain()

        from sage.schemes.projective.projective_space import is_ProjectiveSpace
        if not is_ProjectiveSpace(X) and X.base_ring() in Fields():
            #Then it must be a subscheme
            dim_ideal = X.defining_ideal().dimension()
            if dim_ideal < 1: # no points
                return []
            if dim_ideal == 1: # if X zero-dimensional
                points = set()
                for i in range(X.ambient_space().dimension_relative() + 1):
                    Y = X.affine_patch(i)
                    phi = Y.projective_embedding()
                    aff_points = Y.rational_points()
                    for PP in aff_points:
                        points.add(X.ambient_space()(list(phi(PP))))
                points = sorted(points)
                return points
        R = self.value_ring()
        if is_RationalField(R):
            if not B > 0:
                raise TypeError("A positive bound B (= %s) must be specified."%B)
            from sage.schemes.projective.projective_rational_point import enum_projective_rational_field
            return enum_projective_rational_field(self,B)
        elif R in NumberFields():
            if not B > 0:
                raise TypeError("A positive bound B (= %s) must be specified."%B)
            from sage.schemes.projective.projective_rational_point import enum_projective_number_field
            return enum_projective_number_field(self,B, prec=prec)
        elif is_FiniteField(R):
            from sage.schemes.projective.projective_rational_point import enum_projective_finite_field
            return enum_projective_finite_field(self.extended_codomain())
        else:
            raise TypeError("Unable to enumerate points over %s."%R)
Beispiel #30
0
    def primes_of_bad_reduction(self, check=True):
        r"""
        Determines the primes of bad reduction for a map `self: \mathbb{P}^N \to \mathbb{P}^N`
        defined over `\ZZ` or `\QQ`.

        If ``check`` is ``True``, each prime is verified to be of bad reduction.

        ALGORITHM:

        `p` is a prime of bad reduction if and only if the defining polynomials of self
        have a common zero. Or stated another way, `p` is a prime of bad reducion if and only if the
        radical of the ideal defined by the defining polynomials of self is not `(x_0,x_1,\ldots,x_N)`.
        This happens if and only if some power of each `x_i` is not in the ideal defined by the defining
        polynomials of self. This last condition is what is checked. The lcm of the coefficients of
        the monomials `x_i` in a groebner basis is computed. This may return extra primes.

        INPUT:

        - ``check`` -- Boolean (optional - default: ``True``)

        OUTPUT:

        - a list of integer primes.

        EXAMPLES::

            sage: P.<x,y>=ProjectiveSpace(QQ,1)
            sage: H=Hom(P,P)
            sage: f=H([1/3*x^2+1/2*y^2,y^2])
            sage: print f.primes_of_bad_reduction()
            [2, 3]

        ::

            sage: P.<x,y,z,w>=ProjectiveSpace(QQ,3)
            sage: H=Hom(P,P)
            sage: f=H([12*x*z-7*y^2,31*x^2-y^2,26*z^2,3*w^2-z*w])
            sage: f.primes_of_bad_reduction()
            [2, 3, 7, 13, 31]

        ::

            This is an example where check=False returns extra primes
            sage: P.<x,y,z>=ProjectiveSpace(ZZ,2)
            sage: H=Hom(P,P)
            sage: f=H([3*x*y^2 + 7*y^3 - 4*y^2*z + 5*z^3, -5*x^3 + x^2*y + y^3 + 2*x^2*z, -2*x^2*y + x*y^2 + y^3 - 4*y^2*z + x*z^2])
            sage: f.primes_of_bad_reduction(False)
            [2, 5, 37, 2239, 304432717]
            sage: f.primes_of_bad_reduction()
            [5, 37, 2239, 304432717]

        """
        if self.base_ring() != ZZ and self.base_ring() != QQ:
            raise TypeError("Must be ZZ or QQ")
        from sage.schemes.projective.projective_space import is_ProjectiveSpace
        if is_ProjectiveSpace(self.domain())==False or is_ProjectiveSpace(self.codomain())==False:
            raise NotImplementedError
        R=self.coordinate_ring()
        F=self._polys
        if R.base_ring().is_field():
            J=R.ideal(F)
        else:
            S=PolynomialRing(R.base_ring().fraction_field(),R.gens(),R.ngens())
            J=S.ideal([S.coerce(F[i]) for i in range(R.ngens())])
        if J.dimension()>0:
            raise TypeError("Not a morphism.")
        #normalize to coefficients in the ring not the fraction field.
        F=[F[i]*lcm([F[j].denominator() for j in range(len(F))]) for i in range(len(F))]

        #move the ideal to the ring of integers
        if R.base_ring().is_field():
            S=PolynomialRing(R.base_ring().ring_of_integers(),R.gens(),R.ngens())
            F=[F[i].change_ring(R.base_ring().ring_of_integers()) for i in range(len(F))]
            J=S.ideal(F)
        else:
            J=R.ideal(F)
        GB=J.groebner_basis()
        badprimes=[]

        #get the primes dividing the coefficients of the monomials x_i^k_i
        for i in range(len(GB)):
            LT=GB[i].lt().degrees()
            power=0
            for j in range(R.ngens()):
                if LT[j]!=0:
                    power+=1
            if power==1:
                badprimes=badprimes+GB[i].lt().coefficients()[0].support()
        badprimes=list(set(badprimes))
        badprimes.sort()

        #check to return only the truly bad primes
        if check==True:
            index=0
            while index < len(badprimes):  #figure out which primes are really bad primes...
                S=PolynomialRing(GF(badprimes[index]),R.gens(),R.ngens())
                J=S.ideal([S.coerce(F[j]) for j in range(R.ngens())])
                if J.dimension()==0:
                    badprimes.pop(index)
                else:
                    index+=1
        return(badprimes)
Beispiel #31
0
    def _coerce_map_from_(self, other):
        r"""
        Return true if ``other`` canonically coerces to ``self``.

        EXAMPLES::

            sage: R.<t> = QQ[]
            sage: P = ProjectiveSpace(QQ, 1, 'x')
            sage: P2 = ProjectiveSpace(R, 1, 'x')
            sage: P2(R)._coerce_map_from_(P(QQ))
            True
            sage: P(QQ)._coerce_map_from_(P2(R))
            False

        ::

            sage: P = ProjectiveSpace(QQ, 1, 'x')
            sage: P2 = ProjectiveSpace(CC, 1, 'y')
            sage: P2(CC)._coerce_map_from_(P(QQ))
            False

        ::

            sage: A.<x,y,z> = AffineSpace(QQ, 3)
            sage: H = A.subscheme(z)
            sage: L = A.subscheme([z, y+z])
            sage: A(QQ)._coerce_map_from_(H(QQ))
            True
            sage: H(QQ)._coerce_map_from_(L(QQ))
            True
            sage: L(QQ).has_coerce_map_from(H(QQ))
            False
            sage: A(CC)._coerce_map_from_(H(QQ))
            True
            sage: H(CC)._coerce_map_from_(L(RR))
            True

        ::

            sage: A.<x,y,z> = AffineSpace(QQ, 3)
            sage: A2.<u,v> = AffineSpace(QQ, 2)
            sage: A(QQ).has_coerce_map_from(A2(QQ))
            False

        ::

            sage: A.<x,y> = AffineSpace(QQ, 2)
            sage: P.<u,v,w> = ProjectiveSpace(QQ, 2)
            sage: A(QQ).has_coerce_map_from(P(QQ))
            False

        ::

            sage: A = AffineSpace(QQ, 1)
            sage: A(QQ)._coerce_map_from_(ZZ)
            True

        ::

            sage: PS = ProjectiveSpace(ZZ, 1, 'x')
            sage: PS2 = ProjectiveSpace(Zp(7), 1, 'x')
            sage: PS(ZZ).has_coerce_map_from(PS2(Zp(7)))
            False
            sage: PS2(Zp(7)).has_coerce_map_from(PS(ZZ))
            True

        ::

            sage: PP1 = ProductProjectiveSpaces(ZZ, [2,1], 'x')
            sage: PP1(QQ)._coerce_map_from_(PP1(ZZ))
            True
            sage: PP2 = ProductProjectiveSpaces(QQ, [1,2], 'x')
            sage: PP2(QQ)._coerce_map_from_(PP1(ZZ))
            False
            sage: PP3 = ProductProjectiveSpaces(QQ, [2,1], 'y')
            sage: PP3(QQ)._coerce_map_from_(PP1(ZZ))
            False

        ::

            sage: K.<w> = QuadraticField(2)
            sage: A.<x,y,z> = AffineSpace(QQ, 3)
            sage: H = A.subscheme(z)
            sage: A(K).has_coerce_map_from(H(QQ))
            True

        TESTS::

            sage: P.<x,y> = ProjectiveSpace(QQ, 1)
            sage: X = P. subscheme ([x-y])
            sage: P(1,1) == X(1,1)
            True

        ::

            sage: A = AffineSpace(QQ, 1, 'x')
            sage: AC = AffineSpace(CC, 1, 'x')
            sage: A(3/2) == AC(3/2)
            True

        ::

            sage: A = AffineSpace(QQ, 1)
            sage: A(0) == 0
            True
        """
        target = self.codomain()
        #ring elements can be coerced to a space if we're affine dimension 1
        #and the base rings are coercible
        if isinstance(other, CommutativeRing):
            try:
                from sage.schemes.affine.affine_space import is_AffineSpace
                if is_AffineSpace(target.ambient_space())\
                  and target.ambient_space().dimension_relative() == 1:
                    return target.base_ring().has_coerce_map_from(other)
                else:
                    return False
            except AttributeError:  #no .ambient_space
                return False
        elif isinstance(other, SchemeHomset_points):
            #we are converting between scheme points
            from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme
            source = other.codomain()
            if isinstance(target, AlgebraicScheme_subscheme):
                #subscheme coerce when there is containment
                if not isinstance(source, AlgebraicScheme_subscheme):
                    return False
                if target.ambient_space() == source.ambient_space():
                    if all([
                            g in source.defining_ideal()
                            for g in target.defining_polynomials()
                    ]):
                        return self.domain().coordinate_ring(
                        ).has_coerce_map_from(other.domain().coordinate_ring())
            else:
                #if the target is an ambient space, we can coerce if the base rings coerce
                #and they are the same type: affine, projective, etc and have the same
                #variable names
                from sage.schemes.projective.projective_space import is_ProjectiveSpace
                from sage.schemes.affine.affine_space import is_AffineSpace
                from sage.schemes.product_projective.space import is_ProductProjectiveSpaces
                try:
                    ta = target.ambient_space()
                    sa = source.ambient_space()
                except AttributeError:  #no .ambient_space
                    return False
                #for projective and affine varieties, we check dimension
                #and matching variable names
                if (is_ProjectiveSpace(ta) and is_ProjectiveSpace(sa))\
                  or (is_AffineSpace(ta) and is_AffineSpace(sa)):
                    if (ta.variable_names() == sa.variable_names()):
                        return self.domain().coordinate_ring(
                        ).has_coerce_map_from(other.domain().coordinate_ring())
                    else:
                        return False
                #for products of projective spaces, we check dimension of
                #components and matching variable names
                elif (is_ProductProjectiveSpaces(ta)
                      and is_ProductProjectiveSpaces(sa)):
                    if (ta.dimension_relative_components() == sa.dimension_relative_components()) \
                      and (ta.variable_names() == sa.variable_names()):
                        return self.domain().coordinate_ring(
                        ).has_coerce_map_from(other.domain().coordinate_ring())
                    else:
                        return False
Beispiel #32
0
 def __init__(self, A, f):
     if not (is_ProjectiveSpace(A) and A.dimension != 2):
         raise TypeError("Argument A (= %s) must be a projective plane."%A)
     Curve_generic_projective.__init__(self, A, [f])
Beispiel #33
0
    def dynatomic_polynomial(self,period):
        r"""
        For a map `f:\mathbb{P}^1 \to \mathbb{P}^1` this function computes the dynatomic polynomial.
        The dynatomic polynomial is the analog of the cyclotomic polynomial and its roots are the points of formal period `n`.

        ALGORITHM:

        For a positive integer `n`, let `[F_n,G_n]` be the coordinates of the `nth` iterate of `f`.
        Then construct

        .. MATH::

            \Phi^{\ast}_n(f)(x,y) = \sum_{d \mid n} (yF_d(x,y) - xG_d(x,y))^{\mu(n/d)}

        where `\mu` is the Moebius function.

        For a pair `[m,n]`, let `f^m = [F_m,G_m]`. Compute

        .. MATH::

            \Phi^{\ast}_{m,n}(f)(x,y) = \Phi^{\ast}_n(f)(F_m,G_m)/\Phi^{\ast}_n(f)(F_{m-1},G_{m-1})

        REFERENCES:

        ..

        - B. Hutz. Efficient determination of rational preperiodic points for endomorphisms of projective space. arxiv:1210.6246, 2012.

        - P. Morton and P. Patel. The Galois theory of periodic points of polynomial maps. Proc. London Math. Soc., 68 (1994), 225-263.

        INPUT:

        - ``period`` -- a positive integer or a list/tuple `[m,n]` where `m` is the preperiod and `n` is the period

        OUTPUT:

        - If possible, a two variable polynomial in the coordinate ring of ``self``.
          Otherwise a fraction field element of the coordinate ring of ``self``

        .. TODO::

            Do the division when the base ring is p-adic or a function field so that the output is a polynomial.

        EXAMPLES::

            sage: P.<x,y>=ProjectiveSpace(QQ,1)
            sage: H=Hom(P,P)
            sage: f=H([x^2+y^2,y^2])
            sage: f.dynatomic_polynomial(2)
            x^2 + x*y + 2*y^2

        ::

            sage: P.<x,y>=ProjectiveSpace(ZZ,1)
            sage: H=Hom(P,P)
            sage: f=H([x^2+y^2,x*y])
            sage: f.dynatomic_polynomial(4)
            2*x^12 + 18*x^10*y^2 + 57*x^8*y^4 + 79*x^6*y^6 + 48*x^4*y^8 + 12*x^2*y^10 + y^12

        ::

            sage: P.<x,y>=ProjectiveSpace(CC,1)
            sage: H=Hom(P,P)
            sage: f=H([x^2+y^2,3*x*y])
            sage: f.dynatomic_polynomial(3)
            13.0000000000000*x^6 + 117.000000000000*x^4*y^2 +
            78.0000000000000*x^2*y^4 + y^6

        ::

            sage: P.<x,y>=ProjectiveSpace(QQ,1)
            sage: H=Hom(P,P)
            sage: f=H([x^2-10/9*y^2,y^2])
            sage: f.dynatomic_polynomial([2,1])
            x^4*y^2 - 11/9*x^2*y^4 - 80/81*y^6

        ::

            sage: P.<x,y>=ProjectiveSpace(QQ,1)
            sage: H=Hom(P,P)
            sage: f=H([x^2-29/16*y^2,y^2])
            sage: f.dynatomic_polynomial([2,3])
            x^12 - 95/8*x^10*y^2 + 13799/256*x^8*y^4 - 119953/1024*x^6*y^6 +
            8198847/65536*x^4*y^8 - 31492431/524288*x^2*y^10 +
            172692729/16777216*y^12

        ::

            sage: P.<x,y>=ProjectiveSpace(ZZ,1)
            sage: H=Hom(P,P)
            sage: f=H([x^2-y^2,y^2])
            sage: f.dynatomic_polynomial([1,2])
            x^2 - x*y

        ::

            sage: P.<x,y>=ProjectiveSpace(QQ,1)
            sage: H=Hom(P,P)
            sage: f=H([x^3-y^3,3*x*y^2])
            sage: f.dynatomic_polynomial([0,4])==f.dynatomic_polynomial(4)
            True

        ::

            sage: P.<x,y,z>=ProjectiveSpace(QQ,2)
            sage: H=Hom(P,P)
            sage: f=H([x^2+y^2,x*y,z^2])
            sage: f.dynatomic_polynomial(2)
            Traceback (most recent call last):
            ...
            TypeError: Does not make sense in dimension >1

        ::

            #TODO: it would be nice to get this to actually be a polynomial
            sage: P.<x,y>=ProjectiveSpace(Qp(5),1)
            sage: H=Hom(P,P)
            sage: f=H([x^2+y^2,y^2])
            sage: f.dynatomic_polynomial(2)
            (x^4*y + (2 + O(5^20))*x^2*y^3 - x*y^4 + (2 + O(5^20))*y^5)/(x^2*y -
            x*y^2 + y^3)

        ::

            sage: L.<t>=PolynomialRing(QQ)
            sage: P.<x,y>=ProjectiveSpace(L,1)
            sage: H=Hom(P,P)
            sage: f=H([x^2+t*y^2,y^2])
            sage: f.dynatomic_polynomial(2)
            x^2 + x*y + (t + 1)*y^2

        ::
            sage: K.<c>=PolynomialRing(ZZ)
            sage: P.<x,y>=ProjectiveSpace(K,1)
            sage: H=Hom(P,P)
            sage: f=H([x^2+ c*y^2,y^2])
            sage: f.dynatomic_polynomial([1,2])
            x^2 - x*y + (c + 1)*y^2
       """
        if self.domain() != self.codomain():
            raise TypeError("Must have same domain and codomain to iterate")
        from sage.schemes.projective.projective_space import is_ProjectiveSpace
        if is_ProjectiveSpace(self.domain())==False:
            raise NotImplementedError("Not implemented for subschemes")
        if self.domain().dimension_relative()>1:
            raise TypeError("Does not make sense in dimension >1")

        if (isinstance(period,(list,tuple))==False):
            period=[0,period]
        try:
            period[0]=ZZ(period[0])
            period[1]=ZZ(period[1])
        except TypeError:
            raise TypeError("Period and preperiod must be integers")
        if period[1]<=0:
                raise AttributeError("Period must be at least 1")

        if period[0]!=0:
            m=period[0]
            fm=self.nth_iterate_map(m)
            fm1=self.nth_iterate_map(m-1)
            n=period[1]
            PHI=1;
            x=self.domain().gen(0)
            y=self.domain().gen(1)
            F=self._polys
            f=F
            for d in range(1,n+1):
                if n%d ==0:
                    PHI=PHI*((y*F[0]-x*F[1])**moebius(n/d))
                if d !=n: #avoid extra iteration
                    F=[f[0](F[0],F[1]),f[1](F[0],F[1])]
            if m!=0:
                PHI=PHI(fm._polys)/PHI(fm1._polys)
        else:
            PHI=1;
            x=self.domain().gen(0)
            y=self.domain().gen(1)
            F=self._polys
            f=F
            for d in range(1,period[1]+1):
                if period[1]%d ==0:
                    PHI=PHI*((y*F[0]-x*F[1])**moebius(period[1]/d))
                if d !=period[1]: #avoid extra iteration
                    F=[f[0](F[0],F[1]),f[1](F[0],F[1])]
        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():
            PHI=PHI.numerator()._maxima_().divide(PHI.denominator())[0].sage()
        elif isinstance(self.domain().base_ring(),(PolynomialRing_general,MPolynomialRing_generic)):
            from sage.rings.padics.generic_nodes import is_pAdicField, is_pAdicRing
            from sage.rings.function_field.function_field import is_FunctionField
            BR=self.domain().base_ring().base_ring()
            if is_pAdicField(BR) or is_pAdicRing(BR) or is_FunctionField(BR):
                raise NotImplementedError("Not implemented")
            PHI=PHI.numerator()._maxima_().divide(PHI.denominator())[0].sage()
            #do it again to divide out by denominators of coefficients
            PHI=PHI.numerator()._maxima_().divide(PHI.denominator())[0].sage()
        if PHI.denominator()==1:
            PHI=self.coordinate_ring()(PHI)
        return(PHI)
Beispiel #34
0
    def points(self, B=0, prec=53):
        """
        Return some or all rational points of a projective scheme.

        INPUT:

        - ``B`` - integer (optional, default=0). The bound for the
          coordinates.

        - ``prec`` - he precision to use to compute the elements of bounded height for number fields.

        OUTPUT:

        A list of points. Over a finite field, all points are
        returned. Over an infinite field, all points satisfying the
        bound are returned.

        .. WARNING::

           In the current implementation, the output of the [Doyle-Krumm] algorithm
           cannot be guaranteed to be correct due to the necessity of floating point
           computations. In some cases, the default 53-bit precision is
           considerably lower than would be required for the algorithm to
           generate correct output.

        EXAMPLES::

            sage: P.<x,y> = ProjectiveSpace(QQ,1)
            sage: P(QQ).points(4)
            [(-4 : 1), (-3 : 1), (-2 : 1), (-3/2 : 1), (-4/3 : 1), (-1 : 1),
            (-3/4 : 1), (-2/3 : 1), (-1/2 : 1), (-1/3 : 1), (-1/4 : 1), (0 : 1),
            (1/4 : 1), (1/3 : 1), (1/2 : 1), (2/3 : 1), (3/4 : 1), (1 : 0), (1 : 1),
            (4/3 : 1), (3/2 : 1), (2 : 1), (3 : 1), (4 : 1)]

        ::

            sage: u = QQ['u'].0
            sage: K.<v> = NumberField(u^2 + 3)
            sage: P.<x,y,z> = ProjectiveSpace(K,2)
            sage: len(P(K).points(1.8))
            381

        ::

            sage: P1 = ProjectiveSpace(GF(2),1)
            sage: F.<a> = GF(4,'a')
            sage: P1(F).points()
            [(0 : 1), (1 : 0), (1 : 1), (a : 1), (a + 1 : 1)]

        ::

            sage: P.<x,y,z> = ProjectiveSpace(QQ,2)
            sage: E = P.subscheme([(y^3-y*z^2) - (x^3-x*z^2),(y^3-y*z^2) + (x^3-x*z^2)])
            sage: E(P.base_ring()).points()
            [(-1 : -1 : 1), (-1 : 0 : 1), (-1 : 1 : 1), (0 : -1 : 1), (0 : 0 : 1), (0 : 1 : 1),
            (1 : -1 : 1), (1 : 0 : 1), (1 : 1 : 1)]
        """
        X = self.codomain()
        from sage.schemes.projective.projective_space import is_ProjectiveSpace
        if not is_ProjectiveSpace(X) and X.base_ring() in Fields():
            #Then it must be a subscheme
            dim_ideal = X.defining_ideal().dimension()
            if dim_ideal < 1: # no points
                return []
            if dim_ideal == 1: # if X zero-dimensional
                rat_points = set()
                PS = X.ambient_space()
                N = PS.dimension_relative()
                BR = X.base_ring()
                #need a lexicographic ordering for elimination
                R = PolynomialRing(BR, N + 1, PS.gens(), order='lex')
                I = R.ideal(X.defining_polynomials())
                I0 = R.ideal(0)
                #Determine the points through elimination
                #This is much faster than using the I.variety() function on each affine chart.
                for k in range(N + 1):
                    #create the elimination ideal for the kth affine patch
                    G = I.substitute({R.gen(k):1}).groebner_basis()
                    if G != [1]:
                        P = {}
                        #keep track that we know the kth coordinate is 1
                        P.update({R.gen(k):1})
                        points = [P]
                        #work backwards from solving each equation for the possible
                        #values of the next coordinate
                        for i in range(len(G) - 1, -1, -1):
                            new_points = []
                            good = 0
                            for P in points:
                                #substitute in our dictionary entry that has the values
                                #of coordinates known so far. This results in a single
                                #variable polynomial (by elimination)
                                L = G[i].substitute(P)
                                if L != 0:
                                    L = L.factor()
                                    #the linear factors give the possible rational values of
                                    #this coordinate
                                    for pol, pow in L:
                                        if pol.degree() == 1 and len(pol.variables()) == 1:
                                            good = 1
                                            r = pol.variables()[0]
                                            varindex = R.gens().index(r)
                                            #add this coordinates information to
                                            #each dictionary entry
                                            P.update({R.gen(varindex):-pol.constant_coefficient() / pol.monomial_coefficient(r)})
                                            new_points.append(copy(P))
                                else:
                                    new_points.append(P)
                                    good = 1
                            if good:
                                points = new_points
                        #the dictionary entries now have values for all coordinates
                        #they are the rational solutions to the equations
                        #make them into projective points
                        for i in range(len(points)):
                            if len(points[i]) == N + 1 and I.subs(points[i]) == I0:
                                S = X([points[i][R.gen(j)] for j in range(N + 1)])
                                S.normalize_coordinates()
                                rat_points.add(S)
                rat_points = sorted(rat_points)
                return rat_points
        R = self.value_ring()
        if is_RationalField(R):
            if not B > 0:
                raise TypeError("a positive bound B (= %s) must be specified"%B)
            from sage.schemes.projective.projective_rational_point import enum_projective_rational_field
            return enum_projective_rational_field(self,B)
        elif R in NumberFields():
            if not B > 0:
                raise TypeError("a positive bound B (= %s) must be specified"%B)
            from sage.schemes.projective.projective_rational_point import enum_projective_number_field
            return enum_projective_number_field(self,B, prec=prec)
        elif is_FiniteField(R):
            from sage.schemes.projective.projective_rational_point import enum_projective_finite_field
            return enum_projective_finite_field(self.extended_codomain())
        else:
            raise TypeError("unable to enumerate points over %s"%R)
def enum_projective_rational_field(X,B):
    r"""
    Enumerates projective, rational points on scheme ``X`` of height up to
    bound ``B``.

    INPUT:

    - ``X`` -  a scheme or set of abstract rational points of a scheme;
    - ``B`` -  a positive integer bound.

    OUTPUT:

    - a list containing the projective points of ``X`` of height up to ``B``,
      sorted.

    EXAMPLES::

        sage: P.<X,Y,Z> = ProjectiveSpace(2,QQ)
        sage: C = P.subscheme([X+Y-Z])
        sage: from sage.schemes.projective.projective_rational_point import enum_projective_rational_field
        sage: enum_projective_rational_field(C(QQ),6)
        [(-5 : 6 : 1), (-4 : 5 : 1), (-3 : 4 : 1), (-2 : 3 : 1),
         (-3/2 : 5/2 : 1), (-1 : 1 : 0), (-1 : 2 : 1), (-2/3 : 5/3 : 1),
         (-1/2 : 3/2 : 1), (-1/3 : 4/3 : 1), (-1/4 : 5/4 : 1),
         (-1/5 : 6/5 : 1), (0 : 1 : 1), (1/6 : 5/6 : 1), (1/5 : 4/5 : 1),
         (1/4 : 3/4 : 1), (1/3 : 2/3 : 1), (2/5 : 3/5 : 1), (1/2 : 1/2 : 1),
         (3/5 : 2/5 : 1), (2/3 : 1/3 : 1), (3/4 : 1/4 : 1), (4/5 : 1/5 : 1),
         (5/6 : 1/6 : 1), (1 : 0 : 1), (6/5 : -1/5 : 1), (5/4 : -1/4 : 1),
         (4/3 : -1/3 : 1), (3/2 : -1/2 : 1), (5/3 : -2/3 : 1), (2 : -1 : 1),
         (5/2 : -3/2 : 1), (3 : -2 : 1), (4 : -3 : 1), (5 : -4 : 1),
         (6 : -5 : 1)]
        sage: enum_projective_rational_field(C,6) == enum_projective_rational_field(C(QQ),6)
        True

    ::

        sage: P3.<W,X,Y,Z> = ProjectiveSpace(3,QQ)
        sage: enum_projective_rational_field(P3,1)
        [(-1 : -1 : -1 : 1), (-1 : -1 : 0 : 1), (-1 : -1 : 1 : 0), (-1 : -1 : 1 : 1),
        (-1 : 0 : -1 : 1), (-1 : 0 : 0 : 1), (-1 : 0 : 1 : 0), (-1 : 0 : 1 : 1),
        (-1 : 1 : -1 : 1), (-1 : 1 : 0 : 0), (-1 : 1 : 0 : 1), (-1 : 1 : 1 : 0),
        (-1 : 1 : 1 : 1), (0 : -1 : -1 : 1), (0 : -1 : 0 : 1), (0 : -1 : 1 : 0),
        (0 : -1 : 1 : 1), (0 : 0 : -1 : 1), (0 : 0 : 0 : 1), (0 : 0 : 1 : 0),
        (0 : 0 : 1 : 1), (0 : 1 : -1 : 1), (0 : 1 : 0 : 0), (0 : 1 : 0 : 1),
        (0 : 1 : 1 : 0), (0 : 1 : 1 : 1), (1 : -1 : -1 : 1), (1 : -1 : 0 : 1),
        (1 : -1 : 1 : 0), (1 : -1 : 1 : 1), (1 : 0 : -1 : 1), (1 : 0 : 0 : 0),
        (1 : 0 : 0 : 1), (1 : 0 : 1 : 0), (1 : 0 : 1 : 1), (1 : 1 : -1 : 1),
        (1 : 1 : 0 : 0), (1 : 1 : 0 : 1), (1 : 1 : 1 : 0), (1 : 1 : 1 : 1)]

    ALGORITHM:

    We just check all possible projective points in correct dimension
    of projective space to see if they lie on ``X``.

    AUTHORS:

    - John Cremona and Charlie Turner (06-2010)
    """
    from sage.schemes.projective.projective_space import is_ProjectiveSpace
    if(is_Scheme(X)):
        if (not is_ProjectiveSpace(X.ambient_space())):
            raise TypeError("Ambient space must be projective space over the rational field")
        X = X(X.base_ring())
    else:
        if (not is_ProjectiveSpace(X.codomain().ambient_space())):
            raise TypeError("Codomain must be projective space over the rational field")

    n = X.codomain().ambient_space().ngens()
    zero = (0,) * n
    pts = []
    for c in cartesian_product_iterator([srange(-B,B+1) for _ in range(n)]):
        if gcd(c) == 1 and c > zero:
            try:
                pts.append(X(c))
            except TypeError:
                pass
    pts.sort()
    return pts
 def __init__(self, A, f):
     if not (is_ProjectiveSpace(A) and A.dimension != 2):
         raise TypeError("Argument A (= %s) must be a projective plane." %
                         A)
     Curve_generic_projective.__init__(self, A, [f])
def enum_projective_number_field(X, B, prec=53):
    """
    Enumerates projective points on scheme ``X`` defined over a number field.

    Simply checks all of the points of absolute height of at most ``B``
    and adds those that are on the scheme to the list.

    INPUT:

    - ``X`` - a scheme defined over a number field.

    - ``B`` - a real number.

    - ``prec`` - the precision to use for computing the elements of bounded height of number fields.

    OUTPUT:

     - a list containing the projective points of ``X`` of absolute height up to ``B``,
       sorted.

    .. WARNING::

       In the current implementation, the output of the [Doyle-Krumm] algorithm
       for elements of bounded height cannot be guaranteed to be correct due to
       the necessity of floating point computations. In some cases, the default
       53-bit precision is considerably lower than would be required for the
       algorithm to generate correct output.

    EXAMPLES::

        sage: from sage.schemes.projective.projective_rational_point import enum_projective_number_field
        sage: u = QQ['u'].0
        sage: K = NumberField(u^3 - 5,'v')
        sage: P.<x,y,z> = ProjectiveSpace(K, 2)
        sage: X = P.subscheme([x - y])
        sage: enum_projective_number_field(X(K), 5^(1/3), prec=2^10)
        [(0 : 0 : 1), (-1 : -1 : 1), (1 : 1 : 1), (-1/5*v^2 : -1/5*v^2 : 1), (-v : -v : 1),
        (1/5*v^2 : 1/5*v^2 : 1), (v : v : 1), (1 : 1 : 0)]

    ::

        sage: u = QQ['u'].0
        sage: K = NumberField(u^2 + 3, 'v')
        sage: A.<x,y> = ProjectiveSpace(K,1)
        sage: X = A.subscheme(x-y)
        sage: from sage.schemes.projective.projective_rational_point import enum_projective_number_field
        sage: enum_projective_number_field(X, 2)
        [(1 : 1)]
    """
    from sage.schemes.projective.projective_space import is_ProjectiveSpace
    if (is_Scheme(X)):
        if (not is_ProjectiveSpace(X.ambient_space())):
            raise TypeError(
                "ambient space must be projective space over a number field")
        X = X(X.base_ring())
    else:
        if (not is_ProjectiveSpace(X.codomain().ambient_space())):
            raise TypeError(
                "codomain must be projective space over a number field")

    R = X.codomain().ambient_space()

    pts = []

    for P in R.points_of_bounded_height(B, prec):
        try:
            pts.append(X(P))
        except TypeError:
            pass
    pts.sort()
    return pts
Beispiel #38
0
def Curve(F, A=None):
    """
    Return the plane or space curve defined by ``F``, where
    ``F`` can be either a multivariate polynomial, a list or
    tuple of polynomials, or an algebraic scheme.

    If no ambient space is passed in for ``A``, and if ``F`` is not
    an algebraic scheme, a new ambient space is constructed.

    Also not specifying an ambient space will cause the curve to be defined
    in either affine or projective space based on properties of ``F``. In
    particular, if ``F`` contains a nonhomogenous polynomial, the curve is
    affine, and if ``F`` consists of homogenous polynomials, then the curve
    is projective.

    INPUT:

    - ``F`` -- a multivariate polynomial, or a list or tuple of polynomials, or an algebraic scheme.

    - ``A`` -- (default: None) an ambient space in which to create the curve.

    EXAMPLES: A projective plane curve

    ::

        sage: x,y,z = QQ['x,y,z'].gens()
        sage: C = Curve(x^3 + y^3 + z^3); C
        Projective Plane Curve over Rational Field defined by x^3 + y^3 + z^3
        sage: C.genus()
        1

    EXAMPLES: Affine plane curves

    ::

        sage: x,y = GF(7)['x,y'].gens()
        sage: C = Curve(y^2 + x^3 + x^10); C
        Affine Plane Curve over Finite Field of size 7 defined by x^10 + x^3 + y^2
        sage: C.genus()
        0
        sage: x, y = QQ['x,y'].gens()
        sage: Curve(x^3 + y^3 + 1)
        Affine Plane Curve over Rational Field defined by x^3 + y^3 + 1

    EXAMPLES: A projective space curve

    ::

        sage: x,y,z,w = QQ['x,y,z,w'].gens()
        sage: C = Curve([x^3 + y^3 - z^3 - w^3, x^5 - y*z^4]); C
        Projective Curve over Rational Field defined by x^3 + y^3 - z^3 - w^3, x^5 - y*z^4
        sage: C.genus()
        13

    EXAMPLES: An affine space curve

    ::

        sage: x,y,z = QQ['x,y,z'].gens()
        sage: C = Curve([y^2 + x^3 + x^10 + z^7,  x^2 + y^2]); C
        Affine Curve over Rational Field defined by x^10 + z^7 + x^3 + y^2, x^2 + y^2
        sage: C.genus()
        47

    EXAMPLES: We can also make non-reduced non-irreducible curves.

    ::

        sage: x,y,z = QQ['x,y,z'].gens()
        sage: Curve((x-y)*(x+y))
        Projective Conic Curve over Rational Field defined by x^2 - y^2
        sage: Curve((x-y)^2*(x+y)^2)
        Projective Plane Curve over Rational Field defined by x^4 - 2*x^2*y^2 + y^4

    EXAMPLES: A union of curves is a curve.

    ::

        sage: x,y,z = QQ['x,y,z'].gens()
        sage: C = Curve(x^3 + y^3 + z^3)
        sage: D = Curve(x^4 + y^4 + z^4)
        sage: C.union(D)
        Projective Plane Curve over Rational Field defined by
        x^7 + x^4*y^3 + x^3*y^4 + y^7 + x^4*z^3 + y^4*z^3 + x^3*z^4 + y^3*z^4 + z^7

    The intersection is not a curve, though it is a scheme.

    ::

        sage: X = C.intersection(D); X
        Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:
         x^3 + y^3 + z^3,
         x^4 + y^4 + z^4

    Note that the intersection has dimension `0`.

    ::

        sage: X.dimension()
        0
        sage: I = X.defining_ideal(); I
        Ideal (x^3 + y^3 + z^3, x^4 + y^4 + z^4) of Multivariate Polynomial Ring in x, y, z over Rational Field

    EXAMPLES: In three variables, the defining equation must be
    homogeneous.

    If the parent polynomial ring is in three variables, then the
    defining ideal must be homogeneous.

    ::

        sage: x,y,z = QQ['x,y,z'].gens()
        sage: Curve(x^2+y^2)
        Projective Conic Curve over Rational Field defined by x^2 + y^2
        sage: Curve(x^2+y^2+z)
        Traceback (most recent call last):
        ...
        TypeError: x^2 + y^2 + z is not a homogeneous polynomial

    The defining polynomial must always be nonzero::

        sage: P1.<x,y> = ProjectiveSpace(1,GF(5))
        sage: Curve(0*x)
        Traceback (most recent call last):
        ...
        ValueError: defining polynomial of curve must be nonzero

    ::

        sage: A.<x,y,z> = AffineSpace(QQ, 3)
        sage: C = Curve([y - x^2, z - x^3], A)
        sage: A == C.ambient_space()
        True
    """
    if not A is None:
        if not isinstance(F, (list, tuple)):
            return Curve([F], A)
        if not is_AmbientSpace(A):
            raise TypeError("A (=%s) must be either an affine or projective space"%A)
        if not all([f.parent() == A.coordinate_ring() for f in F]):
            raise TypeError("F (=%s) must be a list or tuple of polynomials of the coordinate ring of " \
            "A (=%s)"%(F, A))
        n = A.dimension_relative()
        if n < 2:
            raise TypeError("A (=%s) must be either an affine or projective space of dimension > 1"%A)
        # there is no dimension check when initializing a plane curve, so check here that F consists
        # of a single nonconstant polynomial
        if n == 2:
            if len(F) != 1 or F[0] == 0 or not is_MPolynomial(F[0]):
                raise TypeError("F (=%s) must consist of a single nonconstant polynomial to define a plane curve"%(F,))
        if is_AffineSpace(A):
            if n > 2:
                return AffineCurve(A, F)
            k = A.base_ring()
            if is_FiniteField(k):
                if k.is_prime_field():
                    return AffinePlaneCurve_prime_finite_field(A, F[0])
                return AffinePlaneCurve_finite_field(A, F[0])
            return AffinePlaneCurve(A, F[0])
        elif is_ProjectiveSpace(A):
            if not all([f.is_homogeneous() for f in F]):
                raise TypeError("polynomials defining a curve in a projective space must be homogeneous")
            if n > 2:
                return ProjectiveCurve(A, F)
            k = A.base_ring()
            if is_FiniteField(k):
                if k.is_prime_field():
                    return ProjectivePlaneCurve_prime_finite_field(A, F[0])
                return ProjectivePlaneCurve_finite_field(A, F[0])
            return ProjectivePlaneCurve(A, F[0])

    if is_AlgebraicScheme(F):
        return Curve(F.defining_polynomials(), F.ambient_space())

    if isinstance(F, (list, tuple)):
        if len(F) == 1:
            return Curve(F[0])
        F = Sequence(F)
        P = F.universe()
        if not is_MPolynomialRing(P):
            raise TypeError("universe of F must be a multivariate polynomial ring")

        for f in F:
            if not f.is_homogeneous():
                A = AffineSpace(P.ngens(), P.base_ring())
                A._coordinate_ring = P
                return AffineCurve(A, F)

        A = ProjectiveSpace(P.ngens()-1, P.base_ring())
        A._coordinate_ring = P
        return ProjectiveCurve(A, F)

    if not is_MPolynomial(F):
        raise TypeError("F (=%s) must be a multivariate polynomial"%F)

    P = F.parent()
    k = F.base_ring()
    if F.parent().ngens() == 2:
        if F == 0:
            raise ValueError("defining polynomial of curve must be nonzero")
        A2 = AffineSpace(2, P.base_ring())
        A2._coordinate_ring = P

        if is_FiniteField(k):
            if k.is_prime_field():
                return AffinePlaneCurve_prime_finite_field(A2, F)
            else:
                return AffinePlaneCurve_finite_field(A2, F)
        else:
            return AffinePlaneCurve(A2, F)

    elif F.parent().ngens() == 3:
        if F == 0:
            raise ValueError("defining polynomial of curve must be nonzero")
        P2 = ProjectiveSpace(2, P.base_ring())
        P2._coordinate_ring = P

        if F.total_degree() == 2 and k.is_field():
            return Conic(F)

        if is_FiniteField(k):
            if k.is_prime_field():
                return ProjectivePlaneCurve_prime_finite_field(P2, F)
            else:
                return ProjectivePlaneCurve_finite_field(P2, F)
        else:
            return ProjectivePlaneCurve(P2, F)


    else:

        raise TypeError("Number of variables of F (=%s) must be 2 or 3"%F)
def enum_projective_rational_field(X, B):
    r"""
    Enumerates projective, rational points on scheme ``X`` of height up to
    bound ``B``.

    INPUT:

    - ``X`` -  a scheme or set of abstract rational points of a scheme.

    - ``B`` -  a positive integer bound.

    OUTPUT:

    - a list containing the projective points of ``X`` of height up to ``B``,
      sorted.

    EXAMPLES::

        sage: P.<X,Y,Z> = ProjectiveSpace(2, QQ)
        sage: C = P.subscheme([X+Y-Z])
        sage: from sage.schemes.projective.projective_rational_point import enum_projective_rational_field
        sage: enum_projective_rational_field(C(QQ), 6)
        [(-5 : 6 : 1), (-4 : 5 : 1), (-3 : 4 : 1), (-2 : 3 : 1),
         (-3/2 : 5/2 : 1), (-1 : 1 : 0), (-1 : 2 : 1), (-2/3 : 5/3 : 1),
         (-1/2 : 3/2 : 1), (-1/3 : 4/3 : 1), (-1/4 : 5/4 : 1),
         (-1/5 : 6/5 : 1), (0 : 1 : 1), (1/6 : 5/6 : 1), (1/5 : 4/5 : 1),
         (1/4 : 3/4 : 1), (1/3 : 2/3 : 1), (2/5 : 3/5 : 1), (1/2 : 1/2 : 1),
         (3/5 : 2/5 : 1), (2/3 : 1/3 : 1), (3/4 : 1/4 : 1), (4/5 : 1/5 : 1),
         (5/6 : 1/6 : 1), (1 : 0 : 1), (6/5 : -1/5 : 1), (5/4 : -1/4 : 1),
         (4/3 : -1/3 : 1), (3/2 : -1/2 : 1), (5/3 : -2/3 : 1), (2 : -1 : 1),
         (5/2 : -3/2 : 1), (3 : -2 : 1), (4 : -3 : 1), (5 : -4 : 1),
         (6 : -5 : 1)]
        sage: enum_projective_rational_field(C,6) == enum_projective_rational_field(C(QQ),6)
        True

    ::

        sage: P3.<W,X,Y,Z> = ProjectiveSpace(3, QQ)
        sage: enum_projective_rational_field(P3, 1)
        [(-1 : -1 : -1 : 1), (-1 : -1 : 0 : 1), (-1 : -1 : 1 : 0), (-1 : -1 : 1 : 1),
        (-1 : 0 : -1 : 1), (-1 : 0 : 0 : 1), (-1 : 0 : 1 : 0), (-1 : 0 : 1 : 1),
        (-1 : 1 : -1 : 1), (-1 : 1 : 0 : 0), (-1 : 1 : 0 : 1), (-1 : 1 : 1 : 0),
        (-1 : 1 : 1 : 1), (0 : -1 : -1 : 1), (0 : -1 : 0 : 1), (0 : -1 : 1 : 0),
        (0 : -1 : 1 : 1), (0 : 0 : -1 : 1), (0 : 0 : 0 : 1), (0 : 0 : 1 : 0),
        (0 : 0 : 1 : 1), (0 : 1 : -1 : 1), (0 : 1 : 0 : 0), (0 : 1 : 0 : 1),
        (0 : 1 : 1 : 0), (0 : 1 : 1 : 1), (1 : -1 : -1 : 1), (1 : -1 : 0 : 1),
        (1 : -1 : 1 : 0), (1 : -1 : 1 : 1), (1 : 0 : -1 : 1), (1 : 0 : 0 : 0),
        (1 : 0 : 0 : 1), (1 : 0 : 1 : 0), (1 : 0 : 1 : 1), (1 : 1 : -1 : 1),
        (1 : 1 : 0 : 0), (1 : 1 : 0 : 1), (1 : 1 : 1 : 0), (1 : 1 : 1 : 1)]

    ALGORITHM:

    We just check all possible projective points in correct dimension
    of projective space to see if they lie on ``X``.

    AUTHORS:

    - John Cremona and Charlie Turner (06-2010)
    """
    from sage.schemes.projective.projective_space import is_ProjectiveSpace
    if (is_Scheme(X)):
        if (not is_ProjectiveSpace(X.ambient_space())):
            raise TypeError(
                "ambient space must be projective space over the rational field"
            )
        X = X(X.base_ring())
    else:
        if (not is_ProjectiveSpace(X.codomain().ambient_space())):
            raise TypeError(
                "codomain must be projective space over the rational field")

    n = X.codomain().ambient_space().ngens()
    zero = (0, ) * n
    pts = []
    for c in cartesian_product_iterator([srange(-B, B + 1) for _ in range(n)]):
        if gcd(c) == 1 and c > zero:
            try:
                pts.append(X(c))
            except TypeError:
                pass
    pts.sort()
    return pts
Beispiel #40
0
    def points(self, B=0, prec=53):
        """
        Return some or all rational points of a projective scheme.

        INPUT:

        - ``B`` - integer (optional, default=0). The bound for the
          coordinates.

        - ``prec`` - he precision to use to compute the elements of bounded height for number fields.

        OUTPUT:

        A list of points. Over a finite field, all points are
        returned. Over an infinite field, all points satisfying the
        bound are returned.

        .. WARNING::

           In the current implementation, the output of the [Doyle-Krumm] algorithm
           cannot be guaranteed to be correct due to the necessity of floating point
           computations. In some cases, the default 53-bit precision is
           considerably lower than would be required for the algorithm to
           generate correct output.

        EXAMPLES::

            sage: P.<x,y> = ProjectiveSpace(QQ,1)
            sage: P(QQ).points(4)
            [(-4 : 1), (-3 : 1), (-2 : 1), (-3/2 : 1), (-4/3 : 1), (-1 : 1),
            (-3/4 : 1), (-2/3 : 1), (-1/2 : 1), (-1/3 : 1), (-1/4 : 1), (0 : 1),
            (1/4 : 1), (1/3 : 1), (1/2 : 1), (2/3 : 1), (3/4 : 1), (1 : 0), (1 : 1),
            (4/3 : 1), (3/2 : 1), (2 : 1), (3 : 1), (4 : 1)]

        ::

            sage: u = QQ['u'].0
            sage: K.<v> = NumberField(u^2 + 3)
            sage: P.<x,y,z> = ProjectiveSpace(K,2)
            sage: len(P(K).points(1.8))
            381

        ::

            sage: P1 = ProjectiveSpace(GF(2),1)
            sage: F.<a> = GF(4,'a')
            sage: P1(F).points()
            [(0 : 1), (1 : 0), (1 : 1), (a : 1), (a + 1 : 1)]

        ::

            sage: P.<x,y,z> = ProjectiveSpace(QQ,2)
            sage: E = P.subscheme([(y^3-y*z^2) - (x^3-x*z^2),(y^3-y*z^2) + (x^3-x*z^2)])
            sage: E(P.base_ring()).points()
            [(-1 : -1 : 1), (-1 : 0 : 1), (-1 : 1 : 1), (0 : -1 : 1), (0 : 0 : 1), (0 : 1 : 1),
            (1 : -1 : 1), (1 : 0 : 1), (1 : 1 : 1)]
        """
        X = self.codomain()
        from sage.schemes.projective.projective_space import is_ProjectiveSpace
        if not is_ProjectiveSpace(X) and X.base_ring() in Fields():
            #Then it must be a subscheme
            dim_ideal = X.defining_ideal().dimension()
            if dim_ideal < 1:  # no points
                return []
            if dim_ideal == 1:  # if X zero-dimensional
                rat_points = set()
                PS = X.ambient_space()
                N = PS.dimension_relative()
                BR = X.base_ring()
                #need a lexicographic ordering for elimination
                R = PolynomialRing(BR, N + 1, PS.variable_names(), order='lex')
                I = R.ideal(X.defining_polynomials())
                I0 = R.ideal(0)
                #Determine the points through elimination
                #This is much faster than using the I.variety() function on each affine chart.
                for k in range(N + 1):
                    #create the elimination ideal for the kth affine patch
                    G = I.substitute({R.gen(k): 1}).groebner_basis()
                    if G != [1]:
                        P = {}
                        #keep track that we know the kth coordinate is 1
                        P.update({R.gen(k): 1})
                        points = [P]
                        #work backwards from solving each equation for the possible
                        #values of the next coordinate
                        for i in range(len(G) - 1, -1, -1):
                            new_points = []
                            good = 0
                            for P in points:
                                #substitute in our dictionary entry that has the values
                                #of coordinates known so far. This results in a single
                                #variable polynomial (by elimination)
                                L = G[i].substitute(P)
                                if L != 0:
                                    L = L.factor()
                                    #the linear factors give the possible rational values of
                                    #this coordinate
                                    for pol, pow in L:
                                        if pol.degree() == 1 and len(
                                                pol.variables()) == 1:
                                            good = 1
                                            r = pol.variables()[0]
                                            varindex = R.gens().index(r)
                                            #add this coordinates information to
                                            #each dictionary entry
                                            P.update({
                                                R.gen(varindex):
                                                -pol.constant_coefficient() /
                                                pol.monomial_coefficient(r)
                                            })
                                            new_points.append(copy(P))
                                else:
                                    new_points.append(P)
                                    good = 1
                            if good:
                                points = new_points
                        #the dictionary entries now have values for all coordinates
                        #they are the rational solutions to the equations
                        #make them into projective points
                        for i in range(len(points)):
                            if len(points[i]) == N + 1 and I.subs(
                                    points[i]) == I0:
                                S = X([
                                    points[i][R.gen(j)] for j in range(N + 1)
                                ])
                                S.normalize_coordinates()
                                rat_points.add(S)
                rat_points = sorted(rat_points)
                return rat_points
        R = self.value_ring()
        if is_RationalField(R):
            if not B > 0:
                raise TypeError("a positive bound B (= %s) must be specified" %
                                B)
            from sage.schemes.projective.projective_rational_point import enum_projective_rational_field
            return enum_projective_rational_field(self, B)
        elif R in NumberFields():
            if not B > 0:
                raise TypeError("a positive bound B (= %s) must be specified" %
                                B)
            from sage.schemes.projective.projective_rational_point import enum_projective_number_field
            return enum_projective_number_field(self, B, prec=prec)
        elif is_FiniteField(R):
            from sage.schemes.projective.projective_rational_point import enum_projective_finite_field
            return enum_projective_finite_field(self.extended_codomain())
        else:
            raise TypeError("unable to enumerate points over %s" % R)