Path: blob/master/sage/schemes/plane_conics/con_number_field.py
4107 views
r"""1Projective plane conics over a number field23AUTHORS:45- Marco Streng (2010-07-20)67"""8#*****************************************************************************9# Copyright (C) 2009/2010 Marco Streng <[email protected]>10#11# Distributed under the terms of the GNU General Public License (GPL)12#13# This code is distributed in the hope that it will be useful,14# but WITHOUT ANY WARRANTY; without even the implied warranty of15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU16# General Public License for more details.17#18# The full text of the GPL is available at:19#20# http://www.gnu.org/licenses/21#*****************************************************************************2223from sage.rings.all import (is_RationalField,24is_RingHomomorphism, is_RealIntervalField,25is_ComplexField, is_ComplexIntervalField,26RDF, CDF, AA, QQbar, PolynomialRing)2728from con_field import ProjectiveConic_field2930class ProjectiveConic_number_field(ProjectiveConic_field):31r"""32Create a projective plane conic curve over a number field.33See ``Conic`` for full documentation.3435EXAMPLES::3637sage: K.<a> = NumberField(x^3 - 2, 'a')38sage: P.<X, Y, Z> = K[]39sage: Conic(X^2 + Y^2 - a*Z^2)40Projective Conic Curve over Number Field in a with defining polynomial x^3 - 2 defined by X^2 + Y^2 + (-a)*Z^24142TESTS::4344sage: K.<a> = NumberField(x^3 - 3, 'a')45sage: Conic([a, 1, -1])._test_pickling()46"""47def __init__(self, A, f):48r"""49See ``Conic`` for full documentation.5051EXAMPLES ::5253sage: Conic([1, 1, 1])54Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^255"""56ProjectiveConic_field.__init__(self, A, f)5758# a single prime such that self has no point over the completion59self._local_obstruction = None60# all finite primes such that self has no point over the completion61self._finite_obstructions = None62# all infinite primes such that self has no point over the completion63self._infinite_obstructions = None646566def has_rational_point(self, point = False, obstruction = False,67algorithm = 'default', read_cache = True):68r"""69Returns ``True`` if and only if ``self`` has a point70defined over its base field `B`.7172If ``point`` and ``obstruction`` are both False (default),73then the output is a boolean ``out`` saying whether ``self``74has a rational point.7576If ``point`` or ``obstruction`` is True, then the output is77a pair ``(out, S)``, where ``out`` is as above and:7879- if ``point`` is True and ``self`` has a rational point,80then ``S`` is a rational point,8182- if ``obstruction`` is True, ``self`` has no rational point,83then ``S`` is a prime or infinite place of `B` such that no84rational point exists over the completion at ``S``.85Finding obstructions is not yet implemented for number fields86(see Sage trac ticket #10742).8788Points and obstructions are cached whenever they are found.89Cached information is used for the output if available, but only90if ``read_cache`` is True.9192ALGORITHM:9394The parameter ``algorithm``95specifies the algorithm to be used:9697- ``'rnfisnorm'`` -- Use PARI's rnfisnorm98(cannot be combined with ``obstruction = True``)99100- ``'local'`` -- Check if a local solution exists for all primes101and infinite places of `B` and apply the Hasse principle.102(cannot be combined with ``point = True``, not yet implemented103for number fields other than `QQ`, see Sage trac ticket #10742.)104105- ``'default'`` -- Use ``'rnfisnorm'``.106107EXAMPLES:108109An example over `\QQ` ::110111sage: C = Conic(QQ, [1, 113922743, -310146482690273725409])112sage: C.has_rational_point(point = True)113(True, (-76842858034579/5424 : -5316144401/5424 : 1))114sage: C.has_rational_point(algorithm = 'local', read_cache = False)115True116117Examples over number fields ::118119sage: K.<i> = QuadraticField(-1)120sage: C = Conic(K, [1, 3, -5])121sage: C.has_rational_point(point = True)122(False, None)123sage: C.has_rational_point(algorithm = "rnfisnorm")124False125sage: C.has_rational_point(algorithm = "rnfisnorm", obstruction = True)126Traceback (most recent call last):127...128ValueError: Algorithm rnfisnorm cannot be combined with obstruction = True in has_rational_point129130sage: P.<x> = QQ[]131sage: L.<b> = NumberField(x^3-5)132sage: C = Conic(L, [1, 2, -3])133sage: C.has_rational_point(point = True, algorithm = 'rnfisnorm')134(True, (5/3 : -1/3 : 1))135136TESTS:137138Create a bunch of conics over number fields and check if ``has_rational_point``139runs without errors for ``algorithm = 'rnfisnorm'``. Check if all points140returned are valid. ::141142sage: P.<X> = QQ[]143sage: Q = P.fraction_field()144sage: c = [1, X/2, 1/X]145sage: l = Sequence(cartesian_product_iterator([c for i in range(3)]))146sage: l = l + [[X, 1, 1, 1, 1, 1]] + [[X, 1/5, 1, 1, 2, 1]]147sage: K.<a> = QuadraticField(-23)148sage: L.<b> = QuadraticField(19)149sage: M.<c> = NumberField(X^3+3*X+1)150sage: m = [[Q(b)(F.gen()) for b in a] for a in l for F in [K, L, M]]151sage: d = []152sage: c = []153sage: c = [Conic(a) for a in m if a != [0,0,0]] # long time: 1 second154sage: d = [C.has_rational_point(algorithm = 'rnfisnorm', point = True) for C in c] # long time: 15 seconds155sage: assert all([c[k].defining_polynomial()(Sequence(d[k][1])) == 0 for k in range(len(c)) if d[k][0]])156157Create a bunch of conics that are known to have rational points158already over `\QQ` and check if points are found by159``has_rational_point``. ::160161sage: l = Sequence(cartesian_product_iterator([[-1, 0, 1] for i in range(3)]))162sage: K.<a> = QuadraticField(-23)163sage: L.<b> = QuadraticField(19)164sage: M.<c> = NumberField(x^5+3*x+1)165sage: m = [[F(b) for b in a] for a in l for F in [K, L, M]]166sage: c = [Conic(a) for a in m if a != [0,0,0] and a != [1,1,1] and a != [-1,-1,-1]] # long time 0.4 seconds167sage: assert all([C.has_rational_point(algorithm = 'rnfisnorm') for C in c]) # long time: 3.5 seconds168sage: assert all([C.defining_polynomial()(Sequence(C.has_rational_point(point = True)[1])) == 0 for C in c]) # uses cache, long time if previous line isn't run169"""170if read_cache:171if self._rational_point is not None:172if point or obstruction:173return True, self._rational_point174else:175return True176if self._local_obstruction is not None:177if point or obstruction:178return False, self._local_obstruction179else:180return False181if (not point) and self._finite_obstructions == [] and \182self._infinite_obstructions == []:183if obstruction:184return True, None185return True186if self.has_singular_point():187if point:188return self.has_singular_point(point = True)189if obstruction:190return True, None191return True192B = self.base_ring()193if algorithm == 'default':194algorithm = 'rnfisnorm'195if algorithm == 'local':196if point:197raise ValueError, "Algorithm 'local' cannot be combined with " \198"point = True in has_rational_point"199obs = self.local_obstructions(infinite = True, finite = False,200read_cache = read_cache)201if obs != []:202if obstruction:203return False, obs[0]204return False205obs = self.local_obstructions(read_cache = read_cache)206if obs == []:207if obstruction:208return True, None209return True210if obstruction:211return False, obs[0]212return False213if algorithm == 'rnfisnorm':214from sage.modules.free_module_element import vector215if obstruction:216raise ValueError, "Algorithm rnfisnorm cannot be combined with " \217"obstruction = True in has_rational_point"218D, T = self.diagonal_matrix()219abc = [D[0,0], D[1,1], D[2,2]]220for j in range(3):221if abc[j] == 0:222pt = self.point(T*vector({2:0,j:1}))223if point or obstruction:224return True, pt225return True226if (-abc[1]/abc[0]).is_square():227pt = self.point(T*vector([(-abc[1]/abc[0]).sqrt(), 1, 0]))228if point or obstruction:229return True, pt230return True231if (-abc[2]/abc[0]).is_square():232pt = self.point(T*vector([(-abc[2]/abc[0]).sqrt(), 0, 1]))233if point or obstruction:234return True, pt235return True236if is_RationalField(B):237K = B238[KtoB, BtoK] = [K.hom(K) for i in range(2)]239else:240K = B.absolute_field('Y')241[KtoB, BtoK] = K.structure()242X = PolynomialRing(K, 'X').gen()243d = BtoK(-abc[1]/abc[0])244den = d.denominator()245L = K.extension(X**2 - d*den**2, names='y')246isnorm = BtoK(-abc[2]/abc[0]).is_norm(L, element=True)247if isnorm[0]:248249pt = self.point(T*vector([KtoB(isnorm[1][0]),250KtoB(isnorm[1][1]*den), 1]))251if point:252return True, pt253return True254if point:255return False, None256return False257if algorithm == 'qfsolve':258raise TypeError, "Algorithm qfsolve in has_rational_point only " \259"for conics over QQ, not over %s" % B260raise ValueError, "Unknown algorithm %s in has_rational_point for %s" \261% algorithm, self262263264def is_locally_solvable(self, p):265r"""266Returns ``True`` if and only if ``self`` has a solution over the267completion of the base field `B` of ``self`` at ``p``. Here ``p``268is a finite prime or infinite place of `B`.269270This is currently not implemented for Number Fields.271See Sage trac ticket #10742.272273EXAMPLES::274275sage: P.<x> = QQ[]276sage: K.<a> = NumberField(x^3 + 5)277sage: C = Conic(K, [1, 2, 3 - a])278sage: [p1, p2] = K.places()279sage: C.is_locally_solvable(p1)280Traceback (most recent call last):281...282NotImplementedError: Sorry, is_locally_solvable is not yet implemented for number fields.283284sage: C.is_locally_solvable(p2)285Traceback (most recent call last):286...287NotImplementedError: Sorry, is_locally_solvable is not yet implemented for number fields.288289sage: O = K.maximal_order()290sage: f = (2*O).factor()291sage: C.is_locally_solvable(f[0][0])292Traceback (most recent call last):293...294NotImplementedError: Sorry, is_locally_solvable is not yet implemented for number fields.295296sage: C.is_locally_solvable(f[1][0])297Traceback (most recent call last):298...299NotImplementedError: Sorry, is_locally_solvable is not yet implemented for number fields.300"""301raise NotImplementedError, "Sorry, is_locally_solvable is not yet implemented for number fields."302303304def local_obstructions(self, finite = True, infinite = True, read_cache = True):305r"""306Returns the sequence of finite primes and/or infinite places307such that ``self`` is locally solvable at those primes and places.308309If the base field is `\QQ`, then the infinite place is denoted `-1`.310311The parameters ``finite`` and ``infinite`` (both True by default) are312used to specify whether to look at finite and/or infinite places.313Note that ``finite = True`` involves factorization of the determinant314of ``self``, hence may be slow.315316Local obstructions are cached. The parameter ``read_cache``317specifies whether to look at the cache before computing anything.318319This is currently not implemented for Number Fields.320See Sage trac ticket #10742.321322EXAMPLES ::323324sage: K.<i> = QuadraticField(-1)325sage: Conic(K, [1, 2, 3]).local_obstructions()326Traceback (most recent call last):327...328NotImplementedError: Sorry, is_locally_solvable is not yet implemented for number fields.329330sage: L.<a> = QuadraticField(5)331sage: Conic(L, [1, 2, 3]).local_obstructions()332Traceback (most recent call last):333...334NotImplementedError: Sorry, is_locally_solvable is not yet implemented for number fields.335336337"""338obs0 = []339obs1 = []340B = self.base_ring()341if infinite:342if read_cache and self._infinite_obstructions != None:343obs0 = self._infinite_obstructions344else:345for b in B.embeddings(AA):346if not self.is_locally_solvable(b):347obs0.append(b)348self._infinite_obstructions = obs0349if finite:350if read_cache and self._finite_obstructions != None:351obs1 = self._finite_obstructions352else:353candidates = []354if self.determinant() != 0:355O = B.maximal_order()356for a in self.symmetric_matrix().list():357if a != 0:358for f in O.fractional_ideal(a).factor():359if f[1] < 0 and not f[0] in candidates:360candidates.append(f[0])361for f in O.fractional_ideal(2*self.determinant()).factor():362if f[1] > 0 and not f[0] in candidates:363candidates.append(f[0])364for b in candidates:365if not self.is_locally_solvable(b):366obs1.append(b)367self._infinite_obstructions = obs1368obs = obs1 + obs0369if finite and infinite:370assert len(obs) % 2 == 0371return obs372373374375376