def __init__(self, A, f): r""" See ``Conic`` for full documentation. EXAMPLES:: sage: c = Conic([1, 1, 1]); c Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^2 """ ProjectiveConic_field.__init__(self, A, f)
def has_rational_point(self, point=False, algorithm='default', read_cache=True): r""" Returns True if and only if the conic ``self`` has a point over its base field `F(t)`, which is a field of rational functions. If ``point`` is True, then returns a second output, which is a rational point if one exists. Points are cached whenever they are found. Cached information is used if and only if ``read_cache`` is True. The default algorithm does not (yet) work for all base fields `F`. In particular, sage is required to have: * an algorithm for finding the square root of elements in finite extensions of `F`; * a factorization and gcd algorithm for `F[t]`; * an algorithm for solving conics over `F`. ALGORITHM: The parameter ``algorithm`` specifies the algorithm to be used: * ``'default'`` -- use a native Sage implementation, based on the algorithm Conic in [HC2006]_. * ``'magma'`` (requires Magma to be installed) -- delegates the task to the Magma computer algebra system. EXAMPLES: We can find points for function fields over (extensions of) `\QQ` and finite fields:: sage: K.<t> = FractionField(PolynomialRing(QQ, 't')) sage: C = Conic(K, [t^2-2, 2*t^3, -2*t^3-13*t^2-2*t+18]) sage: C.has_rational_point(point=True) (True, (-3 : (t + 1)/t : 1)) sage: R.<t> = FiniteField(23)[] sage: C = Conic([2, t^2+1, t^2+5]) sage: C.has_rational_point() True sage: C.has_rational_point(point=True) (True, (5*t : 8 : 1)) sage: F.<i> = QuadraticField(-1) sage: R.<t> = F[] sage: C = Conic([1,i*t,-t^2+4]) sage: C.has_rational_point(point = True) (True, (-t - 2*i : -2*i : 1)) It works on non-diagonal conics as well:: sage: K.<t> = QQ[] sage: C = Conic([4, -4, 8, 1, -4, t + 4]) sage: C.has_rational_point(point=True) (True, (1/2 : 1 : 0)) If no point exists output still depends on the argument ``point``:: sage: K.<t> = QQ[] sage: C = Conic(K, [t^2, (t-1), -2*(t-1)]) sage: C.has_rational_point() False sage: C.has_rational_point(point=True) (False, None) Due to limitations in Sage of algorithms we depend on, it is not yet possible to find points on conics over multivariate function fields (see the requirements above):: sage: F.<t1> = FractionField(QQ['t1']) sage: K.<t2> = FractionField(F['t2']) sage: a = K(1) sage: b = 2*t2^2+2*t1*t2-t1^2 sage: c = -3*t2^4-4*t1*t2^3+8*t1^2*t2^2+16*t1^3-t2-48*t1^4 sage: C = Conic([a,b,c]) sage: C.has_rational_point() Traceback (most recent call last): ... NotImplementedError: is_square() not implemented for elements of Univariate Quotient Polynomial Ring in tbar over Fraction Field of Univariate Polynomial Ring in t1 over Rational Field with modulus tbar^2 + t1*tbar - 1/2*t1^2 In some cases, the algorithm requires us to be able to solve conics over `F`. In particular, the following does not work:: sage: P.<u> = QQ[] sage: E = P.fraction_field() sage: Q.<Y> = E[] sage: F.<v> = E.extension(Y^2 - u^3 - 1) sage: R.<t> = F[] sage: K = R.fraction_field() sage: C = Conic(K, [u, v, 1]) sage: C.has_rational_point() Traceback (most recent call last): ... NotImplementedError: has_rational_point not implemented for conics over base field Univariate Quotient Polynomial Ring in v over Fraction Field of Univariate Polynomial Ring in u over Rational Field with modulus v^2 - u^3 - 1 ``has_rational_point`` fails for some conics over function fields over finite fields, due to :trac:`20003`:: sage: K.<t> = PolynomialRing(GF(7)) sage: C = Conic([5*t^2+4, t^2+3*t+3, 6*t^2+3*t+2, 5*t^2+5, 4*t+3, 4*t^2+t+5]) sage: C.has_rational_point() Traceback (most recent call last): ... TypeError: self (=Scheme morphism: From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5*t^2 + 4)*x^2 + ((6*t^3 + 3*t^2 + 5*t + 5)/(t + 3))*y^2 + ((6*t^6 + 3*t^5 + t^3 + 6*t^2 + 6*t + 2)/(t^4 + t^3 + 4*t^2 + 3*t + 1))*z^2 To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5*t^2 + 4)*x^2 + (t^2 + 3*t + 3)*x*y + (5*t^2 + 5)*y^2 + (6*t^2 + 3*t + 2)*x*z + (4*t + 3)*y*z + (4*t^2 + t + 5)*z^2 Defn: Defined on coordinates by sending (x : y : z) to (x + ((2*t + 5)/(t + 3))*y + ((3*t^4 + 2*t^3 + 5*t^2 + 5*t + 3)/(t^4 + t^3 + 4*t^2 + 3*t + 1))*z : y + ((6*t^3 + 6*t^2 + 3*t + 6)/(t^3 + 4*t^2 + 2*t + 2))*z : z)) domain must equal right (=Scheme morphism: From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5*t^3 + 6*t^2 + 3*t + 3)*x^2 + (t + 4)*y^2 + (6*t^7 + 2*t^5 + t^4 + 2*t^3 + 3*t^2 + 6*t + 6)*z^2 To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5/(t^3 + 4*t^2 + 2*t + 2))*x^2 + (1/(t^3 + 3*t^2 + 5*t + 1))*y^2 + ((6*t^6 + 3*t^5 + t^3 + 6*t^2 + 6*t + 2)/(t^9 + 5*t^8 + t^7 + 6*t^6 + 3*t^5 + 4*t^3 + t^2 + 5*t + 3))*z^2 Defn: Defined on coordinates by sending (x : y : z) to ((t^3 + 4*t^2 + 2*t + 2)*x : (t^2 + 5)*y : (t^5 + 4*t^4 + t^2 + 3*t + 3)*z)) codomain TESTS:: sage: K.<t> = FractionField(PolynomialRing(QQ, 't')) sage: a = (2*t^2 - 3/2*t + 1)/(37/3*t^2 + t - 1/4) sage: b = (1/2*t^2 + 1/3)/(-73*t^2 - 2*t + 11/4) sage: c = (6934/3*t^6 + 8798/3*t^5 - 947/18*t^4 + 3949/9*t^3 + 20983/18*t^2 + 28/3*t - 131/3)/(-2701/3*t^4 - 293/3*t^3 + 301/6*t^2 + 13/4*t - 11/16) sage: C = Conic([a,b,c]) sage: C.has_rational_point(point=True) (True, (4*t + 4 : 2*t + 2 : 1)) A long time test:: sage: K.<t> = FractionField(PolynomialRing(QQ, 't')) sage: a = (-1/3*t^6 - 14*t^5 - 1/4*t^4 + 7/2*t^2 - 1/2*t - 1)/(24/5*t^6 - t^5 - 1/4*t^4 + t^3 - 3*t^2 + 8/5*t + 5) sage: b = (-3*t^3 + 8*t + 1/2)/(-1/3*t^3 + 3/2*t^2 + 1/12*t + 1/2) sage: c = (1232009/225*t^25 - 1015925057/8100*t^24 + 1035477411553/1458000*t^23 + 7901338091/30375*t^22 - 1421379260447/729000*t^21 + 266121260843/972000*t^20 + 80808723191/486000*t^19 - 516656082523/972000*t^18 + 21521589529/40500*t^17 + 4654758997/21600*t^16 - 20064038625227/9720000*t^15 - 173054270347/324000*t^14 + 536200870559/540000*t^13 - 12710739349/50625*t^12 - 197968226971/135000*t^11 - 134122025657/810000*t^10 + 22685316301/120000*t^9 - 2230847689/21600*t^8 - 70624099679/270000*t^7 - 4298763061/270000*t^6 - 41239/216000*t^5 - 13523/36000*t^4 + 493/36000*t^3 + 83/2400*t^2 + 1/300*t + 1/200)/(-27378/125*t^17 + 504387/500*t^16 - 97911/2000*t^15 + 1023531/4000*t^14 + 1874841/8000*t^13 + 865381/12000*t^12 + 15287/375*t^11 + 6039821/6000*t^10 + 599437/1500*t^9 + 18659/250*t^8 + 1218059/6000*t^7 + 2025127/3000*t^6 + 1222759/6000*t^5 + 38573/200*t^4 + 8323/125*t^3 + 15453/125*t^2 + 17031/500*t + 441/10) sage: C = Conic([a,b,c]) sage: C.has_rational_point(point = True) # long time (4 seconds) (True, ((-2/117*t^8 + 304/1053*t^7 + 40/117*t^6 - 1/27*t^5 - 110/351*t^4 - 2/195*t^3 + 11/351*t^2 + 1/117)/(t^4 + 2/39*t^3 + 4/117*t^2 + 2/39*t + 14/39) : -5/3*t^4 + 19*t^3 : 1)) """ from .constructor import Conic if read_cache: if self._rational_point is not None: return (True, self._rational_point) if point else True if algorithm != 'default': return ProjectiveConic_field.has_rational_point( self, point, algorithm, read_cache) # Default algorithm if self.base_ring().characteristic() == 2: raise NotImplementedError("has_rational_point not implemented \ for function field of characteristic 2.") new_conic, transformation, inverse = self.diagonalization() coeff = new_conic.coefficients() if coeff[0] == 0: return (True, transformation([1, 0, 0])) if point else True elif coeff[3] == 0: return (True, transformation([0, 1, 0])) if point else True elif coeff[5] == 0: return (True, transformation([0, 0, 1])) if point else True # We save the coefficients of the reduced form in coeff # A zero of the reduced conic can be multiplied by multipliers # to get a zero of the old conic (coeff, multipliers) = new_conic._reduce_conic() new_conic = Conic(coeff) transformation = transformation \ * new_conic.hom(diagonal_matrix(multipliers)) if coeff[0].degree() % 2 == coeff[1].degree() % 2 and \ coeff[1].degree() % 2 == coeff[2].degree() % 2: case = 0
def has_rational_point(self, point = False, algorithm = 'default', read_cache = True): r""" Returns True if and only if the conic ``self`` has a point over its base field `F(t)`, which is a field of rational functions. If ``point`` is True, then returns a second output, which is a rational point if one exists. Points are cached whenever they are found. Cached information is used if and only if ``read_cache`` is True. The default algorithm does not (yet) work for all base fields `F`. In particular, sage is required to have: * an algorithm for finding the square root of elements in finite extensions of `F`; * a factorization and gcd algorithm for `F[t]`; * an algorithm for solving conics over `F`. ALGORITHM: The parameter ``algorithm`` specifies the algorithm to be used: * ``'default'`` -- use a native Sage implementation, based on the algorithm Conic in [HC2006]_. * ``'magma'`` (requires Magma to be installed) -- delegates the task to the Magma computer algebra system. EXAMPLES: We can find points for function fields over (extensions of) `\QQ` and finite fields:: sage: K.<t> = FractionField(PolynomialRing(QQ, 't')) sage: C = Conic(K, [t^2-2, 2*t^3, -2*t^3-13*t^2-2*t+18]) sage: C.has_rational_point(point=True) (True, (-3 : (t + 1)/t : 1)) sage: R.<t> = FiniteField(23)[] sage: C = Conic([2, t^2+1, t^2+5]) sage: C.has_rational_point() True sage: C.has_rational_point(point=True) (True, (5*t : 8 : 1)) sage: F.<i> = QuadraticField(-1) sage: R.<t> = F[] sage: C = Conic([1,i*t,-t^2+4]) sage: C.has_rational_point(point = True) verbose 0 (3369: multi_polynomial_ideal.py, groebner_basis) Warning: falling back to very slow toy implementation. ... (True, (-t - 2*i : -2*i : 1)) It works on non-diagonal conics as well:: sage: K.<t> = QQ[] sage: C = Conic([4, -4, 8, 1, -4, t + 4]) sage: C.has_rational_point(point=True) (True, (1/2 : 1 : 0)) If no point exists output still depends on the argument ``point``:: sage: K.<t> = QQ[] sage: C = Conic(K, [t^2, (t-1), -2*(t-1)]) sage: C.has_rational_point() False sage: C.has_rational_point(point=True) (False, None) Due to limitations in Sage of algorithms we depend on, it is not yet possible to find points on conics over multivariate function fields (see the requirements above):: sage: F.<t1> = FractionField(QQ['t1']) sage: K.<t2> = FractionField(F['t2']) sage: a = K(1) sage: b = 2*t2^2+2*t1*t2-t1^2 sage: c = -3*t2^4-4*t1*t2^3+8*t1^2*t2^2+16*t1^3-t2-48*t1^4 sage: C = Conic([a,b,c]) sage: C.has_rational_point() ... Traceback (most recent call last): ... NotImplementedError: is_square() not implemented for elements of Univariate Quotient Polynomial Ring in tbar over Fraction Field of Univariate Polynomial Ring in t1 over Rational Field with modulus tbar^2 + t1*tbar - 1/2*t1^2 In some cases, the algorithm requires us to be able to solve conics over `F`. In particular, the following does not work:: sage: P.<u> = QQ[] sage: E = P.fraction_field() sage: Q.<Y> = E[] sage: F.<v> = E.extension(Y^2 - u^3 - 1) sage: R.<t> = F[] sage: K = R.fraction_field() sage: C = Conic(K, [u, v, 1]) sage: C.has_rational_point() ... Traceback (most recent call last): ... NotImplementedError: has_rational_point not implemented for conics over base field Univariate Quotient Polynomial Ring in v over Fraction Field of Univariate Polynomial Ring in u over Rational Field with modulus v^2 - u^3 - 1 ``has_rational_point`` fails for some conics over function fields over finite fields, due to :trac:`20003`:: sage: K.<t> = PolynomialRing(GF(7)) sage: C = Conic([5*t^2+4, t^2+3*t+3, 6*t^2+3*t+2, 5*t^2+5, 4*t+3, 4*t^2+t+5]) sage: C.has_rational_point() ... Traceback (most recent call last): ... TypeError: self (=Scheme morphism: From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5*t^2 + 4)*x^2 + ((6*t^3 + 3*t^2 + 5*t + 5)/(t + 3))*y^2 + ((6*t^6 + 3*t^5 + t^3 + 6*t^2 + 6*t + 2)/(t^4 + t^3 + 4*t^2 + 3*t + 1))*z^2 To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5*t^2 + 4)*x^2 + (t^2 + 3*t + 3)*x*y + (5*t^2 + 5)*y^2 + (6*t^2 + 3*t + 2)*x*z + (4*t + 3)*y*z + (4*t^2 + t + 5)*z^2 Defn: Defined on coordinates by sending (x : y : z) to (x + ((2*t + 5)/(t + 3))*y + ((3*t^4 + 2*t^3 + 5*t^2 + 5*t + 3)/(t^4 + t^3 + 4*t^2 + 3*t + 1))*z : y + ((6*t^3 + 6*t^2 + 3*t + 6)/(t^3 + 4*t^2 + 2*t + 2))*z : z)) domain must equal right (=Scheme morphism: From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5*t^3 + 6*t^2 + 3*t + 3)*x^2 + (t + 4)*y^2 + (6*t^7 + 2*t^5 + t^4 + 2*t^3 + 3*t^2 + 6*t + 6)*z^2 To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5/(t^3 + 4*t^2 + 2*t + 2))*x^2 + (1/(t^3 + 3*t^2 + 5*t + 1))*y^2 + ((6*t^6 + 3*t^5 + t^3 + 6*t^2 + 6*t + 2)/(t^9 + 5*t^8 + t^7 + 6*t^6 + 3*t^5 + 4*t^3 + t^2 + 5*t + 3))*z^2 Defn: Defined on coordinates by sending (x : y : z) to ((t^3 + 4*t^2 + 2*t + 2)*x : (t^2 + 5)*y : (t^5 + 4*t^4 + t^2 + 3*t + 3)*z)) codomain TESTS:: sage: K.<t> = FractionField(PolynomialRing(QQ, 't')) sage: a = (2*t^2 - 3/2*t + 1)/(37/3*t^2 + t - 1/4) sage: b = (1/2*t^2 + 1/3)/(-73*t^2 - 2*t + 11/4) sage: c = (6934/3*t^6 + 8798/3*t^5 - 947/18*t^4 + 3949/9*t^3 + 20983/18*t^2 + 28/3*t - 131/3)/(-2701/3*t^4 - 293/3*t^3 + 301/6*t^2 + 13/4*t - 11/16) sage: C = Conic([a,b,c]) sage: C.has_rational_point(point=True) (True, (4*t + 4 : 2*t + 2 : 1)) A long time test:: sage: K.<t> = FractionField(PolynomialRing(QQ, 't')) sage: a = (-1/3*t^6 - 14*t^5 - 1/4*t^4 + 7/2*t^2 - 1/2*t - 1)/(24/5*t^6 - t^5 - 1/4*t^4 + t^3 - 3*t^2 + 8/5*t + 5) sage: b = (-3*t^3 + 8*t + 1/2)/(-1/3*t^3 + 3/2*t^2 + 1/12*t + 1/2) sage: c = (1232009/225*t^25 - 1015925057/8100*t^24 + 1035477411553/1458000*t^23 + 7901338091/30375*t^22 - 1421379260447/729000*t^21 + 266121260843/972000*t^20 + 80808723191/486000*t^19 - 516656082523/972000*t^18 + 21521589529/40500*t^17 + 4654758997/21600*t^16 - 20064038625227/9720000*t^15 - 173054270347/324000*t^14 + 536200870559/540000*t^13 - 12710739349/50625*t^12 - 197968226971/135000*t^11 - 134122025657/810000*t^10 + 22685316301/120000*t^9 - 2230847689/21600*t^8 - 70624099679/270000*t^7 - 4298763061/270000*t^6 - 41239/216000*t^5 - 13523/36000*t^4 + 493/36000*t^3 + 83/2400*t^2 + 1/300*t + 1/200)/(-27378/125*t^17 + 504387/500*t^16 - 97911/2000*t^15 + 1023531/4000*t^14 + 1874841/8000*t^13 + 865381/12000*t^12 + 15287/375*t^11 + 6039821/6000*t^10 + 599437/1500*t^9 + 18659/250*t^8 + 1218059/6000*t^7 + 2025127/3000*t^6 + 1222759/6000*t^5 + 38573/200*t^4 + 8323/125*t^3 + 15453/125*t^2 + 17031/500*t + 441/10) sage: C = Conic([a,b,c]) sage: C.has_rational_point(point = True) # long time (4 seconds) (True, ((-2/117*t^8 + 304/1053*t^7 + 40/117*t^6 - 1/27*t^5 - 110/351*t^4 - 2/195*t^3 + 11/351*t^2 + 1/117)/(t^4 + 2/39*t^3 + 4/117*t^2 + 2/39*t + 14/39) : -5/3*t^4 + 19*t^3 : 1)) """ from constructor import Conic if read_cache: if self._rational_point is not None: return (True, self._rational_point) if point else True if algorithm != 'default': return ProjectiveConic_field.has_rational_point(self, point, algorithm, read_cache) # Default algorithm if self.base_ring().characteristic() == 2: raise NotImplementedError("has_rational_point not implemented \ for function field of characteristic 2.") new_conic, transformation, inverse = self.diagonalization() coeff = new_conic.coefficients() if coeff[0] == 0: return (True, transformation([1,0,0])) if point else True elif coeff[3] == 0: return (True, transformation([0,1,0])) if point else True elif coeff[5] == 0: return (True, transformation([0,0,1])) if point else True # We save the coefficients of the reduced form in coeff # A zero of the reduced conic can be multiplied by multipliers # to get a zero of the old conic (coeff, multipliers) = new_conic._reduce_conic() new_conic = Conic(coeff) transformation = transformation \ * new_conic.hom(diagonal_matrix(multipliers)) if coeff[0].degree() % 2 == coeff[1].degree() % 2 and \ coeff[1].degree() % 2 == coeff[2].degree() % 2: case = 0 else: case = 1 t, = self.base_ring().base().gens() # t in F[t] supp = [] roots = [[], [], []] remove = None # loop through the coefficients and find a root of f_i (as in # [HC2006]) modulo each element in the coefficients' support for i in (0,1,2): supp.append(list(coeff[i].factor())) for p in supp[i]: if p[1] != 1: raise ValueError("Expected factor of exponent 1.") # Convert to monic factor x = p[0]/list(p[0])[-1] N = p[0].base_ring().extension(x, 'tbar') R = PolynomialRing(N, 'u') u, = R.gens() # If p[0] has degree 1, sage might forget the "defining # polynomial" of N, so we define our own modulo operation if p[0].degree() == 1: mod = t.parent().hom([-x[0]]) else: mod = N if i == 0: x = -mod(coeff[2])/mod(coeff[1]) elif i == 1: x = -mod(coeff[0])/mod(coeff[2]) else: x = -mod(coeff[1])/mod(coeff[0]) if x.is_square(): root = N(x.sqrt()) else: return (False, None) if point else False # if case == 0 and p[0] has degree 1, we switch to case # 1 and remove this factor out of the support. In [HC2006] # this is done later, in FindPoint. if case == 0 and p[0].degree() == 1: case = 1 # remove later so the loop iterator stays in place. remove = (i,p) else: roots[i].append(root) if remove: supp[remove[0]].remove(remove[1]) supp = [[p[0] for p in supp[i]] for i in (0,1,2)] if case == 0: # Find a solution of (5) in [HC2006] leading_conic = Conic(self.base_ring().base_ring(), [coeff[0].leading_coefficient(), coeff[1].leading_coefficient(), coeff[2].leading_coefficient()]) has_point = leading_conic.has_rational_point(True) if has_point[0]: if point: pt = new_conic.find_point(supp, roots, case, has_point[1]) else: pt = True return (True, transformation(pt)) if point else True else: return (False, None) if point else False # case == 1: if point: pt = new_conic.find_point(supp, roots, case) else: pt = True return (True, transformation(pt)) if point else True