| > | restart: with(linalg): with(group): |
Warning, the protected names norm and trace have been redefined and unprotected
See p. 42-43 in "Linear Representations of Finite Groups" by J.P. Serre, and p. 170, 179-180, in "Representations and Characters of Groups (first edition)" by James and Liebeck.
| > | x:=[[1,2],[3,4]]: y:=[[1,3],[2,4]]: z:=[[1,4],[2,3]]: |
| > |
Representatives of the five conjugacy classes in S_4
| > | a:=[[1,2]]: b:=[[1,2],[3,4]]: c:=[[1,2,3]]: d:=[[1,2,3,4]]: e:=[]: |
| > | S4:=permgroup(4, {a,b,c,d,e}): |
| > | elements(S4); |
| > | grouporder(S4); |
| > |
Let's make some procedures to multiply two or three permutations together using the right to left convention that is standard
| > | # mulperms(b,x); # this multiplication is left to right!!!!!! |
| > | mulp2:=proc(perm1,perm2) description "Multiply 2 permutations from right to left (which is conventional) instead of left to right (as mulperms does)."; # Takes a list of permuations and reverses their order before feeding it to mulperms."; # mulperms(seq(args[nargs-i],i=0..(nargs-1))); # argh! mulperms only takes two inputs!!!! mulperms(perm2,perm1); end proc: |
| > | reverselist:=proc() #mulperms(seq(args[nargs-i],i=0..(nargs-1))); seq(args[nargs-i],i=0..(nargs-1)); end proc: |
| > | reverselist(b,c,d); |
| > | mymulp:=proc() description "multiply any number of permutations from right to left"; local accumulated,m; accumulated := mulp2(args[1],args[2]); for m from 3 to nargs do accumulated := mulp2(accumulated,args[m]); end do; accumulated; end proc: |
| > | mymulp(b,c); |
| > | mymulp(b,c,d); |
| > | mymulp(b,x,invperm(b)); |
| > | mulp2(b,mulp2(c,d)); |
| > | #print(mulp2); |
| > | mulp2(b,c); # this is right to left multiplication, which agrees with Serre and convention |
| > | mulp2(b,mulp2(x,invperm(b))); |
| > | mulp3:=proc() description "Multiply 3 permutations together from right to left."; mulp2(args[1],mulp2(args[2],args[3])); end proc: |
Let's make some coset procedures:
| > | lcoset:=proc(g,subgp) local Lsubgp; # list subgp elts Lsubgp:=[op(elements(subgp))]; {seq(mulp2(g,Lsubgp[i]),i=1..nops(Lsubgp))}; end proc: |
| > |
| > | lcosets:=proc(gp,subgp) local Lgp; Lgp:=[op(elements(gp))]: {seq(lcoset(Lgp[i],subgp), i=1..nops(Lgp))}; end proc: |
| > | #lcosets(A4,K); |
| > | rcoset:=proc(subgp,g) local Lsubgp; Lsubgp:=[op(elements(subgp))]; {seq(mulp2(Lsubgp[i],g),i=1..nops(Lsubgp))}; end proc: |
| > | #rcoset(K,[[1,2],[3,4]]); |
| > | rcosets:=proc(subgp,gp) local Lgp; Lgp:=[op(elements(gp))]: {seq(rcoset(subgp,Lgp[i]), i=1..nops(Lgp))}; end proc: |
| > | #rcosets(K,A4); |
Let's get some conjugacy classes:
| > | conj1by2:=proc(elt1,elt2) description "Computes (elt2)(elt1)(elt2)^(-1)"; mulp3(elt2,elt1,invperm(elt2)); end proc: |
| > | conj1by2(x,b); |
| > | #centralizer:=proc(elt,gp) local Lgp: #Lgp:=[op(elements(gp))]: #{[]} union {seq(conj1by2(elt,Lgp[i]),i=1..nops(Lgp))}; #end proc: |
| > | conjugacyclass:=proc(elt,gp) local Lgp: Lgp:=[op(elements(gp))]: {seq(conj1by2(elt,Lgp[i]),i=1..nops(Lgp))}; end proc: |
| > | conjugacyclass([],S4); |
| > | conjugacyclass(x,S4); |
| > |
| > | conjugacyclass(b,S4); |
| > |
| > | conjugacyclass(mulp2(b,b),S4); |
| > |
| > | conjugacyclasses:=proc(gp) local Lgp; Lgp:=[op(elements(gp))]: {seq(conjugacyclass(Lgp[i],gp),i=1..nops(Lgp))}; end proc: |
| > | conjugacyclasses(S4); |
| > | `&*`:=(PERM1,PERM2)->mulp2(PERM1,PERM2): |
| > | `&-`:=(PERM1,PERM2)->mulp2(PERM1,invperm(PERM2)): |
| > | a &* b; |
| > | a &- b; |
| > | A4:=permgroup(4, {c,x,y,z} ): |
| > | elements(A4); |
| > | ListGroup:=proc(gp) description "Make a veritable list of group elements."; [op(elements(gp))]; end proc: |
| > | ListGroup(A4); |
| > | nops(elements(A4)); #grouporder(A4); |
| > | isabelian(A4); |
S_4 is the semidirect product of L and the normal subgroup H
| > | H:=permgroup(4,{x,y,z}): |
| > | elements(H); |
| > | grouporder(H); |
| > | isnormal(S4,H); |
| > | lcoset([[1,2],[3,4]], H); |
| > | rcoset(H, [[1,2],[3,4]]); |
| > | L:=permgroup(4,{a,c}): |
| > | elements(L); |
| > | grouporder(L); |
| > | isnormal(S4,L); |
| > | lcoset([[1,2]], L); |
| > | lcosets(L,S4); |
| > | rcosets(L,S4); |
| > |
| > | inter(H,L); # computes the intersection of H and K |
| > |
| > | b &* x; |
| > | b &* x &- y; |
| > | mulp3(b,x,invperm(y)); |
| > |
| > |
| > |
Let's list off the conjugacy classes of each of the conjugacy class representatives of S4. Note: we name the conjugacy classes by the letter corresponding to their generator and their size (because "D" is a protected variable). Also, we convert them from sets to lists so that the elements remain in a fixed order.
| > | A6:=[op(conjugacyclass(a,S4))]; nops(A6); |
| > | B3:=[op(conjugacyclass(b,S4))]; nops(B3); |
| > | C8:=[op(conjugacyclass(c,S4))]; nops(C8); |
| > | D6:=[op(conjugacyclass(d,S4))]; nops(D6); |
| > | E1:=[op(conjugacyclass(e,S4))]; nops(E1); |
| > |
Let us define a procedure for defining characters for S_4 according to the naming conventions in "Chern approximations for generalised group cohomology" by Neil Strickland on page 21
| > | definecharacter:=proc(val0, val1, val2, val3, val4, val5) description "val0 is the name of the character, and val1 through val5 are the values that this character takes on e,a,b,c,d (respectively) and extends this to conjugacy classes."; local i; `val0`([]):=val1: for i from 1 to nops(A6) do `val0`(A6[i]):=val2 od: for i from 1 to nops(B3) do `val0`(B3[i]):=val3 od: for i from 1 to nops(C8) do `val0`(C8[i]):=val4 od: for i from 1 to nops(D6) do `val0`(D6[i]):=val5 od: return: end proc: |
Define ONE, the trivial character of degree n_1=1.
| > | definecharacter(ONE,1,1,1,1,1); |
| > | ONE([]); ONE([[1,2]]); ONE([[1,2],[3,4]]); ONE([[1,2,3]]); ONE([[1,2,3,4]]); |
| > |
Define epsilon, a character of degree n_2 = 1.
| > | definecharacter(epsilon,1,-1,1,1,-1); |
| > | epsilon([]); epsilon([[1,2]]); epsilon([[1,2],[3,4]]); epsilon([[1,2,3]]); epsilon([[1,2,3,4]]); |
Define sigma, a character of degree n_3 = 2.
| > | definecharacter(sigma,2,0,2,-1,0); |
| > | sigma([]); sigma([[1,2]]); sigma([[1,2],[3,4]]); sigma([[1,2,3]]); sigma([[1,2,3,4]]); |
Define rho, a character of degree n_4 = 3.
| > | definecharacter(rho,3,1,-1,0,-1); |
| > | rho(e); rho(a); rho(b); rho(c); rho(d); |
Define alpha = epsilon * rho, a character of degree n_5 = 3.
| > | definecharacter(alpha,3,-1,-1,0,1); |
| > | alpha(e); alpha(a); alpha(b); alpha(c); alpha(d); |
| > | epsilon(e)*rho(e); epsilon(a)*rho(a); epsilon(b)*rho(b); epsilon(c)*rho(c); epsilon(d)*rho(d); |
| > |
Let's verify the relations among the characters in R(S_4).
| > | CCR:=[e,a,b,c,d]: # a list of conjugacy class representatives |
| > | for i from 1 to nops(CCR) do lprint(epsilon(CCR[i])*epsilon(CCR[i]), ONE(CCR[i])) od; # on each line, print the value of epsilon^2 and ONE on a conjugacy class representative # if the values on each line agree, then the characters are the same |
1, 1
1, 1
1, 1
1, 1
1, 1
| > | for i from 1 to nops(CCR) do lprint(epsilon(CCR[i])*sigma(CCR[i]), sigma(CCR[i])) od; |
2, 2
0, 0
2, 2
-1, -1
0, 0
| > | for i from 1 to nops(CCR) do lprint(sigma(CCR[i])^2, ONE(CCR[i]) + epsilon(CCR[i]) + sigma(CCR[i])) od; |
4, 4
0, 0
4, 4
1, 1
0, 0
| > | for i from 1 to nops(CCR) do lprint(sigma(CCR[i])*rho(CCR[i]), rho(CCR[i]) + alpha(CCR[i])) od; |
6, 6
0, 0
-2, -2
0, 0
0, 0
| > | for i from 1 to nops(CCR) do lprint(rho(CCR[i])^2, ONE(CCR[i]) + sigma(CCR[i]) + rho(CCR[i]) + alpha(CCR[i]) ) od; |
9, 9
1, 1
1, 1
0, 0
1, 1
It is much easier to define and work with Adams operations on the character ring rather than the representation ring. Lemma 3.61 on p. 69 of Adams "Lectures on Lie Groups" and p.7 of Strickland's "Chern approximations..." paper contain a very useful formula that tells that the value of the character chi associated to the representation psi^k (V) on an element g in the group is the value of the character chi associated to V on the element g^k. That is, chi_{psi^k(V)} (g) = chi_V (g^k). In terms of our notation (using the same name for both a representation and its character), we might rephrase this as psi^k(sigma)(g) = sigma (g^k) where sigma = V is the representation.
| > | evalchar:=proc(character,conjclassrep) local i; seq(`character`(conjclassrep[i]),i=1..nops(conjclassrep)); end proc: |
Let's make the Adams operation psi^2 that takes a character to a character.
| > | psi2:=proc(character,conjclassrep) local i; seq(`character`(mulp2(conjclassrep[i],conjclassrep[i])),i=1..nops(conjclassrep)); end proc: |
psi^2(ONE) = ONE
| > | psi2(ONE,[e,a,b,c,d]); |
psi^2(epsilon) = ONE
| > | psi2(epsilon,[e,a,b,c,d]); |
psi^2(sigma) = ONE - epsilon + sigma
| > | psi2(sigma,[e,a,b,c,d]); |
| > | evalchar(ONE-epsilon+sigma,[e,a,b,c,d]); |
psi^2(rho) = ONE + sigma + rho - alpha
| > | psi2(rho,[e,a,b,c,d]); |
| > | evalchar(ONE + sigma + rho - epsilon*rho,[e,a,b,c,d]); # I'm baffled as to why epsilon*rho works here! |
| > | evalchar(ONE + sigma + rho - alpha, [e,a,b,c,d]); |
psi^2(epsilon * rho) = psi^2(alpha) = ONE + sigma + rho - alpha
| > | psi2(alpha,[e,a,b,c,d]); |
| > | # see previous calculation |
| > | psi2(epsilon*rho,[e,a,b,c,d]); |
Let's make the Adams operation psi^3 that takes a character to a character.
| > | psi3:=proc(character,conjclassrep) local i; seq(`character`(mulp3(conjclassrep[i],conjclassrep[i],conjclassrep[i])),i=1..nops(conjclassrep)); end proc: |
psi^3(ONE) = ONE
| > | psi3(ONE,[e,a,b,c,d]); |
psi^3(epsilon) = epsilon
| > | psi3(epsilon,[e,a,b,c,d]); |
| > | evalchar(epsilon,[e,a,b,c,d]); |
psi^3(sigma) = ONE + epsilon
| > | psi3(sigma,[e,a,b,c,d]); |
| > | evalchar(ONE + epsilon,[e,a,b,c,d]); |
psi^3(rho) = ONE + epsilon - sigma + rho
| > | psi3(rho,[e,a,b,c,d]); |
| > | evalchar(ONE + epsilon - sigma + rho,[e,a,b,c,d]); |
psi^3(epsilon * rho) = psi^3(alpha) = ONE + epsilon - sigma + rho
| > | psi3(alpha,[e,a,b,c,d]); |
| > | # see previous calculation |
| > | psi3(epsilon*rho,[e,a,b,c,d]); |
Let's make the Adams operation psi^4 that takes a character to a character.
| > | psi4:=proc(character,conjclassrep) local i; seq(`character`( conjclassrep[i] &* conjclassrep[i] &* conjclassrep[i] &* conjclassrep[i]),i=1..nops(conjclassrep)); end proc: |
psi^4(ONE) = ONE
| > | psi4(ONE,[e,a,b,c,d]); |
psi^4(epsilon) = epsilon
| > | psi4(epsilon,[e,a,b,c,d]); |
| > |
psi^4(sigma) = ONE - epsilon + sigma
| > | psi4(sigma,[e,a,b,c,d]); |
| > | evalchar(ONE - epsilon + sigma,[e,a,b,c,d]); |
psi^4(rho) = 2*ONE - epsilon + sigma
| > | psi4(rho,[e,a,b,c,d]); |
| > | CharacterTable:=matrix([[1,1,2,3,3],[1,-1,0,1,-1],[1,1,2,-1,-1],[1,1,-1,0,0],[1,-1,0,-1,1]]); # the ordered basis here is {ONE, epsilon, sigma, rho, epsilon*rho = alpha} |
| > | augment(CharacterTable,[3,3,3,0,3]); # we augment the matrix above by attaching the rightmost column which contains the solution set we want: psi^4(rho)( [e,a,b,c,d] ) = 3,3,3,0,3 |
| > | gaussjord(augment(CharacterTable,[3,3,3,0,3])); # this says that we need 2*ONE - epsilon + sigma to get the linear combination of characters that equals the character psi^4(rho) |
| > | evalchar(2*ONE - epsilon + sigma,[e,a,b,c,d]); |
psi^4(epsilon * rho) = psi^3(alpha) = 2*ONE - epsilon + sigma
| > | psi4(alpha,[e,a,b,c,d]); |
| > | # see previous calculation |
| > | psi4(epsilon*rho,[e,a,b,c,d]); |
Let's make the Adams operation psi^k in general that takes a character to a character.
| > | # mymulp( a$5 ); a &* a &* a &* a &* a; mymulp( c$5 ); c &* c &* c &* c &* c; |
| > | psi:=proc(k,character,conjclassrep) local i,j; seq(`character`( mymulp( conjclassrep[i]$k) ),i=1..nops(conjclassrep)); end proc: |
psi^5(ONE) = ONE
| > | psi(5,ONE,[e,a,b,c,d]); |
psi^5(epsilon) = epsilon
| > | psi(5,epsilon,[e,a,b,c,d]); |
| > | evalchar(epsilon,CCR); |
psi^5(sigma) = sigma
| > | psi(5,sigma,[e,a,b,c,d]); |
| > | gaussjord(augment(CharacterTable,[ psi(5,sigma,[e,a,b,c,d]) ])); # this says we want 1*sigma |
| > | evalchar(sigma,[e,a,b,c,d]); |
psi^5(rho) = rho
| > | psi(5,rho,[e,a,b,c,d]); |
| > | #CharacterTable:=matrix([[1,1,2,3,3],[1,-1,0,1,-1],[1,1,2,-1,-1],[1,1,-1,0,0],[1,-1,0,-1,1]]); |
| > | #augment(CharacterTable,[ psi(5,rho,[e,a,b,c,d]) ]); |
| > | gaussjord(augment(CharacterTable,[ psi(5,rho,[e,a,b,c,d]) ])); |
| > | evalchar(rho,[e,a,b,c,d]); |
psi^5(epsilon * rho) =
| > | psi(5,alpha,[e,a,b,c,d]); |
| > | # see previous calculation |
| > | psi(5,epsilon*rho,[e,a,b,c,d]); |
| > | gaussjord(augment(CharacterTable,[ psi(5,epsilon*rho,[e,a,b,c,d]) ])); |
| > | evalchar(epsilon*rho,[e,a,b,c,d]); |
So what have we learned here? We've learned that thinking of the character table as a matrix A, if we are given a list b of values that a character chi takes on the conjugacy class representatives, we can solve the system Ax=b for x and thereby obtain the (coefficients in) linear combination of the characters ONE, epsilon, sigma, rho, epsilon*rho that equals chi. Thus, given any character chi, we can express it as a linear combination of ONE, epsilon, sigma, rho, epsilon*rho just by a little linear algebra.
| > |
| > |
| > |
| > |
Now it's time to get serious. Let's write a procedure that takes input psi^k(character) and gives as output the linear combination of ONE, epsilon, sigma, rho, and epsilon*rho which comprise it.
| > | psik2lincombi:=proc(k,character) local CoeffMtx; #print(psi(k,`character`,[e,a,b,c,d])); CoeffMtx:=gaussjord(augment(CharacterTable,[ psi(k,`character`,[e,a,b,c,d]) ])); CoeffMtx[1,6] + CoeffMtx[2,6]*epsilon + CoeffMtx[3,6]*sigma + CoeffMtx[4,6]*rho + CoeffMtx[5,6]*epsilon*rho; #evalchar( #CoeffMtx[1,6] + CoeffMtx[2,6]*epsilon + CoeffMtx[3,6]*sigma + CoeffMtx[4,6]*rho + #CoeffMtx[5,6]*epsilon*rho #, [e,a,b,c,d]); end proc: |
| > | psik2lincombi(5,rho); |
| > | psik2lincombi(6,rho); |
| > | listAdamsOps:=proc(i,j,L) #seq(seq( lprint(k,L[l],psik2lincombi(k,L[l])), l=1..nops(L)), k=i..j); seq(seq( print([psi^k,L[l],`=`,psik2lincombi(k,L[l])]), l=1..nops(L)), k=i..j); end proc: |
Note: the Adams operations on R(G) for a finite group G are always periodic with period the order of G, and perhaps even of smaller period, as is the case for S_4 in which the Adams operations are periodic with period 12 = |S_4|/2. I had suspected that there was periodicity when I saw that psi^k(epsilon)=epsilon^k. The periodicity theorem is Corollary 3.2 on p. 274 in Atiyah and Tall's paper "Group Representations, $\lambda$-rings, and the $J$-homomorphism".
| > | listAdamsOps(2,12,[ONE,epsilon,sigma,rho,epsilon*rho]); |
| > |
| > |