Ejemplo n.º 1
0
    def base_extend(self, S):
        r"""
        Returns the conic over ``S`` given by the same equation as ``self``.

        EXAMPLES::

            sage: c = Conic([1, 1, 1]); c
            Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^2
            sage: c.has_rational_point()
            False
            sage: d = c.base_extend(QuadraticField(-1, 'i')); d
            Projective Conic Curve over Number Field in i with defining polynomial x^2 + 1 defined by x^2 + y^2 + z^2
            sage: d.rational_point(algorithm = 'rnfisnorm')
            (i : 1 : 0)
        """
        if S in _Fields:
            B = self.base_ring()
            if B == S:
                return self
            if not S.has_coerce_map_from(B):
                raise ValueError, "No natural map from the base ring of self " \
                                  "(= %s) to S (= %s)" % (self, S)
            from constructor import Conic
            con = Conic([S(c) for c in self.coefficients()], \
                        self.variable_names())
            if self._rational_point != None:
                pt = [S(c) for c in Sequence(self._rational_point)]
                if not pt == [0,0,0]:
                    # The following line stores the point in the cache
                    # if (and only if) there is no point in the cache.
                    pt = con.point(pt)
            return con
        return ProjectiveCurve_generic.base_extend(self, S)
Ejemplo n.º 2
0
    def base_extend(self, S):
        r"""
        Returns the conic over ``S`` given by the same equation as ``self``.

        EXAMPLES::

            sage: c = Conic([1, 1, 1]); c
            Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^2
            sage: c.has_rational_point()
            False
            sage: d = c.base_extend(QuadraticField(-1, 'i')); d
            Projective Conic Curve over Number Field in i with defining polynomial x^2 + 1 defined by x^2 + y^2 + z^2
            sage: d.rational_point(algorithm = 'rnfisnorm')
            (i : 1 : 0)
        """
        if S in _Fields:
            B = self.base_ring()
            if B == S:
                return self
            if not S.has_coerce_map_from(B):
                raise ValueError("No natural map from the base ring of self " \
                                  "(= %s) to S (= %s)" % (self, S))
            from constructor import Conic
            con = Conic([S(c) for c in self.coefficients()], \
                        self.variable_names())
            if self._rational_point is not None:
                pt = [S(c) for c in Sequence(self._rational_point)]
                if not pt == [0,0,0]:
                    # The following line stores the point in the cache
                    # if (and only if) there is no point in the cache.
                    pt = con.point(pt)
            return con
        return ProjectiveCurve_generic.base_extend(self, S)
Ejemplo n.º 3
0
    def diagonalization(self, names=None):
        r"""
        Returns a diagonal conic `C`, an isomorphism of schemes `M: C` -> ``self``
        and the inverse `N` of `M`.

        EXAMPLES::

            sage: Conic(GF(5), [1,0,1,1,0,1]).diagonalization()
            (Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2,
             Scheme morphism:
              From: Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2
              To:   Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + x*z + z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x + 2*z : y : z),
             Scheme morphism:
              From: Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + x*z + z^2
              To:   Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x - 2*z : y : z))

        The diagonalization is only defined in characteristic different
        from 2:

        ::

            sage: Conic(GF(2), [1,1,1,1,1,0]).diagonalization()
            Traceback (most recent call last):
            ...
            ValueError: The conic self (= Projective Conic Curve over Finite Field of size 2 defined by x^2 + x*y + y^2 + x*z + y*z) has no symmetric matrix because the base field has characteristic 2
        
        An example over a global function field:
        
        ::
        
            sage: K = FractionField(PolynomialRing(GF(7), 't'))
            sage: (t,) = K.gens()
            sage: C = Conic(K, [t/2,0, 1, 2, 0, 3])
            sage: C.diagonalization()
            (Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + ((3*t + 3)/t)*z^2,
             Scheme morphism:
               From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + ((3*t + 3)/t)*z^2
               To:   Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + x*z + 3*z^2
               Defn: Defined on coordinates by sending (x : y : z) to
                     (x + 6/t*z : y : z),
             Scheme morphism:
               From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + x*z + 3*z^2
               To:   Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + ((3*t + 3)/t)*z^2
               Defn: Defined on coordinates by sending (x : y : z) to
                     (x + 1/t*z : y : z))

        """
        if names is None:
            names = self.defining_polynomial().parent().variable_names()
        from constructor import Conic

        D, T = self.diagonal_matrix()
        con = Conic(D, names=names)
        return con, con.hom(T, self), self.hom(T.inverse(), con)
Ejemplo n.º 4
0
    def diagonalization(self, names=None):
        r"""
        Returns a diagonal conic `C`, an isomorphism of schemes `M: C` -> ``self``
        and the inverse `N` of `M`.

        EXAMPLES::

            sage: Conic(GF(5), [1,0,1,1,0,1]).diagonalization()
            (Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2,
             Scheme morphism:
              From: Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2
              To:   Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + x*z + z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x + 2*z : y : z),
             Scheme morphism:
              From: Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + x*z + z^2
              To:   Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x - 2*z : y : z))

        The diagonalization is only defined in characteristic different
        from 2:

        ::

            sage: Conic(GF(2), [1,1,1,1,1,0]).diagonalization()
            Traceback (most recent call last):
            ...
            ValueError: The conic self (= Projective Conic Curve over Finite Field of size 2 defined by x^2 + x*y + y^2 + x*z + y*z) has no symmetric matrix because the base field has characteristic 2
        
        An example over a global function field:
        
        ::
        
            sage: K = FractionField(PolynomialRing(GF(7), 't'))
            sage: (t,) = K.gens()
            sage: C = Conic(K, [t/2,0, 1, 2, 0, 3])
            sage: C.diagonalization()
            (Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + ((3*t + 3)/t)*z^2,
             Scheme morphism:
               From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + ((3*t + 3)/t)*z^2
               To:   Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + x*z + 3*z^2
               Defn: Defined on coordinates by sending (x : y : z) to
                     (x + 6/t*z : y : z),
             Scheme morphism:
               From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + x*z + 3*z^2
               To:   Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + ((3*t + 3)/t)*z^2
               Defn: Defined on coordinates by sending (x : y : z) to
                     (x + 1/t*z : y : z))

        """
        if names is None:
            names = self.defining_polynomial().parent().variable_names()
        from constructor import Conic
        D, T = self.diagonal_matrix()
        con = Conic(D, names=names)
        return con, con.hom(T, self), self.hom(T.inverse(), con)
Ejemplo n.º 5
0
    def diagonalization(self,names = None):
        r"""
        Returns a diagonal conic `C`, an isomorphism of schemes `M: C` -> ``self``
        and the inverse `N` of `M`.

        EXAMPLES::

            sage: Conic(GF(5), [1,0,1,1,0,1]).diagonalization()
            (Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2,
             Scheme morphism:
              From: Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2
              To:   Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + x*z + z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x + 2*z : y : z),
             Scheme morphism:
              From: Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + x*z + z^2
              To:   Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x - 2*z : y : z))

        The diagonalization is only defined in characteristic different
        from 2:

        ::

            sage: Conic(GF(2), [1,1,1,1,1,0]).diagonalization()
            Traceback (most recent call last):
            ...
            ValueError: The conic self (= Projective Conic Curve over Finite Field of size 2 defined by x^2 + x*y + y^2 + x*z + y*z) has no symmetric matrix because the base field has characteristic 2
        """
        if names == None:
            names = self.defining_polynomial().parent().variable_names()
        from constructor import Conic
        D, T = self.diagonal_matrix()
        con = Conic(D, names = names)
        return con, con.hom(T, self), self.hom(T.inverse(), con)
Ejemplo n.º 6
0
    def diagonalization(self, names=None):
        r"""
        Returns a diagonal conic `C`, an isomorphism of schemes `M: C` -> ``self``
        and the inverse `N` of `M`.

        EXAMPLES::

            sage: Conic(GF(5), [1,0,1,1,0,1]).diagonalization()
            (Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2,
             Scheme morphism:
              From: Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2
              To:   Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + x*z + z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x + 2*z : y : z),
             Scheme morphism:
              From: Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + x*z + z^2
              To:   Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x - 2*z : y : z))

        The diagonalization is only defined in characteristic different
        from 2:

        ::

            sage: Conic(GF(2), [1,1,1,1,1,0]).diagonalization()
            Traceback (most recent call last):
            ...
            ValueError: The conic self (= Projective Conic Curve over Finite Field of size 2 defined by x^2 + x*y + y^2 + x*z + y*z) has no symmetric matrix because the base field has characteristic 2
        """
        if names == None:
            names = self.defining_polynomial().parent().variable_names()
        from constructor import Conic
        D, T = self.diagonal_matrix()
        con = Conic(D, names=names)
        return con, con.hom(T, self), self.hom(T.inverse(), con)
Ejemplo n.º 7
0
    def hom(self, x, Y=None):
        r"""
        Return the scheme morphism from ``self`` to ``Y`` defined by ``x``.
        Here ``x`` can be a matrix or a sequence of polynomials.
        If ``Y`` is omitted, then a natural image is found if possible.

        EXAMPLES:

        Here are a few Morphisms given by matrices. In the first
        example, ``Y`` is omitted, in the second example, ``Y`` is specified.

        ::

            sage: c = Conic([-1, 1, 1])
            sage: h = c.hom(Matrix([[1,1,0],[0,1,0],[0,0,1]])); h
            Scheme morphism:
              From: Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2
              To:   Projective Conic Curve over Rational Field defined by -x^2 + 2*x*y + z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x + y : y : z)
            sage: h([-1, 1, 0])
            (0 : 1 : 0)

            sage: c = Conic([-1, 1, 1])
            sage: d = Conic([4, 1, -1])
            sage: c.hom(Matrix([[0, 0, 1/2], [0, 1, 0], [1, 0, 0]]), d)
            Scheme morphism:
              From: Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2
              To:   Projective Conic Curve over Rational Field defined by 4*x^2 + y^2 - z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (1/2*z : y : x)

        ``ValueError`` is raised if the wrong codomain ``Y`` is specified:

        ::

            sage: c = Conic([-1, 1, 1])
            sage: c.hom(Matrix([[0, 0, 1/2], [0, 1, 0], [1, 0, 0]]), c)
            Traceback (most recent call last):
            ...
            ValueError: The matrix x (= [  0   0 1/2]
            [  0   1   0]
            [  1   0   0]) does not define a map from self (= Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2) to Y (= Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2)
        """
        if is_Matrix(x):
            from constructor import Conic
            y = x.inverse()
            A = y.transpose()*self.matrix()*y
            im = Conic(A)
            if Y == None:
                Y = im
            else:
                q = Y.defining_polynomial()/im.defining_polynomial()
                if not (q.numerator().is_constant()
                        and q.denominator().is_constant()):
                    raise ValueError, "The matrix x (= %s) does not define a " \
                                      "map from self (= %s) to Y (= %s)" % \
                                      (x, self, Y)
            x = Sequence(x*vector(self.ambient_space().gens()))
            return self.Hom(Y)(x, check = False)
        return ProjectiveCurve_generic.hom(self, x, Y)
Ejemplo n.º 8
0
    def hom(self, x, Y=None):
        r"""
        Return the scheme morphism from ``self`` to ``Y`` defined by ``x``.
        Here ``x`` can be a matrix or a sequence of polynomials.
        If ``Y`` is omitted, then a natural image is found if possible.

        EXAMPLES:

        Here are a few Morphisms given by matrices. In the first
        example, ``Y`` is omitted, in the second example, ``Y`` is specified.

        ::

            sage: c = Conic([-1, 1, 1])
            sage: h = c.hom(Matrix([[1,1,0],[0,1,0],[0,0,1]])); h
            Scheme morphism:
              From: Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2
              To:   Projective Conic Curve over Rational Field defined by -x^2 + 2*x*y + z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x + y : y : z)
            sage: h([-1, 1, 0])
            (0 : 1 : 0)

            sage: c = Conic([-1, 1, 1])
            sage: d = Conic([4, 1, -1])
            sage: c.hom(Matrix([[0, 0, 1/2], [0, 1, 0], [1, 0, 0]]), d)
            Scheme morphism:
              From: Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2
              To:   Projective Conic Curve over Rational Field defined by 4*x^2 + y^2 - z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (1/2*z : y : x)

        ``ValueError`` is raised if the wrong codomain ``Y`` is specified:

        ::

            sage: c = Conic([-1, 1, 1])
            sage: c.hom(Matrix([[0, 0, 1/2], [0, 1, 0], [1, 0, 0]]), c)
            Traceback (most recent call last):
            ...
            ValueError: The matrix x (= [  0   0 1/2]
            [  0   1   0]
            [  1   0   0]) does not define a map from self (= Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2) to Y (= Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2)
        """
        if is_Matrix(x):
            from constructor import Conic
            y = x.inverse()
            A = y.transpose()*self.matrix()*y
            im = Conic(A)
            if Y is None:
                Y = im
            else:
                q = Y.defining_polynomial()/im.defining_polynomial()
                if not (q.numerator().is_constant()
                        and q.denominator().is_constant()):
                    raise ValueError("The matrix x (= %s) does not define a " \
                                      "map from self (= %s) to Y (= %s)" % \
                                      (x, self, Y))
            x = Sequence(x*vector(self.ambient_space().gens()))
            return self.Hom(Y)(x, check = False)
        return ProjectiveCurve_generic.hom(self, x, Y)
Ejemplo n.º 9
0
    def hom(self, x, Y=None):
        r"""
        Return the scheme morphism from ``self`` to ``Y`` defined by ``x``.
        Here ``x`` can be a matrix or a sequence of polynomials.
        If ``Y`` is omitted, then a natural image is found if possible.

        EXAMPLES:

        Here are a few Morphisms given by matrices. In the first
        example, ``Y`` is omitted, in the second example, ``Y`` is specified.

        ::

            sage: c = Conic([-1, 1, 1])
            sage: h = c.hom(Matrix([[1,1,0],[0,1,0],[0,0,1]])); h
            Scheme morphism:
              From: Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2
              To:   Projective Conic Curve over Rational Field defined by -x^2 + 2*x*y + z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x + y : y : z)
            sage: h([-1, 1, 0])
            (0 : 1 : 0)

            sage: c = Conic([-1, 1, 1])
            sage: d = Conic([4, 1, -1])
            sage: c.hom(Matrix([[0, 0, 1/2], [0, 1, 0], [1, 0, 0]]), d)
            Scheme morphism:
              From: Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2
              To:   Projective Conic Curve over Rational Field defined by 4*x^2 + y^2 - z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (1/2*z : y : x)

        ``ValueError`` is raised if the wrong codomain ``Y`` is specified:

        ::

            sage: c = Conic([-1, 1, 1])
            sage: c.hom(Matrix([[0, 0, 1/2], [0, 1, 0], [1, 0, 0]]), c)
            Traceback (most recent call last):
            ...
            ValueError: The matrix x (= [  0   0 1/2]
            [  0   1   0]
            [  1   0   0]) does not define a map from self (= Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2) to Y (= Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2)
        
        The identity map between two representations of the same conic:
        
        ::
        
            sage: C = Conic([1,2,3,4,5,6])
            sage: D = Conic([2,4,6,8,10,12])
            sage: C.hom(identity_matrix(3), D)
            Scheme morphism:
              From: Projective Conic Curve over Rational Field defined by x^2 + 2*x*y + 4*y^2 + 3*x*z + 5*y*z + 6*z^2
              To:   Projective Conic Curve over Rational Field defined by 2*x^2 + 4*x*y + 8*y^2 + 6*x*z + 10*y*z + 12*z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x : y : z)

        An example not over the rational numbers:
        
        ::
        
            sage: P.<t> = QQ[]
            sage: C = Conic([1,0,0,t,0,1/t])
            sage: D = Conic([1/t^2, 0, -2/t^2, t, 0, (t + 1)/t^2])
            sage: T = Matrix([[t,0,1],[0,1,0],[0,0,1]])
            sage: C.hom(T, D)
            Scheme morphism:
              From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Rational Field defined by x^2 + t*y^2 + 1/t*z^2
              To:   Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Rational Field defined by 1/t^2*x^2 + t*y^2 + (-2/t^2)*x*z + ((t + 1)/t^2)*z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (t*x + z : y : z)

        """
        if is_Matrix(x):
            from constructor import Conic
            y = x.inverse()
            A = y.transpose() * self.matrix() * y
            im = Conic(A)
            if Y is None:
                Y = im
            elif not Y == im:
                raise ValueError("The matrix x (= %s) does not define a " \
                                 "map from self (= %s) to Y (= %s)" % \
                                 (x, self, Y))
            x = Sequence(x * vector(self.ambient_space().gens()))
            return self.Hom(Y)(x, check=False)
        return ProjectiveCurve_generic.hom(self, x, Y)
    def has_rational_point(self, point = False, algorithm = 'default',
        read_cache = True):
        r"""
        Returns True if and only if the conic ``self``
        has a point over its base field `F(t)`, which is a field of rational
        functions.

        If ``point`` is True, then returns a second output, which is
        a rational point if one exists.

        Points are cached whenever they are found. Cached information
        is used if and only if ``read_cache`` is True.
        
        The default algorithm does not (yet) work for all base fields `F`.
        In particular, sage is required to have:
        
        * an algorithm for finding the square root of elements in finite
          extensions of `F`;
        
        * a factorization and gcd algorithm for `F[t]`;
        
        * an algorithm for solving conics over `F`.
        
        ALGORITHM:
        
        The parameter ``algorithm`` specifies the algorithm
        to be used:

        * ``'default'`` -- use a native Sage implementation, based on the
          algorithm Conic in [HC2006]_.

        * ``'magma'`` (requires Magma to be installed) --
          delegates the task to the Magma computer algebra
          system.
        
        EXAMPLES:
        
        We can find points for function fields over (extensions of) `\QQ`
        and finite fields::
        
            sage: K.<t> = FractionField(PolynomialRing(QQ, 't'))
            sage: C = Conic(K, [t^2-2, 2*t^3, -2*t^3-13*t^2-2*t+18])
            sage: C.has_rational_point(point=True)
            (True, (-3 : (t + 1)/t : 1))
            sage: R.<t> = FiniteField(23)[]
            sage: C = Conic([2, t^2+1, t^2+5])
            sage: C.has_rational_point()
            True
            sage: C.has_rational_point(point=True)
            (True, (5*t : 8 : 1))
            sage: F.<i> = QuadraticField(-1)
            sage: R.<t> = F[]
            sage: C = Conic([1,i*t,-t^2+4])
            sage: C.has_rational_point(point = True)
            verbose 0 (3369: multi_polynomial_ideal.py, groebner_basis) Warning: falling back to very slow toy implementation.
            ...
            (True, (-t - 2*i : -2*i : 1))

        It works on non-diagonal conics as well::

            sage: K.<t> = QQ[]
            sage: C = Conic([4, -4, 8, 1, -4, t + 4])
            sage: C.has_rational_point(point=True)
            (True, (1/2 : 1 : 0))

        If no point exists output still depends on the argument ``point``::

            sage: K.<t> = QQ[]
            sage: C = Conic(K, [t^2, (t-1), -2*(t-1)])
            sage: C.has_rational_point()
            False
            sage: C.has_rational_point(point=True)
            (False, None)
        
        Due to limitations in Sage of algorithms we depend on, it is not
        yet possible to find points on conics over multivariate function fields
        (see the requirements above)::
        
            sage: F.<t1> = FractionField(QQ['t1'])
            sage: K.<t2> = FractionField(F['t2'])
            sage: a = K(1)
            sage: b = 2*t2^2+2*t1*t2-t1^2
            sage: c = -3*t2^4-4*t1*t2^3+8*t1^2*t2^2+16*t1^3-t2-48*t1^4
            sage: C = Conic([a,b,c])
            sage: C.has_rational_point()
            ...
            Traceback (most recent call last):
            ...
            NotImplementedError: is_square() not implemented for elements of
            Univariate Quotient Polynomial Ring in tbar over Fraction Field
            of Univariate Polynomial Ring in t1 over Rational Field with
            modulus tbar^2 + t1*tbar - 1/2*t1^2
        
        In some cases, the algorithm requires us to be
        able to solve conics over `F`. In particular, the following does not
        work::

            sage: P.<u> = QQ[]
            sage: E = P.fraction_field()
            sage: Q.<Y> = E[]
            sage: F.<v> = E.extension(Y^2 - u^3 - 1)
            sage: R.<t> = F[]
            sage: K = R.fraction_field()
            sage: C = Conic(K, [u, v, 1])
            sage: C.has_rational_point()
            ...
            Traceback (most recent call last):
            ...
            NotImplementedError: has_rational_point not implemented for conics
            over base field Univariate Quotient Polynomial Ring in v over
            Fraction Field of Univariate Polynomial Ring in u over Rational
            Field with modulus v^2 - u^3 - 1

        ``has_rational_point`` fails for some conics over function fields
        over finite fields, due to :trac:`20003`::

            sage: K.<t> = PolynomialRing(GF(7))
            sage: C = Conic([5*t^2+4, t^2+3*t+3, 6*t^2+3*t+2, 5*t^2+5, 4*t+3, 4*t^2+t+5])
            sage: C.has_rational_point()
            ...
            Traceback (most recent call last):
            ...
            TypeError: self (=Scheme morphism:
              From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5*t^2 + 4)*x^2 + ((6*t^3 + 3*t^2 + 5*t + 5)/(t + 3))*y^2 + ((6*t^6 + 3*t^5 + t^3 + 6*t^2 + 6*t + 2)/(t^4 + t^3 + 4*t^2 + 3*t + 1))*z^2
              To:   Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5*t^2 + 4)*x^2 + (t^2 + 3*t + 3)*x*y + (5*t^2 + 5)*y^2 + (6*t^2 + 3*t + 2)*x*z + (4*t + 3)*y*z + (4*t^2 + t + 5)*z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x + ((2*t + 5)/(t + 3))*y + ((3*t^4 + 2*t^3 + 5*t^2 + 5*t + 3)/(t^4 + t^3 + 4*t^2 + 3*t + 1))*z : y + ((6*t^3 + 6*t^2 + 3*t + 6)/(t^3 + 4*t^2 + 2*t + 2))*z : z)) domain must equal right (=Scheme morphism:
              From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5*t^3 + 6*t^2 + 3*t + 3)*x^2 + (t + 4)*y^2 + (6*t^7 + 2*t^5 + t^4 + 2*t^3 + 3*t^2 + 6*t + 6)*z^2
              To:   Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5/(t^3 + 4*t^2 + 2*t + 2))*x^2 + (1/(t^3 + 3*t^2 + 5*t + 1))*y^2 + ((6*t^6 + 3*t^5 + t^3 + 6*t^2 + 6*t + 2)/(t^9 + 5*t^8 + t^7 + 6*t^6 + 3*t^5 + 4*t^3 + t^2 + 5*t + 3))*z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    ((t^3 + 4*t^2 + 2*t + 2)*x : (t^2 + 5)*y : (t^5 + 4*t^4 + t^2 + 3*t + 3)*z)) codomain

            
        TESTS::

            sage: K.<t> = FractionField(PolynomialRing(QQ, 't'))
            sage: a = (2*t^2 - 3/2*t + 1)/(37/3*t^2 + t - 1/4)
            sage: b = (1/2*t^2 + 1/3)/(-73*t^2 - 2*t + 11/4)
            sage: c = (6934/3*t^6 + 8798/3*t^5 - 947/18*t^4 + 3949/9*t^3 + 20983/18*t^2 + 28/3*t - 131/3)/(-2701/3*t^4 - 293/3*t^3 + 301/6*t^2 + 13/4*t - 11/16)
            sage: C = Conic([a,b,c])
            sage: C.has_rational_point(point=True)
            (True, (4*t + 4 : 2*t + 2 : 1))

        A long time test::

            sage: K.<t> = FractionField(PolynomialRing(QQ, 't'))
            sage: a = (-1/3*t^6 - 14*t^5 - 1/4*t^4 + 7/2*t^2 - 1/2*t - 1)/(24/5*t^6 - t^5 - 1/4*t^4 + t^3 - 3*t^2 + 8/5*t + 5)
            sage: b = (-3*t^3 + 8*t + 1/2)/(-1/3*t^3 + 3/2*t^2 + 1/12*t + 1/2)
            sage: c = (1232009/225*t^25 - 1015925057/8100*t^24 + 1035477411553/1458000*t^23 + 7901338091/30375*t^22 - 1421379260447/729000*t^21 + 266121260843/972000*t^20 + 80808723191/486000*t^19 - 516656082523/972000*t^18 + 21521589529/40500*t^17 + 4654758997/21600*t^16 - 20064038625227/9720000*t^15 - 173054270347/324000*t^14 + 536200870559/540000*t^13 - 12710739349/50625*t^12 - 197968226971/135000*t^11 - 134122025657/810000*t^10 + 22685316301/120000*t^9 - 2230847689/21600*t^8 - 70624099679/270000*t^7 - 4298763061/270000*t^6 - 41239/216000*t^5 - 13523/36000*t^4 + 493/36000*t^3 + 83/2400*t^2 + 1/300*t + 1/200)/(-27378/125*t^17 + 504387/500*t^16 - 97911/2000*t^15 + 1023531/4000*t^14 + 1874841/8000*t^13 + 865381/12000*t^12 + 15287/375*t^11 + 6039821/6000*t^10 + 599437/1500*t^9 + 18659/250*t^8 + 1218059/6000*t^7 + 2025127/3000*t^6 + 1222759/6000*t^5 + 38573/200*t^4 + 8323/125*t^3 + 15453/125*t^2 + 17031/500*t + 441/10)
            sage: C = Conic([a,b,c])
            sage: C.has_rational_point(point = True) # long time (4 seconds)
            (True,
             ((-2/117*t^8 + 304/1053*t^7 + 40/117*t^6 - 1/27*t^5 - 110/351*t^4 - 2/195*t^3 + 11/351*t^2 + 1/117)/(t^4 + 2/39*t^3 + 4/117*t^2 + 2/39*t + 14/39) : -5/3*t^4 + 19*t^3 : 1))
        """
        from constructor import Conic
        
        if read_cache:
            if self._rational_point is not None:
                return (True, self._rational_point) if point else True
        
        if algorithm != 'default':
            return ProjectiveConic_field.has_rational_point(self, point,
                algorithm, read_cache)
        
        # Default algorithm
        if self.base_ring().characteristic() == 2:
            raise NotImplementedError("has_rational_point not implemented \
for function field of characteristic 2.")
        new_conic, transformation, inverse = self.diagonalization()
        coeff = new_conic.coefficients()
        if coeff[0] == 0:
            return (True, transformation([1,0,0])) if point else True
        elif coeff[3] == 0:
            return (True, transformation([0,1,0])) if point else True
        elif coeff[5] == 0:
            return (True, transformation([0,0,1])) if point else True
        
        # We save the coefficients of the reduced form in coeff
        # A zero of the reduced conic can be multiplied by multipliers
        # to get a zero of the old conic
        (coeff, multipliers) = new_conic._reduce_conic()
        new_conic = Conic(coeff)
        transformation = transformation \
            * new_conic.hom(diagonal_matrix(multipliers))
        if coeff[0].degree() % 2 == coeff[1].degree() % 2 and \
                coeff[1].degree() % 2 == coeff[2].degree() % 2:
            case = 0
        else:
            case = 1
        
        t, = self.base_ring().base().gens() # t in F[t]
        supp = []
        roots = [[], [], []]
        remove = None
        # loop through the coefficients and find a root of f_i (as in
        # [HC2006]) modulo each element in the coefficients' support
        for i in (0,1,2):
            supp.append(list(coeff[i].factor()))
            for p in supp[i]:
                if p[1] != 1:
                    raise ValueError("Expected factor of exponent 1.")
                # Convert to monic factor
                x = p[0]/list(p[0])[-1]
                N = p[0].base_ring().extension(x, 'tbar')
                R = PolynomialRing(N, 'u')
                u, = R.gens()
                # If p[0] has degree 1, sage might forget the "defining
                # polynomial" of N, so we define our own modulo operation
                if p[0].degree() == 1:
                    mod = t.parent().hom([-x[0]])
                else:
                    mod = N
                if i == 0:
                    x = -mod(coeff[2])/mod(coeff[1])
                elif i == 1:
                    x = -mod(coeff[0])/mod(coeff[2])
                else:
                    x = -mod(coeff[1])/mod(coeff[0])
                if x.is_square():
                    root = N(x.sqrt())
                else:
                    return (False, None) if point else False
                # if case == 0 and p[0] has degree 1, we switch to case
                # 1 and remove this factor out of the support. In [HC2006]
                # this is done later, in FindPoint.
                if case == 0 and p[0].degree() == 1:
                    case = 1
                    # remove later so the loop iterator stays in place.
                    remove = (i,p)
                else:
                    roots[i].append(root)
        if remove:
            supp[remove[0]].remove(remove[1])
        supp = [[p[0] for p in supp[i]] for i in (0,1,2)]

        if case == 0:
        # Find a solution of (5) in [HC2006]
            leading_conic = Conic(self.base_ring().base_ring(),
                        [coeff[0].leading_coefficient(),
                        coeff[1].leading_coefficient(),
                        coeff[2].leading_coefficient()])
            has_point = leading_conic.has_rational_point(True)
            if has_point[0]:
                if point:
                    pt = new_conic.find_point(supp, roots, case,
                        has_point[1])
                else:
                    pt = True
                return (True, transformation(pt)) if point else True
            else:
                return (False, None) if point else False
        # case == 1:
        if point:
            pt = new_conic.find_point(supp, roots, case)
        else:
            pt = True
        return (True, transformation(pt)) if point else True
Ejemplo n.º 11
0
    def has_rational_point(self, point = False, algorithm = 'default',
        read_cache = True):
        r"""
        Returns True if and only if the conic ``self``
        has a point over its base field `F(t)`, which is a field of rational
        functions.

        If ``point`` is True, then returns a second output, which is
        a rational point if one exists.

        Points are cached whenever they are found. Cached information
        is used if and only if ``read_cache`` is True.
        
        The default algorithm does not (yet) work for all base fields `F`.
        In particular, sage is required to have:
        
        * an algorithm for finding the square root of elements in finite
          extensions of `F`;
        
        * a factorization and gcd algorithm for `F[t]`;
        
        * an algorithm for solving conics over `F`.
        
        ALGORITHM:
        
        The parameter ``algorithm`` specifies the algorithm
        to be used:

        * ``'default'`` -- use a native Sage implementation, based on the
          algorithm Conic in [HC2006]_.

        * ``'magma'`` (requires Magma to be installed) --
          delegates the task to the Magma computer algebra
          system.
        
        EXAMPLES:
        
        We can find points for function fields over (extensions of) `\QQ`
        and finite fields::
        
            sage: K.<t> = FractionField(PolynomialRing(QQ, 't'))
            sage: C = Conic(K, [t^2-2, 2*t^3, -2*t^3-13*t^2-2*t+18])
            sage: C.has_rational_point(point=True)
            (True, (-3 : (t + 1)/t : 1))
            sage: R.<t> = FiniteField(23)[]
            sage: C = Conic([2, t^2+1, t^2+5])
            sage: C.has_rational_point()
            True
            sage: C.has_rational_point(point=True)
            (True, (5*t : 8 : 1))
            sage: F.<i> = QuadraticField(-1)
            sage: R.<t> = F[]
            sage: C = Conic([1,i*t,-t^2+4])
            sage: C.has_rational_point(point = True)
            verbose 0 (3369: multi_polynomial_ideal.py, groebner_basis) Warning: falling back to very slow toy implementation.
            ...
            (True, (-t - 2*i : -2*i : 1))

        It works on non-diagonal conics as well::

            sage: K.<t> = QQ[]
            sage: C = Conic([4, -4, 8, 1, -4, t + 4])
            sage: C.has_rational_point(point=True)
            (True, (1/2 : 1 : 0))

        If no point exists output still depends on the argument ``point``::

            sage: K.<t> = QQ[]
            sage: C = Conic(K, [t^2, (t-1), -2*(t-1)])
            sage: C.has_rational_point()
            False
            sage: C.has_rational_point(point=True)
            (False, None)
        
        Due to limitations in Sage of algorithms we depend on, it is not
        yet possible to find points on conics over multivariate function fields
        (see the requirements above)::
        
            sage: F.<t1> = FractionField(QQ['t1'])
            sage: K.<t2> = FractionField(F['t2'])
            sage: a = K(1)
            sage: b = 2*t2^2+2*t1*t2-t1^2
            sage: c = -3*t2^4-4*t1*t2^3+8*t1^2*t2^2+16*t1^3-t2-48*t1^4
            sage: C = Conic([a,b,c])
            sage: C.has_rational_point()
            ...
            Traceback (most recent call last):
            ...
            NotImplementedError: is_square() not implemented for elements of
            Univariate Quotient Polynomial Ring in tbar over Fraction Field
            of Univariate Polynomial Ring in t1 over Rational Field with
            modulus tbar^2 + t1*tbar - 1/2*t1^2
        
        In some cases, the algorithm requires us to be
        able to solve conics over `F`. In particular, the following does not
        work::

            sage: P.<u> = QQ[]
            sage: E = P.fraction_field()
            sage: Q.<Y> = E[]
            sage: F.<v> = E.extension(Y^2 - u^3 - 1)
            sage: R.<t> = F[]
            sage: K = R.fraction_field()
            sage: C = Conic(K, [u, v, 1])
            sage: C.has_rational_point()
            ...
            Traceback (most recent call last):
            ...
            NotImplementedError: has_rational_point not implemented for conics
            over base field Univariate Quotient Polynomial Ring in v over
            Fraction Field of Univariate Polynomial Ring in u over Rational
            Field with modulus v^2 - u^3 - 1

        ``has_rational_point`` fails for some conics over function fields
        over finite fields, due to :trac:`20003`::

            sage: K.<t> = PolynomialRing(GF(7))
            sage: C = Conic([5*t^2+4, t^2+3*t+3, 6*t^2+3*t+2, 5*t^2+5, 4*t+3, 4*t^2+t+5])
            sage: C.has_rational_point()
            ...
            Traceback (most recent call last):
            ...
            TypeError: self (=Scheme morphism:
              From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5*t^2 + 4)*x^2 + ((6*t^3 + 3*t^2 + 5*t + 5)/(t + 3))*y^2 + ((6*t^6 + 3*t^5 + t^3 + 6*t^2 + 6*t + 2)/(t^4 + t^3 + 4*t^2 + 3*t + 1))*z^2
              To:   Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5*t^2 + 4)*x^2 + (t^2 + 3*t + 3)*x*y + (5*t^2 + 5)*y^2 + (6*t^2 + 3*t + 2)*x*z + (4*t + 3)*y*z + (4*t^2 + t + 5)*z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    (x + ((2*t + 5)/(t + 3))*y + ((3*t^4 + 2*t^3 + 5*t^2 + 5*t + 3)/(t^4 + t^3 + 4*t^2 + 3*t + 1))*z : y + ((6*t^3 + 6*t^2 + 3*t + 6)/(t^3 + 4*t^2 + 2*t + 2))*z : z)) domain must equal right (=Scheme morphism:
              From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5*t^3 + 6*t^2 + 3*t + 3)*x^2 + (t + 4)*y^2 + (6*t^7 + 2*t^5 + t^4 + 2*t^3 + 3*t^2 + 6*t + 6)*z^2
              To:   Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5/(t^3 + 4*t^2 + 2*t + 2))*x^2 + (1/(t^3 + 3*t^2 + 5*t + 1))*y^2 + ((6*t^6 + 3*t^5 + t^3 + 6*t^2 + 6*t + 2)/(t^9 + 5*t^8 + t^7 + 6*t^6 + 3*t^5 + 4*t^3 + t^2 + 5*t + 3))*z^2
              Defn: Defined on coordinates by sending (x : y : z) to
                    ((t^3 + 4*t^2 + 2*t + 2)*x : (t^2 + 5)*y : (t^5 + 4*t^4 + t^2 + 3*t + 3)*z)) codomain

            
        TESTS::

            sage: K.<t> = FractionField(PolynomialRing(QQ, 't'))
            sage: a = (2*t^2 - 3/2*t + 1)/(37/3*t^2 + t - 1/4)
            sage: b = (1/2*t^2 + 1/3)/(-73*t^2 - 2*t + 11/4)
            sage: c = (6934/3*t^6 + 8798/3*t^5 - 947/18*t^4 + 3949/9*t^3 + 20983/18*t^2 + 28/3*t - 131/3)/(-2701/3*t^4 - 293/3*t^3 + 301/6*t^2 + 13/4*t - 11/16)
            sage: C = Conic([a,b,c])
            sage: C.has_rational_point(point=True)
            (True, (4*t + 4 : 2*t + 2 : 1))

        A long time test::

            sage: K.<t> = FractionField(PolynomialRing(QQ, 't'))
            sage: a = (-1/3*t^6 - 14*t^5 - 1/4*t^4 + 7/2*t^2 - 1/2*t - 1)/(24/5*t^6 - t^5 - 1/4*t^4 + t^3 - 3*t^2 + 8/5*t + 5)
            sage: b = (-3*t^3 + 8*t + 1/2)/(-1/3*t^3 + 3/2*t^2 + 1/12*t + 1/2)
            sage: c = (1232009/225*t^25 - 1015925057/8100*t^24 + 1035477411553/1458000*t^23 + 7901338091/30375*t^22 - 1421379260447/729000*t^21 + 266121260843/972000*t^20 + 80808723191/486000*t^19 - 516656082523/972000*t^18 + 21521589529/40500*t^17 + 4654758997/21600*t^16 - 20064038625227/9720000*t^15 - 173054270347/324000*t^14 + 536200870559/540000*t^13 - 12710739349/50625*t^12 - 197968226971/135000*t^11 - 134122025657/810000*t^10 + 22685316301/120000*t^9 - 2230847689/21600*t^8 - 70624099679/270000*t^7 - 4298763061/270000*t^6 - 41239/216000*t^5 - 13523/36000*t^4 + 493/36000*t^3 + 83/2400*t^2 + 1/300*t + 1/200)/(-27378/125*t^17 + 504387/500*t^16 - 97911/2000*t^15 + 1023531/4000*t^14 + 1874841/8000*t^13 + 865381/12000*t^12 + 15287/375*t^11 + 6039821/6000*t^10 + 599437/1500*t^9 + 18659/250*t^8 + 1218059/6000*t^7 + 2025127/3000*t^6 + 1222759/6000*t^5 + 38573/200*t^4 + 8323/125*t^3 + 15453/125*t^2 + 17031/500*t + 441/10)
            sage: C = Conic([a,b,c])
            sage: C.has_rational_point(point = True) # long time (4 seconds)
            (True,
             ((-2/117*t^8 + 304/1053*t^7 + 40/117*t^6 - 1/27*t^5 - 110/351*t^4 - 2/195*t^3 + 11/351*t^2 + 1/117)/(t^4 + 2/39*t^3 + 4/117*t^2 + 2/39*t + 14/39) : -5/3*t^4 + 19*t^3 : 1))
        """
        from constructor import Conic
        
        if read_cache:
            if self._rational_point is not None:
                return (True, self._rational_point) if point else True
        
        if algorithm != 'default':
            return ProjectiveConic_field.has_rational_point(self, point,
                algorithm, read_cache)
        
        # Default algorithm
        if self.base_ring().characteristic() == 2:
            raise NotImplementedError("has_rational_point not implemented \
for function field of characteristic 2.")
        new_conic, transformation, inverse = self.diagonalization()
        coeff = new_conic.coefficients()
        if coeff[0] == 0:
            return (True, transformation([1,0,0])) if point else True
        elif coeff[3] == 0:
            return (True, transformation([0,1,0])) if point else True
        elif coeff[5] == 0:
            return (True, transformation([0,0,1])) if point else True
        
        # We save the coefficients of the reduced form in coeff
        # A zero of the reduced conic can be multiplied by multipliers
        # to get a zero of the old conic
        (coeff, multipliers) = new_conic._reduce_conic()
        new_conic = Conic(coeff)
        transformation = transformation \
            * new_conic.hom(diagonal_matrix(multipliers))
        if coeff[0].degree() % 2 == coeff[1].degree() % 2 and \
                coeff[1].degree() % 2 == coeff[2].degree() % 2:
            case = 0
Ejemplo n.º 12
0
                # 1 and remove this factor out of the support. In [HC2006]
                # this is done later, in FindPoint.
                if case == 0 and p[0].degree() == 1:
                    case = 1
                    # remove later so the loop iterator stays in place.
                    remove = (i,p)
                else:
                    roots[i].append(root)
        if remove:
            supp[remove[0]].remove(remove[1])
        supp = [[p[0] for p in supp[i]] for i in (0,1,2)]

        if case == 0:
        # Find a solution of (5) in [HC2006]
            leading_conic = Conic(self.base_ring().base_ring(),
                        [coeff[0].leading_coefficient(),
                        coeff[1].leading_coefficient(),
                        coeff[2].leading_coefficient()])
            has_point = leading_conic.has_rational_point(True)
            if has_point[0]:
                if point:
                    pt = new_conic.find_point(supp, roots, case,
                        has_point[1])
                else:
                    pt = True
                return (True, transformation(pt)) if point else True
            else:
                return (False, None) if point else False
        # case == 1:
        if point:
            pt = new_conic.find_point(supp, roots, case)
        else: