How to express the coefficients of an iterated group action on a basis as a matrix?

I have a basis $(b_i)_{i \in I} = (1, y_1, y_2, y_1^2, y_1y_2, y_2^2, y_1^2y_2, y_1y_2^2, y_1^2y_2^2)$, and a group action $g$ on that basis, where $g$ acts by:

$g(y_1) = y_1+1$, and $g(y_2) = y_2-y_1^2-y_1$.

For each basis element $b_i$, I want the array $(b_i, g(b_i), g^2(b_i), ..., g^8(b_i))$. I want to see the dimension of the vector space spanned by those values.

My first and foremost question is as follows: How can I get sage to put the coefficients of the array of polynomials (in a quotient ring) into columns of a matrix?

I can't seem to get sage to spit out the coefficients at all! I tried S(b_i).coefficients() and S(b_i).list(), and I got AttributeError: 'QuotientRing_generic_with_category.element_class' object has no attribute 'coefficients'

Here is my code for context:

R.<y1, y2> = PowerSeriesRing(GF(3), default_prec = 5)
I = R.ideal(y1^3, y2^3)
S = R.quotient_ring(I)
#defining the group action
g(y1) = y1 + 1
h(y2) = y2 - y1^2 - y1

#defining the basis
b1(y1,y2)= y1
b2(y1,y2)= y1^2
b3(y1,y2)= y1*y2
b4(y1,y2)= y2
b5(y1,y2)= y2^2
b6(y1,y2)= y1^2*y2
b7(y1,y2)= y1*y2^2
b8(y1,y2)= y1^2*y2^2

Secondly, how can I more concisely run the iteration itself? Here is how I implemented an iterated group action on a basis element. I list only the $b_4$ example for readability, the others are the same but with $b_i$

g1b4(y1, y2) = b4(g(y1), h(y2)).expand()
g2b4(y1, y2) = g1b4(g(y1), h(y2)).expand()
g3b4(y1, y2) = g2b4(g(y1), h(y2)).expand()
g4b4(y1, y2) = g3b4(g(y1), h(y2)).expand()
g5b4(y1, y2) = g4b4(g(y1), h(y2)).expand()
g6b4(y1, y2) = g5b4(g(y1), h(y2)).expand()
g7b4(y1, y2) = g6b4(g(y1), h(y2)).expand()
g8b4(y1, y2) = g7b4(g(y1), h(y2)).expand()
g9b4(y1, y2) = g8b4(g(y1), h(y2)).expand()
print(S(g1b4))
print(S(g2b4))
print(S(g3b4))
print(S(g4b4))
print(S(g5b4))
print(S(g6b4))
print(S(g7b4))
print(S(g8b4))
print(S(g9b4))

Edit: I also realized that for $b_3$, the output of iteration has $y_1^3$ in it, even though we are considering its image in the quotient ring. How could this be happening?

edit retag close merge delete

Sort by » oldest newest most voted

When you write b1(y1,y2)= y1 this defines b1 as a symbolic function, not a polynomial. Note the difference

sage:     b1(y1,y2)= y1
sage: type(b1)
<class 'sage.symbolic.expression.Expression'>
sage: R.<y1,y2> = PolynomialRing(GF(3))
sage: b1 = y1
sage: type(b1)
<class 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'>

Because these are different they behave differently.

In the following snippet, I show how to compute the matrix of g, that is [g(1), g(y1), g(y1^2), ...]

R.<y1, y2> = PolynomialRing(GF(3))   # NOTE: don't use series but polynomials
I = R.ideal(y1^3, y2^3)
S = R.quotient_ring(I)

# NOTE: use Python functions
# group action
def transform(poly):
return S(poly.lift().subs(y1=y1 + 1, y2=y2 - y1^2 - y1))

# defining the basis together with an inverse map
B = list(map(S, [1, y1, y1^2, y1*y2, y2, y2^2, y1^2*y2, y1*y2^2, y1^2*y2^2]))
indices = {monom: i for i, monom in enumerate(B)}

mat = []
for poly in B:
v =  * len(B)
image = transform(poly).lift()
for c, m in zip(image.coefficients(), image.monomials()):
v[indices[m]] = c
mat.append(v)
mat = matrix(mat).transpose()
print(mat)
more

If I understand correctly, your code outputs one matrix: (g(e)) for each e in E, that is: (g(1), g(y1), g(y1^2), ...., g(y1^2y2^2)). However, I would like a matrix recursively applying the group action ((e, g(e), ..., g^8(e)) for each e in E, giving 9 matrices. How can one encode the recursive use of the group action?

1

You are right. To turn it into an answer to your question, you just need to change the lines building the matrix. You can design a simple loop for making the list mat = [poly, transform(poly), transform(transform(poly)), ...].

Just in case this is helpful for anyone else, here is the functional code answering my original question:

R.<y1, y2> = PolynomialRing(GF(3))
I = R.ideal(y1^3, y2^3)
S = R.quotient_ring(I)

# group action
def transform(poly):
return S(poly.lift().subs(y1=y1 + 1, y2=y2 - y1^2 - y1))

#iterating the group action
def right_iterate(n, g, poly):
gg = poly
for k in range(n):
gg = g(gg)
return gg

#defining the basis
E = list(map(S, [1, y1, y1^2, y1*y2, y2, y2^2, y1^2*y2, y1*y2^2, y1^2*y2^2]))
indices = {monom: i for i, monom in enumerate(E)}

for poly in E:
mat = []
for i in range(9):
v = *len(E)
image = right_iterate(i,transform,poly).lift()
for c, m in zip(image.coefficients(), image.monomials()):
v[indices[m]] = c
mat.append(v)
mat = matrix(mat).transpose()
print("__")
print(poly)
print(mat.echelon_form().row_space())
more