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

Commit

Permalink
Fixing some things and tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
tscrim authored and trevorkarn committed Jul 26, 2022
1 parent 368491c commit f2a25e3
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 136 deletions.
145 changes: 23 additions & 122 deletions src/sage/algebras/clifford_algebra.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
r"""
Clifford Algebras
Expand Down Expand Up @@ -1850,118 +1849,6 @@ def lifted_form(x, y):
codomain=self.base_ring(),
name="Bilinear Form")

def exterior_bitset_f4(self, I):
r"""
Return a Groebner basis for an ideal `I` of the exterior algebra.
EXAMPLES::
sage: E.<a,b,c,d,e> = ExteriorAlgebra(QQ)
sage: rels = [c*d*e - b*d*e + b*c*e - b*c*d,
....: c*d*e - a*d*e + a*c*e - a*c*d,
....: b*d*e - a*d*e + a*b*e - a*b*d,
....: b*c*e - a*c*e + a*b*e - a*b*c,
....: b*c*d - a*c*d + a*b*d - a*b*c]
sage: I = E.ideal(rels);
sage: exterior_bitset_f4(I)
(b*c*d-b*c*e+b*d*e-c*d*e,
a*c*d-a*c*e+a*d*e-c*d*e,
a*b*d-a*b*e+a*d*e-b*d*e,
a*b*c-a*b*e+a*c*e-b*c*e)
The example above was computed first using M2:
E = QQ[a..e, SkewCommutative => true]
I = ideal( c*d*e - b*d*e + b*c*e - b*c*d,
c*d*e - a*d*e + a*c*e - a*c*d,
b*d*e - a*d*e + a*b*e - a*b*d,
b*c*e - a*c*e + a*b*e - a*b*c,
b*c*d - a*c*d + a*b*d - a*b*c)
groebnerBasis(I)
returns:
o3 = | bcd-bce+bde-cde acd-ace+ade-cde abd-abe+ade-bde abc-abe+ace-bce |
"""

# following https://pi.math.cornell.edu/~djp282/documents/math6140-2017a.pdf

def get_pairs(pairs):
# this implements the `select` function of Peifer

# change pairs in here so I don't have to do it after calling get_pairs.
return pairs.pop() # temporarily do Buchbergers

def f4_sel(P):
# this is the function on page 13 of the original F4 paper.

return P

# P is a list of pairs
# TODO: implement the better choice.

def symbolic_preprocessing(P, G):
# the first/second terms of the S polynomial might
# have to be adjusted a la Stokes' paper
left = set() # the first term of the S polynomial
right = set() # the second term of the S polynomial
L = left.union(right)
done = set(f.monomials()[0] for f in L)

from itertools import chain
mon_L = set(chain.from_iterable(f.monomials() for f in L))

while done != mon_L:
m = sorted(mon_L.difference(done), key = lambda x: (-len(x.support_of_term()), tuple(x.support_of_term())))[0]
done = done.add(m)
for g in G:
if divides(g.monomials()[0], m):
L.add(m * g/g.monomials()[0])
break
return L

def f4_reduce(P, G):
# given a current set of pairs P and a
# current basis G, return G' of new basis

L = symbolic_preprocessing(P, G)
lm_L = set(f.monomials()[0] for f in L)

d = dict()
for i, f in enumerate(F):
d.update(((i,hash(m)),c) for m,c in f._monomial_coefficients.items())
M = MatrixSpace(E.base_ring(), len(L), 2^self.ngens(), sparse=True)
poly_matrix = M(d).rref()

Lprime = set(E._from_dict(dict((FrozenBitset(format(k,'b')[::-1]),v) for k,v in row.dict().items())) for row in poly_matrix)

Gprime = set()

for f in Lprime:
if f.monomials()[0] in lm_L:
continue
Gprime.add(f)

return Gprime

F = I.gens()
G = set(F)
k = I.ngens()

from itertools import combinations
pairs = set(combinations(range(k), 2)) # this is Peifer's P

while pairs:
P = f4_sel(pairs) # this is different from Buchbergers which would be pairs.pop()
Gtemp = f4_reduce(P, G)
pairs.difference_update(P)

for h in Gtemp:
G.add(h)
k += 1
pairs.update((i,k) for i in range(k))

return G

def _ideal_class_(self, n=0):
"""
Return the class that is used to implement ideals of ``self``.
Expand Down Expand Up @@ -2950,7 +2837,7 @@ def reduce(self, f):
"""
return f.reduce(self)

def groebner_basis(self, term_order="negrevlex"):
def groebner_basis(self, term_order="neglex"):
r"""
Return the reduced Gröbner basis of ``self``.
Expand All @@ -2959,13 +2846,13 @@ def groebner_basis(self, term_order="negrevlex"):
- ``term_order`` -- the term order used to compute the Gröbner basis;
must be one of the following:
* ``"negrevlex"`` -- (default) negative reverse lex order
* ``"neglex"`` -- (default) negative (read right-to-left) lex order
* ``"degrevlex"`` -- degree reverse lex order
* ``"deglex"`` -- degree lex order
EXAMPLES:
We compute an example that was checked against Macaulay2::
We compute an example::
sage: E.<a,b,c,d,e> = ExteriorAlgebra(QQ)
sage: rels = [c*d*e - b*d*e + b*c*e - b*c*d,
Expand All @@ -2983,19 +2870,33 @@ def groebner_basis(self, term_order="negrevlex"):
With different term orders::
sage: I.groebner_basis("degrevlex")
(-b*c*d + b*c*e - b*d*e + c*d*e,
-a*c*d + a*c*e - a*d*e + c*d*e,
-a*b*d + a*b*e - a*d*e + b*d*e,
-a*b*c + a*b*e - a*c*e + b*c*e)
(b*c*d - b*c*e + b*d*e - c*d*e,
a*c*d - a*c*e + a*d*e - c*d*e,
a*b*d - a*b*e + a*d*e - b*d*e,
a*b*c - a*b*e + a*c*e - b*c*e)
sage: I.groebner_basis("deglex")
(-a*c*d + a*c*e - a*d*e + c*d*e,
-a*b*c + a*b*d - a*c*d + b*c*d,
-a*b*d + a*b*e - a*d*e + b*d*e,
-a*b*c + a*b*e - a*c*e + b*c*e)
The example above was computed first using M2, which agrees with
the ``"degrevlex"`` ordering::
E = QQ[a..e, SkewCommutative => true]
I = ideal( c*d*e - b*d*e + b*c*e - b*c*d,
c*d*e - a*d*e + a*c*e - a*c*d,
b*d*e - a*d*e + a*b*e - a*b*d,
b*c*e - a*c*e + a*b*e - a*b*c,
b*c*d - a*c*d + a*b*d - a*b*c)
groebnerBasis(I)
returns:
o3 = | bcd-bce+bde-cde acd-ace+ade-cde abd-abe+ade-bde abc-abe+ace-bce |
"""
if term_order == "negrevlex":
from sage.algebras.exterior_algebra_groebner import GroebnerStrategyNegRevLex as strategy
if term_order == "neglex":
from sage.algebras.exterior_algebra_groebner import GroebnerStrategyNegLex as strategy
elif term_order == "degrevlex":
from sage.algebras.exterior_algebra_groebner import GroebnerStrategyDegRevLex as strategy
elif term_order == "deglex":
Expand Down
2 changes: 1 addition & 1 deletion src/sage/algebras/exterior_algebra_groebner.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ cdef class GroebnerStrategy:
cdef Integer bitset_to_int(self, FrozenBitset X)
cdef FrozenBitset int_to_bitset(self, Integer n)

cdef class GroebnerStrategyNegRevLex(GroebnerStrategy):
cdef class GroebnerStrategyNegLex(GroebnerStrategy):
pass

cdef class GroebnerStrategyDegRevLex(GroebnerStrategy):
Expand Down
19 changes: 6 additions & 13 deletions src/sage/algebras/exterior_algebra_groebner.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ cdef class GroebnerStrategy:
"""
Perform the preprocessing step.
"""
#print("Start preprocessing:", P)
cdef CliffordAlgebraElement f, g, f0, f1

cdef set L = set()
Expand Down Expand Up @@ -159,7 +158,6 @@ cdef class GroebnerStrategy:
monL.update(set(f._monomial_coefficients) - done)
L.add(f)
break
#print("preprocessing:", L)
return L

cdef inline list reduction(self, list P, list G):
Expand Down Expand Up @@ -205,10 +203,8 @@ cdef class GroebnerStrategy:
P[deg] = [(f0, f1)]

while P:
#print("Cur G:", G)
Pp = P.pop(min(P)) # The selection: lowest lcm degree
Gp = self.reduction(Pp, G)
#print("Reduction yielded:", Gp)
G.extend(Gp)
for j in range(n, len(G)):
f1 = G[j]
Expand All @@ -223,8 +219,6 @@ cdef class GroebnerStrategy:
P[deg] = [(f0, f1)]
n = len(G)

#print(G)

# Now that we have a Gröbner basis, we make this into a reduced Gröbner basis
cdef set pairs = set((i, j) for i in range(n) for j in range(n) if i != j)
cdef list supp
Expand Down Expand Up @@ -254,13 +248,12 @@ cdef class GroebnerStrategy:
break
if G[i] != f:
G[i] = f
#print("reduction:", G)
if not f:
pairs.difference_update((k, i) for k in range(n))
else:
pairs.update((k, i) for k in range(n) if k != i)

return tuple([f for f in G if f])
return tuple([~f[self.leading_supp(f)] * f for f in G if f])

cdef Integer bitset_to_int(self, FrozenBitset X):
raise NotImplementedError
Expand All @@ -278,7 +271,7 @@ cdef class GroebnerStrategy:
sage: from sage.algebras.exterior_algebra_groebner import *
sage: E.<x,y,z> = ExteriorAlgebra(QQ)
sage: I = E.ideal([x, y])
sage: GroebnerStrategyNegRevLex(I).sorted_monomials()
sage: GroebnerStrategyNegLex(I).sorted_monomials()
[1, x, y, x*y, z, x*z, y*z, x*y*z]
sage: GroebnerStrategyDegLex(I).sorted_monomials()
[1, x, y, z, x*y, x*z, y*z, x*y*z]
Expand All @@ -287,7 +280,7 @@ cdef class GroebnerStrategy:
sage: E.<a,b,c,d> = ExteriorAlgebra(QQ)
sage: I = E.ideal([a, b])
sage: GroebnerStrategyNegRevLex(I).sorted_monomials()
sage: GroebnerStrategyNegLex(I).sorted_monomials()
[1,
a,
b, a*b,
Expand Down Expand Up @@ -324,7 +317,7 @@ cdef class GroebnerStrategy:
sage: from sage.algebras.exterior_algebra_groebner import *
sage: E.<a,b,c,d> = ExteriorAlgebra(QQ)
sage: I = E.ideal([a, b])
sage: GroebnerStrategyDegLex(I).sorted_monomials()
sage: GroebnerStrategyDegLex(I).monomial_to_int()
{1: 0,
a: 1, b: 2, c: 3, d: 4,
a*b: 5, a*c: 6, a*d: 7, b*c: 8, b*d: 9, c*d: 10,
Expand All @@ -340,9 +333,9 @@ cdef class GroebnerStrategy:
B = self.E.basis()
return {B[X]: self.bitset_to_int(X) for X in self.E._indices}

cdef class GroebnerStrategyNegRevLex(GroebnerStrategy):
cdef class GroebnerStrategyNegLex(GroebnerStrategy):
"""
Gröbner basis strategy implementing negrevlex ordering.
Gröbner basis strategy implementing neglex ordering.
"""
cdef inline Integer bitset_to_int(self, FrozenBitset X):
"""
Expand Down

0 comments on commit f2a25e3

Please sign in to comment.