Skip to content
This repository was archived by the owner on Feb 1, 2023. It is now read-only.

Commit ec4fd4a

Browse files
author
Release Manager
committed
Trac #29625: support for weighted term orders in normal_basis
As a follow-up to #29543, this ticket changes the `normal_basis` method of ideals to handle the case of weighted term orders. With this change, the degree of the monomials in the normal basis is taken with respect to the weighted degree (which agrees with Sage's notion of degree). {{{ sage: R.<x,y,z> = PolynomialRing(QQ, order=TermOrder('wdegrevlex', (1, 2, 3))) sage: I = R.ideal(x*y^2 + x^5, z*y + x^3*y) sage: I.normal_basis(degree=9) [x^2*y^2*z, x^3*z^2, x*y*z^2, z^3] sage: all(f.degree() == 9 for f in _) True }}} This also came up in an [https://ask.sagemath.org/question/47623 Ask SageMath question]. The implementation uses the Singular function [https://www.singular.uni- kl.de/Manual/4-1-2/sing_377.htm#SEC417 weightKB]. URL: https://trac.sagemath.org/29625 Reported by: gh-mwageringel Ticket author(s): Markus Wageringel Reviewer(s): Travis Scrimshaw
2 parents 6e2957b + f0604bd commit ec4fd4a

File tree

1 file changed

+43
-6
lines changed

1 file changed

+43
-6
lines changed

src/sage/rings/polynomial/multi_polynomial_ideal.py

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2888,7 +2888,7 @@ def hilbert_numerator(self, grading = None, algorithm = 'sage'):
28882888
raise ValueError("'algorithm' must be one of 'sage' or 'singular'")
28892889

28902890
@require_field
2891-
def _normal_basis_libsingular(self, degree):
2891+
def _normal_basis_libsingular(self, degree, weights=None):
28922892
r"""
28932893
Return the normal basis for a given Groebner basis.
28942894
@@ -2899,6 +2899,9 @@ def _normal_basis_libsingular(self, degree):
28992899
29002900
- ``degree`` -- ``None`` or integer
29012901
2902+
- ``weights`` -- tuple of positive integers (default: ``None``); if not
2903+
``None``, compute the degree with respect to these weights
2904+
29022905
OUTPUT:
29032906
29042907
If ``degree`` is an integer, only the monomials of the given degree in
@@ -2913,6 +2916,9 @@ def _normal_basis_libsingular(self, degree):
29132916
sage: J = R.ideal(x^2-2*x*z+5)
29142917
sage: J.normal_basis(3) # indirect doctest
29152918
[z^3, y*z^2, x*z^2, y^2*z, x*y*z, y^3, x*y^2]
2919+
sage: [J._normal_basis_libsingular(d, (2, 2, 3)) for d in (0..8)]
2920+
[[1], [], [x, y], [z], [x*y, y^2], [x*z, y*z], [x*y^2, y^3, z^2],
2921+
[x*y*z, y^2*z], [x*y^3, y^4, x*z^2, y*z^2]]
29162922
29172923
TESTS:
29182924
@@ -2926,7 +2932,13 @@ def _normal_basis_libsingular(self, degree):
29262932
from sage.rings.polynomial.multi_polynomial_ideal_libsingular import kbase_libsingular
29272933
from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence
29282934
gb = self._groebner_basis_libsingular()
2929-
res = kbase_libsingular(self.ring().ideal(gb), degree)
2935+
J = self.ring().ideal(gb)
2936+
if weights is None:
2937+
res = kbase_libsingular(J, degree)
2938+
else:
2939+
from sage.libs.singular.function_factory import ff
2940+
res = ff.weightKB(J, -1 if degree is None else degree,
2941+
tuple(weights), attributes={J: {'isSB': 1}})
29302942
if len(res) == 1 and res[0].is_zero():
29312943
res = []
29322944
return PolynomialSequence(self.ring(), res, immutable=True)
@@ -2943,7 +2955,8 @@ def normal_basis(self, degree=None, algorithm='libsingular',
29432955
- ``degree`` -- integer (default: ``None``)
29442956
29452957
- ``algorithm`` -- string (default: ``"libsingular"``); if not the
2946-
default, this will use the ``kbase()`` command from Singular
2958+
default, this will use the ``kbase()`` or ``weightKB()`` command from
2959+
Singular
29472960
29482961
- ``singular`` -- the singular interpreter to use when ``algorithm`` is
29492962
not ``"libsingular"`` (default: the default instance)
@@ -2974,18 +2987,35 @@ def normal_basis(self, degree=None, algorithm='libsingular',
29742987
sage: [J.normal_basis(d, algorithm='singular') for d in (0..3)]
29752988
[[1], [z, y, x], [z^2, y*z, x*z, x*y], [z^3, y*z^2, x*z^2, x*y*z]]
29762989
2990+
In case of a polynomial ring with a weighted term order, the degree of
2991+
the monomials is taken with respect to the weights. ::
2992+
2993+
sage: T = TermOrder('wdegrevlex', (1, 2, 3))
2994+
sage: R.<x,y,z> = PolynomialRing(QQ, order=T)
2995+
sage: B = R.ideal(x*y^2 + x^5, z*y + x^3*y).normal_basis(9); B
2996+
[x^2*y^2*z, x^3*z^2, x*y*z^2, z^3]
2997+
sage: all(f.degree() == 9 for f in B)
2998+
True
2999+
29773000
TESTS:
29783001
29793002
Check that this method works over QQbar (:trac:`25351`)::
29803003
2981-
sage: P.<x,y,z> = QQbar[]
3004+
sage: R.<x,y,z> = QQbar[]
29823005
sage: I = R.ideal(x^2+y^2+z^2-4, x^2+2*y^2-5, x*z-1)
29833006
sage: I.normal_basis()
29843007
[y*z^2, z^2, y*z, z, x*y, y, x, 1]
29853008
sage: J = R.ideal(x^2+y^2+z^2-4, x^2+2*y^2-5)
29863009
sage: [J.normal_basis(d) for d in (0..3)]
29873010
[[1], [z, y, x], [z^2, y*z, x*z, x*y], [z^3, y*z^2, x*z^2, x*y*z]]
29883011
3012+
Check the option ``algorithm="singular"`` with a weighted term order::
3013+
3014+
sage: T = TermOrder('wdegrevlex', (1, 2, 3))
3015+
sage: S.<x,y,z> = PolynomialRing(GF(2), order=T)
3016+
sage: S.ideal(x^6 + y^3 + z^2).normal_basis(6, algorithm='singular')
3017+
[x^4*y, x^2*y^2, y^3, x^3*z, x*y*z, z^2]
3018+
29893019
Check the deprecation::
29903020
29913021
sage: R.<x,y> = PolynomialRing(QQ)
@@ -3001,15 +3031,22 @@ def normal_basis(self, degree=None, algorithm='libsingular',
30013031
algorithm = degree
30023032
degree = None
30033033

3034+
weights = tuple(x.degree() for x in self.ring().gens())
3035+
if all(w == 1 for w in weights):
3036+
weights = None
3037+
30043038
if algorithm == 'libsingular':
3005-
return self._normal_basis_libsingular(degree)
3039+
return self._normal_basis_libsingular(degree, weights=weights)
30063040
else:
30073041
gb = self.groebner_basis()
30083042
R = self.ring()
30093043
if degree is None:
30103044
res = singular.kbase(R.ideal(gb))
3011-
else:
3045+
elif weights is None:
30123046
res = singular.kbase(R.ideal(gb), int(degree))
3047+
else:
3048+
res = singular.weightKB(R.ideal(gb), int(degree),
3049+
singular(weights, type='intvec'))
30133050
return PolynomialSequence(R, [R(f) for f in res], immutable=True)
30143051

30153052

0 commit comments

Comments
 (0)