@@ -2888,38 +2888,65 @@ 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 ):
2891+ def _normal_basis_libsingular (self , degree ):
28922892 r"""
2893- Returns the normal basis for a given groebner basis. It will use
2894- the Groebner Basis as computed by
2893+ Return the normal basis for a given Groebner basis.
2894+
2895+ This will use the Groebner basis as computed by
28952896 ``MPolynomialIdeal._groebner_basis_libsingular()``.
28962897
2898+ INPUT:
2899+
2900+ - ``degree`` -- integer; if not ``None``, return only the monomials of
2901+ the given degree
2902+
28972903 EXAMPLES::
28982904
28992905 sage: R.<x,y,z> = PolynomialRing(QQ)
29002906 sage: I = R.ideal(x^2-2*x*z+5, x*y^2+y*z+1, 3*y^2-8*x*z)
29012907 sage: I.normal_basis() #indirect doctest
29022908 [z^2, y*z, x*z, z, x*y, y, x, 1]
2909+ sage: J = R.ideal(x^2-2*x*z+5)
2910+ sage: J.normal_basis(3) # indirect doctest
2911+ [z^3, y*z^2, x*z^2, y^2*z, x*y*z, y^3, x*y^2]
2912+
2913+ TESTS:
2914+
2915+ Check that zero is not included in trivial results::
2916+
2917+ sage: R.<x,y,z> = PolynomialRing(QQ)
2918+ sage: I = R.ideal(x^2-2*x*z+5, x*y^2+y*z+1, 3*y^2-8*x*z)
2919+ sage: I._normal_basis_libsingular(5)
2920+ []
29032921 """
29042922 from sage .rings .polynomial .multi_polynomial_ideal_libsingular import kbase_libsingular
29052923 from sage .rings .polynomial .multi_polynomial_sequence import PolynomialSequence
29062924 gb = self ._groebner_basis_libsingular ()
2907-
2908- return PolynomialSequence (self .ring (), kbase_libsingular (self .ring ().ideal (gb )), immutable = True )
2925+ res = kbase_libsingular (self .ring ().ideal (gb ), degree )
2926+ if len (res ) == 1 and res [0 ].is_zero ():
2927+ res = []
2928+ return PolynomialSequence (self .ring (), res , immutable = True )
29092929
29102930 @require_field
29112931 @handle_AA_and_QQbar
2912- def normal_basis (self , algorithm = 'libsingular' , singular = singular_default ):
2932+ def normal_basis (self , degree = None , algorithm = 'libsingular' ,
2933+ singular = singular_default ):
29132934 """
2914- Returns a vector space basis (consisting of monomials) of the
2915- quotient ring by the ideal, resp. of a free module by the module,
2916- in case it is finite dimensional and if the input is a standard
2917- basis with respect to the ring ordering.
2935+ Return a vector space basis (consisting of monomials) of the
2936+ quotient ring of this ideal.
29182937
29192938 INPUT:
29202939
2921- ``algorithm`` - defaults to use libsingular, if it is anything
2922- else we will use the ``kbase()`` command
2940+ - ``degree`` -- integer (default: ``None``); if not ``None``, return
2941+ only the monomials of the given degree
2942+
2943+ - ``algorithm`` -- string (default: ``"libsingular"``); if different
2944+ from the default, this will use the ``kbase()`` command from
2945+ Singular instead of libsingular
2946+
2947+ - ``singular`` -- instance of Singular interface (default: the default
2948+ instance); the singular interpreter to use when ``algorithm`` is not
2949+ ``"libsingular"``
29232950
29242951 EXAMPLES::
29252952
@@ -2930,6 +2957,18 @@ def normal_basis(self, algorithm='libsingular', singular=singular_default):
29302957 sage: I.normal_basis(algorithm='singular')
29312958 [y*z^2, z^2, y*z, z, x*y, y, x, 1]
29322959
2960+ The result can be restricted to monomials of a chosen degree, which is
2961+ particularly useful when the quotient ring is not finite-dimensional as
2962+ a vector space. ::
2963+
2964+ sage: J = R.ideal(x^2+y^2+z^2-4, x^2+2*y^2-5)
2965+ sage: J.dimension()
2966+ 1
2967+ sage: [J.normal_basis(d) for d in (0..3)]
2968+ [[1], [z, y, x], [z^2, y*z, x*z, x*y], [z^3, y*z^2, x*z^2, x*y*z]]
2969+ sage: [J.normal_basis(d, algorithm='singular') for d in (0..3)]
2970+ [[1], [z, y, x], [z^2, y*z, x*z, x*y], [z^3, y*z^2, x*z^2, x*y*z]]
2971+
29332972 TESTS:
29342973
29352974 Check that this method works over QQbar (:trac:`25351`)::
@@ -2938,15 +2977,22 @@ def normal_basis(self, algorithm='libsingular', singular=singular_default):
29382977 sage: I = R.ideal(x^2+y^2+z^2-4, x^2+2*y^2-5, x*z-1)
29392978 sage: I.normal_basis()
29402979 [y*z^2, z^2, y*z, z, x*y, y, x, 1]
2980+ sage: J = R.ideal(x^2+y^2+z^2-4, x^2+2*y^2-5)
2981+ sage: [J.normal_basis(d) for d in (0..3)]
2982+ [[1], [z, y, x], [z^2, y*z, x*z, x*y], [z^3, y*z^2, x*z^2, x*y*z]]
29412983 """
29422984 from sage .rings .polynomial .multi_polynomial_sequence import PolynomialSequence
29432985
29442986 if algorithm == 'libsingular' :
2945- return self ._normal_basis_libsingular ()
2987+ return self ._normal_basis_libsingular (degree )
29462988 else :
29472989 gb = self .groebner_basis ()
29482990 R = self .ring ()
2949- return PolynomialSequence (R , [R (f ) for f in singular .kbase (R .ideal (gb ))], immutable = True )
2991+ if degree is None :
2992+ res = singular .kbase (R .ideal (gb ))
2993+ else :
2994+ res = singular .kbase (R .ideal (gb ), int (degree ))
2995+ return PolynomialSequence (R , [R (f ) for f in res ], immutable = True )
29502996
29512997
29522998class MPolynomialIdeal_macaulay2_repr :
0 commit comments