6. Invariants of paths
We saw in section 4 how to compute the Thrall coefficients, and in section 5 how to compute higher Lie idempotents.
[1]:
s=SymmetricFunctions(QQ).schur()
def thrall_coefficient(la,mu):
return s.gessel_reutenauer(la).coefficient(mu)
def higher_lie_idempotent(la):
return DescentAlgebra(QQ, la.size()).I().idempotent(la).to_symmetric_group_algebra()
The function \(\texttt{invariant_multiplicity}\) computes, for a given \(d\) and \(\lambda \vdash \ell d\), the dimension of the space of invariants inside \(W_\lambda(\mathbb{C}^d)\). This is just the Thrall coefficient \(a^{\lambda}_{(\ell^d)}\).
[2]:
def invariant_multiplicity(la,d):
k=sum(la)
if k%d!=0:
return False
else:
l=k//d
invPartition=Partition([l for _ in range(d)])
return thrall_coefficient(la,invPartition)
The function \(\texttt{invariant_graded_parts}\) prints the dimensions of the components \(U_{\lambda}(\mathbb{C}^d)\) of the invariant ring \(\mathcal{I}_{\leq m}(\mathbb{C}^d)\). Here \(\lambda\) runs over all parititions with \(\lambda_1 \leq m\) and \(|\lambda| \leq \texttt{max_degree}\).
[3]:
def invariant_graded_parts(d,max_degree=9,m=False):
l=1
while l*d<=max_degree:
print("==============")
if order:
partitions=Partitions(l*d,max_part=m)
else:
partitions=Partitions(l*d)
for la in partitions:
mult=invariant_multiplicity(la,d)
if mult>0:
print(str(la)+": "+str(mult))
l+=1
The ring \(\mathcal{I}_{\leq 2}(\mathbb{C}^3)\), see Proposition 6.5:
[4]:
invariant_graded_parts(3,m=2)
==============
[2, 1]: 1
==============
[2, 2, 1, 1]: 1
==============
[2, 2, 2, 1, 1, 1]: 1
The ring \(\mathcal{I}_{\leq 3}(\mathbb{C}^2)\), see Proposition 6.6:
[5]:
invariant_graded_parts(2,m=3)
==============
[2]: 1
==============
[3, 1]: 1
[2, 2]: 1
==============
[3, 2, 1]: 1
[2, 2, 2]: 1
==============
[3, 3, 1, 1]: 1
[3, 2, 2, 1]: 1
[2, 2, 2, 2]: 1
A basis for the space of invariants
We need two auxiliary functions:
\(\texttt{isotypic_basis}\) computes a basis of the isotypic component \(\mathbb{S}^{\lambda}(\mathbb{C}^d)^{\oplus {m_{\lambda}}} \subset (\mathbb{C}^d)^{\otimes k}\) in the Schur-Weyl decomposition.
[6]:
#la is a partition of size k
#The output is a list of elements of SchurTensorModule(QQ, d, k)
from sage.combinat.symmetric_group_algebra import e_hat
def isotypic_basis(la,d):
b=[]
k=la.size()
A=SymmetricGroupAlgebra(QQ,k)
symmetrizer=A.central_orthogonal_idempotent(la)
T=SchurTensorModule(QQ, d, k)
B=T.basis()
SST=SemistandardTableaux(la,max_entry=d)
ST=StandardTableaux(la)
est=e_hat(list(ST)[-1])
for st in ST:
p = Permutation(flatten(st))
E=A(p.inverse())*est
for sst in SST:
b.append(B[tuple(flatten(sst))]*E)
return b
\(\texttt{module_projection}\) projects a submodule of \((\mathbb{C}^d)^{\otimes k}\) along an idempotent:
[7]:
# b is a basis of the submodule
# E is the idempotent
# Optional: dim_bound specifies an upper bound on the dimension of the projection. This will speed up the computation.
def module_projection(d,k,b,E,dim_bound=oo):
if dim_bound==0:
return False
W=False
for v in b:
vE=v*(E.antipode())
if vE!=0:
V=span([vector(vE.dense_coefficient_list())])
if not W:
W=V
else:
W+=V
if W.dimension()==dim_bound:
break
L=list(IntegerVectors(k=k,min_part=1,max_part=d))
L.sort()
T=FreeModule(QQ,L)
B=list(T.basis())
return [sum([v[i]*B[i] for i in range(d^k)]) for v in W.basis()]
The function \(\texttt{path_invariants}\) computes for each partition \(\lambda\) of \(d\ell\) the space of invariants in \(W_{\lambda}(\mathbb{C}^d)\).
[8]:
#The optional argument m restricts to partitions whose entries are at most m.
#Output: a dict, listing for each partition $\lambda$ of $dl$ the space of invariants in $W_{\lambda}(\CC^d)$
def path_invariants(d,l,m=False):
D=dict()
k=d*l
invPartition=Partition([l for _ in range(d)])
b=isotypic_basis(invPartition,d)
for la in Partitions(k):
if m and la[0] > m:
continue
invMult=s.gessel_reutenauer(la).coefficient(invPartition)
if invMult==0:
continue
E=higher_lie_idempotent(la)
D[la]=module_projection(d,k,b,E,dim_bound=invMult)
return D
Here are the invariants from Example 6.7:
[9]:
path_invariants(2,2)
[9]:
{[3, 1]: [B[[1, 1, 2, 2]] - 1/2*B[[1, 2, 1, 2]] - 1/2*B[[1, 2, 2, 1]] - 1/2*B[[2, 1, 1, 2]] - 1/2*B[[2, 1, 2, 1]] + B[[2, 2, 1, 1]]],
[2, 2]: [B[[1, 1, 2, 2]] - B[[1, 2, 2, 1]] - B[[2, 1, 1, 2]] + B[[2, 2, 1, 1]]]}