Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
28203: some PEP cleaning of toy_buchberger
Browse files Browse the repository at this point in the history
  • Loading branch information
mwageringel committed Jul 15, 2019
1 parent 95ea5f3 commit 4095e7f
Showing 1 changed file with 92 additions and 82 deletions.
174 changes: 92 additions & 82 deletions src/sage/rings/polynomial/toy_buchberger.py
Expand Up @@ -12,7 +12,7 @@
method on multivariate polynomial objects.
.. note::
.. NOTE::
The notion of 'term' and 'monomial' in [BW1993]_ is swapped from the
notion of those words in Sage (or the other way around, however you
Expand All @@ -26,8 +26,8 @@
Consider Katsura-6 w.r.t. a ``degrevlex`` ordering.::
sage: from sage.rings.polynomial.toy_buchberger import *
sage: P.<a,b,c,e,f,g,h,i,j,k> = PolynomialRing(GF(32003),10)
sage: I = sage.rings.ideal.Katsura(P,6)
sage: P.<a,b,c,e,f,g,h,i,j,k> = PolynomialRing(GF(32003))
sage: I = sage.rings.ideal.Katsura(P, 6)
sage: g1 = buchberger(I)
sage: g2 = buchberger_improved(I)
Expand All @@ -47,10 +47,10 @@
sage: Ideal(g1) == Ideal(g2) == Ideal(g3)
True
If ``get_verbose()`` is `>= 1` a protocol is provided::
If ``get_verbose()`` is `>= 1`, a protocol is provided::
sage: set_verbose(1)
sage: P.<a,b,c> = PolynomialRing(GF(127),3)
sage: P.<a,b,c> = PolynomialRing(GF(127))
sage: I = sage.rings.ideal.Katsura(P)
// sage... ideal
Expand Down Expand Up @@ -141,26 +141,27 @@
from sage.misc.misc import get_verbose
from sage.structure.sequence import Sequence

#some aliases that conform to Becker and Weispfenning's notation:
# some aliases that conform to Becker and Weispfenning's notation:
LCM = lambda f, g: f.parent().monomial_lcm(f, g)
LM = lambda f: f.lm()
LT = lambda f: f.lt()

def spol(f,g):

def spol(f, g):
"""
Computes the S-polynomial of f and g.
Compute the S-polynomial of f and g.
INPUT:
- ``f,g`` - polynomials
- ``f, g`` -- polynomials
OUTPUT:
- The S-polynomial of f and g.
EXAMPLES::
sage: R.<x,y,z> = PolynomialRing(QQ,3)
sage: R.<x,y,z> = PolynomialRing(QQ)
sage: from sage.rings.polynomial.toy_buchberger import spol
sage: spol(x^2 - z - 1, z^2 - y - 1)
x^2*y - z^3 + x^2 - z^2
Expand All @@ -171,18 +172,18 @@ def spol(f,g):

def buchberger(F):
"""
The original version of Buchberger's algorithm as presented in
[BW1993]_, page 214.
Compute a Groebner basis using the original version of Buchberger's
algorithm as presented in [BW1993]_, page 214.
INPUT:
- ``F`` - an ideal in a multivariate polynomial ring
- ``F`` -- an ideal in a multivariate polynomial ring
OUTPUT:
a Groebner basis for F
.. note::
.. NOTE::
The verbosity of this function may be controlled with a
``set_verbose()`` call. Any value >=1 will result in this
Expand All @@ -191,7 +192,7 @@ def buchberger(F):
EXAMPLES::
sage: from sage.rings.polynomial.toy_buchberger import buchberger
sage: R.<x,y,z> = PolynomialRing(QQ,3)
sage: R.<x,y,z> = PolynomialRing(QQ)
sage: I = R.ideal([x^2 - z - 1, z^2 - y - 1, x*y^2 - x - 1])
sage: set_verbose(0)
sage: gb = buchberger(I)
Expand All @@ -206,14 +207,14 @@ def buchberger(F):
if get_verbose() >= 1:
reductions_to_zero = 0

while B!=set():
g1,g2 = select(B)
B.remove( (g1,g2) )
while B:
g1, g2 = select(B)
B.remove((g1, g2))

h = spol(g1,g2).reduce(G)
h = spol(g1, g2).reduce(G)
if h != 0:
B = B.union( [(g,h) for g in G] )
G.add( h )
B = B.union((g, h) for g in G)
G.add(h)

if get_verbose() >= 1:
print("(%s, %s) => %s" % (g1, g2, h))
Expand All @@ -226,23 +227,24 @@ def buchberger(F):

return Sequence(G)


def buchberger_improved(F):
"""
An improved version of Buchberger's algorithm as presented in
[BW1993]_, page 232.
Compute a Groebner basis using an improved version of Buchberger's
algorithm as presented in [BW1993]_, page 232.
This variant uses the Gebauer-Moeller Installation to apply
Buchberger's first and second criterion to avoid useless pairs.
INPUT:
- ``F`` - an ideal in a multivariate polynomial ring
- ``F`` -- an ideal in a multivariate polynomial ring
OUTPUT:
a Groebner basis for F
.. note::
.. NOTE::
The verbosity of this function may be controlled with a
``set_verbose()`` call. Any value ``>=1`` will result in this
Expand All @@ -251,30 +253,31 @@ def buchberger_improved(F):
EXAMPLES::
sage: from sage.rings.polynomial.toy_buchberger import buchberger_improved
sage: R.<x,y,z> = PolynomialRing(QQ,3)
sage: R.<x,y,z> = PolynomialRing(QQ)
sage: set_verbose(0)
sage: sorted(buchberger_improved(R.ideal([x^4-y-z,x*y*z-1])))
sage: sorted(buchberger_improved(R.ideal([x^4-y-z, x*y*z-1])))
[x*y*z - 1, x^3 - y^2*z - y*z^2, y^3*z^2 + y^2*z^3 - x^2]
"""
F = inter_reduction(F.gens())

G = set()
B = set()

if get_verbose() >=1:
if get_verbose() >= 1:
reductions_to_zero = 0

while F != set():
while F:
f = min(F)
F.remove(f)
G,B = update(G,B,f)
G, B = update(G, B, f)

while B != set():
while B:

g1,g2 = select(B)
B.remove((g1,g2))
h = spol(g1,g2).reduce(G)
if h!=0: G,B = update(G,B,h)
g1, g2 = select(B)
B.remove((g1, g2))
h = spol(g1, g2).reduce(G)
if h != 0:
G, B = update(G, B, h)

if get_verbose() >= 1:
print("(%s, %s) => %s" % (g1, g2, h))
Expand All @@ -287,91 +290,94 @@ def buchberger_improved(F):

return Sequence(inter_reduction(G))

def update(G,B,h):

def update(G, B, h):
"""
Update ``G`` using the list of critical pairs ``B`` and the
Update ``G`` using the set of critical pairs ``B`` and the
polynomial ``h`` as presented in [BW1993]_, page 230. For this,
Buchberger's first and second criterion are tested.
This function implements the Gebauer-Moeller Installation.
INPUT:
- ``G`` - an intermediate Groebner basis
- ``B`` - a list of critical pairs
- ``h`` - a polynomial
- ``G`` -- an intermediate Groebner basis
- ``B`` -- a set of critical pairs
- ``h`` -- a polynomial
OUTPUT:
a tuple of an intermediate Groebner basis and a list of
a tuple of an intermediate Groebner basis and a set of
critical pairs
EXAMPLES::
sage: from sage.rings.polynomial.toy_buchberger import update
sage: R.<x,y,z> = PolynomialRing(QQ,3)
sage: R.<x,y,z> = PolynomialRing(QQ)
sage: set_verbose(0)
sage: update(set(),set(),x*y*z)
sage: update(set(), set(), x*y*z)
({x*y*z}, set())
sage: G,B = update(set(),set(),x*y*z-1)
sage: G,B = update(G,B,x*y^2-1)
sage: G,B
sage: G, B = update(set(), set(), x*y*z-1)
sage: G, B = update(G, B, x*y^2-1)
sage: G, B
({x*y*z - 1, x*y^2 - 1}, {(x*y^2 - 1, x*y*z - 1)})
"""
R = h.parent()

C = set([(h,g) for g in G])
C = set((h, g) for g in G)
D = set()

while C != set():
(h,g) = C.pop()
while C:
(h, g) = C.pop()

lcm_divides = lambda rhs: R.monomial_divides( LCM(LM(h),LM(rhs[1])), LCM(LM(h),LM(g)))
lcm_divides = lambda rhs: R.monomial_divides(LCM(LM(h), LM(rhs[1])),
LCM(LM(h), LM(g)))

if R.monomial_pairwise_prime(LM(h),LM(g)) or \
(\
not any( lcm_divides(f) for f in C ) \
and
not any( lcm_divides(f) for f in D ) \
):
D.add( (h,g) )
if R.monomial_pairwise_prime(LM(h), LM(g)) or \
(
not any(lcm_divides(f) for f in C)
and
not any(lcm_divides(f) for f in D)
):
D.add((h, g))

E = set()

while D != set():
(h,g) = D.pop()
if not R.monomial_pairwise_prime(LM(h),LM(g)):
E.add( (h,g) )
while D:
(h, g) = D.pop()
if not R.monomial_pairwise_prime(LM(h), LM(g)):
E.add((h, g))

B_new = set()

while B != set():
g1,g2 = B.pop()
if not R.monomial_divides( LM(h), LCM(LM(g1),LM(g2)) ) or \
R.monomial_lcm(LM(g1),LM( h)) == LCM(LM(g1),LM(g2)) or \
R.monomial_lcm(LM( h),LM(g2)) == LCM(LM(g1),LM(g2)) :
B_new.add( (g1,g2) )
while B:
g1, g2 = B.pop()
if not R.monomial_divides(LM(h), LCM(LM(g1), LM(g2))) or \
R.monomial_lcm(LM(g1), LM(h)) == LCM(LM(g1), LM(g2)) or \
R.monomial_lcm(LM(h), LM(g2)) == LCM(LM(g1), LM(g2)):
B_new.add((g1, g2))

B_new = B_new.union( E )
B_new = B_new.union(E)

G_new = set()

while G != set():
while G:
g = G.pop()
if not R.monomial_divides(LM(h), LM(g)):
G_new.add(g)

G_new.add(h)

return G_new,B_new
return G_new, B_new


def select(P):
"""
The normal selection strategy
Select a polynomial using the normal selection strategy.
INPUT:
- ``P`` - a list of critical pairs
- ``P`` -- a list of critical pairs
OUTPUT:
Expand All @@ -380,18 +386,21 @@ def select(P):
EXAMPLES::
sage: from sage.rings.polynomial.toy_buchberger import select
sage: R.<x,y,z> = PolynomialRing(QQ,3, order='lex')
sage: R.<x,y,z> = PolynomialRing(QQ, order='lex')
sage: ps = [x^3 - z -1, z^3 - y - 1, x^5 - y - 2]
sage: pairs = [[ps[i],ps[j]] for i in range(3) for j in range(i+1,3)]
sage: pairs = [[ps[i], ps[j]] for i in range(3) for j in range(i+1, 3)]
sage: select(pairs)
[x^3 - z - 1, -y + z^3 - 1]
"""
return min(P, key=lambda fi_fj: LCM(LM(fi_fj[0]), LM(fi_fj[1])).total_degree())
return min(P, key=lambda fi_fj: LCM(LM(fi_fj[0]),
LM(fi_fj[1])).total_degree())


def inter_reduction(Q):
r"""
If ``Q`` is the set `(f_1, ..., f_n)` this method
Compute inter-reduced polynomials from a set of polynomials.
If ``Q`` is the set `(f_1, ..., f_n)`, this method
returns `(g_1, ..., g_s)` such that:
- `<f_1,...,f_n> = <g_1,...,g_s>`
Expand All @@ -413,14 +422,14 @@ def inter_reduction(Q):
::
sage: P.<x,y> = QQ[]
sage: reduced = inter_reduction(set([x^2-5*y^2,x^3]))
sage: reduced = inter_reduction(set([x^2-5*y^2, x^3]))
sage: reduced == set([x*y^2, x^2-5*y^2])
True
sage: reduced == inter_reduction(set([2*(x^2-5*y^2),x^3]))
sage: reduced == inter_reduction(set([2*(x^2-5*y^2), x^3]))
True
"""
if not Q:
return Q # if Q is empty we cannot get a base ring
return Q # if Q is empty we cannot get a base ring
base_ring = next(iter(Q)).base_ring()

Q = set(Q)
Expand All @@ -429,9 +438,10 @@ def inter_reduction(Q):
for p in sorted(Qbar):
Q.remove(p)
h = p.reduce(Q)
if h!=0:
if h != 0:
Q.add(h)
if Qbar == Q:
if base_ring.is_field():
return set([f.lc()**(-1) * f for f in Qbar])
else: return Qbar
return set(f.lc()**(-1) * f for f in Qbar)
else:
return Qbar

0 comments on commit 4095e7f

Please sign in to comment.