Skip to content

Commit

Permalink
Trac #7946: Fix TestSuite failures for schemes
Browse files Browse the repository at this point in the history
Consider the following situation:
{{{
sage: S = Spec(ZZ)
sage: x = S.an_element()
}}}
Running `TestSuite(S)` and `TestSuite(x)` yields several failures.  A
related problem is
{{{
sage: S
Spectrum of Integer Ring
sage: parent(x)
Set of rational points of Spectrum of Integer Ring
}}}
whereas we expect `parent(x) is S`.

Here is the complete `TestSuite` report:
{{{
sage: TestSuite(S).run()
Failure in _test_an_element:
Traceback (most recent call last):
...
NotImplementedError
------------------------------------------------------------
  Failure in _test_category:
  Traceback (most recent call last):
  ...
  AssertionError: False is not true
  ------------------------------------------------------------
  Failure in _test_pickling:
  Traceback (most recent call last):
  ...
  AssertionError: Point on Spectrum of Integer Ring defined by the
Principal ideal (991) of Integer Ring != Point on Spectrum of Integer
Ring defined by the Principal ideal (991) of Integer Ring
  ------------------------------------------------------------
  The following tests failed: _test_category, _test_pickling
Failure in _test_elements
Failure in _test_some_elements:
Traceback (most recent call last):
...
NotImplementedError
------------------------------------------------------------
The following tests failed: _test_an_element, _test_elements,
_test_some_elements
}}}
{{{
sage: TestSuite(x).run()
Failure in _test_category:
Traceback (most recent call last):
...
AssertionError: False is not true
------------------------------------------------------------
Failure in _test_pickling:
Traceback (most recent call last):
...
AssertionError: Point on Spectrum of Integer Ring defined by the
Principal ideal (991) of Integer Ring != Point on Spectrum of Integer
Ring defined by the Principal ideal (991) of Integer Ring
------------------------------------------------------------
The following tests failed: _test_category, _test_pickling
}}}

(Note: the `NotImplementedError` that one gets after applying #16158 is
a different one than before.)

URL: http://trac.sagemath.org/7946
Reported by: nthiery
Ticket author(s): Peter Bruin
Reviewer(s): Travis Scrimshaw
  • Loading branch information
Release Manager authored and vbraun committed Nov 14, 2014
2 parents 39abd9f + 5fd92ee commit f8b7591
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 27 deletions.
10 changes: 5 additions & 5 deletions src/sage/schemes/generic/morphism.py
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,10 @@ def _call_(self, x):
The image scheme point.
EXAMPLES::
EXAMPLES:
The following fails because inverse images of prime ideals
under ring homomorphisms are not yet implemented::
sage: R.<x> = PolynomialRing(QQ)
sage: phi = R.hom([QQ(7)])
Expand All @@ -791,10 +794,7 @@ def _call_(self, x):
sage: f(X.an_element()) # indirect doctest
Traceback (most recent call last):
...
TypeError: Point on Spectrum of Rational Field defined by the
Principal ideal (0) of Rational Field fails to convert into the
map's domain Spectrum of Rational Field, but a `pushforward`
method is not properly implemented
NotImplementedError
"""
# By virtue of argument preprocessing in __call__, we can assume that
# x is a topological scheme point of self
Expand Down
58 changes: 48 additions & 10 deletions src/sage/schemes/generic/point.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ class SchemePoint(Element):
Base class for points on a scheme, either topological or defined
by a morphism.
"""
def __init__(self, S):
def __init__(self, S, parent=None):
"""
INPUT:
- ``S`` -- a scheme
- ``S`` - a scheme
- ``parent`` -- the parent in which to construct this point
TESTS::
Expand All @@ -34,7 +35,7 @@ def __init__(self, S):
sage: P = SchemePoint(S); P
Point on Spectrum of Integer Ring
"""
Element.__init__(self, S.Hom(S))
Element.__init__(self, parent)
self.__S = S

def scheme(self):
Expand Down Expand Up @@ -74,19 +75,40 @@ def is_SchemeTopologicalPoint(x):
return isinstance(x, SchemeTopologicalPoint)

class SchemeTopologicalPoint(SchemePoint):
pass
"""
Base class for topological points on schemes.
"""
def __init__(self, S):
"""
INPUT:
- ``S`` -- a scheme
TESTS:
The parent of a topological point is the scheme on which it
lies (see :trac:`7946`)::
sage: R = Zmod(8)
sage: S = Spec(R)
sage: x = S(R.ideal(2))
sage: isinstance(x, sage.schemes.generic.point.SchemeTopologicalPoint)
True
sage: x.parent() is S
True
"""
SchemePoint.__init__(self, S, parent=S)

class SchemeTopologicalPoint_affine_open(SchemeTopologicalPoint):
def __init__(self, u, x):
"""
INPUT:
- ``u`` -- morphism with domain an affine scheme `U`
- ``u`` - morphism with domain U an affine scheme
- ``x`` - point on U
- ``x`` -- topological point on `U`
"""
SchemePoint.__init__(self, u.codomain())
SchemeTopologicalPoint.__init__(self, u.codomain())
self.__u = u
self.__x = x

Expand Down Expand Up @@ -147,8 +169,10 @@ def __init__(self, S, P, check=False):
"""
R = S.coordinate_ring()
from sage.rings.ideal import is_Ideal
if not (is_Ideal(P) and P.ring() is R):
if not is_Ideal(P):
P = R.ideal(P)
elif P.ring() is not R:
P = R.ideal(P.gens())
# ideally we would have check=True by default, but
# unfortunately is_prime() is only implemented in a small
# number of cases
Expand Down Expand Up @@ -186,6 +210,20 @@ def prime_ideal(self):
"""
return self.__P

def __cmp__(self, other):
"""
Compare ``self`` to ``other``.
TESTS::
sage: S = Spec(ZZ)
sage: x = S(ZZ.ideal(5))
sage: y = S(ZZ.ideal(7))
sage: x == y
False
"""
return cmp(self.__P, other.__P)

########################################################
# Points on a scheme defined by a morphism
########################################################
Expand All @@ -201,7 +239,7 @@ def __init__(self, f):
- ``f`` - a morphism of schemes
"""
SchemePoint.__init__(self, f.codomain())
SchemePoint.__init__(self, f.codomain(), parent=f.parent())
self.__f = f

def _repr_(self):
Expand Down
80 changes: 69 additions & 11 deletions src/sage/schemes/generic/scheme.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,19 @@
# http://www.gnu.org/licenses/
#*****************************************************************************


from sage.structure.parent import Parent
from sage.misc.all import cached_method
from sage.rings.all import (IntegerRing,
ZZ, GF, PowerSeriesRing,
Rationals)

from sage.rings.commutative_ring import is_CommutativeRing
from sage.rings.ideal import is_Ideal
from sage.rings.morphism import is_RingHomomorphism
from sage.structure.unique_representation import UniqueRepresentation

from sage.schemes.generic.point import SchemeTopologicalPoint_prime_ideal

def is_Scheme(x):
"""
Test whether ``x`` is a scheme.
Expand Down Expand Up @@ -93,14 +95,16 @@ def __init__(self, X=None, category=None):
"""
Construct a scheme.
TESTS::
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(skip = ["_test_an_element", "_test_elements",
... "_test_some_elements", "_test_category"]) # See #7946
sage: TestSuite(X).run()
"""
from sage.schemes.generic.morphism import is_SchemeMorphism

Expand Down Expand Up @@ -162,7 +166,7 @@ def _morphism(self, *args, **kwds):
TESTS:
This shows that issue at trac ticket 7389 is solved::
This shows that issue at :trac:`7389` is solved::
sage: S = Spec(ZZ)
sage: f = S.identity_morphism()
Expand Down Expand Up @@ -912,7 +916,7 @@ def __call__(self, *args):
sage: P = S(ZZ.ideal(3)); P
Point on Spectrum of Integer Ring defined by the Principal ideal (3) of Integer Ring
sage: type(P)
<class 'sage.schemes.generic.point.SchemeTopologicalPoint_prime_ideal'>
<class 'sage.schemes.generic.point.AffineScheme_with_category.element_class'>
sage: S(ZZ.ideal(next_prime(1000000)))
Point on Spectrum of Integer Ring defined by the Principal ideal (1000003) of Integer Ring
Expand All @@ -936,15 +940,69 @@ def __call__(self, *args):
Set of morphisms
From: Spectrum of Integer Ring
To: Spectrum of Integer Ring
For affine or projective varieties, passing the correct number
of elements of the base ring constructs the rational point
with these elements as coordinates::
sage: S = AffineSpace(ZZ, 1)
sage: S(0)
(0)
To prevent confusion with this usage, topological points must
be constructed by explicitly specifying a prime ideal, not
just generators::
sage: R = S.coordinate_ring()
sage: S(R.ideal(0))
Point on Affine Space of dimension 1 over Integer Ring defined by the Ideal (0) of Multivariate Polynomial Ring in x over Integer Ring
This explains why the following example raises an error rather
than constructing the topological point defined by the prime
ideal `(0)` as one might expect::
sage: S = Spec(ZZ)
sage: S(0)
Traceback (most recent call last):
...
TypeError: cannot call Spectrum of Integer Ring with arguments (0,)
"""
if len(args) == 1:
from sage.rings.ideal import is_Ideal
x = args[0]
if is_Ideal(x) and x.ring() is self.coordinate_ring():
from sage.schemes.generic.point import SchemeTopologicalPoint_prime_ideal
return SchemeTopologicalPoint_prime_ideal(self, x)
if ((isinstance(x, self.element_class) and (x.parent() is self or x.parent() == self))
or (is_Ideal(x) and x.ring() is self.coordinate_ring())):
# Construct a topological point from x.
return self._element_constructor_(x)
try:
# Construct a scheme homset or a scheme-valued point from
# args using the generic Scheme.__call__() method.
return super(AffineScheme, self).__call__(*args)
except NotImplementedError:
# This arises from self._morphism() not being implemented.
# We must convert it into a TypeError to keep the coercion
# system working.
raise TypeError('cannot call %s with arguments %s' % (self, args))

Element = SchemeTopologicalPoint_prime_ideal

return super(AffineScheme, self).__call__(*args)
def _element_constructor_(self, x):
"""
Construct a topological point from `x`.
TESTS::
sage: S = Spec(ZZ)
sage: S(ZZ.ideal(0))
Point on Spectrum of Integer Ring defined by the Principal ideal (0) of Integer Ring
"""
if isinstance(x, self.element_class):
if x.parent() is self:
return x
elif x.parent() == self:
return self.element_class(self, x.prime_ideal())
elif is_Ideal(x) and x.ring() is self.coordinate_ring():
return self.element_class(self, x)
raise TypeError('cannot convert %s to a topological point of %s' % (x, self))

def _an_element_(self):
r"""
Expand Down
2 changes: 1 addition & 1 deletion src/sage/schemes/generic/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def Spec(R, S=None):
Spectrum of Multivariate Polynomial Ring in x0, x1, x2 over Rational Field
sage: X = Spec(PolynomialRing(GF(49,'a'), 3, 'x')); X
Spectrum of Multivariate Polynomial Ring in x0, x1, x2 over Finite Field in a of size 7^2
sage: TestSuite(X).run(skip=["_test_an_element", "_test_elements", "_test_some_elements"])
sage: TestSuite(X).run()
Applying ``Spec`` twice to the same ring gives identical output
(see :trac:`17008`)::
Expand Down

0 comments on commit f8b7591

Please sign in to comment.