Sharedgröbner basis calculations / Calculations for p = 2.sagewsOpen in CoCalc
Gröbner Basis Calculations for $p=2$
#E is an elliptic curve defined by E : f = 0 over QQ_2
#Aim: Find (f,fx,fy) \cap <1,x,y,x*y>_ZZ[a1,a2,a3,a4,a6]
#Note: we do calculations over $ZZ$ and later use the fact that we are actually over ZZ_2.
from sage.rings.polynomial.toy_d_basis import d_basis
# We introduce an extra variable xy=x*y in order to have a monomial ordering that satiesfies x^2>y^2>xy >x>y ...
R.<xy,x,y,a1,a2,a3,a4,a6> = PolynomialRing(ZZ, 8, order = 'deglex(3),deglex(5)')
f = y^2 + a1*x*y + a3*y - x^3 + a2*x^2 + a4*x + a6
fx = f.derivative(x)
fy = f.derivative(y)
fz = xy-x*y
I = R.ideal(f,fx,fy,fz)
I_gb = d_basis(I); I_gb

Polynomial Sequence with 44 Polynomials in 8 Variables
for i in range(10):
[i, I_gb[i].lm()]

[0, x^3] [1, xy^2] [2, xy*x] [3, xy*y] [4, x^2*a2] [5, x^2*a4] [6, x^2] [7, x*y] [8, y^2] [9, xy*a2*a3^2]
#We want to find I \cap <1,x,x*y,y>, so we leave out elements with higher leading monomial.
I_neu = I_gb[9:];
#And we add the terms x*Delta, y*Delta and xy*Delta in order to get a generating system as a $ZZ[a1,a2,a3,a4,a6]$-module (!)
Delta = I_neu[len(I_neu)-1]
I_neu = I_neu + [Delta*x,Delta*y,Delta*xy]

#We show that only 4 of the elements in I_neu are necessary to generate all of <1,x,y,xy> as an ZZ_2[a1,a2,a3,a4,a6]-module.
#Those are:
generators = [I_neu[4], I_neu[5], I_neu[6], fy];
#Calculations are done over QQ[x,y], so that we can calculate lifts.
R.<xy,x,y,a1,a2,a3,a4,a6> = PolynomialRing(QQ,8,order = 'deglex(3),deglex(5)')
I_neu=[R(el) for el in I_neu]
generators = [R(el) for el in generators]

#Check that {I_neu[4], I_neu[5], I_neu[6],f y} generate I_neu
#The coefficients for the lifts of the elements in I_neu are stored in the list "coeff"
I_test = R.ideal(generators)
coeff = []
for el in I_neu:
if el in I_test:
coeff.append(el.lift(I_test))
else:
print 'not in ideal'
#This means I_neu[i] = sum_{j=0}^{3} coeff[i][j]*generators[j] for each i

#The coefficients are elements of QQ[x,y,a1,a2,a3,a4,a6]. We have to check that they are actually in ZZ_2[a1,a2,a3,a4,a6]. That is for each element: 2 does not divide its denominator and the leading monomial is in QQ[a1,a2,a3,a4,a6]
for el in coeff:
for poly in el:
if 2.divides(poly.denominator()) or not poly.lm() < y:
print 'non-integral lift', el