Ticket #727: trac_727_more_conic_files4.patch

File trac_727_more_conic_files4.patch, 137.4 KB (added by Marco Streng, 12 years ago)

apply after trac_727_more_conic_files1,2,3; requires trac_9334-hilbert.patch to work

  • new file sage/schemes/plane_conics/con_field.py

    # HG changeset patch
    # User Marco Streng <marco.streng@gmail.com>
    # Date 1278937664 -7200
    # Node ID dd59f5b6d61d4ac60bc704125145ee772476c5a2
    # Parent  510cd246e899886d8808693f7c8f257c71e13451
    Trac 727: split conic class into many classes
    
    diff -r 510cd246e899 -r dd59f5b6d61d sage/schemes/plane_conics/con_field.py
    - +  
     1r"""
     2Projective plane conics over a field.
     3
     4AUTHORS:
     5
     6- Marco Streng (2010-08-07)
     7
     8- Nick Alexander (2008-01-08)
     9
     10"""
     11#*****************************************************************************
     12#       Copyright (C) 2008 Nick Alexander <ncalexander@gmail.com>
     13#       Copyright (C) 2009/2010 Marco Streng <marco.streng@gmail.com>
     14#
     15#  Distributed under the terms of the GNU General Public License (GPL)
     16#
     17#    This code is distributed in the hope that it will be useful,
     18#    but WITHOUT ANY WARRANTY; without even the implied warranty of
     19#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     20#    General Public License for more details.
     21#
     22#  The full text of the GPL is available at:
     23#
     24#                  http://www.gnu.org/licenses/
     25#*****************************************************************************
     26
     27from sage.libs.pari.gen import pari
     28from sage.misc.all import add, sage_eval
     29from sage.rings.all import (PolynomialRing, ZZ, QQ, MPolynomialRing,
     30                            degree_lowest_rational_function,
     31                            is_PrimeField, is_FiniteField,
     32                            is_ComplexField, is_RealField,
     33                            is_pAdicField, is_Field,
     34                            is_RationalField)
     35from sage.modules.free_module_element import vector
     36from sage.structure.sequence import Sequence
     37from sage.structure.element import is_Vector
     38from sage.schemes.generic.projective_space import (ProjectiveSpace,
     39                                                   is_ProjectiveSpace)
     40from sage.matrix.constructor import Matrix
     41from sage.matrix.matrix import is_Matrix
     42
     43from sage.schemes.plane_curves.curve import Curve_generic_projective
     44from sage.schemes.plane_curves.projective_curve import ProjectiveCurve_generic
     45from sage.quadratic_forms.qfsolve import Qfsolve, Qfparam
     46
     47from sage.rings.number_field.number_field import is_NumberField                           
     48
     49from sage.rings.all import RR
     50
     51class ProjectiveConic_field(ProjectiveCurve_generic):
     52    def __init__(self, A, f):
     53        ProjectiveCurve_generic.__init__(self, A, f)
     54        self._coefficients = [f[(2,0,0)], f[(1,1,0)], f[(1,0,1)],
     55                                f[(0,2,0)], f[(0,1,1)], f[(0,0,2)]]
     56        self._parametrization = None
     57        self._diagonal_matrix = None
     58       
     59        self._rational_point = None
     60
     61
     62
     63
     64    def _repr_type(self):
     65        return "Projective Conic"
     66
     67    def base_extend(self, S):
     68        r"""
     69        Returns the conic over `S`, given by the same equation as self.
     70
     71        EXAMPLES:
     72
     73        ::
     74
     75            sage: c = Conic([1, 1, 1]); c
     76            Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^2
     77            sage: c.has_rational_point()
     78            False
     79            sage: d = c.base_extend(QuadraticField(-1, 'i')); d
     80            Projective Conic Curve over Number Field in i with defining polynomial x^2 + 1 defined by x^2 + y^2 + z^2
     81            sage: d.rational_point()
     82            (-i : 1 : 0)
     83        """
     84        if is_Field(S):
     85            B = self.base_ring()
     86            if B == S:
     87                return self
     88            if not S.has_coerce_map_from(B):
     89                raise ValueError, "No natural map from the base ring of self " \
     90                                  "(= %s) to S (= %s)" % (self, S)
     91            from constructor import Conic
     92            con = Conic([S(c) for c in self.coefficients()], \
     93                        self.variable_names())
     94            if self._rational_point != None:
     95                pt = [S(c) for c in Sequence(self._rational_point)]
     96                if not pt == [0,0,0]:
     97                    _ = con.point(pt)
     98            return con
     99        return ProjectiveCurve_generic.base_extend(self, S)
     100   
     101    def cache_point(self, p):
     102        r"""
     103        Replace the point in the cache of self by `p` for use
     104        by self.rational_point and self.parametrization.
     105       
     106        EXAMPLES:
     107
     108        ::
     109
     110            sage: c = Conic([1, -1, 1])
     111            sage: c.point([15, 17, 8])
     112            (15/8 : 17/8 : 1)
     113            sage: c.rational_point()
     114            (15/8 : 17/8 : 1)
     115            sage: c.cache_point(c.rational_point(read_cache = False))
     116            sage: c.rational_point()
     117            (1 : 1 : 0)
     118        """
     119        if isinstance(p, (tuple, list)):
     120            p = self.point(p)
     121        self._rational_point = p
     122
     123    def coefficients(self):
     124        r"""
     125        Gives a the 6 coefficients of the conic
     126        in lexicographic order.
     127       
     128        EXAMPLES:
     129       
     130        ::
     131       
     132            sage: Conic(QQ, [1,2,3,4,5,6]).coefficients()
     133            [1, 2, 3, 4, 5, 6]
     134
     135            sage: P.<x,y,z> = GF(13)[]
     136            sage: a = Conic(x^2+5*x*y+y^2+z^2).coefficients(); a
     137            [1, 5, 0, 1, 0, 1]
     138            sage: Conic(a)
     139            Projective Conic Curve over Finite Field of size 13 defined by x^2 + 5*x*y + y^2 + z^2
     140        """
     141        return self._coefficients
     142       
     143       
     144    def derivative_matrix(self):
     145        r"""
     146        Gives the derivative of the defining polynomial,
     147        which is a linear map, as a `3 \times 3` matrix.
     148       
     149        Examples:
     150       
     151        In characteristic different from 2, the
     152        derivative matrix is twice the symmetric matrix:
     153
     154        ::
     155       
     156            sage: c = Conic(QQ, [1,1,1,1,1,0])
     157            sage: c.symmetric_matrix()
     158            [  1 1/2 1/2]
     159            [1/2   1 1/2]
     160            [1/2 1/2   0]
     161            sage: c.derivative_matrix()
     162            [2 1 1]
     163            [1 2 1]
     164            [1 1 0]
     165
     166        An example in characteristic 2:
     167
     168        ::
     169
     170            sage: P.<t> = GF(2)[]
     171            sage: c = Conic([t, 1, t^2, 1, 1, 0]); c
     172            Projective 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*z
     173            sage: c.is_smooth()
     174            True
     175            sage: c.derivative_matrix()
     176            [  0   1 t^2]
     177            [  1   0   1]
     178            [t^2   1   0]
     179        """
     180        from sage.matrix.constructor import matrix
     181        [a,b,c,d,e,f] = self.coefficients()
     182        return matrix([[ 2*a ,   b ,   c ],
     183                       [   b , 2*d ,   e ],
     184                       [   c ,   e , 2*f ]])
     185       
     186    def determinant(self):
     187        r"""
     188        Gives the determinant of the symmetric matrix that defines the conic.
     189        This is defined only if the base field has characteristic different
     190        from 2.
     191
     192        EXAMPLES:
     193
     194        ::
     195
     196            sage: C = Conic([1,2,3,4,5,6])
     197            sage: C.determinant()
     198            41/4
     199            sage: C.symmetric_matrix().determinant()
     200            41/4
     201
     202        Determinants are only defined in characteristic different from 2::
     203
     204            sage: C = Conic(GF(2), [1, 1, 1, 1, 1, 0])
     205            sage: C.is_smooth()
     206            True
     207            sage: C.determinant()
     208            Traceback (most recent call last):
     209            ...
     210            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
     211        """
     212        return self.symmetric_matrix().determinant()
     213
     214    det = determinant
     215
     216    def diagonal_matrix(self):
     217        r"""
     218        Returns a diagonal matrix `D` and a matrix `T` such that `T^t A T = D`
     219        holds, where `(x, y, z) A (x, y, z)^t` is the defining polynomial
     220        of the conic `self`.
     221
     222        EXAMPLE:
     223
     224        ::
     225
     226            sage: c = Conic(QQ, [1,2,3,4,5,6])
     227            sage: d, t = c.diagonal_matrix(); d, t
     228            (
     229            [    1     0     0]  [   1   -1 -7/6]
     230            [    0     3     0]  [   0    1 -1/3]
     231            [    0     0 41/12], [   0    0    1]
     232            )
     233            sage: t.transpose()*c.symmetric_matrix()*t
     234            [    1     0     0]
     235            [    0     3     0]
     236            [    0     0 41/12]
     237         
     238        Diagonal matrices are only defined in characteristic different
     239        from 2:
     240       
     241        ::
     242
     243            sage: c = Conic(GF(4, 'a'), [0, 1, 1, 1, 1, 1])
     244            sage: c.is_smooth()
     245            True
     246            sage: c.diagonal_matrix()
     247            Traceback (most recent call last):
     248            ...
     249            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
     250        """
     251        A = self.symmetric_matrix()
     252        B = self.base_ring()
     253        basis = [vector(B,{2:0,i:1}) for i in range(3)]
     254        for i in range(3):
     255            zerovalue = (basis[i]*A*basis[i].transpose()== 0)
     256            if zerovalue:
     257                for j in range(i+1,3):
     258                    if basis[j]*A*basis[j].transpose() != 0:
     259                        b = basis[i]
     260                        basis[i] = basis[j]
     261                        basis[j] = b
     262                        zerovalue = False
     263            if zerovalue:
     264                for j in range(i+1,3):
     265                    if basis[i]*A*basis[j].transpose() != 0:
     266                        basis[i] = basis[i]+basis[j]
     267                        zerovalue = False
     268            if not zerovalue:
     269                l = (basis[i]*A*basis[i].transpose())
     270                for j in range(i+1,3):
     271                    basis[j] = basis[j] - \
     272                               (basis[i]*A*basis[j].transpose())/l * basis[i]
     273        T = Matrix(basis).transpose()
     274        return T.transpose()*A*T, T
     275       
     276    def diagonalization(self,names = None):
     277        r"""
     278        Returns a diagonal conic C, an isomorphism of schemes M: C -> self
     279        and the inverse N of M.
     280       
     281        EXAMPLES:
     282       
     283        ::
     284            sage: Conic(GF(5), [1,0,1,1,0,1]).diagonalization()           
     285            (Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2,
     286             Scheme morphism:
     287              From: Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2
     288              To:   Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + x*z + z^2
     289              Defn: Defined on coordinates by sending (x : y : z) to
     290                    (x + 2*z : y : z),
     291             Scheme morphism:
     292              From: Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + x*z + z^2
     293              To:   Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2
     294              Defn: Defined on coordinates by sending (x : y : z) to
     295                    (x - 2*z : y : z))
     296
     297        The diagonalization is only defined in characteristic different
     298        from 2:
     299       
     300        ::
     301
     302            sage: Conic(GF(2), [1,1,1,1,1,0]).diagonalization()
     303            Traceback (most recent call last):
     304            ...
     305            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
     306        """
     307        if names == None:
     308            names = self.defining_polynomial().parent().variable_names()
     309        from constructor import Conic
     310        D, T = self.diagonal_matrix()
     311        con = Conic(D, names = names)
     312        return con, con.hom(T, self), self.hom(T.inverse(), con)
     313
     314    def gens(self):
     315        r"""
     316        Returns the generators of the coordinate ring of self.
     317       
     318        EXAMPLES:
     319            sage: P.<x,y,z> = QQ[]
     320            sage: c = Conic(x^2+y^2+z^2)
     321            sage: c.gens()
     322            (xbar, ybar, zbar)
     323            sage: c.defining_polynomial()(c.gens())
     324            0
     325        """
     326        return self.coordinate_ring().gens()
     327
     328
     329    def has_rational_point(self, point = False,
     330                           algorithm = 'default', read_cache = True):
     331        r"""
     332        Returns True if and only if self has a point defined over its base field B.
     333
     334        If point is True, then returns a second output, which is
     335        a rational point if one exists, and is None otherwise.
     336       
     337        Points are cached whenever they are found. If read_cache is True,
     338        then cached information is used for the output if available.
     339       
     340        EXAMPLES:
     341
     342        Examples over real and complex fields ::
     343
     344            sage: Conic(RR, [1, 1, 1]).has_rational_point()
     345            False
     346            sage: Conic(CC, [1, 1, 1]).has_rational_point()
     347            True
     348           
     349            sage: Conic(RR, [1, 2, -3]).has_rational_point(point = True)
     350            (True, (1.73205080756888 : 0.000000000000000 : 1.00000000000000))
     351        """
     352        if read_cache:
     353            if self._rational_point is not None:
     354                if point:
     355                    return True, self._rational_point
     356                else:
     357                    return True
     358        B = self.base_ring()
     359        if is_ComplexField(B):
     360            if point:
     361                [_,_,_,d,e,f] = self._coefficients
     362                if d == 0:
     363                    return True, self.point([0,1,0])
     364                return True, self.point([0, ((e**2-4*d*f).sqrt()-e)/(2*d), 1],
     365                                        check = False)
     366            return True
     367        if is_RealField(B):
     368            D, T = self.diagonal_matrix()
     369            [a, b, c] = [D[0,0], D[1,1], D[2,2]]
     370            if a == 0:
     371                ret = True, self.point(T*vector([1,0,0]), check = False)
     372            elif a*c <= 0:
     373                ret = True, self.point(T*vector([(-c/a).sqrt(),0,1]),
     374                                       check = False)
     375            elif b == 0:
     376                ret = True, self.point(T*vector([0,1,0]), check = False)
     377            elif b*c <= 0:
     378                ret = True, self.point(T*vector([0,(-c/b).sqrt(),0,1]),
     379                                       check = False)
     380            else:
     381                ret = False, None
     382            if point:
     383                return ret
     384            return ret[0]
     385        raise NotImplementedError, "has_rational_point not implemented for " \
     386                                   "conics over base field %s" % B
     387       
     388    def has_singular_point(self, point = False):
     389        r"""
     390        Return True if and only if self has a rational
     391        singular point.
     392       
     393        If point is True, then also return a rational singular
     394        point (or None if no such point exists).
     395       
     396        EXAMPLES:
     397       
     398        ::
     399           
     400            sage: c = Conic(QQ, [1,0,1]); c
     401            Projective Conic Curve over Rational Field defined by x^2 + z^2
     402            sage: c.has_singular_point(point = True)
     403            (True, (0 : 1 : 0))
     404           
     405            sage: P.<x,y,z> = GF(7)[]
     406            sage: e = Conic((x+y+z)*(x-y+2*z)); e
     407            Projective Conic Curve over Finite Field of size 7 defined by x^2 - y^2 + 3*x*z + y*z + 2*z^2
     408            sage: e.has_singular_point(point = True)
     409            (True, (2 : 4 : 1))
     410
     411            sage: Conic([1, 1, -1]).has_singular_point()
     412            False
     413            sage: Conic([1, 1, -1]).has_singular_point(point = True)
     414            (False, None)
     415
     416        has_singular_point is not implemented over all fields
     417        of characteristic 2. It is implemented over finite fields.
     418
     419        ::
     420
     421            sage: F.<a> = FiniteField(8)
     422            sage: Conic([a, a+1, 1]).has_singular_point(point = True)
     423            (True, (a + 1 : 0 : 1))
     424
     425            sage: P.<t> = GF(2)[]
     426            sage: C = Conic(P, [t,t,1]); C
     427            Projective 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^2
     428            sage: C.has_singular_point(point = False)
     429            Traceback (most recent call last):
     430            ...
     431            NotImplementedError: Sorry, find singular point on conics not implemented over all fields of characteristic 2.
     432        """
     433        if not point:
     434           ret = self.has_singular_point(point = True)
     435           return ret[0]
     436        B = self.base_ring()
     437        if B.characteristic() == 2:
     438            [a,b,c,d,e,f] = self.coefficients()
     439            if b == 0 and c == 0 and e == 0:
     440                for i in range(3):
     441                    if [a, d, f][i] == 0:
     442                        return True, self.point(vector(B, {2:0, i:1}))
     443                if hasattr(a/f, 'is_square') and hasattr(a/f, 'sqrt'):
     444                    if (a/f).is_square():
     445                        return True, self.point([1,0,(a/f).sqrt()])
     446                    if (d/f).is_square():
     447                        return True, self.point([0,1,(d/f).sqrt()])
     448                raise NotImplementedError, "Sorry, find singular point on conics not implemented over all fields of characteristic 2."
     449            pt = [e, c, b]
     450            if self.defining_polynomial()(pt) == 0:
     451                return True, self.point(pt)
     452            return False, None
     453        D = self.symmetric_matrix()
     454        if D.det() == 0:
     455            return True, self.point(Sequence(D.right_kernel().gen()))
     456        return False, None
     457
     458    def hom(self, x, Y=None):
     459        r"""
     460        Return the scheme morphism from self to Y defined by x.
     461        Here x can be a matrix or a sequence of polynomials.
     462        If Y is omitted, then a natural image is found if possible.
     463
     464        EXAMPLES:
     465       
     466        Morphisms given by matrices. In the first example, Y is omitted,
     467        in the second example, Y is specified.
     468
     469        ::
     470           
     471            sage: c = Conic([-1, 1, 1])
     472            sage: h = c.hom(Matrix([[1,1,0],[0,1,0],[0,0,1]])); h
     473            Scheme morphism:
     474              From: Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2
     475              To:   Projective Conic Curve over Rational Field defined by -x^2 + 2*x*y + z^2
     476              Defn: Defined on coordinates by sending (x : y : z) to
     477                    (x + y : y : z)
     478            sage: h([-1, 1, 0])
     479            (0 : 1 : 0)
     480
     481            sage: c = Conic([-1, 1, 1])
     482            sage: d = Conic([4, 1, -1])
     483            sage: c.hom(Matrix([[0, 0, 1/2], [0, 1, 0], [1, 0, 0]]), d)
     484            Scheme morphism:
     485              From: Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2
     486                To:   Projective Conic Curve over Rational Field defined by 4*x^2 + y^2 - z^2
     487                  Defn: Defined on coordinates by sending (x : y : z) to
     488                          (1/2*z : y : x)
     489
     490        A ValueError is raised if the wrong codomain Y is specified:
     491
     492        ::
     493       
     494            sage: c = Conic([-1, 1, 1])
     495            sage: c.hom(Matrix([[0, 0, 1/2], [0, 1, 0], [1, 0, 0]]), c)
     496            Traceback (most recent call last):
     497            ...
     498            ValueError: The matrix x (= [  0   0 1/2]
     499            [  0   1   0]
     500            [  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)
     501        """
     502        if is_Matrix(x):   
     503            from constructor import Conic
     504            y = x.inverse()
     505            A = y.transpose()*self.matrix()*y
     506            im = Conic(A)
     507            if Y == None:
     508                Y = im
     509            else:
     510                q = Y.defining_polynomial()/im.defining_polynomial()
     511                if not (q.numerator().is_constant()
     512                        and q.denominator().is_constant()):
     513                    raise ValueError, "The matrix x (= %s) does not define a " \
     514                                      "map from self (= %s) to Y (= %s)" % \
     515                                      (x, self, Y)
     516            x = Sequence(x*vector(self.ambient_space().gens()))
     517            return self.Hom(Y)(x, check = False)
     518        return ProjectiveCurve_generic.hom(self, x, Y)           
     519           
     520       
     521    def is_diagonal(self):
     522        r"""
     523        Return True if and only if the conic has the form
     524        `a*x^2 + b*y^2 + c*z^2`.
     525
     526        EXAMPLES:
     527
     528        ::
     529
     530            sage: c=Conic([1,1,0,1,0,1]); c
     531            Projective Conic Curve over Rational Field defined by x^2 + x*y + y^2 + z^2
     532            sage: d,t = c.diagonal_matrix()
     533            sage: c.is_diagonal()
     534            False
     535            sage: c.diagonalization()[0].is_diagonal()
     536            True
     537        """
     538        return all([self.coefficients()[i] == 0 for i in [1,2,4]])
     539
     540
     541    def is_smooth(self):
     542        r"""
     543        Returns True if and only if self is smooth.
     544
     545        EXAMPLES:
     546
     547        ::
     548
     549            sage: Conic([1,-1,0]).is_smooth()
     550            False
     551            sage: Conic(GF(2),[1,1,1,1,1,0]).is_smooth()
     552            True
     553        """
     554        if self.base_ring().characteristic() == 2:
     555            [a,b,c,d,e,f] = self.coefficients()
     556            if b == 0 and c == 0 and e == 0:
     557                return False
     558            return self.defining_polynomial()([e, c, b]) != 0
     559        return self.determinant() != 0
     560
     561
     562    def matrix(self):
     563        r"""
     564        Returns a matrix `M` such that `(x, y, z) M (x, y, z)^t`
     565        is the defining equation of self.
     566        The matrix `M` is upper triangular if the base field has
     567        characteristic 2 and symmetric otherwise.
     568
     569        EXAMPLES:
     570            sage: R.<x, y, z> = QQ[]
     571            sage: C = Conic(x^2 + x*y + y^2 + z^2)
     572            sage: C.matrix()
     573            [  1 1/2   0]
     574            [1/2   1   0]
     575            [  0   0   1]
     576
     577            sage: R.<x, y, z> = GF(2)[]
     578            sage: C = Conic(x^2 + x*y + y^2 + x*z + z^2)
     579            sage: C.matrix()
     580            [1 1 1]
     581            [0 1 0]
     582            [0 0 1]
     583        """
     584        if self.base_ring().characteristic() == 2:
     585            return self.upper_triangular_matrix()
     586        return self.symmetric_matrix()
     587       
     588    _matrix_ = matrix
     589
     590    def parametrization(self, point=None, morphism=True):
     591        r"""
     592        Return a parametrization of self and the inverse
     593        of the parametrization.
     594
     595        If point is specified, then that point is used
     596        for the parametrization. Otherwise, use rational_point
     597        to find a point.
     598           
     599        If morphism is False, then returns the tuples of three
     600        polynomials that give the parametrization.
     601       
     602        Raises ValueError if no rational point exists or self is non-smooth.
     603
     604        ALGORITHM:
     605       
     606            Uses Denis Simon's Qfparam if the base field is `QQ`.
     607            Gives a straightforward non-optimized parametrization
     608            otherwise.
     609       
     610        EXAMPLES:
     611            sage: R.<x,y,z> = QQ[]
     612            sage: C = Conic(7*x^2 + 2*y*z + z^2)
     613            sage: (p, i) = C.parametrization(morphism = False); (p, i)
     614            ([-2*x*y, 7*x^2 + y^2, -2*y^2], [-1/2*x, -1/2*z])
     615            sage: C.defining_polynomial()(p)
     616            0
     617            sage: i[0](p) / i[1](p)
     618            x/y
     619
     620            sage: C = Conic(x^2 + 2*y^2 + z^2)
     621            sage: C.parametrization()
     622            Traceback (most recent call last):
     623            ...
     624            ValueError: Conic Projective Conic Curve over Rational Field defined by x^2 + 2*y^2 + z^2 has no rational points over Rational Field!
     625
     626            sage: C = Conic(x^2 + y^2 + 7*z^2)
     627            sage: C.parametrization()
     628            Traceback (most recent call last):
     629            ...
     630            ValueError: Conic Projective Conic Curve over Rational Field defined by x^2 + y^2 + 7*z^2 has no rational points over Rational Field!
     631
     632            sage: c = Conic([1,1,-1])
     633            sage: c.param()
     634            (Scheme morphism:
     635              From: Projective Space of dimension 1 over Rational Field
     636              To:   Projective Conic Curve over Rational Field defined by x^2 + y^2 - z^2
     637              Defn: Defined on coordinates by sending (x : y) to
     638                    (2*x*y : x^2 - y^2 : x^2 + y^2),
     639             Scheme morphism:
     640               From: Projective Conic Curve over Rational Field defined by x^2 + y^2 - z^2
     641               To:   Projective Space of dimension 1 over Rational Field
     642               Defn: Defined on coordinates by sending (x : y : z) to
     643                     (1/2*x : -1/2*y + 1/2*z))
     644            sage: c = Conic(GF(2), [1,1,1,1,1,0])
     645            sage: c.param()
     646            (Scheme morphism:
     647              From: Projective Space of dimension 1 over Finite Field of size 2
     648              To:   Projective Conic Curve over Finite Field of size 2 defined by x^2 + x*y
     649            + y^2 + x*z + y*z
     650              Defn: Defined on coordinates by sending (x : y) to
     651                    (x*y + y^2 : x^2 + x*y : x^2 + x*y + y^2),
     652             Scheme morphism:
     653              From: Projective Conic Curve over Finite Field of size 2 defined by x^2 + x*y
     654            + y^2 + x*z + y*z
     655              To:   Projective Space of dimension 1 over Finite Field of size 2
     656              Defn: Defined on coordinates by sending (x : y : z) to
     657                    (y : x))
     658        """
     659        if (not self._parametrization is None) and not point:
     660            par = self._parametrization
     661        else:
     662            if not self.is_smooth():
     663                raise ValueError, "The conic self (=%s) is not smooth, hence does not have a parametrization.", self
     664            if point == None:
     665                point = self.rational_point()
     666            point = Sequence(point)
     667            B = self.base_ring()
     668            Q = PolynomialRing(B, 'x,y')
     669            [x, y] = Q.gens()
     670            gens = self.ambient_space().gens()
     671            if is_RationalField(B):
     672                from sage.quadratic_forms.qfsolve import Qfparam
     673                from sage.rings.arith import lcm
     674                M = self.symmetric_matrix()
     675                M *= lcm([ t.denominator() for t in M.list() ])
     676                par1 = Qfparam(M, point)
     677                B = Matrix([[par1[i][j] for j in range(3)] for i in range(3)])
     678                # self is in the image of B and does not lie on a line,
     679                # hence B is invertible
     680                A = B.inverse()
     681                par2 = [sum([A[i,j]*gens[j] for j in range(3)]) for i in [1,0]]
     682                par = ([Q(pol(x/y)*y**2) for pol in par1], par2)
     683            else:
     684                P = PolynomialRing(B, 4, ['X', 'Y', 'T0', 'T1'])
     685                [X, Y, T0, T1] = P.gens()
     686                c3 = [j for j in range(2,-1,-1) if point[j] != 0][0]
     687                c1 = [j for j in range(3) if j != c3][0]
     688                c2 = [j for j in range(3) if j != c3 and j != c1][0]
     689                L = [0,0,0]
     690                L[c1] = Y*T1*point[c1] + Y*T0
     691                L[c2] = Y*T1*point[c2] + X*T0
     692                L[c3] = Y*T1*point[c3]
     693                bezout = P(self.defining_polynomial()(L) / T0)
     694                t = [bezout([x,y,0,-1]),bezout([x,y,1,0])]
     695                par = (tuple([Q(p([x,y,t[0],t[1]])/y) for  p in L]),
     696                       tuple([gens[m]*point[c3]-gens[c3]*point[m]
     697                           for m in [c2,c1]]))
     698            if self._parametrization is None:
     699                self._parametrization = par
     700        if not morphism:
     701            return par
     702        P1 = ProjectiveSpace(self.base_ring(), 1, 'x,y')
     703        return P1.hom(par[0],self), self.Hom(P1)(par[1], check = False)
     704       
     705    param = parametrization
     706                   
     707    def point(self, v, check=True):
     708        r"""
     709        Constructs a point on self corresponding to the input.
     710       
     711        If no rational point on self is known yet, then also caches the point
     712        for use by self.rational_point and self.parametrization
     713
     714        EXAMPLES:
     715
     716        ::
     717
     718            sage: c = Conic([1, -1, 1])
     719            sage: c.point([15, 17, 8])
     720            (15/8 : 17/8 : 1)
     721            sage: c.rational_point()
     722            (15/8 : 17/8 : 1)
     723            sage: d = Conic([1, -1, 1])
     724            sage: d.rational_point()
     725            (1 : 1 : 0)
     726        """
     727        if is_Vector(v):
     728            v = Sequence(v)
     729        p = ProjectiveCurve_generic.point(self, v, check=check)
     730        if self._rational_point is None:
     731            self._rational_point = p
     732        return p
     733
     734       
     735    def random_rational_point(self, bound=None):
     736        r"""
     737        Return a random rational point of this conic.
     738       
     739        The output is the image of a random point X on the
     740        projective line under a parametrization of self.
     741        If a bound is specified and the base field is `\QQ`,
     742        then that is a bound on the naive height of X.
     743        If the base field is a finite field, then the
     744        output is uniformly distributed over the rational
     745        points of self.
     746
     747        EXAMPLES:
     748           
     749        ::
     750            sage: c = Conic(GF(2), [1,1,1,1,1,0])
     751            sage: [c.random_rational_point() for _ in range(10)] # output is random
     752           
     753            [(0 : 0 : 1),
     754             (1 : 0 : 1),
     755             (1 : 0 : 1),
     756             (0 : 0 : 1),
     757             (1 : 0 : 1),
     758             (0 : 1 : 1),
     759             (0 : 1 : 1),
     760             (0 : 0 : 1),
     761             (0 : 0 : 1),
     762             (1 : 0 : 1)]
     763        """
     764        if not self.is_smooth():
     765            raise NotImplementedError, "Sorry, random points not implemented " \
     766                                       "for non-smooth conics"
     767        par = self.parametrization()
     768        x = 0
     769        y = 0
     770        B = self.base_ring()
     771        if is_RationalField(B) and bound != None:
     772            if bound < 1:
     773                raise ValueError, "The bound (= %s) needs to be at least 1" % \
     774                                  bound
     775            while x == 0 and y == 0:
     776                x = ZZ.random_element(-bound, bound+1)
     777                y = ZZ.random_element(-bound, bound+1)
     778        else:
     779            while x == 0 and y == 0:
     780                x = B.random_element()
     781                y = B.random_element()
     782        return par[0]([x,y])
     783
     784
     785    def rational_point(self, algorithm = 'default', read_cache = True):
     786        r"""Return a rational point (x0, y0, z0) on self.
     787
     788        Raises ValueError if no rational point exists.
     789
     790        See has_rational_point(self) for the algorithm used and for the use of
     791        the parameters algorithm and read_cache.
     792         
     793        EXAMPLES:
     794
     795        Examples over QQ ::
     796       
     797            sage: R.<x,y,z> = QQ[]
     798            sage: C = Conic(7*x^2 + 2*y*z + z^2)
     799            sage: C.rational_point()
     800            (0 : 1 : 0)
     801
     802            sage: C = Conic(x^2 + 2*y^2 + z^2)
     803            sage: C.rational_point()
     804            Traceback (most recent call last):
     805            ...
     806            ValueError: Conic Projective Conic Curve over Rational Field defined by x^2 + 2*y^2 + z^2 has no rational points over Rational Field!
     807
     808            sage: C = Conic(x^2 + y^2 + 7*z^2)
     809            sage: C.rational_point(algorithm = 'all')
     810            Traceback (most recent call last):
     811            ...
     812            ValueError: Conic Projective Conic Curve over Rational Field defined by x^2 + y^2 + 7*z^2 has no rational points over Rational Field!
     813
     814        Examples over number fields ::
     815           
     816            sage: _.<x> = QQ[]
     817            sage: L.<b> = NumberField(x^3-5)
     818            sage: C = Conic(L, [3, 2, -5])
     819            sage: C.rational_point(algorithm = 'all')  # long time (1 second)
     820            (-1 : -1 : 1)
     821       
     822        Examples over finite fields ::
     823       
     824            sage: F.<a> = FiniteField(7^20)
     825            sage: C = Conic([1, a, -5]); C
     826            Projective Conic Curve over Finite Field in a of size 7^20 defined by x^2 + (a)*y^2 + 2*z^2
     827            sage: C.rational_point()  # output is random
     828            (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)
     829             
     830        Examples over real and complex fields ::
     831
     832            sage: Conic(CC, [1, 2, 3]).rational_point()
     833            (0 : 1.22474487139159*I : 1)
     834
     835            sage: Conic(RR, [1, 1, 1]).rational_point()
     836            Traceback (most recent call last):
     837            ...
     838            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!
     839        """
     840        bl,pt = self.has_rational_point(point = True, algorithm = algorithm,
     841                                        read_cache = read_cache)
     842        if bl:
     843            return pt
     844        raise ValueError, "Conic %s has no rational points over %s!" % \
     845                          (self, self.ambient_space().base_ring())
     846
     847
     848    def singular_point(self):
     849        r"""
     850        Returns a singular rational point of self
     851       
     852        EXAMPLES:
     853       
     854        ::
     855
     856            sage: Conic(GF(2), [1,1,1,1,1,1]).singular_point()
     857            (1 : 1 : 1)
     858
     859        A ValueError is raised if the conic has no rational singular point
     860           
     861        ::
     862
     863            sage: Conic(QQ, [1,1,1,1,1,1]).singular_point()
     864            Traceback (most recent call last):
     865            ...
     866            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
     867        """
     868        b = self.has_singular_point(point = True)
     869        if not b[0]:
     870            raise ValueError, "The conic self (= %s) has no rational " \
     871                              "singular point" % self
     872        return b[1]
     873
     874    def symmetric_matrix(self):
     875        r"""
     876        The symmetric matrix M such that (x y z) M (x y z)^t
     877        is the defining equation of  self.
     878       
     879        EXAMPLES:
     880            sage: R.<x, y, z> = QQ[]
     881            sage: C = Conic(x^2 + x*y/2 + y^2 + z^2)
     882            sage: C.symmetric_matrix()
     883            [  1 1/4   0]
     884            [1/4   1   0]
     885            [  0   0   1]
     886
     887            sage: C = Conic(x^2 + 2*x*y + y^2 + 3*x*z + z^2)
     888            sage: v = vector([x, y, z])
     889            sage: v * C.symmetric_matrix() * v
     890            x^2 + 2*x*y + y^2 + 3*x*z + z^2
     891        """
     892        [a,b,c,d,e,f] = self.coefficients()
     893        if self.base_ring().characteristic() == 2:
     894            if b == 0 and c == 0 and e == 0:
     895                return matrix([[a,0,0],[0,d,0],[0,0,f]])
     896            raise ValueError, "The conic self (= %s) has no symmetric matrix " \
     897                              "because the base field has characteristic 2" % \
     898                              self
     899        from sage.matrix.constructor import matrix
     900        return matrix([[  a , b/2, c/2 ],
     901                       [ b/2,  d , e/2 ],
     902                       [ c/2, e/2,  f  ]])
     903
     904
     905    def upper_triangular_matrix(self):
     906        r"""
     907        The upper-triangular matrix M such that (x y z) M (x y z)^t
     908        is the defining equation of self.
     909
     910        EXAMPLES:
     911            sage: R.<x, y, z> = QQ[]
     912            sage: C = Conic(x^2 + x*y + y^2 + z^2)
     913            sage: C.upper_triangular_matrix()
     914            [1 1 0]
     915            [0 1 0]
     916            [0 0 1]
     917
     918            sage: C = Conic(x^2 + 2*x*y + y^2 + 3*x*z + z^2)
     919            sage: v = vector([x, y, z])
     920            sage: v * C.upper_triangular_matrix() * v
     921            x^2 + 2*x*y + y^2 + 3*x*z + z^2
     922        """
     923        from sage.matrix.constructor import matrix
     924        [a,b,c,d,e,f] = self.coefficients()
     925        return matrix([[ a, b, c ],
     926                       [ 0, d, e ],
     927                       [ 0, 0, f ]])
     928   
     929    def variable_names(self):
     930        r"""
     931        Returns the variable names of the defining polynomial
     932        of self
     933
     934        EXAMPLES:
     935
     936        ::
     937
     938            sage: c=Conic([1,1,0,1,0,1], 'x,y,z')
     939            sage: c.variable_names()
     940            ('x', 'y', 'z')
     941            sage: c.variable_name()
     942            'x'
     943        """
     944        return self.defining_polynomial().parent().variable_names()
     945   
     946       
     947       
     948
     949 
  • new file sage/schemes/plane_conics/con_finite_field.py

    diff -r 510cd246e899 -r dd59f5b6d61d sage/schemes/plane_conics/con_finite_field.py
    - +  
     1r"""
     2Projective plane conics over finite fields.
     3
     4AUTHORS:
     5
     6- Marco Streng (2009-08-07)
     7
     8- Nick Alexander (2008-01-08)
     9
     10"""
     11#*****************************************************************************
     12#       Copyright (C) 2008 Nick Alexander <ncalexander@gmail.com>
     13#       Copyright (C) 2009 Marco Streng <marco.streng@gmail.com>
     14#
     15#  Distributed under the terms of the GNU General Public License (GPL)
     16#
     17#    This code is distributed in the hope that it will be useful,
     18#    but WITHOUT ANY WARRANTY; without even the implied warranty of
     19#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     20#    General Public License for more details.
     21#
     22#  The full text of the GPL is available at:
     23#
     24#                  http://www.gnu.org/licenses/
     25#*****************************************************************************
     26
     27from sage.libs.pari.gen import pari
     28from sage.misc.all import add, sage_eval
     29from sage.rings.all import (PolynomialRing, ZZ, QQ, MPolynomialRing,
     30                            degree_lowest_rational_function,
     31                            is_PrimeField, is_FiniteField,
     32                            is_ComplexField, is_RealField,
     33                            is_pAdicField, is_Field,
     34                            is_RationalField)
     35from sage.modules.free_module_element import vector
     36from sage.structure.sequence import Sequence
     37from sage.structure.element import is_Vector
     38from sage.schemes.generic.projective_space import (ProjectiveSpace,
     39                                                   is_ProjectiveSpace)
     40from sage.matrix.constructor import Matrix
     41from sage.matrix.matrix import is_Matrix
     42
     43from sage.schemes.plane_curves.curve import Curve_generic_projective
     44from sage.schemes.plane_curves.projective_curve import ProjectiveCurve_generic
     45from sage.schemes.plane_curves.projective_curve import ProjectiveCurve_finite_field
     46
     47from sage.quadratic_forms.qfsolve import Qfsolve, Qfparam
     48
     49from con_field import ProjectiveConic_field
     50
     51class ProjectiveConic_finite_field(ProjectiveConic_field, ProjectiveCurve_finite_field):
     52    def __init__(self, A, f):
     53        ProjectiveConic_field.__init__(self, A, f)
     54
     55
     56    def count_points(self, n):
     57        r"""
     58        If the base field `B` of `self` is finite of order `q`,
     59        then returns the number of points over `GF{q}, ..., GF{q^n}`.
     60       
     61        EXAMPLES:
     62
     63            sage: P.<x,y,z> = GF(3)[]
     64            sage: c = Conic(x^2+y^2+z^2)
     65            sage: c.count_points(4)
     66            [4, 10, 28, 82]
     67        """       
     68        F = self.base_ring()
     69        q = F.cardinality()
     70        return [q**i+1 for i in range(1, n+1)]
     71       
     72       
     73    def has_rational_point(self, point = False, read_cache = True, \
     74                           algorithm = 'default'):
     75        r"""
     76        Always returns True because self has a point defined over
     77        its finite base field B.
     78
     79        If 'point' is True, then returns a second output S, which is a
     80        rational point.
     81       
     82        Points are cached. If 'read_cache' is True, then cached information
     83        is used for the output if available. If no cached point is available
     84        or 'read_cache' is False, then random y-coordinates are tried
     85        if 'self' is smooth and a singular point is returned otherwise.
     86       
     87        EXAMPLES:
     88
     89        ::
     90       
     91            sage: Conic(FiniteField(37), [1, 2, 3, 4, 5, 6]).has_rational_point()
     92            True
     93           
     94            sage: C = Conic(FiniteField(2), [1, 1, 1, 1, 1, 0]); C
     95            Projective Conic Curve over Finite Field of size 2 defined by x^2 + x*y + y^2 + x*z + y*z
     96            sage: C.has_rational_point(point = True)  # output is random
     97            (True, (0 : 0 : 1))
     98           
     99            sage: p = next_prime(10^50)
     100            sage: F = FiniteField(p)
     101            sage: C = Conic(F, [1, 2, 3]); C
     102            Projective Conic Curve over Finite Field of size 100000000000000000000000000000000000000000000000151 defined by x^2 + 2*y^2 + 3*z^2
     103            sage: C.has_rational_point(point = True)  # output is random
     104            (True,
     105             (14971942941468509742682168602989039212496867586852 : 75235465708017792892762202088174741054630437326388 : 1)
     106     
     107            sage: F.<a> = FiniteField(7^20)
     108            sage: C = Conic([1, a, -5]); C
     109            Projective Conic Curve over Finite Field in a of size 7^20 defined by x^2 + (a)*y^2 + 2*z^2
     110            sage: C.has_rational_point(point = True)  # output is random
     111            (True,
     112             (a^18 + 2*a^17 + 4*a^16 + 6*a^13 + a^12 + 6*a^11 + 3*a^10 + 4*a^9 + 2*a^8 + 4*a^7 + a^6 + 4*a^4 + 6*a^2 + 3*a + 6 : 5*a^19 + 5*a^18 + 5*a^17 + a^16 + 2*a^15 + 3*a^14 + 4*a^13 + 5*a^12 + a^11 + 3*a^10 + 2*a^8 + 3*a^7 + 4*a^6 + 4*a^5 + 6*a^3 + 5*a^2 + 2*a + 4 : 1))
     113             
     114        """
     115        if not point:
     116            return True
     117        if read_cache:
     118            if self._rational_point is not None:
     119                return True, self._rational_point
     120        B = self.base_ring()
     121        s, pt = self.has_singular_point(point = True)
     122        if s:
     123            return True, pt
     124        while True:
     125            x = B.random_element()
     126            Y = PolynomialRing(B,'Y').gen()
     127            r = self.defining_polynomial()([x,Y,1]).roots()
     128            if len(r) > 0:
     129                return True, self.point([x,r[0][0],B(1)])
     130
     131
     132
  • new file sage/schemes/plane_conics/con_global_field.py

    diff -r 510cd246e899 -r dd59f5b6d61d sage/schemes/plane_conics/con_global_field.py
    - +  
     1r"""
     2Projective plane conics over a global field.
     3
     4AUTHORS:
     5
     6- Marco Streng (2009-08-07)
     7
     8- Nick Alexander (2008-01-08)
     9
     10"""
     11#*****************************************************************************
     12#       Copyright (C) 2008 Nick Alexander <ncalexander@gmail.com>
     13#       Copyright (C) 2009 Marco Streng <marco.streng@gmail.com>
     14#
     15#  Distributed under the terms of the GNU General Public License (GPL)
     16#
     17#    This code is distributed in the hope that it will be useful,
     18#    but WITHOUT ANY WARRANTY; without even the implied warranty of
     19#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     20#    General Public License for more details.
     21#
     22#  The full text of the GPL is available at:
     23#
     24#                  http://www.gnu.org/licenses/
     25#*****************************************************************************
     26
     27from sage.libs.pari.gen import pari
     28from sage.misc.all import add, sage_eval
     29from sage.rings.all import (PolynomialRing, ZZ, QQ, MPolynomialRing,
     30                            degree_lowest_rational_function,
     31                            is_PrimeField, is_FiniteField,
     32                            is_ComplexField, is_RealField,
     33                            is_pAdicField, is_Field,
     34                            is_RationalField, is_RingHomomorphism)
     35from sage.rings.number_field.number_field import is_NumberField                           
     36from sage.modules.free_module_element import vector
     37from sage.structure.sequence import Sequence
     38from sage.structure.element import is_Vector
     39from sage.schemes.generic.projective_space import (ProjectiveSpace,
     40                                                   is_ProjectiveSpace)
     41from sage.matrix.constructor import Matrix
     42from sage.matrix.matrix import is_Matrix
     43
     44from sage.schemes.plane_curves.curve import Curve_generic_projective
     45from sage.schemes.plane_curves.projective_curve import ProjectiveCurve_generic
     46from sage.quadratic_forms.qfsolve import Qfsolve, Qfparam
     47
     48from con_field import ProjectiveConic_field
     49
     50class ProjectiveConic_global_field(ProjectiveConic_field):
     51    def __init__(self, A, f):
     52        ProjectiveConic_field.__init__(self, A, f)
     53        # a single prime such that self has no point over the completion
     54        self._local_obstruction = None
     55        # all finite primes such that self has no point over the completion
     56        self._finite_obstructions = None
     57        # all infinite primes such that self has no point over the completion
     58        self._infinite_obstructions = None
     59
     60
     61    def is_locally_solvable(self, p):
     62        r"""
     63        Returns True if and only if self has a solution over the completion
     64        of the base field `B` of self at `p`. Here `p` is a finite prime
     65        or infinite place of `B`.
     66
     67        EXAMPLES:
     68
     69        An example over QQ ::
     70
     71            sage: C = Conic(QQ, [1,2,3])
     72            sage: C.is_locally_solvable(-1)
     73            False
     74            sage: C.is_locally_solvable(2)
     75            False
     76            sage: C.is_locally_solvable(3)
     77            True
     78
     79        Example over a number field ::
     80
     81            sage: _.<x> = QQ[]
     82            sage: K.<a> = NumberField(x^3 + 5)
     83            sage: C = Conic(K, [1, 2, 3 - a])
     84            sage: [p1, p2] = K.places()
     85            sage: C.is_locally_solvable(p1)
     86            False
     87            sage: C.is_locally_solvable(p2)
     88            True
     89        """
     90        raise TypeError, "is_locally_solvable not yet implemented for" \
     91                         "conics over global field %s" % B
     92
     93    def local_obstructions(self, finite = True, infinite = True, read_cache = True):
     94        r"""
     95        Returns the sequence of finite primes and/or infinite places
     96        such that self is locally solvable at those primes and places.
     97       
     98        If the base field is `QQ`, then the infinite place is denoted `-1`.
     99
     100        The parameters finite and infinite (both True by default) are
     101        used to specify whether to look at finite and/or infinite places.
     102        Note that finite = True involves factorization of the determinant
     103        of self, hence may be slow.
     104       
     105        Local obstructions are cached. The parameter read_cache can be used
     106        to specify whether to look at the cache before computing anything.
     107
     108        EXAMPLES:
     109
     110        Examples over QQ ::
     111
     112            sage: Conic(QQ, [1, 1, 1]).local_obstructions()
     113            [2, -1]
     114            sage: Conic(QQ, [1, 2, -3]).local_obstructions()
     115            []
     116            sage: Conic(QQ, [1, 2, 3, 4, 5, 6]).local_obstructions()
     117            [41, -1]
     118
     119
     120        Examples over number fields ::
     121
     122            sage: K.<i> = QuadraticField(-1)
     123            sage: Conic(K, [1, 1, 1]).local_obstructions()
     124            []
     125            sage: Conic(K, [1, 2, -3]).local_obstructions()
     126            []
     127            sage: Conic(K, [1, 2, 3, 4, 5, 6]).local_obstructions()
     128            [Fractional ideal (5*i - 4), Fractional ideal (-5*i - 4)]
     129
     130            sage: _.<x> = QQ[]
     131            sage: L.<b> = NumberField(x^4-2)
     132            sage: Conic(L, [1, 1, 1]).local_obstructions() # long time (2 seconds)
     133            [Ring morphism:
     134              From: Number Field in b with defining polynomial x^4 - 2
     135              To:   Real Field with 106 bits of precision
     136              Defn: b |--> -1.189207115002721066717492233629, Ring morphism:
     137              From: Number Field in b with defining polynomial x^4 - 2
     138              To:   Real Field with 106 bits of precision
     139              Defn: b |--> 1.189207115002721066717492233629]
     140            sage: Conic(L, [b, 1, 1]).local_obstructions() # long time (2 seconds)
     141            [Fractional ideal (b),
     142             Ring morphism:
     143             From: Number Field in b with defining polynomial x^4 - 2
     144             To:   Real Field with 106 bits of precision
     145             Defn: b |--> 1.189207115002721066717492233629]
     146        """
     147        obs0 = []
     148        obs1 = []
     149        B = self.base_ring()
     150        if infinite:
     151            if read_cache and self._infinite_obstructions != None:
     152                obs0 = self._infinite_obstructions
     153            else:
     154                if is_RationalField(B):
     155                    if not self.is_locally_solvable(-1):
     156                        obs0 = [-1]
     157                elif is_NumberField(B):
     158                    for b in B.places():
     159                        if not self.is_locally_solvable(b):
     160                            obs0.append(b)
     161                else:
     162                    raise TypeError, "Base field (=%s) needs to be QQ or a" \
     163                                     "number field in local_obstructions" % B
     164                self._infinite_obstructions = obs0
     165        if finite:
     166            if read_cache and self._finite_obstructions != None:
     167                obs1 = self._finite_obstructions
     168            else:
     169                candidates = []
     170                if is_RationalField(B):
     171                    if self.determinant() != 0:
     172                        for a in self.symmetric_matrix().list():
     173                            if a != 0:
     174                                for f in a.factor():
     175                                    if f[1] < 0 and not f[0] in candidates:
     176                                        candidates.append(f[0])
     177                        for f in (2*self.determinant()).factor():
     178                            if f[1] > 0 and not f[0] in candidates:
     179                                candidates.append(f[0])
     180                elif is_NumberField(B):
     181                    if self.determinant() != 0:
     182                        O = B.maximal_order()
     183                        for a in self.symmetric_matrix().list():
     184                            if a != 0:
     185                                for f in O.fractional_ideal(a).factor():
     186                                    if f[1] < 0 and not f[0] in candidates:
     187                                        candidates.append(f[0])
     188                        for f in O.fractional_ideal(2*self.determinant()).factor():
     189                            if f[1] > 0 and not f[0] in candidates:
     190                                candidates.append(f[0])       
     191                else:
     192                    raise TypeError, "Base field (=%s) needs to be QQ or a " \
     193                                     "number field in local_obstructions" % B
     194                for b in candidates:
     195                    if not self.is_locally_solvable(b):
     196                       obs1.append(b)
     197                self._infinite_obstructions = obs1
     198        obs = obs1 + obs0
     199        if finite and infinite and len(obs)%2==1:
     200            raise RuntimeError, "Bug in local_obstructions or in " \
     201                                "is_locally_solvable: the number of bad places" \
     202                                "for conic self (=%s) is odd" % self
     203        return obs
     204
     205
  • new file sage/schemes/plane_conics/con_number_field.py

    diff -r 510cd246e899 -r dd59f5b6d61d sage/schemes/plane_conics/con_number_field.py
    - +  
     1r"""
     2Projective plane conics over a number field.
     3
     4AUTHORS:
     5
     6- Marco Streng (2009-08-07)
     7
     8- Nick Alexander (2008-01-08)
     9
     10"""
     11#*****************************************************************************
     12#       Copyright (C) 2008 Nick Alexander <ncalexander@gmail.com>
     13#       Copyright (C) 2009 Marco Streng <marco.streng@gmail.com>
     14#
     15#  Distributed under the terms of the GNU General Public License (GPL)
     16#
     17#    This code is distributed in the hope that it will be useful,
     18#    but WITHOUT ANY WARRANTY; without even the implied warranty of
     19#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     20#    General Public License for more details.
     21#
     22#  The full text of the GPL is available at:
     23#
     24#                  http://www.gnu.org/licenses/
     25#*****************************************************************************
     26
     27from sage.libs.pari.gen import pari
     28from sage.misc.all import add, sage_eval
     29from sage.rings.all import (PolynomialRing, ZZ, QQ, RR, MPolynomialRing,
     30                            degree_lowest_rational_function,
     31                            is_PrimeField, is_FiniteField,
     32                            is_ComplexField, is_RealField,
     33                            is_pAdicField, is_Field,
     34                            is_RationalField, is_RingHomomorphism)
     35from sage.rings.number_field.number_field import is_NumberField                           
     36from sage.modules.free_module_element import vector
     37from sage.structure.sequence import Sequence
     38from sage.structure.element import is_Vector
     39from sage.schemes.generic.projective_space import (ProjectiveSpace,
     40                                                   is_ProjectiveSpace)
     41from sage.matrix.constructor import Matrix
     42from sage.matrix.matrix import is_Matrix
     43
     44from sage.schemes.plane_curves.curve import Curve_generic_projective
     45from sage.schemes.plane_curves.projective_curve import ProjectiveCurve_generic
     46from sage.quadratic_forms.qfsolve import Qfsolve, Qfparam
     47
     48from con_global_field import ProjectiveConic_global_field
     49
     50
     51class ProjectiveConic_number_field(ProjectiveConic_global_field):
     52    def __init__(self, A, f):
     53        ProjectiveConic_global_field.__init__(self, A, f)
     54
     55
     56    def has_rational_point(self, point = False, obstruction = False,
     57                           algorithm = 'default', read_cache = True):
     58        r"""
     59        Returns True if and only if self has a point defined over its base field B.
     60
     61        If point or obstruction is True, then returns a second output S:
     62        - if point is True and self has a rational point,
     63          then S is a rational point;
     64        - if obstruction is True, self has no rational point,
     65          then S is a prime or infinite place
     66          of the base ring such that no rational point exists
     67          over the localization at S.
     68       
     69        Points and obstructions are cached, whenever they are found.
     70        If read_cache is True,
     71        then cached information is used for the output if available.
     72       
     73        ALGORITHM:
     74           
     75            The parameter ``algorithm``
     76            specifies the algorithm to be used:
     77           
     78                ``rnfisnorm`` - Use PARI's rnfisnorm (cannot be combined with
     79                                obstruction = True)
     80                ``local``     - Check if a local solution exists for all primes
     81                                and infinite places of K (cannot be combined with
     82                                point = True)
     83                ``default``   - Use ``qfsolve`` over `\QQ`. Use ``local`` over
     84                                other number fields. If the output is True and
     85                                point is True, then use ``rnfisnorm`` to find
     86                                the point.
     87                ``all``       - Use all applicable algorithms, check that the
     88                                outputs agree, and return the common answer.
     89           
     90        EXAMPLES:
     91
     92        The following would not terminate quickly with algorithm = 'rnfisnorm' ::
     93
     94            sage: C = Conic(QQ, [1, 113922743, -310146482690273725409])
     95            sage: C.has_rational_point(point = True)
     96            (True, (-76842858034579/5424 : -5316144401/5424 : 1))
     97            sage: C.has_rational_point(algorithm = 'local', read_cache = False)
     98            True
     99
     100        Examples over number fields ::
     101           
     102            sage: K.<i> = QuadraticField(-1)
     103            sage: C = Conic(K, [1, 3, -5])
     104            sage: C.has_rational_point(point = True, obstruction = True, \
     105                                       algorithm = 'all')
     106            (False, Fractional ideal (-i - 2))
     107
     108            sage: _.<x> = QQ[]
     109            sage: L.<b> = NumberField(x^3-5)
     110            sage: C = Conic(L, [1, 2, -3])
     111            sage: C.has_rational_point(point = True, obstruction = True, \
     112                                       algorithm = 'all') # long time (1 second)
     113            (True, (5/3 : -1/3 : 1))
     114       
     115        """
     116        if read_cache:
     117            if self._rational_point is not None:
     118                if point or obstruction:
     119                    return True, self._rational_point
     120                else:
     121                    return True
     122            if self._local_obstruction is not None:
     123                if point or obstruction:
     124                    return False, self._local_obstruction
     125                else:
     126                    return False
     127            if (not point) and self._finite_obstructions == [] and \
     128               self._infinite_obstructions == []:
     129                if obstruction:
     130                    return True, None
     131                return True
     132        B = self.base_ring()
     133        if algorithm == 'default':
     134            ret = self.has_rational_point(point = False, obstruction = True,
     135                                          algorithm = 'local')
     136            if ret[0]:
     137                if point:
     138                    ret = self.has_rational_point(point = True,
     139                                                  obstruction = False,
     140                                                  algorithm = 'rnfisnorm')
     141                    if not ret[0]:
     142                        raise RuntimeError, "Outputs of algorithms in " \
     143                                            "has_rational_point disagree for " \
     144                                            "conic %s" % self
     145                    return ret
     146                if obstruction:
     147                    return True, None
     148                return True
     149            if point or obstruction:
     150                return ret
     151            return False
     152        if algorithm == 'all':
     153            ret = []
     154            ret.append(self.has_rational_point(obstruction = True,
     155                                               algorithm = 'local',
     156                                               read_cache = False))
     157            ret.append(self.has_rational_point(point = True,
     158                                               algorithm = 'rnfisnorm',
     159                                               read_cache = False))
     160            if all([r[0] for r in ret]):
     161                if point or obstruction:
     162                    return [a for a in ret if a[1] != None][0]
     163                return True
     164            if all([not r[0] for r in ret]):
     165                if point or obstruction:
     166                    return [a for a in ret if a[1] != None][0]
     167                return False
     168            raise RuntimeError, "Bug in has_rational_point: different " \
     169                                "algorithms yield different outputs for conic " \
     170                                "self (=%s)" % self
     171        if algorithm == 'local':
     172            if point:
     173                raise ValueError, "Algorithm local cannot be combined with " \
     174                                  "point = True in has_rational_point"
     175            obs = self.local_obstructions(infinite = True, finite = False,
     176                                          read_cache = read_cache)
     177            if obs != []:
     178                if obstruction:
     179                    return False, obs[0]
     180                return False
     181            obs = self.local_obstructions(read_cache = read_cache)
     182            if obs == []:
     183                if obstruction:
     184                    return True, None
     185                return True
     186            if obstruction:
     187                return False, obs[0]
     188            return False
     189        if algorithm == 'rnfisnorm':
     190            if obstruction:
     191                raise ValueError, "Algorithm rnfisnorm cannot be combined with " \
     192                                  "obstruction = True in has_rational_point"
     193            D, T = self.diagonal_matrix()
     194            abc = [D[0,0], D[1,1], D[2,2]]
     195            for j in range(3):
     196                if abc[j] == 0:
     197                    pt = self.point(T*vector({2:0,j:1}))
     198                    if point or obstruction:
     199                        return True, pt
     200                    return True
     201            if (-abc[1]/abc[0]).is_square():
     202                pt = self.point(T*vector([1, (-abc[1]/abc[0]).sqrt(), 0]))
     203                if point or obstruction:
     204                    return True, pt
     205                return True
     206            if is_RationalField(B):
     207                K = B
     208                [KtoB, BtoK] = [K.hom(K) for _ in range(2)]
     209            elif is_NumberField(B):
     210                K = B.absolute_field('Y')
     211                [KtoB, BtoK] = K.structure()
     212            else:
     213                raise TypeError, "Algorithm rnfisnorm is only for QQ and number " \
     214                                 "fields, not for %s" % B
     215            from rnfisnorm import rnfisnorm
     216            isnorm = rnfisnorm(BtoK(-abc[1]/abc[0]), BtoK(-abc[2]/abc[0]))
     217            if isnorm[0]:
     218                pt = self.point(T*vector([KtoB(isnorm[1][0]),
     219                                          KtoB(isnorm[1][1]), 1]))
     220                if point:
     221                    return True, pt
     222                return True
     223            if point:
     224                return False, None
     225            return False       
     226        if algorithm == 'qfsolve':
     227            raise TypeError, "Algorithm qfsolve in has_rational_point only " \
     228                                 "for conics over QQ, not over %s" % B
     229        raise ValueError, "Unknown algorithm %s in has_rational_point for %s" \
     230                          % algorithm, self
     231
     232    def is_locally_solvable(self, p):
     233        r"""
     234        Returns True if and only if self has a solution over the completion
     235        of the base field `B` of self at `p`. Here `p` is a finite prime
     236        or infinite place of `B`.
     237
     238        EXAMPLES::
     239
     240            sage: _.<x> = QQ[]
     241            sage: K.<a> = NumberField(x^3 + 5)
     242            sage: C = Conic(K, [1, 2, 3 - a])
     243            sage: [p1, p2] = K.places()
     244            sage: C.is_locally_solvable(p1)
     245            False
     246            sage: C.is_locally_solvable(p2)
     247            True
     248            sage: O = K.maximal_order()
     249            sage: f = (2*O).factor(); f
     250            (Fractional ideal (-a^2 - a + 1)) * (Fractional ideal (a^2 - 2*a + 3))
     251            sage: C.is_locally_solvable(f[0][0])
     252            True
     253            sage: C.is_locally_solvable(f[1][0])
     254            False
     255        """
     256        B = self.base_ring()
     257        D, T = self.diagonal_matrix()
     258        abc = [D[j, j] for j in range(3)]
     259        if abc[2] == 0:
     260            return True
     261        a = -abc[0]/abc[2]
     262        b = -abc[1]/abc[2]
     263        from sage.rings.arith import generalized_hilbert_symbol
     264        if is_RingHomomorphism(p):
     265                   
     266            def generalized_infinite_hilbert_symbol(a, b, p):
     267                one = ZZ(1)
     268                zero = ZZ(0)
     269                if is_RealField(p.codomain()):
     270                    if a == 0 or b == 0:
     271                        return zero
     272                    if p(a) > 0 or p(b) > 0:
     273                        return one
     274                    return -one
     275                if is_ComplexField(p.codomain()):
     276                    if all([im.is_real() for im in p.im_gens()]):
     277                        raise TypeError, "Could not determine whether the place p " \
     278                                         "(= %s) is real or complex in " \
     279                                         "is_locally_solvable" % p
     280                    if a == 0 or b == 0:
     281                        return zero
     282                    return one
     283                raise ValueError, "p (=%s) must be a prime or infinite place in is_locally_solvable" % p
     284               
     285            hs = generalized_infinite_hilbert_symbol(a, b, p)
     286        else:
     287            hs = generalized_hilbert_symbol(a, b, p)
     288        if hs == -1:
     289            if self._local_obstruction == None:
     290                self._local_obstruction = p
     291            return False
     292        return True
     293
     294
  • new file sage/schemes/plane_conics/con_prime_finite_field.py

    diff -r 510cd246e899 -r dd59f5b6d61d sage/schemes/plane_conics/con_prime_finite_field.py
    - +  
     1r"""
     2Projective plane conics over prime finite fields.
     3
     4AUTHORS:
     5
     6- Marco Streng (2009-08-07)
     7
     8- Nick Alexander (2008-01-08)
     9
     10"""
     11#*****************************************************************************
     12#       Copyright (C) 2008 Nick Alexander <ncalexander@gmail.com>
     13#       Copyright (C) 2009 Marco Streng <marco.streng@gmail.com>
     14#
     15#  Distributed under the terms of the GNU General Public License (GPL)
     16#
     17#    This code is distributed in the hope that it will be useful,
     18#    but WITHOUT ANY WARRANTY; without even the implied warranty of
     19#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     20#    General Public License for more details.
     21#
     22#  The full text of the GPL is available at:
     23#
     24#                  http://www.gnu.org/licenses/
     25#*****************************************************************************
     26
     27from sage.libs.pari.gen import pari
     28from sage.misc.all import add, sage_eval
     29from sage.rings.all import (PolynomialRing, ZZ, QQ, MPolynomialRing,
     30                            degree_lowest_rational_function,
     31                            is_PrimeField, is_FiniteField,
     32                            is_ComplexField, is_RealField,
     33                            is_pAdicField, is_Field,
     34                            is_RationalField)
     35from sage.modules.free_module_element import vector
     36from sage.structure.sequence import Sequence
     37from sage.structure.element import is_Vector
     38from sage.schemes.generic.projective_space import (ProjectiveSpace,
     39                                                   is_ProjectiveSpace)
     40from sage.matrix.constructor import Matrix
     41from sage.matrix.matrix import is_Matrix
     42
     43from sage.schemes.plane_curves.curve import Curve_generic_projective
     44from sage.schemes.plane_curves.projective_curve import ProjectiveCurve_prime_finite_field
     45from sage.quadratic_forms.qfsolve import Qfsolve, Qfparam
     46
     47from con_finite_field import ProjectiveConic_finite_field
     48
     49class ProjectiveConic_prime_finite_field(ProjectiveConic_finite_field, ProjectiveCurve_prime_finite_field):
     50    def __init__(self, A, f):
     51        ProjectiveConic_finite_field.__init__(self, A, f)
     52        ProjectiveCurve_prime_finite_field.__init__(self, A, f)
     53
     54
  • new file sage/schemes/plane_conics/con_rational_field.py

    diff -r 510cd246e899 -r dd59f5b6d61d sage/schemes/plane_conics/con_rational_field.py
    - +  
     1r"""
     2Projective plane conics over QQ.
     3
     4AUTHORS:
     5
     6- Marco Streng (2009-08-07)
     7
     8- Nick Alexander (2008-01-08)
     9
     10"""
     11#*****************************************************************************
     12#       Copyright (C) 2008 Nick Alexander <ncalexander@gmail.com>
     13#       Copyright (C) 2009 Marco Streng <marco.streng@gmail.com>
     14#
     15#  Distributed under the terms of the GNU General Public License (GPL)
     16#
     17#    This code is distributed in the hope that it will be useful,
     18#    but WITHOUT ANY WARRANTY; without even the implied warranty of
     19#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     20#    General Public License for more details.
     21#
     22#  The full text of the GPL is available at:
     23#
     24#                  http://www.gnu.org/licenses/
     25#*****************************************************************************
     26
     27from sage.libs.pari.gen import pari
     28from sage.misc.all import add, sage_eval
     29from sage.rings.all import (PolynomialRing, ZZ, QQ, RR, MPolynomialRing,
     30                            degree_lowest_rational_function,
     31                            is_PrimeField, is_FiniteField,
     32                            is_ComplexField, is_RealField,
     33                            is_pAdicField, is_Field,
     34                            is_RationalField, is_RingHomomorphism)
     35from sage.modules.free_module_element import vector
     36from sage.structure.sequence import Sequence
     37from sage.structure.element import is_Vector
     38from sage.schemes.generic.projective_space import (ProjectiveSpace,
     39                                                   is_ProjectiveSpace)
     40from sage.matrix.constructor import Matrix
     41from sage.matrix.matrix import is_Matrix
     42
     43from sage.schemes.plane_curves.curve import Curve_generic_projective
     44from sage.schemes.plane_curves.projective_curve import ProjectiveCurve_generic
     45from sage.quadratic_forms.qfsolve import Qfsolve, Qfparam
     46
     47from con_number_field import ProjectiveConic_number_field
     48
     49from sage.structure.element import is_InfinityElement
     50
     51class ProjectiveConic_rational_field(ProjectiveConic_number_field):
     52    def __init__(self, A, f):
     53        ProjectiveConic_number_field.__init__(self, A, f)
     54
     55
     56    def has_rational_point(self, point = False, obstruction = False,
     57                           algorithm = 'default', read_cache = True):
     58        r"""
     59        Returns True if and only if self has a point defined over `QQ`.
     60
     61        If point or obstruction is True, then returns a second output S:
     62        - if point is True and self has a rational point,
     63          then S is a rational point;
     64        - if obstruction is True, self has no rational point,
     65          then S is a prime or infinite place
     66          of the base ring such that no rational point exists
     67          over the localization at S.
     68       
     69        Points and obstructions are cached, whenever they are found.
     70        If read_cache is True,
     71        then cached information is used for the output if available.
     72       
     73        ALGORITHM:
     74           
     75            The parameter ``algorithm``
     76            specifies the algorithm to be used:
     77           
     78                ``qfsolve``   - Use Denis Simon's Qfsolve (only over `\QQ)
     79                ``rnfisnorm`` - Use PARI's rnfisnorm (cannot be combined with
     80                                obstruction = True)
     81                ``local``     - Check if a local solution exists for all primes
     82                                and infinite places of K (cannot be combined with
     83                                point = True)
     84                ``default``   - Use ``qfsolve`` over `\QQ`. Use ``local`` over
     85                                other number fields. If the output is True and
     86                                point is True, then use ``rnfisnorm`` to find
     87                                the point.
     88                ``all``       - Use all applicable algorithms, check that the
     89                                outputs agree, and return the common answer.
     90           
     91        EXAMPLES:
     92
     93            sage: C = Conic(QQ, [1, 2, -3])
     94            sage: C.has_rational_point(point = True, obstruction = True)
     95            (True, (-1 : -1 : 1))
     96            sage: D = Conic(QQ, [1, 3, -5])
     97            sage: D.has_rational_point(point = True, obstruction = True, \
     98                                       algorithm = 'all')
     99            (False, 3)
     100
     101        The following would not terminate quickly with algorithm = 'rnfisnorm' ::
     102
     103            sage: C = Conic(QQ, [1, 113922743, -310146482690273725409])
     104            sage: C.has_rational_point(point = True)
     105            (True, (-76842858034579/5424 : -5316144401/5424 : 1))
     106            sage: C.has_rational_point(algorithm = 'local', read_cache = False)
     107            True
     108
     109        """
     110        if read_cache:
     111            if self._rational_point is not None:
     112                if point or obstruction:
     113                    return True, self._rational_point
     114                else:
     115                    return True
     116            if self._local_obstruction is not None:
     117                if point or obstruction:
     118                    return False, self._local_obstruction
     119                else:
     120                    return False
     121            if (not point) and self._finite_obstructions == [] and \
     122               self._infinite_obstructions == []:
     123                if obstruction:
     124                    return True, None
     125                return True
     126        if algorithm == 'default':
     127            algorithm = 'qfsolve'
     128        if algorithm == 'all':
     129            ret = []
     130            ret.append(self.has_rational_point(point = True,
     131                                               obstruction = True,
     132                                               algorithm = 'qfsolve',
     133                                               read_cache = False))
     134            ret.append(self.has_rational_point(obstruction = True,
     135                                               algorithm = 'local',
     136                                               read_cache = False))
     137            ret.append(self.has_rational_point(point = True,
     138                                               algorithm = 'rnfisnorm',
     139                                               read_cache = False))
     140            if all([r[0] for r in ret]):
     141                if point or obstruction:
     142                    return [a for a in ret if a[1] != None][0]
     143                return True
     144            if all([not r[0] for r in ret]):
     145                if point or obstruction:
     146                    return [a for a in ret if a[1] != None][0]
     147                return False
     148            raise RuntimeError, "Bug in has_rational_point: different " \
     149                                "algorithms yield different outputs for conic " \
     150                                "self (=%s)" % self
     151        if algorithm == 'qfsolve':                       
     152            from sage.quadratic_forms.qfsolve import Qfsolve
     153            from sage.rings.arith import lcm
     154            M = self.symmetric_matrix()
     155            M *= lcm([ t.denominator() for t in M.list() ])
     156            pt = Qfsolve(M)
     157            if pt in ZZ:
     158                if pt == -1:
     159                    pt = QQ.embeddings(RR)[0]
     160                if self._local_obstruction == None:
     161                    self._local_obstruction = pt
     162                if point or obstruction:
     163                    return False, pt
     164                return False
     165            pt = self.point([pt[0], pt[1], pt[2]])
     166            if point or obstruction:
     167                return True, pt
     168            return True
     169        return ProjectiveConic_number_field.has_rational_point(self, point = point, \
     170                                            obstruction = obstruction, \
     171                                            algorithm = algorithm, \
     172                                            read_cache = read_cache)
     173                                           
     174    def is_locally_solvable(self, p):
     175        r"""
     176        Returns True if and only if self has a solution over the
     177        p-adic numbers.. Here `p` is a prime number or equals
     178        -1, infinity, or `\RR` to denote the infinite place.
     179
     180        EXAMPLES:
     181       
     182        ::
     183
     184            sage: C = Conic(QQ, [1,2,3])
     185            sage: C.is_locally_solvable(-1)
     186            False
     187            sage: C.is_locally_solvable(2)
     188            False
     189            sage: C.is_locally_solvable(3)
     190            True
     191            sage: C.is_locally_solvable(QQ.hom(RR))
     192            False
     193            sage: D = Conic(QQ, [1, 2, -3])
     194            sage: D.is_locally_solvable(infinity)
     195            True
     196            sage: D.is_locally_solvable(RR)
     197            True           
     198
     199        """
     200        D, T = self.diagonal_matrix()
     201        abc = [D[j, j] for j in range(3)]
     202        if abc[2] == 0:
     203            return True
     204        a = -abc[0]/abc[2]
     205        b = -abc[1]/abc[2]
     206        from sage.rings.arith import hilbert_symbol
     207        if is_RealField(p) or is_InfinityElement(p):
     208            p = -1
     209        elif is_RingHomomorphism(p):
     210            if p.domain == QQ and is_RealField(p.codomain):
     211                p = -1
     212            else:
     213                raise TypeError, "p (=%s) needs to be a prime of base field " \
     214                                     "B ( =`QQ`) in is_locally_solvable" % p
     215        if hilbert_symbol(a, b, p) == -1:
     216            if self._local_obstruction == None:
     217                self._local_obstruction = p
     218            return False
     219        return True
     220
  • deleted file sage/schemes/plane_conics/conic_solve.py

    diff -r 510cd246e899 -r dd59f5b6d61d sage/schemes/plane_conics/conic_solve.py
    + -  
    1 r"""
    2 Find rational points on plane conics over fields.
    3 
    4 AUTHORS:
    5 
    6 - Marco Streng (2009-08-07)
    7 
    8 - Nick Alexander (2008-01-08)
    9 
    10 """
    11 #*****************************************************************************
    12 #       Copyright (C) 2008 Nick Alexander <ncalexander@gmail.com>
    13 #       Copyright (C) 2009 Marco Streng <marco.streng@gmail.com>
    14 #
    15 #  Distributed under the terms of the GNU General Public License (GPL)
    16 #
    17 #    This code is distributed in the hope that it will be useful,
    18 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
    19 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    20 #    General Public License for more details.
    21 #
    22 #  The full text of the GPL is available at:
    23 #
    24 #                  http://www.gnu.org/licenses/
    25 #*****************************************************************************
    26 
    27 from sage.rings.all import (PolynomialRing, ZZ, is_FiniteField,
    28                             is_ComplexField, is_RealField,
    29                             is_pAdicField, is_RationalField,
    30                             is_NumberField, RR, is_RingHomomorphism)
    31 from sage.modules.free_module_element import vector
    32 from sage.structure.sequence import Sequence
    33 from sage.schemes.generic.projective_space import ProjectiveSpace
    34 from sage.matrix.constructor import Matrix
    35 
    36 
    37 
    38 
    39 def has_rational_point(self, point = False, obstruction = False,
    40                        algorithm = 'default', read_cache = True):
    41     r"""
    42     Returns True if and only if self has a point defined over its base field B.
    43 
    44     If point or obstruction is True, then returns a second output S:
    45     - if point is True and self has a rational point,
    46       then S is a rational point;
    47     - if obstruction is True, self has no rational point, and the base
    48       ring is a global field, then S is a prime or infinite place
    49       of the base ring such that no rational point exists
    50       over the localization at S.
    51    
    52     Points and obstructions are cached, even if they are not returned as
    53     output, but only if the algorithm finds them. If read_cache is True,
    54     then cached information is used for the output if available.
    55    
    56     ALGORITHM:
    57        
    58         If the base field is finite, try random y-coordinates.
    59        
    60         If the base field is a number field, the parameter ``algorithm``
    61         specifies the algorithm to be used:
    62        
    63             ``qfsolve``   - Use Denis Simon's Qfsolve (only over `\QQ)
    64             ``rnfisnorm`` - Use PARI's rnfisnorm (cannot be combined with
    65                             obstruction = True)
    66             ``local``     - Check if a local solution exists for all primes
    67                             and infinite places of K (cannot be combined with
    68                             point = True)
    69             ``default``   - Use ``qfsolve`` over `\QQ`. Use ``local`` over
    70                             other number fields. If the output is True and
    71                             point is True, then use ``rnfisnorm`` to find
    72                             the point.
    73             ``all``       - Use all applicable algorithms, check that the
    74                             outputs agree, and return the common answer.
    75        
    76     EXAMPLES:
    77 
    78     Examples over QQ ::
    79 
    80         sage: C = Conic(QQ, [1, 2, -3])
    81         sage: C.has_rational_point(point = True, obstruction = True)
    82         (True, (-1 : -1 : 1))
    83         sage: D = Conic(QQ, [1, 3, -5])
    84         sage: D.has_rational_point(point = True, obstruction = True, \
    85                                    algorithm = 'all')
    86         (False, 3)
    87 
    88     The following would not terminate quickly with algorithm = 'rnfisnorm' ::
    89 
    90         sage: C = Conic(QQ, [1, 113922743, -310146482690273725409])
    91         sage: C.has_rational_point(point = True)
    92         (True, (-76842858034579/5424 : -5316144401/5424 : 1))
    93         sage: C.has_rational_point(algorithm = 'local', read_cache = False)
    94         True
    95 
    96     Examples over number fields ::
    97        
    98         sage: K.<i> = QuadraticField(-1)
    99         sage: C = Conic(K, [1, 3, -5])
    100         sage: C.has_rational_point(point = True, obstruction = True, \
    101                                    algorithm = 'all')
    102         (False, Fractional ideal (-i - 2))
    103 
    104         sage: _.<x> = QQ[]
    105         sage: L.<b> = NumberField(x^3-5)
    106         sage: C = Conic(L, [1, 2, -3])
    107         sage: C.has_rational_point(point = True, obstruction = True, \
    108                                    algorithm = 'all') # long time (1 second)
    109         (True, (5/3 : -1/3 : 1))
    110    
    111     Examples over finite fields ::
    112    
    113         sage: Conic(FiniteField(37), [1, 2, 3, 4, 5, 6]).has_rational_point()
    114         True
    115        
    116         sage: C = Conic(FiniteField(2), [1, 1, 1, 1, 1, 0]); C
    117         Projective Conic Curve over Finite Field of size 2 defined by x^2 + x*y + y^2 + x*z + y*z
    118         sage: C.has_rational_point(point = True)  # output is random
    119         (True, (0 : 0 : 1))
    120        
    121         sage: p = next_prime(10^50)
    122         sage: F = FiniteField(p)
    123         sage: C = Conic(F, [1, 2, 3]); C
    124         Projective Conic Curve over Finite Field of size 100000000000000000000000000000000000000000000000151 defined by x^2 + 2*y^2 + 3*z^2
    125         sage: C.has_rational_point(point = True)  # output is random
    126         (True,
    127          (14971942941468509742682168602989039212496867586852 : 75235465708017792892762202088174741054630437326388 : 1)
    128  
    129         sage: F.<a> = FiniteField(7^20)
    130         sage: C = Conic([1, a, -5]); C
    131         Projective Conic Curve over Finite Field in a of size 7^20 defined by x^2 + (a)*y^2 + 2*z^2
    132         sage: C.has_rational_point(point = True)  # output is random
    133         (True,
    134          (a^18 + 2*a^17 + 4*a^16 + 6*a^13 + a^12 + 6*a^11 + 3*a^10 + 4*a^9 + 2*a^8 + 4*a^7 + a^6 + 4*a^4 + 6*a^2 + 3*a + 6 : 5*a^19 + 5*a^18 + 5*a^17 + a^16 + 2*a^15 + 3*a^14 + 4*a^13 + 5*a^12 + a^11 + 3*a^10 + 2*a^8 + 3*a^7 + 4*a^6 + 4*a^5 + 6*a^3 + 5*a^2 + 2*a + 4 : 1))
    135          
    136     Examples over real and complex fields ::
    137 
    138         sage: Conic(RR, [1, 1, 1]).has_rational_point()
    139         False
    140         sage: Conic(CC, [1, 1, 1]).has_rational_point()
    141         True
    142        
    143         sage: Conic(RR, [1, 2, -3]).has_rational_point(point = True)
    144         (True, (1.73205080756888 : 0.000000000000000 : 1.00000000000000))
    145     """
    146     if read_cache:
    147         if self._rational_point is not None:
    148             if point or obstruction:
    149                 return True, self._rational_point
    150             else:
    151                 return True
    152         if self._local_obstruction is not None:
    153             if point or obstruction:
    154                 return False, self._local_obstruction
    155             else:
    156                 return False
    157         if (not point) and self._finite_obstructions == [] and \
    158            self._infinite_obstructions == []:
    159             return True
    160     B = self.base_ring()
    161     if algorithm == 'default':
    162         if is_RationalField(B):
    163             algorithm = 'qfsolve'
    164         elif is_NumberField(B):
    165             ret = self.has_rational_point(point = False, obstruction = True,
    166                                           algorithm = 'local')
    167             if ret[0]:
    168                 if point:
    169                     ret = self.has_rational_point(point = True,
    170                                                   obstruction = False,
    171                                                   algorithm = 'rnfisnorm')
    172                     if not ret[0]:
    173                         raise RuntimeError, "Outputs of algorithms in " \
    174                                             "has_rational_point disagree for " \
    175                                             "conic %s" % self
    176                     return ret
    177                 if obstruction:
    178                     return True, None
    179                 return True
    180             if point or obstruction:
    181                 return ret
    182             return False
    183     if algorithm == 'all':
    184         ret = []
    185         if is_RationalField(B):
    186             ret.append(self.has_rational_point(point = True,
    187                                                obstruction = True,
    188                                                algorithm = 'qfsolve',
    189                                                read_cache = False))
    190         if is_NumberField(B):
    191             ret.append(self.has_rational_point(obstruction = True,
    192                                                algorithm = 'local',
    193                                                read_cache = False))
    194             ret.append(self.has_rational_point(point = True,
    195                                                algorithm = 'rnfisnorm',
    196                                                read_cache = False))
    197         if all([r[0] for r in ret]):
    198             if point or obstruction:
    199                 return [a for a in ret if a[1] != None][0]
    200             return True
    201         if all([not r[0] for r in ret]):
    202             if point or obstruction:
    203                 return [a for a in ret if a[1] != None][0]
    204             return False
    205         raise RuntimeError, "Bug in has_rational_point: different " \
    206                             "algorithms yield different outputs for conic " \
    207                             "self (=%s)" % self
    208     if algorithm == 'qfsolve':
    209         if not is_RationalField(B):
    210             raise TypeError, "Algorithm qfsolve in has_rational_point only " \
    211                              "for conics over QQ, not over %s" % B
    212         from sage.quadratic_forms.qfsolve import Qfsolve
    213         from sage.rings.arith import lcm
    214         M = self.symmetric_matrix()
    215         M *= lcm([ t.denominator() for t in M.list() ])
    216         pt = Qfsolve(M)
    217         if pt in ZZ:
    218             if pt == -1:
    219                 pt = B.embeddings(RR)[0]
    220             if self._local_obstruction == None:
    221                 self._local_obstruction = pt
    222             if point or obstruction:
    223                 return False, pt
    224             return False
    225         pt = self.point([pt[0], pt[1], pt[2]])
    226         if point or obstruction:
    227             return True, pt
    228         return True
    229     if algorithm == 'local':
    230         if point:
    231             raise ValueError, "Algorithm local cannot be combined with " \
    232                               "point = True in has_rational_point"
    233         obs = self.local_obstructions(infinite = True, finite = False,
    234                                       read_cache = read_cache)
    235         if obs != []:
    236             if obstruction:
    237                 return False, obs[0]
    238             return False
    239         obs = self.local_obstructions(read_cache = read_cache)
    240         if obs == []:
    241             if obstruction:
    242                 return True, None
    243             return True
    244         if obstruction:
    245             return False, obs[0]
    246         return False
    247     if algorithm == 'rnfisnorm':
    248         if obstruction:
    249             raise ValueError, "Algorithm rnfisnorm cannot be combined with " \
    250                               "obstruction = True in has_rational_point"
    251         D, T = self.diagonal_matrix()
    252         abc = [D[0,0], D[1,1], D[2,2]]
    253         for j in range(3):
    254             if abc[j] == 0:
    255                 pt = self.point(T*vector({2:0,j:1}))
    256                 if point or obstruction:
    257                     return True, pt
    258                 return True
    259         if (-abc[1]/abc[0]).is_square():
    260             pt = self.point(T*vector([1, (-abc[1]/abc[0]).sqrt(), 0]))
    261             if point or obstruction:
    262                 return True, pt
    263             return True
    264         if is_RationalField(B):
    265             K = B
    266             [KtoB, BtoK] = [K.hom(K) for _ in range(2)]
    267         elif is_NumberField(B):
    268             K = B.absolute_field('Y')
    269             [KtoB, BtoK] = K.structure()
    270         else:
    271             raise TypeError, "Algorithm rnfisnorm is only for QQ and number " \
    272                              "fields, not for %s" % B
    273         from rnfisnorm import rnfisnorm
    274         isnorm = rnfisnorm(BtoK(-abc[1]/abc[0]), BtoK(-abc[2]/abc[0]))
    275         if isnorm[0]:
    276             pt = self.point(T*vector([KtoB(isnorm[1][0]),
    277                                       KtoB(isnorm[1][1]), 1]))
    278             if point:
    279                 return True, pt
    280             return True
    281         if point:
    282             return False, None
    283         return False       
    284     if is_FiniteField(B):
    285         if point:
    286             s, pt = self.has_singular_point(point = True)
    287             if s:
    288                 return True, pt
    289             while True:
    290                 x = B.random_element()
    291                 Y = PolynomialRing(B,'Y').gen()
    292                 r = self.defining_polynomial()([x,Y,1]).roots()
    293                 if len(r) > 0:
    294                     return True, self.point([x,r[0][0],B(1)])
    295         if obstruction:
    296             return True, None
    297         return True
    298     if is_ComplexField(B):
    299         if point:
    300             [_,_,_,d,e,f] = self._coefficients
    301             if d == 0:
    302                 return True, self.point([0,1,0])
    303             return True, self.point([0, ((e**2-4*d*f).sqrt()-e)/(2*d), 1],
    304                                     check = False)
    305         if obstruction:
    306             return True, None
    307         return True
    308     if is_RealField(B):
    309         D, T = self.diagonal_matrix()
    310         [a, b, c] = [D[0,0], D[1,1], D[2,2]]
    311         if a == 0:
    312             ret = True, self.point(T*vector([1,0,0]), check = False)
    313         elif a*c <= 0:
    314             ret = True, self.point(T*vector([(-c/a).sqrt(),0,1]),
    315                                    check = False)
    316         elif b == 0:
    317             ret = True, self.point(T*vector([0,1,0]), check = False)
    318         elif b*c <= 0:
    319             ret = True, self.point(T*vector([0,(-c/b).sqrt(),0,1]),
    320                                    check = False)
    321         else:
    322             ret = False, None
    323         if point or obstruction:
    324             return ret
    325         return ret[0]
    326     raise NotImplementedError, "has_rational_point not implemented for " \
    327                                "conics over base field %s" % B
    328 
    329 def is_locally_solvable(self, p):
    330     r"""
    331     Returns True if and only if self has a solution over the completion
    332     of the base field `B` of self at `p`. Here `p` is a finite prime
    333     or infinite place of `B`.
    334 
    335     If `B` is `QQ`, then `p=-1` can be used to denote the infinite place.
    336 
    337     EXAMPLES:
    338 
    339     An example over QQ ::
    340 
    341         sage: C = Conic(QQ, [1,2,3])
    342         sage: C.is_locally_solvable(-1)
    343         False
    344         sage: C.is_locally_solvable(2)
    345         False
    346         sage: C.is_locally_solvable(3)
    347         True
    348 
    349     Example over a number field ::
    350 
    351         sage: _.<x> = QQ[]
    352         sage: K.<a> = NumberField(x^3 + 5)
    353         sage: C = Conic(K, [1, 2, 3 - a])
    354         sage: [p1, p2] = K.places()
    355         sage: C.is_locally_solvable(p1)
    356         False
    357         sage: C.is_locally_solvable(p2)
    358         True
    359         sage: O = K.maximal_order()
    360         sage: f = (2*O).factor(); f
    361         (Fractional ideal (-a^2 - a + 1)) * (Fractional ideal (a^2 - 2*a + 3))
    362         sage: C.is_locally_solvable(f[0][0])
    363         True
    364         sage: C.is_locally_solvable(f[1][0])
    365         False
    366     """
    367     B = self.base_ring()
    368     D, T = self.diagonal_matrix()
    369     abc = [D[j, j] for j in range(3)]
    370     if abc[2] == 0:
    371         return True
    372     a = -abc[0]/abc[2]
    373     b = -abc[1]/abc[2]
    374     if is_RationalField(B):
    375         from sage.rings.arith import hilbert_symbol
    376         if is_RingHomomorphism(p):
    377             if p.domain == B and is_RealField(p.codomain):
    378                 p = -1
    379             else:
    380                 raise TypeError, "p (=%s) needs to be a prime of base field " \
    381                                  "B ( =`QQ`) in is_locally_solvable" % p
    382         if hilbert_symbol(a, b, p) == -1:
    383             if self._local_obstruction == None:
    384                 self._local_obstruction = p
    385             return False
    386         return True
    387     if is_NumberField(B):
    388         from sage.rings.arith import generalized_hilbert_symbol
    389         if generalized_hilbert_symbol(a, b, p) == -1:
    390             if self._local_obstruction == None:
    391                 self._local_obstruction = p
    392             return False
    393         return True
    394     raise TypeError, "Base field %s needs to be a number field or the " \
    395                      "rational numbers in is_locally_solvable" % B
    396 
    397 
    398 def local_obstructions(self, finite = True, infinite = True, read_cache = True):
    399     r"""
    400     Returns the sequence of finite primes and/or infinite places
    401     such that self is locally solvable at those primes and places.
    402    
    403     If the base field is `QQ`, then the infinite place is denoted `-1`.
    404 
    405     The parameters finite and infinite (both True by default) are
    406     used to specify whether to look at finite and/or infinite places.
    407     Note that finite = True involves factorization of the determinant
    408     of self, hence may be slow.
    409    
    410     Local obstructions are cached. The parameter read_cache can be used
    411     to specify whether to look at the cache before computing anything.
    412 
    413     EXAMPLES:
    414 
    415     Examples over QQ ::
    416 
    417         sage: Conic(QQ, [1, 1, 1]).local_obstructions()
    418         [2, -1]
    419         sage: Conic(QQ, [1, 2, -3]).local_obstructions()
    420         []
    421         sage: Conic(QQ, [1, 2, 3, 4, 5, 6]).local_obstructions()
    422         [41, -1]
    423 
    424 
    425     Examples over number fields ::
    426 
    427         sage: K.<i> = QuadraticField(-1)
    428         sage: Conic(K, [1, 1, 1]).local_obstructions()
    429         []
    430         sage: Conic(K, [1, 2, -3]).local_obstructions()
    431         []
    432         sage: Conic(K, [1, 2, 3, 4, 5, 6]).local_obstructions()
    433         [Fractional ideal (5*i - 4), Fractional ideal (-5*i - 4)]
    434 
    435         sage: _.<x> = QQ[]
    436         sage: L.<b> = NumberField(x^4-2)
    437         sage: Conic(L, [1, 1, 1]).local_obstructions() # long time (2 seconds)
    438         [Ring morphism:
    439           From: Number Field in b with defining polynomial x^4 - 2
    440           To:   Real Field with 106 bits of precision
    441           Defn: b |--> -1.189207115002721066717492233629, Ring morphism:
    442           From: Number Field in b with defining polynomial x^4 - 2
    443           To:   Real Field with 106 bits of precision
    444           Defn: b |--> 1.189207115002721066717492233629]
    445         sage: Conic(L, [b, 1, 1]).local_obstructions() # long time (2 seconds)
    446         [Fractional ideal (b),
    447          Ring morphism:
    448          From: Number Field in b with defining polynomial x^4 - 2
    449          To:   Real Field with 106 bits of precision
    450          Defn: b |--> 1.189207115002721066717492233629]
    451     """
    452     obs0 = []
    453     obs1 = []
    454     B = self.base_ring()
    455     if infinite:
    456         if read_cache and self._infinite_obstructions != None:
    457             obs0 = self._infinite_obstructions
    458         else:
    459             if is_RationalField(B):
    460                 if not self.is_locally_solvable(-1):
    461                     obs0 = [-1]
    462             elif is_NumberField(B):
    463                 for b in B.places():
    464                     if not self.is_locally_solvable(b):
    465                         obs0.append(b)
    466             else:
    467                 raise TypeError, "Base field (=%s) needs to be QQ or a" \
    468                                  "number field in local_obstructions" % B
    469             self._infinite_obstructions = obs0
    470     if finite:
    471         if read_cache and self._finite_obstructions != None:
    472             obs1 = self._finite_obstructions
    473         else:
    474             candidates = []
    475             if is_RationalField(B):
    476                 if self.determinant() != 0:
    477                     for a in self.symmetric_matrix().list():
    478                         if a != 0:
    479                             for f in a.factor():
    480                                 if f[1] < 0 and not f[0] in candidates:
    481                                     candidates.append(f[0])
    482                     for f in (2*self.determinant()).factor():
    483                         if f[1] > 0 and not f[0] in candidates:
    484                             candidates.append(f[0])
    485             elif is_NumberField(B):
    486                 if self.determinant() != 0:
    487                     O = B.maximal_order()
    488                     for a in self.symmetric_matrix().list():
    489                         if a != 0:
    490                             for f in O.fractional_ideal(a).factor():
    491                                 if f[1] < 0 and not f[0] in candidates:
    492                                     candidates.append(f[0])
    493                     for f in O.fractional_ideal(2*self.determinant()).factor():
    494                         if f[1] > 0 and not f[0] in candidates:
    495                             candidates.append(f[0])       
    496             else:
    497                 raise TypeError, "Base field (=%s) needs to be QQ or a " \
    498                                  "number field in local_obstructions" % B
    499             for b in candidates:
    500                 if not self.is_locally_solvable(b):
    501                    obs1.append(b)
    502             self._infinite_obstructions = obs1
    503     obs = obs1 + obs0
    504     if finite and infinite and len(obs)%2==1:
    505         raise RuntimeError, "Bug in local_obstructions or in " \
    506                             "is_locally_solvable: the number of bad places" \
    507                             "for conic self (=%s) is odd" % self
    508     return obs
    509 
    510 def parametrization(self, point=None, morphism=True):
    511     r"""
    512     Return a parametrization of self and the inverse
    513     of the parametrization.
    514 
    515     If point is specified, then that point is used
    516     for the parametrization. Otherwise, use rational_point
    517     to find a point.
    518        
    519     If morphism is False, then returns the tuples of three
    520     polynomials that give the parametrization.
    521    
    522     Raises ValueError if no rational point exists or self is non-smooth.
    523 
    524     ALGORITHM:
    525    
    526         Uses Denis Simon's Qfparam if the base field is `QQ`.
    527         Gives a straightforward non-optimized parametrization
    528         otherwise.
    529    
    530     EXAMPLES:
    531         sage: R.<x,y,z> = QQ[]
    532         sage: C = Curve(7*x^2 + 2*y*z + z^2)
    533         sage: (p, i) = C.parametrization(morphism = False); (p, i)
    534         ([-2*x*y, 7*x^2 + y^2, -2*y^2], [-1/2*x, -1/2*z])
    535         sage: C.defining_polynomial()(p)
    536         0
    537         sage: i[0](p) / i[1](p)
    538         x/y
    539 
    540         sage: C = Curve(x^2 + 2*y^2 + z^2)
    541         sage: C.parametrization()
    542         Traceback (most recent call last):
    543         ...
    544         ValueError: Conic Projective Conic Curve over Rational Field defined by x^2 + 2*y^2 + z^2 has no rational points over Rational Field!
    545 
    546         sage: C = Curve(x^2 + y^2 + 7*z^2)
    547         sage: C.parametrization()
    548         Traceback (most recent call last):
    549         ...
    550         ValueError: Conic Projective Conic Curve over Rational Field defined by x^2 + y^2 + 7*z^2 has no rational points over Rational Field!
    551 
    552         sage: c = Conic([1,1,-1])
    553         sage: c.param()
    554         (Scheme morphism:
    555           From: Projective Space of dimension 1 over Rational Field
    556           To:   Projective Conic Curve over Rational Field defined by x^2 + y^2 - z^2
    557           Defn: Defined on coordinates by sending (x : y) to
    558                 (2*x*y : x^2 - y^2 : x^2 + y^2),
    559          Scheme morphism:
    560            From: Projective Conic Curve over Rational Field defined by x^2 + y^2 - z^2
    561            To:   Projective Space of dimension 1 over Rational Field
    562            Defn: Defined on coordinates by sending (x : y : z) to
    563                  (1/2*x : -1/2*y + 1/2*z))
    564         sage: c = Conic(GF(2), [1,1,1,1,1,0])
    565         sage: c.param()
    566         (Scheme morphism:
    567           From: Projective Space of dimension 1 over Finite Field of size 2
    568           To:   Projective Conic Curve over Finite Field of size 2 defined by x^2 + x*y
    569         + y^2 + x*z + y*z
    570           Defn: Defined on coordinates by sending (x : y) to
    571                 (x*y + y^2 : x^2 + x*y : x^2 + x*y + y^2),
    572          Scheme morphism:
    573           From: Projective Conic Curve over Finite Field of size 2 defined by x^2 + x*y
    574         + y^2 + x*z + y*z
    575           To:   Projective Space of dimension 1 over Finite Field of size 2
    576           Defn: Defined on coordinates by sending (x : y : z) to
    577                 (y : x))
    578     """
    579     if (not self._parametrization is None) and not point:
    580         par = self._parametrization
    581     else:
    582         if not self.is_smooth():
    583             raise ValueError, "The conic self (=%s) is not smooth, hence does not have a parametrization.", self
    584         if point == None:
    585             point = self.rational_point()
    586         point = Sequence(point)
    587         B = self.base_ring()
    588         Q = PolynomialRing(B, 'x,y')
    589         [x, y] = Q.gens()
    590         gens = self.ambient_space().gens()
    591         if is_RationalField(B):
    592             from sage.quadratic_forms.qfsolve import Qfparam
    593             from sage.rings.arith import lcm
    594             M = self.symmetric_matrix()
    595             M *= lcm([ t.denominator() for t in M.list() ])
    596             par1 = Qfparam(M, point)
    597             B = Matrix([[par1[i][j] for j in range(3)] for i in range(3)])
    598             # self is in the image of B and does not lie on a line,
    599             # hence B is invertible
    600             A = B.inverse()
    601             par2 = [sum([A[i,j]*gens[j] for j in range(3)]) for i in [1,0]]
    602             par = ([Q(pol(x/y)*y**2) for pol in par1], par2)
    603         else:
    604             P = PolynomialRing(B, 4, ['X', 'Y', 'T0', 'T1'])
    605             [X, Y, T0, T1] = P.gens()
    606             c3 = [j for j in range(2,-1,-1) if point[j] != 0][0]
    607             c1 = [j for j in range(3) if j != c3][0]
    608             c2 = [j for j in range(3) if j != c3 and j != c1][0]
    609             L = [0,0,0]
    610             L[c1] = Y*T1*point[c1] + Y*T0
    611             L[c2] = Y*T1*point[c2] + X*T0
    612             L[c3] = Y*T1*point[c3]
    613             bezout = P(self.defining_polynomial()(L) / T0)
    614             t = [bezout([x,y,0,-1]),bezout([x,y,1,0])]
    615             par = (tuple([Q(p([x,y,t[0],t[1]])/y) for  p in L]),
    616                    tuple([gens[m]*point[c3]-gens[c3]*point[m]
    617                        for m in [c2,c1]]))
    618         if self._parametrization is None:
    619             self._parametrization = par
    620     if not morphism:
    621         return par
    622     P1 = ProjectiveSpace(self.base_ring(), 1, 'x,y')
    623     return P1.hom(par[0],self), self.hom(par[1],P1)
    624    
    625                
    626 def rational_point(self, algorithm = 'default', read_cache = True):
    627     r"""Return a rational point (x0, y0, z0) on self.
    628 
    629     Raises ValueError if no rational point exists.
    630 
    631     See has_rational_point(self) for the algorithm used and for the use of
    632     the parameters algorithm and read_cache.
    633      
    634     EXAMPLES:
    635 
    636     Examples over QQ ::
    637    
    638         sage: R.<x,y,z> = QQ[]
    639         sage: C = Curve(7*x^2 + 2*y*z + z^2)
    640         sage: C.rational_point()
    641         (0 : 1 : 0)
    642 
    643         sage: C = Curve(x^2 + 2*y^2 + z^2)
    644         sage: C.rational_point()
    645         Traceback (most recent call last):
    646         ...
    647         ValueError: Conic Projective Conic Curve over Rational Field defined by x^2 + 2*y^2 + z^2 has no rational points over Rational Field!
    648 
    649         sage: C = Curve(x^2 + y^2 + 7*z^2)
    650         sage: C.rational_point(algorithm = 'all')
    651         Traceback (most recent call last):
    652         ...
    653         ValueError: Conic Projective Conic Curve over Rational Field defined by x^2 + y^2 + 7*z^2 has no rational points over Rational Field!
    654 
    655     Examples over number fields ::
    656        
    657         sage: _.<x> = QQ[]
    658         sage: L.<b> = NumberField(x^3-5)
    659         sage: C = Conic(L, [3, 2, -5])
    660         sage: C.rational_point(algorithm = 'all')  # long time (1 second)
    661         (-1 : -1 : 1)
    662    
    663     Examples over finite fields ::
    664    
    665         sage: F.<a> = FiniteField(7^20)
    666         sage: C = Conic([1, a, -5]); C
    667         Projective Conic Curve over Finite Field in a of size 7^20 defined by x^2 + (a)*y^2 + 2*z^2
    668         sage: C.rational_point()  # output is random
    669         (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)
    670          
    671     Examples over real and complex fields ::
    672 
    673         sage: Conic(CC, [1, 2, 3]).rational_point()
    674         (0 : 1.22474487139159*I : 1)
    675 
    676         sage: Conic(RR, [1, 1, 1]).rational_point()
    677         Traceback (most recent call last):
    678         ...
    679         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!
    680     """
    681     bl,pt = self.has_rational_point(point = True, algorithm = algorithm,
    682                                     read_cache = read_cache)
    683     if bl:
    684         return pt
    685     raise ValueError, "Conic %s has no rational points over %s!" % \
    686                       (self, self.ambient_space().base_ring())
    687 
    688    
    689 
  • sage/schemes/plane_conics/constructor.py

    diff -r 510cd246e899 -r dd59f5b6d61d sage/schemes/plane_conics/constructor.py
    a b  
    2727from sage.quadratic_forms.all import is_QuadraticForm
    2828from sage.rings.all import (PolynomialRing, is_MPolynomial,
    2929                            is_MPolynomialRing, is_Ring,
    30                             is_IntegralDomain)
     30                            is_IntegralDomain, is_FiniteField,
     31                            is_PrimeFiniteField,
     32                            is_RationalField)
     33from sage.rings.number_field.number_field import is_NumberField                           
    3134from sage.schemes.generic.all import ProjectiveSpace
    3235from sage.schemes.generic.morphism import (SchemeMorphism_affine_coordinates,
    3336                            SchemeMorphism_projective_coordinates_field)
    3437from sage.structure.all import Sequence
    3538from sage.structure.element import is_Matrix
    3639
    37 from projective_conic import ProjectiveConic_generic
     40from con_field import ProjectiveConic_field
     41from con_finite_field import ProjectiveConic_finite_field
     42from con_prime_finite_field import ProjectiveConic_prime_finite_field
     43from con_global_field import ProjectiveConic_global_field
     44from con_number_field import ProjectiveConic_number_field
     45from con_rational_field import ProjectiveConic_rational_field
    3846
    3947def Conic(base_field, F=None, names=None, unique=True):
    4048    r"""
     
    208216
    209217    if F.parent().ngens() == 3:
    210218        P2 = ProjectiveSpace(2, base_field, names)
    211         return ProjectiveConic_generic(P2, F)
     219        if is_PrimeFiniteField(base_field):
     220            return ProjectiveConic_prime_finite_field(P2, F)
     221        if is_FiniteField(base_field):
     222            return ProjectiveConic_finite_field(P2, F)
     223        if is_RationalField(base_field):
     224            return ProjectiveConic_rational_field(P2, F)
     225        if is_NumberField(base_field):
     226            return ProjectiveConic_number_field(P2, F)
     227        return ProjectiveConic_field(P2, F)
    212228
    213229    raise TypeError, "Number of variables of F (=%s) must be 2 or 3" % F
  • deleted file sage/schemes/plane_conics/projective_conic.py

    diff -r 510cd246e899 -r dd59f5b6d61d sage/schemes/plane_conics/projective_conic.py
    + -  
    1 r"""
    2 Projective plane conics over a field.
    3 
    4 AUTHORS:
    5 
    6 - Marco Streng (2009-08-07)
    7 
    8 - Nick Alexander (2008-01-08)
    9 
    10 """
    11 #*****************************************************************************
    12 #       Copyright (C) 2008 Nick Alexander <ncalexander@gmail.com>
    13 #       Copyright (C) 2009 Marco Streng <marco.streng@gmail.com>
    14 #
    15 #  Distributed under the terms of the GNU General Public License (GPL)
    16 #
    17 #    This code is distributed in the hope that it will be useful,
    18 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
    19 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    20 #    General Public License for more details.
    21 #
    22 #  The full text of the GPL is available at:
    23 #
    24 #                  http://www.gnu.org/licenses/
    25 #*****************************************************************************
    26 
    27 from sage.libs.pari.gen import pari
    28 from sage.misc.all import add, sage_eval
    29 from sage.rings.all import (PolynomialRing, ZZ, QQ, MPolynomialRing,
    30                             degree_lowest_rational_function,
    31                             is_PrimeField, is_FiniteField,
    32                             is_ComplexField, is_RealField,
    33                             is_pAdicField, is_Field,
    34                             is_RationalField)
    35 from sage.modules.free_module_element import vector
    36 from sage.structure.sequence import Sequence
    37 from sage.structure.element import is_Vector
    38 from sage.schemes.generic.projective_space import (ProjectiveSpace,
    39                                                    is_ProjectiveSpace)
    40 from sage.matrix.constructor import Matrix
    41 from sage.matrix.matrix import is_Matrix
    42 
    43 from sage.schemes.plane_curves.curve import Curve_generic_projective
    44 from sage.schemes.plane_curves.projective_curve import ProjectiveCurve_generic
    45 from sage.quadratic_forms.qfsolve import Qfsolve, Qfparam
    46 
    47 
    48 class ProjectiveConic_generic(ProjectiveCurve_generic):
    49     def __init__(self, A, f):
    50         ProjectiveCurve_generic.__init__(self, A, f)
    51         self._coefficients = [f[(2,0,0)], f[(1,1,0)], f[(1,0,1)],
    52                                 f[(0,2,0)], f[(0,1,1)], f[(0,0,2)]]
    53         self._rational_point = None
    54         self._parametrization = None
    55         self._diagonal_matrix = None
    56        
    57         # a single prime such that self has no point over the completion
    58         self._local_obstruction = None
    59         # all finite primes such that self has no point over the completion
    60         self._finite_obstructions = None
    61         # all infinite primes such that self has no point over the completion
    62         self._infinite_obstructions = None
    63 
    64     from conic_solve import (has_rational_point, rational_point,
    65                              parametrization, local_obstructions,
    66                              is_locally_solvable)
    67 
    68     param = parametrization
    69 
    70 
    71     def _repr_type(self):
    72         return "Projective Conic"
    73 
    74     def _vector_(self):
    75         return vector(self.coefficients())
    76 
    77     def base_extend(self, S):
    78         r"""
    79         Returns the conic over `S`, given by the same equation as self.
    80 
    81         EXAMPLES:
    82 
    83         ::
    84 
    85             sage: c = Conic([1, 1, 1]); c
    86             Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^2
    87             sage: c.has_rational_point()
    88             False
    89             sage: d = c.base_extend(QuadraticField(-1, 'i')); d
    90             Projective Conic Curve over Number Field in i with defining polynomial x^2 + 1 defined by x^2 + y^2 + z^2
    91             sage: d.rational_point()
    92             (-i : 1 : 0)
    93         """
    94         if is_Field(S):
    95             B = self.base_ring()
    96             if B == S:
    97                 return self
    98             if not S.has_coerce_map_from(B):
    99                 raise ValueError, "No natural map from the base ring of self " \
    100                                   "(= %s) to S (= %s)" % (self, S)
    101             from constructor import Conic
    102             con = Conic([S(c) for c in self.coefficients()], \
    103                         self.variable_names())
    104             if self._rational_point != None:
    105                 pt = [S(c) for c in Sequence(self._rational_point)]
    106                 if not pt == [0,0,0]:
    107                     _ = con.point(pt)
    108             return con
    109         return ProjectiveCurve_generic.base_extend(self, S)
    110    
    111     def cache_point(self, p):
    112         r"""
    113         Replace the point in the cache of self by `p` for use
    114         by self.rational_point and self.parametrization.
    115        
    116         EXAMPLES:
    117 
    118         ::
    119 
    120             sage: c = Conic([1, -1, 1])
    121             sage: c.point([15, 17, 8])
    122             (15/8 : 17/8 : 1)
    123             sage: c.rational_point()
    124             (15/8 : 17/8 : 1)
    125             sage: c.cache_point(c.rational_point(read_cache = False))
    126             sage: c.rational_point()
    127             (1 : 1 : 0)
    128         """
    129         if isinstance(p, (tuple, list)):
    130             p = self.point(p)
    131         self._rational_point = p
    132 
    133     def coefficients(self):
    134         r"""
    135         Gives a the 6 coefficients of the conic
    136         in lexicographic order.
    137        
    138         EXAMPLES:
    139        
    140         ::
    141        
    142             sage: Conic(QQ, [1,2,3,4,5,6]).coefficients()
    143             [1, 2, 3, 4, 5, 6]
    144 
    145             sage: P.<x,y,z> = GF(13)[]
    146             sage: a = Conic(x^2+5*x*y+y^2+z^2).coefficients(); a
    147             [1, 5, 0, 1, 0, 1]
    148             sage: Conic(a)
    149             Projective Conic Curve over Finite Field of size 13 defined by x^2 + 5*x*y + y^2 + z^2
    150         """
    151         return self._coefficients
    152        
    153     def count_points(self, n):
    154         r"""
    155         If the base field `B` of `self` is finite of order `q`,
    156         then returns the number of points over `GF{q}, ..., GF{q^n}`.
    157        
    158         EXAMPLES:
    159 
    160             sage: P.<x,y,z> = GF(3)[]
    161             sage: c = Conic(x^2+y^2+z^2)
    162             sage: c.count_points(4)
    163             [4, 10, 28, 82]
    164         """       
    165         F = self.base_ring()
    166         if not F.is_finite():
    167             raise TypeError, "Point counting only defined for schemes over " \
    168                              "finite fields, not over the base ring of self " \
    169                              "(= %s)" % self
    170         q = F.cardinality()
    171         return [q**i+1 for i in range(1, n+1)]
    172        
    173     def derivative_matrix(self):
    174         r"""
    175         Gives the derivative of the defining polynomial,
    176         which is a linear map, as a `3 \times 3` matrix.
    177        
    178         Examples:
    179        
    180         In characteristic different from 2, the
    181         derivative matrix is twice the symmetric matrix:
    182 
    183         ::
    184        
    185             sage: c = Conic(QQ, [1,1,1,1,1,0])
    186             sage: c.symmetric_matrix()
    187             [  1 1/2 1/2]
    188             [1/2   1 1/2]
    189             [1/2 1/2   0]
    190             sage: c.derivative_matrix()
    191             [2 1 1]
    192             [1 2 1]
    193             [1 1 0]
    194 
    195         An example in characteristic 2:
    196 
    197         ::
    198 
    199             sage: P.<t> = GF(2)[]
    200             sage: c = Conic([t, 1, t^2, 1, 1, 0]); c
    201             Projective 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*z
    202             sage: c.is_smooth()
    203             True
    204             sage: c.derivative_matrix()
    205             [  0   1 t^2]
    206             [  1   0   1]
    207             [t^2   1   0]
    208         """
    209         from sage.matrix.constructor import matrix
    210         [a,b,c,d,e,f] = self.coefficients()
    211         return matrix([[ 2*a ,   b ,   c ],
    212                        [   b , 2*d ,   e ],
    213                        [   c ,   e , 2*f ]])
    214        
    215     def determinant(self):
    216         r"""
    217         Gives the determinant of the symmetric matrix that defines the conic.
    218         This is defined only if the base field has characteristic different
    219         from 2.
    220 
    221         EXAMPLES:
    222 
    223         ::
    224 
    225             sage: C = Conic([1,2,3,4,5,6])
    226             sage: C.determinant()
    227             41/4
    228             sage: C.symmetric_matrix().determinant()
    229             41/4
    230 
    231         Determinants are only defined in characteristic different from 2::
    232 
    233             sage: C = Conic(GF(2), [1, 1, 1, 1, 1, 0])
    234             sage: C.is_smooth()
    235             True
    236             sage: C.determinant()
    237             Traceback (most recent call last):
    238             ...
    239             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
    240         """
    241         return self.symmetric_matrix().determinant()
    242 
    243     det = determinant
    244 
    245     def diagonal_matrix(self):
    246         r"""
    247         Returns a diagonal matrix `D` and a matrix `T` such that `T^t A T = D`
    248         holds, where `(x, y, z) A (x, y, z)^t` is the defining polynomial
    249         of the conic `self`.
    250 
    251         EXAMPLE:
    252 
    253         ::
    254 
    255             sage: c = Conic(QQ, [1,2,3,4,5,6])
    256             sage: d, t = c.diagonal_matrix(); d, t
    257             ([    1     0     0]
    258             [    0     3     0]
    259             [    0     0 41/12],
    260              [   1   -1 -7/6]
    261              [   0    1 -1/3]
    262              [   0    0    1])
    263             sage: t.transpose()*c.symmetric_matrix()*t
    264             [    1     0     0]
    265             [    0     3     0]
    266             [    0     0 41/12]
    267          
    268         Diagonal matrices are only defined in characteristic different
    269         from 2:
    270        
    271         ::
    272 
    273             sage: c = Conic(GF(4, 'a'), [0, 1, 1, 1, 1, 1])
    274             sage: c.is_smooth()
    275             True
    276             sage: c.diagonal_matrix()
    277             Traceback (most recent call last):
    278             ...
    279             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
    280         """
    281         A = self.symmetric_matrix()
    282         B = self.base_ring()
    283         basis = [vector(B,{2:0,i:1}) for i in range(3)]
    284         for i in range(3):
    285             zerovalue = (basis[i]*A*basis[i].transpose()== 0)
    286             if zerovalue:
    287                 for j in range(i+1,3):
    288                     if basis[j]*A*basis[j].transpose() != 0:
    289                         b = basis[i]
    290                         basis[i] = basis[j]
    291                         basis[j] = b
    292                         zerovalue = False
    293             if zerovalue:
    294                 for j in range(i+1,3):
    295                     if basis[i]*A*basis[j].transpose() != 0:
    296                         basis[i] = basis[i]+basis[j]
    297                         zerovalue = False
    298             if not zerovalue:
    299                 l = (basis[i]*A*basis[i].transpose())
    300                 for j in range(i+1,3):
    301                     basis[j] = basis[j] - \
    302                                (basis[i]*A*basis[j].transpose())/l * basis[i]
    303         T = Matrix(basis).transpose()
    304         return T.transpose()*A*T, T
    305        
    306     def diagonalization(self,names = None):
    307         r"""
    308         Returns a diagonal conic C, an isomorphism of schemes M: C -> self
    309         and the inverse N of M.
    310        
    311         EXAMPLES:
    312        
    313         ::
    314             sage: Conic(GF(5), [1,0,1,1,0,1]).diagonalization()           
    315             (Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2,
    316              Scheme morphism:
    317               From: Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2
    318               To:   Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + x*z + z^2
    319               Defn: Defined on coordinates by sending (x : y : z) to
    320                     (x + 2*z : y : z),
    321              Scheme morphism:
    322               From: Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + x*z + z^2
    323               To:   Projective Conic Curve over Finite Field of size 5 defined by x^2 + y^2 + 2*z^2
    324               Defn: Defined on coordinates by sending (x : y : z) to
    325                     (x - 2*z : y : z))
    326 
    327         The diagonalization is only defined in characteristic different
    328         from 2:
    329        
    330         ::
    331 
    332             sage: Conic(GF(2), [1,1,1,1,1,0]).diagonalization()
    333             Traceback (most recent call last):
    334             ...
    335             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
    336         """
    337         if names == None:
    338             names = self.defining_polynomial().parent().variable_names()
    339         from constructor import Conic
    340         D, T = self.diagonal_matrix()
    341         con = Conic(D, names = names)
    342         return con, con.hom(T, self), self.hom(T.inverse(), con)
    343        
    344     def gens(self):
    345         r"""
    346         Returns the generators of the coordinate ring of self.
    347        
    348         EXAMPLES:
    349             sage: P.<x,y,z> = QQ[]
    350             sage: c = Conic(x^2+y^2+z^2)
    351             sage: c.gens()
    352             (xbar, ybar, zbar)
    353             sage: c.defining_polynomial()(c.gens())
    354             0
    355         """
    356         return self.coordinate_ring().gens()
    357        
    358     def has_singular_point(self, point = False):
    359         r"""
    360         Return True if and only if self has a rational
    361         singular point.
    362        
    363         If point is True, then also return a rational singular
    364         point (or None if no such point exists).
    365        
    366         EXAMPLES:
    367        
    368         ::
    369            
    370             sage: c = Conic(QQ, [1,0,1]); c
    371             Projective Conic Curve over Rational Field defined by x^2 + z^2
    372             sage: c.has_singular_point(point = True)
    373             (True, (0 : 1 : 0))
    374            
    375             sage: P.<x,y,z> = GF(7)[]
    376             sage: e = Conic((x+y+z)*(x-y+2*z)); e
    377             Projective Conic Curve over Finite Field of size 7 defined by x^2 - y^2 + 3*x*z + y*z + 2*z^2
    378             sage: e.has_singular_point(point = True)
    379             (True, (2 : 4 : 1))
    380 
    381             sage: Conic([1, 1, -1]).has_singular_point()
    382             False
    383             sage: Conic([1, 1, -1]).has_singular_point(point = True)
    384             (False, None)
    385 
    386         has_singular_point is not implemented over all fields
    387         of characteristic 2. It is implemented over finite fields.
    388 
    389         ::
    390 
    391             sage: F.<a> = FiniteField(8)
    392             sage: Conic([a, a+1, 1]).has_singular_point(point = True)
    393             (True, (a + 1 : 0 : 1))
    394 
    395             sage: P.<t> = GF(2)[]
    396             sage: C = Conic(P, [t,t,1]); C
    397             Projective 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^2
    398             sage: C.has_singular_point(point = False)
    399             Traceback (most recent call last):
    400             ...
    401             NotImplementedError: Sorry, find singular point on conics not implemented over all fields of characteristic 2.
    402         """
    403         if not point:
    404            ret = self.has_singular_point(point = True)
    405            return ret[0]
    406         B = self.base_ring()
    407         if B.characteristic() == 2:
    408             [a,b,c,d,e,f] = self.coefficients()
    409             if b == 0 and c == 0 and e == 0:
    410                 for i in range(3):
    411                     if [a, d, f][i] == 0:
    412                         return True, self.point(vector(B, {2:0, i:1}))
    413                 if hasattr(a/f, 'is_square') and hasattr(a/f, 'sqrt'):
    414                     if (a/f).is_square():
    415                         return True, self.point([1,0,(a/f).sqrt()])
    416                     if (d/f).is_square():
    417                         return True, self.point([0,1,(d/f).sqrt()])
    418                 raise NotImplementedError, "Sorry, find singular point on conics not implemented over all fields of characteristic 2."
    419             pt = [e, c, b]
    420             if self.defining_polynomial()(pt) == 0:
    421                 return True, self.point(pt)
    422             return False, None
    423         D = self.symmetric_matrix()
    424         if D.det() == 0:
    425             return True, self.point(Sequence(D.right_kernel().gen()))
    426         return False, None
    427 
    428     def hom(self, x, Y=None):
    429         r"""
    430         Return the scheme morphism from self to Y defined by x.
    431         Here x can be a matrix or a sequence of polynomials.
    432         If Y is omitted, then a natural image is found if possible.
    433 
    434         EXAMPLES:
    435        
    436         Morphisms given by matrices. In the first example, Y is omitted,
    437         in the second example, Y is specified.
    438 
    439         ::
    440            
    441             sage: c = Conic([-1, 1, 1])
    442             sage: h = c.hom(Matrix([[1,1,0],[0,1,0],[0,0,1]])); h
    443             Scheme morphism:
    444               From: Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2
    445               To:   Projective Conic Curve over Rational Field defined by -x^2 + 2*x*y + z^2
    446               Defn: Defined on coordinates by sending (x : y : z) to
    447                     (x + y : y : z)
    448             sage: h([-1, 1, 0])
    449             (0 : 1 : 0)
    450 
    451             sage: c = Conic([-1, 1, 1])
    452             sage: d = Conic([4, 1, -1])
    453             sage: c.hom(Matrix([[0, 0, 1/2], [0, 1, 0], [1, 0, 0]]), d)
    454             Scheme morphism:
    455               From: Projective Conic Curve over Rational Field defined by -x^2 + y^2 + z^2
    456                 To:   Projective Conic Curve over Rational Field defined by 4*x^2 + y^2 - z^2
    457                   Defn: Defined on coordinates by sending (x : y : z) to
    458                           (1/2*z : y : x)
    459 
    460         A morphism given by polynomials:
    461 
    462         ::
    463 
    464             sage: c = Conic(GF(13), [-1, 1, 1])
    465             sage: P.<x, y, z> = GF(13)[]
    466             sage: h = c.hom([x + z, y - z], ProjectiveSpace(GF(13), 1)); h
    467             Scheme morphism:
    468               From: Projective Conic Curve over Finite Field of size 13 defined by -x^2 + y^2 + z^2
    469               To:   Projective Space of dimension 1 over Finite Field of size 13
    470               Defn: Defined on coordinates by sending (x : y : z) to
    471                     (x + z : y - z)
    472             sage: h([1, 1, 0])
    473             (1 : 1)
    474             sage: h([1, 0, 1])
    475             (11 : 1)
    476 
    477         A ValueError is raised if the wrong codomain Y is specified:
    478 
    479         ::
    480        
    481             sage: c = Conic([-1, 1, 1])
    482             sage: c.hom(Matrix([[0, 0, 1/2], [0, 1, 0], [1, 0, 0]]), c)
    483             Traceback (most recent call last):
    484             ...
    485             ValueError: The matrix x (= [  0   0 1/2]
    486             [  0   1   0]
    487             [  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)
    488         """
    489         if is_Matrix(x):   
    490             from constructor import Conic
    491             y = x.inverse()
    492             A = y.transpose()*self.matrix()*y
    493             im = Conic(A)
    494             if Y != None:
    495                 q = Y.defining_polynomial()/im.defining_polynomial()
    496                 if not (q.numerator().is_constant()
    497                         and q.denominator().is_constant()):
    498                     raise ValueError, "The matrix x (= %s) does not define a " \
    499                                       "map from self (= %s) to Y (= %s)" % \
    500                                       (x, self, Y)
    501                 im = Y
    502             return self.hom(Sequence(x*vector(self.ambient_space().gens())), im)
    503         return ProjectiveCurve_generic.hom(self, x, Y)           
    504            
    505     def irreducible_components(self):
    506         r"""
    507         Return the irreducible components of this conic, as
    508         subschemes of the same ambient space.
    509        
    510         EXAMPLES:
    511         ::
    512             sage: P.<x,y,z> = GF(7)[]
    513             sage: e = Conic((x+y+z)*(x-y+2*z)); e
    514             Projective Conic Curve over Finite Field of size 7 defined by x^2 - y^2 + 3*x*z
    515             + y*z + 2*z^2
    516            
    517             sage: e.irreducible_components()
    518             [
    519             Closed subscheme of Projective Space of dimension 2 over Finite Field of size 7
    520             defined by:
    521               x - y + 2*z,
    522             Closed subscheme of Projective Space of dimension 2 over Finite Field of size 7
    523             defined by:
    524               x + y + z
    525             ]
    526            
    527             sage: Conic(GF(7), [1,1,1]).irreducible_components()
    528             [Closed subscheme of Projective Space of dimension 2 over Finite Field of size 7
    529              defined by:
    530               x^2 + y^2 + z^2]
    531         """
    532         if self.is_smooth():
    533             return [self.ambient_space().subscheme(self.defining_polynomial())]
    534         return ProjectiveCurve_generic.irreducible_components(self)
    535        
    536     def is_diagonal(self):
    537         r"""
    538         Return True if and only if the conic has the form
    539         `a*x^2 + b*y^2 + c*z^2`.
    540 
    541         EXAMPLES:
    542 
    543         ::
    544 
    545             sage: c=Conic([1,1,0,1,0,1]); c
    546             Projective Conic Curve over Rational Field defined by x^2 + x*y + y^2 + z^2
    547             sage: d,t = c.diagonal_matrix()
    548             sage: c.is_diagonal()
    549             False
    550             sage: c.diagonalization()[0].is_diagonal()
    551             True
    552         """
    553         return all([self.coefficients()[i] == 0 for i in [1,2,4]])
    554 
    555     def is_isomorphic(self, c, isomorphism = False):
    556         r"""
    557         Return True if and only if self is isomorphic to
    558         the conic or projective line c.
    559        
    560         If the parameter isomorphic is True, then also return
    561         an isomorphism from self to c and its inverse.
    562         """
    563         B = self.base_field()
    564         Bc = c.base_field()
    565         if not B == Bc:
    566             raise TypeError, "c (= %s) must be a curve with the same base " \
    567                              "field as self in is_isomorphic" % c
    568         if is_ProjectiveSpace(c) and c.dimension == 1:
    569             if self.has_rational_point():
    570                 if isomorphism:
    571                     par = self.parametrization()
    572                     return True, par[1], par[0]
    573                 return True
    574             if isomorphism:
    575                 return False, None
    576             return False
    577         if not isinstance(c, sage.schemes.plane_curves.projective_curve.
    578                                   ProjectiveConic_generic):
    579             raise TypeError, "c (= %s) must be a conic or projective line in " \
    580                              "is_isomorphic" % c
    581         obs = self.local_obstructions(finite = False)
    582         obsc = c.local_obstructions(finite = False)
    583         if not (all([o in obs for o in obsc]) and
    584                 all([o in obsc for o in obs])):
    585             if isomorphism:
    586                 return False, None
    587             return False
    588         obs = self.local_obstructions()
    589         obsc = c.local_obstructions()
    590         if not (all([o in obs for o in obsc]) and
    591                 all([o in obsc for o in obs])):
    592             if isomorphism:
    593                 return False, None
    594             return False
    595         if isomorphism:
    596             if obs != 0:
    597                 raise NotImplementedError, "Find isomorphism for conics " \
    598                                            "without rational points not " \
    599                                            "yet implemented"
    600             par = self.parametrization()
    601             parc = c.parametrization()
    602             return (True, self.hom([s(par[1].defining_polynomials())
    603                          for s in parc[0]], c),
    604                          c.hom([s(parc[1].defining_polynomials())
    605                          for s in par[1]], self))
    606         return True
    607 
    608     def is_smooth(self):
    609         r"""
    610         Returns True if and only if self is smooth.
    611 
    612         EXAMPLES:
    613 
    614         ::
    615 
    616             sage: Conic([1,-1,0]).is_smooth()
    617             False
    618             sage: Conic(GF(2),[1,1,1,1,1,0]).is_smooth()
    619             True
    620         """
    621         if self.base_ring().characteristic() == 2:
    622             [a,b,c,d,e,f] = self.coefficients()
    623             if b == 0 and c == 0 and e == 0:
    624                 return False
    625             return self.defining_polynomial()([e, c, b]) != 0
    626         return self.determinant() != 0
    627        
    628     def matrix(self):
    629         r"""
    630         Returns a matrix `M` such that `(x, y, z) M (x, y, z)^t`
    631         is the defining equation of self.
    632         The matrix `M` is upper triangular if the base field has
    633         characteristic 2 and symmetric otherwise.
    634 
    635         EXAMPLES:
    636             sage: R.<x, y, z> = QQ[]
    637             sage: C = Conic(x^2 + x*y + y^2 + z^2)
    638             sage: C.matrix()
    639             [  1 1/2   0]
    640             [1/2   1   0]
    641             [  0   0   1]
    642 
    643             sage: R.<x, y, z> = GF(2)[]
    644             sage: C = Conic(x^2 + x*y + y^2 + x*z + z^2)
    645             sage: C.matrix()
    646             [1 1 1]
    647             [0 1 0]
    648             [0 0 1]
    649         """
    650         if self.base_ring().characteristic() == 2:
    651             return self.upper_triangular_matrix()
    652         return self.symmetric_matrix()
    653        
    654     _matrix_ = matrix
    655 
    656     def point(self, v, check=True):
    657         r"""
    658         Constructs a point on self corresponding to the input.
    659        
    660         If no rational point on self is known yet, then also caches the point
    661         for use by self.rational_point and self.parametrization
    662 
    663         EXAMPLES:
    664 
    665         ::
    666 
    667             sage: c = Conic([1, -1, 1])
    668             sage: c.point([15, 17, 8])
    669             (15/8 : 17/8 : 1)
    670             sage: c.rational_point()
    671             (15/8 : 17/8 : 1)
    672             sage: d = Conic([1, -1, 1])
    673             sage: d.rational_point()
    674             (1 : 1 : 0)
    675         """
    676         if is_Vector(v):
    677             v = Sequence(v)
    678         p = ProjectiveCurve_generic.point(self, v, check=check)
    679         if self._rational_point is None:
    680             self._rational_point = p
    681         return p
    682 
    683     def random_rational_point(self, bound=None):
    684         r"""
    685         Return a random rational point of this conic.
    686        
    687         The output is the image of a random point X on the
    688         projective line under a parametrization of self.
    689         If a bound is specified and the base field is `\QQ`,
    690         then that is a bound on the naive height of X.
    691         If the base field is a finite field, then the
    692         output is uniformly distributed over the rational
    693         points of self.
    694 
    695         EXAMPLES:
    696            
    697         ::
    698             sage: c = Conic(GF(2), [1,1,1,1,1,0])
    699             sage: [c.random_rational_point() for _ in range(10)] # output is random
    700            
    701             [(0 : 0 : 1),
    702              (1 : 0 : 1),
    703              (1 : 0 : 1),
    704              (0 : 0 : 1),
    705              (1 : 0 : 1),
    706              (0 : 1 : 1),
    707              (0 : 1 : 1),
    708              (0 : 0 : 1),
    709              (0 : 0 : 1),
    710              (1 : 0 : 1)]
    711         """
    712         if not self.is_smooth():
    713             raise NotImplementedError, "Sorry, random points not implemented " \
    714                                        "for non-smooth conics"
    715         par = self.parametrization()
    716         x = 0
    717         y = 0
    718         B = self.base_ring()
    719         if is_RationalField(B) and bound != None:
    720             if bound < 1:
    721                 raise ValueError, "The bound (= %s) needs to be at least 1" % \
    722                                   bound
    723             while x == 0 and y == 0:
    724                 x = ZZ.random_element(-bound, bound+1)
    725                 y = ZZ.random_element(-bound, bound+1)
    726         else:
    727             while x == 0 and y == 0:
    728                 x = B.random_element()
    729                 y = B.random_element()
    730         return par[0]([x,y])
    731 
    732     def singular_point(self):
    733         r"""
    734         Returns a singular rational point of self
    735        
    736         EXAMPLES:
    737        
    738         ::
    739 
    740             sage: Conic(GF(2), [1,1,1,1,1,1]).singular_point()
    741             (1 : 1 : 1)
    742 
    743         A ValueError is raised if the conic has no rational singular point
    744            
    745         ::
    746 
    747             sage: Conic(QQ, [1,1,1,1,1,1]).singular_point()
    748             Traceback (most recent call last):
    749             ...
    750             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
    751         """
    752         b = self.has_singular_point(point = True)
    753         if not b[0]:
    754             raise ValueError, "The conic self (= %s) has no rational " \
    755                               "singular point" % self
    756         return b[1]
    757 
    758     def symmetric_matrix(self):
    759         r"""
    760         The symmetric matrix M such that (x y z) M (x y z)^t
    761         is the defining equation of  self.
    762        
    763         EXAMPLES:
    764             sage: R.<x, y, z> = QQ[]
    765             sage: C = Curve(x^2 + x*y/2 + y^2 + z^2)
    766             sage: C.symmetric_matrix()
    767             [  1 1/4   0]
    768             [1/4   1   0]
    769             [  0   0   1]
    770 
    771             sage: C = Curve(x^2 + 2*x*y + y^2 + 3*x*z + z^2)
    772             sage: v = vector([x, y, z])
    773             sage: v * C.symmetric_matrix() * v
    774             x^2 + 2*x*y + y^2 + 3*x*z + z^2
    775         """
    776         [a,b,c,d,e,f] = self.coefficients()
    777         if self.base_ring().characteristic() == 2:
    778             if b == 0 and c == 0 and e == 0:
    779                 return matrix([[a,0,0],[0,d,0],[0,0,f]])
    780             raise ValueError, "The conic self (= %s) has no symmetric matrix " \
    781                               "because the base field has characteristic 2" % \
    782                               self
    783         from sage.matrix.constructor import matrix
    784         return matrix([[  a , b/2, c/2 ],
    785                        [ b/2,  d , e/2 ],
    786                        [ c/2, e/2,  f  ]])
    787  
    788     def upper_triangular_matrix(self):
    789         r"""
    790         The upper-triangular matrix M such that (x y z) M (x y z)^t
    791         is the defining equation of self.
    792 
    793         EXAMPLES:
    794             sage: R.<x, y, z> = QQ[]
    795             sage: C = Curve(x^2 + x*y + y^2 + z^2)
    796             sage: C.upper_triangular_matrix()
    797             [1 1 0]
    798             [0 1 0]
    799             [0 0 1]
    800 
    801             sage: C = Curve(x^2 + 2*x*y + y^2 + 3*x*z + z^2)
    802             sage: v = vector([x, y, z])
    803             sage: v * C.upper_triangular_matrix() * v
    804             x^2 + 2*x*y + y^2 + 3*x*z + z^2
    805         """
    806         from sage.matrix.constructor import matrix
    807         [a,b,c,d,e,f] = self.coefficients()
    808         return matrix([[ a, b, c ],
    809                        [ 0, d, e ],
    810                        [ 0, 0, f ]])
    811    
    812     def variable_names(self):
    813         r"""
    814         Returns the variable names of the defining polynomial
    815         of self
    816 
    817         EXAMPLES:
    818 
    819         ::
    820 
    821             sage: c=Conic([1,1,0,1,0,1], 'x,y,z')
    822             sage: c.variable_names()
    823             ('x', 'y', 'z')
    824             sage: c.variable_name()
    825             'x'
    826         """
    827         return self.defining_polynomial().parent().variable_names()
    828    
    829 
  • sage/schemes/plane_conics/rnfisnorm.py

    diff -r 510cd246e899 -r dd59f5b6d61d sage/schemes/plane_conics/rnfisnorm.py
    a b  
    3535
    3636
    3737def rnfisnorm(L, x, galois_check = 2, extra_primes = 0):
    38     r"""
     38    r"""
     39    WARNING: This function should not be in sage.schemes.plane_conics,
     40    where it is now, and will be removed from here. It can be added
     41    to number_field, or replaced by the patch of trac #2329.
     42   
    3943    For a relative number field `L` and an element `x` of its base field `K`,
    4044    determine whether `x` is the relative norm `N_{L/K}(y)` of an element
    4145    `y\in L`.