Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rings/infinite polynomial ring fixes #37761

Merged
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
12fc4bc
return numerator and denominator as elements of self, restrict elemen…
mantepse Apr 6, 2024
a0deca4
add docstring to numerator, remove wrong denominator method (the inhe…
mantepse Apr 7, 2024
690e048
remove workaround and fix InfinitePolynomialRing instead
mantepse Apr 3, 2024
6d4659c
add documentation and tests, remove cached_method
mantepse Apr 3, 2024
0fe5270
add doctest, fix linter
mantepse Apr 7, 2024
064d6ba
add doctest for coercion issue
mantepse Apr 7, 2024
7b49ae1
Fix missing backticks
mantepse Apr 7, 2024
a36aac5
Fix missing backticks
mantepse Apr 7, 2024
b128a60
remove misleading sentence and whitespace
mantepse Apr 7, 2024
8015042
add missing colon
mantepse Apr 7, 2024
385ee8c
use proper sphinx roles
mantepse Apr 7, 2024
6706a39
remove whitespace
mantepse Apr 8, 2024
575731d
improve docstring formatting
mantepse Apr 8, 2024
97dbbc6
remove unnecessary parens
mantepse Apr 8, 2024
9b76cf6
improve docstring
mantepse Apr 8, 2024
2f607aa
fix sphinx role
mantepse Apr 8, 2024
b42e2d9
Merge branch 'sagemath:develop' into rings/infinite_polynomial_ring_f…
mantepse Apr 13, 2024
91ad38e
Merge branch 'sagemath:develop' into rings/infinite_polynomial_ring_f…
mantepse Jun 17, 2024
a8fa295
Merge branch 'sagemath:develop' into rings/infinite_polynomial_ring_f…
mantepse Jul 12, 2024
0b93f3a
Merge branch 'sagemath:develop' into rings/infinite_polynomial_ring_f…
mantepse Jul 19, 2024
3cdc7ad
revert original fix -- replacing self._base(x) with self._base.coerce…
mantepse Jul 27, 2024
c719db3
Apply suggestions concerning docstring formatting from code review
mantepse Aug 6, 2024
3435194
Merge branch 'develop' into rings/infinite_polynomial_ring_fixes
mantepse Aug 6, 2024
7999167
indent forgotten lines
mantepse Aug 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 127 additions & 31 deletions src/sage/rings/polynomial/infinite_polynomial_element.py
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,41 @@
"""
return self._p.is_nilpotent()

def numerator(self):
r"""
Return a numerator of ``self``, computed as ``self * self.denominator()``.

.. WARNING::

This is not the numerator of the rational function
defined by ``self``, which would always be ``self`` since it is a
polynomial.

EXAMPLES::

sage: X.<x> = InfinitePolynomialRing(QQ)
sage: p = 2/3*x[1] + 4/9*x[2] - 2*x[1]*x[3]
sage: num = p.numerator(); num
-18*x_3*x_1 + 4*x_2 + 6*x_1

TESTS::

sage: num.parent()
Infinite polynomial ring in x over Rational Field

Check that :issue:`37756` is fixed::

sage: R.<a> = InfinitePolynomialRing(QQ)
sage: P.<x,y> = QQ[]
sage: FF = P.fraction_field()
sage: FF(a[0])
Traceback (most recent call last):
...
TypeError: Could not find a mapping of the passed element to this ring.
"""
P = self.parent()
return InfinitePolynomial(P, self._p.numerator())

@cached_method
def variables(self):
"""
Expand All @@ -577,9 +612,70 @@

"""
if hasattr(self._p, 'variables'):
return tuple(self._p.variables())
P = self.parent()
return tuple(InfinitePolynomial(P, v) for v in self._p.variables())
return ()

def monomials(self):
"""
Return the list of monomials in ``self``.

The returned list is decreasingly ordered by the term ordering of
``self.parent()``.

EXAMPLES::

sage: X.<x> = InfinitePolynomialRing(QQ)
sage: p = x[1]^3 + x[2] - 2*x[1]*x[3]
sage: p.monomials()
[x_3*x_1, x_2, x_1^3]

sage: X.<x> = InfinitePolynomialRing(QQ, order='deglex')
sage: p = x[1]^3 + x[2] - 2*x[1]*x[3]
sage: p.monomials()
[x_1^3, x_3*x_1, x_2]
"""
P = self.parent()
return [InfinitePolynomial(P, m) for m in self._p.monomials()]

def monomial_coefficient(self, mon):
tscrim marked this conversation as resolved.
Show resolved Hide resolved
"""
Return the base ring element that is the coefficient of ``mon``
in ``self``.

This function contrasts with the function :meth:`coefficient`,
which returns the coefficient of a monomial viewing this
polynomial in a polynomial ring over a base ring having fewer
variables.

INPUT:

- ``mon`` -- a monomial in the parent of ``self``

OUTPUT: coefficient in base ring

.. SEEALSO::

For coefficients in a base ring of fewer variables,
look at :meth:`coefficient`.

EXAMPLES::

sage: X.<x> = InfinitePolynomialRing(QQ)
sage: f = 2*x[0]*x[2] + 3*x[1]^2
sage: c = f.monomial_coefficient(x[1]^2); c
3
sage: c.parent()
Rational Field

sage: c = f.coefficient(x[2]); c
2*x_0
sage: c.parent()
Infinite polynomial ring in x over Rational Field

"""
return self._p.monomial_coefficient(mon._p)
mantepse marked this conversation as resolved.
Show resolved Hide resolved

@cached_method
def max_index(self):
r"""
Expand Down Expand Up @@ -1017,42 +1113,42 @@
2

"""
P = self.parent()
if self._p == 0:
res = 0
elif isinstance(monomial, self.__class__):
if not (self.parent().has_coerce_map_from(monomial.parent())):
res = 0
return P.zero()

Check warning on line 1118 in src/sage/rings/polynomial/infinite_polynomial_element.py

View check run for this annotation

Codecov / codecov/patch

src/sage/rings/polynomial/infinite_polynomial_element.py#L1118

Added line #L1118 was not covered by tests
if isinstance(monomial, self.__class__):
if not P.has_coerce_map_from(monomial.parent()):
return P.zero()

Check warning on line 1121 in src/sage/rings/polynomial/infinite_polynomial_element.py

View check run for this annotation

Codecov / codecov/patch

src/sage/rings/polynomial/infinite_polynomial_element.py#L1121

Added line #L1121 was not covered by tests
if hasattr(self._p, 'variables'):
VarList = [str(X) for X in self._p.variables()]
else:
if hasattr(self._p, 'variables'):
VarList = [str(X) for X in self._p.variables()]
else:
VarList = []
if hasattr(monomial._p, 'variables'):
VarList.extend([str(X) for X in monomial._p.variables()])
VarList = list(set(VarList))
VarList.sort(key=self.parent().varname_key, reverse=True)
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
if len(VarList) == 1:
# 'xx' is guaranteed to be no variable
# name of monomial, since coercions
# were tested before
R = PolynomialRing(self._p.base_ring(), VarList + ['xx'], order=self.parent()._order)

res = PolynomialRing(self._p.base_ring(), VarList, order=self.parent()._order)(R(self._p).coefficient(R(monomial._p)))
else:
R = PolynomialRing(self._p.base_ring(), VarList, order=self.parent()._order)
res = R(self._p).coefficient(R(monomial._p))
elif isinstance(monomial, dict):
VarList = []

Check warning on line 1125 in src/sage/rings/polynomial/infinite_polynomial_element.py

View check run for this annotation

Codecov / codecov/patch

src/sage/rings/polynomial/infinite_polynomial_element.py#L1125

Added line #L1125 was not covered by tests
if hasattr(monomial._p, 'variables'):
VarList.extend([str(X) for X in monomial._p.variables()])
VarList = list(set(VarList))
VarList.sort(key=P.varname_key, reverse=True)
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
if len(VarList) == 1:
# 'xx' is guaranteed to be no variable
# name of monomial, since coercions
# were tested before
R = PolynomialRing(self._p.base_ring(), VarList + ['xx'], order=P._order)
S = PolynomialRing(self._p.base_ring(), VarList, order=P._order)
res = S(R(self._p).coefficient(R(monomial._p)))
return InfinitePolynomial(P, res)

R = PolynomialRing(self._p.base_ring(), VarList, order=P._order)
res = R(self._p).coefficient(R(monomial._p))
return InfinitePolynomial(P, res)

if isinstance(monomial, dict):
if monomial:
I = iter(monomial)
K = next(I)
del monomial[K]
res = self.coefficient(K).coefficient(monomial)
else:
return self
else:
raise TypeError("Objects of type %s have no coefficients in InfinitePolynomials" % (type(monomial)))
return self.parent()(res)
return self.coefficient(K).coefficient(monomial)
return self
raise TypeError("Objects of type %s have no coefficients in InfinitePolynomials" % (type(monomial)))

Check warning on line 1151 in src/sage/rings/polynomial/infinite_polynomial_element.py

View check run for this annotation

Codecov / codecov/patch

src/sage/rings/polynomial/infinite_polynomial_element.py#L1151

Added line #L1151 was not covered by tests

# Essentials for Buchberger
def reduce(self, I, tailreduce=False, report=None):
Expand Down
21 changes: 16 additions & 5 deletions src/sage/rings/polynomial/infinite_polynomial_ring.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

- ``R``, the base ring. It has to be a commutative ring, and in some
applications it must even be a field
- ``names``, a finite list of generator names. Generator names must be alpha-numeric.
- ``names``, a finite list of generator names. Generator names must be alphanumeric.
- ``order`` (optional string). The default order is ``'lex'`` (lexicographic).
``'deglex'`` is degree lexicographic, and ``'degrevlex'`` (degree reverse
lexicographic) is possible but discouraged.
Expand Down Expand Up @@ -279,8 +279,8 @@
class InfinitePolynomialRingFactory(UniqueFactory):
"""
A factory for creating infinite polynomial ring elements. It
handles making sure that they are unique as well as handling
pickling. For more details, see
makes sure that they are unique as well as handling pickling.
For more details, see
:class:`~sage.structure.factory.UniqueFactory` and
:mod:`~sage.rings.polynomial.infinite_polynomial_ring`.

Expand Down Expand Up @@ -566,7 +566,7 @@

def __next__(self):
"""
Return a dictionary that can be used to interprete strings in the base ring of ``self``.
Return a dictionary that can be used to interpret strings in the base ring of ``self``.

EXAMPLES::

Expand Down Expand Up @@ -704,7 +704,7 @@
names = ['x']
for n in names:
if not (isinstance(n, str) and n.isalnum() and (not n[0].isdigit())):
raise ValueError("generator names must be alpha-numeric strings not starting with a digit, but %s is not" % n)
raise ValueError("generator names must be alphanumeric strings not starting with a digit, but %s is not" % n)

Check warning on line 707 in src/sage/rings/polynomial/infinite_polynomial_ring.py

View check run for this annotation

Codecov / codecov/patch

src/sage/rings/polynomial/infinite_polynomial_ring.py#L707

Added line #L707 was not covered by tests
if len(names) != len(set(names)):
raise ValueError("generator names must be pairwise different")
self._names = tuple(names)
Expand Down Expand Up @@ -888,6 +888,17 @@
Traceback (most recent call last):
...
ValueError: cannot convert 1/3 into an element of Infinite polynomial ring in x over Integer Ring

.. WARNING:

The :issue:`37756` is not yet fixed::

sage: L.<x, y> = QQ[]
mantepse marked this conversation as resolved.
Show resolved Hide resolved
sage: R.<a> = InfinitePolynomialRing(QQ)
sage: M = InfinitePolynomialRing(L, names=["a"])
sage: c = a[0]
sage: M(c) # known bug
a_0
mantepse marked this conversation as resolved.
Show resolved Hide resolved
"""
from sage.rings.polynomial.infinite_polynomial_element import InfinitePolynomial
# In many cases, the easiest solution is to "simply" evaluate
Expand Down
Loading