Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
| Download

Code for "Normal Reflection Subgroups" by Carlos Arreche and Nathan Williams

Views: 29
Visibility: Unlisted (only visible to those who know the link)
Image: default
############################################################################################################## # Let G be a rank 2 exceptional complex reflection group # # This code is determines the Orlik-Solomon spaces and fake degrees # # for all normal reflection subgroups N of G, for all Galois twists of the reflection representation of G # ############################################################################################################## #field_of_def := rec(4:=3,5:=3,6:=12,7:=12,8:=4,9:=8,10:=12,11:=24,12:=8,13:=8,14:=24,15:=24,16:=5,17:=20,18:=15,19:=60,20:=15,21:=60,22:=20,23:=5,24:=7,25:=3,26:=3,27:=15,28:=1,29:=4,30:=5,31:=4,32:=3,33:=3,34:=3,35:=2,36:=2,37:=2); group_data={ (4,2,2):('(C4 x C2) : C2',4), 4:('SL(2,3)',3), 5:('C3 x SL(2,3)',12), 6:('((C4 x C2) : C2) : C3',12), 7:('C3 x (((C4 x C2) : C2) : C3)',12), 8:('SL(2,3) : C4',24), 9:('(SL(2,3) : C4) : C2',24), 10:('C3 x (SL(2,3) : C4)',24), 11:('C3 x ((((C8 x C2) : C2) : C3) : C2)',24), 12:('GL(2,3)',8), 13:('(((C4 x C2) : C2) : C3) : C2',24), 14:('C3 x GL(2,3)',24), 15:('C3 x ((((C4 x C2) : C2) : C3) : C2)',24), 16:('C5 x SL(2,5)',5), 17:('C5 x (SL(2,5) : C2)',60), 18:('C15 x SL(2,5)',60), 19:('C15 x (SL(2,5) : C2)',60), 20:('C3 x SL(2,5)',15), 21:('C3 x (SL(2,5) : C2)',60), 22:('SL(2,5) : C2',20), 26:('C2 x ((((C3 x C3) : C3) : Q8) : C3)',3), 28:('((((C2 x C2 x C2) : (C2 x C2)) : (C3 x C3)) : C2) : C2',2), }# note that we are using the matrices in Sage, # so the field of definition is not minimal. # This is not a *problem*, but it is worth saying. iso_type={iso_type[0]:G for G,iso_type in group_data.items()} iso_type.update({'GL(2,3) : C2':13})# structure description is not an isomorphism invariant! def NormalReflectionSubgroups(G,structure=False): S=[G.conjugacy_class(i) for i in G.conjugacy_classes_representatives() if i in G.reflections()] NRS=[] for i in Subsets(S): N=G.subgroup([k for j in i for k in j]) if N not in NRS and N!=G and len(N)!=1: NRS.append(N) if structure==False: return NRS else: strNRS=[] for N in NRS: H=G.quotient(N) N_str=N.structure_description() H_str=H.structure_description() if N_str in iso_type:# and H_str in iso_type: strNRS.append([iso_type[N_str],H_str]) else: strNRS.append([N_str,H_str]) return (NRS,strNRS) def matrix_double(gg,s): g=list(gg) n=len(g) return matrix([[g[i][j] if (i<n and j<n) else (s(g[i-n][j-n]) if (i>=n and j>=n) else 0) for j in range(2*n)] for i in range(2*n)]) scale=3 def find_Galois(F,s): z=F.gen() for r in F.galois_group(): if r(z)==z^s: return r break def get_invariant(G,e,two=False): f1=AlgebraicForm(4,e+1,x^e*a+y^e*b) f1=sum([f1.transformed(g).polynomial() for g in VN]) if f1==0: f1=AlgebraicForm(4,e+1,x^e*b+y^e*a)#this is a hack, not guaranteed to work(!) f1=sum([f1.transformed(g).polynomial() for g in VN]) if f1==0: f1=AlgebraicForm(4,e+1,sum([x^i*y^(e-i) for i in range(e+1)])*(a+b))#this is a hack, not guaranteed to work(!) f1=sum([f1.transformed(g).polynomial() for g in VN]) if f1==0: i=0 while f1==0 and i<10: i+=1 f1=AlgebraicForm(4,e+1,sum([randrange(1,scale+1)*x^i*y^(e-i) for i in range(e+1)])*(a+b))#this is a hack, not guaranteed to work(!) f1=sum([f1.transformed(g).polynomial() for g in VN]) if two==True: #f2=0 #while f2==0 : # f2=AlgebraicForm(4,e+1,sum([randrange(-scale,scale)*x^i*y^(e-i) for i in range(e+1)])*(a+b)+(scale+1)*(x^e+y^e)*(a+b)) # f2=sum([f2.transformed(g).polynomial() for g in G]) I=[f1]*R f2=AlgebraicForm(4,e+1,x^e*a-y^e*b) f2=sum([f2.transformed(g).polynomial() for g in VN]) if f2==0 or f2 in I: f2=AlgebraicForm(4,e+1,x^e*b-y^e*a)#this is a hack, not guaranteed to work(!) f2=sum([f2.transformed(g).polynomial() for g in VN]) if f2==0 or f2 in I: f2=AlgebraicForm(4,e+1,sum([(-1)^i*x^i*y^(e-i) for i in range(e+1)])*(a-b))#this is a hack, not guaranteed to work(!) f2=sum([f2.transformed(g).polynomial() for g in VN]) if f2==0 or f2 in I: i=0 while (f2==0 or f2 in I) and i<10: i+=1 f2=AlgebraicForm(4,e+1,sum([randrange(1,scale+1)*x^i*y^(e-i) for i in range(e+1)])*(a-b))#this is a hack, not guaranteed to work(!) f2=sum([f2.transformed(g).polynomial() for g in VN]) return [f1,f2] else: return f1 def Orlik_Solomon_Sum(N,s): try: G=N.ambient_group() except: G=N out=0 for g in N.conjugacy_classes_representatives(): out+=len(N.conjugacy_class(g))*prod([(1-s(i))/(1-i) for i in eigenvalues(g) if i!=1])*q^(((G(g).matrix()-one)).kernel().dimension()) return out def Orlik_Solomon_Sum_rep(G,rep,s): out=0 for g in G.conjugacy_classes_representatives(): out+=len(G.conjugacy_class(g))*prod([(1-s(i))/(1-i) for i in eigenvalues(g) if i!=1])*q^(((g.matrix()-one)).kernel().dimension())*t^((prod([rep[j-1] for j in g.reduced_word()])-one).kernel().dimension()) return out def scalar_product(G,rep1,rep2): out=0 one1=matrix.identity(rep1[0].dimensions()[0]) one2=matrix.identity(rep2[0].dimensions()[0]) for g in G.conjugacy_classes_representatives(): g_word=g.reduced_word() out+=len(G.conjugacy_class(g))*(prod([rep1[j-1] for j in g.reduced_word()])*one1).trace()*(prod([rep2[j-1] for j in g.reduced_word()])*one2).trace() return out/len(G) # put in the Shephard-Tood numbering for the range of rank two exceptional complex reflection groups you wish to compute for STn in range(4,8): print "Complex Reflection Reflection Group G_",STn #STn=5 G=ReflectionGroup(STn) h=group_data[iso_type[G.structure_description()]][1] print "G defined over Z(",h,")" F=CyclotomicField(h) UCF=UniversalCyclotomicField() R.<x,y,a,b>=F[] gap3.RequirePackage('"chevie"') q,t=var('q','t') Z=PolynomialRing(ZZ, 'q') Z2=PolynomialRing(ZZ, 'q,t') set_verbose(-1) from sage.rings.invariants.invariant_theory import AlgebraicForm #len(G) NS=NormalReflectionSubgroups(G,structure=True) twists=[i for i in range(h) if GCD(i,h)==1] #len(twists) print "Normal Reflection Subgroups are: ",NS[1] #len(NS[1]) #starting to build a dictionary #g:{n:{s:[e_i^G(Vs),e_i^N(Vs),N_OS_invariants,N_OS_matrices]}} pout="" fout = file('G'+str(STn)+'.txt','w') for N_num in range(len(NS[1])): for tw in twists: #print N_num,s,"\n" N=NS[0][N_num] #set normal subgroup N #ADJUST HERE TO COMPUTE FOR DIFFERENT GALOIS GROUPS #galois twist GAL=tw #print len(G),len(N) s=find_Galois(F,tw) eigs=dict([]) def eigenvalues(g): if g in eigs: return eigs[g] else: eigs[g]=G(g).matrix().apply_map(F).eigenvalues() return eigs[g] one=G.one().matrix() out=0 NSum=Z(factor(Orlik_Solomon_Sum(N,s))) GSum=Z(factor(Orlik_Solomon_Sum(G,s))) #for g in N.conjugacy_classes_representatives(): # out+=len(N.conjugacy_class(g))*prod([(1-s(i))/(1-i) for i in eigenvalues(g) if i!=1])*q^(((G(g).matrix()-one)).kernel().dimension()) #factN=factor(NSum) #factG=factor(GSum) #print "Galois-twisted sum over N = ",factor(NSum) #print "Galois-twisted sum over G = ",factor(GSum) eNs=flatten([[-(i[0])]*(i[1]) for i in NSum.roots()]) eGs=flatten([[-(i[0])]*(i[1]) for i in GSum.roots()]) #print "From which we compute the N-twisted exponents = ",eNs #print " and the G-twisted exponents = ",eGs VGgens=[matrix_double(r.matrix().apply_map(F),s) for r in list(G.simple_reflections())] VNgens=[matrix_double(G(r).matrix().apply_map(F),s) for r in list(N.gens())] VG=MatrixGroup(VGgens) VN=MatrixGroup(VNgens) if eNs[0]!=eNs[1]: Ninvs=[get_invariant(VN,d) for d in eNs] else: Ninvs=get_invariant(VN,eNs[0],two=True) Ninvs=[f/f.coefficients()[0] for f in Ninvs] #print " N-invariants on Orlik-Solomon Space:\n",Ninvs,"\n" I = Ninvs*R rep=map(matrix,[[AlgebraicForm(4,f.degree(),f).transformed(g).polynomial().lift(I) for f in Ninvs] for g in VG.gens()]) #rep=[m.apply_map(F) for m in rep] rep=[m.substitute(x=0,y=0).apply_map(F) for m in rep]# #for r in rep: #print " The action of G on \VNs is given by the matrices: " #rep pout+="("+str(STn)+","+str(NS[1][N_num][0])+","+str(GAL)+"):["+str(eGs)+","+str(eNs)+","+str([p*UCF(1)for p in Ninvs])+","+str([[[k*UCF(1) for k in j] for j in i] for i in rep])+"]}}," fout.write(pout) fout.close() print "\n"
Complex Reflection Reflection Group G_ 4 G defined over Z( 3 ) Normal Reflection Subgroups are: [] Complex Reflection Reflection Group G_ 5 G defined over Z( 12 ) Normal Reflection Subgroups are: [[4, 'C3'], [4, 'C3']] Complex Reflection Reflection Group G_ 6 G defined over Z( 12 ) Normal Reflection Subgroups are: [[(4, 2, 2), 'C3'], [4, 'C2']] Complex Reflection Reflection Group G_ 7 G defined over Z( 12 ) Normal Reflection Subgroups are: [[(4, 2, 2), 'C3 x C3'], [4, 'C6'], [4, 'C6'], [6, 'C3'], [6, 'C3'], [5, 'C2']]
#################################################################################################### # START HUNT: Only for if you have to go HUNTING for an invariant by hand, because the # averaging guess above didn't pan out...maybe put in a test for this? # 2 problems can arise: # 1. You got a 0 polynomial as an invariant # 2. You got a lower degree invariant *times* an N-invariant (on V^*) polynomial. #################################################################################################### print eNs Ninvs f1=AlgebraicForm(4,5+1,x^3*y^2*(b)+y^5*b+y^5*a) f1=sum([f1.transformed(g).polynomial() for g in VN]) f1
[5, 11] [0, 39/4*x^10*y*a + 5511/4*x^8*y^3*a - 117/2*x^6*y^5*a + 5511/2*x^4*y^7*a + 195/4*x^2*y^9*a - 501/4*y^11*a + 501/4*x^11*b - 195/4*x^9*y^2*b - 5511/2*x^7*y^4*b + 117/2*x^5*y^6*b - 5511/4*x^3*y^8*b - 39/4*x*y^10*b] 6*x^5*a - 30*x*y^4*a - 30*x^4*y*b + 6*y^5*b
Ninvs=[Ninvs[1],f1]#Ninvs[0] Ninvs=[f/f.coefficients()[0] for f in Ninvs] Ninvs I = Ninvs*R rep=map(matrix,[[AlgebraicForm(4,f.degree(),f).transformed(g).polynomial().lift(I) for f in Ninvs] for g in VG.gens()]) #for r in rep: #print " N-invariants on Orlik-Solomon Space:\n",Ninvs,"\n" #rep=map(matrix,[[AlgebraicForm(4,f.degree(),f).transformed(g).polynomial().lift(I) for f in Ninvs] for g in VG.gens()]) rep=[m.substitute(x=0,y=0).apply_map(F) for m in rep] view(rep) #for r in rep: #print " The action of G on \VNs is given by the matrices: " #rep "("+str(STn)+","+str(NS[1][N_num][0])+","+str(GAL)+"):["+str(eGs)+","+str(eNs)+","+str([p*UCF(1)for p in Ninvs])+","+str([[[k*UCF(1) for k in j] for j in i] for i in rep])+"]}}" #################################################################################################### # END HUNT. ####################################################################################################
[x^10*y*a + 1837/13*x^8*y^3*a - 6*x^6*y^5*a + 3674/13*x^4*y^7*a + 5*x^2*y^9*a - 167/13*y^11*a + 167/13*x^11*b - 5*x^9*y^2*b - 3674/13*x^7*y^4*b + 6*x^5*y^6*b - 1837/13*x^3*y^8*b - x*y^10*b, x^5*a - 5*x*y^4*a - 5*x^4*y*b + y^5*b]
[(1001)\displaystyle \left(\begin{array}{rr} -1 & 0 \\ 0 & 1 \end{array}\right), (1001)\displaystyle \left(\begin{array}{rr} 1 & 0 \\ 0 & 1 \end{array}\right), (1001)\displaystyle \left(\begin{array}{rr} 1 & 0 \\ 0 & 1 \end{array}\right)]
'(7,5,7):[[5, 17],[5, 11],[x^10*y*a + 1837/13*x^8*y^3*a + (-6)*x^6*y^5*a + 3674/13*x^4*y^7*a + 5*x^2*y^9*a + (-167/13)*y^11*a + 167/13*x^11*b + (-5)*x^9*y^2*b + (-3674/13)*x^7*y^4*b + 6*x^5*y^6*b + (-1837/13)*x^3*y^8*b - x*y^10*b, x^5*a + (-5)*x*y^4*a + (-5)*x^4*y*b + y^5*b],[[[-1, 0], [0, 1]], [[1, 0], [0, 1]], [[1, 0], [0, 1]]]]}}'
#This now builds the GAP3 representations, which are correctly paired with the fake degrees #we then figure out what fake degrees our rep decomposes as. G3=gap3.ComplexReflectionGroup(STn) Irrs2=[i for i,j in enumerate(G3.FakeDegrees(gap3(1))) if j<=2] Rep2=[map(matrix,gap3.Representation(G3,i+1).sage()) for i in Irrs2] FakeDegrees=gap3.FakeDegrees(G3,'x') SC=[scalar_product(G,i,rep) for i in Rep2] [FakeDegrees[i+1] for i,j in enumerate(SC) if j!=0]
[1, x^8]
gal=s #THIS COMPUTES THE s=1 GALOIS TWIST (SO E ITSELF) s=find_Galois(F,1) VGgens=[matrix_double(r.matrix().apply_map(F),s) for r in list(G.simple_reflections())] VNgens=[matrix_double(G(r).matrix().apply_map(F),s) for r in list(N.gens())] VG=MatrixGroup(VGgens) VN=MatrixGroup(VNgens) NDegs=ReflectionGroup(iso_type[N.structure_description()]).degrees() print "N degrees are: ",NDegs if NDegs[0]!=NDegs[1]: Ninvs=[get_invariant(VN,d-1) for d in NDegs] else: Ninvs=get_invariant(VN,NDegs[0]-1,two=True) #if len(Set(NDegs))==2: # Ninvs=[get_invariant(VN,d-1) for d in NDegs] #else: # Ninvs=[get_invariant(VN,NDegs[0]-1),get_invariant(VN,NDegs[0]-1,two=True)] #print Ninvs,"\n" I = Ninvs*R #we can now compute the representation of G on E. This can be removed later if we only care about the Galois twist rep=map(matrix,[[AlgebraicForm(4,f.degree(),f).transformed(g).polynomial().lift(I) for f in Ninvs] for g in VG.gens()]) #rep s=gal#from above # at this point we *could* sum over all of G to see our main theorem, but it was enough to find the sum over N to get the e_i(V^s) out=Z2(factor(Orlik_Solomon_Sum_rep(G,rep,s))) #for g in G.conjugacy_classes_representatives(): # out+=len(G.conjugacy_class(g))*prod([(1-s(i))/(1-i) for i in eigenvalues(g) if i!=1])*q^(((g.matrix()-one)).kernel().dimension())*t^((prod([rep[j-1] for j in g.reduced_word()])-one).kernel().dimension()) factor(out)
N degrees are: (4, 12) t * (q + 5) * (q*t + 9*t + 8)
#def Orlik_Solomon_Space(G,N,s): # input is a rank 2 complex reflection group G, a normal reflection subgroup N, and a Galois twist s # h=group_data[iso_type[G.structure_description()]][1] # F=CyclotomicField(h) # z=F.gen() # find the right Galois twist # for r in F.galois_group(): # if r(z)==z^s: # s=r # break # R.<x,y,a,b>=F[] # from sage.rings.invariants.invariant_theory import AlgebraicForm # Ggens=[matrix_double(t.matrix().apply_map(s),s) for t in list(G.simple_reflections())] # Ngens=[matrix_double(G(t).matrix().apply_map(s),s) for t in list(N.gens())] # G=MatrixGroup(Ggens) # N=MatrixGroup(Ngens) VNgens=[G(r).matrix().apply_map(F) for r in list(N.gens())] VN=MatrixGroup(VNgens) I=list(Ideal(VN.invariant_generators()).normal_basis()) VNgens=[matrix_double(G(r).matrix().apply_map(F),s) for r in list(N.gens())] VN=MatrixGroup(VNgens) out=[] for f in I: if f.degree() in eNs: f=f.substitute(x1=x,x2=y) f=AlgebraicForm(4,f.degree()+1,f*(a+b)) f=sum([f.transformed(g).polynomial() for g in VN]) if f!=0: out.append(f) out ︠cf94ae0a-1ae7-45b8-948c-42a9a1ece3bf︠