#For a given group g and prime p, IncompleteAtlas returns a #list of which numbered representations in the atlas do not have #names. IncompleteAtlas := function(g,p) local gp,c, i, incompletechars, rep, gens,cgens, m; gp := AllAtlasGeneratingSetInfos(g); c := AllAtlasGeneratingSetInfos(g, Characteristic, p); incompletechars := []; for i in [1..Length(c)] do rep := AtlasGenerators(gp[c[i].repnr].identifier); gens := rep.generators; cgens := List(gens,x -> CMat(x)); m := Module(cgens); if DegreeOfSplittingField(m) = 1 then if IsBound(c[i].charactername) = false then Add(incompletechars, c[i].repnr); fi; fi; od; return incompletechars; end; #Finds the lcm of a list. LcmList := function(list) local l, lcm, i,j, counter; l := Collected(list); #check if all things in list are 1 if Length(l) = 1 then return 1; fi; #don't need to take lcm of (1,n) if l[1][1] = 1 then Remove(l,1); fi; #keep taking pairwise lcm until you get one number counter := Length(l); while counter > 1 do lcm := []; for i in [1..Length(l)-1] do for j in [i+1..Length(l)] do Add(lcm, LcmInt(l[i][1],l[j][1])); od; od; l := Collected(lcm); counter := Length(l); od; return l[1][1]; end; #For a given group g, AllIncompleteAtlas returns a list of primes #which divide the order of the group and which Atlas #representations don't have an associated character name for #those primes. AllIncompleteAtlas := function(g) local l, i, p, allreps, m; l := Collected(Factors(Size(CharacterTable(g)))); i := 1; p := 0; allreps := []; m := []; for i in [1..Length(l)] do p := l[i][1]; m := [p, IncompleteAtlas(g,p)]; Add(allreps,m); od; return allreps; end; #IrrChar takes in a group g, prime p, and an atlas rep n, #It matches up an atlas representation n with associated #character name. IrrChar := function(g,p,n) local gp,a,b,c,d,traces,ct,pos; gp :=AllAtlasGeneratingSetInfos(g); a:= AtlasStraightLineProgram(g,"classes"); if a = fail then a := LocalClasses(g); if a = fail then return fail; fi; fi; b:= AtlasGenerators(gp[n].identifier); c:= ResultOfStraightLineProgram(a.program, b.generators); d:= Filtered(c, x -> Order(x) mod p > 0); traces:= List(d, x -> BrauerCharacterValue(Unpack(x))); ct := CharacterTable(g) mod p; pos := Position(Irr(ct), traces); if pos = fail then return fail; else return AtlasCharacterNames(ct)[pos]; fi; end; #Given a group G, a prime p, a list l of which characters have an #associated representation in the atlas, and a number n of which #character you want to build, plan gives which characters you #should tensor to build the rep plan := function(G, p, l, n) local ct, irr, list, tensor, decomp,i,j; ct := CharacterTable(G) mod p; irr := Irr(ct); list := []; for i in l do for j in l do if list = [] then tensor := Tensored([irr[i]],[irr[j]]); decomp := Decomposition(irr, tensor, 5); if decomp[1][n] > 0 then Append(list, [AtlasCharacterNames(ct)[i],AtlasCharacterNames(ct)[j]]); fi; fi; od; od; return list; end; #Brian's program for getting the list of absolutely irreducible #representations. CMatz := function(mat,field) local p,d,cf; cf := Collected(Factors(Size(field))); p := cf[1][1]; d := cf[1][2]; return CMat(List(mat, x -> CVec(x,p,d))); end; AbsIrredReps:= function(gapname,p) local gp,i,m,rep,c,gens,cgens,list; gp:=AllAtlasGeneratingSetInfos(gapname); list:=[]; c:=AllAtlasGeneratingSetInfos(gapname,Characteristic,p); for i in [1..Length(c)] do rep:=AtlasGenerators(gp[c[i].repnr].identifier); gens := rep.generators; if ConvertToMatrixRep(gens[1]) = fail then cgens := List(gens, x -> CMatz(x,rep.ring)); else cgens := List(gens, x -> CMat(x)); fi; m:=Module(cgens); if DegreeOfSplittingField(m) = 1 then Add(list, c[i]); fi; od; return list; end; #Input: group G, prime p. Gets the numbers in the character table #corresponding to the representations in the Atlas. charreps := function(G, p) local charnames,chars,i; charnames := []; chars := AbsIrredReps(G,p); for i in [1..Size(chars)] do if IsBound(chars[i].charactername) = true then Add(charnames, chars[i].charactername); else Add(charnames, IrrChar(G, p, chars[i].repnr)); fi; od; return charnames; end; #Input: group G, prime p. gets numbers for characters we have #corresponding reps in Atlas gapchars := function(G,p) local nums,names, ct,i; nums := []; names := charreps(G,p); ct := CharacterTable(G) mod p; for i in [1..Size(names)] do Add(nums, Position(AtlasCharacterNames(ct),names[i])); od; return nums; end; #Input: Group G, prime p. gets the numbers for characters we #don't have reps in Atlas incompletechars := function(G,p) local completechars,ct,ichars,i; completechars := [1]; Append(completechars, gapchars(G,p)); ct:= CharacterTable(G) mod p; ichars :=[]; for i in [1..Size(Irr(ct))] do if Position(completechars, i) = fail then Add(ichars, i); fi; od; return ichars; end; #Input: group G, prime p, list l in the form [rep number n, pairs #of rep numbers which tensors to get n]. Gives the smallest #tensor in the form [rep number n, [a,b]] smallest:= function(G,p,l) local cn, irr, list, small,sc,nc,i; irr:= Irr(CharacterTable(G) mod p); cn := AtlasCharacterNames(CharacterTable(G) mod p); list:= l; if Length(l)>1 then small := l[2]; for i in [2..Length(l)] do sc := irr[small[1]][1]*irr[small[2]][1]; nc := irr[l[i][1]][1]*irr[l[i][2]][1]; if nc < sc then small := l[i]; fi; od; list := [l[1],[cn[small[1]],cn[small[2]]]]; fi; return list; end; #Given a group G, a prime p, a list of which characters have an #associated representation in the atlas, bplan gives smallest #tensor for each rep (if it can be made) bplan := function(G, p, l) local ct, irr, list, listb, tensor, decomp,i,j,k,m,n; ct := CharacterTable(G) mod p; irr := Irr(ct); list := []; listb := []; for k in [1..Size(Irr(ct))] do Add(listb,[k]); od; for i in l do for j in l do if j>i-1 then tensor := Tensored([irr[i]],[irr[j]]); decomp := Decomposition(irr, tensor, 5); for n in [2..Size(Irr(ct))] do if n in l then listb:= listb; else if decomp[1][n] > 0 then Add(listb[n],[i,j]); fi; fi; od; fi; od; od; for m in [1..Length(listb)] do Add(list,smallest(G,p,listb[m])); od; return list; end; #Input: Group G, prime p, list l of your initial known #characters. Gets new list of characters you have(no record of #how to get them) newlist:= function(G,p,l) local list,blist,i; list := l; blist := bplan(G,p,l); for i in [1..Length(blist)] do if Length(blist[i])> 1 then Add(list, blist[i][1]); fi; od; return list; end; #Input: group, prime, list of known characters. Extracts only new #characters (no record of how to get them) newchar:= function(G,p,l) local list,blist,i; list := []; blist := bplan(G,p,l); for i in [1..Length(blist)] do if Length(blist[i])> 1 then Add(list, blist[i][1]); fi; od; return list; end; #Input: group, prime. Recursively does bplan until you construct #all the characters. Returns list of lists. Output i the form #[...,n,[a,b],..] where n is the number (in the character #table) of the character you don't have a rep for and a and b are #the Atlas names of the reps you should tensor to get n. nplan:= function(G,p) local l,ct,irr,blist,list,i; l:= gapchars(G,p); ct := CharacterTable(G) mod p; irr := Irr(ct); list := []; while Length(l)< Size(irr)-1 do blist := bplan(G,p,l); for i in [1..Length(blist)] do if Length(blist[i])>1 then Append(list,blist[i]); fi; od; l := newlist(G,p,l); od; return list; end; changefield := function(cgens,field) local i,mats; for i in [1..Size(cgens)] do Add(mats,CMat(List(cgens[i],x -> CVec(Unpack(x),field)))); od; return mats; end; #Input: group, rep number in atlas, prime, power. Output: representation as a module #add a check that the field is an extension. buildrep := function(g,n,field) local gp,cgens,mats,i; gp := AllAtlasGeneratingSetInfos(g); if IsSubset(field,AtlasGenerators(gp[n].identifier).ring) = false then return fail; fi; mats := []; if ConvertToMatrixRep(AtlasGenerators(gp[n].identifier).generators[1]) = fail then cgens := List(AtlasGenerators(gp[n].identifier).generators, x -> CMatz(x,gp[n].ring)); else cgens := List(AtlasGenerators(gp[n].identifier).generators, x -> CMat(x)); fi; cgens := List(AtlasGenerators(gp[n].identifier).generators, x -> CMat(x)); if gp[n].ring = field then return cgens; else for i in [1..Size(cgens)] do Add(mats,CMat(List(cgens[i],x -> CVec(Unpack(x),field)))); od; fi; return mats; end; #Input: group, prime, rep generators. Output: the character of the representation charval := function(g,p,gens) local a,c,d,traces; a:= AtlasStraightLineProgram(g,"classes"); if a = fail then a := LocalClasses(g); if a = fail then return fail; fi; fi; c:= ResultOfStraightLineProgram(a.program, gens); d:= Filtered(c, x -> Order(x) mod p > 0); traces:= List(d, x -> BrauerCharacterValue(Unpack(x))); return traces; end; #Input: Group, prime, list of chars (their number in GAP). Output: the minimum field all chars are over minfield := function(G,p,l) local list,fields,ct, irr, i,j; list := []; fields := []; ct := CharacterTable(G) mod p; irr := Irr(ct); for i in l do Add(list, List(irr[i],x->FrobeniusCharacterValue(Unpack(x),p))); od; for j in [1..Length(l)] do Add(fields, LogInt(Size(Field(list[j])),p)); od; return GF(p^LcmList(fields)); end; #input: group, prime; Output: list of character names of irred. reps namechars := function(G,p) local abs, names, i; abs := AbsIrredReps(G,p); names := []; for i in [1..Length(abs)] do if IsBound(abs[i].charactername) = true then Add(names, abs[i].charactername); else Add(names, IrrChar(G,p,abs[i].repnr)); fi; od; return names; end; #Input: Two lists of matrices. kprod takes the tensor product of the lists of matrices. Output: A list of matrices. (Note matrices should be as CMat). #add a check that matrices are over the same field. kprod := function(s,t) local i,kp; kp := []; for i in [1..Length(s)] do Add(kp,KroneckerProduct(s[i],t[i])); od; return kp; end; #Input: group, prime, GAP rep number, Output: the representation repn := function(G,p,n) local np,t,irr,abs, field,names,i,r,s,rep1,rep2,tensor,factors,k,num; np := nplan(G,p); t := Position(np,n) +1; irr := Irr(CharacterTable(G) mod p); abs := AbsIrredReps(G,p); field := minfield(G,p,[2..Size(irr)]); names := []; for i in [1..Length(abs)] do if IsBound(abs[i].charactername) = true then Add(names, abs[i].charactername); else Add(names, IrrChar(G,p,abs[i].repnr)); fi; od; r := Position(names, np[t][1]); s := Position(names, np[t][2]); rep1 := buildrep(G,abs[r].repnr,field); rep2 := buildrep(G,abs[s].repnr,field); tensor := Module(kprod(rep1,rep2)); factors := Chop(tensor); for k in [1..Length(factors.db)] do num := Position(irr, charval(G,p,RepresentingMatrices(factors.db[k]))); if num = n then return RepresentingMatrices(factors.db[k]); fi; od; end; repnl := function(G,p,n,l) local np,t,ct,irr,abs,a,b,list, field,names,i,r,s,rep1,rep2,tensor,factors,k,num,rep; np := nplan(G,p); t := Position(np,n) +1; ct := CharacterTable(G) mod p; irr := Irr(ct); abs := AbsIrredReps(G,p); a:= Position(AtlasCharacterNames(ct),np[t][1]); b:= Position(AtlasCharacterNames(ct),np[t][2]); list := [n, a,b]; field := minfield(G,p,list); names := []; for i in [1..Length(abs)] do if IsBound(abs[i].charactername) = true then Add(names, abs[i].charactername); else Add(names, IrrChar(G,p,abs[i].repnr)); fi; od; r := Position(names, np[t][1]); s := Position(names, np[t][2]); if r = fail then rep1 := l[Position(l,a)+1]; else rep1 := buildrep(G,abs[r].repnr,field); fi; if s = fail then rep1 := l[Position(l,b)+1]; else rep2 := buildrep(G,abs[s].repnr,field); fi; tensor := Module(kprod(rep1,rep2)); factors := Chop(tensor); for k in [1..Length(factors)] do num := Position(irr, charval(G,p,factors[k][1].generators)); if num = n then rep := factors[k][1]; fi; od; return rep; end; #builds all unknown reps given a group and a prime repnall := function(G,p) local np,list,i,n; np:= nplan(G,p); list := []; for i in [1..Length(np)/2] do n := np[2*i-1]; if np[2*i][1] in namechars(G,p) and np[2*i][2] in namechars(G,p) then Append(list, [n,repn(G,p,n)]); else Append(list, [n,repnl(G,p,n,list)]); fi; od; return list; end; #finish group: Input: a group; output: which primes still need representations, which primes do not have any representations (so we can't build new ones) finishgroup := function(g) local l, i, p, primes, m,j,none; l := Collected(Factors(Size(CharacterTable(g)))); primes := []; m := []; for i in [1..Length(l)] do p := l[i][1]; if Length(incompletechars(g,p)) >0 then Add(primes,p); fi; od; if primes = [] then Print(g); Print(" has all representations for all primes dividing the order."); else Print(g); Print(" needs representations for "); Print(primes); none := []; for j in primes do if AbsIrredReps(g,j) = [] then Add(none,j); fi; od; if Length(none) >0 then Print(" but the group has no representations in the Atlas for "); Print(none); fi; fi; end; #input: group, prime, [c1, c2] (where c1, c2 are the characters to tensor), list of characters I'm going to change this around so the field will just be a minimal splitting field for the entire group #output: a list of rep number, generators. ie [repnr, gens, repnr, gens, etc.] elrep := function(G,p,rl,field) local ic,irr,abs,j,names, i,r,s,rep1,rep2,tensor,factors,k,num,brep; ic := incompletechars(G,p); irr := Irr(CharacterTable(G) mod p); abs := AbsIrredReps(G,p); names := []; brep := []; for i in [1..Length(abs)] do if IsBound(abs[i].charactername) = true then Add(names, abs[i].charactername); else Add(names, IrrChar(G,p,abs[i].repnr)); fi; od; r := Position(names, rl[1]); s := Position(names, rl[2]); rep1 := buildrep(G,abs[r].repnr,field); rep2 := buildrep(G,abs[s].repnr,field); tensor := Module(kprod(rep1,rep2)); factors := Chop(tensor); for k in [1..Length(factors.db)] do num := Position(irr, charval(G,p,RepresentingMatrices(factors.db[k]))); for j in ic do if num = j then Append(brep,[j,factors.db[k]]); fi; od; od; return brep; end; ismallest:= function(G,p,l) local cn, irr, list, small,sc,nc,i,j,list2; irr:= Irr(CharacterTable(G) mod p); cn := AtlasCharacterNames(CharacterTable(G) mod p); list:= l; if Length(l)>1 then small := l[2]; for i in [2..Length(l)] do sc := irr[small[1]][1]*irr[small[2]][1]; nc := irr[l[i][1]][1]*irr[l[i][2]][1]; if nc < sc then small := l[i]; fi; od; list := [l[1],[small[1],small[2]]]; fi; return list; end; maxten := function(l) local list,i,n; list := []; for i in [1..Length(l)] do if Length(l[i]) > 1 then Add(list,l[i][2][1]*l[i][2][2]); else Add(list,0); fi; od; n := Positions(list,Maximum(list)); return n; end; eplan := function(G,p) local l, irr, list, list2, list3, listb, k, i, j, tensor, decomp, n,m,tp; l:= gapchars(G,p); irr := Irr(CharacterTable(G) mod p); list := []; listb := []; for k in [1..Size(Irr(CharacterTable(G) mod p))] do Add(listb,[k]); od; for i in l do for j in l do if j>i-1 then tensor := Tensored([irr[i]],[irr[j]]); decomp := Decomposition(irr, tensor, 5); for n in [2..Size(Irr(CharacterTable(G) mod p))] do if n in l then listb:= listb; else if decomp[1][n] > 0 then Add(listb[n],[i,j]); fi; fi; od; fi; od; od; list2 := []; for i in [1..Length(irr)] do if Length(listb[i])>1 then Add(list2,i); fi; od; for i in [1..Length(listb)] do Add(list,ismallest(G,p,listb[i])); od; list3 := []; while Length(list2)>0 do m := maxten(list); tp := list[m[1]][2]; Add(list3,[AtlasCharacterNames(CharacterTable(G) mod p)[tp[1]],AtlasCharacterNames(CharacterTable(G) mod p)[tp[2]]]); for i in m do RemoveSet(list2,i); od; od; return list3; end;