Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" Projective plane conics over a number field
AUTHORS:
- Marco Streng (2010-07-20)
""" from __future__ import absolute_import #***************************************************************************** # Copyright (C) 2009/2010 Marco Streng <marco.streng@gmail.com> # # Distributed under the terms of the GNU General Public License (GPL) # # This code is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # The full text of the GPL is available at: # # http://www.gnu.org/licenses/ #*****************************************************************************
from sage.rings.all import (RDF, CDF, AA, RLF, QQbar, PolynomialRing)
from sage.rings.complex_field import is_ComplexField
from sage.rings.ring import is_Ring from sage.rings.rational_field import is_RationalField from sage.rings.real_mpfi import is_RealIntervalField from sage.rings.complex_interval_field import is_ComplexIntervalField
from .con_field import ProjectiveConic_field
class ProjectiveConic_number_field(ProjectiveConic_field): r""" Create a projective plane conic curve over a number field. See ``Conic`` for full documentation.
EXAMPLES::
sage: K.<a> = NumberField(x^3 - 2, 'a') sage: P.<X, Y, Z> = K[] sage: Conic(X^2 + Y^2 - a*Z^2) Projective Conic Curve over Number Field in a with defining polynomial x^3 - 2 defined by X^2 + Y^2 + (-a)*Z^2
TESTS::
sage: K.<a> = NumberField(x^3 - 3, 'a') sage: Conic([a, 1, -1])._test_pickling() """ def __init__(self, A, f): r""" See ``Conic`` for full documentation.
EXAMPLES ::
sage: Conic([1, 1, 1]) Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^2 """
# a single prime such that self has no point over the completion # all finite primes such that self has no point over the completion # all infinite primes such that self has no point over the completion
def has_rational_point(self, point = False, obstruction = False, algorithm = 'default', read_cache = True): r""" Returns ``True`` if and only if ``self`` has a point defined over its base field `B`.
If ``point`` and ``obstruction`` are both False (default), then the output is a boolean ``out`` saying whether ``self`` has a rational point.
If ``point`` or ``obstruction`` is True, then the output is a pair ``(out, S)``, where ``out`` is as above and:
- if ``point`` is True and ``self`` has a rational point, then ``S`` is a rational point,
- if ``obstruction`` is True, ``self`` has no rational point, then ``S`` is a prime or infinite place of `B` such that no rational point exists over the completion at ``S``.
Points and obstructions are cached whenever they are found. Cached information is used for the output if available, but only if ``read_cache`` is True.
ALGORITHM:
The parameter ``algorithm`` specifies the algorithm to be used:
- ``'rnfisnorm'`` -- Use PARI's rnfisnorm (cannot be combined with ``obstruction = True``)
- ``'local'`` -- Check if a local solution exists for all primes and infinite places of `B` and apply the Hasse principle. (Cannot be combined with ``point = True``.)
- ``'default'`` -- Use algorithm ``'rnfisnorm'`` first. Then, if no point exists and obstructions are requested, use algorithm ``'local'`` to find an obstruction.
- ``'magma'`` (requires Magma to be installed) -- delegates the task to the Magma computer algebra system.
EXAMPLES:
An example over `\QQ` ::
sage: C = Conic(QQ, [1, 113922743, -310146482690273725409]) sage: C.has_rational_point(point = True) (True, (-76842858034579/5424 : -5316144401/5424 : 1)) sage: C.has_rational_point(algorithm = 'local', read_cache = False) True
Examples over number fields::
sage: K.<i> = QuadraticField(-1) sage: C = Conic(K, [1, 3, -5]) sage: C.has_rational_point(point = True, obstruction = True) (False, Fractional ideal (-i - 2)) sage: C.has_rational_point(algorithm = "rnfisnorm") False sage: C.has_rational_point(algorithm = "rnfisnorm", obstruction = True, read_cache=False) Traceback (most recent call last): ... ValueError: Algorithm rnfisnorm cannot be combined with obstruction = True in has_rational_point
sage: P.<x> = QQ[] sage: L.<b> = NumberField(x^3-5) sage: C = Conic(L, [1, 2, -3]) sage: C.has_rational_point(point = True, algorithm = 'rnfisnorm') (True, (5/3 : -1/3 : 1))
sage: K.<a> = NumberField(x^4+2) sage: Conic(QQ, [4,5,6]).has_rational_point() False sage: Conic(K, [4,5,6]).has_rational_point() True sage: Conic(K, [4,5,6]).has_rational_point(algorithm='magma', read_cache=False) # optional - magma True
TESTS:
Create a bunch of conics over number fields and check whether ``has_rational_point`` runs without errors for algorithms ``'rnfisnorm'`` and ``'local'``. Check if all points returned are valid. If Magma is available, then also check if the output agrees with Magma. ::
sage: P.<X> = QQ[] sage: Q = P.fraction_field() sage: c = [1, X/2, 1/X] sage: l = Sequence(cartesian_product_iterator([c for i in range(3)])) sage: l = l + [[X, 1, 1, 1, 1, 1]] + [[X, 1/5, 1, 1, 2, 1]] sage: K.<a> = QuadraticField(-23) sage: L.<b> = QuadraticField(19) sage: M.<c> = NumberField(X^3+3*X+1) sage: m = [[Q(b)(F.gen()) for b in a] for a in l for F in [K, L, M]] sage: d = [] sage: c = [] sage: c = [Conic(a) for a in m if a != [0,0,0]] sage: d = [C.has_rational_point(algorithm = 'rnfisnorm', point = True) for C in c] # long time: 3.3 seconds sage: all([c[k].defining_polynomial()(Sequence(d[k][1])) == 0 for k in range(len(d)) if d[k][0]]) True sage: [C.has_rational_point(algorithm='local', read_cache=False) for C in c] == [o[0] for o in d] # long time: 5 seconds True sage: [C.has_rational_point(algorithm = 'magma', read_cache=False) for C in c] == [o[0] for o in d] # long time: 3 seconds, optional - magma True
Create a bunch of conics that are known to have rational points already over `\QQ` and check if points are found by ``has_rational_point``. ::
sage: l = Sequence(cartesian_product_iterator([[-1, 0, 1] for i in range(3)])) sage: K.<a> = QuadraticField(-23) sage: L.<b> = QuadraticField(19) sage: M.<c> = NumberField(x^5+3*x+1) sage: m = [[F(b) for b in a] for a in l for F in [K, L, M]] sage: c = [Conic(a) for a in m if a != [0,0,0] and a != [1,1,1] and a != [-1,-1,-1]] sage: assert all([C.has_rational_point(algorithm = 'rnfisnorm') for C in c]) sage: assert all([C.defining_polynomial()(Sequence(C.has_rational_point(point = True)[1])) == 0 for C in c]) sage: assert all([C.has_rational_point(algorithm='local', read_cache=False) for C in c]) # long time: 1 second """ else: return True return False, self._local_obstruction else: self._infinite_obstructions == []: if obstruction: return True, None return True return self.has_singular_point(point = True) return True, None
algorithm='rnfisnorm', read_cache=False) algorithm='local', read_cache=False) raise RuntimeError("Outputs of algorithms in " \ "has_rational_point disagree " \ "for conic %s" % self) if point: return False, None return False
raise ValueError("Algorithm 'local' cannot be combined " \ "with point = True in has_rational_point") read_cache = read_cache) if obstruction: return False, obs[0] return False return True, None return False "with obstruction = True in " \ "has_rational_point") pt = self.point(T*vector({2:0,j:1})) if point or obstruction: return True, pt return True return True, pt else:
KtoB(isnorm[1][1]*den), 1])) return True return False if algorithm == 'qfsolve': raise TypeError("Algorithm qfsolve in has_rational_point only " \ "for conics over QQ, not over %s" % B) if obstruction: raise ValueError("Invalid combination: obstruction=True and " \ "algorithm=%s" % algorithm)
return ProjectiveConic_field.has_rational_point(self, point = point, algorithm = algorithm, read_cache = False)
def is_locally_solvable(self, p): r""" Returns ``True`` if and only if ``self`` has a solution over the completion of the base field `B` of ``self`` at ``p``. Here ``p`` is a finite prime or infinite place of `B`.
EXAMPLES::
sage: P.<x> = QQ[] sage: K.<a> = NumberField(x^3 + 5) sage: C = Conic(K, [1, 2, 3 - a]) sage: [p1, p2] = K.places() sage: C.is_locally_solvable(p1) False
sage: C.is_locally_solvable(p2) True
sage: O = K.maximal_order() sage: f = (2*O).factor() sage: C.is_locally_solvable(f[0][0]) True
sage: C.is_locally_solvable(f[1][0]) False """ return True
def local_obstructions(self, finite = True, infinite = True, read_cache = True): r""" Returns the sequence of finite primes and/or infinite places such that ``self`` is locally solvable at those primes and places.
If the base field is `\QQ`, then the infinite place is denoted `-1`.
The parameters ``finite`` and ``infinite`` (both True by default) are used to specify whether to look at finite and/or infinite places. Note that ``finite = True`` involves factorization of the determinant of ``self``, hence may be slow.
Local obstructions are cached. The parameter ``read_cache`` specifies whether to look at the cache before computing anything.
EXAMPLES ::
sage: K.<i> = QuadraticField(-1) sage: Conic(K, [1, 2, 3]).local_obstructions() []
sage: L.<a> = QuadraticField(5) sage: Conic(L, [1, 2, 3]).local_obstructions() [Ring morphism: From: Number Field in a with defining polynomial x^2 - 5 To: Algebraic Real Field Defn: a |--> -2.236067977499790?, Ring morphism: From: Number Field in a with defining polynomial x^2 - 5 To: Algebraic Real Field Defn: a |--> 2.236067977499790?] """ obs0 = self._infinite_obstructions else: obs1 = self._finite_obstructions else: candidates.append(f[0])
|