Path: blob/master/sage/schemes/plane_conics/con_field.py
4097 views
r"""1Projective plane conics over a field23AUTHORS:45- Marco Streng (2010-07-20)67- Nick Alexander (2008-01-08)89"""10#*****************************************************************************11# Copyright (C) 2008 Nick Alexander <[email protected]>12# Copyright (C) 2009/2010 Marco Streng <[email protected]>13#14# Distributed under the terms of the GNU General Public License (GPL)15#16# This code is distributed in the hope that it will be useful,17# but WITHOUT ANY WARRANTY; without even the implied warranty of18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU19# General Public License for more details.20#21# The full text of the GPL is available at:22#23# http://www.gnu.org/licenses/24#*****************************************************************************2526from sage.rings.all import (PolynomialRing,27is_ComplexField, is_RealField,28is_Field)29from sage.modules.free_module_element import vector30from sage.structure.sequence import Sequence31from sage.structure.element import is_Vector32from sage.schemes.generic.projective_space import ProjectiveSpace33from sage.matrix.constructor import Matrix34from sage.matrix.matrix import is_Matrix3536from sage.schemes.plane_curves.projective_curve import ProjectiveCurve_generic3738class ProjectiveConic_field(ProjectiveCurve_generic):39r"""40Create a projective plane conic curve over a field.41See ``Conic`` for full documentation.4243EXAMPLES::4445sage: K = FractionField(PolynomialRing(QQ, 't'))46sage: P.<X, Y, Z> = K[]47sage: Conic(X^2 + Y^2 - Z^2)48Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Rational Field defined by X^2 + Y^2 - Z^24950TESTS::5152sage: K = FractionField(PolynomialRing(QQ, 't'))53sage: Conic([K(1), 1, -1])._test_pickling()54"""55def __init__(self, A, f):56r"""57See ``Conic`` for full documentation.5859EXAMPLES:6061::6263sage: c = Conic([1, 1, 1]); c64Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^265"""66ProjectiveCurve_generic.__init__(self, A, f)67self._coefficients = [f[(2,0,0)], f[(1,1,0)], f[(1,0,1)],68f[(0,2,0)], f[(0,1,1)], f[(0,0,2)]]69self._parametrization = None70self._diagonal_matrix = None7172self._rational_point = None7374757677def _repr_type(self):78r"""79Returns ``'Projective Conic'``, which is the first part of the80plain text representation of this object as output by81the function ``_repr_`` of the class ``Curve_generic``.8283EXAMPLES::8485sage: c = Conic([1, 1, 1]); c86Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^287sage: c._repr_()88'Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^2'89sage: c._repr_type()90'Projective Conic'91"""92return "Projective Conic"9394def base_extend(self, S):95r"""96Returns the conic over ``S`` given by the same equation as ``self``.9798EXAMPLES::99100sage: c = Conic([1, 1, 1]); c101Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^2102sage: c.has_rational_point()103False104sage: d = c.base_extend(QuadraticField(-1, 'i')); d105Projective Conic Curve over Number Field in i with defining polynomial x^2 + 1 defined by x^2 + y^2 + z^2106sage: d.rational_point(algorithm = 'rnfisnorm')107(i : 1 : 0)108"""109if is_Field(S):110B = self.base_ring()111if B == S:112return self113if not S.has_coerce_map_from(B):114raise ValueError, "No natural map from the base ring of self " \115"(= %s) to S (= %s)" % (self, S)116from constructor import Conic117con = Conic([S(c) for c in self.coefficients()], \118self.variable_names())119if self._rational_point != None:120pt = [S(c) for c in Sequence(self._rational_point)]121if not pt == [0,0,0]:122# The following line stores the point in the cache123# if (and only if) there is no point in the cache.124pt = con.point(pt)125return con126return ProjectiveCurve_generic.base_extend(self, S)127128def cache_point(self, p):129r"""130Replace the point in the cache of ``self`` by ``p`` for use131by ``self.rational_point()`` and ``self.parametrization()``.132133EXAMPLES::134135sage: c = Conic([1, -1, 1])136sage: c.point([15, 17, 8])137(15/8 : 17/8 : 1)138sage: c.rational_point()139(15/8 : 17/8 : 1)140sage: c.cache_point(c.rational_point(read_cache = False))141sage: c.rational_point()142(1 : 1 : 0)143"""144if isinstance(p, (tuple, list)):145p = self.point(p)146self._rational_point = p147148def coefficients(self):149r"""150Gives a the `6` coefficients of the conic ``self``151in lexicographic order.152153EXAMPLES::154155sage: Conic(QQ, [1,2,3,4,5,6]).coefficients()156[1, 2, 3, 4, 5, 6]157158sage: P.<x,y,z> = GF(13)[]159sage: a = Conic(x^2+5*x*y+y^2+z^2).coefficients(); a160[1, 5, 0, 1, 0, 1]161sage: Conic(a)162Projective Conic Curve over Finite Field of size 13 defined by x^2 + 5*x*y + y^2 + z^2163"""164return self._coefficients165166167def derivative_matrix(self):168r"""169Gives the derivative of the defining polynomial of170the conic ``self``, which is a linear map,171as a `3 \times 3` matrix.172173EXAMPLES:174175In characteristic different from `2`, the176derivative matrix is twice the symmetric matrix:177178::179180sage: c = Conic(QQ, [1,1,1,1,1,0])181sage: c.symmetric_matrix()182[ 1 1/2 1/2]183[1/2 1 1/2]184[1/2 1/2 0]185sage: c.derivative_matrix()186[2 1 1]187[1 2 1]188[1 1 0]189190An example in characteristic `2`:191192::193194sage: P.<t> = GF(2)[]195sage: c = Conic([t, 1, t^2, 1, 1, 0]); c196Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL) defined by t*x^2 + x*y + y^2 + t^2*x*z + y*z197sage: c.is_smooth()198True199sage: c.derivative_matrix()200[ 0 1 t^2]201[ 1 0 1]202[t^2 1 0]203"""204from sage.matrix.constructor import matrix205[a,b,c,d,e,f] = self.coefficients()206return matrix([[ 2*a , b , c ],207[ b , 2*d , e ],208[ c , e , 2*f ]])209210def determinant(self):211r"""212Returns the determinant of the symmetric matrix that defines213the conic ``self``.214215This is defined only if the base field has characteristic216different from `2`.217218EXAMPLES:219220::221222sage: C = Conic([1,2,3,4,5,6])223sage: C.determinant()22441/4225sage: C.symmetric_matrix().determinant()22641/4227228Determinants are only defined in characteristic different from `2`::229230sage: C = Conic(GF(2), [1, 1, 1, 1, 1, 0])231sage: C.is_smooth()232True233sage: C.determinant()234Traceback (most recent call last):235...236ValueError: 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 2237"""238return self.symmetric_matrix().determinant()239240def diagonal_matrix(self):241r"""242Returns a diagonal matrix `D` and a matrix `T` such that `T^t A T = D`243holds, where `(x, y, z) A (x, y, z)^t` is the defining polynomial244of the conic ``self``.245246EXAMPLES:247248::249250sage: c = Conic(QQ, [1,2,3,4,5,6])251sage: d, t = c.diagonal_matrix(); d, t252(253[ 1 0 0] [ 1 -1 -7/6]254[ 0 3 0] [ 0 1 -1/3]255[ 0 0 41/12], [ 0 0 1]256)257sage: t.transpose()*c.symmetric_matrix()*t258[ 1 0 0]259[ 0 3 0]260[ 0 0 41/12]261262Diagonal matrices are only defined in characteristic different263from `2`:264265::266267sage: c = Conic(GF(4, 'a'), [0, 1, 1, 1, 1, 1])268sage: c.is_smooth()269True270sage: c.diagonal_matrix()271Traceback (most recent call last):272...273ValueError: 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 2274"""275A = self.symmetric_matrix()276B = self.base_ring()277basis = [vector(B,{2:0,i:1}) for i in range(3)]278for i in range(3):279zerovalue = (basis[i]*A*basis[i].column()== 0)280if zerovalue:281for j in range(i+1,3):282if basis[j]*A*basis[j].column() != 0:283b = basis[i]284basis[i] = basis[j]285basis[j] = b286zerovalue = False287if zerovalue:288for j in range(i+1,3):289if basis[i]*A*basis[j].column() != 0:290basis[i] = basis[i]+basis[j]291zerovalue = False292if not zerovalue:293l = (basis[i]*A*basis[i].column())294for j in range(i+1,3):295basis[j] = basis[j] - \296(basis[i]*A*basis[j].column())/l * basis[i]297T = Matrix(basis).transpose()298return T.transpose()*A*T, T299300def diagonalization(self,names = None):301r"""302Returns a diagonal conic `C`, an isomorphism of schemes `M: C` -> ``self``303and the inverse `N` of `M`.304305EXAMPLES::306307sage: Conic(GF(5), [1,0,1,1,0,1]).diagonalization()308(Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2,309Scheme morphism:310From: Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2311To: Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + x*z + z^2312Defn: Defined on coordinates by sending (x : y : z) to313(x + 2*z : y : z),314Scheme morphism:315From: Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + x*z + z^2316To: Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2317Defn: Defined on coordinates by sending (x : y : z) to318(x - 2*z : y : z))319320The diagonalization is only defined in characteristic different321from 2:322323::324325sage: Conic(GF(2), [1,1,1,1,1,0]).diagonalization()326Traceback (most recent call last):327...328ValueError: 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 2329"""330if names == None:331names = self.defining_polynomial().parent().variable_names()332from constructor import Conic333D, T = self.diagonal_matrix()334con = Conic(D, names = names)335return con, con.hom(T, self), self.hom(T.inverse(), con)336337def gens(self):338r"""339Returns the generators of the coordinate ring of ``self``.340341EXAMPLES:342343::344345sage: P.<x,y,z> = QQ[]346sage: c = Conic(x^2+y^2+z^2)347sage: c.gens()348(xbar, ybar, zbar)349sage: c.defining_polynomial()(c.gens())3500351352The function ``gens()`` is required for the following construction:353354::355356sage: C.<a,b,c> = Conic(GF(3), [1, 1, 1])357sage: C358Projective Conic Curve over Finite Field of size 3 defined by a^2 + b^2 + c^2359360"""361return self.coordinate_ring().gens()362363def has_rational_point(self, point = False,364algorithm = 'default', read_cache = True):365r"""366Returns True if and only if the conic ``self``367has a point over its base field `B`.368369If ``point`` is True, then returns a second output, which is370a rational point if one exists.371372Points are cached whenever they are found. Cached information373is used if and only if ``read_cache`` is True.374375EXAMPLES:376377sage: Conic(RR, [1, 1, 1]).has_rational_point()378False379sage: Conic(CC, [1, 1, 1]).has_rational_point()380True381382sage: Conic(RR, [1, 2, -3]).has_rational_point(point = True)383(True, (1.73205080756888 : 0.000000000000000 : 1.00000000000000))384"""385if read_cache:386if self._rational_point is not None:387if point:388return True, self._rational_point389else:390return True391B = self.base_ring()392if is_ComplexField(B):393if point:394[_,_,_,d,e,f] = self._coefficients395if d == 0:396return True, self.point([0,1,0])397return True, self.point([0, ((e**2-4*d*f).sqrt()-e)/(2*d), 1],398check = False)399return True400if is_RealField(B):401D, T = self.diagonal_matrix()402[a, b, c] = [D[0,0], D[1,1], D[2,2]]403if a == 0:404ret = True, self.point(T*vector([1,0,0]), check = False)405elif a*c <= 0:406ret = True, self.point(T*vector([(-c/a).sqrt(),0,1]),407check = False)408elif b == 0:409ret = True, self.point(T*vector([0,1,0]), check = False)410elif b*c <= 0:411ret = True, self.point(T*vector([0,(-c/b).sqrt(),0,1]),412check = False)413else:414ret = False, None415if point:416return ret417return ret[0]418raise NotImplementedError, "has_rational_point not implemented for " \419"conics over base field %s" % B420421def has_singular_point(self, point = False):422r"""423Return True if and only if the conic ``self`` has a rational424singular point.425426If ``point`` is True, then also return a rational singular427point (or ``None`` if no such point exists).428429EXAMPLES:430431::432433sage: c = Conic(QQ, [1,0,1]); c434Projective Conic Curve over Rational Field defined by x^2 + z^2435sage: c.has_singular_point(point = True)436(True, (0 : 1 : 0))437438sage: P.<x,y,z> = GF(7)[]439sage: e = Conic((x+y+z)*(x-y+2*z)); e440Projective Conic Curve over Finite Field of size 7 defined by x^2 - y^2 + 3*x*z + y*z + 2*z^2441sage: e.has_singular_point(point = True)442(True, (2 : 4 : 1))443444sage: Conic([1, 1, -1]).has_singular_point()445False446sage: Conic([1, 1, -1]).has_singular_point(point = True)447(False, None)448449``has_singular_point`` is not implemented over all fields450of characteristic `2`. It is implemented over finite fields.451452::453454sage: F.<a> = FiniteField(8)455sage: Conic([a, a+1, 1]).has_singular_point(point = True)456(True, (a + 1 : 0 : 1))457458sage: P.<t> = GF(2)[]459sage: C = Conic(P, [t,t,1]); C460Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL) defined by t*x^2 + t*y^2 + z^2461sage: C.has_singular_point(point = False)462Traceback (most recent call last):463...464NotImplementedError: Sorry, find singular point on conics not implemented over all fields of characteristic 2.465"""466if not point:467ret = self.has_singular_point(point = True)468return ret[0]469B = self.base_ring()470if B.characteristic() == 2:471[a,b,c,d,e,f] = self.coefficients()472if b == 0 and c == 0 and e == 0:473for i in range(3):474if [a, d, f][i] == 0:475return True, self.point(vector(B, {2:0, i:1}))476if hasattr(a/f, 'is_square') and hasattr(a/f, 'sqrt'):477if (a/f).is_square():478return True, self.point([1,0,(a/f).sqrt()])479if (d/f).is_square():480return True, self.point([0,1,(d/f).sqrt()])481raise NotImplementedError, "Sorry, find singular point on conics not implemented over all fields of characteristic 2."482pt = [e, c, b]483if self.defining_polynomial()(pt) == 0:484return True, self.point(pt)485return False, None486D = self.symmetric_matrix()487if D.determinant() == 0:488return True, self.point(Sequence(D.right_kernel().gen()))489return False, None490491def hom(self, x, Y=None):492r"""493Return the scheme morphism from ``self`` to ``Y`` defined by ``x``.494Here ``x`` can be a matrix or a sequence of polynomials.495If ``Y`` is omitted, then a natural image is found if possible.496497EXAMPLES:498499Here are a few Morphisms given by matrices. In the first500example, ``Y`` is omitted, in the second example, ``Y`` is specified.501502::503504sage: c = Conic([-1, 1, 1])505sage: h = c.hom(Matrix([[1,1,0],[0,1,0],[0,0,1]])); h506Scheme morphism:507From: Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2508To: Projective Conic Curve over Rational Field defined by -x^2 + 2*x*y + z^2509Defn: Defined on coordinates by sending (x : y : z) to510(x + y : y : z)511sage: h([-1, 1, 0])512(0 : 1 : 0)513514sage: c = Conic([-1, 1, 1])515sage: d = Conic([4, 1, -1])516sage: c.hom(Matrix([[0, 0, 1/2], [0, 1, 0], [1, 0, 0]]), d)517Scheme morphism:518From: Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2519To: Projective Conic Curve over Rational Field defined by 4*x^2 + y^2 - z^2520Defn: Defined on coordinates by sending (x : y : z) to521(1/2*z : y : x)522523``ValueError`` is raised if the wrong codomain ``Y`` is specified:524525::526527sage: c = Conic([-1, 1, 1])528sage: c.hom(Matrix([[0, 0, 1/2], [0, 1, 0], [1, 0, 0]]), c)529Traceback (most recent call last):530...531ValueError: The matrix x (= [ 0 0 1/2]532[ 0 1 0]533[ 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)534"""535if is_Matrix(x):536from constructor import Conic537y = x.inverse()538A = y.transpose()*self.matrix()*y539im = Conic(A)540if Y == None:541Y = im542else:543q = Y.defining_polynomial()/im.defining_polynomial()544if not (q.numerator().is_constant()545and q.denominator().is_constant()):546raise ValueError, "The matrix x (= %s) does not define a " \547"map from self (= %s) to Y (= %s)" % \548(x, self, Y)549x = Sequence(x*vector(self.ambient_space().gens()))550return self.Hom(Y)(x, check = False)551return ProjectiveCurve_generic.hom(self, x, Y)552553554def is_diagonal(self):555r"""556Return True if and only if the conic has the form557`a*x^2 + b*y^2 + c*z^2`.558559EXAMPLES:560561::562563sage: c=Conic([1,1,0,1,0,1]); c564Projective Conic Curve over Rational Field defined by x^2 + x*y + y^2 + z^2565sage: d,t = c.diagonal_matrix()566sage: c.is_diagonal()567False568sage: c.diagonalization()[0].is_diagonal()569True570"""571return all([self.coefficients()[i] == 0 for i in [1,2,4]])572573574def is_smooth(self):575r"""576Returns True if and only if ``self`` is smooth.577578EXAMPLES:579580::581582sage: Conic([1,-1,0]).is_smooth()583False584sage: Conic(GF(2),[1,1,1,1,1,0]).is_smooth()585True586"""587if self.base_ring().characteristic() == 2:588[a,b,c,d,e,f] = self.coefficients()589if b == 0 and c == 0 and e == 0:590return False591return self.defining_polynomial()([e, c, b]) != 0592return self.determinant() != 0593594595def _magma_init_(self, magma):596"""597Internal function. Returns a string to initialize this598conic in the Magma subsystem.599600EXAMPLES::601602sage: C = Conic(QQ, [1,2,3])603sage: C._magma_init_(magma) # optional - magma604'Conic([_sage_ref1|1/1,2/1,3/1,0/1,0/1,0/1])'605sage: C = Conic(GF(41), [-1,2,5]) # optional - magma606sage: C._magma_init_(magma) # optional - magma607'Conic([_sage_ref2|GF(41)!40,GF(41)!2,GF(41)!5,GF(41)!0,GF(41)!0,GF(41)!0])'608sage: F.<a> = GF(25)609sage: C = Conic([3,0,1,4,a,2])610sage: C611Projective 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^2612sage: magma(C) # optional - magma613Conic over GF(5^2) defined by6143*X^2 + 4*Y^2 + X*Z + a*Y*Z + 2*Z^2615sage: magma(Conic([1/2,2/3,-4/5,6/7,8/9,-10/11])) # optional - magma616Conic over Rational Field defined by6171/2*X^2 + 2/3*X*Y + 6/7*Y^2 - 4/5*X*Z + 8/9*Y*Z - 10/11*Z^2618sage: R.<x> = Frac(QQ['x'])619sage: magma(Conic([x,1+x,1-x])) # optional - magma620Conic over Univariate rational function field over Rational Field defined by621x*X^2 + (x + 1)*Y^2 + (-x + 1)*Z^2622sage: P.<x> = QQ[]623sage: K.<b> = NumberField(x^3+x+1)624sage: magma(Conic([b,1,2])) # optional - magma625Conic over Number Field with defining polynomial x^3 + x + 1 over the Rational Field defined by626b*X^2 + Y^2 + 2*Z^2627"""628kmn = magma(self.base_ring())._ref()629coeffs = self.coefficients()630magma_coeffs = [coeffs[i]._magma_init_(magma) for i in [0, 3, 5, 1, 4, 2]]631return 'Conic([%s|%s])' % (kmn,','.join(magma_coeffs))632633634def matrix(self):635r"""636Returns a matrix `M` such that `(x, y, z) M (x, y, z)^t`637is the defining equation of ``self``.638639The matrix `M` is upper triangular if the base field has640characteristic `2` and symmetric otherwise.641642EXAMPLES::643644sage: R.<x, y, z> = QQ[]645sage: C = Conic(x^2 + x*y + y^2 + z^2)646sage: C.matrix()647[ 1 1/2 0]648[1/2 1 0]649[ 0 0 1]650651sage: R.<x, y, z> = GF(2)[]652sage: C = Conic(x^2 + x*y + y^2 + x*z + z^2)653sage: C.matrix()654[1 1 1]655[0 1 0]656[0 0 1]657"""658if self.base_ring().characteristic() == 2:659return self.upper_triangular_matrix()660return self.symmetric_matrix()661662_matrix_ = matrix663664def parametrization(self, point=None, morphism=True):665r"""666Return a parametrization `f` of ``self`` together with the667inverse of `f`.668669If ``point`` is specified, then that point is used670for the parametrization. Otherwise, use ``self.rational_point()``671to find a point.672673If ``morphism`` is True, then `f` is returned in the form674of a Scheme morphism. Otherwise, it is a tuple of polynomials675that gives the parametrization.676677EXAMPLES:678679An example over a finite field ::680681sage: c = Conic(GF(2), [1,1,1,1,1,0])682sage: c.parametrization()683(Scheme morphism:684From: Projective Space of dimension 1 over Finite Field of size 2685To: Projective Conic Curve over Finite Field of size 2 defined by x^2 + x*y686+ y^2 + x*z + y*z687Defn: Defined on coordinates by sending (x : y) to688(x*y + y^2 : x^2 + x*y : x^2 + x*y + y^2),689Scheme morphism:690From: Projective Conic Curve over Finite Field of size 2 defined by x^2 + x*y691+ y^2 + x*z + y*z692To: Projective Space of dimension 1 over Finite Field of size 2693Defn: Defined on coordinates by sending (x : y : z) to694(y : x))695696An example with ``morphism = False`` ::697698sage: R.<x,y,z> = QQ[]699sage: C = Curve(7*x^2 + 2*y*z + z^2)700sage: (p, i) = C.parametrization(morphism = False); (p, i)701([-2*x*y, 7*x^2 + y^2, -2*y^2], [-1/2*x, -1/2*z])702sage: C.defining_polynomial()(p)7030704sage: i[0](p) / i[1](p)705x/y706707A ``ValueError`` is raised if ``self`` has no rational point ::708709sage: C = Conic(x^2 + y^2 + 7*z^2)710sage: C.parametrization()711Traceback (most recent call last):712...713ValueError: Conic Projective Conic Curve over Rational Field defined by x^2 + y^2 + 7*z^2 has no rational points over Rational Field!714715A ``ValueError`` is raised if ``self`` is not smooth ::716717sage: C = Conic(x^2 + y^2)718sage: C.parametrization()719Traceback (most recent call last):720...721ValueError: The conic self (=Projective Conic Curve over Rational Field defined by x^2 + y^2) is not smooth, hence does not have a parametrization.722"""723if (not self._parametrization is None) and not point:724par = self._parametrization725else:726if not self.is_smooth():727raise ValueError, "The conic self (=%s) is not smooth, hence does not have a parametrization." % self728if point == None:729point = self.rational_point()730point = Sequence(point)731B = self.base_ring()732Q = PolynomialRing(B, 'x,y')733[x, y] = Q.gens()734gens = self.ambient_space().gens()735P = PolynomialRing(B, 4, ['X', 'Y', 'T0', 'T1'])736[X, Y, T0, T1] = P.gens()737c3 = [j for j in range(2,-1,-1) if point[j] != 0][0]738c1 = [j for j in range(3) if j != c3][0]739c2 = [j for j in range(3) if j != c3 and j != c1][0]740L = [0,0,0]741L[c1] = Y*T1*point[c1] + Y*T0742L[c2] = Y*T1*point[c2] + X*T0743L[c3] = Y*T1*point[c3]744bezout = P(self.defining_polynomial()(L) / T0)745t = [bezout([x,y,0,-1]),bezout([x,y,1,0])]746par = (tuple([Q(p([x,y,t[0],t[1]])/y) for p in L]),747tuple([gens[m]*point[c3]-gens[c3]*point[m]748for m in [c2,c1]]))749if self._parametrization is None:750self._parametrization = par751if not morphism:752return par753P1 = ProjectiveSpace(self.base_ring(), 1, 'x,y')754return P1.hom(par[0],self), self.Hom(P1)(par[1], check = False)755756def point(self, v, check=True):757r"""758Constructs a point on ``self`` corresponding to the input ``v``.759760If ``check`` is True, then checks if ``v`` defines a valid761point on ``self``.762763If no rational point on ``self`` is known yet, then also caches the point764for use by ``self.rational_point()`` and ``self.parametrization()``.765766EXAMPLES ::767768sage: c = Conic([1, -1, 1])769sage: c.point([15, 17, 8])770(15/8 : 17/8 : 1)771sage: c.rational_point()772(15/8 : 17/8 : 1)773sage: d = Conic([1, -1, 1])774sage: d.rational_point()775(1 : 1 : 0)776"""777if is_Vector(v):778v = Sequence(v)779p = ProjectiveCurve_generic.point(self, v, check=check)780if self._rational_point is None:781self._rational_point = p782return p783784785def random_rational_point(self, *args1, **args2):786r"""787Return a random rational point of the conic ``self``.788789ALGORITHM:7907911. Compute a parametrization `f` of ``self`` using792``self.parametrization()``.7932. Computes a random point `(x:y)` on the projective794line.7953. Output `f(x:y)`.796797The coordinates x and y are computed using798``B.random_element``, where ``B`` is the base field of799``self`` and additional arguments to ``random_rational_point``800are passed to ``random_element``.801802If the base field is a finite field, then the803output is uniformly distributed over the points of self.804805EXAMPLES ::806807sage: c = Conic(GF(2), [1,1,1,1,1,0])808sage: [c.random_rational_point() for i in range(10)] # output is random809[(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)]810811sage: d = Conic(QQ, [1, 1, -1])812sage: d.random_rational_point(den_bound = 1, num_bound = 5) # output is random813(-24/25 : 7/25 : 1)814815sage: Conic(QQ, [1, 1, 1]).random_rational_point()816Traceback (most recent call last):817...818ValueError: Conic Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^2 has no rational points over Rational Field!819820"""821if not self.is_smooth():822raise NotImplementedError, "Sorry, random points not implemented " \823"for non-smooth conics"824par = self.parametrization()825x = 0826y = 0827B = self.base_ring()828while x == 0 and y == 0:829x = B.random_element(*args1, **args2)830y = B.random_element(*args1, **args2)831return par[0]([x,y])832833834def rational_point(self, algorithm = 'default', read_cache = True):835r"""836Return a point on ``self`` defined over the base field.837838Raises ``ValueError`` if no rational point exists.839840See ``self.has_rational_point`` for the algorithm used841and for the use of the parameters ``algorithm`` and ``read_cache``.842843EXAMPLES:844845Examples over `\QQ` ::846847sage: R.<x,y,z> = QQ[]848sage: C = Conic(7*x^2 + 2*y*z + z^2)849sage: C.rational_point()850(0 : 1 : 0)851852sage: C = Conic(x^2 + 2*y^2 + z^2)853sage: C.rational_point()854Traceback (most recent call last):855...856ValueError: Conic Projective Conic Curve over Rational Field defined by x^2 + 2*y^2 + z^2 has no rational points over Rational Field!857858sage: C = Conic(x^2 + y^2 + 7*z^2)859sage: C.rational_point(algorithm = 'rnfisnorm')860Traceback (most recent call last):861...862ValueError: Conic Projective Conic Curve over Rational Field defined by x^2 + y^2 + 7*z^2 has no rational points over Rational Field!863864Examples over number fields ::865866sage: P.<x> = QQ[]867sage: L.<b> = NumberField(x^3-5)868sage: C = Conic(L, [3, 2, -5])869sage: C.rational_point(algorithm = 'rnfisnorm') # long time (1/2 second), output is random870(37632*b^2 + 88168*b - 260801 : -99528*b^2 + 153348*b + 28799 : 1)871872Examples over finite fields ::873874sage: F.<a> = FiniteField(7^20)875sage: C = Conic([1, a, -5]); C876Projective Conic Curve over Finite Field in a of size 7^20 defined by x^2 + (a)*y^2 + 2*z^2877sage: C.rational_point() # output is random878(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)879880Examples over `\RR` and `\CC` ::881882sage: Conic(CC, [1, 2, 3]).rational_point()883(0 : 1.22474487139159*I : 1)884885sage: Conic(RR, [1, 1, 1]).rational_point()886Traceback (most recent call last):887...888ValueError: 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!889"""890bl,pt = self.has_rational_point(point = True, algorithm = algorithm,891read_cache = read_cache)892if bl:893return pt894raise ValueError, "Conic %s has no rational points over %s!" % \895(self, self.ambient_space().base_ring())896897898def singular_point(self):899r"""900Returns a singular rational point of ``self``901902EXAMPLES:903904::905906sage: Conic(GF(2), [1,1,1,1,1,1]).singular_point()907(1 : 1 : 1)908909``ValueError`` is raised if the conic has no rational singular point910911::912913sage: Conic(QQ, [1,1,1,1,1,1]).singular_point()914Traceback (most recent call last):915...916ValueError: 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 point917"""918b = self.has_singular_point(point = True)919if not b[0]:920raise ValueError, "The conic self (= %s) has no rational " \921"singular point" % self922return b[1]923924def symmetric_matrix(self):925r"""926The symmetric matrix `M` such that `(x y z) M (x y z)^t`927is the defining equation of ``self``.928929EXAMPLES ::930931sage: R.<x, y, z> = QQ[]932sage: C = Conic(x^2 + x*y/2 + y^2 + z^2)933sage: C.symmetric_matrix()934[ 1 1/4 0]935[1/4 1 0]936[ 0 0 1]937938sage: C = Conic(x^2 + 2*x*y + y^2 + 3*x*z + z^2)939sage: v = vector([x, y, z])940sage: v * C.symmetric_matrix() * v941x^2 + 2*x*y + y^2 + 3*x*z + z^2942"""943[a,b,c,d,e,f] = self.coefficients()944if self.base_ring().characteristic() == 2:945if b == 0 and c == 0 and e == 0:946return matrix([[a,0,0],[0,d,0],[0,0,f]])947raise ValueError, "The conic self (= %s) has no symmetric matrix " \948"because the base field has characteristic 2" % \949self950from sage.matrix.constructor import matrix951return matrix([[ a , b/2, c/2 ],952[ b/2, d , e/2 ],953[ c/2, e/2, f ]])954955956def upper_triangular_matrix(self):957r"""958The upper-triangular matrix `M` such that `(x y z) M (x y z)^t`959is the defining equation of ``self``.960961EXAMPLES::962963sage: R.<x, y, z> = QQ[]964sage: C = Conic(x^2 + x*y + y^2 + z^2)965sage: C.upper_triangular_matrix()966[1 1 0]967[0 1 0]968[0 0 1]969970sage: C = Conic(x^2 + 2*x*y + y^2 + 3*x*z + z^2)971sage: v = vector([x, y, z])972sage: v * C.upper_triangular_matrix() * v973x^2 + 2*x*y + y^2 + 3*x*z + z^2974"""975from sage.matrix.constructor import matrix976[a,b,c,d,e,f] = self.coefficients()977return matrix([[ a, b, c ],978[ 0, d, e ],979[ 0, 0, f ]])980981def variable_names(self):982r"""983Returns the variable names of the defining polynomial984of ``self``.985986EXAMPLES:987988::989990sage: c=Conic([1,1,0,1,0,1], 'x,y,z')991sage: c.variable_names()992('x', 'y', 'z')993sage: c.variable_name()994'x'995996The function ``variable_names()`` is required997for the following construction:998999::10001001sage: C.<p,q,r> = Conic(QQ, [1, 1, 1])1002sage: C1003Projective Conic Curve over Rational Field defined by p^2 + q^2 + r^210041005"""1006return self.defining_polynomial().parent().variable_names()10071008100910101011