Skip to content

Commit 0c12be1

Browse files
author
Release Manager
committed
Trac #33757: commutativity test
In several places the commutativity of a ring is tested via `isinstance(base_ring, sage.rings.ring.CommutativeRing)` rather than `base_ring in sage.categories.commutative_rings.CommutativeRings()`. This makes it impossible to have a nicely interacting ring that would just inherit from `Parent`. Note that the answers from `ring.is_commutative()` and `ring in CommutativeRings()` could be different : the former tests the category initialization whether the second could involve some (possibly costly) checks. The same remark applies to - integral domains - fields - ... See also #32810 URL: https://trac.sagemath.org/33757 Reported by: vdelecroix Ticket author(s): Frédéric Chapoton Reviewer(s): Travis Scrimshaw
2 parents ba1e689 + b9e410d commit 0c12be1

File tree

14 files changed

+94
-91
lines changed

14 files changed

+94
-91
lines changed

src/sage/categories/schemes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,11 @@ def _call_(self, x):
137137
from sage.schemes.generic.morphism import is_SchemeMorphism
138138
if is_SchemeMorphism(x):
139139
return x
140-
from sage.rings.ring import CommutativeRing
140+
from sage.categories.commutative_rings import CommutativeRings
141141
from sage.schemes.generic.spec import Spec
142142
from sage.categories.map import Map
143143
from sage.categories.all import Rings
144-
if isinstance(x, CommutativeRing):
144+
if x in CommutativeRings():
145145
return Spec(x)
146146
elif isinstance(x, Map) and x.category_for().is_subcategory(Rings()):
147147
# x is a morphism of Rings

src/sage/dynamics/arithmetic_dynamics/wehlerK3.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,12 @@
2727

2828
from sage.calculus.functions import jacobian
2929
from sage.categories.fields import Fields
30+
from sage.categories.commutative_rings import CommutativeRings
3031
from sage.categories.number_fields import NumberFields
3132
from sage.misc.functional import sqrt
3233
from sage.misc.cachefunc import cached_method
3334
from sage.misc.mrange import xmrange
34-
from sage.rings.all import CommutativeRing
3535
from sage.rings.finite_rings.finite_field_constructor import GF
36-
from sage.rings.finite_rings.finite_field_base import is_FiniteField
3736
from sage.rings.fraction_field import FractionField
3837
from sage.rings.integer_ring import ZZ
3938
from sage.rings.number_field.order import is_NumberFieldOrder
@@ -48,6 +47,7 @@
4847

4948
_NumberFields = NumberFields()
5049
_Fields = Fields()
50+
_CommutativeRings = CommutativeRings()
5151

5252

5353
def WehlerK3Surface(polys):
@@ -75,14 +75,12 @@ def WehlerK3Surface(polys):
7575

7676
R = polys[0].parent().base_ring()
7777
if R in _Fields:
78-
if is_FiniteField(R):
78+
if R in _Fields.Finite():
7979
return WehlerK3Surface_finite_field(polys)
80-
else:
81-
return WehlerK3Surface_field(polys)
82-
elif isinstance(R, CommutativeRing):
80+
return WehlerK3Surface_field(polys)
81+
if R in _CommutativeRings:
8382
return WehlerK3Surface_ring(polys)
84-
else:
85-
raise TypeError("R (= %s) must be a commutative ring" % R)
83+
raise TypeError("R (= %s) must be a commutative ring" % R)
8684

8785

8886
def random_WehlerK3Surface(PP):
@@ -131,7 +129,7 @@ class WehlerK3Surface_ring(AlgebraicScheme_subscheme_product_projective):
131129
x*y*v^2 + z^2*u*w
132130
"""
133131
def __init__(self, polys):
134-
if not isinstance(polys, (list,tuple)):
132+
if not isinstance(polys, (list, tuple)):
135133
raise TypeError("polys must be a list or tuple of polynomials")
136134
R = polys[0].parent()
137135
vars = R.variable_names()
@@ -2295,7 +2293,6 @@ def orbit_phi(self, P, N, **kwds):
22952293
: 3992260691327218828582255586014718568398539828275296031491644987908/18550615454277582153932951051931712107449915856862264913424670784695 :
22962294
1 , -117756062505511/54767410965117 : -23134047983794359/37466994368025041 : 1)]
22972295
"""
2298-
22992296
if not isinstance(N, (list, tuple)):
23002297
N = [0, N]
23012298
try:

src/sage/geometry/polyhedron/parent.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
from sage.rings.integer_ring import ZZ
2020
from sage.rings.rational_field import QQ
2121
from sage.rings.real_double import RDF
22-
from sage.rings.ring import CommutativeRing
2322
from sage.categories.fields import Fields
2423
from sage.categories.rings import Rings
2524
from sage.categories.modules import Modules
@@ -1012,7 +1011,7 @@ def _get_action_(self, other, op, self_is_left):
10121011
extended_self._internal_coerce_map_from(self).__copy__())
10131012
return action
10141013

1015-
if op is operator.mul and isinstance(other, CommutativeRing):
1014+
if op is operator.mul and other in Rings().Commutative():
10161015
ring = self._coerce_base_ring(other)
10171016
if ring is self.base_ring():
10181017
return ActedUponAction(other, self, not self_is_left)

src/sage/rings/complex_double.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ cdef class ComplexDoubleField_class(sage.rings.abc.ComplexDoubleField):
174174
(-1.0, -1.0 + 1.2246...e-16*I, False)
175175
"""
176176
from sage.categories.fields import Fields
177-
ParentWithGens.__init__(self, self, ('I',), normalize=False, category=Fields().Metric().Complete())
177+
ParentWithGens.__init__(self, self, ('I',), normalize=False, category=Fields().Infinite().Metric().Complete())
178178
self._populate_coercion_lists_()
179179

180180
def __reduce__(self):

src/sage/rings/ideal.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
If `R` is non-commutative, the former creates a left and the latter
1212
a right ideal, and ``R*[a,b,...]*R`` creates a two-sided ideal.
1313
"""
14-
#*****************************************************************************
14+
# ****************************************************************************
1515
# Copyright (C) 2005 William Stein <[email protected]>
1616
#
1717
# Distributed under the terms of the GNU General Public License (GPL)
@@ -23,16 +23,23 @@
2323
#
2424
# The full text of the GPL is available at:
2525
#
26-
# http://www.gnu.org/licenses/
27-
#*****************************************************************************
26+
# https://www.gnu.org/licenses/
27+
# ****************************************************************************
2828

2929
from types import GeneratorType
3030

31-
import sage.rings.ring
31+
from sage.categories.rings import Rings
32+
from sage.categories.fields import Fields
3233
from sage.structure.element import MonoidElement
3334
from sage.structure.richcmp import rich_to_bool, richcmp
3435
from sage.structure.sequence import Sequence
3536

37+
38+
# for efficiency
39+
_Rings = Rings()
40+
_Fields = Fields()
41+
42+
3643
def Ideal(*args, **kwds):
3744
r"""
3845
Create the ideal in ring with given generators.
@@ -171,7 +178,7 @@ def Ideal(*args, **kwds):
171178
first = args[0]
172179

173180
inferred_field = False
174-
if not isinstance(first, sage.rings.ring.Ring):
181+
if first not in _Rings:
175182
if isinstance(first, Ideal_generic) and len(args) == 1:
176183
R = first.ring()
177184
gens = first.gens()
@@ -182,12 +189,12 @@ def Ideal(*args, **kwds):
182189
gens = args
183190
gens = Sequence(gens)
184191
R = gens.universe()
185-
inferred_field = isinstance(R, sage.rings.ring.Field)
192+
inferred_field = R in _Fields
186193
else:
187194
R = first
188195
gens = args[1:]
189196

190-
if not isinstance(R, sage.rings.ring.CommutativeRing):
197+
if R not in _Rings.Commutative():
191198
raise TypeError("R must be a commutative ring")
192199

193200
I = R.ideal(*gens, **kwds)
@@ -200,6 +207,7 @@ def Ideal(*args, **kwds):
200207

201208
return I
202209

210+
203211
def is_Ideal(x):
204212
r"""
205213
Return ``True`` if object is an ideal of a ring.

src/sage/rings/polynomial/polynomial_ring_constructor.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,15 @@
1111
rings but rather quotients of them (see module
1212
:mod:`sage.rings.polynomial.pbori` for more details).
1313
"""
14-
15-
#*****************************************************************************
14+
# ****************************************************************************
1615
# Copyright (C) 2006 William Stein <[email protected]>
1716
#
1817
# This program is free software: you can redistribute it and/or modify
1918
# it under the terms of the GNU General Public License as published by
2019
# the Free Software Foundation, either version 2 of the License, or
2120
# (at your option) any later version.
22-
# http://www.gnu.org/licenses/
23-
#*****************************************************************************
24-
25-
21+
# https://www.gnu.org/licenses/
22+
# ****************************************************************************
2623
from sage.structure.category_object import normalize_names
2724
import sage.rings.ring as ring
2825
import sage.rings.padics.padic_base_leaves as padic_base_leaves
@@ -32,16 +29,19 @@
3229
from sage.rings.finite_rings.finite_field_base import is_FiniteField
3330

3431
from sage.misc.cachefunc import weak_cached_function
32+
import sage.misc.weak_dict
3533

3634
from sage.categories.fields import Fields
37-
_Fields = Fields()
3835
from sage.categories.commutative_rings import CommutativeRings
39-
_CommutativeRings = CommutativeRings()
36+
from sage.categories.domains import Domains
4037
from sage.categories.complete_discrete_valuation import CompleteDiscreteValuationRings, CompleteDiscreteValuationFields
38+
39+
_CommutativeRings = CommutativeRings()
40+
_Fields = Fields()
41+
_Domains = Domains()
4142
_CompleteDiscreteValuationRings = CompleteDiscreteValuationRings()
4243
_CompleteDiscreteValuationFields = CompleteDiscreteValuationFields()
4344

44-
import sage.misc.weak_dict
4545
_cache = sage.misc.weak_dict.WeakValueDictionary()
4646

4747

@@ -659,6 +659,7 @@ def unpickle_PolynomialRing(base_ring, arg1=None, arg2=None, sparse=False):
659659
args = [arg for arg in (arg1, arg2) if arg is not None]
660660
return PolynomialRing(base_ring, *args, sparse=sparse)
661661

662+
662663
from sage.misc.persist import register_unpickle_override
663664
register_unpickle_override('sage.rings.polynomial.polynomial_ring_constructor', 'PolynomialRing', unpickle_PolynomialRing)
664665

@@ -720,15 +721,15 @@ def _single_variate(base_ring, name, sparse=None, implementation=None, order=Non
720721

721722
# Generic implementations
722723
if constructor is None:
723-
if not isinstance(base_ring, ring.CommutativeRing):
724+
if base_ring not in _CommutativeRings:
724725
constructor = polynomial_ring.PolynomialRing_general
725726
elif base_ring in _CompleteDiscreteValuationRings:
726727
constructor = polynomial_ring.PolynomialRing_cdvr
727728
elif base_ring in _CompleteDiscreteValuationFields:
728729
constructor = polynomial_ring.PolynomialRing_cdvf
729-
elif base_ring.is_field(proof=False):
730+
elif base_ring in _Fields:
730731
constructor = polynomial_ring.PolynomialRing_field
731-
elif base_ring.is_integral_domain(proof=False):
732+
elif base_ring in _Domains:
732733
constructor = polynomial_ring.PolynomialRing_integral_domain
733734
else:
734735
constructor = polynomial_ring.PolynomialRing_commutative
@@ -737,8 +738,8 @@ def _single_variate(base_ring, name, sparse=None, implementation=None, order=Non
737738

738739
# Only use names which are not supported by the specialized class.
739740
if specialized is not None:
740-
implementation_names = [n for n in implementation_names if
741-
specialized._implementation_names_impl(n, base_ring, sparse) is NotImplemented]
741+
implementation_names = [n for n in implementation_names
742+
if specialized._implementation_names_impl(n, base_ring, sparse) is NotImplemented]
742743

743744
if implementation is not None:
744745
kwds["implementation"] = implementation
@@ -928,7 +929,6 @@ def BooleanPolynomialRing_constructor(n=None, names=None, order="lex"):
928929
sage: x2 > x3
929930
True
930931
"""
931-
932932
if isinstance(n, str):
933933
names = n
934934
n = -1

src/sage/rings/quotient_ring.py

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -97,17 +97,15 @@
9797
True
9898
9999
"""
100-
#*****************************************************************************
100+
# ****************************************************************************
101101
# Copyright (C) 2005 William Stein <[email protected]>
102102
#
103103
# This program is free software: you can redistribute it and/or modify
104104
# it under the terms of the GNU General Public License as published by
105105
# the Free Software Foundation, either version 2 of the License, or
106106
# (at your option) any later version.
107107
# http://www.gnu.org/licenses/
108-
#*****************************************************************************
109-
110-
108+
# ****************************************************************************
111109
import sage.misc.latex as latex
112110
from . import ring, ideal, quotient_ring_element
113111
from sage.structure.category_object import normalize_names
@@ -118,6 +116,10 @@
118116
from sage.categories.commutative_rings import CommutativeRings
119117

120118

119+
_Rings = Rings()
120+
_CommRings = CommutativeRings()
121+
122+
121123
MPolynomialIdeal_quotient = None
122124
try:
123125
from sage.interfaces.singular import singular as singular_default, is_SingularElement
@@ -276,20 +278,15 @@ def QuotientRing(R, I, names=None, **kwds):
276278
"""
277279
# 1. Not all rings inherit from the base class of rings.
278280
# 2. We want to support quotients of free algebras by homogeneous two-sided ideals.
279-
#if not isinstance(R, commutative_ring.CommutativeRing):
280-
# raise TypeError, "R must be a commutative ring."
281281
from sage.rings.finite_rings.integer_mod_ring import Integers
282282
from sage.rings.integer_ring import ZZ
283-
if R not in Rings():
284-
raise TypeError("R must be a ring.")
285-
try:
286-
is_commutative = R.is_commutative()
287-
except (AttributeError, NotImplementedError):
288-
is_commutative = False
283+
if R not in _Rings:
284+
raise TypeError("R must be a ring")
285+
is_commutative = R in _CommRings
289286
if names is None:
290287
try:
291288
names = tuple([x + 'bar' for x in R.variable_names()])
292-
except ValueError: # no names are assigned
289+
except ValueError: # no names are assigned
293290
pass
294291
else:
295292
names = normalize_names(R.ngens(), names)
@@ -321,10 +318,11 @@ def QuotientRing(R, I, names=None, **kwds):
321318
if S == ZZ:
322319
return Integers((I_lift+J).gen(), **kwds)
323320
return R.__class__(S, I_lift + J, names=names)
324-
if isinstance(R, ring.CommutativeRing):
321+
if R in _CommRings:
325322
return QuotientRing_generic(R, I, names, **kwds)
326323
return QuotientRing_nc(R, I, names, **kwds)
327324

325+
328326
def is_QuotientRing(x):
329327
"""
330328
Tests whether or not ``x`` inherits from :class:`QuotientRing_nc`.
@@ -349,14 +347,12 @@ def is_QuotientRing(x):
349347
True
350348
sage: is_QuotientRing(F)
351349
False
352-
353350
"""
354351
return isinstance(x, QuotientRing_nc)
355352

356353

357-
_Rings = Rings()
358-
_RingsQuotients = Rings().Quotients()
359-
_CommutativeRingsQuotients = CommutativeRings().Quotients()
354+
_RingsQuotients = _Rings.Quotients()
355+
_CommutativeRingsQuotients = _CommRings.Quotients()
360356
from sage.structure.category_object import check_default_category
361357

362358

@@ -512,10 +508,13 @@ def construction(self):
512508
names = self.cover_ring().variable_names()
513509
except ValueError:
514510
names = None
515-
if self in CommutativeRings():
516-
return QuotientFunctor(self.__I, names=names, domain=CommutativeRings(), codomain=CommutativeRings(), as_field=isinstance(self, Field)), self.__R
511+
if self in _CommRings:
512+
return QuotientFunctor(self.__I, names=names, domain=_CommRings,
513+
codomain=_CommRings,
514+
as_field=isinstance(self, Field)), self.__R
517515
else:
518-
return QuotientFunctor(self.__I, names=names, as_field=isinstance(self, Field)), self.__R
516+
return QuotientFunctor(self.__I, names=names,
517+
as_field=isinstance(self, Field)), self.__R
519518

520519
def _repr_(self):
521520
"""
@@ -1290,6 +1289,7 @@ def term_order(self):
12901289
"""
12911290
return self.__R.term_order()
12921291

1292+
12931293
class QuotientRing_generic(QuotientRing_nc, ring.CommutativeRing):
12941294
r"""
12951295
Creates a quotient ring of a *commutative* ring `R` by the ideal `I`.
@@ -1316,13 +1316,14 @@ def __init__(self, R, I, names, category=None):
13161316
13171317
TESTS::
13181318
1319-
sage: isinstance(ZZ.quo(2), sage.rings.ring.CommutativeRing) # indirect doctest
1319+
sage: ZZ.quo(2) in Rings().Commutative() # indirect doctest
13201320
True
13211321
"""
1322-
if not isinstance(R, ring.CommutativeRing):
1322+
if R not in _CommRings:
13231323
raise TypeError("This class is for quotients of commutative rings only.\n For non-commutative rings, use <sage.rings.quotient_ring.QuotientRing_nc>")
13241324
if not self._is_category_initialized():
1325-
category = check_default_category(_CommutativeRingsQuotients,category)
1325+
category = check_default_category(_CommutativeRingsQuotients,
1326+
category)
13261327
QuotientRing_nc.__init__(self, R, I, names, category=category)
13271328

13281329
def _macaulay2_init_(self, macaulay2=None):

0 commit comments

Comments
 (0)