# # Procedures for testing the validity of the database of matrix models: # # checkreps - verify all models in the database for W(R) # checkone - confirm that a list of matrices is a matrix model for W(R) # checktraces - confirm that a rep'n of W(R) has the correct traces # classtest - certify a set of "discriminating" conjugacy classes read `coxeter2.4v.txt`; withcoxeter(): read sparseops; read unpack; if `+`(0)=0 then # we are using Maple V.4 or later myspace:=proc() kernelopts(bytesalloc) end else # we don't have to deal with the latest "improvements" myspace:=proc() 4*status[2] end fi; # checkreps - verify all models in the database for W(R) # # After the user loads one of the files of models via a read command, # checkreps(R) will unpack each of the orthogonal and rational seminormal # models for W(R) in that file, and use 'checkone' and 'checktraces' to # verify that they obey the Coxeter relations and have the right character. # Copious information about the time cost of each test is lprinted. # After the i-th model has been tested, a line of the form "i, N, t, sp" # is printed, where N is the dimension, t is the amount of time used to # test the i-th model, and sp is the amount of RAM allocated (in bytes). # To save time, only a subset of the character values are checked--by # default, only those corresponding to para-Coxeter classes. To specify # an alternate set of classes, supply a sublist of [1,2,...,m] (where m is # the number of conjugacy classes of W(R)) as a second argument. # Use coxeter[class_rep](R) to see the listing of conjugacy classes. # The first step in this program is to run 'classtest' to see if the chosen # list of conjugacy classes is sufficiently large to uniquely identify the # irreducible characters of W(R). If this test fails, no further checking # is done and an ERROR is generated. # If any of the models fails one of the integrity checks, an ERROR is # generated and the program halts immediately. # WARNING: testing the orthogonal models for E8 takes a long time. # # Uncomment the following line to omit testing of the orthogonal models: #seminormal_only:=true; checkreps:=proc(R) local n,st,st0,st00,a,cc,ct,i; interface(quiet=true); st00:=time(); n:=coxeter['rank'](R); if not assigned(Rep[n]) then ERROR(`load models data first`) elif nargs>1 then cc:=args[2] else cc:=coxeter['class_rep'](R); cc:=[seq([i,cc[i]],i=1..nops(cc))]; cc:=map(proc(x) if nops(x[2])=nops({op(x[2])}) then x[1] fi end,cc); fi; ct:=coxeter['irr_chars'](R); st:=time(); if classtest(R,cc) then lprint(`class list is sufficient`,time()-st); printf(`\n`) else ERROR(`insufficent classes to detect irreps; try a different list`) fi; for i to nops(ct) do st0:=time(); if not seminormal_only=true then st:=time(); a:=unpack(i,n); lprint(`orthogonal unpacking`,time()-st); st:=time(); checkone(a,R); lprint(`orthogonal checking`,time()-st); fi; st:=time(); a:=unpack(i,n,'semi'); lprint(`seminormal unpacking`,time()-st); st:=time(); checkone(a,R); lprint(`seminormal checking`,time()-st); st:=time(); checktraces(a,ct[i],R,cc); lprint(`character checking`,time()-st); print(i,nops(a[1]),time()-st0,myspace()); od; interface(quiet=false); R,time()-st00,myspace(); end; # checkone - confirm that a list of matrices is a matrix model for W(R) # # If rep is an alleged matrix model for W(R) (orthogonal or seminormal), # in the format produced by the 'unpack' function, checkone(rep,R) will # verify that the generators satisfy the Coxeter relations of W(R). # In the orthogonal case, also check that the matrices are orthogonal. # In the seminormal case, also check that the matrices preserve the correct # diagonal form (the n+1-th matrix in the given list of matrices). checkone:=proc(rep,R) local n,N,m,j,k,v,fl,f; n:=coxeter['rank'](R); m:=coxeter['cox_matrix'](R); if nops(rep)=n then fl:=NULL else fl:='semi' fi; N:=nops(rep[1]); v:=[seq(cat('e',j),j=1..N)]; for j to n do f:=braid_eqns(1,fast_prod(rep[j],rep[j]),v,fl); if simplify(f,'sqrt')<>{0} then ERROR(cat(`not involution `,j)) fi; if fl<>NULL then f:=fast_prod(rep[j],rep[n+1]) else f:=rep[j] fi; if not is_sym(f) then ERROR(cat(`does not preserve form `,j)) fi; for k to j-1 do f:=braid_eqns(m[j,k],rep[j],rep[k],fl); if simplify(f,'sqrt')<>{0} then ERROR(cat(`bad braid `,j,` `,k)) fi; od od; true end; # checktraces - confirm that a rep'n of W(R) has the correct traces # # If rep is a rational matrix model for W(R), given as a list of matrices # representing the generators (in the format produced by 'unpack'), and f # is a character of W(R) (a list of traces), checktraces(rep,f,R) will # verify that the character of 'rep' is f. # If a fourth argument L is supplied, where L is a sublist of [1,2,...,m] # (m = number of conjugacy classes of W(R)), then only the traces on # conjugacy classes indexed by L are tested. # Use coxeter[class_rep](R) to see the listing of conjugacy classes. # We do not assume that the model is hereditary, nor that the ordering of # simple reflections is graceful: traces are computed naively. checktraces:=proc(rep,f,R) local cr,cc,j,w,k,tr; cr:=coxeter['class_rep'](R); if nargs>3 then cc:=args[4] else cc:=[$1..nops(f)] fi; for j in cc do w:=cr[j]; if nops(w)=0 then tr:=nops(rep[1]) else tr:=rep[w[1]]; for k from 2 to nops(w) do tr:=fast_prod(tr,rep[w[k]]) od; tr:=convert([seq(coeff(tr[k],cat('e',k)),k=1..nops(tr))],`+`); fi; if f[j]<>tr then ERROR(cat(`wrong trace at class `,j)) fi od; true end; # classtest - certify a set of "discriminating" conjugacy classes # # classtest(R,cc) uses linear programming methods to test whether a # subset of the conjugacy classes of W(R) are sufficient to distinguish # every irreducible character of W(R) from among all characters of W(R). # In other words, suppose that f and g are known to be characters of # representations of W(R), and that f is irreducible. If the values of # of f and g agree on a particular subset of conjugacy classes, must f=g? # The set of conjugacy classes is specified as a sublist cc of [1,...,m], # where m is the number of conjugacy classes of W(R). # Use coxeter[class_rep](R) to see the listing of conjugacy classes. # If cc is omitted, the default is to use the list of para-Coxeter classes. # Add the optional argument 'verbose' to see the list of irreps of W(R) # that fail to be uniquely determined by the chosen conjugacy classes. # # Note: for A_n, B_n (n odd), D_n, E6, E7, E8, the para-Coxeter classes # are sufficient, but there can be much smaller discriminating sets. classtest:=proc(R) local N,ct,cc,i,j,f,c,lp,dims,flag; flag:=-1; N:=nargs; if args[N]='verbose' then flag:=0; N:=N-1 fi; ct:=coxeter['irr_chars'](R); if N>1 then cc:=args[2] else cc:=coxeter['class_rep'](R); cc:=[seq([j,cc[j]],j=1..nops(cc))]; cc:=map(proc(x) if nops(x[2])=nops({op(x[2])}) then x[1] fi end,cc); fi; dims:=[seq([j,ct[j][1]],j=1..nops(ct))]; f:={seq(convert([seq(c[j]*ct[j][i],j=1..nops(ct))],`+`)=0,i=cc)}; for i to nops(ct) do lp:=map(proc(x,y) if x[2]>y then x[1] fi end,dims,ct[i][1]); lp:=subs({seq(c[j]=0,j=lp),c[i]=-1},f); lp:=traperror(simplex['feasible'](lp,NONNEGATIVE)); # trap a bug in V.3 if lp=lasterror and lp<>'infeasible' then ERROR(lasterror) elif lp<>lasterror and lp then if flag<0 then RETURN(false) else flag:=flag+1; lprint(cat(`irrep `,i,` fails the classtest`)) fi; fi; od; evalb(flag<1) end;