# 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 = [0] * 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?

( 2021-04-24 23:30:29 +0100 )edit
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)), ...].

( 2021-04-25 08:44:37 +0100 )edit

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 = [0]*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