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

Commit 5912940

Browse files
author
Release Manager
committed
Trac #29543: normal_basis for positive-dimensional ideals
This ticket adds a `degree` option to the `normal_basis` method of ideals. This allows to limit the output to monomials of a particular degree, which is useful when the corresponding quotient ring is not finite- dimensional as a vector space. {{{ sage: R.<x,y,z> = QQ[] sage: I = R.ideal(x^2 + y^2 - 1) sage: [I.normal_basis(d) for d in (0..3)] [[1], [z, y, x], [z^2, y*z, x*z, y^2, x*y], [z^3, y*z^2, x*z^2, y^2*z, x*y*z, y^3, x*y^2]] }}} Previously, the method could only be used when the quotient ring was finite-dimensional. This functionality is provided by Singular. For reference, the corresponding Singular function is [https://www.singular.uni- kl.de/Manual/4-1-2/sing_275.htm#SEC315 kbase]. URL: https://trac.sagemath.org/29543 Reported by: gh-mwageringel Ticket author(s): Markus Wageringel Reviewer(s): Travis Scrimshaw, Kwankyu Lee
2 parents b327485 + 8fd5628 commit 5912940

File tree

2 files changed

+93
-17
lines changed

2 files changed

+93
-17
lines changed

src/sage/rings/polynomial/multi_polynomial_ideal.py

Lines changed: 78 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2888,38 +2888,70 @@ 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`` -- ``None`` or integer
2901+
2902+
OUTPUT:
2903+
2904+
If ``degree`` is an integer, only the monomials of the given degree in
2905+
the normal basis.
2906+
28972907
EXAMPLES::
28982908
28992909
sage: R.<x,y,z> = PolynomialRing(QQ)
29002910
sage: I = R.ideal(x^2-2*x*z+5, x*y^2+y*z+1, 3*y^2-8*x*z)
29012911
sage: I.normal_basis() #indirect doctest
29022912
[z^2, y*z, x*z, z, x*y, y, x, 1]
2913+
sage: J = R.ideal(x^2-2*x*z+5)
2914+
sage: J.normal_basis(3) # indirect doctest
2915+
[z^3, y*z^2, x*z^2, y^2*z, x*y*z, y^3, x*y^2]
2916+
2917+
TESTS:
2918+
2919+
Check that zero is not included in trivial results::
2920+
2921+
sage: R.<x,y,z> = PolynomialRing(QQ)
2922+
sage: I = R.ideal(x^2-2*x*z+5, x*y^2+y*z+1, 3*y^2-8*x*z)
2923+
sage: I._normal_basis_libsingular(5)
2924+
[]
29032925
"""
29042926
from sage.rings.polynomial.multi_polynomial_ideal_libsingular import kbase_libsingular
29052927
from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence
29062928
gb = self._groebner_basis_libsingular()
2907-
2908-
return PolynomialSequence(self.ring(), kbase_libsingular(self.ring().ideal(gb)), immutable=True)
2929+
res = kbase_libsingular(self.ring().ideal(gb), degree)
2930+
if len(res) == 1 and res[0].is_zero():
2931+
res = []
2932+
return PolynomialSequence(self.ring(), res, immutable=True)
29092933

29102934
@require_field
29112935
@handle_AA_and_QQbar
2912-
def normal_basis(self, algorithm='libsingular', singular=singular_default):
2936+
def normal_basis(self, degree=None, algorithm='libsingular',
2937+
singular=singular_default):
29132938
"""
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.
2939+
Return a vector space basis of the quotient ring of this ideal.
29182940
29192941
INPUT:
29202942
2921-
``algorithm`` - defaults to use libsingular, if it is anything
2922-
else we will use the ``kbase()`` command
2943+
- ``degree`` -- integer (default: ``None``)
2944+
2945+
- ``algorithm`` -- string (default: ``"libsingular"``); if not the
2946+
default, this will use the ``kbase()`` command from Singular
2947+
2948+
- ``singular`` -- the singular interpreter to use when ``algorithm`` is
2949+
not ``"libsingular"`` (default: the default instance)
2950+
2951+
OUTPUT:
2952+
2953+
Monomials in the basis. If ``degree`` is given, only the monomials of
2954+
the given degree are returned.
29232955
29242956
EXAMPLES::
29252957
@@ -2930,6 +2962,18 @@ def normal_basis(self, algorithm='libsingular', singular=singular_default):
29302962
sage: I.normal_basis(algorithm='singular')
29312963
[y*z^2, z^2, y*z, z, x*y, y, x, 1]
29322964
2965+
The result can be restricted to monomials of a chosen degree, which is
2966+
particularly useful when the quotient ring is not finite-dimensional as
2967+
a vector space. ::
2968+
2969+
sage: J = R.ideal(x^2+y^2+z^2-4, x^2+2*y^2-5)
2970+
sage: J.dimension()
2971+
1
2972+
sage: [J.normal_basis(d) for d in (0..3)]
2973+
[[1], [z, y, x], [z^2, y*z, x*z, x*y], [z^3, y*z^2, x*z^2, x*y*z]]
2974+
sage: [J.normal_basis(d, algorithm='singular') for d in (0..3)]
2975+
[[1], [z, y, x], [z^2, y*z, x*z, x*y], [z^3, y*z^2, x*z^2, x*y*z]]
2976+
29332977
TESTS:
29342978
29352979
Check that this method works over QQbar (:trac:`25351`)::
@@ -2938,15 +2982,35 @@ def normal_basis(self, algorithm='libsingular', singular=singular_default):
29382982
sage: I = R.ideal(x^2+y^2+z^2-4, x^2+2*y^2-5, x*z-1)
29392983
sage: I.normal_basis()
29402984
[y*z^2, z^2, y*z, z, x*y, y, x, 1]
2985+
sage: J = R.ideal(x^2+y^2+z^2-4, x^2+2*y^2-5)
2986+
sage: [J.normal_basis(d) for d in (0..3)]
2987+
[[1], [z, y, x], [z^2, y*z, x*z, x*y], [z^3, y*z^2, x*z^2, x*y*z]]
2988+
2989+
Check the deprecation::
2990+
2991+
sage: R.<x,y> = PolynomialRing(QQ)
2992+
sage: _ = R.ideal(x^2+y^2, x*y+2*y).normal_basis('singular')
2993+
doctest:...: DeprecationWarning: "algorithm" should be used as keyword argument
2994+
See https://trac.sagemath.org/29543 for details.
29412995
"""
29422996
from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence
2997+
if isinstance(degree, str):
2998+
from sage.misc.superseded import deprecation
2999+
deprecation(29543,
3000+
'"algorithm" should be used as keyword argument')
3001+
algorithm = degree
3002+
degree = None
29433003

29443004
if algorithm == 'libsingular':
2945-
return self._normal_basis_libsingular()
3005+
return self._normal_basis_libsingular(degree)
29463006
else:
29473007
gb = self.groebner_basis()
29483008
R = self.ring()
2949-
return PolynomialSequence(R, [R(f) for f in singular.kbase(R.ideal(gb))], immutable=True)
3009+
if degree is None:
3010+
res = singular.kbase(R.ideal(gb))
3011+
else:
3012+
res = singular.kbase(R.ideal(gb), int(degree))
3013+
return PolynomialSequence(R, [R(f) for f in res], immutable=True)
29503014

29513015

29523016
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)