Skip to content

Commit 811ac59

Browse files
author
Release Manager
committed
gh-36030: Implement algebra_containment from Singular (issue #34502) <!-- ^^^^^ 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" --> This implements subalgebra containment for polynomials: whether a polynomial is contained in the subalgebra determined by given generators. <!-- Describe your changes here in detail --> <!-- 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. --> This fixes #34502. It provides several algorithms for the calculution, using Singular's algebra_containment, Singular's inSubring, or Sage's Groebner basis tools. ### 📝 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. - [X] The description explains in detail what this PR is about. - [X] I have linked a relevant issue or discussion. - [X] I have created tests covering the changes. - [X] 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: #36030 Reported by: John H. Palmieri Reviewer(s): John H. Palmieri, Kwankyu Lee
2 parents 05ad57b + 851126b commit 811ac59

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed

src/sage/rings/polynomial/multi_polynomial_libsingular.pyx

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5757,6 +5757,83 @@ cdef class MPolynomial_libsingular(MPolynomial_libsingular_base):
57575757
else:
57585758
return self * self.denominator()
57595759

5760+
def in_subalgebra(self, J, algorithm="algebra_containment"):
5761+
"""
5762+
Return whether this polynomial is contained in the subalgebra
5763+
generated by ``J``
5764+
5765+
INPUT:
5766+
5767+
- ``J`` -- list of elements of the parent polynomial ring
5768+
5769+
- ``algorithm`` -- can be ``"algebra_containment"`` (the default),
5770+
``"inSubring"``, or ``"groebner"``.
5771+
5772+
- ``"algebra_containment"``: use Singular's
5773+
``algebra_containment`` function,
5774+
https://www.singular.uni-kl.de/Manual/4-2-1/sing_1247.htm#SEC1328. The
5775+
Singular documentation suggests that this is frequently
5776+
faster than the next option.
5777+
5778+
- ``"inSubring"``: use Singular's ``inSubring`` function,
5779+
https://www.singular.uni-kl.de/Manual/4-2-0/sing_1240.htm#SEC1321.
5780+
5781+
- ``"groebner"``: use the algorithm described in Singular's
5782+
documentation, but within Sage: if the subalgebra
5783+
generators are `y_1`, ..., `y_m`, then create a new
5784+
polynomial algebra with the old generators along with new
5785+
ones: `z_1`, ..., `z_m`. Create the ideal `(z_1 - y_1,
5786+
..., z_m - y_m)`, and reduce the polynomial modulo this
5787+
ideal. The polynomial is contained in the subalgebra if
5788+
and only if the remainder involves only the new variables
5789+
`z_i`.
5790+
5791+
EXAMPLES::
5792+
5793+
sage: P.<x,y,z> = QQ[]
5794+
sage: J = [x^2 + y^2, x^2 + z^2]
5795+
sage: (y^2).in_subalgebra(J)
5796+
False
5797+
sage: a = (x^2 + y^2) * (x^2 + z^2)
5798+
sage: a.in_subalgebra(J, algorithm='inSubring')
5799+
True
5800+
sage: (a^2).in_subalgebra(J, algorithm='groebner')
5801+
True
5802+
sage: (a + a^2).in_subalgebra(J)
5803+
True
5804+
"""
5805+
R = self.parent()
5806+
algorithm = algorithm.lower()
5807+
from sage.libs.singular.function import singular_function, lib as singular_lib
5808+
singular_lib('algebra.lib')
5809+
if algorithm == "algebra_containment":
5810+
execute = singular_function('execute')
5811+
try:
5812+
get_printlevel = singular_function('get_printlevel')
5813+
except NameError:
5814+
execute('proc get_printlevel {return (printlevel);}')
5815+
get_printlevel = singular_function('get_printlevel')
5816+
# It's fairly verbose unless printlevel is -1.
5817+
saved_printlevel = get_printlevel()
5818+
execute('printlevel=-1')
5819+
contains = singular_function('algebra_containment')(self, R.ideal(J)) == 1
5820+
execute('printlevel={}'.format(saved_printlevel))
5821+
return contains
5822+
elif algorithm == "insubring":
5823+
return singular_function('inSubring')(self, R.ideal(J))[0] == 1
5824+
elif algorithm == "groebner":
5825+
new_gens = [f"newgens{i}" for i in range(len(J))]
5826+
ngens = len(new_gens)
5827+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
5828+
S = PolynomialRing(R.base_ring(), R.gens() + tuple(new_gens),
5829+
order=f'degrevlex({len(R.gens())}),degrevlex({ngens})')
5830+
new_gens = S.gens()[-ngens:]
5831+
I = S.ideal([g - S(j) for (g,j) in zip(new_gens, J)])
5832+
z = S(self).reduce(I)
5833+
return set(z.variables()).issubset(new_gens)
5834+
else:
5835+
raise ValueError("unknown algorithm")
5836+
57605837

57615838
def unpickle_MPolynomial_libsingular(MPolynomialRing_libsingular R, d):
57625839
"""

0 commit comments

Comments
 (0)