Skip to content

Commit ba7d118

Browse files
author
Release Manager
committed
gh-36045: `sage.rings.polynomial`: Modularization fixes, `# needs` <!-- ^^^^^ Please provide a concise, informative and self-explanatory title. Don't put issue numbers in there, do this in the PR body below. For example, instead of "Fixes #1234" use "Introduce new method to calculate 1+1" --> <!-- Describe your changes here in detail --> <!-- Why is this change required? What problem does it solve? --> - Part of: #29705 - Cherry-picked from: #35095 <!-- If this PR resolves an open issue, please link to it here. For example "Fixes #12345". --> <!-- If your change requires a documentation PR, please link it appropriately. --> ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> <!-- If your change requires a documentation PR, please link it appropriately --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> <!-- Feel free to remove irrelevant items. --> - [x] The title is concise, informative, and self-explanatory. - [ ] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [ ] I have updated the documentation accordingly. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on - #12345: short description why this is a dependency - #34567: ... --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> URL: #36045 Reported by: Matthias Köppe Reviewer(s): David Coudert
2 parents a38d129 + fafd930 commit ba7d118

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+5222
-4594
lines changed

src/sage/rings/polynomial/cyclotomic.pyx

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -30,32 +30,34 @@ import sys
3030
from cysignals.memory cimport sig_malloc, check_calloc, sig_free
3131
from cysignals.signals cimport sig_on, sig_off
3232

33-
from sage.structure.element cimport parent
34-
3533
from sage.arith.misc import factor
36-
from sage.rings.integer_ring import ZZ
37-
from sage.misc.misc_c import prod
3834
from sage.combinat.subset import subsets
39-
from sage.libs.pari.all import pari
35+
from sage.misc.misc_c import prod
36+
from sage.rings.integer_ring import ZZ
37+
from sage.structure.element cimport parent
4038

39+
try:
40+
from sage.libs.pari.all import pari
41+
except ImportError:
42+
pass
4143

4244
def cyclotomic_coeffs(nn, sparse=None):
4345
"""
44-
Return the coefficients of the n-th cyclotomic polynomial
46+
Return the coefficients of the `n`-th cyclotomic polynomial
4547
by using the formula
4648
4749
.. MATH::
4850
4951
\\Phi_n(x) = \\prod_{d|n} (1-x^{n/d})^{\\mu(d)}
5052
51-
where `\\mu(d)` is the Möbius function that is 1 if d has an even
52-
number of distinct prime divisors, -1 if it has an odd number of
53-
distinct prime divisors, and 0 if d is not squarefree.
53+
where `\\mu(d)` is the Möbius function that is 1 if `d` has an even
54+
number of distinct prime divisors, `-1` if it has an odd number of
55+
distinct prime divisors, and `0` if `d` is not squarefree.
5456
5557
Multiplications and divisions by polynomials of the
5658
form `1-x^n` can be done very quickly in a single pass.
5759
58-
If sparse is ``True``, the result is returned as a dictionary of
60+
If ``sparse`` is ``True``, the result is returned as a dictionary of
5961
the non-zero entries, otherwise the result is returned as a list
6062
of python ints.
6163
@@ -72,17 +74,19 @@ def cyclotomic_coeffs(nn, sparse=None):
7274
7375
Check that it has the right degree::
7476
75-
sage: euler_phi(30)
77+
sage: euler_phi(30) # needs sage.libs.pari
7678
8
77-
sage: R(cyclotomic_coeffs(14)).factor()
79+
sage: R(cyclotomic_coeffs(14)).factor() # needs sage.libs.pari
7880
x^6 - x^5 + x^4 - x^3 + x^2 - x + 1
7981
8082
The coefficients are not always +/-1::
8183
8284
sage: cyclotomic_coeffs(105)
83-
[1, 1, 1, 0, 0, -1, -1, -2, -1, -1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, -1, -1, -2, -1, -1, 0, 0, 1, 1, 1]
85+
[1, 1, 1, 0, 0, -1, -1, -2, -1, -1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, -1,
86+
0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, -1, -1, -2,
87+
-1, -1, 0, 0, 1, 1, 1]
8488
85-
In fact the height is not bounded by any polynomial in n (Erdos),
89+
In fact the height is not bounded by any polynomial in `n` (Erdos),
8690
although takes a while just to exceed linear::
8791
8892
sage: v = cyclotomic_coeffs(1181895)
@@ -200,10 +204,10 @@ def cyclotomic_value(n, x):
200204
201205
INPUT:
202206
203-
- `n` -- an Integer, specifying which cyclotomic polynomial is to be
207+
- ``n`` -- an Integer, specifying which cyclotomic polynomial is to be
204208
evaluated
205209
206-
- `x` -- an element of a ring
210+
- ``x`` -- an element of a ring
207211
208212
OUTPUT:
209213
@@ -247,9 +251,12 @@ def cyclotomic_value(n, x):
247251
248252
TESTS::
249253
250-
sage: R.<x> = QQ[]
251-
sage: K.<i> = NumberField(x^2 + 1)
252-
sage: for y in [-1, 0, 1, 2, 1/2, Mod(3, 8), Mod(3,11), GF(9,'a').gen(), Zp(3)(54), i, x^2+2]:
254+
sage: elements = [-1, 0, 1, 2, 1/2, Mod(3, 8), Mod(3,11)]
255+
sage: R.<x> = QQ[]; elements += [x^2 + 2]
256+
sage: K.<i> = NumberField(x^2 + 1); elements += [i] # needs sage.rings.number_fields
257+
sage: elements += [GF(9,'a').gen()] # needs sage.rings.finite_rings
258+
sage: elements += [Zp(3)(54)] # needs sage.rings.padics
259+
sage: for y in elements:
253260
....: for n in [1..60]:
254261
....: val1 = cyclotomic_value(n, y)
255262
....: val2 = cyclotomic_polynomial(n)(y)
@@ -258,29 +265,31 @@ def cyclotomic_value(n, x):
258265
....: if val1.parent() is not val2.parent():
259266
....: print("Wrong parent for cyclotomic_value(%s, %s) in %s"%(n,y,parent(y)))
260267
261-
sage: cyclotomic_value(20, I)
268+
sage: cyclotomic_value(20, I) # needs sage.symbolic
262269
5
263270
sage: a = cyclotomic_value(10, mod(3, 11)); a
264271
6
265272
sage: a.parent()
266273
Ring of integers modulo 11
267-
sage: cyclotomic_value(30, -1.0)
274+
sage: cyclotomic_value(30, -1.0) # needs sage.rings.real_mpfr
268275
1.00000000000000
276+
277+
sage: # needs sage.libs.pari
269278
sage: S.<t> = R.quotient(R.cyclotomic_polynomial(15))
270279
sage: cyclotomic_value(15, t)
271280
0
272281
sage: cyclotomic_value(30, t)
273282
2*t^7 - 2*t^5 - 2*t^3 + 2*t
274283
sage: S.<t> = R.quotient(x^10)
275-
sage: cyclotomic_value(2^128-1, t)
284+
sage: cyclotomic_value(2^128 - 1, t)
276285
-t^7 - t^6 - t^5 + t^2 + t + 1
277-
sage: cyclotomic_value(10,mod(3,4))
286+
sage: cyclotomic_value(10, mod(3,4))
278287
1
279288
280289
Check that the issue with symbolic element in :trac:`14982` is fixed::
281290
282-
sage: a = cyclotomic_value(3, I)
283-
sage: parent(a)
291+
sage: a = cyclotomic_value(3, I) # needs sage.rings.number_fields
292+
sage: parent(a) # needs sage.rings.number_fields
284293
Number Field in I with defining polynomial x^2 + 1 with I = 1*I
285294
"""
286295
n = ZZ(n)
@@ -387,7 +396,7 @@ def bateman_bound(nn):
387396
EXAMPLES::
388397
389398
sage: from sage.rings.polynomial.cyclotomic import bateman_bound
390-
sage: bateman_bound(2**8*1234567893377)
399+
sage: bateman_bound(2**8 * 1234567893377) # needs sage.libs.pari
391400
66944986927
392401
"""
393402
_, n = nn.val_unit(2)

src/sage/rings/polynomial/flatten.py

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -111,37 +111,41 @@ def __init__(self, domain):
111111
112112
::
113113
114+
sage: # needs sage.rings.number_field
114115
sage: x = polygen(ZZ, 'x')
115-
sage: K.<v> = NumberField(x^3 - 2) # optional - sage.rings.number_field
116-
sage: R = K['x','y']['a','b'] # optional - sage.rings.number_field
116+
sage: K.<v> = NumberField(x^3 - 2)
117+
sage: R = K['x','y']['a','b']
117118
sage: from sage.rings.polynomial.flatten import FlatteningMorphism
118-
sage: f = FlatteningMorphism(R) # optional - sage.rings.number_field
119-
sage: f(R('v*a*x^2 + b^2 + 1/v*y')) # optional - sage.rings.number_field
119+
sage: f = FlatteningMorphism(R)
120+
sage: f(R('v*a*x^2 + b^2 + 1/v*y'))
120121
v*x^2*a + b^2 + (1/2*v^2)*y
121122
122123
::
123124
124-
sage: R = QQbar['x','y']['a','b'] # optional - sage.rings.number_field
125+
sage: # needs sage.rings.number_field
126+
sage: R = QQbar['x','y']['a','b']
125127
sage: from sage.rings.polynomial.flatten import FlatteningMorphism
126-
sage: f = FlatteningMorphism(R) # optional - sage.rings.number_field
127-
sage: f(R('QQbar(sqrt(2))*a*x^2 + b^2 + QQbar(I)*y')) # optional - sage.rings.number_field
128+
sage: f = FlatteningMorphism(R)
129+
sage: f(R('QQbar(sqrt(2))*a*x^2 + b^2 + QQbar(I)*y')) # needs sage.symbolic
128130
1.414213562373095?*x^2*a + b^2 + I*y
129131
130132
::
131133
132-
sage: R.<z> = PolynomialRing(QQbar, 1) # optional - sage.rings.number_field
134+
sage: # needs sage.rings.number_field
135+
sage: R.<z> = PolynomialRing(QQbar, 1)
133136
sage: from sage.rings.polynomial.flatten import FlatteningMorphism
134-
sage: f = FlatteningMorphism(R) # optional - sage.rings.number_field
135-
sage: f.domain(), f.codomain() # optional - sage.rings.number_field
137+
sage: f = FlatteningMorphism(R)
138+
sage: f.domain(), f.codomain()
136139
(Multivariate Polynomial Ring in z over Algebraic Field,
137140
Multivariate Polynomial Ring in z over Algebraic Field)
138141
139142
::
140143
141-
sage: R.<z> = PolynomialRing(QQbar) # optional - sage.rings.number_field
144+
sage: # needs sage.rings.number_field
145+
sage: R.<z> = PolynomialRing(QQbar)
142146
sage: from sage.rings.polynomial.flatten import FlatteningMorphism
143-
sage: f = FlatteningMorphism(R) # optional - sage.rings.number_field
144-
sage: f.domain(), f.codomain() # optional - sage.rings.number_field
147+
sage: f = FlatteningMorphism(R)
148+
sage: f.domain(), f.codomain()
145149
(Univariate Polynomial Ring in z over Algebraic Field,
146150
Univariate Polynomial Ring in z over Algebraic Field)
147151
@@ -376,8 +380,8 @@ def _call_(self, p):
376380
377381
sage: from sage.rings.polynomial.flatten import FlatteningMorphism
378382
sage: rings = [ZZ['x']['y']['a,b,c']]
379-
sage: rings += [GF(4)['x','y']['a','b']] # optional - sage.rings.finite_rings
380-
sage: rings += [AA['x']['a','b']['y'], QQbar['a1','a2']['t']['X','Y']] # optional - sage.rings.number_field
383+
sage: rings += [GF(4)['x','y']['a','b']] # needs sage.rings.finite_rings
384+
sage: rings += [AA['x']['a','b']['y'], QQbar['a1','a2']['t']['X','Y']] # needs sage.rings.number_field
381385
sage: for R in rings:
382386
....: f = FlatteningMorphism(R)
383387
....: g = f.section()
@@ -490,8 +494,9 @@ def __init__(self, domain, D):
490494
sage: P.<z> = AffineSpace(R, 1)
491495
sage: H = End(P)
492496
sage: f = H([z^2 + c])
493-
sage: f.specialization({c:1})
494-
Scheme endomorphism of Affine Space of dimension 1 over Real Field with 53 bits of precision
497+
sage: f.specialization({c:1}) # needs sage.modules
498+
Scheme endomorphism of
499+
Affine Space of dimension 1 over Real Field with 53 bits of precision
495500
Defn: Defined on coordinates by sending (z) to
496501
(z^2 + 1.00000000000000)
497502
"""

src/sage/rings/polynomial/groebner_fan.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,51 +1246,51 @@ def render(self, file=None, larger=False, shift=0, rgbcolor=(0, 0, 0),
12461246
12471247
INPUT:
12481248
1249-
- ``file`` - a filename if you prefer the output
1249+
- ``file`` -- a filename if you prefer the output
12501250
saved to a file. This will be in xfig format.
12511251
1252-
- ``shift`` - shift the positions of the variables in
1252+
- ``shift`` -- shift the positions of the variables in
12531253
the drawing. For example, with shift=1, the corners will be b
12541254
(right), c (left), and d (top). The shifting is done modulo the
12551255
number of variables in the polynomial ring. The default is 0.
12561256
1257-
- ``larger`` - bool (default: ``False``); if ``True``, make
1257+
- ``larger`` -- bool (default: ``False``); if ``True``, make
12581258
the triangle larger so that the shape of the Groebner region
12591259
appears. Affects the xfig file but probably not the sage graphics
12601260
(?)
12611261
1262-
- ``rgbcolor`` - This will not affect the saved xfig
1262+
- ``rgbcolor`` -- This will not affect the saved xfig
12631263
file, only the sage graphics produced.
12641264
1265-
- ``polyfill`` - Whether or not to fill the cones with
1265+
- ``polyfill`` -- Whether or not to fill the cones with
12661266
a color determined by the highest degree in each reduced Groebner
12671267
basis for that cone.
12681268
1269-
- ``scale_colors`` - if True, this will normalize
1269+
- ``scale_colors`` -- if True, this will normalize
12701270
color values to try to maximize the range
12711271
12721272
12731273
EXAMPLES::
12741274
12751275
sage: R.<x,y,z> = PolynomialRing(QQ,3)
12761276
sage: G = R.ideal([y^3 - x^2, y^2 - 13*x,z]).groebner_fan()
1277-
sage: test_render = G.render()
1277+
sage: test_render = G.render() # needs sage.plot
12781278
12791279
::
12801280
12811281
sage: R.<x,y,z> = PolynomialRing(QQ,3)
12821282
sage: G = R.ideal([x^2*y - z, y^2*z - x, z^2*x - y]).groebner_fan()
1283-
sage: test_render = G.render(larger=True)
1283+
sage: test_render = G.render(larger=True) # needs sage.plot
12841284
12851285
TESTS:
12861286
12871287
Testing the case where the number of generators is < 3. Currently,
1288-
this should raise a ``NotImplementedError`` error.
1288+
this should raise a :class:`NotImplementedError`.
12891289
12901290
::
12911291
12921292
sage: R.<x,y> = PolynomialRing(QQ, 2)
1293-
sage: R.ideal([y^3 - x^2, y^2 - 13*x]).groebner_fan().render()
1293+
sage: R.ideal([y^3 - x^2, y^2 - 13*x]).groebner_fan().render() # needs sage.plot
12941294
Traceback (most recent call last):
12951295
...
12961296
NotImplementedError
@@ -1460,17 +1460,17 @@ def render3d(self, verbose=False):
14601460
14611461
sage: R4.<w,x,y,z> = PolynomialRing(QQ,4)
14621462
sage: gf = R4.ideal([w^2-x,x^2-y,y^2-z,z^2-x]).groebner_fan()
1463-
sage: three_d = gf.render3d()
1463+
sage: three_d = gf.render3d() # needs sage.plot
14641464
14651465
TESTS:
14661466
14671467
Now test the case where the number of generators is not 4. Currently,
1468-
this should raise a ``NotImplementedError`` error.
1468+
this should raise a :class:`NotImplementedError` error.
14691469
14701470
::
14711471
14721472
sage: P.<a,b,c> = PolynomialRing(QQ, 3, order="lex")
1473-
sage: sage.rings.ideal.Katsura(P, 3).groebner_fan().render3d()
1473+
sage: sage.rings.ideal.Katsura(P, 3).groebner_fan().render3d() # needs sage.plot
14741474
Traceback (most recent call last):
14751475
...
14761476
NotImplementedError

src/sage/rings/polynomial/hilbert.pyx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ in any example with more than 34 variables.
2020
#
2121
#*****************************************************************************
2222

23+
import sage.interfaces.abc
24+
2325
from sage.rings.polynomial.polydict cimport ETuple
2426
from sage.rings.polynomial.polynomial_integer_dense_flint cimport Polynomial_integer_dense_flint
25-
from sage.interfaces.singular import Singular
2627

2728
from cysignals.memory cimport sig_malloc
2829
from cpython.list cimport PyList_GET_ITEM
@@ -476,7 +477,7 @@ def first_hilbert_series(I, grading=None, return_grading=False):
476477
cdef Polynomial_integer_dense_flint fhs = Polynomial_integer_dense_flint.__new__(Polynomial_integer_dense_flint)
477478
fhs._parent = PR
478479
fhs._is_gen = 0
479-
if isinstance(I.parent(), Singular):
480+
if isinstance(I, sage.interfaces.abc.SingularElement):
480481
S = I._check_valid()
481482
# First, we need to deal with quotient rings, which also covers the case
482483
# of graded commutative rings that arise as cohomology rings in odd characteristic.

src/sage/rings/polynomial/ideal.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ def residue_class_degree(self):
3232
3333
EXAMPLES::
3434
35-
sage: R.<t> = GF(5)[] # optional - sage.rings.finite_rings
36-
sage: P = R.ideal(t^4 + t + 1) # optional - sage.rings.finite_rings
37-
sage: P.residue_class_degree() # optional - sage.rings.finite_rings
35+
sage: R.<t> = GF(5)[]
36+
sage: P = R.ideal(t^4 + t + 1)
37+
sage: P.residue_class_degree()
3838
4
3939
"""
4040
return self.gen().degree()
@@ -45,8 +45,8 @@ def residue_field(self, names=None, check=True):
4545
4646
EXAMPLES::
4747
48-
sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + 2*t + 9) # optional - sage.rings.finite_rings
49-
sage: k.<a> = P.residue_field(); k # optional - sage.rings.finite_rings
48+
sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + 2*t + 9)
49+
sage: k.<a> = P.residue_field(); k # needs sage.rings.finite_rings
5050
Residue field in a of Principal ideal (t^3 + 2*t + 9) of
5151
Univariate Polynomial Ring in t over Finite Field of size 17
5252
"""
@@ -75,11 +75,11 @@ def groebner_basis(self, algorithm=None):
7575
7676
sage: R.<x> = QQ[]
7777
sage: I = R.ideal([x^2 - 1, x^3 - 1])
78-
sage: G = I.groebner_basis(); G # optional - sage.libs.singular
78+
sage: G = I.groebner_basis(); G
7979
[x - 1]
80-
sage: type(G) # optional - sage.libs.singular
80+
sage: type(G)
8181
<class 'sage.rings.polynomial.multi_polynomial_sequence.PolynomialSequence_generic'>
82-
sage: list(G) # optional - sage.libs.singular
82+
sage: list(G)
8383
[x - 1]
8484
"""
8585
gb = self.gens_reduced()

0 commit comments

Comments
 (0)