@@ -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