Skip to content

Commit

Permalink
gh-37159: Fix change_ring method of multi-variate polynomials
Browse files Browse the repository at this point in the history
    
<!-- ^^^^^
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 -->

Fixes #36832.

<!-- Why is this change required? What problem does it solve? -->
<!-- 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: #37159
Reported by: Kwankyu Lee
Reviewer(s): Gonzalo Tornaría, Kwankyu Lee
  • Loading branch information
Release Manager committed Feb 1, 2024
2 parents b6a4bb5 + fb1b108 commit 02fbbdd
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 60 deletions.
66 changes: 49 additions & 17 deletions src/sage/rings/polynomial/multi_polynomial.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ r"""
Base class for elements of multivariate polynomial rings
"""

#*****************************************************************************
# ********************************************************************
# Copyright (C) 2005 William Stein <wstein@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
# https://www.gnu.org/licenses/
#*****************************************************************************
# ********************************************************************

from sage.rings.integer cimport Integer
from sage.rings.integer_ring import ZZ
Expand All @@ -33,9 +35,9 @@ from sage.rings.polynomial.polynomial_element cimport Polynomial

cdef class MPolynomial(CommutativePolynomial):

####################
# -------------------------
# Some standard conversions
####################
# -------------------------
def _scalar_conversion(self, R):
r"""
TESTS::
Expand Down Expand Up @@ -360,7 +362,6 @@ cdef class MPolynomial(CommutativePolynomial):
"""
return multi_derivative(self, args)


def polynomial(self, var):
r"""
Let ``var`` be one of the variables of the parent of ``self``. This
Expand Down Expand Up @@ -840,26 +841,43 @@ cdef class MPolynomial(CommutativePolynomial):

def change_ring(self, R):
r"""
Return a copy of this polynomial but with coefficients in ``R``,
if at all possible.
Return this polynomial with coefficients converted to ``R``.
INPUT:
- ``R`` -- a ring or morphism.
- ``R`` -- a ring or morphism; if a morphism, the coefficients
are mapped to the codomain of ``R``
OUTPUT: a new polynomial with the base ring changed to ``R``.
EXAMPLES::
sage: R.<x,y> = QQ[]
sage: f = x^3 + 3/5*y + 1
sage: f.change_ring(GF(7))
x^3 + 2*y + 1
sage: g = x^2 + 5*y
sage: g.change_ring(GF(5))
x^2
::
sage: R.<x,y> = GF(9,'a')[] # needs sage.rings.finite_rings
sage: # needs sage.rings.finite_rings
sage: R.<x,y> = GF(9,'a')[]
sage: (x+2*y).change_ring(GF(3))
x - y
::
sage: # needs sage.rings.finite_rings
sage: F.<a> = GF(7^2)
sage: R.<x,y> = F[]
sage: f = x^2 + a^2*y^2 + a*x + a^3*y
sage: g = f.change_ring(F.frobenius_endomorphism()); g
x^2 + (-a - 2)*y^2 + (-a + 1)*x + (2*a + 2)*y
sage: g.change_ring(F.frobenius_endomorphism()) == f
True
::
sage: # needs sage.rings.number_field
Expand All @@ -869,21 +887,35 @@ cdef class MPolynomial(CommutativePolynomial):
sage: f.change_ring(K.embeddings(CC)[1])
x^2 + (-0.500000000000000 - 0.866025403784438*I)*y
::
sage: # needs sage.rings.number_field
sage: K.<w> = CyclotomicField(5)
sage: R.<x,y> = K[]
sage: f = x^2 + w*y
sage: f.change_ring(K.embeddings(QQbar)[1])
x^2 + (-0.8090169943749474? + 0.5877852522924731?*I)*y
TESTS:
Check that :trac:`25022` is fixed::
Check that :issue:`25022` is fixed::
sage: # needs sage.rings.number_field sage.symbolic
sage: K.<x,y> = ZZ[]
sage: (x*y).change_ring(SR).monomials() # needs sage.rings.number_field sage.symbolic
sage: (x*y).change_ring(SR).monomials()
[x*y]
Check that :issue:`36832` is fixed::
sage: F = GF(11)
sage: phi = Hom(F,F).an_element()
sage: R.<x,y> = F[]
sage: x.change_ring(phi)
x
"""
if isinstance(R, Map):
#if we're given a hom of the base ring extend to a poly hom
if R.domain() == self.base_ring():
R = self.parent().hom(R, self.parent().change_ring(R.codomain()))
return R(self)
else:
return self.parent().change_ring(R)(self.dict())
return self.map_coefficients(R)
return self.parent().change_ring(R)(self.dict())

def is_symmetric(self, group=None):
r"""
Expand Down
34 changes: 0 additions & 34 deletions src/sage/rings/polynomial/multi_polynomial_element.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,40 +412,6 @@ def __rpow__(self, n):
def element(self):
return self.__element

def change_ring(self, R):
r"""
Change the base ring of this polynomial to ``R``.
INPUT:
- ``R`` -- ring or morphism.
OUTPUT: a new polynomial converted to ``R``.
EXAMPLES::
sage: R.<x,y> = QQ[]
sage: f = x^2 + 5*y
sage: f.change_ring(GF(5))
x^2
::
sage: # needs sage.rings.number_field
sage: K.<w> = CyclotomicField(5)
sage: R.<x,y> = K[]
sage: f = x^2 + w*y
sage: f.change_ring(K.embeddings(QQbar)[1])
x^2 + (-0.8090169943749474? + 0.5877852522924731?*I)*y
"""
if isinstance(R, Morphism):
#if we're given a hom of the base ring extend to a poly hom
if R.domain() == self.base_ring():
R = self.parent().hom(R, self.parent().change_ring(R.codomain()))
return R(self)
else:
return self.parent().change_ring(R)(self)


class MPolynomial_polydict(Polynomial_singular_repr, MPolynomial_element):
r"""
Expand Down
17 changes: 8 additions & 9 deletions src/sage/rings/polynomial/multi_polynomial_libsingular.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,15 @@ AUTHORS:
"""

#*****************************************************************************
# ********************************************************************
# Copyright (C) 2005 William Stein <wstein@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
# http://www.gnu.org/licenses/
#*****************************************************************************
# https://www.gnu.org/licenses/
# ********************************************************************

# The Singular API is as follows:
#
Expand Down Expand Up @@ -1530,9 +1532,9 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base):

return old

### The following methods are handy for implementing Groebner
### basis algorithms. They do only superficial type/sanity checks
### and should be called carefully.
# The following methods are handy for implementing Groebner
# basis algorithms. They do only superficial type/sanity checks
# and should be called carefully.

def monomial_quotient(self, MPolynomial_libsingular f, MPolynomial_libsingular g, coeff=False):
r"""
Expand Down Expand Up @@ -1677,7 +1679,6 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base):
else:
return True


def monomial_lcm(self, MPolynomial_libsingular f, MPolynomial_libsingular g):
"""
LCM for monomials. Coefficients are ignored.
Expand Down Expand Up @@ -5242,7 +5243,6 @@ cdef class MPolynomial_libsingular(MPolynomial_libsingular_base):
y += base_map(c)*mul([ im_gens[i]**m[i] for i in range(n) if m[i]])
return y


def _derivative(self, MPolynomial_libsingular var):
"""
Differentiates this polynomial with respect to the provided
Expand Down Expand Up @@ -5694,7 +5694,6 @@ cdef class MPolynomial_libsingular(MPolynomial_libsingular_base):
i.append( new_MP(self._parent, pDiff(self._poly, k)))
return i


def numerator(self):
"""
Return a numerator of self computed as self * self.denominator()
Expand Down

0 comments on commit 02fbbdd

Please sign in to comment.