Skip to content

Commit 272c557

Browse files
author
Release Manager
committed
Trac #31668: Run TestSuite on polynomial rings
#27364 fixes a bug that `_test_construction` should have found -- except `TestSuite` is not called at all for any multivariate polynomial rings. We add a bunch of `TestSuite` calls for the rings constructed as examples in `polynomial_ring_constructor`. Many tests are failing; we skip these tests to make this ticket mergeable. In follow-up tickets, these failures should be fixed. Related: - https://groups.google.com/g/sage-devel/c/vGzNJKAQWbs/m/nhm1iIPWAwAJ - https://groups.google.com/g/sage-devel/c/xiH9d4oBwaI/m/9Q0U1bUlAwAJ URL: https://trac.sagemath.org/31668 Reported by: mkoeppe Ticket author(s): Matthias Koeppe Reviewer(s): Vincent Delecroix, Travis Scrimshaw
2 parents 6f8fb9b + 73dfeb8 commit 272c557

File tree

10 files changed

+159
-16
lines changed

10 files changed

+159
-16
lines changed

build/pkgs/configure/checksums.ini

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
tarball=configure-VERSION.tar.gz
2-
sha1=c39297a2d58601cfa6baa9045140c3485ee9ffab
3-
md5=534693f57e442ff0cd9e4cfbc4768ebc
4-
cksum=82888323
2+
sha1=db995d44fdbaf1c20e95de3257a54d7e71e01dbb
3+
md5=aa42a4557361c1049b00a8f9b275a84e
4+
cksum=1730113298
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2c3a4cef8d3ce703174c93a92ed0efcbecdd36ba
1+
f96de9c84911bea01d729290cf707e3bab988864

src/sage/categories/pushout.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,7 @@ class PolynomialFunctor(ConstructionFunctor):
833833
"""
834834
rank = 9
835835

836-
def __init__(self, var, multi_variate=False, sparse=False):
836+
def __init__(self, var, multi_variate=False, sparse=False, implementation=None):
837837
"""
838838
TESTS::
839839
@@ -857,6 +857,7 @@ def __init__(self, var, multi_variate=False, sparse=False):
857857
self.var = var
858858
self.multi_variate = multi_variate
859859
self.sparse = sparse
860+
self.implementation = implementation
860861

861862
def _apply_functor(self, R):
862863
"""
@@ -870,7 +871,10 @@ def _apply_functor(self, R):
870871
871872
"""
872873
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
873-
return PolynomialRing(R, self.var, sparse=self.sparse)
874+
kwds = {}
875+
if self.implementation:
876+
kwds['implementation'] = self.implementation
877+
return PolynomialRing(R, self.var, sparse=self.sparse, **kwds)
874878

875879
def _apply_functor_to_morphism(self, f):
876880
"""

src/sage/rings/polynomial/multi_polynomial.pyx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2575,6 +2575,43 @@ cdef class MPolynomial(CommutativeRingElement):
25752575
d = self.dict()
25762576
return all(c.is_nilpotent() for c in d.values())
25772577

2578+
def _test_subs(self, tester=None, **options):
2579+
r"""
2580+
Run some tests using the ``subs`` method.
2581+
2582+
TESTS::
2583+
2584+
sage: R.<x,y> = QQbar[]
2585+
sage: (x + y)._test_subs()
2586+
"""
2587+
if tester is None:
2588+
tester = self._tester(**options)
2589+
2590+
gens = self.parent().gens()
2591+
2592+
if gens:
2593+
# substituting all variables (in a polynomial ring with variables) with 0
2594+
d = {str(gen): 0 for gen in gens}
2595+
tester.assertEqual(self.subs(**d).parent(), self.parent().base_ring())
2596+
2597+
# substituting all variables (in a polynomial ring with variables)
2598+
# with elements of another ring
2599+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
2600+
other = PolynomialRing(self.parent().base_ring(), 'other', len(gens))
2601+
other_gens = other.gens()
2602+
d = {str(gen): other_gen for gen, other_gen in zip(gens, other_gens)}
2603+
tester.assertEqual(self.subs(**d).parent(), other)
2604+
2605+
if len(gens) > 1:
2606+
# substituting one variable (in a polynomial ring with variables) with 0
2607+
d = {str(gens[0]): 0}
2608+
tester.assertEqual(self.subs(**d).parent(), self.parent())
2609+
2610+
# test error checking: partial substitution by elements
2611+
# from another ring is not allowed
2612+
d = {str(gens[0]): other_gens[0]}
2613+
with tester.assertRaises((ValueError, TypeError)):
2614+
self.subs(**d)
25782615

25792616
cdef remove_from_tuple(e, int ind):
25802617
w = list(e)

src/sage/rings/polynomial/multi_polynomial_ring_base.pyx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,6 +1299,27 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing):
12991299

13001300
return self(dict(zip(M, C)))
13011301

1302+
def some_elements(self):
1303+
r"""
1304+
Return a list of polynomials.
1305+
1306+
This is typically used for running generic tests.
1307+
1308+
EXAMPLES::
1309+
1310+
sage: R.<x,y> = QQ[]
1311+
sage: R.some_elements()
1312+
[x, y, x + y, x^2 + x*y, 0, 1]
1313+
1314+
"""
1315+
R = self.base_ring()
1316+
L = list(self.gens())
1317+
if L:
1318+
L.append(L[0] + L[-1])
1319+
L.append(L[0] * L[-1])
1320+
L.extend([self.zero(), self.one()])
1321+
return L
1322+
13021323
def change_ring(self, base_ring=None, names=None, order=None):
13031324
"""
13041325
Return a new multivariate polynomial ring which isomorphic to

src/sage/rings/polynomial/pbori/pbori.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ cdef class BooleanPolynomialRing(MPolynomialRing_base):
308308
True
309309
sage: x2 > x3
310310
True
311-
sage: TestSuite(P).run()
311+
sage: TestSuite(P).run(skip=["_test_zero_divisors", "_test_elements"])
312312
313313
Boolean polynomial rings are unique parent structures. We
314314
thus have::

src/sage/rings/polynomial/polynomial_ring.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,9 @@ def flattening_morphism(self):
619619
return IdentityMorphism(self)
620620

621621
def construction(self):
622+
"""
623+
Return the construction functor.
624+
"""
622625
return categories.pushout.PolynomialFunctor(self.variable_name(), sparse=self.__is_sparse), self.base_ring()
623626

624627
def completion(self, p, prec=20, extras=None):
@@ -1951,6 +1954,38 @@ def _repr_(self):
19511954
s = PolynomialRing_commutative._repr_(self)
19521955
return s + self._implementation_repr
19531956

1957+
def construction(self):
1958+
"""
1959+
Return the construction functor.
1960+
1961+
EXAMPLES::
1962+
1963+
sage: from sage.rings.polynomial.polynomial_ring import PolynomialRing_integral_domain as PRing
1964+
sage: R = PRing(ZZ, 'x'); R
1965+
Univariate Polynomial Ring in x over Integer Ring
1966+
sage: functor, arg = R.construction(); functor, arg
1967+
(Poly[x], Integer Ring)
1968+
sage: functor.implementation is None
1969+
True
1970+
1971+
sage: R = PRing(ZZ, 'x', implementation='NTL'); R
1972+
Univariate Polynomial Ring in x over Integer Ring (using NTL)
1973+
sage: functor, arg = R.construction(); functor, arg
1974+
(Poly[x], Integer Ring)
1975+
sage: functor.implementation
1976+
'NTL'
1977+
"""
1978+
implementation = None
1979+
# NOTE: This is obviously not a complete solution. The parents
1980+
# don't keep track in a clean way what the implementation is.
1981+
# Trac #31852 is the task of finding a general solution for
1982+
# construction functors of parents with multiple
1983+
# implementations, such as MatrixSpace, Polyhedron, and
1984+
# PolynomialRing.
1985+
if 'NTL' in self._implementation_repr:
1986+
implementation = 'NTL'
1987+
return categories.pushout.PolynomialFunctor(self.variable_name(), sparse=self.is_sparse(),
1988+
implementation=implementation), self.base_ring()
19541989

19551990
class PolynomialRing_field(PolynomialRing_integral_domain,
19561991
ring.PrincipalIdealDomain):

src/sage/rings/polynomial/polynomial_ring_constructor.py

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -418,22 +418,22 @@ def PolynomialRing(base_ring, *args, **kwds):
418418
419419
The generic implementation is different in some cases::
420420
421-
sage: R = PolynomialRing(GF(2), 'j', implementation="generic"); type(R)
421+
sage: R = PolynomialRing(GF(2), 'j', implementation="generic"); TestSuite(R).run(skip=['_test_construction', '_test_pickling']); type(R)
422422
<class 'sage.rings.polynomial.polynomial_ring.PolynomialRing_field_with_category'>
423-
sage: S = PolynomialRing(GF(2), 'j'); type(S)
423+
sage: S = PolynomialRing(GF(2), 'j'); TestSuite(S).run(); type(S)
424424
<class 'sage.rings.polynomial.polynomial_ring.PolynomialRing_dense_mod_p_with_category'>
425425
426-
sage: R = PolynomialRing(ZZ, 'x,y', implementation="generic"); type(R)
426+
sage: R = PolynomialRing(ZZ, 'x,y', implementation="generic"); TestSuite(R).run(skip=['_test_elements', '_test_elements_eq_transitive']); type(R)
427427
<class 'sage.rings.polynomial.multi_polynomial_ring.MPolynomialRing_polydict_domain_with_category'>
428-
sage: S = PolynomialRing(ZZ, 'x,y'); type(S)
428+
sage: S = PolynomialRing(ZZ, 'x,y'); TestSuite(S).run(skip='_test_elements'); type(S)
429429
<class 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomialRing_libsingular'>
430430
431431
Sparse univariate polynomials only support a generic
432432
implementation::
433433
434-
sage: R = PolynomialRing(ZZ, 'j', sparse=True); type(R)
434+
sage: R = PolynomialRing(ZZ, 'j', sparse=True); TestSuite(R).run(); type(R)
435435
<class 'sage.rings.polynomial.polynomial_ring.PolynomialRing_integral_domain_with_category'>
436-
sage: R = PolynomialRing(GF(49), 'j', sparse=True); type(R)
436+
sage: R = PolynomialRing(GF(49), 'j', sparse=True); TestSuite(R).run(); type(R)
437437
<class 'sage.rings.polynomial.polynomial_ring.PolynomialRing_field_with_category'>
438438
439439
If the requested implementation is not known or not supported for
@@ -487,11 +487,14 @@ def PolynomialRing(base_ring, *args, **kwds):
487487
:trac:`7712` and :trac:`13760` are fixed::
488488
489489
sage: P.<y,z> = PolynomialRing(RealIntervalField(2))
490+
sage: TestSuite(P).run(skip=['_test_elements', '_test_elements_eq_transitive'])
490491
sage: Q.<x> = PolynomialRing(P)
492+
sage: TestSuite(Q).run(skip=['_test_additive_associativity', '_test_associativity', '_test_distributivity', '_test_prod'])
491493
sage: C = (y-x)^3
492494
sage: C(y/2)
493495
1.?*y^3
494496
sage: R.<x,y> = PolynomialRing(RIF,2)
497+
sage: TestSuite(R).run(skip=['_test_elements', '_test_elements_eq_transitive'])
495498
sage: RIF(-2,1)*x
496499
0.?e1*x
497500
@@ -549,6 +552,49 @@ def PolynomialRing(base_ring, *args, **kwds):
549552
Traceback (most recent call last):
550553
...
551554
TypeError: unable to convert 'x' to an integer
555+
556+
We run the testsuite for various polynomial rings, skipping tests that currently fail::
557+
558+
sage: R.<w> = PolynomialRing(PolynomialRing(GF(7),'k')); TestSuite(R).run(); R
559+
Univariate Polynomial Ring in w over Univariate Polynomial Ring in k over Finite Field of size 7
560+
sage: ZxNTL = PolynomialRing(ZZ, 'x', implementation='NTL'); TestSuite(ZxNTL).run(skip='_test_pickling'); ZxNTL
561+
Univariate Polynomial Ring in x over Integer Ring (using NTL)
562+
sage: ZxFLINT = PolynomialRing(ZZ, 'x', implementation='FLINT'); TestSuite(ZxFLINT).run(); ZxFLINT
563+
Univariate Polynomial Ring in x over Integer Ring
564+
sage: Zx = PolynomialRing(ZZ, 'x', implementation='generic'); TestSuite(Zx).run(skip=['_test_construction', '_test_pickling']); Zx
565+
Univariate Polynomial Ring in x over Integer Ring
566+
sage: R = PolynomialRing(QQ, 'a,b,c'); TestSuite(R).run(skip='_test_elements'); R
567+
Multivariate Polynomial Ring in a, b, c over Rational Field
568+
sage: R = PolynomialRing(QQ, 'x,y,z', order='degrevlex'); TestSuite(R).run(skip='_test_elements'); R
569+
Multivariate Polynomial Ring in x, y, z over Rational Field
570+
sage: S = PolynomialRing(QQ, 'x,y,z', order='invlex'); TestSuite(S).run(skip=['_test_construction', '_test_elements']); S
571+
Multivariate Polynomial Ring in x, y, z over Rational Field
572+
sage: Q0 = PolynomialRing(QQ,[]); TestSuite(Q0).run(skip=['_test_elements', '_test_elements_eq_transitive', '_test_gcd_vs_xgcd', '_test_quo_rem']); Q0
573+
Multivariate Polynomial Ring in no variables over Rational Field
574+
sage: P.<x> = PolynomialRing(QQ, implementation="singular"); TestSuite(P).run(skip=['_test_construction', '_test_elements', '_test_euclidean_degree', '_test_quo_rem']); P
575+
Multivariate Polynomial Ring in x over Rational Field
576+
sage: Q1 = PolynomialRing(QQ,"x",1); TestSuite(Q1).run(skip=['_test_construction', '_test_elements', '_test_euclidean_degree', '_test_quo_rem']); Q1
577+
Multivariate Polynomial Ring in x over Rational Field
578+
sage: Q0 = PolynomialRing(QQ,"x",0); TestSuite(Q0).run(skip=['_test_elements', '_test_elements_eq_transitive', '_test_gcd_vs_xgcd', '_test_quo_rem']); Q0
579+
Multivariate Polynomial Ring in no variables over Rational Field
580+
sage: R = PolynomialRing(GF(2), 'j', implementation="generic"); TestSuite(R).run(skip=['_test_construction', '_test_pickling']); type(R)
581+
<class 'sage.rings.polynomial.polynomial_ring.PolynomialRing_field_with_category'>
582+
sage: S = PolynomialRing(GF(2), 'j'); TestSuite(S).run(); type(S)
583+
<class 'sage.rings.polynomial.polynomial_ring.PolynomialRing_dense_mod_p_with_category'>
584+
sage: R = PolynomialRing(ZZ, 'x,y', implementation="generic"); TestSuite(R).run(skip=['_test_elements', '_test_elements_eq_transitive']); type(R)
585+
<class 'sage.rings.polynomial.multi_polynomial_ring.MPolynomialRing_polydict_domain_with_category'>
586+
sage: S = PolynomialRing(ZZ, 'x,y'); TestSuite(S).run(skip='_test_elements'); type(S)
587+
<class 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomialRing_libsingular'>
588+
sage: R = PolynomialRing(ZZ, 'j', sparse=True); TestSuite(R).run(); type(R)
589+
<class 'sage.rings.polynomial.polynomial_ring.PolynomialRing_integral_domain_with_category'>
590+
sage: R = PolynomialRing(GF(49), 'j', sparse=True); TestSuite(R).run(); type(R)
591+
<class 'sage.rings.polynomial.polynomial_ring.PolynomialRing_field_with_category'>
592+
sage: P.<y,z> = PolynomialRing(RealIntervalField(2))
593+
sage: TestSuite(P).run(skip=['_test_elements', '_test_elements_eq_transitive'])
594+
sage: Q.<x> = PolynomialRing(P)
595+
sage: TestSuite(Q).run(skip=['_test_additive_associativity', '_test_associativity', '_test_distributivity', '_test_prod'])
596+
sage: R.<x,y> = PolynomialRing(RIF,2)
597+
sage: TestSuite(R).run(skip=['_test_elements', '_test_elements_eq_transitive'])
552598
"""
553599
if not ring.is_Ring(base_ring):
554600
raise TypeError("base_ring {!r} must be a ring".format(base_ring))

src/sage/rings/ring.pyx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ cdef class Ring(ParentWithGens):
132132
running ._test_some_elements() . . . pass
133133
running ._test_zero() . . . pass
134134
running ._test_zero_divisors() . . . pass
135-
sage: TestSuite(QQ['x','y']).run()
136-
sage: TestSuite(ZZ['x','y']).run()
135+
sage: TestSuite(QQ['x','y']).run(skip='_test_elements')
136+
sage: TestSuite(ZZ['x','y']).run(skip='_test_elements')
137137
sage: TestSuite(ZZ['x','y']['t']).run()
138138
139139
Test against another bug fixed in :trac:`9944`::

src/sage/sets/image_set.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def __init__(self, map, domain_subset, *, category=None, is_injective=None, inve
7979
sage: f = H(lambda v: v[0]*x + v[1]*(x^2-y) + v[2]^2*(y+2) + v[3] - v[0]^2)
8080
sage: Im = f.image()
8181
sage: TestSuite(Im).run(skip=['_test_an_element', '_test_pickling',
82-
....: '_test_some_elements'])
82+
....: '_test_some_elements', '_test_elements'])
8383
"""
8484
if not is_Parent(domain_subset):
8585
from sage.sets.set import Set

0 commit comments

Comments
 (0)