def __init__(self, parent, phi, check=True): """ The Python constuctor. See :class:`SchemeMorphism_structure_map` for details. TESTS:: sage: from sage.schemes.generic.morphism import SchemeMorphism_spec sage: SchemeMorphism_spec(Spec(QQ).Hom(Spec(ZZ)), ZZ.hom(QQ)) Affine Scheme morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring Defn: Ring Coercion morphism: From: Integer Ring To: Rational Field """ SchemeMorphism.__init__(self, parent) if check: if not is_RingHomomorphism(phi): raise TypeError("phi (=%s) must be a ring homomorphism" % phi) if phi.domain() != parent.codomain().coordinate_ring(): raise TypeError("phi (=%s) must have domain %s" % (phi, parent.codomain().coordinate_ring())) if phi.codomain() != parent.domain().coordinate_ring(): raise TypeError("phi (=%s) must have codomain %s" % (phi, parent.domain().coordinate_ring())) self.__ring_homomorphism = phi
def hom(self, x, Y=None): r""" Return the scheme morphism from ``self`` to ``Y`` defined by ``x``. INPUT: - ``x`` -- anything hat determines a scheme morphism. If ``x`` is a scheme, try to determine a natural map to ``x``. - ``Y`` -- the codomain scheme (optional). If ``Y`` is not given, try to determine ``Y`` from context. - ``check`` -- boolean (optional, default=``True``). Whether to check the defining data for consistency. OUTPUT: The scheme morphism from ``self`` to ``Y`` defined by ``x``. EXAMPLES: We construct the inclusion from `\mathrm{Spec}(\QQ)` into `\mathrm{Spec}(\ZZ)` induced by the inclusion from `\ZZ` into `\QQ`:: sage: X = Spec(QQ) sage: X.hom(ZZ.hom(QQ)) Affine Scheme morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring Defn: Ring Coercion morphism: From: Integer Ring To: Rational Field TESTS: We can construct a morphism to an affine curve (trac #7956):: sage: S.<p,q> = QQ[] sage: A1.<r> = AffineSpace(QQ,1) sage: A1_emb = Curve(p-2) sage: A1.hom([2,r],A1_emb) Scheme morphism: From: Affine Space of dimension 1 over Rational Field To: Affine Curve over Rational Field defined by p - 2 Defn: Defined on coordinates by sending (r) to (2, r) """ if is_Scheme(x): return self.Hom(x).natural_map() if Y is None: if is_RingHomomorphism(x): import spec Y = spec.Spec(x.domain()) return Scheme.hom(self, x, Y)
def __call__(self, x, check=True): """ INPUT: - `x` -- a ring morphism, or a list or tuple of that define a ring morphism. - ``check`` -- (default: True) passed onto functions called by this to be more careful about input argument type checking EXAMPLES:: sage: f = ZZ.hom(QQ); f Ring Coercion morphism: From: Integer Ring To: Rational Field :: sage: H = Hom(Spec(QQ,ZZ), Spec(ZZ)); H Set of points of Spectrum of Integer Ring defined over Rational Field :: sage: phi = H(f); phi Affine Scheme morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring Defn: Ring Coercion morphism: From: Integer Ring To: Rational Field TESTS:: We illustrate input type checking:: sage: R.<x,y> = QQ[] sage: A.<x,y> = AffineSpace(R) sage: C = A.subscheme(x*y-1) sage: H = C.Hom(C); H Set of points of Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x*y - 1 defined over Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x*y - 1) sage: H(1) Traceback (most recent call last): ... TypeError: x must be a ring homomorphism, list or tuple """ if isinstance(x, (list, tuple)): return self.domain()._point_morphism_class(self, x, check=check) if is_RingHomomorphism(x): return morphism.SchemeMorphism_spec(self, x, check=check) raise TypeError, "x must be a ring homomorphism, list or tuple"
def __init__(self, X=None, category=None): """ Construct a scheme. TESTS:: sage: R.<x, y> = QQ[] sage: I = (x^2 - y^2)*R sage: RmodI = R.quotient(I) sage: X = Spec(RmodI) sage: TestSuite(X).run(skip = ["_test_an_element", "_test_elements", ... "_test_some_elements", "_test_category"]) # See #7946 """ from sage.schemes.generic.spec import is_Spec from sage.schemes.generic.morphism import is_SchemeMorphism if X is None: try: from sage.schemes.generic.spec import SpecZ self._base_scheme = SpecZ except ImportError: # we are currently constructing SpecZ self._base_ring = ZZ elif is_Scheme(X): self._base_scheme = X elif is_SchemeMorphism(X): self._base_morphism = X elif is_CommutativeRing(X): self._base_ring = X elif is_RingHomomorphism(X): self._base_ring = X.codomain() else: raise ValueError("The base must be define by a scheme, " "scheme morphism, or commutative ring.") from sage.categories.schemes import Schemes if not X: default_category = Schemes() else: default_category = Schemes(self.base_scheme()) if category is None: category = default_category else: assert category.is_subcategory(default_category), "%s is not a subcategory of %s" % ( category, default_category, ) Parent.__init__(self, self.base_ring(), category=category)
def __init__(self, X=None, category=None): """ Construct a scheme. TESTS:: sage: R.<x, y> = QQ[] sage: I = (x^2 - y^2)*R sage: RmodI = R.quotient(I) sage: X = Spec(RmodI) sage: TestSuite(X).run(skip = ["_test_an_element", "_test_elements", ... "_test_some_elements", "_test_category"]) # See #7946 """ from sage.schemes.generic.spec import is_Spec from sage.schemes.generic.morphism import is_SchemeMorphism if X is None: try: from sage.schemes.generic.spec import SpecZ self._base_scheme = SpecZ except ImportError: # we are currently constructing SpecZ self._base_ring = ZZ elif is_Scheme(X): self._base_scheme = X elif is_SchemeMorphism(X): self._base_morphism = X elif is_CommutativeRing(X): self._base_ring = X elif is_RingHomomorphism(X): self._base_ring = X.codomain() else: raise ValueError('The base must be define by a scheme, ' 'scheme morphism, or commutative ring.') from sage.categories.schemes import Schemes if not X: default_category = Schemes() else: default_category = Schemes(self.base_scheme()) if category is None: category = default_category else: assert category.is_subcategory(default_category), \ "%s is not a subcategory of %s"%(category, default_category) Parent.__init__(self, self.base_ring(), category=category)
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 """ D, T = self.diagonal_matrix() abc = [D[j, j] for j in range(3)] for a in abc: if a == 0: return True a = -abc[0] / abc[2] b = -abc[1] / abc[2] ret = self.base_ring().hilbert_symbol(a, b, p) if ret == -1: if self._local_obstruction is None: if (not is_RingHomomorphism(p)) or p.codomain() is AA or \ p.codomain() is RLF: self._local_obstruction = p return False return True
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 """ D, T = self.diagonal_matrix() abc = [D[j, j] for j in range(3)] for a in abc: if a == 0: return True a = -abc[0]/abc[2] b = -abc[1]/abc[2] ret = self.base_ring().hilbert_symbol(a, b, p) if ret == -1: if self._local_obstruction is None: if (not is_RingHomomorphism(p)) or p.codomain() is AA or \ p.codomain() is RLF: self._local_obstruction = p return False return True
def __init__(self, X=None, category=None): """ Construct a scheme. TESTS: The full test suite works since :trac:`7946`:: sage: R.<x, y> = QQ[] sage: I = (x^2 - y^2)*R sage: RmodI = R.quotient(I) sage: X = Spec(RmodI) sage: TestSuite(X).run() """ from sage.schemes.generic.morphism import is_SchemeMorphism if X is None: self._base_ring = ZZ elif is_Scheme(X): self._base_scheme = X elif is_SchemeMorphism(X): self._base_morphism = X elif isinstance(X, CommutativeRing): self._base_ring = X elif is_RingHomomorphism(X): self._base_ring = X.codomain() else: raise ValueError('The base must be define by a scheme, ' 'scheme morphism, or commutative ring.') from sage.categories.schemes import Schemes if X is None: default_category = Schemes() else: default_category = Schemes(self.base_scheme()) if category is None: category = default_category else: assert category.is_subcategory(default_category), \ "%s is not a subcategory of %s"%(category, default_category) Parent.__init__(self, self.base_ring(), category=category)
def __init__(self, X=None, category=None): """ Construct a scheme. TESTS: The full test suite works since :trac:`7946`:: sage: R.<x, y> = QQ[] sage: I = (x^2 - y^2)*R sage: RmodI = R.quotient(I) sage: X = Spec(RmodI) sage: TestSuite(X).run() """ from sage.schemes.generic.morphism import is_SchemeMorphism if X is None: self._base_ring = ZZ elif is_Scheme(X): self._base_scheme = X elif is_SchemeMorphism(X): self._base_morphism = X elif is_CommutativeRing(X): self._base_ring = X elif is_RingHomomorphism(X): self._base_ring = X.codomain() else: raise ValueError('The base must be define by a scheme, ' 'scheme morphism, or commutative ring.') from sage.categories.schemes import Schemes if X is None: default_category = Schemes() else: default_category = Schemes(self.base_scheme()) if category is None: category = default_category else: assert category.is_subcategory(default_category), \ "%s is not a subcategory of %s"%(category, default_category) Parent.__init__(self, self.base_ring(), category = category)
def is_locally_solvable(self, p): r""" Returns True if and only if ``self`` has a solution over the `p`-adic numbers. Here `p` is a prime number or equals `-1`, infinity, or `\RR` to denote the infinite place. EXAMPLES:: sage: C = Conic(QQ, [1,2,3]) sage: C.is_locally_solvable(-1) False sage: C.is_locally_solvable(2) False sage: C.is_locally_solvable(3) True sage: C.is_locally_solvable(QQ.hom(RR)) False sage: D = Conic(QQ, [1, 2, -3]) sage: D.is_locally_solvable(infinity) True sage: D.is_locally_solvable(RR) True """ D, T = self.diagonal_matrix() abc = [D[j, j] for j in range(3)] if abc[2] == 0: return True a = -abc[0] / abc[2] b = -abc[1] / abc[2] if is_RealField(p) or is_InfinityElement(p): p = -1 elif is_RingHomomorphism(p): if p.domain() is QQ and is_RealField(p.codomain()): p = -1 else: raise TypeError("p (=%s) needs to be a prime of base field " \ "B ( =`QQ`) in is_locally_solvable" % p) if hilbert_symbol(a, b, p) == -1: if self._local_obstruction is None: self._local_obstruction = p return False return True
def is_locally_solvable(self, p): r""" Returns True if and only if ``self`` has a solution over the `p`-adic numbers. Here `p` is a prime number or equals `-1`, infinity, or `\RR` to denote the infinite place. EXAMPLES:: sage: C = Conic(QQ, [1,2,3]) sage: C.is_locally_solvable(-1) False sage: C.is_locally_solvable(2) False sage: C.is_locally_solvable(3) True sage: C.is_locally_solvable(QQ.hom(RR)) False sage: D = Conic(QQ, [1, 2, -3]) sage: D.is_locally_solvable(infinity) True sage: D.is_locally_solvable(RR) True """ D, T = self.diagonal_matrix() abc = [D[j, j] for j in range(3)] if abc[2] == 0: return True a = -abc[0]/abc[2] b = -abc[1]/abc[2] if is_RealField(p) or is_InfinityElement(p): p = -1 elif is_RingHomomorphism(p): if p.domain() is QQ and is_RealField(p.codomain()): p = -1 else: raise TypeError("p (=%s) needs to be a prime of base field " \ "B ( =`QQ`) in is_locally_solvable" % p) if hilbert_symbol(a, b, p) == -1: if self._local_obstruction is None: self._local_obstruction = p return False return True
def _call_(self, x): """ Construct a scheme from the data in ``x`` EXAMPLES: Let us first construct the category of schemes:: sage: S = Schemes(); S Category of schemes We create a scheme from a ring:: sage: X = S(ZZ); X # indirect doctest Spectrum of Integer Ring We create a scheme from a scheme (do nothing):: sage: S(X) Spectrum of Integer Ring We create a scheme morphism from a ring homomorphism.x:: sage: phi = ZZ.hom(QQ); phi Ring Coercion morphism: From: Integer Ring To: Rational Field sage: f = S(phi); f # indirect doctest Affine Scheme morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring Defn: Ring Coercion morphism: From: Integer Ring To: Rational Field sage: f.domain() Spectrum of Rational Field sage: f.codomain() Spectrum of Integer Ring sage: S(f) # indirect doctest Affine Scheme morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring Defn: Ring Coercion morphism: From: Integer Ring To: Rational Field """ from sage.schemes.generic.scheme import is_Scheme if is_Scheme(x): return x from sage.schemes.generic.morphism import is_SchemeMorphism if is_SchemeMorphism(x): return x from sage.rings.morphism import is_RingHomomorphism from sage.rings.commutative_ring import is_CommutativeRing from sage.schemes.generic.spec import Spec if is_CommutativeRing(x): return Spec(x) elif is_RingHomomorphism(x): A = Spec(x.codomain()) return A.hom(x) else: raise TypeError( "No way to create an object or morphism in %s from %s" % (self, x))
def _call_(self, x): """ Construct a scheme from the data in ``x`` EXAMPLES: Let us first construct the category of schemes:: sage: S = Schemes(); S Category of schemes We create a scheme from a ring:: sage: X = S(ZZ); X # indirect doctest Spectrum of Integer Ring We create a scheme from a scheme (do nothing):: sage: S(X) Spectrum of Integer Ring We create a scheme morphism from a ring homomorphism.x:: sage: phi = ZZ.hom(QQ); phi Ring Coercion morphism: From: Integer Ring To: Rational Field sage: f = S(phi); f # indirect doctest Affine Scheme morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring Defn: Ring Coercion morphism: From: Integer Ring To: Rational Field sage: f.domain() Spectrum of Rational Field sage: f.codomain() Spectrum of Integer Ring sage: S(f) # indirect doctest Affine Scheme morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring Defn: Ring Coercion morphism: From: Integer Ring To: Rational Field """ from sage.schemes.generic.scheme import is_Scheme if is_Scheme(x): return x from sage.schemes.generic.morphism import is_SchemeMorphism if is_SchemeMorphism(x): return x from sage.rings.morphism import is_RingHomomorphism from sage.rings.ring import CommutativeRing from sage.schemes.generic.spec import Spec if isinstance(x, CommutativeRing): return Spec(x) elif is_RingHomomorphism(x): A = Spec(x.codomain()) return A.hom(x) else: raise TypeError("No way to create an object or morphism in %s from %s"%(self, x))
def _element_constructor_(self, x, check=True): """ Construct a scheme morphism. INPUT: - `x` -- anything that defines a morphism of toric varieties. A matrix, fan morphism, or a list or tuple of homogeneous polynomials that define a morphism. - ``check`` -- boolean (default: ``True``) passed onto functions called by this to be more careful about input argument type checking OUTPUT: The morphism of toric varieties determined by ``x``. EXAMPLES: First, construct from fan morphism:: sage: dP8.<t,x0,x1,x2> = toric_varieties.dP8() sage: P2.<y0,y1,y2> = toric_varieties.P2() sage: hom_set = dP8.Hom(P2) sage: fm = FanMorphism(identity_matrix(2), dP8.fan(), P2.fan()) sage: hom_set(fm) # calls hom_set._element_constructor_() Scheme morphism: From: 2-d CPR-Fano toric variety covered by 4 affine patches To: 2-d CPR-Fano toric variety covered by 3 affine patches Defn: Defined by sending Rational polyhedral fan in 2-d lattice N to Rational polyhedral fan in 2-d lattice N. A matrix will automatically be converted to a fan morphism:: sage: hom_set(identity_matrix(2)) Scheme morphism: From: 2-d CPR-Fano toric variety covered by 4 affine patches To: 2-d CPR-Fano toric variety covered by 3 affine patches Defn: Defined by sending Rational polyhedral fan in 2-d lattice N to Rational polyhedral fan in 2-d lattice N. Alternatively, one can use homogeneous polynomials to define morphisms:: sage: P2.inject_variables() Defining y0, y1, y2 sage: dP8.inject_variables() Defining t, x0, x1, x2 sage: hom_set([x0,x1,x2]) Scheme morphism: From: 2-d CPR-Fano toric variety covered by 4 affine patches To: 2-d CPR-Fano toric variety covered by 3 affine patches Defn: Defined on coordinates by sending [t : x0 : x1 : x2] to [x0 : x1 : x2] A morphism of the coordinate ring will also work:: sage: ring_hom = P2.coordinate_ring().hom([x0,x1,x2], dP8.coordinate_ring()) sage: ring_hom Ring morphism: From: Multivariate Polynomial Ring in y0, y1, y2 over Rational Field To: Multivariate Polynomial Ring in t, x0, x1, x2 over Rational Field Defn: y0 |--> x0 y1 |--> x1 y2 |--> x2 sage: hom_set(ring_hom) Scheme morphism: From: 2-d CPR-Fano toric variety covered by 4 affine patches To: 2-d CPR-Fano toric variety covered by 3 affine patches Defn: Defined on coordinates by sending [t : x0 : x1 : x2] to [x0 : x1 : x2] """ from sage.schemes.toric.morphism import SchemeMorphism_polynomial_toric_variety if isinstance(x, (list, tuple)): return SchemeMorphism_polynomial_toric_variety(self, x, check=check) if is_RingHomomorphism(x): assert x.domain() is self.codomain().coordinate_ring() assert x.codomain() is self.domain().coordinate_ring() return SchemeMorphism_polynomial_toric_variety(self, x.im_gens(), check=check) if is_Matrix(x): x = FanMorphism(x, self.domain().fan(), self.codomain().fan()) if isinstance(x, FanMorphism): if x.is_dominant(): from sage.schemes.toric.morphism import SchemeMorphism_fan_toric_variety_dominant return SchemeMorphism_fan_toric_variety_dominant(self, x, check=check) else: from sage.schemes.toric.morphism import SchemeMorphism_fan_toric_variety return SchemeMorphism_fan_toric_variety(self, x, check=check) raise TypeError("x must be a fan morphism or a list/tuple of polynomials")
def _element_constructor_(self, x, check=True): """ Construct a scheme morphism. INPUT: - `x` -- a ring morphism, or a list or a tuple that define a ring morphism. - ``check`` -- boolean (default: ``True``) passed onto functions called by this one to be more careful about input argument type checking. EXAMPLES:: sage: f = ZZ.hom(QQ); f Ring Coercion morphism: From: Integer Ring To: Rational Field sage: H = Hom(Spec(QQ, ZZ), Spec(ZZ)); H Set of morphisms From: Spectrum of Rational Field To: Spectrum of Integer Ring sage: phi = H(f); phi Affine Scheme morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring Defn: Ring Coercion morphism: From: Integer Ring To: Rational Field TESTS:: sage: H._element_constructor_(f) Affine Scheme morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring Defn: Ring Coercion morphism: From: Integer Ring To: Rational Field We illustrate input type checking:: sage: R.<x,y> = QQ[] sage: A.<x,y> = AffineSpace(R) sage: C = A.subscheme(x*y-1) sage: H = C.Hom(C); H Set of morphisms From: Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x*y - 1 To: Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x*y - 1 sage: H(1) Traceback (most recent call last): ... TypeError: x must be a ring homomorphism, list or tuple """ if isinstance(x, (list, tuple)): return self.domain()._morphism(self, x, check=check) if is_RingHomomorphism(x): return SchemeMorphism_spec(self, x, check=check) raise TypeError("x must be a ring homomorphism, list or tuple")
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 `\QQ`. 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 the following holds: - if ``point`` is True and ``self`` has a rational point, then ``S`` is a rational point, - if ``obstruction`` is True and ``self`` has no rational point, then ``S`` is a prime such that no rational point exists over the completion at ``S`` or `-1` if no point exists over `\RR`. Points and obstructions are cached, whenever they are found. Cached information is used if and only if ``read_cache`` is True. ALGORITHM: The parameter ``algorithm`` specifies the algorithm to be used: - ``'qfsolve'`` -- Use PARI/GP function ``qfsolve`` - ``'rnfisnorm'`` -- Use PARI's function rnfisnorm (cannot be combined with ``obstruction = True``) - ``'local'`` -- Check if a local solution exists for all primes and infinite places of `\QQ` and apply the Hasse principle (cannot be combined with ``point = True``) - ``'default'`` -- Use ``'qfsolve'`` - ``'magma'`` (requires Magma to be installed) -- delegates the task to the Magma computer algebra system. EXAMPLES:: sage: C = Conic(QQ, [1, 2, -3]) sage: C.has_rational_point(point = True) (True, (1 : 1 : 1)) sage: D = Conic(QQ, [1, 3, -5]) sage: D.has_rational_point(point = True) (False, 3) sage: P.<X,Y,Z> = QQ[] sage: E = Curve(X^2 + Y^2 + Z^2); E Projective Conic Curve over Rational Field defined by X^2 + Y^2 + Z^2 sage: E.has_rational_point(obstruction = True) (False, -1) The following would not terminate quickly with ``algorithm = 'rnfisnorm'`` :: 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 sage: C.has_rational_point(point=True, algorithm='magma', read_cache=False) # optional - magma (True, (30106379962113/7913 : 12747947692/7913 : 1)) TESTS: Create a bunch of conics over `\QQ`, check if ``has_rational_point`` runs without errors and returns consistent answers for all algorithms. Check if all points returned are valid. :: sage: l = Sequence(cartesian_product_iterator([[-1, 0, 1] for i in range(6)])) sage: c = [Conic(QQ, a) for a in l if a != [0,0,0] and a != (0,0,0,0,0,0)] sage: d = [] sage: d = [[C]+[C.has_rational_point(algorithm = algorithm, read_cache = False, obstruction = (algorithm != 'rnfisnorm'), point = (algorithm != 'local')) for algorithm in ['local', 'qfsolve', 'rnfisnorm']] for C in c[::10]] # long time: 7 seconds sage: assert all([e[1][0] == e[2][0] and e[1][0] == e[3][0] for e in d]) sage: assert all([e[0].defining_polynomial()(Sequence(e[i][1])) == 0 for e in d for i in [2,3] if e[1][0]]) """ if read_cache: if self._rational_point is not None: if point or obstruction: return True, self._rational_point else: return True if self._local_obstruction is not None: if point or obstruction: return False, self._local_obstruction else: return False if (not point) and self._finite_obstructions == [] and \ self._infinite_obstructions == []: if obstruction: return True, None return True if self.has_singular_point(): if point: return self.has_singular_point(point=True) if obstruction: return True, None return True if algorithm == 'default' or algorithm == 'qfsolve': M = self.symmetric_matrix() M *= lcm([t.denominator() for t in M.list()]) pt = qfsolve(M) if pt in ZZ: if self._local_obstruction is None: self._local_obstruction = pt if point or obstruction: return False, pt return False pt = self.point([pt[0], pt[1], pt[2]]) if point or obstruction: return True, pt return True ret = ProjectiveConic_number_field.has_rational_point( \ self, point = point, \ obstruction = obstruction, \ algorithm = algorithm, \ read_cache = read_cache) if point or obstruction: if is_RingHomomorphism(ret[1]): ret[1] = -1 return ret
def _element_constructor_(self, x, check=True): """ Construct a scheme morphism. INPUT: - `x` -- anything that defines a morphism of toric varieties. A matrix, fan morphism, or a list or tuple of homogeneous polynomials that define a morphism. - ``check`` -- boolean (default: ``True``) passed onto functions called by this to be more careful about input argument type checking OUTPUT: The morphism of toric varieties determined by ``x``. EXAMPLES: First, construct from fan morphism:: sage: dP8.<t,x0,x1,x2> = toric_varieties.dP8() sage: P2.<y0,y1,y2> = toric_varieties.P2() sage: hom_set = dP8.Hom(P2) sage: fm = FanMorphism(identity_matrix(2), dP8.fan(), P2.fan()) sage: hom_set(fm) # calls hom_set._element_constructor_() Scheme morphism: From: 2-d CPR-Fano toric variety covered by 4 affine patches To: 2-d CPR-Fano toric variety covered by 3 affine patches Defn: Defined by sending Rational polyhedral fan in 2-d lattice N to Rational polyhedral fan in 2-d lattice N. A matrix will automatically be converted to a fan morphism:: sage: hom_set(identity_matrix(2)) Scheme morphism: From: 2-d CPR-Fano toric variety covered by 4 affine patches To: 2-d CPR-Fano toric variety covered by 3 affine patches Defn: Defined by sending Rational polyhedral fan in 2-d lattice N to Rational polyhedral fan in 2-d lattice N. Alternatively, one can use homogeneous polynomials to define morphisms:: sage: P2.inject_variables() Defining y0, y1, y2 sage: dP8.inject_variables() Defining t, x0, x1, x2 sage: hom_set([x0,x1,x2]) Scheme morphism: From: 2-d CPR-Fano toric variety covered by 4 affine patches To: 2-d CPR-Fano toric variety covered by 3 affine patches Defn: Defined on coordinates by sending [t : x0 : x1 : x2] to [x0 : x1 : x2] A morphism of the coordinate ring will also work:: sage: ring_hom = P2.coordinate_ring().hom([x0,x1,x2], dP8.coordinate_ring()) sage: ring_hom Ring morphism: From: Multivariate Polynomial Ring in y0, y1, y2 over Rational Field To: Multivariate Polynomial Ring in t, x0, x1, x2 over Rational Field Defn: y0 |--> x0 y1 |--> x1 y2 |--> x2 sage: hom_set(ring_hom) Scheme morphism: From: 2-d CPR-Fano toric variety covered by 4 affine patches To: 2-d CPR-Fano toric variety covered by 3 affine patches Defn: Defined on coordinates by sending [t : x0 : x1 : x2] to [x0 : x1 : x2] """ from sage.schemes.toric.morphism import SchemeMorphism_polynomial_toric_variety if isinstance(x, (list, tuple)): return SchemeMorphism_polynomial_toric_variety(self, x, check=check) if is_RingHomomorphism(x): assert x.domain() is self.codomain().coordinate_ring() assert x.codomain() is self.domain().coordinate_ring() return SchemeMorphism_polynomial_toric_variety(self, x.im_gens(), check=check) from sage.schemes.toric.morphism import SchemeMorphism_fan_toric_variety if isinstance(x, FanMorphism): return SchemeMorphism_fan_toric_variety(self, x, check=check) if is_Matrix(x): fm = FanMorphism(x, self.domain().fan(), self.codomain().fan()) return SchemeMorphism_fan_toric_variety(self, fm, check=check) raise TypeError, "x must be a fan morphism or a list/tuple of polynomials"
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 `\QQ`. 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 the following holds: - if ``point`` is True and ``self`` has a rational point, then ``S`` is a rational point, - if ``obstruction`` is True and ``self`` has no rational point, then ``S`` is a prime such that no rational point exists over the completion at ``S`` or `-1` if no point exists over `\RR`. Points and obstructions are cached, whenever they are found. Cached information is used if and only if ``read_cache`` is True. ALGORITHM: The parameter ``algorithm`` specifies the algorithm to be used: - ``'qfsolve'`` -- Use PARI/GP function ``qfsolve`` - ``'rnfisnorm'`` -- Use PARI's function rnfisnorm (cannot be combined with ``obstruction = True``) - ``'local'`` -- Check if a local solution exists for all primes and infinite places of `\QQ` and apply the Hasse principle (cannot be combined with ``point = True``) - ``'default'`` -- Use ``'qfsolve'`` - ``'magma'`` (requires Magma to be installed) -- delegates the task to the Magma computer algebra system. EXAMPLES:: sage: C = Conic(QQ, [1, 2, -3]) sage: C.has_rational_point(point = True) (True, (1 : 1 : 1)) sage: D = Conic(QQ, [1, 3, -5]) sage: D.has_rational_point(point = True) (False, 3) sage: P.<X,Y,Z> = QQ[] sage: E = Curve(X^2 + Y^2 + Z^2); E Projective Conic Curve over Rational Field defined by X^2 + Y^2 + Z^2 sage: E.has_rational_point(obstruction = True) (False, -1) The following would not terminate quickly with ``algorithm = 'rnfisnorm'`` :: 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 sage: C.has_rational_point(point=True, algorithm='magma', read_cache=False) # optional - magma (True, (30106379962113/7913 : 12747947692/7913 : 1)) TESTS: Create a bunch of conics over `\QQ`, check if ``has_rational_point`` runs without errors and returns consistent answers for all algorithms. Check if all points returned are valid. :: sage: l = Sequence(cartesian_product_iterator([[-1, 0, 1] for i in range(6)])) sage: c = [Conic(QQ, a) for a in l if a != [0,0,0] and a != (0,0,0,0,0,0)] sage: d = [] sage: d = [[C]+[C.has_rational_point(algorithm = algorithm, read_cache = False, obstruction = (algorithm != 'rnfisnorm'), point = (algorithm != 'local')) for algorithm in ['local', 'qfsolve', 'rnfisnorm']] for C in c[::10]] # long time: 7 seconds sage: assert all([e[1][0] == e[2][0] and e[1][0] == e[3][0] for e in d]) sage: assert all([e[0].defining_polynomial()(Sequence(e[i][1])) == 0 for e in d for i in [2,3] if e[1][0]]) """ if read_cache: if self._rational_point is not None: if point or obstruction: return True, self._rational_point else: return True if self._local_obstruction is not None: if point or obstruction: return False, self._local_obstruction else: return False if (not point) and self._finite_obstructions == [] and \ self._infinite_obstructions == []: if obstruction: return True, None return True if self.has_singular_point(): if point: return self.has_singular_point(point = True) if obstruction: return True, None return True if algorithm == 'default' or algorithm == 'qfsolve': M = self.symmetric_matrix() M *= lcm([ t.denominator() for t in M.list() ]) pt = qfsolve(M) if pt in ZZ: if self._local_obstruction is None: self._local_obstruction = pt if point or obstruction: return False, pt return False pt = self.point([pt[0], pt[1], pt[2]]) if point or obstruction: return True, pt return True ret = ProjectiveConic_number_field.has_rational_point( \ self, point = point, \ obstruction = obstruction, \ algorithm = algorithm, \ read_cache = read_cache) if point or obstruction: if is_RingHomomorphism(ret[1]): ret[1] = -1 return ret