# References: # [DELS] M. de Boeck, A. Evseev, S. Lyle, and L. Speyer, On bases of some simple modules of symmetric groups and Hecke algebras, preprint. # [HM] J. Hu and A. Mathas, Seminormal forms and cyclotomic quiver Hecke algebras of type A, Math. Ann. 364 (2016), 1189-1254. # # The code below has been used with Version 4.7.9 of GAP. # The most useful function for the "end-user" is probably the function Gram at the end of the file, which computes the Gram matrix of a Specht module of a level 1 cyclotomic KLR algebra of # type A_{e-1}^{(1)}. The input and output of this function are explained in comments before the function, and an example of its use is given at the end of the file. # # The code below uses results from [HM]. It computes Gram matrices for cyclotomic KLR algebras of level 1 only, # though there are no conceptual obstacles to doing the same for an arbitrary level. # Let $O= \C[t]_{(t-\xi)}$, where $\C$ is the field of complex numbers and $\xi$ is a primitive $e$th root of unity in $\C$. # Then $(O,t)$ is an e-idempotent subring of $\C(t)$, in the sense of [HM, Definition 4.1]. The paper [HM] constructs a lift of the cyclotomic KLR algebra $R^{\Lambda_0}_{n,\C}$ to # $O$ and considers the scalar extension $A$ of this lift to $\C(t)$. This scalar extension has a seminormal basis $\{\psi_{ST}\}$. # For each partition $\lambda$ of $n$, we have a lift of the Specht module $S^\lambda$ for $R^{\Lamdba_0}_{n,\C}$ to $O$, which then yields an $A$-module by scalar extension. # Denote by $\{ f_T | T\in \Std(\lambda)\}$ the `seminormal' $\C(t)$-basis of this $A$-module, which is derived from the above basis $\{\psi_{ST}\}$ of $A$. # Then the Gram matrix of the relevant form with respect to $\{ f_T\}$ is diagonal, and its entries are known, see [HM, (5.1) and Corollary 5.2]. # Also, the transition matrix from the basis $\{ v^T \}$ (as in the notation of [DELS, Section 2]) to $\{ f_T\}$ is determined by the formulas in [HM], # see in particular Lemma 5.1 in op. cit. Using these results, the program computes the Gram matrix with respect to the basis $\{ v^T | T\in \Std(\lambda)\}$, first, over $\O$, and then, by # substituting $t:=\xi$, over $\Q$ (or, equivalently, over $\Z$). # All elements of $\C(t)$ computed by the program, in fact, belong to $\Q(t)$. # Setting up the indeterminate t and hence the ring $\Q(t)$ of rational functions. ($\Q$ is $\mathbb Q$.) t:=Indeterminate(Integers,1); SetName(t,"t"); AreEqual:=function(S,T) local j; for j in [1..Size(S)] do if not T[j]=S[j] then return false; fi; od; if not Size(S)=Size(T) then return false; fi; return true; end; # If stdr is a list of the format returned by StTableauxRexes, then this function returns the number of T in that list. postab:=function(T,stdr) local j; for j in [1..Size(stdr)] do if AreEqual(T,stdr[j][2]) then return j; fi; od; return fail; end; #returns a list standard y-tableaux, where y is a partition. StTableaux:=function(y) local rec_list, i, res, x, t, n; n:=Sum(y); if n=0 then return [ [] ]; fi; res:=[]; for i in [1..Size(y)] do if i = Size(y) or y[i]>y[i+1] then x:=ShallowCopy(y); x[i]:=x[i]-1; if x[i] = 0 then Remove(x,i); fi; rec_list:=StTableaux(x); for t in rec_list do if Size(x)=Size(y) then Add(t[i], n); else Add(t, [n]); fi; Add(res, t); od; fi; od; return res; end; # returns [a,b] where a is the row number and b is the column number of r in the tableau T pos:=function(T,r) local j,a,b; for j in [1..Size(T)] do b:=Position(T[j], r); if not b=fail then a:=j; break; fi; #r0 and c0 are the row and column numbers of the box r in s od; return [a,b]; end; # Returns s list of quadruples [i,t,r,j] where # a) t runs through all standard y-tableaux # b) i is the number of t in the given list # c) r is the largest element of {1,...,n} such that the tableau ts_r is standard and dominates t # d) j is the number of ts_r in our list. (We always have j1 do if r=0 then for k in [0..n-1] do q:=q+t^k; od; else for k in [1..-n] do q:=q-t^(-k); od; fi; return q; end; # returns the value \beta_r(S) for a standard tableau S in terms of the indeterminate t. Here e is the quantum characteristic. #See [HM, Equation (5.4)]. beta:=function(e,S,r,t) local res0,res1, c0,c1, r0, r1,j,tmp; tmp:=pos(S,r); r0:=tmp[1]; c0:=tmp[2]; tmp:=pos(S,r+1); r1:=tmp[1]; c1:=tmp[2]; if r0 = r1 or c0=c1 then return 0*t^0; fi; #s(r,r+1) is not standard in this case if r0not term[2]=zero); end; # returns a list with Size(stdr) items. The i-th entry of the list is an object of type (LCf) representing v^{T_i}. vasf:=function(e,stdr,t) local ret,i,reti,j,r,term, new,k; ret:=List([1..Size(stdr)], j->[] ); for i in [1..Size(stdr)] do if stdr[i][3]=0 then ret[i]:=[ [ i, 1*t^0 ] ]; # here i=1 else r:=stdr[i][3]; j:=stdr[i][4]; for term in ret[j] do new:=StructuralCopy(psi(e,stdr,term[1],r,t)); for k in [1..Size(new)] do new[k][2]:=term[2]*new[k][2]; od; Append(ret[i], new); ret[i]:=collect(ret[i],0*t^0); od; fi; od; return ret; end; # For an object lc of type (LCf) or (LCv) representing an element u of the Specht module, returns an object representing g*u. # Here g is an element of $\Z(t)$, i.e. a rational function in t over the integers. multiply:=function(g,lc) local ret,i; ret:=StructuralCopy(lc); for i in [1..Size(ret)] do ret[i][2]:=g*ret[i][2]; od; return ret; end; # returns a list with Size(stdr) items. The i-th entry of the list is an object of type (LCv) representing f_{T_i}. Here vf=vasf(e,stdr,t). [We are just inverting a unitriangular matrix here.] fasv:=function(e,stdr,vf,t) local ret,i,reti,j,r,term, new,k, b, found; ret:=List([1..Size(stdr)], j->[] ); for i in [1..Size(stdr)] do reti:=[]; for term in vf[i] do if term[1]=i then Add(reti, term); # we assuming that term[2]=1*t^0 here: this will be the case when vf is the output of vasf. else j:=term[1]; new:=StructuralCopy(ret[j]); for k in [1..Size(new)] do new[k][2]:=-term[2]*new[k][2]; od; Append(reti, new); fi; od; ret[i]:=collect(reti,0*t^0); #for term in reti do # found:=false; # for b in [1..Size(ret[i])] do if ret[i][b][1]=term[1] then ret[i][b][2]:=ret[i][b][2]+term[2]; found:=true; break; fi; od; # if not found then Add(ret[i],term); fi; #od; od; return ret; end; # Given an object lcf of type (LCf), returns an object of type (LCv) representing the same element of the relevant Specht module. Here fv is the output of fasv(e,stdr,t). # The same function works in the reverse direction (i.e. translates (LCv) into (LCf)) if fv in the input is replaced by vf=vasf(e,stdr,i). lcf_to_lcv:=function(e,stdr,fv, lcf,t) local term,ret; ret:=[]; for term in lcf do Append(ret, multiply(term[2], fv[term[1]])); od; return collect(ret,0*t^0); end; # returns an object of type (LCv) representing $v^{T_i}\psi_r$. #Here vf and fv are the outputs of vasf and fasv respectively. vpsiasv:=function(e,stdr,vf,fv,i,r,t) local asf,ret,term; asf:=[]; for term in vf[i] do Append(asf, multiply(term[2],psi(e,stdr,term[1],r,t))); od; asf:=collect(asf, 0*t^0); # asf is an object of type (LCf) representing $v^{T_i}\psi_r$. return lcf_to_lcv(e,stdr,fv,asf,t); end; # returns an object of type (LCv) representing $v^{T_i}y_r$. Here vf and fv are the outputs of vasf and fasv respectively. vYasv:=function(e,stdr,vf,fv,i,r,t) local asf,ret, term; asf:=[]; for term in vf[i] do Append(asf, multiply(term[2],Y(e,stdr,term[1],r,t))); od; asf:=collect(asf, 0*t^0); # asf is an object of type (LCf) representing $v^{T_i}y_r$. return lcf_to_lcv(e,stdr,fv,asf,t); end; # For an object lcv of type (LCv), returns an object of type lcv representing the product lcv*\psi_r multbypsi:=function(e,stdr,vf,fv,lcv,r,t) local ret, term; ret:=[]; for term in lcv do Append(ret, multiply(term[2], vpsiasv(e,stdr,vf,fv,term[1], r,t))); od; return collect(ret, 0*t^0); end; # For an object lcv of type (LCv), returns an object of type lcv representing the product lcv*y_r multbyY:=function(e,stdr,vf,fv,lcv,r,t) local ret, term; ret:=[]; for term in lcv do Append(ret, multiply(term[2], vYasv(e,stdr,vf,fv,term[1], r,t))); od; return collect(ret, 0*t^0); end; # returns the size of the tableau t. sizetab:=function(t) local i; return(Sum([1..Length(t)],i->Length(t[i]))); end; # returns $\gamma_{t^{\lambda}}\in \Z[t,t^{-1}]$, given by Hu--Mathas, Equation (5.1). gatla:=function(e,la,t) local k,l,ret; ret:=1; for k in [1..Size(la)] do for l in [1..QuoInt(la[k],e)] do ret:=ret*qint(e*l,t); od; od; return ret; end; # returns the list whose i-th entry is $\gamma_{T_i}$ as defined by [HM, Corollary 5.2], where $T_1,T_2,...$ is the list of standard lambda-tableaux given by stdr. gamma:=function(e,la,stdr,t) local ret, i,gt; ret:=[]; for i in [1..Size(stdr)] do if i=1 then gt:=gatla(e,la,t); else gt:=beta(e,stdr[i][2],stdr[i][3],t)*ret[stdr[i][4]]/beta(e,stdr[stdr[i][4]][2],stdr[i][3],t); fi; Add(ret,gt); od; return ret; end; # returns the e-residue sequence of the tableau T of size n ResidueSeq:=function(e,T) local k,l,i,ret; ret:=[]; for k in [1..Size(T)] do for l in [1..Size(T[k])] do ret[T[k][l]]:=(l-k) mod e; od; od; return ret; end; # Returns the pair [Tab, G] where Tab is the list of numbers of lambda-tableaux T such that the residue of T is bi, and # G is the Gram matrix $(v^{T_i}, v^{T_j})$ where i,j run through Tab. # Here (f^{T_i}, f^{T_j})=\delta_{i,j} \gamma_{T_i}$: see proof of Lemma 5.9 in Hu-Mathas. GramSubmatrix:=function(e,la,stdr,vf,fv,ga,bi,t) local lst, k,l, G, a,b; lst:=Filtered([1..Size(stdr)], k->ResidueSeq(e,stdr[k][2])=bi); G:=List([1..Size(lst)], k-> List([1..Size(lst)],l->0*t^0) ); for k in [1..Size(lst)] do for l in [k..Size(lst)] do for a in vf[lst[k]] do for b in vf[lst[l]] do if b[1]=a[1] then G[k][l]:=G[k][l]+ga[a[1]]*a[2]*b[2]; break; fi; od; od; if not k=l then G[l][k]:=G[k][l]; fi; od; od; #Print(G); return [lst,G]; end; #The function Gram takes as input an integer $e\ge 2$, a partition la and an e-residue sequence bi of length equal to the size of la. # The output is a list G=[G[1], G[2]], where # 1) G[1] is the list of standard la-tableaux with residue sequence bi (in lexicographic order). Denote these tableaux T_1,...,T_m in the order listed. # 2) G[2] is an integer-valued matrix such that the (i,j)-entry of G[2] is the inner product # of two elements of the universal row Specht module over \Z corresponding to la. # # Here, the notation is as in [DELS, Section 2]. In particular v^T denotes a basis element corresponding to the standard tableau T (in the Specht module), and # v^T depends on the choice of a reduced expression for T. The program chooses a particular reduced expression. Gram:=function(e,la,bi) local stdr,vf,fv,ga,t,GS,tab,N,G,k,l; t:=Indeterminate(Integers,1); stdr:=StTableauxRexes(la); vf:=vasf(e,stdr,t); fv:=fasv(e,stdr,vf,t); ga:=gamma(e,la,stdr,t); GS:=GramSubmatrix(e,la,stdr,vf,fv,ga,bi,t); tab:=List(GS[1], k->stdr[k][2]); N:=Size(tab); G:=List([1..N], k-> List([1..N],l->0*E(e)) ); for k in [1..N] do for l in [1..N] do G[k][l]:=Value(GS[2][k][l], E(e)); od; od; return [tab, G]; end; #Example of use of Gram (this example corresponds to [DELS, Example 6.2]): # # #GAP, Version 4.7.9 of 29-Nov-2015 (free software, GPL) #│ GAP │ http://www.gap-system.org #└───────┘ Architecture: x86_64-apple-darwin15.0.0-gcc-default64 # Libs used: gmp, readline # Loading the library and packages ... # Components: trans 1.0, prim 2.1, small* 1.0, id* 1.0 # Packages: AClib 1.2, Alnuth 3.0.0, AtlasRep 1.5.0, AutPGrp 1.6, Browse 1.8.6, Carat 2.1.4, CRISP 1.3.9, Cryst 4.1.12, CrystCat 1.1.6, CTblLib 1.2.2, FactInt 1.5.3, FGA 1.3.0, GAPDoc 1.5.1, IO 4.4.4, # IRREDSOL 1.2.4, LAGUNA 3.7.0, Polenta 1.3.2, Polycyclic 2.11, RadiRoot 2.7, ResClasses 3.4.0, Sophus 1.23, SpinSym 1.5, TomLib 1.2.5 # Try '?help' for help. See also '?copyright' and '?authors' # gap> Read("Gram2016.g"); # gap> la:=[4,3,1];; bi:=[0,1,2,2,0,1,0,1];; # gap> G:=Gram(3,la,bi);; # gap> G[1]; # [ [ [ 1, 2, 3, 7 ], [ 4, 5, 6 ], [ 8 ] ], [ [ 1, 2, 4, 7 ], [ 3, 5, 6 ], [ 8 ] ], [ [ 1, 2, 3, 5 ], [ 4, 7, 8 ], [ 6 ] ], [ [ 1, 2, 4, 5 ], [ 3, 7, 8 ], [ 6 ] ], # [ [ 1, 2, 3, 7 ], [ 4, 5, 8 ], [ 6 ] ], [ [ 1, 2, 4, 7 ], [ 3, 5, 8 ], [ 6 ] ] ] # gap> Display(G[2]); # [ [ 0, 0, 0, 0, 0, 1 ], # [ 0, 0, 0, 0, 1, 0 ], # [ 0, 0, 0, 0, 0, 1 ], # [ 0, 0, 0, 0, 1, 0 ], # [ 0, 1, 0, 1, 0, 0 ], # [ 1, 0, 1, 0, 0, 0 ] ] # gap>