Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" Projective plane conics over a field
AUTHORS:
- Marco Streng (2010-07-20)
- Nick Alexander (2008-01-08)
""" from __future__ import absolute_import #***************************************************************************** # Copyright (C) 2008 Nick Alexander <ncalexander@gmail.com> # Copyright (C) 2009/2010 Marco Streng <marco.streng@gmail.com> # # Distributed under the terms of the GNU General Public License (GPL) # # This code is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # The full text of the GPL is available at: # # http://www.gnu.org/licenses/ #*****************************************************************************
from sage.rings.all import PolynomialRing
from sage.rings.complex_field import is_ComplexField from sage.rings.real_mpfr import is_RealField
from sage.modules.free_module_element import vector from sage.structure.sequence import Sequence from sage.structure.element import is_Vector from sage.schemes.projective.projective_space import ProjectiveSpace from sage.matrix.constructor import Matrix from sage.structure.element import is_Matrix
from sage.schemes.curves.projective_curve import ProjectivePlaneCurve
from sage.categories.fields import Fields _Fields = Fields()
class ProjectiveConic_field(ProjectivePlaneCurve): r""" Create a projective plane conic curve over a field. See ``Conic`` for full documentation.
EXAMPLES::
sage: K = FractionField(PolynomialRing(QQ, 't')) sage: P.<X, Y, Z> = K[] sage: Conic(X^2 + Y^2 - Z^2) Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Rational Field defined by X^2 + Y^2 - Z^2
TESTS::
sage: K = FractionField(PolynomialRing(QQ, 't')) sage: Conic([K(1), 1, -1])._test_pickling() """ def __init__(self, A, f): r""" See ``Conic`` for full documentation.
EXAMPLES:
::
sage: c = Conic([1, 1, 1]); c Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^2 """ f[(0,2,0)], f[(0,1,1)], f[(0,0,2)]]
def _repr_type(self): r""" Returns ``'Projective Conic'``, which is the first part of the plain text representation of this object as output by the function ``_repr_`` of the class ``Curve_generic``.
EXAMPLES::
sage: c = Conic([1, 1, 1]); c Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^2 sage: c._repr_() 'Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^2' sage: c._repr_type() 'Projective Conic' """
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) """ return self raise ValueError("No natural map from the base ring of self " \ "(= %s) to S (= %s)" % (self, S)) self.variable_names()) 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 ProjectivePlaneCurve.base_extend(self, S)
def cache_point(self, p): r""" Replace the point in the cache of ``self`` by ``p`` for use by ``self.rational_point()`` and ``self.parametrization()``.
EXAMPLES::
sage: c = Conic([1, -1, 1]) sage: c.point([15, 17, 8]) (15/8 : 17/8 : 1) sage: c.rational_point() (15/8 : 17/8 : 1) sage: c.cache_point(c.rational_point(read_cache = False)) sage: c.rational_point() (-1 : 1 : 0) """ p = self.point(p)
def coefficients(self): r""" Gives a the `6` coefficients of the conic ``self`` in lexicographic order.
EXAMPLES::
sage: Conic(QQ, [1,2,3,4,5,6]).coefficients() [1, 2, 3, 4, 5, 6]
sage: P.<x,y,z> = GF(13)[] sage: a = Conic(x^2+5*x*y+y^2+z^2).coefficients(); a [1, 5, 0, 1, 0, 1] sage: Conic(a) Projective Conic Curve over Finite Field of size 13 defined by x^2 + 5*x*y + y^2 + z^2 """
def derivative_matrix(self): r""" Gives the derivative of the defining polynomial of the conic ``self``, which is a linear map, as a `3 \times 3` matrix.
EXAMPLES:
In characteristic different from `2`, the derivative matrix is twice the symmetric matrix:
::
sage: c = Conic(QQ, [1,1,1,1,1,0]) sage: c.symmetric_matrix() [ 1 1/2 1/2] [1/2 1 1/2] [1/2 1/2 0] sage: c.derivative_matrix() [2 1 1] [1 2 1] [1 1 0]
An example in characteristic `2`:
::
sage: P.<t> = GF(2)[] sage: c = Conic([t, 1, t^2, 1, 1, 0]); c Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using GF2X) defined by t*x^2 + x*y + y^2 + t^2*x*z + y*z sage: c.is_smooth() True sage: c.derivative_matrix() [ 0 1 t^2] [ 1 0 1] [t^2 1 0] """ [ b , 2*d , e ], [ c , e , 2*f ]])
def determinant(self): r""" Returns the determinant of the symmetric matrix that defines the conic ``self``.
This is defined only if the base field has characteristic different from `2`.
EXAMPLES:
::
sage: C = Conic([1,2,3,4,5,6]) sage: C.determinant() 41/4 sage: C.symmetric_matrix().determinant() 41/4
Determinants are only defined in characteristic different from `2`::
sage: C = Conic(GF(2), [1, 1, 1, 1, 1, 0]) sage: C.is_smooth() True sage: C.determinant() 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 """
def diagonal_matrix(self): r""" Returns a diagonal matrix `D` and a matrix `T` such that `T^t A T = D` holds, where `(x, y, z) A (x, y, z)^t` is the defining polynomial of the conic ``self``.
EXAMPLES:
::
sage: c = Conic(QQ, [1,2,3,4,5,6]) sage: d, t = c.diagonal_matrix(); d, t ( [ 1 0 0] [ 1 -1 -7/6] [ 0 3 0] [ 0 1 -1/3] [ 0 0 41/12], [ 0 0 1] ) sage: t.transpose()*c.symmetric_matrix()*t [ 1 0 0] [ 0 3 0] [ 0 0 41/12]
Diagonal matrices are only defined in characteristic different from `2`:
::
sage: c = Conic(GF(4, 'a'), [0, 1, 1, 1, 1, 1]) sage: c.is_smooth() True sage: c.diagonal_matrix() Traceback (most recent call last): ... ValueError: The conic self (= Projective Conic Curve over Finite Field in a of size 2^2 defined by x*y + y^2 + x*z + y*z + z^2) has no symmetric matrix because the base field has characteristic 2 """ if basis[i]*A*basis[j].column() != 0: basis[i] = basis[i]+basis[j] zerovalue = False (basis[i]*A*basis[j].column())/l * basis[i]
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))
"""
def gens(self): r""" Returns the generators of the coordinate ring of ``self``.
EXAMPLES:
::
sage: P.<x,y,z> = QQ[] sage: c = Conic(x^2+y^2+z^2) sage: c.gens() (xbar, ybar, zbar) sage: c.defining_polynomial()(c.gens()) 0
The function ``gens()`` is required for the following construction:
::
sage: C.<a,b,c> = Conic(GF(3), [1, 1, 1]) sage: C Projective Conic Curve over Finite Field of size 3 defined by a^2 + b^2 + c^2
"""
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 `B`.
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.
ALGORITHM:
The parameter ``algorithm`` specifies the algorithm to be used:
- ``'default'`` -- If the base field is real or complex, use an elementary native Sage implementation.
- ``'magma'`` (requires Magma to be installed) -- delegates the task to the Magma computer algebra system.
EXAMPLES:
sage: Conic(RR, [1, 1, 1]).has_rational_point() False sage: Conic(CC, [1, 1, 1]).has_rational_point() True
sage: Conic(RR, [1, 2, -3]).has_rational_point(point = True) (True, (1.73205080756888 : 0.000000000000000 : 1.00000000000000))
Conics over polynomial rings can be solved internally::
sage: R.<t> = QQ[] sage: C = Conic([-2,t^2+1,t^2-1]) sage: C.has_rational_point() True
And they can also be solved with Magma::
sage: C.has_rational_point(algorithm='magma') # optional - magma True sage: C.has_rational_point(algorithm='magma', point=True) # optional - magma (True, (t : 1 : 1))
sage: D = Conic([t,1,t^2]) sage: D.has_rational_point(algorithm='magma') # optional - magma False
TESTS:
One of the following fields comes with an embedding into the complex numbers, one does not. Check that they are both handled correctly by the Magma interface. ::
sage: K.<i> = QuadraticField(-1) sage: K.coerce_embedding() Generic morphism: From: Number Field in i with defining polynomial x^2 + 1 To: Complex Lazy Field Defn: i -> 1*I sage: Conic(K, [1,1,1]).rational_point(algorithm='magma') # optional - magma (-i : 1 : 0)
sage: x = QQ['x'].gen() sage: L.<i> = NumberField(x^2+1, embedding=None) sage: Conic(L, [1,1,1]).rational_point(algorithm='magma') # optional - magma (-i : 1 : 0) sage: L == K False """ if point: return True, self._rational_point else: return True
from sage.interfaces.magma import magma M = magma(self) b = M.HasRationalPoint().sage() if not point: return b if not b: return False, None M_pt = M.HasRationalPoint(nvals=2)[1]
# Various attempts will be made to convert `pt` to # a Sage object. The end result will always be checked # by self.point().
pt = [M_pt[1], M_pt[2], M_pt[3]]
# The first attempt is to use sequences. This is efficient and # succeeds in cases where the Magma interface fails to convert # number field elements, because embeddings between number fields # may be lost on conversion to and from Magma. # This should deal with all absolute number fields. try: return True, self.point([B(c.Eltseq().sage()) for c in pt]) except TypeError: pass
# The second attempt tries to split Magma elements into # numerators and denominators first. This is necessary # for the field of rational functions, because (at the moment of # writing) fraction field elements are not converted automatically # from Magma to Sage. try: return True, self.point( \ [B(c.Numerator().sage()/c.Denominator().sage()) for c in pt]) except (TypeError, NameError): pass
# Finally, let the Magma interface handle conversion. try: return True, self.point([B(c.sage()) for c in pt]) except (TypeError, NameError): pass
raise NotImplementedError("No correct conversion implemented for converting the Magma point %s on %s to a correct Sage point on self (=%s)" % (M_pt, M, self))
raise ValueError("Unknown algorithm: %s" % algorithm)
return True, self.point([0,1,0]) check = False) ret = True, self.point(T*vector([1,0,0]), check = False) check = False) ret = True, self.point(T*vector([0,1,0]), check = False) ret = True, self.point(T*vector([0,(-c/b).sqrt(),0,1]), check = False) else: "conics over base field %s" % B)
def has_singular_point(self, point = False): r""" Return True if and only if the conic ``self`` has a rational singular point.
If ``point`` is True, then also return a rational singular point (or ``None`` if no such point exists).
EXAMPLES:
::
sage: c = Conic(QQ, [1,0,1]); c Projective Conic Curve over Rational Field defined by x^2 + z^2 sage: c.has_singular_point(point = True) (True, (0 : 1 : 0))
sage: P.<x,y,z> = GF(7)[] sage: e = Conic((x+y+z)*(x-y+2*z)); e Projective Conic Curve over Finite Field of size 7 defined by x^2 - y^2 + 3*x*z + y*z + 2*z^2 sage: e.has_singular_point(point = True) (True, (2 : 4 : 1))
sage: Conic([1, 1, -1]).has_singular_point() False sage: Conic([1, 1, -1]).has_singular_point(point = True) (False, None)
``has_singular_point`` is not implemented over all fields of characteristic `2`. It is implemented over finite fields.
::
sage: F.<a> = FiniteField(8) sage: Conic([a, a+1, 1]).has_singular_point(point = True) (True, (a + 1 : 0 : 1))
sage: P.<t> = GF(2)[] sage: C = Conic(P, [t,t,1]); C Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using GF2X) defined by t*x^2 + t*y^2 + z^2 sage: C.has_singular_point(point = False) Traceback (most recent call last): ... NotImplementedError: Sorry, find singular point on conics not implemented over all fields of characteristic 2. """ return True, self.point(vector(B, {2:0, i:1})) return True, self.point([0,1,(d/f).sqrt()])
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)
""" "map from self (= %s) to Y (= %s)" % \ (x, self, Y)) return ProjectivePlaneCurve.hom(self, x, Y)
def is_diagonal(self): r""" Return True if and only if the conic has the form `a*x^2 + b*y^2 + c*z^2`.
EXAMPLES:
::
sage: c=Conic([1,1,0,1,0,1]); c Projective Conic Curve over Rational Field defined by x^2 + x*y + y^2 + z^2 sage: d,t = c.diagonal_matrix() sage: c.is_diagonal() False sage: c.diagonalization()[0].is_diagonal() True """
def is_smooth(self): r""" Returns True if and only if ``self`` is smooth.
EXAMPLES:
::
sage: Conic([1,-1,0]).is_smooth() False sage: Conic(GF(2),[1,1,1,1,1,0]).is_smooth() True """ return False
def _magma_init_(self, magma): """ Internal function. Returns a string to initialize this conic in the Magma subsystem.
EXAMPLES::
sage: C = Conic(QQ, [1,2,3]) sage: C._magma_init_(magma) # optional - magma 'Conic([_sage_ref...|1/1,2/1,3/1,0/1,0/1,0/1])' sage: C = Conic(GF(41), [-1,2,5]) # optional - magma sage: C._magma_init_(magma) # optional - magma 'Conic([_sage_ref...|GF(41)!40,GF(41)!2,GF(41)!5,GF(41)!0,GF(41)!0,GF(41)!0])' sage: F.<a> = GF(25) sage: C = Conic([3,0,1,4,a,2]) sage: C Projective Conic Curve over Finite Field in a of size 5^2 defined by -2*x^2 - y^2 + x*z + (a)*y*z + 2*z^2 sage: magma(C) # optional - magma Conic over GF(5^2) defined by 3*X^2 + 4*Y^2 + X*Z + a*Y*Z + 2*Z^2 sage: magma(Conic([1/2,2/3,-4/5,6/7,8/9,-10/11])) # optional - magma Conic over Rational Field defined by 1/2*X^2 + 2/3*X*Y + 6/7*Y^2 - 4/5*X*Z + 8/9*Y*Z - 10/11*Z^2 sage: R.<x> = Frac(QQ['x']) sage: magma(Conic([x,1+x,1-x])) # optional - magma Conic over Univariate rational function field over Rational Field defined by x*X^2 + (x + 1)*Y^2 + (-x + 1)*Z^2 sage: P.<x> = QQ[] sage: K.<b> = NumberField(x^3+x+1) sage: magma(Conic([b,1,2])) # optional - magma Conic over Number Field with defining polynomial x^3 + x + 1 over the Rational Field defined by b*X^2 + Y^2 + 2*Z^2 """ kmn = magma(self.base_ring())._ref() coeffs = self.coefficients() magma_coeffs = [coeffs[i]._magma_init_(magma) for i in [0, 3, 5, 1, 4, 2]] return 'Conic([%s|%s])' % (kmn,','.join(magma_coeffs))
def matrix(self): r""" Returns a matrix `M` such that `(x, y, z) M (x, y, z)^t` is the defining equation of ``self``.
The matrix `M` is upper triangular if the base field has characteristic `2` and symmetric otherwise.
EXAMPLES::
sage: R.<x, y, z> = QQ[] sage: C = Conic(x^2 + x*y + y^2 + z^2) sage: C.matrix() [ 1 1/2 0] [1/2 1 0] [ 0 0 1]
sage: R.<x, y, z> = GF(2)[] sage: C = Conic(x^2 + x*y + y^2 + x*z + z^2) sage: C.matrix() [1 1 1] [0 1 0] [0 0 1] """
_matrix_ = matrix
def parametrization(self, point=None, morphism=True): r""" Return a parametrization `f` of ``self`` together with the inverse of `f`.
If ``point`` is specified, then that point is used for the parametrization. Otherwise, use ``self.rational_point()`` to find a point.
If ``morphism`` is True, then `f` is returned in the form of a Scheme morphism. Otherwise, it is a tuple of polynomials that gives the parametrization.
EXAMPLES:
An example over a finite field ::
sage: c = Conic(GF(2), [1,1,1,1,1,0]) sage: c.parametrization() (Scheme morphism: From: Projective Space of dimension 1 over Finite Field of size 2 To: Projective Conic Curve over Finite Field of size 2 defined by x^2 + x*y + y^2 + x*z + y*z Defn: Defined on coordinates by sending (x : y) to (x*y + y^2 : x^2 + x*y : x^2 + x*y + y^2), Scheme morphism: From: Projective Conic Curve over Finite Field of size 2 defined by x^2 + x*y + y^2 + x*z + y*z To: Projective Space of dimension 1 over Finite Field of size 2 Defn: Defined on coordinates by sending (x : y : z) to (y : x))
An example with ``morphism = False`` ::
sage: R.<x,y,z> = QQ[] sage: C = Curve(7*x^2 + 2*y*z + z^2) sage: (p, i) = C.parametrization(morphism = False); (p, i) ([-2*x*y, x^2 + 7*y^2, -2*x^2], [-1/2*x, 1/7*y + 1/14*z]) sage: C.defining_polynomial()(p) 0 sage: i[0](p) / i[1](p) x/y
A ``ValueError`` is raised if ``self`` has no rational point ::
sage: C = Conic(x^2 + y^2 + 7*z^2) sage: C.parametrization() Traceback (most recent call last): ... ValueError: Conic Projective Conic Curve over Rational Field defined by x^2 + y^2 + 7*z^2 has no rational points over Rational Field!
A ``ValueError`` is raised if ``self`` is not smooth ::
sage: C = Conic(x^2 + y^2) sage: C.parametrization() Traceback (most recent call last): ... ValueError: The conic self (=Projective Conic Curve over Rational Field defined by x^2 + y^2) is not smooth, hence does not have a parametrization. """ else: raise ValueError("The conic self (=%s) is not smooth, hence does not have a parametrization." % self) tuple([gens[m]*point[c3]-gens[c3]*point[m] for m in [c2,c1]]))
def point(self, v, check=True): r""" Constructs a point on ``self`` corresponding to the input ``v``.
If ``check`` is True, then checks if ``v`` defines a valid point on ``self``.
If no rational point on ``self`` is known yet, then also caches the point for use by ``self.rational_point()`` and ``self.parametrization()``.
EXAMPLES ::
sage: c = Conic([1, -1, 1]) sage: c.point([15, 17, 8]) (15/8 : 17/8 : 1) sage: c.rational_point() (15/8 : 17/8 : 1) sage: d = Conic([1, -1, 1]) sage: d.rational_point() (-1 : 1 : 0) """
def random_rational_point(self, *args1, **args2): r""" Return a random rational point of the conic ``self``.
ALGORITHM:
1. Compute a parametrization `f` of ``self`` using ``self.parametrization()``. 2. Computes a random point `(x:y)` on the projective line. 3. Output `f(x:y)`.
The coordinates x and y are computed using ``B.random_element``, where ``B`` is the base field of ``self`` and additional arguments to ``random_rational_point`` are passed to ``random_element``.
If the base field is a finite field, then the output is uniformly distributed over the points of self.
EXAMPLES ::
sage: c = Conic(GF(2), [1,1,1,1,1,0]) sage: [c.random_rational_point() for i in range(10)] # output is random [(1 : 0 : 1), (1 : 0 : 1), (1 : 0 : 1), (0 : 1 : 1), (1 : 0 : 1), (0 : 0 : 1), (1 : 0 : 1), (1 : 0 : 1), (0 : 0 : 1), (1 : 0 : 1)]
sage: d = Conic(QQ, [1, 1, -1]) sage: d.random_rational_point(den_bound = 1, num_bound = 5) # output is random (-24/25 : 7/25 : 1)
sage: Conic(QQ, [1, 1, 1]).random_rational_point() Traceback (most recent call last): ... ValueError: Conic Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^2 has no rational points over Rational Field!
""" raise NotImplementedError("Sorry, random points not implemented " \ "for non-smooth conics")
def rational_point(self, algorithm = 'default', read_cache = True): r""" Return a point on ``self`` defined over the base field.
Raises ``ValueError`` if no rational point exists.
See ``self.has_rational_point`` for the algorithm used and for the use of the parameters ``algorithm`` and ``read_cache``.
EXAMPLES:
Examples over `\QQ` ::
sage: R.<x,y,z> = QQ[] sage: C = Conic(7*x^2 + 2*y*z + z^2) sage: C.rational_point() (0 : 1 : 0)
sage: C = Conic(x^2 + 2*y^2 + z^2) sage: C.rational_point() Traceback (most recent call last): ... ValueError: Conic Projective Conic Curve over Rational Field defined by x^2 + 2*y^2 + z^2 has no rational points over Rational Field!
sage: C = Conic(x^2 + y^2 + 7*z^2) sage: C.rational_point(algorithm = 'rnfisnorm') Traceback (most recent call last): ... ValueError: Conic Projective Conic Curve over Rational Field defined by x^2 + y^2 + 7*z^2 has no rational points over Rational Field!
Examples over number fields ::
sage: P.<x> = QQ[] sage: L.<b> = NumberField(x^3-5) sage: C = Conic(L, [3, 2, -5]) sage: p = C.rational_point(algorithm = 'rnfisnorm') sage: p # output is random (60*b^2 - 196*b + 161 : -120*b^2 - 6*b + 361 : 1) sage: C.defining_polynomial()(list(p)) 0
sage: K.<i> = QuadraticField(-1) sage: D = Conic(K, [3, 2, 5]) sage: D.rational_point(algorithm = 'rnfisnorm') # output is random (-3 : 4*i : 1)
sage: L.<s> = QuadraticField(2) sage: Conic(QQ, [1, 1, -3]).has_rational_point() False sage: E = Conic(L, [1, 1, -3]) sage: E.rational_point() # output is random (-1 : -s : 1)
Currently Magma is better at solving conics over number fields than Sage, so it helps to use the algorithm 'magma' if Magma is installed::
sage: q = C.rational_point(algorithm = 'magma', read_cache=False) # optional - magma sage: q # output is random, optional - magma (-1 : -1 : 1) sage: C.defining_polynomial()(list(p)) # optional - magma 0 sage: len(str(p)) / len(str(q)) > 2 # optional - magma True
sage: D.rational_point(algorithm = 'magma', read_cache=False) # random, optional - magma (1 : 2*i : 1)
sage: E.rational_point(algorithm='magma', read_cache=False) # random, optional - magma (-s : 1 : 1)
sage: F = Conic([L.gen(), 30, -20]) sage: q = F.rational_point(algorithm='magma') # optional - magma sage: q # output is random, optional - magma (-10/7*s + 40/7 : 5/7*s - 6/7 : 1) sage: p = F.rational_point(read_cache=False) sage: p # output is random (788210*s - 1114700 : -171135*s + 242022 : 1) sage: len(str(p)) > len(str(q)) # optional - magma True
sage: Conic([L.gen(), 30, -21]).has_rational_point(algorithm='magma') # optional - magma False
Examples over finite fields ::
sage: F.<a> = FiniteField(7^20) sage: C = Conic([1, a, -5]); C Projective Conic Curve over Finite Field in a of size 7^20 defined by x^2 + (a)*y^2 + 2*z^2 sage: C.rational_point() # output is random (4*a^19 + 5*a^18 + 4*a^17 + a^16 + 6*a^15 + 3*a^13 + 6*a^11 + a^9 + 3*a^8 + 2*a^7 + 4*a^6 + 3*a^5 + 3*a^4 + a^3 + a + 6 : 5*a^18 + a^17 + a^16 + 6*a^15 + 4*a^14 + a^13 + 5*a^12 + 5*a^10 + 2*a^9 + 6*a^8 + 6*a^7 + 6*a^6 + 2*a^4 + 3 : 1)
Examples over `\RR` and `\CC` ::
sage: Conic(CC, [1, 2, 3]).rational_point() (0 : 1.22474487139159*I : 1)
sage: Conic(RR, [1, 1, 1]).rational_point() Traceback (most recent call last): ... ValueError: Conic Projective Conic Curve over Real Field with 53 bits of precision defined by x^2 + y^2 + z^2 has no rational points over Real Field with 53 bits of precision! """ read_cache = read_cache) (self, self.ambient_space().base_ring()))
def singular_point(self): r""" Returns a singular rational point of ``self``
EXAMPLES:
::
sage: Conic(GF(2), [1,1,1,1,1,1]).singular_point() (1 : 1 : 1)
``ValueError`` is raised if the conic has no rational singular point
::
sage: Conic(QQ, [1,1,1,1,1,1]).singular_point() Traceback (most recent call last): ... ValueError: The conic self (= Projective Conic Curve over Rational Field defined by x^2 + x*y + y^2 + x*z + y*z + z^2) has no rational singular point """ "singular point" % self)
def symmetric_matrix(self): r""" The symmetric matrix `M` such that `(x y z) M (x y z)^t` is the defining equation of ``self``.
EXAMPLES ::
sage: R.<x, y, z> = QQ[] sage: C = Conic(x^2 + x*y/2 + y^2 + z^2) sage: C.symmetric_matrix() [ 1 1/4 0] [1/4 1 0] [ 0 0 1]
sage: C = Conic(x^2 + 2*x*y + y^2 + 3*x*z + z^2) sage: v = vector([x, y, z]) sage: v * C.symmetric_matrix() * v x^2 + 2*x*y + y^2 + 3*x*z + z^2 """ return matrix([[a,0,0],[0,d,0],[0,0,f]]) "because the base field has characteristic 2" % \ self) [ b/2, d , e/2 ], [ c/2, e/2, f ]])
def upper_triangular_matrix(self): r""" The upper-triangular matrix `M` such that `(x y z) M (x y z)^t` is the defining equation of ``self``.
EXAMPLES::
sage: R.<x, y, z> = QQ[] sage: C = Conic(x^2 + x*y + y^2 + z^2) sage: C.upper_triangular_matrix() [1 1 0] [0 1 0] [0 0 1]
sage: C = Conic(x^2 + 2*x*y + y^2 + 3*x*z + z^2) sage: v = vector([x, y, z]) sage: v * C.upper_triangular_matrix() * v x^2 + 2*x*y + y^2 + 3*x*z + z^2 """ [ 0, d, e ], [ 0, 0, f ]])
def variable_names(self): r""" Returns the variable names of the defining polynomial of ``self``.
EXAMPLES:
::
sage: c=Conic([1,1,0,1,0,1], 'x,y,z') sage: c.variable_names() ('x', 'y', 'z') sage: c.variable_name() 'x'
The function ``variable_names()`` is required for the following construction:
::
sage: C.<p,q,r> = Conic(QQ, [1, 1, 1]) sage: C Projective Conic Curve over Rational Field defined by p^2 + q^2 + r^2
"""
|