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

Commit f0604bd

Browse files
committed
29625: support weighted term orders in normal_basis
1 parent 50c5ac8 commit f0604bd

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)