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

Commit 223802c

Browse files
committed
29543: add degree option to normal_basis
1 parent 10ed24e commit 223802c

File tree

2 files changed

+75
-17
lines changed

2 files changed

+75
-17
lines changed

src/sage/rings/polynomial/multi_polynomial_ideal.py

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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

29522998
class MPolynomialIdeal_macaulay2_repr:

src/sage/rings/polynomial/multi_polynomial_ideal_libsingular.pyx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,17 @@ cdef ideal *sage_ideal_to_singular_ideal(I) except NULL:
146146
raise TypeError("All generators must be of type MPolynomial_libsingular.")
147147
return i
148148

149-
def kbase_libsingular(I):
149+
def kbase_libsingular(I, degree=None):
150150
"""
151151
SINGULAR's ``kbase()`` algorithm.
152152
153153
INPUT:
154154
155155
- ``I`` -- a groebner basis of an ideal
156156
157+
- ``degree`` -- integer (default: ``None``); if not ``None``, return
158+
only the monomials of the given degree
159+
157160
OUTPUT:
158161
159162
Computes a vector space basis (consisting of monomials) of the quotient
@@ -162,12 +165,19 @@ def kbase_libsingular(I):
162165
the ring ordering. If the input is not a standard basis, the leading terms
163166
of the input are used and the result may have no meaning.
164167
168+
With two arguments: computes the part of a vector space basis of the
169+
respective quotient with degree of the monomials equal to the second
170+
argument. Here, the quotient does not need to be finite dimensional.
171+
165172
EXAMPLES::
166173
167174
sage: R.<x,y> = PolynomialRing(QQ, order='lex')
168175
sage: I = R.ideal(x^2-2*y^2, x*y-3)
169-
sage: I.normal_basis()
176+
sage: I.normal_basis() # indirect doctest
170177
[y^3, y^2, y, 1]
178+
sage: J = R.ideal(x^2-2*y^2)
179+
sage: [J.normal_basis(d) for d in (0..4)] # indirect doctest
180+
[[1], [y, x], [y^2, x*y], [y^3, x*y^2], [y^4, x*y^3]]
171181
"""
172182

173183
global singular_options
@@ -179,8 +189,10 @@ def kbase_libsingular(I):
179189
cdef ideal *result
180190
singular_options = singular_options | Sy_bit(OPT_REDSB)
181191

192+
degree = -1 if degree is None else int(degree)
193+
182194
sig_on()
183-
result = scKBase(-1, i, q)
195+
result = scKBase(degree, i, q)
184196
sig_off()
185197

186198
id_Delete(&i, r)

0 commit comments

Comments
 (0)