with(coxeter): read(f_maple): # to get the fake Coxeter number by the three # methods, do: # read(fake_maple): # then # cox_euler(R); # cox_sym(R); # or # cox_recip(R); # where R is the name of a finite Coxeter group legal # for the coxeter package, or one of the following, # some of which are just ad hoc names to expand the repertoire # past the affine groups: # tildeA6 or similar # tildeB6 or similar # tildeC6 or similar # tildeD6 or similar # tildeE6 or similar for all other exceptional affine groups. # ring4e5 means a graph which is a cycle with 5 elements, # one label 4, others 3. (Max label here = 9) # k4_334622 means a complete graph on four vertices # with labels a12=3, a13=3, a14=4, a23=6, a24=2, a34=2. # Although labels of 2 are allowed, the graph must be # connected for this to make sense. Max label is 9 # tildeI7 is a path with 3 vertices, one label 7 and the other 3 # To get the fake exponents, do # fake_exp(R,h_proc) # where h_proc is one of cox_euler, cox_sym or cox_recip. # Every procedure in this file is offered with the following caveat: # They only work for irreducible # Coxeter groups such that all proper parabolics are # either finite or irreducible or both. # To generalize, one would need to implement # irreducibility-testing without relying on the coxeter # package's "base" and "name_of" functions, # which only work for finite groups. # calculates the f_poly (reversed) but leaves # the Coxeter number h as a variable # for an irreducible group of finite type or # my infinite type. # If this is applied to a group with a non-finite parabolic, the parabolic is # required to be irreducible. # This requires the second parameter h_proc, # a procedure for determining a coxeter number. # h_proc could be one of the procedures below f_poly_h_rev:=proc(R,h_proc) local partial_f_poly,f,cm,rk; option remember; cm:=inf_cox_matrix(R); rk:=inf_rank(R); partial_f_poly:=0; f:=proc(list) ; try partial_f_poly:=partial_f_poly+f_poly_rev(name_of(linalg[submatrix](cm,list,list))); catch "not a finite Coxeter group": partial_f_poly:=partial_f_poly+f_poly_rev_inf(linalg[submatrix](cm,list,list),h_proc); end try; end proc; f_on_k_sublists([seq(i,i=1..rk)],rk-1,f); return((h*m+2)*subs(xprime=x,int(partial_f_poly,x=0..xprime,'continuous'))/2+1); end; # calculates the f_poly but leaves h as a variable # for an irreducible group of finite type or # my infinite type. f_poly_h:=proc(R,h_proc) option remember; return(x^inf_rank(R)*subs(x=1/x,f_poly_h_rev(R,h_proc))); end; # The euler characteristic method # for determining h cox_euler:=proc(R) # print(expand(subs(x=-1,factor(f_poly_h(R,cox_euler)))),expand(subs(m=m-1,x=0,factor(f_poly_h(R,cox_euler))))); return(solve(expand(subs(x=-1,factor(f_poly_h(R,cox_euler))))=expand(subs(m=m-1,x=0,factor(f_poly_h(R,cox_euler)))),h)); end; # works on an irreducible Coxeter group, as long as its proper parabolics are all finite # h_proc should be a procedure which finds a fake Coxeter number. f_poly_rev_inf:=proc(R,h_proc) local cm,rk,partial_f_poly,f; option remember; cm:=inf_cox_matrix(R); rk:=inf_rank(R); partial_f_poly:=0; f:=proc(list) ; partial_f_poly:=partial_f_poly+f_poly_rev(name_of(linalg[submatrix](cm,list,list))); end proc; f_on_k_sublists([seq(i,i=1..rk)],rk-1,f); return((h_proc(R)*m+2)*subs(xprime=x,int(partial_f_poly,x=0..xprime,'continuous'))/2+1); end; # The symmetry-based method # for determining h cox_sym:=proc(R) local RmG,QmG,c,f,cm,rk; #option remember; cm:=inf_cox_matrix(R); rk:=inf_rank(R); # calculate RmG RmG:=0; f:=proc(list) ; try RmG:=RmG+cat_formula(name_of(linalg[submatrix](cm,list,list))); catch "not a finite Coxeter group": RmG:=RmG+catalan_inf(linalg[submatrix](cm,list,list),cox_sym); end try; end proc; f_on_k_sublists([seq(i,i=1..rk)],rk-1,f); RmG:=factor(RmG/inf_rank(R)); #print(RmG); # now QmG QmG:=factor(RmG/(m+1)); #print(roots(QmG)); # check that this is a polynomial... if not(type(QmG,polynom(rational,m))) then printf("%a not a polynomial.",R); end if; # find c c:=-2*coeff(QmG,m,inf_rank(R)-3)/coeff(QmG,m,inf_rank(R)-2)/(inf_rank(R)-2); #print(c); if factor(subs(m=c-m,QmG))<>(-1)^inf_rank(R)*QmG then printf("%a not symmetric.",R); end if; return -2/(c+1); end; # finds the fake coxeter number by the reciprocity method. # should only be tried for irreducible groups. # This procedure leaves in the m's, rather than setting them to 1. cox_recip:=proc(R) local partial_cat,f,partial_pos_cat,f_pos,partial_cat_in_ex,f_in_ex,h,cm,rk; option remember; cm:=inf_cox_matrix(R); rk:=inf_rank(R); partial_cat:=0; f:=proc(list) ; try partial_cat:=partial_cat+cat_formula(name_of(linalg[submatrix](cm,list,list))); catch "not a finite Coxeter group": partial_cat:=partial_cat+catalan_inf(linalg[submatrix](cm,list,list),cox_recip); end try; end proc; f_on_k_sublists([seq(i,i=1..rk)],rk-1,f); partial_pos_cat:=0; f_pos:=proc(list) ; try partial_pos_cat:=partial_pos_cat+pos_cat_formula(name_of(linalg[submatrix](cm,list,list))); catch "not a finite Coxeter group": partial_pos_cat:=partial_pos_cat+pos_catalan_inf(linalg[submatrix](cm,list,list),cox_recip); end try; end proc; f_on_k_sublists([seq(i,i=1..rk)],rk-1,f_pos); partial_cat_in_ex:=1; f_in_ex:=proc(list); if (nops(list)0) then try partial_cat_in_ex:=partial_cat_in_ex+pos_cat_formula(name_of(linalg[submatrix](cm,list,list))); catch "not a finite Coxeter group": partial_cat_in_ex:=partial_cat_in_ex+pos_catalan_inf(linalg[submatrix](cm,list,list),cox_recip); end try; end if; end proc; f_on_sublists([seq(i,i=1..rk)],f_in_ex); #print(subs(m=1,(h*(m+1)-2)/(2*rk)*partial_pos_cat+partial_cat_in_ex)); #print(subs(m=1,(h*m+2)/(2*rk)*partial_cat)); return solve((h*(m+1)-2)/(2*rk)*partial_pos_cat+partial_cat_in_ex=(h*m+2)/(2*rk)*partial_cat,h); end; # finds the fake coxeter number by the M(G) method # should only be tried for irreducible groups. cox_mg:=proc(R) local cm,rk,cox,em_gee,Sigma1,Sigma2,i,f; option remember; cm:=inf_cox_matrix(R); rk:=inf_rank(R); Sigma1:=0; f:= proc(list) Sigma1:=Sigma1+mg(linalg[submatrix](cm,list,list)) end proc; f_on_k_sublists([seq(i,i=1..rk)],rk-1,f); Sigma2:=0; f:= proc(list) Sigma2:=Sigma2+mg(linalg[submatrix](cm,list,list)) end proc; for i from 2 to rk-1 do f_on_k_sublists([seq(i,i=1..rk)],i,f); od; em_gee:=Sigma1*Sigma2/(rk*(rk-1)-Sigma1); cox:=2/rk*(em_gee+Sigma2+rk); return(cox); end proc; # Calculates the invariant M(G), or really M(R) for a root system R # For R of finite type, uses the known formulas for the Catalan number, # divided by m then setting m=0. # Otherwise, uses the method given in the paper. mg:=proc(R) local cm,rk,em_gee,Sigma1,Sigma2,i,f; option remember; cm:=inf_cox_matrix(R); rk:=inf_rank(R); try if irreduc(name_of(R)) then em_gee:=rk*subs(m=0,pos_cat_formula(name_of(cm))/m); else em_gee:=0; end if; catch "not a finite Coxeter group": Sigma1:=0; f:= proc(list) Sigma1:=Sigma1+mg(linalg[submatrix](cm,list,list)); #print(mg(linalg[submatrix](cm,list,list))); end proc; f_on_k_sublists([seq(i,i=1..rk)],rk-1,f); Sigma2:=0; f:= proc(list) Sigma2:=Sigma2+mg(linalg[submatrix](cm,list,list)); #print(mg(linalg[submatrix](cm,list,list))); end proc; for i from 2 to rk-1 do f_on_k_sublists([seq(i,i=1..rk)],i,f); od; #print(Sigma1); #print(Sigma2); em_gee:=Sigma1*Sigma2/(rk*(rk-1)-Sigma1); end try; return(em_gee); end proc; # computes the "fake" exponents. # h_proc should be a procedure which finds a fake Coxeter number. fake_exp:=proc(R,h_proc) local cat,rts,exps,r; option remember; cat:=catalan_inf(R,h_proc); rts:=[solve(cat=0,m)]; exps:=[]; for r in rts do exps:=[op(exps),-h_proc(R)*r-1]; od; return(sort(exps)); end; # works on an irreducible Coxeter group, as long as its proper parabolics are all finite # h_proc should be a procedure which finds a fake Coxeter number. catalan_inf:=proc(R,h_proc) local cm,rk,partial_cat,f; option remember; cm:=inf_cox_matrix(R); rk:=inf_rank(R); partial_cat:=0; f:=proc(list) ; try partial_cat:=partial_cat+cat_formula(name_of(linalg[submatrix](cm,list,list))); catch "not a finite Coxeter group": partial_cat:=partial_cat+catalan_inf(linalg[submatrix](cm,list,list),h_proc); end try; end proc; f_on_k_sublists([seq(i,i=1..rk)],rk-1,f); return (h_proc(R)*m+2)/(2*rk)*partial_cat; end; # works on an irreducible Coxeter group, as long as its proper parabolics are all finite pos_catalan_inf:=proc(R,h_proc) local cm,rk,partial_cat,f; option remember; cm:=inf_cox_matrix(R); rk:=inf_rank(R); partial_cat:=0; f:=proc(list) ; partial_cat:=partial_cat+pos_cat_formula(name_of(linalg[submatrix](cm,list,list))); end proc; f_on_k_sublists([seq(i,i=1..rk)],rk-1,f); return (h_proc(R)*(m+1)-2)/(2*rk)*partial_cat; end; # f_on_sublists applies the function f to each sublist of list f_on_sublists:=proc(list,f) local newf, i; if list=[] then f([]); return NULL; end if; newf:=proc(x) f([op(1,list),op(x)]); f(x); end proc; f_on_sublists([seq(op(j,list),j=2..nops(list))],newf); return NULL; end; # f_on_k_sublists applies the function f to each k-sublist of list f_on_k_sublists:=proc(list,k,f) local newf, i; if list=[] then if k=0 then f([]); end if; return NULL; end if; newf:=proc(x) f([op(1,list),op(x)]); end proc; f_on_k_sublists([seq(op(j,list),j=2..nops(list))],k,f); f_on_k_sublists([seq(op(j,list),j=2..nops(list))],k-1,newf); return NULL; end; # gives the coxeter matrix inf_cox_matrix:=proc(R) option remember; if type(R, 'array') then return R; end if; if substring(R,1..5)= tilde then return apply(cat(substring(R,6..6),tilde),convert(substring(R,7..length(R)),decimal,10)); elif substring(R,1..4)= ring then return ring(convert(substring(R,7..length(R)),decimal,10),convert(substring(R,5..5),decimal,10)); elif substring(R,1..2)= k4 then return k4(convert(substring(R,4..4),decimal,10),convert(substring(R,5..5),decimal,10), convert(substring(R,6..6),decimal,10),convert(substring(R,7..7),decimal,10), convert(substring(R,8..8),decimal,10),convert(substring(R,9..9),decimal,10)); else return(cox_matrix(R)); end if; end; # gives the inf_rank:=proc(R) option remember; if type(R, 'array') then return linalg[trace](R); end if; if substring(R,1..6)=tildeI then return 3; elif substring(R,1..2)= k4 then return 4; elif substring(R,1..5)= tilde then return convert(substring(R,7..length(R)),decimal,10)+1; elif substring(R,1..4)= ring then return convert(substring(R,7..length(R)),decimal,10); else return(rank(R)); end if; end; #defining the affine groups as Coxeter matrices. # recall that the rank will be one greater than the "n" # for n>0 although n=1 won't work in the "fake" setup. Atilde:=proc(n) if n<1 then error("illegal group"); end if; if n=1 then return array([[1,infinity],[infinity,1]]); end if; return array(1..n+1,1..n+1,[seq([seq(Atilde_entry(n,i,j),j=1..n+1)],i=1..n+1)]); end; # for n>1. Ctilde:=proc(n) if n<2 then error("illegal group"); end if; return array(1..n+1,1..n+1,[seq([seq(Ctilde_entry(n,i,j),j=1..n+1)],i=1..n+1)]); end; # for n>2. Btilde:=proc(n) if n<3 then error("illegal group"); end if; return array(1..n+1,1..n+1,[seq([seq(Btilde_entry(n,i,j),j=1..n+1)],i=1..n+1)]); end; # for n>3. Dtilde:=proc(n) if n<4 then error("illegal group"); end if; return array(1..n+1,1..n+1,[seq([seq(Dtilde_entry(n,i,j),j=1..n+1)],i=1..n+1)]); end; Etilde:=proc(n) if n=6 then return array(1..n+1,1..n+1, [ [1,2,3,2,2,2,2], [2,1,2,3,2,2,3], [3,2,1,3,2,2,2], [2,3,3,1,3,2,2], [2,2,2,3,1,3,2], [2,2,2,2,3,1,2], [2,3,2,2,2,2,1] ]); elif n=7 then return array(1..n+1,1..n+1, [ [1,2,3,2,2,2,2,3], [2,1,2,3,2,2,2,2], [3,2,1,3,2,2,2,2], [2,3,3,1,3,2,2,2], [2,2,2,3,1,3,2,2], [2,2,2,2,3,1,3,2], [2,2,2,2,2,3,1,2], [3,2,2,2,2,2,2,1] ]); elif n=8 then return array(1..n+1,1..n+1, [ [1,2,3,2,2,2,2,2,2], [2,1,2,3,2,2,2,2,2], [3,2,1,3,2,2,2,2,2], [2,3,3,1,3,2,2,2,2], [2,2,2,3,1,3,2,2,2], [2,2,2,2,3,1,3,2,2], [2,2,2,2,2,3,1,3,2], [2,2,2,2,2,2,3,1,3], [2,2,2,2,2,2,2,3,1] ]); else error("illegal group"); end if; end; Ftilde:=proc(n) if n=4 then return array(1..n+1,1..n+1, [ [1,3,2,2,2], [3,1,4,2,2], [2,4,1,3,2], [2,2,3,1,3], [2,2,2,3,1] ]); else error("illegal group"); end if; end; Gtilde:=proc(n) if n=2 then return array(1..n+1,1..n+1, [ [1,6,2], [6,1,3], [2,3,1] ]); else error("illegal group"); end if; end; # this is NOT an affine example, # and the n means a label, not a rank. # This is a path with 3 vertices, one label n, the other 3. Itilde:=proc(n) return array(1..3,1..3, [ [1,n,2], [n,1,3], [2,3,1] ]); end; # a non-affine example. # Gives a cycle of size s with one label l, others 3. ring:=proc(s,l) if s<3 then error("illegal group"); end if; return array(1..s,1..s,[seq([seq(ring_entry(s,l,i,j),j=1..s)],i=1..s)]); end; # the complete graph on [4] with labels # a12, a13, a14, a23, a24, a34 # k4:=proc(a12,a13,a14,a23,a24,a34) return array(1..4,1..4,[[1,a12,a13,a14],[a12,1,a23,a24],[a13,a23,1,a34],[a14,a24,a34,1]]); end; # helpers for determining entries of the Coxeter matrices Atilde_entry:=proc(n,i,j) if i=j then return 1; elif abs(i-j)=1 then return 3; elif {i,j}={1,n+1} then return 3; else return 2; end if; end; Ctilde_entry:=proc(n,i,j) if i=j then return 1; elif {i,j}={1,2} then return 4; elif {i,j}={n,n+1} then return 4; elif abs(i-j)=1 then return 3; else return 2; end if; end; Btilde_entry:=proc(n,i,j) if i=j then return 1; elif {i,j}={1,2} then return 4; elif {i,j}={n,n+1} then return 2; elif {i,j}={n,n-1} then return 3; elif {i,j}={n-1,n+1} then return 3; elif abs(i-j)=1 then return 3; else return 2; end if; end; Dtilde_entry:=proc(n,i,j) if i=j then return 1; elif {i,j}={1,2} then return 2; elif {i,j}={1,3} then return 3; elif {i,j}={2,3} then return 3; elif {i,j}={n,n+1} then return 2; elif {i,j}={n,n-1} then return 3; elif {i,j}={n-1,n+1} then return 3; elif abs(i-j)=1 then return 3; else return 2; end if; end; # helpers for determining entries of the Coxeter matrices ring_entry:=proc(s,l,i,j) if i=j then return 1; elif abs(i-j)=1 then return 3; elif {i,j}={1,s} then return l; else return 2; end if; end; # returns the catalan number from the product formula cat_formula:=proc(R) local cat,expo,name,first; option remember; if rank(R)=0 then return 1; end if; if irreduc(name_of(R)) then cat:=1; for expo in exponents(R) do cat:=cat*(m*cox_number(R)+expo+1)/(expo+1); od; return cat; else name:=name_of(R); first:=op(1,op(2,factors(name))); return (cat_formula(op(1,first))^op(2,first))*cat_formula(name/op(1,first)^op(2,first)); end if; end; # returns the catalan number from the product formula pos_cat_formula:=proc(R) local cat,expo,name,first; option remember; if rank(R)=0 then return 1; end if; if irreduc(name_of(R)) then cat:=1; for expo in exponents(R) do cat:=cat*(m*cox_number(R)+expo-1)/(expo+1); od; return cat; else name:=name_of(R); first:=op(1,op(2,factors(name))); return (pos_cat_formula(op(1,first))^op(2,first))*pos_cat_formula(name/op(1,first)^op(2,first)); end if; end;