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

Commit 56920d5

Browse files
author
Release Manager
committed
Trac #28567: allow user to specify strategy for Groebner basis computations with Macaulay2
The {{{groebner_basis}}} method for an ideal in a polynomial ring can be computed using the default Groebner basis command in Macaulay2. Here we extend the functionality by allowing the user to specify the strategy to be used by Macaulay2. URL: https://trac.sagemath.org/28567 Reported by: saliola Ticket author(s): Dima Pasechnik, Franco Saliola Reviewer(s): Markus Wageringel, Dima Pasechnik
2 parents 1471238 + a22d20c commit 56920d5

File tree

2 files changed

+71
-16
lines changed

2 files changed

+71
-16
lines changed

src/sage/misc/cachefunc.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ cdef class CachedFunction(object):
925925
sage: P.<x,y> = QQ[]
926926
sage: I = P*[x,y]
927927
sage: from sage.misc.sageinspect import sage_getsourcelines
928-
sage: l = " elif algorithm == 'macaulay2:gb':\n"
928+
sage: l = ' elif algorithm.startswith("macaulay2:"):\n'
929929
sage: l in sage_getsourcelines(I.groebner_basis)[0] # indirect doctest
930930
True
931931

src/sage/rings/polynomial/multi_polynomial_ideal.py

Lines changed: 70 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2997,16 +2997,25 @@ def _macaulay2_(self, macaulay2=None):
29972997
self.__macaulay2[macaulay2] = z
29982998
return z
29992999

3000-
def _groebner_basis_macaulay2(self):
3000+
def _groebner_basis_macaulay2(self, strategy=None):
30013001
r"""
30023002
Return the Groebner basis for this ideal, computed using
30033003
Macaulay2.
30043004
30053005
ALGORITHM:
30063006
3007-
Computed using Macaulay2. A big advantage of Macaulay2 is that
3008-
it can compute the Groebner basis of ideals in polynomial
3009-
rings over the integers.
3007+
Compute the Groebner basis using the specified strategy in Macaulay2.
3008+
With no strategy option, the Macaulay2 ``gb`` command is used; other
3009+
possible strategies are "f4" and "mgb", which correspond to the "F4"
3010+
and "MGB" strategies in Macaulay2.
3011+
3012+
A big advantage of Macaulay2 is that it can compute the Groebner basis
3013+
of ideals in polynomial rings over the integers.
3014+
3015+
INPUT:
3016+
3017+
- ``strategy`` -- (default: ``'gb'``) argument specifying the strategy
3018+
to be used by Macaulay2; possiblities: ``'f4'``, ``'gb'``, ``'mgb'``.
30103019
30113020
EXAMPLES::
30123021
@@ -3027,11 +3036,41 @@ def _groebner_basis_macaulay2(self):
30273036
sage: I = ideal([y^2*z - x^3 - 19^2*x*z, y^2, 19^2])
30283037
sage: I.groebner_basis('macaulay2') # optional - macaulay2
30293038
[x^3, y^2, 361]
3039+
3040+
Over finite fields, Macaulay2 supports different algorithms to compute
3041+
Gröbner bases::
3042+
3043+
sage: R = PolynomialRing(GF(101), 'x', 4)
3044+
sage: I = sage.rings.ideal.Cyclic(R)
3045+
sage: gb1 = I.groebner_basis('macaulay2:gb') # optional - macaulay2
3046+
sage: I = sage.rings.ideal.Cyclic(R)
3047+
sage: gb2 = I.groebner_basis('macaulay2:mgb') # optional - macaulay2
3048+
sage: I = sage.rings.ideal.Cyclic(R)
3049+
sage: gb3 = I.groebner_basis('macaulay2:f4') # optional - macaulay2
3050+
sage: gb1 == gb2 == gb3 # optional - macaulay2
3051+
True
3052+
3053+
TESTS::
3054+
3055+
sage: R.<x,y,z> = ZZ[]
3056+
sage: I = ideal([y^2*z - x^3 - 19*x*z, y^2, 19^2])
3057+
sage: I.groebner_basis('macaulay2:gibberish') # optional - macaulay2
3058+
Traceback (most recent call last):
3059+
...
3060+
ValueError: unsupported Macaulay2 strategy
30303061
"""
30313062
from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence
30323063

30333064
I = self._macaulay2_()
3034-
G = str(I.gb().generators().external_string()).replace('\n','')
3065+
if strategy == "gb" or strategy is None:
3066+
m2G = I.gb().generators()
3067+
elif strategy == 'f4':
3068+
m2G = I.groebnerBasis('Strategy=>"F4"')
3069+
elif strategy == 'mgb':
3070+
m2G = I.groebnerBasis('Strategy=>"MGB"')
3071+
else:
3072+
raise ValueError("unsupported Macaulay2 strategy")
3073+
G = str(m2G.external_string()).replace('\n','')
30353074
i = G.rfind('{{')
30363075
j = G.rfind('}}')
30373076
G = G[i+2:j].split(',')
@@ -3817,6 +3856,12 @@ def groebner_basis(self, algorithm='', deg_bound=None, mult_bound=None, prot=Fal
38173856
'macaulay2:gb'
38183857
Macaulay2's ``gb`` command (if available)
38193858
3859+
'macaulay2:f4'
3860+
Macaulay2's ``GroebnerBasis`` command with the strategy "F4" (if available)
3861+
3862+
'macaulay2:mgb'
3863+
Macaulay2's ``GroebnerBasis`` command with the strategy "MGB" (if available)
3864+
38203865
'magma:GroebnerBasis'
38213866
Magma's ``Groebnerbasis`` command (if available)
38223867
@@ -3916,19 +3961,29 @@ def groebner_basis(self, algorithm='', deg_bound=None, mult_bound=None, prot=Fal
39163961
sage: gb == gb.reduced()
39173962
False
39183963
3919-
but that ``toy:buchberger2`` does.::
3964+
but that ``toy:buchberger2`` does. ::
39203965
39213966
sage: I = sage.rings.ideal.Katsura(P,3) # regenerate to prevent caching
39223967
sage: gb = I.groebner_basis('toy:buchberger2'); gb
39233968
[a - 60*c^3 + 158/7*c^2 + 8/7*c - 1, b + 30*c^3 - 79/7*c^2 + 3/7*c, c^4 - 10/21*c^3 + 1/84*c^2 + 1/84*c]
39243969
sage: gb == gb.reduced()
39253970
True
39263971
3927-
::
3972+
Here we use Macaulay2 with three different strategies over a finite
3973+
field. ::
39283974
3929-
sage: I = sage.rings.ideal.Katsura(P,3) # regenerate to prevent caching
3930-
sage: I.groebner_basis('macaulay2:gb') # optional - macaulay2
3931-
[a - 60*c^3 + 158/7*c^2 + 8/7*c - 1, b + 30*c^3 - 79/7*c^2 + 3/7*c, c^4 - 10/21*c^3 + 1/84*c^2 + 1/84*c]
3975+
sage: R.<a,b,c> = PolynomialRing(GF(101), 3)
3976+
sage: I = sage.rings.ideal.Katsura(R,3) # regenerate to prevent caching
3977+
sage: I.groebner_basis('macaulay2:gb') # optional - macaulay2
3978+
[c^3 + 28*c^2 - 37*b + 13*c, b^2 - 41*c^2 + 20*b - 20*c, b*c - 19*c^2 + 10*b + 40*c, a + 2*b + 2*c - 1]
3979+
3980+
sage: I = sage.rings.ideal.Katsura(R,3) # regenerate to prevent caching
3981+
sage: I.groebner_basis('macaulay2:f4') # optional - macaulay2
3982+
[c^3 + 28*c^2 - 37*b + 13*c, b^2 - 41*c^2 + 20*b - 20*c, b*c - 19*c^2 + 10*b + 40*c, a + 2*b + 2*c - 1]
3983+
3984+
sage: I = sage.rings.ideal.Katsura(R,3) # regenerate to prevent caching
3985+
sage: I.groebner_basis('macaulay2:mgb') # optional - macaulay2
3986+
[c^3 + 28*c^2 - 37*b + 13*c, b^2 - 41*c^2 + 20*b - 20*c, b*c - 19*c^2 + 10*b + 40*c, a + 2*b + 2*c - 1]
39323987
39333988
::
39343989
@@ -3937,7 +3992,7 @@ def groebner_basis(self, algorithm='', deg_bound=None, mult_bound=None, prot=Fal
39373992
[a - 60*c^3 + 158/7*c^2 + 8/7*c - 1, b + 30*c^3 - 79/7*c^2 + 3/7*c, c^4 - 10/21*c^3 + 1/84*c^2 + 1/84*c]
39383993
39393994
Singular and libSingular can compute Groebner basis with degree
3940-
restrictions.::
3995+
restrictions. ::
39413996
39423997
sage: R.<x,y> = QQ[]
39433998
sage: I = R*[x^3+y^2,x^2*y+1]
@@ -3980,7 +4035,7 @@ def groebner_basis(self, algorithm='', deg_bound=None, mult_bound=None, prot=Fal
39804035
The list of available options is provided at
39814036
:class:`~sage.libs.singular.option.LibSingularOptions`.
39824037
3983-
Note that Groebner bases over `\ZZ` can also be computed.::
4038+
Note that Groebner bases over `\ZZ` can also be computed. ::
39844039
39854040
sage: P.<a,b,c> = PolynomialRing(ZZ,3)
39864041
sage: I = P * (a + 2*b + 2*c - 1, a^2 - a + 2*b^2 + 2*c^2, 2*a*b + 2*b*c - b)
@@ -4212,8 +4267,8 @@ def groebner_basis(self, algorithm='', deg_bound=None, mult_bound=None, prot=Fal
42124267
if prot == "sage":
42134268
warn("The libsingular interface does not support prot='sage', reverting to 'prot=True'.")
42144269
gb = self._groebner_basis_libsingular(algorithm[len('libsingular:'):], deg_bound=deg_bound, mult_bound=mult_bound, prot=prot, *args, **kwds)
4215-
elif algorithm == 'macaulay2:gb':
4216-
gb = self._groebner_basis_macaulay2(*args, **kwds)
4270+
elif algorithm.startswith("macaulay2:"):
4271+
gb = self._groebner_basis_macaulay2(strategy=algorithm.split(":")[1], *args, **kwds)
42174272
elif algorithm == 'magma:GroebnerBasis':
42184273
gb = self._groebner_basis_magma(prot=prot, deg_bound=deg_bound, *args, **kwds)
42194274
elif algorithm == 'toy:buchberger':
@@ -4745,7 +4800,7 @@ def random_element(self, degree, compute_gb=False, *args, **kwds):
47454800
47464801
EXAMPLES:
47474802
4748-
We compute a uniformly random element up to the provided degree.::
4803+
We compute a uniformly random element up to the provided degree. ::
47494804
47504805
sage: P.<x,y,z> = GF(127)[]
47514806
sage: I = sage.rings.ideal.Katsura(P)

0 commit comments

Comments
 (0)