One Hat Cyber Team
Your IP :
216.73.216.115
Server IP :
194.44.31.54
Server :
Linux zen.imath.kiev.ua 4.18.0-553.77.1.el8_10.x86_64 #1 SMP Fri Oct 3 14:30:23 UTC 2025 x86_64
Server Software :
Apache/2.4.37 (Rocky Linux) OpenSSL/1.1.1k
PHP Version :
5.6.40
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
usr
/
share
/
Macaulay2
/
View File Name :
WeylGroups.m2
-- -*- coding: utf-8 -*- -- licensed under GPL, any version newPackage( "WeylGroups", Version => "0.5.3", Date => "October 15, 2022", Authors => { {Name => "Baptiste Calmès", HomePage => "http://bcalmes.perso.math.cnrs.fr/"}, {Name => "Viktor Petrov"} }, Headline => "root systems and Weyl groups", Keywords => {"Lie Groups and Lie Algebras"}, AuxiliaryFiles => true, PackageExports => {"Graphics"}, DebuggingMode => false) -- Put here the name of functions that should be visible to users export{ "RootSystem", "cartanMatrix", "rootSystem", "rootSystemA", "rootSystemB", "rootSystemC", "rootSystemD", "rootSystemE", "rootSystemF4", "rootSystemG2", "Weight", "weight", "Root", "isPositiveRoot", "isRoot", "addRoots", "numberOfPositiveRoots", "halfSumOfRoots", "reflect", "simpleRoot", "rootCoefficients", "WeylGroupElement", "reduce", "reducedDecomposition", "isReduced", "coxeterLength", "longestWeylGroupElement", "underBruhat", "aboveBruhat", "isLtBruhat", "intervalBruhat", "positiveRoots", "reflection", "scalarProduct", "eval", "isReflection", "whoseReflection", "listWeylGroupElements", "neutralWeylGroupElement", "Parabolic", "parabolic", "WeylGroupLeftCoset", "WeylGroupRightCoset", "WeylGroupDoubleCoset", "minimalRepresentative", "isMinimalRepresentative", "DynkinDiagram", "dynkinDiagram", "connectedComponents", "endVertices", "dynkinType", "DynkinType", "dynkinExponents", "HasseDiagram", "HasseGraph", "hasseDiagramToGraph", "hasseGraphToPicture", "storeHasseGraph", "loadHasseGraph", "poincareSeries" } -- Variables that can be modified by the user exportMutable{ } -- Package code --Defining the class of root systems RootSystem = new Type of MutableHashTable --Cartan matrix of a root system cartanMatrix = method() protect CartanMatrixTr protect RootSystemRank cartanMatrix(RootSystem) := (R) -> transpose R.CartanMatrixTr --rank of a root system rank(RootSystem) := (R) -> R.RootSystemRank --Defining equality of root systems (maybe we should also test the lengths of the roots?) RootSystem == RootSystem := (R1, R2) -> R1.CartanMatrixTr == R2.CartanMatrixTr protect ReducedDecompositions protect WeylGroupList protect Reflections protect PositiveRoots protect RootNorms protect CartanMatrixTrInv --Defining the direct sum of two root systems RootSystem ++ RootSystem := (R1, R2) -> ( new RootSystem from { RootSystemRank=>R1.RootSystemRank+R2.RootSystemRank, CartanMatrixTr=>R1.CartanMatrixTr++R2.CartanMatrixTr, CartanMatrixTrInv=>R1.CartanMatrixTrInv++R2.CartanMatrixTrInv, RootNorms=>R1.RootNorms | R2.RootNorms, PositiveRoots=>set {}, -- we can do more efficiently if R1.PositiveRoots and R2.PositiveRoots are already computed Reflections=>new HashTable from {}, WeylGroupList=>{}, ReducedDecompositions=>new MutableHashTable from {} } ) --Defining the class of Dynkin diagrams as a BasicList of elements {{1,3},{},{},{}} representing a vertex. Inside, the lists are the lists of edges towards another vertex, of resp. simple edges, double towards smaller, double towards greater, triple. Of course, most of the time most will be empty. DynkinDiagram = new Type of BasicList --Finding rank of Dynkin diagram rank(DynkinDiagram):= (D) -> #D --(internal function) Finding the labels of the neighbors of the i-th vertex in a Dynkin diagram neighbors = method() neighbors(DynkinDiagram,ZZ) := (D,i) -> set join(D#(i-1)#0,D#(i-1)#1,D#(i-1)#2,D#(i-1)#3,D#(i-1)#4) --(internal function) Reindexing elements according to a list to obtain a coherent Dynkin diagram reindex=(D,L)-> ( T:=new HashTable from for i from 0 to #L-1 list L#i => i+1; new DynkinDiagram from apply(D,x->applyTable(x,z->T#z)) ) --Finding the connected components of a Dynkin diagram connectedComponents=method() connectedComponents(DynkinDiagram) := (D) -> ( vertcompolist:={}; --will contain the sets of vertices of the connected components for i from 1 to #D do ( verticompo:=set{i}; --set of vertices of connected component of i vertnoticompolist:={}; --list of other connected components vertices sets for j from 0 to #vertcompolist-1 do if neighbors(D,i)*vertcompolist#j =!=set{} then ( verticompo=vertcompolist#j+verticompo; ) else ( vertnoticompolist=append(vertnoticompolist,vertcompolist#j); ); vertcompolist=append(vertnoticompolist,verticompo); ); vertcompolist=apply(vertcompolist,toList); --transform the connected components into lists vertcompolist=apply(vertcompolist,sort); --sort each of these lists dyncompolist:=applyTable(vertcompolist,i->D#(i-1)); --make a list with the edge data of the corresponding vertices apply(dyncompolist,vertcompolist,reindex) ) --(internal function) Returning the position (in the list) of the small side of a double edge of an irreducible Dynkin diagram if it has one. smallSideDoubleEdge= (D)-> ( for i from 0 to #D-1 do if (D#i#2 !={}) then return({i}); return({}); ) --(internal function) Returning the position (in the list) of the big side of a double edge of an irreducible Dynkin diagram if it has one. bigSideDoubleEdge= (D)-> ( for i from 0 to #D-1 do if (D#i#1 !={}) then return({i}); return({}); ) --(internal function) Testing if an irreducible Dynkin diagram has a triple edge isG2= (D)-> ( for i from 0 to #D-1 do if (D#i#3 !={} or D#i#4 !={}) then return(true); return(false); ) --(internal function) Returning the number (ie at least 1) of the branch point of an irreducible Dynkin diagram if it has one branchPoint= (D)-> ( for i from 0 to #D-1 do if (#(D#i#0)>2) then return({i+1}); return({}); ) --(internal function) Says whether the vertex at position i (as in a list) in the Dynkin diagram D is an end point. isEndPoint=(D,i)-> ( (#(D#i#0)+#(D#i#1)+#(D#i#2)<2) ) --Finds the indices all end points of a Dynkin diagram D endVertices=method() endVertices(DynkinDiagram) := (D) -> ( set for i from 0 to #D-1 list if (#(D#i#0)+#(D#i#1)+#(D#i#2)<2) then i+1 else continue ) --Defining the class of Dynkin types. DynkinType = new Type of BasicList --Defining the sum (disjoint union) of two Dynkin types DynkinType ++ DynkinType := (T1,T2) -> new DynkinType from join(T1,T2) --Defining the equality of two Dynkin types DynkinType == DynkinType := (T1,T2) -> (sort toList T1) === (sort toList T2) --(internal function) Finding the type of a connected Dynkin diagram (it should not be empty) connectedDynkinType=method() connectedDynkinType(DynkinDiagram):=(D)-> ( if isG2(D) then {"G",2} else ( brp:=branchPoint(D); if brp=={} then ( sm:=smallSideDoubleEdge(D); bg:=bigSideDoubleEdge(D); if sm=={} and bg=={} then {"A",rank(D)} else ( if isEndPoint(D,sm#0) then {"B",rank(D)} else if isEndPoint(D,bg#0) then {"C", rank(D)} else {"F",4} ) ) else ( if #(endVertices(D)*neighbors(D,brp#0))>1 then {"D",rank(D)} else {"E", rank(D)} ) ) ) --Finding the type of any Dynkin diagram. The result is a list of irreducible types. dynkinType = method() dynkinType(DynkinDiagram) := (D) -> new DynkinType from sort apply(connectedComponents(D),connectedDynkinType) dynkinType(RootSystem) := (R) -> dynkinType(dynkinDiagram(R)) dynkinType(BasicList) := (L) -> ( for i from 0 to #L-1 do if instance(L#i#1,ZZ)==false or L#i#1<1 then error "Second elements must be positive integers."; mylist:={}; for i from 0 to #L-1 do ( H:=L#i#0; if H == "A" then mylist=append(mylist,{"A", L#i#1}) else if H == "B" then (if L#i#1==1 then mylist=append(mylist,{"A", 1}) else mylist=append(mylist,{"B", L#i#1})) else if H == "C" then (if L#i#1==1 then mylist=append(mylist,{"A", 1}) else if L#i#1==2 then mylist=append(mylist,{"B", 2}) else mylist=append(mylist,{"C", L#i#1})) else if H == "D" then (if L#i#1==1 then mylist=append(mylist,{"A",1}) else if L#i#1==2 then mylist=join(mylist,{{"A", 1},{"A",1}}) else if L#i#1==3 then mylist=append(mylist,{"A",3}) else mylist=append(mylist,{"D", L#i#1})) else if H == "E" then (if L#i#1<9 and L#i#1>5 then mylist=append(mylist,{"E",L#i#1}) else error "The type E can only have rank 6,7 or 8.") else if H == "F" then (if L#i#1==4 then mylist=append(mylist,{"F",4}) else error "The type F can only have rank 4.") else if H == "G" then (if L#i#1==2 then mylist=append(mylist,{"G",2}) else error "The type G can only have rank 2.") else error "The first elements must be strings containing one letter among A, B, C, D, E, F or G." ); new DynkinType from mylist ) --exponents of a DynkinType (as listed in Bourbaki for irreducibles) dynkinExponents=method() dynkinExponents(DynkinType):= (D) -> ( for i from 0 to #D-1 list ( if D#i#0=="A" then toList (1..D#i#1) else if D#i#0=="B" or D#i#0=="C" then apply(toList (1..D#i#1),x->2*x-1) else if D#i#0=="D" then append(apply(toList(1..D#i#1-1),x->2*x-1),D#i#1-1) else if D#i#0=="G" then {1,5} else if D#i#0=="F" then {1,5,7,11} else if D#i#0=="E" then (if D#i#1==6 then {1,4,5,7,8,11} else if D#i#1==7 then {1,5,7,9,11,13,17} else if D#i#1==8 then {1,7,11,13,17,19,23,29} ) ) ) --Finding the Cartan matrix of a Dynkin diagram. --cartanMatrix(DynkinDiagram) := (D) -> --Finding the Dynkin diagram of a root system dynkinDiagram = method() dynkinDiagram(RootSystem) := (R) -> ( new DynkinDiagram from for i from 0 to R.RootSystemRank-1 list ( simp:={}; sdoub:={}; bdoub:={}; strip:={}; btrip:={}; for j from 0 to R.RootSystemRank-1 when #simp+2*(#sdoub+#bdoub)+3*#(strip+btrip)<3 do ( if R.CartanMatrixTr_(i,j) != 0 then ( if R.CartanMatrixTr_(j,i) == -1 then ( if R.CartanMatrixTr_(i,j) == -1 then simp=append(simp,j+1) else if R.CartanMatrixTr_(i,j) == -2 then bdoub={j+1} else if R.CartanMatrixTr_(i,j) == -3 then (btrip={j+1}; break) ) else if R.CartanMatrixTr_(j,i) == -2 then sdoub={j+1} else if R.CartanMatrixTr_(j,i) == -3 then (strip={j+1}; break) ) ); {simp,sdoub,bdoub,strip,btrip} ) ) --(internal function) Defining the root System of a DynkinType. rootSystemIrred = (Tirr) -> ( if Tirr#0==="A" then rootSystemA(Tirr#1) else if Tirr#0==="B" then rootSystemB(Tirr#1) else if Tirr#0==="C" then rootSystemC(Tirr#1) else if Tirr#0==="D" then rootSystemD(Tirr#1) else if Tirr#0==="E" then rootSystemE(Tirr#1) else if Tirr#0==="F" then rootSystemF4 else if Tirr#0==="G" then rootSystemG2 ) rootSystem = method() rootSystem(DynkinType):=(T)-> ( if #T<1 then new RootSystem from {RootSystemRank => 0, CartanMatrixTr =>(matrix{{1}})^{}_{} ,CartanMatrixTrInv => (matrix{{1_QQ}})^{}_{} , RootNorms=>{}, PositiveRoots => set{}, Reflections => new HashTable from {}, WeylGroupList => {}, ReducedDecompositions => new MutableHashTable from {}} else ( R:=rootSystemIrred(T#0); for i from 1 to #T-1 do R=R++rootSystemIrred(T#i); R ) ) --Constructing the root system of a Dynkin diagram rootSystem(DynkinDiagram) := (D) -> ( if #D==0 then ( new RootSystem from { RootSystemRank => 0, CartanMatrixTr => (matrix{{1}})^{}_{}, CartanMatrixTrInv => (matrix{{1_QQ}})^{}_{}, RootNorms=>{}, PositiveRoots => set{}, Reflections => new HashTable from {}}, WeylGroupList => {}, ReducedDecompositions => new MutableHashTable from {} ) else ( M:=matrix for i from 0 to #D-1 list for j from 0 to #D-1 list ( if i==j then 2 else if (set(D#i#0))#?(j+1) then -1 else if (set(D#i#1))#?(j+1) then -1 else if (set(D#i#2))#?(j+1) then -2 else if (set(D#i#3))#?(j+1) then -1 else if (set(D#i#4))#?(j+1) then -3 else 0 ); --we are now trying to find the roots that are not of length one (it means they are on the big side of a multiple edge or connected by simple edges to such a thing) length1set:=set{}; --the ones of squared length 1 length2set:=set{}; --the ones of squared length 2 length3set:=set{}; --the ones of squared length 3 smallend:=set{}; --ends at the small side of a double edge or a triple edge for i from 0 to #D-1 do --putting the obvious ones where they belong ( if #(D#i#4)>0 then (length1set=length1set+set{i+1}; smallend=smallend+set{i+1}) else if #(D#i#3)>0 then length3set=length3set+set{i+1} else if #(D#i#2)>0 then (length1set=length1set+set{i+1}; smallend=smallend+set{i+1}) else if #(D#i#1)>0 then length2set=length2set+set{i+1} else if #(D#i#0)==0 then length1set=length1set+set{i+1} else if #(D#i#0)==3 then length1set=length1set+set{i+1} ); theends:=toList(endVertices(D)) - (length2set + length3set + smallend); --ends of the diagram still to be treated todecide:=set{}; --connected set whose length we want to find at the current step i:=0; startend:=0; while #theends>0 do ( todecide=set{theends#0}; startend=set{theends#0}; i=D#((theends#0)-1)#0#0; --next point in the simple edge chain. It has to exist and be unique because we start from an end not isolated or it would already have been removed as an obvious point while true do ( if length1set#?i then (length1set= length1set + todecide; theends = theends - startend; break) else if length2set#?i then ( length2set= length2set + todecide; theends = theends - startend; break ) else if (set(theends))#?i then ( length1set= length1set + todecide + set{i}; theends = theends - startend -set{i}; break ) else ( todecide=todecide + set{i}; i=((D#(i-1)#0)-todecide)#0 ) ) ); new RootSystem from { RootSystemRank => #D, CartanMatrixTr => M, CartanMatrixTrInv => inverse promote(M,QQ), RootNorms => for i from 1 to #D list if length2set#?i then 2 else if length3set#?i then 3 else 1, PositiveRoots => set {}, Reflections => new HashTable from {}, WeylGroupList => {}, ReducedDecompositions => new MutableHashTable from {} } ) ) --Drawing the Dynkin diagram (what do we really want to see?) --draw = method() --draw(DynkinDiagram) := (D)-> --the poincare series of a root system (the characteristic function of the number of Weyl group elements per length) poincareSeries= method() poincareSeries(RootSystem,RingElement):=(R,x)-> ( product apply(dynkinExponents(dynkinType(R)),y->product apply(y,n->(x^(n+1)-1) // (x-1))) ) --number of positive roots numberOfPositiveRoots = method() numberOfPositiveRoots(DynkinType) := (T) -> ( sum toList apply(T,x-> ( if x#0==="A" then (x#1)*((x#1)+1)//2 else if x#0==="B" or x#0==="C" then (x#1)*(x#1) else if x#0==="D" then (x#1)*((x#1)-1) else if x#0==="E" then (if x#1===6 then 36 else if x#1===7 then 63 else 120) else if x#0==="F" then 24 else 6 )) ) numberOfPositiveRoots(RootSystem) := (R) -> numberOfPositiveRoots dynkinType R --Defining the class of weights (expressed as vectors in ZZ^n, the basis consisting in the fundamental weights) Weight = new Type of Vector --Constructor for weights weight=method() weight(RootSystem,BasicList):= (R,L)-> ( if #L != R.RootSystemRank then error "The number of coordinates of the weight vector and the rank of the root system should be equal." else for i in L do if not(instance(i,ZZ)) then error "The weight vector should have integer coefficients."; if #L==0 then new Weight from 0_(ZZ^0) else new Weight from vector L ) weight(RootSystem,Vector):= (R,V)-> ( if rank(class(V)) != R.RootSystemRank then error "The number of coordinates of the weight vector and the rank of the root system should be equal." else for i in entries(V) do if not(instance(i,ZZ)) then error "The weight vector should have integer coefficients."; if rank(class(V))==0 then new Weight from 0_(ZZ^0) else new Weight from V ) --redefining sum of two weights Weight + Weight := (p1,p2) -> new Weight from ((new Vector from p1)+(new Vector from p2)) --redefining difference of two weights Weight - Weight := (p1,p2) -> new Weight from ((new Vector from p1)-(new Vector from p2)) --defining scalar times weight ZZ * Weight := (n,p) -> new Weight from {n*p#0} --defining opposite to a weight - Weight := (p) -> (-1)*p --check whether a weight is a positive root isPositiveRoot = method() isPositiveRoot(RootSystem,Weight) := (R,p) -> (positiveRoots(R))#?(new Root from p) --check whether a weight is a root isRoot = method() isRoot(RootSystem,Weight) := (R,p) -> isPositiveRoot(R,p) or isPositiveRoot(R,-p) --the half-sum of positive roots halfSumOfRoots = method() halfSumOfRoots(RootSystem) := (R) -> ( if R.RootSystemRank>0 then new Weight from vector(toList(R.RootSystemRank:1)) else new Weight from 0_(ZZ^0) ) reflect = method() --reflect a weight with respect to n-th simple root reflect(RootSystem,ZZ,Weight) := (R,n,p) -> ( p-(p_(n-1))*simpleRoot(R,n) ) --do several reflections listed in L reflect(RootSystem,BasicList,Weight) := (R,L,p) -> ( q := p; scan(reverse L,i->q=reflect(R,i,q)); q ) --Defining the class of roots (expressed as appropriate weights) Root = new Type of Weight --Sum of roots: gives a root if it is a root, or a weight if not. addRoots = method() addRoots(RootSystem,Root,Root) := (R,r,q) -> ( s:=(new Weight from r) + (new Weight from q); if isRoot(R,s) then new Root from s else s ) --Preventing scalar multiples on roots ZZ*Root := (n,r) -> if n==1 or n==-1 then new Root from n*new Weight from r else n*new Weight from r --reflect a root with respect to n-th simple root reflect(RootSystem,ZZ,Root) := (R,n,r) -> new Root from reflect(R,n,new Weight from r) --do several reflections listed in L reflect(RootSystem,BasicList,Root) := (R,L,r) -> new Root from reflect(R,L,new Weight from r) --n-th simple root simpleRoot = method() simpleRoot(RootSystem,ZZ) := (R,n) -> ( new Root from (R.CartanMatrixTr)_(n-1) ) --Vector of the coefficients of something at the simple roots rootCoefficients = method() --Vector of the coefficients of a root at the simple roots (integers) rootCoefficients(RootSystem,Root) := (R,r) -> vector(apply(entries(R.CartanMatrixTrInv*r),floor)) --Vector of the coefficients of a weight at the simple roots (rationals) rootCoefficients(RootSystem,Weight) := (R,v) -> (R.CartanMatrixTrInv*v) --the squared norm of a root norm(RootSystem,Root) := (R,r) -> ( x := rootCoefficients(R,r); (sum for i from 0 to rank(R)-1 list x_i*(R.RootNorms)#i*r_i)//2 ) --the scalar product of two weights scalarProduct = method() --the scalar product of the i-th fundamental weight with the j-th scalarProduct(RootSystem,ZZ,ZZ) := (R,i,j) -> ( ((R.CartanMatrixTrInv)_(j-1,i-1))*(R.RootNorms#(j-1))//2 ) --the scalar product of two general weights scalarProduct(RootSystem,Weight,Weight) := (R,u,v) -> ( sum apply(apply(entries((R.CartanMatrixTrInv)*u),entries(v),(x,y)->x*y),R.RootNorms,(x,y)->x*y)//2 ) --the scalar product of the i-th fundamental weight with a general weight scalarProduct(RootSystem,ZZ,Weight) := (R,i,v) -> ( (((R.CartanMatrixTrInv)*v)_(i-1))*(R.RootNorms#(i-1))//2 ) --the dual of a root evaluated at something eval = method() --the dual of the simple root j evaluated at the simple root i eval(RootSystem,ZZ,ZZ) := (R,i,j) -> (R.CartanMatrixTr_(j-1,i-1)) --the dual the j-th simple root evaluated at a weight (no consistency test for the dimension of the Weight, and the root system is not really used). eval(RootSystem,Weight,ZZ) := (R,v,j) -> v_(j-1) --the dual of a root evaluated at the i-th fundamental weight eval(RootSystem,ZZ,Root) := (R,i,r) -> ( floor(2*scalarProduct(R,i,r)//norm(R,r)) ) --the dual of a root evaluated at a weight (which might in particular be a root) eval(RootSystem,Weight,Root) := (R,v,r) -> ( floor(2*scalarProduct(R,v,r)//norm(R,r)) ) --Defining the elements of a Weyl group (expressed as pairs {R,p}, where R is a root system and p=w(rho)) WeylGroupElement = new Type of BasicList --Defining equality of two Weyl group elements WeylGroupElement == WeylGroupElement := (w1,w2) -> (w1#0==w2#0) and (w1#1==w2#1) --Defining action of a Weyl group on weights WeylGroupElement * Weight := (w,p) -> ( reflect(w#0,reducedDecomposition(w),p) ) --Defining action of a Weyl group on roots WeylGroupElement * Root := (w,r) -> new Root from w*(new Weight from r) --Defining product of two Weyl group elements WeylGroupElement * WeylGroupElement := (w1,w2) -> ( if w1#0 =!= w2#0 then error "The arguments should be from the Weyl group of the same root system." else new WeylGroupElement from {w1#0, w1*(w2#1)} ) --Defining inverse to a Weyl group element inverse(WeylGroupElement) := (w) -> reduce(w#0,reverse(reducedDecomposition(w))) --Defining powers of a Weyl group element WeylGroupElement^ZZ := (w,n) -> ( p := halfSumOfRoots(w#0); if n==0 then new WeylGroupElement from {w#0,p} else if (n==1) or (w#1==p) then w else if n>0 then ( t := w^(n//2); if n%2 == 0 then t*t else t*t*w ) else inverse(w)^(-n) ) --the Weyl group element defined by a product of simple reflections reduce = method() reduce(RootSystem,BasicList) := (R,L) -> ( new WeylGroupElement from {R,reflect(R,L,halfSumOfRoots(R))} ) --the (lexicographically least) reduced decomposition of w reducedDecomposition = method() reducedDecomposition(WeylGroupElement) := (w) -> ( if (w#0).ReducedDecompositions#?(w#1) then (w#0).ReducedDecompositions#(w#1) else (w#0).ReducedDecompositions#(w#1)= ( n := rank(w#0); i := 0; while (i<n) and ((w#1)_i>0) do i=i+1; if i==n then {} else prepend(i+1,reducedDecomposition(new WeylGroupElement from {w#0, reflect(w#0,i+1,w#1)})) ) ) --check whether a given decomposition is reduced (relies on l(s_i w)>l(w) equivalent to w(\rho)_i >0 ) isReduced = method () isReduced(RootSystem,BasicList) := (R,L) -> ( b:=true; v:=halfSumOfRoots(R); for i from 1 to #L-1 do ( v=reflect(R,L#(#L-i),v); if v_(L#(#L-i-1)-1)<0 then (b=false; break); ); b ) --check whether the length of the Weyl group element multiplied on the left by the reflection in the list is l(w)+length of list isReduced(BasicList,WeylGroupElement) := (L,w) -> ( b:=true; v:=w#1; for i from 1 to #L do ( if v_(L#(#L-i)-1)<0 then (b=false; break); v=reflect(w#0,L#(#L-i),v); ); b ) --the length of a Weyl group element coxeterLength = method () coxeterLength(WeylGroupElement) := (w) -> #(reducedDecomposition(w)) --the longest Weyl group element longestWeylGroupElement = method() longestWeylGroupElement(RootSystem) := (R) -> ( new WeylGroupElement from {R,-halfSumOfRoots(R)} ) --the neutral Weyl group element neutralWeylGroupElement = method() neutralWeylGroupElement(RootSystem) := (R) -> ( new WeylGroupElement from {R,halfSumOfRoots(R)} ) --set of all positive roots of R positiveRoots = method() positiveRoots(RootSystem) := (R) -> ( if R.RootSystemRank==0 then {} else if #(R.PositiveRoots)==0 then R.PositiveRoots=( L := reducedDecomposition longestWeylGroupElement R; set for i from 0 to #L-1 list reflect(R,take(L,{0,i-1}),simpleRoot(R,L#i)) ) else R.PositiveRoots ) --reflection with respect to a root reflection = method() reflection(RootSystem,Root) := (R,r) -> ( x := rootCoefficients(R,r); new WeylGroupElement from {R,halfSumOfRoots(R) - ((sum for i from 0 to rank(R)-1 list (x_i*((R.RootNorms)#i)))//norm(R,r)) *r} ) --hash table of all reflections allReflections = method() allReflections(RootSystem) := (R) -> ( if #(R.Reflections)==0 then R.Reflections=new HashTable from for r in (toList positiveRoots(R)) list ((reflection(R,r))#1)=>r else R.Reflections ) --check whether a Weyl group element is a reflection... isReflection = method() isReflection(WeylGroupElement) := (w) -> (allReflections(w#0))#?(w#1) --...and find whose reflection it is whoseReflection = method() whoseReflection(WeylGroupElement) := (w) -> (allReflections(w#0))#(w#1) isLtBruhat = method() --Checking whether w1 is less than w2 in the Bruhat order isLtBruhat(WeylGroupElement, WeylGroupElement) := (w1, w2) -> ( if w1#0 =!= w2#0 then error "The arguments should be from the Weyl group of the same root system." else ( n := rank(w2#0); i := 0; while (i<n) and ((w2#1)_i>0) do i=i+1; if i==n then w1==w2 else if (w1#1)_i<0 then isLtBruhat(new WeylGroupElement from {w1#0, reflect(w1#0,i+1,w1#1)}, new WeylGroupElement from {w2#0, reflect(w2#0,i+1,w2#1)}) else isLtBruhat(w1, new WeylGroupElement from {w2#0, reflect(w2#0,i+1,w2#1)}) ) ) --Finding all elements just below w for the Bruhat order underBruhat = method () underBruhat(WeylGroupElement) := (w) -> ( L:=reducedDecomposition(w); M:={}; result:={}; len:=#L; b:=true; u:=local u; --the potential element to keep if it has the right length s:=local s; --simple reflexion to be removed from the reduced dec. of w v:=halfSumOfRoots(w#0); --the end part of the dec. of w, stored as how it acts on the half sum of roots for i from 1 to len do ( s=L#(#L-1); L=drop(L,-1); b=true; u=v; for j from 1 to #L do --testing if the decomposition with the reflexion s removed is reduced ( if u_(L#(#L-j)-1)<0 then (b=false; break); u=reflect(w#0,L#(#L-j),u); ); v=reflect(w#0,{s},v); if b then result=append(result,{new WeylGroupElement from {w#0,u},whoseReflection(new WeylGroupElement from {w#0,reflect(w#0,M,v)})}); M=append(M,s); ); result ) --Finding elements that are below a list of elements (assumed of the same length) --Maybe we should check if all elements in L have the same length and are in the same root system, otherwise, it is not very natural. underBruhat(BasicList):=(L)-> ( result:=new MutableHashTable from {}; U:=local U; for i from 0 to #L-1 do ( U=underBruhat(L#i); --find the elements below this one. for j from 0 to #U-1 do if result#?(U#j#0) then result#(U#j#0)=append(result#(U#j#0),{i,U#j#1}) else result#(U#j#0)={{i,U#j#1}}; ); apply(pairs result,(x,y)->{x,y}) ) --the following is not debugged, it produces a weird output. --underBruhat(BasicList,ZZ):= (L,n) -> -- ( -- if n<=0 then {} -- else -- ( -- L2 := {apply(L,x->{x,{}})}; -- for i from 1 to n do L2=append(L2,underBruhat(apply(L2#(i-1),x->x#0))); -- L2 -- ) -- ) --Finding all elements just above w for the Bruhat order aboveBruhat = method () aboveBruhat(WeylGroupElement) := (w) -> ( w0:=longestWeylGroupElement w#0; apply(underBruhat(w0*w),x->{w0*x#0,x#1}) ) --like underBruhat (see above), but with elements above. aboveBruhat(BasicList):=(L)-> ( result:=new MutableHashTable from {}; U:=local U; for i from 0 to #L-1 do ( U=aboveBruhat(L#i); --find the elements above this one. for j from 0 to #U-1 do if result#?(U#j#0) then result#(U#j#0)=append(result#(U#j#0),{i,U#j#1}) else result#(U#j#0)={{i,U#j#1}}; ); apply(pairs result,(x,y)->{x,y}) ) --the following is not debugged, it produces a weird output. --aboveBruhat(BasicList,ZZ):= (L,n) -> -- ( -- if n<=0 then {} -- else -- ( -- L2 := {apply(L,x->{x,{}})}; -- for i from 1 to n do L2=append(L2,aboveBruhat(apply(L2#(i-1),x->x#0))); -- L2 -- ) -- ) --(internal function) extract elements above given ones in a list of lists produced by apply underBruhat repeatedly extractHasse = (A,P) -> ( newA := {}; mypos := P; l:=#A; smallerlist := local smallerlist; if mypos == {} then ( for i from 0 to #A-1 list {} ) else ( for i from 1 to #A do ( smallerlist = (A#(l-i))_mypos; mypos =sort toList( sum apply(smallerlist,y->set apply(y#1,x->x#0))); --actually this sum is a set union: we are extracting the indices for the next row. newA=prepend( apply(smallerlist,w->{w#0,apply(w#1,x->{position(mypos,y->(y==x#0)),x#1})}), newA); --we replace the references in the current row to the new positions in the next row and we append this current row to our new big list. ); newA ) ) --(internal function) reverse the links in a list of lists describing a Hasse diagram. In the argument, the links point to the previous row, whereas in the output, the links point towards the next row. reverseLinks = (A)-> ( myrow := local myrow; l:=#A; results := {apply(A#(l-1),x->{x#0,{}})}; for i from 2 to l do ( myrow = new MutableList from apply(A#(l-i),x->{x#0,{}}); for j from 0 to #(A#(l-i+1))-1 do ( apply(A#(l-i+1)#j#1, x->(myrow#(x#0) = {myrow#(x#0)#0,append(myrow#(x#0)#1,{j,x#1})})); ); results=prepend(toList(myrow),results) ); results ) --list all elements of the Weyl group of a given length listWeylGroupElements = method() listWeylGroupElements(RootSystem,ZZ) := (R,k) -> ( if k<0 then error "The length should be nonnegative"; n := (numberOfPositiveRoots R)-k; if n<0 then {} else if n<k then ( w := longestWeylGroupElement R; apply(listWeylGroupElements(R,n),x->w*x) ) else ( S := local S; if #(R.WeylGroupList)==0 then R.WeylGroupList = {{halfSumOfRoots R}}; for i from #(R.WeylGroupList)-1 to k-1 do ( S = set {}; apply((R.WeylGroupList)#i, x->( for j from 0 to R.RootSystemRank-1 do if x_j>0 then S = S + set {reflect(R,j+1,x)} )); R.WeylGroupList = append(R.WeylGroupList,toList S); ); apply((R.WeylGroupList)#k,x->new WeylGroupElement from {R,x}) ) ) --Defining the class of parabolic subgroups in a Weyl group, represented by the set of generators Parabolic = new Type of Set --Constructing a parabolic subgroup out of a root system and a set of roots. This just checks that the roots selected have numbers that are less than the rank of the root system. parabolic = method() parabolic(RootSystem,Set) := (R,S) -> ( for i in toList S do if not (instance(i,ZZ) and i>0 and i<=R.RootSystemRank) then error "The indices designating the simple roots in the parabolic need to be integers at least 1 and at most the rank of the root system."; new Parabolic from S ) --equality of parabolics Parabolic == Parabolic := (P1,P2) -> P1===P2 --Finding the Dynkin Diagram of the Levy sugroup of a parabolic sugroup from the Dynkin diagram of the group. dynkinDiagram(DynkinDiagram,Parabolic) := (D,P) -> ( L:=sort(toList P); newdynkin:=for i from 0 to #L-1 list D#((L#i)-1); newdynkin=apply(newdynkin,v->apply(v,x->select(x,i->P#?i))); --suppresses edges towards vertices not in P reindex(newdynkin,L) ) --the poincare series of a parabolic of a root system (the characteristic function of the number of elements per length in the set of minimal representents of the Weyl group modulo the root systemp of the parabolic. poincareSeries(RootSystem,Parabolic,RingElement):=(R,P,x)-> ( poincareSeries(R,x) // poincareSeries(rootSystem(R,P),x) ) --Defining the class of Hasse diagrams as BasicList of {{w,{{1,v1},{3,v3}...}},...} representing a row of a Hasse diagram, with vertices w in the Weyl group and the links to the next row, together with the reflections of the link. HasseDiagram = new Type of BasicList --(not used anymore, another algorithm below) compute the interval between two Weyl group elements for the Bruhat order, i.e. the set of elements w such that u<=w<=v together with the reflections involved. This is done by finding successively the "cone" of all elements i steps below u and above v until these two cones can intersect (have a row in the same length). Whether we go down from u or up from v is decided at each iteration (variable fromtop) according to what seems to have the least number of elements in the last computed row. Then, when the two computed cones arrive at a length where they can intersect, one computes if they actually do, and one goes back up (and down) using their intersection finding all elements above this intersection or below it that are in the cones. --intervalBruhat = method() --intervalBruhat(WeylGroupElement,WeylGroupElement):= (u,v) -> -- ( -- if u#0 =!= v#0 then error "The two elements must live in the same Weyl group." -- else -- ( -- lendiff := coxeterLength(v)-coxeterLength(u); -- if lendiff<0 then new HasseDiagram from {} -- else -- ( -- fromtop := true; -- toppart :=new MutableList from {{{v,{}}}}; -- topindex := 0; -- bottompart :=new MutableList from {{{u,{}}}}; -- bottomindex := 0; -- pos:=local pos; -- while lendiff - topindex - bottomindex >0 do -- ( -- if fromtop then -- ( -- toppart#(topindex+1)=underBruhat(apply(toppart#topindex,x->x#0)); -- topindex=topindex+1; -- ) -- else -- ( -- bottompart#(bottomindex+1)=aboveBruhat(apply(bottompart#bottomindex,x->x#0)); -- bottomindex=bottomindex+1; -- ); -- fromtop = (#(toppart#topindex)<=#(bottompart#bottomindex)); -- ); -- toprow := apply(toppart#topindex,x->x#0); -- bottomrow := apply(bottompart#bottomindex,x->x#0); -- poslist :={}; -- newbottomrow := {}; -- for i from 0 to #bottomrow-1 do -- ( -- pos = position(toprow,x->(x==bottomrow#i)); -- if pos =!= null then -- ( -- poslist = append(poslist,pos); -- newbottomrow = append(newbottomrow,bottompart#bottomindex#i); -- ) -- ); -- bottompart#bottomindex = newbottomrow; --replacing the top row of the bottom cone by the elements that are also in the bottom row of the top cone. -- newbottompart := extractHasse(bottompart,toList(0..#(bottompart#bottomindex)-1)); -- newtoppart := extractHasse(toppart,poslist); -- newtoppart = drop(reverseLinks(newtoppart),-1); -- new HasseDiagram from newtoppart|reverse(newbottompart) -- ) -- ) -- ) --compute the interval between two Weyl group elements for the Bruhat order, i.e. the set of elements w such that u<=w<=v together with the reflections involved. It starts from the top element v, and recursively generates elements under, but checks for each element that it is indeed above u by using isLtBruhat. If it is not, it is discarded right away. The advantage over intervalBruhat is that lots of elements are discarded, but on the other hand it takes some time to apply isLtBruhat on every element. intervalBruhat = method() intervalBruhat(WeylGroupElement,WeylGroupElement):= (u,v) -> ( if u#0 =!= v#0 then error "The two elements must live in the same Weyl group." else ( lendiff := coxeterLength(v)-coxeterLength(u); if lendiff<0 or isLtBruhat(u,v)==false then new HasseDiagram from {} else ( myinterval:=new MutableList from {{{v,{}}}}; rowindex := 0; while lendiff>rowindex do ( myinterval#(rowindex+1)=select(underBruhat(apply(myinterval#rowindex,x->x#0)),y->isLtBruhat(u,y#0)); rowindex=rowindex+1; ); new HasseDiagram from reverseLinks(myinterval) ) ) ) --computing the poincare series of a hasse diagram. poincareSeries(HasseDiagram,RingElement):=(H,x)-> ( sum for i from 0 to #H-1 list #(H#i)*x^i ) --Defining the class of Hasse graphs. It is a bit the same thing as Hasse diagrams, except that it is intended for graphic display, so vertices and links are just strings (that will be used in the graphic). So a typical row looks like {{"1",{2,"121"},{},...},...}. The labels can be anything. HasseGraph = new Type of BasicList --Turning a Hasse diagram into a Hasse graph minimal implementation with no labels. hasseDiagramToGraph = method(Options => true) hasseDiagramToGraph(HasseDiagram) := {"labels"=>""} >> opts -> (D) -> ( if (opts#"labels")==="reduced decomposition" then new HasseGraph from for i from 0 to #D-1 list apply(D#i,x->{concatenate(apply(reducedDecomposition(x#0),toString)),apply(x#1,y->{concatenate(apply(reducedDecomposition(reflection(x#0#0,y#1)),toString)),y#0})}) else ( new HasseGraph from for i from 0 to #D-1 list apply(D#i,x->{"",apply(x#1,y->{"",y#0})}) ) ) --making graphic elements for the package "Graphics" out of a HasseGraph (and return them in a Picture object). No labels for the moment. hasseGraphToPicture = method(Options=>true) hasseGraphToPicture(HasseGraph) := {"top margin"=>100,"left margin"=>100,"horizontal space"=>100,"row space"=>100,"tag distance"=>20,"point radius"=>2,"point options"=>new HashTable from {"fill"=>"black"}, "edge options" => new HashTable from {"stroke-width"=>"2"}, "tag options"=>new HashTable from {}} >> opts -> (G) -> ( topmargin:=opts#"top margin"; leftmargin:=opts#"left margin"; interpoint:= opts#"horizontal space"; interrow:= opts#"row space"; pointtagdist:=opts#"tag distance"; --edgetagdist:=20; pointrad:= opts#"point radius"; --linewidth:= opts#"edge width"; rowsize:=toList(apply(G,x->#x)); maxpoints:=max(rowsize); optionspoints:= opts#"point options"; optionstags:= opts#"tag options"; optionslinks:= opts#"edge options"; mypoints := flatten for i from 0 to #G-1 list ( flatten for j from 0 to #(G#i)-1 list {formatGraphicPrimitives({circle(point(round(0.0+leftmargin+((maxpoints-rowsize#i)/2 +j)*interpoint),topmargin+i*interrow),pointrad)}, optionspoints), formatGraphicPrimitives({textTag(point(round(0.0+leftmargin+((maxpoints-rowsize#i)/2 +j)*interpoint),topmargin+i*interrow),G#i#j#0)}, optionstags)} ); mylinks := flatten for i from 0 to #G-1 list flatten for j from 0 to #(G#i)-1 list flatten for k from 0 to #(G#i#j#1)-1 list formatGraphicPrimitives({segment(point(round(0.0+leftmargin+((maxpoints-rowsize#i)/2 +j)*interpoint),topmargin+i*interrow),point(round(0.0+leftmargin+((maxpoints-rowsize#(i+1))/2 +(G#i#j#1#k#1))*interpoint),topmargin+(i+1)*interrow))},optionslinks); picture(mylinks|mypoints) ) -- for i from 0 to #G-1 do -- for j from 0 to #(G#i)-1 do -- ( -- myPicture = append(myPicture,formatGraphicPrimitive( -- point(round(0.0+leftmargin+((maxpoints-rowsize#i)/2 +j)*interpoint),topmargin+i*interrow), -- new HashTable from {"fill"=>"black","r"=>toString(pointrad)} -- )); -- myPicture = append(myPicture,formatGraphicPrimitive( -- textTag(point(round(0.0+leftmargin+((maxpoints-rowsize#i)/2 +j)*interpoint),topmargin+i*interrow),G#i#j#0), -- new HashTable from {} -- )); -- -- for k from 0 to #(G#i#j#1)-1 do -- ( -- myPicture = append(myPicture,formatGraphicPrimitive( -- segment(point(round(0.0+leftmargin+((maxpoints-rowsize#i)/2 +j)*interpoint),topmargin+i*interrow),point(round(0.0+leftmargin+((maxpoints-rowsize#(i+1))/2 +(G#i#j#1#k#1))*interpoint),topmargin+(i+1)*interrow)), -- new HashTable from {"stroke-width"=>"toString(linewidth)"} -- )); -- ); -- ); -- myPicture --Finding the root system of the Levi part of a parabolic subgroup. rootSystem(RootSystem,Parabolic) := (R,P) -> ( L:=sort(toList P) - (toList ((#P):1)); M:= if #P>0 then submatrix(R.CartanMatrixTr,L,L) else (matrix{{1}})^{}_{}; new RootSystem from { RootSystemRank => #P, CartanMatrixTr => M, CartanMatrixTrInv => inverse(promote(M,QQ)), RootNorms => apply(L,x->(R.RootNorms)#x), PositiveRoots => set{}, --This should be made more efficient. Later... Reflections => new HashTable from {}, --This I don't know how to make efficient for the moment. WeylGroupList => {}, ReducedDecompositions => new MutableHashTable from {} } ) --Checking whether a root is in the sub root system of the parabolic. isRoot(RootSystem,Parabolic,Root) := (R,P,r) -> ( C:=toList(set (1..R.RootSystemRank) - P); C=C-toList(#C:1); zeroList:=(#C:0); toSequence((entries(rootCoefficients(R,r)))_C)===zeroList ) --Finding the positive roots of the root system that are in the subroot system of P positiveRoots(RootSystem,Parabolic) := (R,P) -> ( C:=toList(set (1..R.RootSystemRank) - P); C=C-toList(#C:1); zeroList:=(#C:0); set select(toList positiveRoots(R),r->toSequence((entries(rootCoefficients(R,r)))_C)==zeroList) ) --Defining the class of left cosets of the form wW_P, represented by the list {P,w}, w being of minimal length WeylGroupLeftCoset = new Type of BasicList --Defining equality of left cosets WeylGroupLeftCoset == WeylGroupLeftCoset := (c1, c2) -> isSubset(c1#0,c2#0) and isSubset(c2#0,c1#0) and (c1#1==c2#1) --the minimal representative of a left coset minimalRepresentative = method() minimalRepresentative(WeylGroupLeftCoset) := (c) -> c#1 --Defining the class of right cosets of the form W_Pw, represented by the list {P,w}, w being of minimal length WeylGroupRightCoset = new Type of BasicList --Defining equality of right cosets WeylGroupRightCoset == WeylGroupRightCoset := (c1, c2) -> isSubset(c1#0,c2#0) and isSubset(c2#0,c1#0) and (c1#1==c2#1) --the minimal representative of a right coset minimalRepresentative(WeylGroupRightCoset) := (c) -> c#1 --Defining the class of double cosets of the form W_PwW_Q, represented by the list {P,Q,w}, w being of minimal length WeylGroupDoubleCoset = new Type of BasicList --Defining equality of double cosets WeylGroupDoubleCoset == WeylGroupDoubleCoset := (c1, c2) -> isSubset(c1#0,c2#0) and isSubset(c2#0,c1#0) and isSubset(c1#1,c2#1) and isSubset(c2#1,c1#1) and (c1#2==c2#2) --the minimal representative of a double coset minimalRepresentative(WeylGroupDoubleCoset) := (c) -> c#2 --compute the left coset wW_P WeylGroupElement % Parabolic := (w, P) -> new WeylGroupLeftCoset from {P,inverse ((P % inverse(w))#1)} --compute the right coset W_Pw Parabolic % WeylGroupElement := (P, w) -> ( n := rank(w#0); t := w#1; i := local i; while true do ( i = 0; while (i<n) and (not member(i+1,P) or (t_i>0)) do i=i+1; if i==n then break; t = reflect(w#0,i+1,t); ); new WeylGroupRightCoset from {P,new WeylGroupElement from {w#0,t}} ) --check whether an element of the Weyl group is the minimal representative of a left coset isMinimalRepresentative = method() isMinimalRepresentative(WeylGroupElement,Parabolic) := (w, P) -> isMinimalRepresentative(P, inverse w) --check whether an element of the Weyl group is the minimal representative of a right coset isMinimalRepresentative(Parabolic,WeylGroupElement) := (P, w) -> all(toList P,i -> (w#1)_(i-1) > 0) --check whether an element of the Weyl group is the minimal representative of a double coset isMinimalRepresentative(Parabolic,WeylGroupElement,Parabolic) := (P, w, Q) -> isMinimalRepresentative(P,w) and isMinimalRepresentative(w,Q) --compute the double coset Parabolic % WeylGroupLeftCoset := (P, c) -> new WeylGroupDoubleCoset from {P, c#0, (P % (c#1))#1} WeylGroupRightCoset % Parabolic := (c, Q) -> new WeylGroupDoubleCoset from {c#0, Q, ((c#1) % Q)#1} --action of the Weyl group on left cosets WeylGroupElement * WeylGroupLeftCoset := (w, c) -> new WeylGroupLeftCoset from {c#0, ((w*(c#1))%(c#0))#1} --action of the Weyl group on right cosets WeylGroupRightCoset * WeylGroupElement := (c, w) -> new WeylGroupRightCoset from {c#0, ((c#0)%((c#1)*w))#1} --longest element of a parabolic sugroup of the Weyl group (as an element of the Weyl group) longestWeylGroupElement(RootSystem,Parabolic) := (R,P) -> ( longestWeylGroupElement(R)*inverse(minimalRepresentative(P % longestWeylGroupElement(R))) ) --parabolic associated to a double coset (as in Finite Groups of Lie Type, p. 65, thm 2.7.4) parabolic(WeylGroupDoubleCoset) := (w) -> ( R:=w#2#0; P:=w#0; Q:=w#1; v:=inverse(w#2); r:= local r; new Parabolic from set(select(toList P,i->(r=v*simpleRoot(R,i); isPositiveRoot(R,r) and isRoot(R,P,r)))) ) --compute a Bruhat interval for the Bruhat order on W/W_P. intervalBruhat(WeylGroupLeftCoset,WeylGroupLeftCoset):= (u,v) -> ( if u#0 =!= v#0 or u#1#0 =!= v#1#0 then error "The cosets must live in the same Weyl group (same root system) and be modulo the same parabolic." else ( lendiff := coxeterLength(v#1)-coxeterLength(u#1); if lendiff<0 or isLtBruhat(u#1,v#1)==false then new HasseDiagram from {} else ( myinterval:=new MutableList from {{{v#1,{}}}}; rowindex := 0; while lendiff>rowindex do ( myinterval#(rowindex+1)=select(underBruhat(apply(myinterval#rowindex,x->x#0)),y->(isLtBruhat(u#1,y#0) and isMinimalRepresentative(y#0,u#0))); rowindex=rowindex+1; ); new HasseDiagram from reverseLinks(myinterval) ) ) ) --not used anymore, new algorithm above ----compute a Bruhat interval for the Bruhat order on W/W_P. --intervalBruhat(WeylGroupLeftCoset,WeylGroupLeftCoset):= (u,v) -> -- ( -- if u#0 =!= v#0 or u#1#0 =!= v#1#0 then error "The cosets must live in the same Weyl group (same root system) and be modulo the same parabolic." -- else -- ( -- P:= v#0; -- lendiff := coxeterLength(v#1)-coxeterLength(u#1); -- if lendiff<0 then new HasseDiagram from {} -- else -- ( -- fromtop := true; -- toppart :=new MutableList from {{{v#1,{}}}}; -- topindex := 0; -- bottompart :=new MutableList from {{{u#1,{}}}}; -- bottomindex := 0; -- pos:=local pos; -- while lendiff - topindex - bottomindex >0 do -- ( -- if fromtop then -- ( -- toppart#(topindex+1)=select(underBruhat(apply(toppart#topindex,x->x#0)),y->isMinimalRepresentative(y#0,P)); -- topindex=topindex+1; -- ) -- else -- ( -- bottompart#(bottomindex+1)=select(aboveBruhat(apply(bottompart#bottomindex,x->x#0)),y->isMinimalRepresentative(y#0,P)); -- bottomindex=bottomindex+1; -- ); -- fromtop = (#(toppart#topindex)<=#(bottompart#bottomindex)); -- ); -- toprow := apply(toppart#topindex,x->x#0); -- bottomrow := apply(bottompart#bottomindex,x->x#0); -- poslist :={}; -- newbottomrow := {}; -- for i from 0 to #bottomrow-1 do -- ( -- pos = position(toprow,x->(x==bottomrow#i)); -- if pos =!= null then -- ( -- poslist = append(poslist,pos); -- newbottomrow = append(newbottomrow,bottompart#bottomindex#i); -- ) -- ); -- bottompart#bottomindex = newbottomrow; --replacing the top row of the bottom cone by the elements that are also in the bottom row of the top cone. -- newbottompart := extractHasse(bottompart,toList(0..#(bottompart#bottomindex)-1)); -- newtoppart := extractHasse(toppart,poslist); -- newtoppart = drop(reverseLinks(newtoppart),-1); -- new HasseDiagram from newtoppart|reverse(newbottompart) -- ) -- ) -- ) --compute a Bruhat interval for the Bruhat order on W_P\W. intervalBruhat(WeylGroupRightCoset,WeylGroupRightCoset):= (u,v) -> ( if u#0 =!= v#0 or u#1#0 =!= v#1#0 then error "The cosets must live in the same Weyl group (same root system) and be modulo the same parabolic." else ( lendiff := coxeterLength(v#1)-coxeterLength(u#1); if lendiff<0 or isLtBruhat(u#1,v#1)==false then new HasseDiagram from {} else ( myinterval:=new MutableList from {{{v#1,{}}}}; rowindex := 0; while lendiff>rowindex do ( myinterval#(rowindex+1)=select(underBruhat(apply(myinterval#rowindex,x->x#0)),y->(isLtBruhat(u#1,y#0) and isMinimalRepresentative(u#0,y#0))); rowindex=rowindex+1; ); new HasseDiagram from reverseLinks(myinterval) ) ) ) --no longer used, new algo above. ----compute a Bruhat interval for the Bruhat order on W_P\W. --intervalBruhat(WeylGroupRightCoset,WeylGroupRightCoset):= (u,v) -> -- ( -- if u#0 =!= v#0 or u#1#0 =!= v#1#0 then error "The cosets must live in the same Weyl group (same root system) and be modulo the same parabolic." -- else -- ( -- P:= v#0; -- lendiff := coxeterLength(v#1)-coxeterLength(u#1); -- if lendiff<0 then new HasseDiagram from {} -- else -- ( -- fromtop := true; -- toppart :=new MutableList from {{{v#1,{}}}}; -- topindex := 0; -- bottompart :=new MutableList from {{{u#1,{}}}}; -- bottomindex := 0; -- pos:=local pos; -- while lendiff - topindex - bottomindex >0 do -- ( -- if fromtop then -- ( -- toppart#(topindex+1)=select(underBruhat(apply(toppart#topindex,x->x#0)),y->isMinimalRepresentative(P,y#0)); -- topindex=topindex+1; -- ) -- else -- ( -- bottompart#(bottomindex+1)=select(aboveBruhat(apply(bottompart#bottomindex,x->x#0)),y->isMinimalRepresentative(P,y#0)); -- bottomindex=bottomindex+1; -- ); -- fromtop = (#(toppart#topindex)<=#(bottompart#bottomindex)); -- ); -- toprow := apply(toppart#topindex,x->x#0); -- bottomrow := apply(bottompart#bottomindex,x->x#0); -- poslist :={}; -- newbottomrow := {}; -- for i from 0 to #bottomrow-1 do -- ( -- pos = position(toprow,x->(x==bottomrow#i)); -- if pos =!= null then -- ( -- poslist = append(poslist,pos); -- newbottomrow = append(newbottomrow,bottompart#bottomindex#i); -- ) -- ); -- bottompart#bottomindex = newbottomrow; --replacing the top row of the bottom cone by the elements that are also in the bottom row of the top cone. -- newbottompart := extractHasse(bottompart,toList(0..#(bottompart#bottomindex)-1)); -- newtoppart := extractHasse(toppart,poslist); -- newtoppart = drop(reverseLinks(newtoppart),-1); -- new HasseDiagram from newtoppart|reverse(newbottompart) -- ) -- ) -- ) --Root system of type A rootSystemA = (n) -> ( if not instance(n,ZZ) then error "The argument should be an integer." else if n<=0 then error "The argument should be positive." else ( M := matrix( for i from 1 to n list for j from 1 to n list if (j<i-1) or (j>i+1) then 0 else if j==i then 2 else -1 ); new RootSystem from { RootSystemRank => n, CartanMatrixTr => M, CartanMatrixTrInv => inverse promote(M,QQ), RootNorms => toList (n:1), PositiveRoots => set {}, Reflections => new HashTable from {}, WeylGroupList => {}, ReducedDecompositions => new MutableHashTable from {} } ) ) --Root system of type B rootSystemB = (n) -> ( if not instance(n,ZZ) then error "The argument should be an integer." else if n<=0 then error "The argument should be positive." else ( M := matrix( for i from 1 to n list for j from 1 to n list if (i==n) and (j==n-1) then -2 else if (j<i-1) or (j>i+1) then 0 else if j==i then 2 else -1 ); new RootSystem from { RootSystemRank => n, CartanMatrixTr => M, CartanMatrixTrInv => inverse promote(M,QQ), RootNorms => append(toList((n-1):2),1), PositiveRoots => set {}, Reflections => new HashTable from {}, WeylGroupList => {}, ReducedDecompositions => new MutableHashTable from {} } ) ) --Root system of type C rootSystemC = (n) -> ( if not instance(n,ZZ) then error "The argument should be an integer" else if n<=0 then error "The argument should be positive" else ( M := matrix( for i from 1 to n list for j from 1 to n list if (i==n-1) and (j==n) then -2 else if (j<i-1) or (j>i+1) then 0 else if j==i then 2 else -1 ); new RootSystem from { RootSystemRank => n, CartanMatrixTr => M, CartanMatrixTrInv => inverse promote(M,QQ), RootNorms => append(toList((n-1):1),2), PositiveRoots => set {}, Reflections => new HashTable from {}, WeylGroupList => {}, ReducedDecompositions => new MutableHashTable from {} } ) ) --Root system of type D rootSystemD = (n) -> ( if not instance(n,ZZ) then error "The argument should be an integer" else if n<=0 then error "The argument should be positive" else ( M := matrix( for i from 1 to n list for j from 1 to n list if ((i==n-2) and (j==n)) or ((i==n) and (j==n-2)) then -1 else if ((i==n-1) and (j==n)) or ((i==n) and (j==n-1)) or (j<i-1) or (j>i+1) then 0 else if j==i then 2 else -1 ); new RootSystem from { RootSystemRank => n, CartanMatrixTr => M, CartanMatrixTrInv => inverse promote(M,QQ), RootNorms => toList(n:1), PositiveRoots => set {}, Reflections => new HashTable from {}, WeylGroupList => {}, ReducedDecompositions => new MutableHashTable from {} } ) ) --Root system of type E rootSystemE = (n) -> ( if not instance(n,ZZ) then error "The argument should be an integer" else if (n<6) or (n>8) then error "The argument should be equal to 6, 7, or 8" else ( M := matrix( for i from 1 to n list for j from 1 to n list if ((i==1) and (j==3)) or ((i==3) and (j==1)) or ((i==2) and (j==4)) or ((i==4) and (j==2)) then -1 else if ((i==1) and (j==2)) or ((i==2) and (j==1)) or ((i==2) and (j==3)) or ((i==3) and (j==2)) or (j<i-1) or (j>i+1) then 0 else if j==i then 2 else -1 ); new RootSystem from { RootSystemRank => n, CartanMatrixTr => M, CartanMatrixTrInv => inverse promote(M,QQ), RootNorms => toList(n:1), PositiveRoots => set {}, Reflections => new HashTable from {}, WeylGroupList => {}, ReducedDecompositions => new MutableHashTable from {} } ) ) --Root system of type F4 rootSystemF4 = new RootSystem from { RootSystemRank => 4, CartanMatrixTr => matrix{{2,-1,0,0},{-1,2,-1,0},{0,-2,2,-1},{0,0,-1,2}}, CartanMatrixTrInv => inverse promote(matrix{{2,-1,0,0},{-1,2,-1,0},{0,-2,2,-1},{0,0,-1,2}},QQ), RootNorms => {2,2,1,1}, PositiveRoots => set {}, Reflections => new HashTable from {}, WeylGroupList => {}, ReducedDecompositions => new MutableHashTable from {} } --Root system of type G2 rootSystemG2 = new RootSystem from { RootSystemRank => 2, CartanMatrixTr => matrix{{2,-3},{-1,2}}, CartanMatrixTrInv => inverse promote(matrix{{2,-3},{-1,2}},QQ), RootNorms => {1,3}, PositiveRoots => set {}, Reflections => new HashTable from {}, WeylGroupList => {}, ReducedDecompositions => new MutableHashTable from {} } --Will store a Hasse graph in a file. storeHasseGraph=method() storeHasseGraph(HasseGraph,String) := (H,filename) -> ( filename << (new List from H) << endl << close ) --Will extract a hasse graph stored as a list in a file. loadHasseGraph=method() loadHasseGraph(String):=(filename)-> ( mylist:=value get filename; new HasseGraph from for i from 0 to #mylist-1 list apply(mylist#i,x->{if x#0===null then "" else toString(x#0),apply(x#1,y->{toString(y#0),y#1})}) ) --The rest of the file is documentation. beginDocumentation() doc /// Key WeylGroups Headline Weyl groups Description Text This package provides functions to compute in Weyl groups of root systems. In particular, it can compute intervals for the Bruhat order. Text Here is a quick @HREF(currentLayout#"packages" | "WeylGroups/tutorial.html","tutorial")@ on how to use it. Subnodes RootSystem Weight Root WeylGroupElement Parabolic WeylGroupLeftCoset WeylGroupRightCoset WeylGroupDoubleCoset DynkinDiagram DynkinType HasseDiagram HasseGraph /// doc /// Key RootSystem Headline the class of all root systems Subnodes rootSystem cartanMatrix (rank, RootSystem) (rootSystem,DynkinType) rootSystemA rootSystemB rootSystemC rootSystemD rootSystemE (rootSystem,RootSystem,Parabolic) (rootSystem,DynkinDiagram) /// doc /// Key cartanMatrix Headline the Cartan matrix of a root system /// doc /// Key (cartanMatrix, RootSystem) Headline the Cartan matrix of a root system Usage cartanMatrix(R) Inputs R: RootSystem Outputs : Matrix the Cartan matrix of {\tt R} Description Example R=rootSystemA(3) cartanMatrix R /// TEST /// R=rootSystemA(3); assert(cartanMatrix(R)==matrix{{2,-1,0},{-1,2,-1},{0,-1,2}}) /// doc /// Key (rank, RootSystem) Headline the rank of a root system Usage r=rank(R) Inputs R: RootSystem Outputs : ZZ the rank of {\tt R} Description Example R = rootSystemA(5) rank R /// TEST /// R=rootSystemA(3); assert(rank(R)==3) /// doc /// Key (symbol ++,RootSystem,RootSystem) Headline the direct sum of root systems Usage R1 ++ R2 Inputs R1: RootSystem R2: RootSystem Outputs : RootSystem the direct sum of {\tt R1} and {\tt R2} Description Example R1=rootSystemA(2) R2=rootSystemA(3) R1++R2 /// doc /// Key (symbol ==,RootSystem,RootSystem) Headline equality of root systems Usage R1 == R2 Inputs R1: RootSystem R2: RootSystem Outputs : Boolean {\tt true} if the Cartan matrices of {\tt R1} and {\tt R2} coincide and {\tt false} otherwise Description Example R1=rootSystemA(2) R2=rootSystemA(2) R1==R2 /// doc /// Key rootSystemA Headline a root system of type A Usage rootSystemA(n) Inputs n: ZZ Outputs : RootSystem a root system of type A and of rank {\tt n} Description Example rootSystemA(5) /// doc /// Key rootSystemB Headline a root system of type B Usage rootSystemB(n) Inputs n: ZZ Outputs : RootSystem a root system of type B and of rank {\tt n} Description Example rootSystemB(5) /// doc /// Key rootSystemC Headline a root system of type C Usage rootSystemC(n) Inputs n: ZZ Outputs : RootSystem a root system of type C and of rank {\tt n} Description Example rootSystemC(5) /// doc /// Key rootSystemD Headline a root system of type D Usage rootSystemD(n) Inputs n: ZZ Outputs : RootSystem a root system of type D and of rank {\tt n} Description Example rootSystemD(5) /// doc /// Key rootSystemE Headline a root system of type E Usage rootSystemE(n) Inputs n: ZZ from 6 to 8 Outputs : RootSystem a root system of type E and of rank {\tt n} Description Example rootSystemE(6) /// doc /// Key "rootSystemF4" Headline the root system of type F4 /// doc /// Key "rootSystemG2" Headline the root system of type G2 /// doc /// Key rootSystem Headline obtain a root system /// doc /// Key (rootSystem,RootSystem,Parabolic) Headline the root system of the Levy subgroup of a parabolic Usage rootSystem(R,P) Inputs R: RootSystem P: Parabolic Outputs : RootSystem the root system of the Levy subgroup of {\tt P} Description Example R1=rootSystemD(4) P=parabolic(R1,set{1,3,4}) R2=rootSystem(R1,P) dynkinType(R2) /// TEST /// R1=rootSystemD(4); P=parabolic(R1,set{1,3,4}); R2=rootSystem(R1,P); assert(dynkinType(R2)==dynkinType({{"A",1},{"A",1},{"A",1}})) /// doc /// Key (rootSystem,DynkinType) Headline the root system of a given type Usage rootSystem(T) Inputs T: DynkinType Outputs : RootSystem the root system of the corresponding type Description Example rootSystem(dynkinType({{"A",2},{"D",4}})) /// TEST /// assert(rootSystem(dynkinType({{"A",2},{"D",4}}))==rootSystemA(2)++rootSystemD(4)) /// doc /// Key (rootSystem,DynkinDiagram) Headline the root system corresponding to a Dynkin diagram Usage rootSystem(D) Inputs D: DynkinDiagram Outputs : RootSystem the root system corresponding to the Dynkin diagram Description Example R1=rootSystemB(3)++rootSystemD(4) D=dynkinDiagram(R1) R2=rootSystem(D) R1==R2 /// TEST /// R1=rootSystemB(3)++rootSystemD(4) D=dynkinDiagram(R1) R2=rootSystem(D) assert(R1==R2) /// doc /// Key Weight Headline the class of weights Description Text a weight is represented by an element of ZZ^n, the basis consisting in the fundamental weights Subnodes weight (weight,RootSystem,BasicList) (weight,RootSystem,Vector) isPositiveRoot isRoot /// doc /// Key (symbol +,Weight,Weight) Headline the sum of two weights Usage p1 + p2 Inputs p1: Weight p2: Weight Outputs : Weight the sum of {\tt p1} and {\tt p2} Description Example R=rootSystemA(4) M=cartanMatrix R p1=weight(R,M_0) p2=weight(R,M_1) p1+p2 /// TEST /// R=rootSystemA(4); p1=weight(R,{1,1,2,3}); p2=weight(R,{1,1,-2,3}); assert(p1+p2==weight(R,{2,2,0,6})) /// doc /// Key (symbol -,Weight,Weight) Headline the difference of two weights Usage p1 - p2 Inputs p1: Weight p2: Weight Outputs : Weight the difference of {\tt p1} and {\tt p2} Description Example R=rootSystemA(4) M=cartanMatrix R p1=weight(R,M_0) p2=weight(R,M_1) p1-p2 /// TEST /// R=rootSystemA(4); p1=weight(R,{1,1,2,3}); p2=weight(R,{1,1,-2,3}); assert(p1-p2==weight(R,{0,0,4,0})) /// doc /// Key (symbol *,ZZ,Weight) Headline the multiple of a weight Usage n * p Inputs n: ZZ p: Weight Outputs : Weight n times {\tt p} Description Example R=rootSystemA(4) M=cartanMatrix R p=weight(R,M_2) -2*p /// TEST /// R=rootSystemA(3); p=weight(R,{1,2,1}); assert(2*p==weight(R,{2,4,2})) /// doc /// Key (symbol -,Weight) Headline the negative of a weight Usage - p Inputs p: Weight Outputs : Weight the negative of {\tt p} Description Example R=rootSystemA(4) M=cartanMatrix R p=weight(R,M_2) -p /// TEST /// R=rootSystemA(3); p=weight(R,{1,2,1}); assert(-p==weight(R,{-1,-2,-1})) /// doc /// Key weight Headline construct a weight in the weight lattice of a root system /// doc /// Key (weight,RootSystem,BasicList) Headline construct a weight from a list Usage weight(R,L) Inputs R: RootSystem L: BasicList the coordinates of the weight Outputs : Weight a weight vector in a the weight lattice of {\tt R} Description Example R=rootSystemB(3) weight(R,{1,2,1}) /// TEST /// R=rootSystemA(4); assert(weight(R,{1,1,2,3})==new Weight from vector{1,1,2,3}) /// doc /// Key (weight,RootSystem,Vector) Headline construct a weight from a vector Usage weight(R,v) Inputs R: RootSystem v: Vector the coordinates of the weight Outputs : Weight a weight vector in a the weight lattice of {\tt R} Description Example R=rootSystemB(3) weight(R,vector {1,2,1}) /// TEST /// R=rootSystemA(4); assert(weight(R,vector{1,1,2,3})==new Weight from vector{1,1,2,3}) /// doc /// Key Root Headline the class of roots (or, more generally, elements of the root lattice) Description Text a root is represented by the respective weight Subnodes addRoots (addRoots, RootSystem, Root, Root) (symbol *, ZZ, Root) halfSumOfRoots simpleRoot (norm, RootSystem, Root) rootCoefficients positiveRoots numberOfPositiveRoots /// doc /// Key addRoots Headline adding roots /// doc /// Key (addRoots, RootSystem, Root, Root) Headline the sum of two roots Usage r1 + r2 Inputs R: RootSystem r1: Root r2: Root Outputs : Weight the sum of {\tt r1} and {\tt r2}. Actually, it is returned as an object of class @TO Root@ if the resulting weight is a root. Description Example R=rootSystemA(2) r1=simpleRoot(R,1) r2=simpleRoot(R,2) r=addRoots(R,r1,r2) addRoots(R,r1,r) /// TEST /// R=rootSystemA(2); r1=simpleRoot(R,1); r2=simpleRoot(R,2); assert(addRoots(R,r1,r1)==weight(R,{4,-2})); assert(isRoot(R,addRoots(R,r1,r2))==true) /// doc /// Key (symbol *, ZZ, Root) Headline multiplication of a root by an integer Usage n*r Inputs n: ZZ r: Root Outputs : Weight Description Example R=rootSystemA(3) r=simpleRoot(R,1) 2*r Text Note that if the integer is +1 or -1, we obtain a weight that is a root. Example -1*r /// TEST /// R=rootSystemA(2); r=simpleRoot(R,1); assert(-2*r==weight(R,{-4,2})); /// doc /// Key halfSumOfRoots Headline the half-sum of positive roots /// doc /// Key (halfSumOfRoots, RootSystem) Headline the half-sum of positive roots Usage halfSumOfRoots(R) Inputs R: RootSystem Outputs : Weight the half-sum of positive roots in {\tt R} Description Example halfSumOfRoots(rootSystemE(6)) /// TEST /// R=rootSystemE(6); assert(halfSumOfRoots(R)==weight(R,{1,1,1,1,1,1})) /// doc /// Key isPositiveRoot Headline check whether a weight is a positive root /// doc /// Key (isPositiveRoot, RootSystem, Weight) Headline check whether a weight is a positive root Usage isPositiveRoot(R,p) Inputs R: RootSystem p: Weight Outputs : Boolean {\tt true} if {\tt p} is a positive root in {\tt R} and {\tt false} otherwise Description Example R=rootSystemE(6) p=halfSumOfRoots(R) isPositiveRoot(R,p) /// TEST /// R=rootSystemA(3); w1=weight(R,{1,2,1}); w2=weight(R,{2,-1,0}); assert(isPositiveRoot(R,w1)==false); assert(isPositiveRoot(R,w2)==true) /// doc /// Key isRoot Headline check whether a weight is a root or whether a root is in a parabolic sub root system /// doc /// Key (isRoot, RootSystem, Weight) Headline check whether a weight is a positive root Usage isRoot(R,p) Inputs R: RootSystem p: Weight Outputs : Boolean {\tt true} if {\tt p} is a root in {\tt R} and {\tt false} otherwise Description Example R=rootSystemE(6) p=simpleRoot(R,1) isPositiveRoot(R,-p) isRoot(R,-p) /// TEST /// R=rootSystemE(6); p=simpleRoot(R,1); isPositiveRoot(R,-p); assert(isRoot(R,-p)==true) /// doc /// Key (isRoot, RootSystem, Parabolic, Root) Headline check whether a root is in the sub root system of the parabolic Usage isRoot(R,P,r) Inputs R: RootSystem P: Parabolic r: Root Outputs : Boolean {\tt true} if {\tt p} is a root in the sub root system of {\tt R} defined by {\tt P} and {\tt false} otherwise Description Example R=rootSystemE(6) P=parabolic(R,set{1,3}) r1=simpleRoot(R,1) r2=simpleRoot(R,2) isRoot(R,P,r1) isRoot(R,P,r2) /// TEST /// R=rootSystemE(6); P=parabolic(R,set{1,3}); r1=simpleRoot(R,1); r2=simpleRoot(R,2); assert(isRoot(R,P,r1)==true); assert(isRoot(R,P,r2)==false) /// doc /// Key simpleRoot Headline a simple root /// doc /// Key (simpleRoot, RootSystem, ZZ) Headline the n-th simple root Usage simpleRoot(R,n) Inputs R: RootSystem n: ZZ Outputs : Root the {\tt n}-th simple root of {\tt R} Description Example simpleRoot(rootSystemE(6),2) /// doc /// Key (norm, RootSystem, Root) Headline the squared norm of a root Usage norm(R,r) Inputs R: RootSystem r: Root Outputs : ZZ the squared norm of {\tt r}, short roots being of norm 1 Description Example norm(rootSystemF4,simpleRoot(rootSystemF4,2)) /// TEST /// assert(norm(rootSystemF4,simpleRoot(rootSystemF4,2))==2) /// doc /// Key scalarProduct Headline compute a scalar product (invariant by the Weyl group) /// doc /// Key (scalarProduct, RootSystem, ZZ, ZZ) Headline the scalar product of two fundamental weights Usage scalarProduct(R,i,j) Inputs R: RootSystem i: ZZ the number of the first fundamental weight j: ZZ the number of the second fundamental weight Outputs : QQ the scalar product of the {\tt i}-th fundamental weight with the {\tt j}-th Description Example R=rootSystemA(2) scalarProduct(R,1,1) scalarProduct(R,1,2) scalarProduct(R,2,2) /// TEST /// assert(scalarProduct(rootSystemA(2),1,2)==1/6) /// doc /// Key (scalarProduct, RootSystem, ZZ, Weight) Headline the scalar product of a fundamental weight and a weight Usage scalarProduct(R,i,v) Inputs R: RootSystem i: ZZ the number of the fundamental weight v: Weight the other weight Outputs : QQ the scalar product of the {\tt i}-th fundamental weight with the weight {\tt v} Description Example R=rootSystemA(2) v=weight(R,{1,2}) scalarProduct(R,1,v) /// TEST /// R=rootSystemA(2); v=weight(R,{1,2}); assert(scalarProduct(R,1,v)==2/3) /// doc /// Key (scalarProduct, RootSystem, Weight, Weight) Headline the scalar product of two weights Usage scalarProduct(R,u,v) Inputs R: RootSystem u: Weight the first weight v: Weight the second weight Outputs : QQ the scalar product of {\tt u} and {\tt v} Description Example R=rootSystemA(2) u=weight(R,{1,2}) v=weight(R,{0,3}) scalarProduct(R,u,v) /// TEST /// R=rootSystemA(2) u=weight(R,{1,2}) v=weight(R,{0,3}) assert(scalarProduct(R,u,v)==5/2) /// doc /// Key eval Headline evaluate the dual of a root at something /// doc /// Key (eval, RootSystem, ZZ, ZZ) Headline evaluate the dual of a simple root at another one Usage eval(R,i,j) Inputs R: RootSystem i: ZZ the number of the first simple root j: ZZ the number of the second simple root Outputs : ZZ the dual of the {\tt j}-th simple root evaluated at the {\tt i}-th simple root Description Example R=rootSystemA(2) eval(R,1,1) eval(R,1,2) /// TEST /// R=rootSystemA(2); assert(eval(R,1,1)==2); assert(eval(R,1,2)==-1); /// doc /// Key (eval, RootSystem, Weight, ZZ) Headline evaluate the dual of a simple root at a Weight Usage eval(R,v,i) Inputs R: RootSystem v: Weight i: ZZ the number of the simple root Outputs : ZZ the dual of the {\tt i}-th simple root evaluated at the weight {\tt v} Description Example R=rootSystemA(2) v=weight(R,{1,2}) eval(R,v,1) /// TEST /// R=rootSystemA(2); v=weight(R,{1,2}); assert(eval(R,v,1)==1) /// doc /// Key (eval, RootSystem, Weight, Root) Headline evaluate the dual of a root at a Weight Usage eval(R,v,r) Inputs R: RootSystem v: Weight r: Root Outputs : ZZ the dual of the root {\tt r} evaluated at the weight {\tt v} Description Example R=rootSystemA(2) L=toList(positiveRoots(R)) v=weight(R,{1,2}) eval(R,v,L#0) eval(R,v,L#1) eval(R,v,L#2) /// doc /// Key (eval, RootSystem, ZZ, Root) Headline evaluate the dual of a root at a fundamental weight Usage eval(R,i,r) Inputs R: RootSystem i: ZZ the number of a weight r: Root Outputs : ZZ the dual of the root {\tt r} evaluated at the {\tt i}-th fundamental weight Description Example R=rootSystemA(2) L=toList(positiveRoots(R)) eval(R,1,L#0) eval(R,1,L#1) eval(R,1,L#2) /// TEST /// R=rootSystemA(2); L=toList(positiveRoots(R)); v=weight(R,{1,2}); assert(L/(ell -> (eval(R,v,ell), eval(R,1,ell)))//sort == sort {(2,0),(3,1),(1,1)}) --assert(eval(R,v,L#0)==2); --assert(eval(R,v,L#1)==3); --assert(eval(R,v,L#2)==1); --assert(eval(R,1,L#0)==0); --assert(eval(R,1,L#1)==1); --assert(eval(R,1,L#2)==1) /// doc /// Key rootCoefficients Headline coefficients at the simple roots /// doc /// Key (rootCoefficients,RootSystem,Root) Headline the coefficients at the simple roots Usage rootCoefficients(R,r) Inputs R: RootSystem r: Root Outputs : Vector whose components are the coefficients of {\tt r} at the simple roots of {\tt R} Description Example R=rootSystemE(8) r1=simpleRoot(R,1) r2=simpleRoot(R,2) rootCoefficients(R,r1+r2) /// doc /// Key (rootCoefficients,RootSystem,Weight) Headline the coefficients at the simple roots Usage rootCoefficients(R,p) Inputs R: RootSystem p: Weight Outputs : Vector whose components are the coefficients of {\tt p} at the simple roots of {\tt R} Description Example R=rootSystemE(6) rootCoefficients(R,halfSumOfRoots(R)) /// TEST /// R=rootSystemE(6); r1=simpleRoot(R,1); r2=simpleRoot(R,2); assert(rootCoefficients(R,halfSumOfRoots(R))==vector{8_QQ,11,15,21,15,8}); assert(rootCoefficients(R,r1+r2)==vector{1_QQ,1,0,0,0,0}) /// doc /// Key positiveRoots Headline the set of all positive roots /// doc /// Key (positiveRoots,RootSystem) Headline the set of all positive roots Usage positiveRoots(R) Inputs R: RootSystem Outputs : Set of all positive roots of {\tt R} Description Example positiveRoots(rootSystemA(3)) /// doc /// Key (positiveRoots,RootSystem, Parabolic) Headline the set of all positive roots in a parabolic sugroups Usage positiveRoots(R,P) Inputs R: RootSystem P: Parabolic Outputs : Set of all positive roots of {\tt R} that are written as sums of roots corresponding to reflexions in {\tt P} Description Example R=rootSystemA(4) P=parabolic(R,set{1,2}) positiveRoots(R,P) /// doc /// Key numberOfPositiveRoots Headline the number of positive roots /// doc /// Key (numberOfPositiveRoots,RootSystem) Headline the number of positive roots Usage numberOfPositiveRoots(R) Inputs R: RootSystem Outputs : ZZ the number of positive roots of {\tt R} Description Example numberOfPositiveRoots(rootSystemD(4)) /// doc /// Key (numberOfPositiveRoots,DynkinType) Headline the number of positive roots Usage numberOfPositiveRoots(D) Inputs D: DynkinType Outputs : ZZ the number of positive roots of {\tt D} Description Example D=dynkinType{{"A",5},{"E",6}} numberOfPositiveRoots(D) /// TEST /// R=rootSystemA(4); P=parabolic(R,set{1,2}); assert(#positiveRoots(R,P)==numberOfPositiveRoots(rootSystemA(2))); assert(numberOfPositiveRoots(dynkinType{{"A",2},{"E",6}})==39) /// doc /// Key listWeylGroupElements Headline list all elements of a given length in a Weyl group /// doc /// Key (listWeylGroupElements,RootSystem,ZZ) Headline list all elements of a given length in a Weyl group Usage listWeylGroupElements(R,k) Inputs R: RootSystem k: ZZ Outputs : List of all elements of length {\tt k} in the Weyl group of {\tt R} Description Example listWeylGroupElements(rootSystemG2,4) /// TEST /// assert(set apply(listWeylGroupElements(rootSystemG2,4),reducedDecomposition)===set {{1,2,1,2},{2,1,2,1}}) /// doc /// Key reflect Headline apply the reflection with respect to a root /// doc /// Key (reflect,RootSystem,ZZ,Weight) Headline apply to a weight the reflection with respect to a root Usage reflect(R,i,p) Inputs R: RootSystem i: ZZ p: Weight Outputs : Weight s_i(p) Description Example R = rootSystemB(4) p = halfSumOfRoots(R) reflect(R,4,p) /// doc /// Key (reflect,RootSystem,BasicList,Weight) Headline apply to a weight several reflections with respect to roots Usage reflect(R,L,p) Inputs R: RootSystem L: BasicList p: Weight Outputs : Weight s_{L_0}...s_{L_{\#L-1}}(p) Description Example R = rootSystemB(4) p = halfSumOfRoots(R) reflect(R,{1,2,3,4},p) /// doc /// Key (reflect,RootSystem,ZZ,Root) Headline apply to a root the reflection with respect to a simple root Usage reflect(R,i,r) Inputs R: RootSystem i: ZZ r: Root Outputs : Weight s_i(r) Description Example R = rootSystemB(4) r = simpleRoot(R,3) reflect(R,4,r) /// doc /// Key (reflect,RootSystem,BasicList,Root) Headline apply to a root several reflections with respect to simple roots Usage reflect(R,L,r) Inputs R: RootSystem L: BasicList r: Root Outputs : Weight s_{L_0}...s_{L_{\#L-1}}(r) Description Example R = rootSystemB(4) r = simpleRoot(R,3) reflect(R,{1,2,3,4},r) /// TEST /// R=rootSystemB(4); assert(reflect(R,{1,2,3,4},halfSumOfRoots(R))==weight(R,{-4,1,1,3})) /// doc /// Key WeylGroupElement Headline the class of elements of Weyl groups Description Text {\tt w} is represented by the list consisting of a root system and {\tt w} applied to the half-sum of positive roots Subnodes reduce reducedDecomposition isReduced coxeterLength longestWeylGroupElement reflection isReflection whoseReflection listWeylGroupElements neutralWeylGroupElement underBruhat aboveBruhat isLtBruhat intervalBruhat /// doc /// Key (symbol ==,WeylGroupElement,WeylGroupElement) Headline equality of elements of Weyl groups Usage w1 == w2 Inputs w1: WeylGroupElement w2: WeylGroupElement Outputs : Boolean {\tt true} if {\tt w1} and {\tt w2} belong to the same Weyl group and coincide, and {\tt false} otherwise Description Example w1=reduce(rootSystemD(5),{3}) w1==inverse(w1) /// TEST /// w1=reduce(rootSystemD(5),{3}); assert(w1==inverse(w1)) /// doc /// Key (symbol *,WeylGroupElement,WeylGroupElement) Headline the product of two elements of a Weyl group Usage w1 * w2 Inputs w1: WeylGroupElement w2: WeylGroupElement Outputs : WeylGroupElement the product of {\tt w1} and {\tt w2} Description Example R=rootSystemC(4) w1=reduce(R,{1}) w2=reduce(R,{2}) w1*w2 /// TEST /// R=rootSystemC(4); w1=reduce(R,{1}); w2=reduce(R,{2}); assert(reducedDecomposition(w1*w2*w1)=={1,2,1}) /// doc /// Key (inverse,WeylGroupElement) Headline the inverse to an element of a Weyl group Usage inverse(w) Inputs w: WeylGroupElement Outputs : WeylGroupElement the inverse to {\tt w} Description Example w=reduce(rootSystemE(6),{1,2,3}) inverse w /// TEST /// assert(reducedDecomposition(inverse(reduce(rootSystemE(6),{1,2,3})))=={2,3,1}) /// doc /// Key (symbol ^,WeylGroupElement,ZZ) Headline the power of an element of a Weyl group Usage w^n Inputs w: WeylGroupElement n: ZZ Outputs : WeylGroupElement the {\tt n}-th power of {\tt w} Description Example w=reduce(rootSystemE(6),{1,2,3}) w^10 /// TEST /// R=rootSystemE(6); assert(reducedDecomposition((reduce(R,{1,2,3}))^3)=={2}) /// doc /// Key (symbol *,WeylGroupElement,Weight) Headline apply an element of a Weyl group to a weight Usage w * p Inputs w: WeylGroupElement p: Weight Outputs : Weight {\tt w} applied to {\tt p} Description Example R=rootSystemC(4) w=reduce(R,{1}) p=halfSumOfRoots R w*p /// doc /// Key (symbol *,WeylGroupElement,Root) Headline apply an element of a Weyl group to a root Usage w * r Inputs w: WeylGroupElement r: Root Outputs : Root {\tt w} applied to {\tt r} Description Example R=rootSystemC(4) w=reduce(R,{1}) r=simpleRoot(R,2) w*r /// TEST /// R=rootSystemC(4); w=reduce(R,{1}); p=halfSumOfRoots R assert(w*p==weight(R,{-1,2,1,1})) /// doc /// Key longestWeylGroupElement Headline the longest element of a Weyl group /// doc /// Key (longestWeylGroupElement, RootSystem) Headline the longest element of the Weyl group of a root system Usage longestWeylGroupElement(R) Inputs R: RootSystem Outputs : WeylGroupElement the longest element of the Weyl group of {\tt R} Description Example longestWeylGroupElement rootSystemF4 /// TEST /// assert(reducedDecomposition(longestWeylGroupElement rootSystemG2)=={1,2,1,2,1,2}) /// doc /// Key (longestWeylGroupElement, RootSystem, Parabolic) Headline the longest element of a parabolic subgroup of the Weyl group of a root system Usage longestWeylGroupElement(R,P) Inputs R: RootSystem P: Parabolic Outputs : WeylGroupElement the longest element of the parabolic sugroup of the Weyl group of {\tt R} generated by the reflections in P Description Example R=rootSystemF4; longestWeylGroupElement(R,parabolic(R,set{1,2})) /// TEST /// R=rootSystemF4; assert(reducedDecomposition(longestWeylGroupElement(R,parabolic(R,set{3,4})))=={3,4,3}) /// doc /// Key neutralWeylGroupElement Headline the neutral element of a Weyl group /// doc /// Key (neutralWeylGroupElement, RootSystem) Headline the neutral element of the Weyl group of a root system Usage neutralWeylGroupElement(R) Inputs R: RootSystem Outputs : WeylGroupElement the neutral element of the Weyl group of {\tt R} Description Example neutralWeylGroupElement rootSystemF4 /// TEST /// assert(reducedDecomposition(neutralWeylGroupElement(rootSystemG2))=={}) /// doc /// Key reduce Headline the product of several reflections /// doc /// Key (reduce,RootSystem,BasicList) Headline the product of several reflections with respect to simple roots Usage reduce(R,L) Inputs R: RootSystem L: BasicList Outputs : WeylGroupElement s_{L_0}...s_{L_{\#L-1}} Description Example reduce(rootSystemF4,{1,2,3,4}) /// TEST /// R=rootSystemA(3); assert(reduce(R,{1,3})==reduce(R,{3,1})) /// doc /// Key reducedDecomposition Headline the reduced decomposition of an element of a Weyl group /// doc /// Key (reducedDecomposition, WeylGroupElement) Headline the reduced decomposition of an element of a Weyl group Usage reducedDecomposition(w) Inputs w: WeylGroupElement Outputs : List the lexicographically least reduced decomposition of {\tt w} Description Example reducedDecomposition longestWeylGroupElement rootSystemF4 /// TEST /// assert(reducedDecomposition(longestWeylGroupElement(rootSystemB(2)))=={1,2,1,2}) /// doc /// Key isReduced Headline check whether a decomposition is of minimal length /// doc /// Key (isReduced, RootSystem, BasicList) Headline whether a decomposition in simple reflections is reduced Usage isReduced(R,L) Inputs R: RootSystem L: BasicList of indices of simple reflections Outputs : Boolean true if the length of the product of these simple reflections is indeed their number, and false if not Description Example R=rootSystemF4 L=reducedDecomposition longestWeylGroupElement R isReduced(R,L) L={1,1} isReduced(R,L) /// TEST /// R=rootSystemF4; L=reducedDecomposition longestWeylGroupElement R; assert(isReduced(R,L)==true); L={1,1}; assert(isReduced(R,L)==false) /// doc /// Key (isReduced, BasicList, WeylGroupElement) Headline whether an Weyl group element can be multiplied by some simple reflections with length increasing at each step Usage isReduced(L,w) Inputs L: BasicList of indices of simple reflections w: WeylGroupElement Outputs : Boolean true if the length of the product (on the left) of these simple reflections by w is the length of w plus their number, and false if not Description Example R=rootSystemA(3) w=reduce(R,{1,2,1}) isReduced({2,3},w) isReduced({1},w) /// TEST /// R=rootSystemA(3); w=reduce(R,{1,2,1}); assert(isReduced({2,3},w)); assert(isReduced({1},w)==false) /// doc /// Key coxeterLength Headline the length of a reduced decomposition of an element of a Weyl group /// doc /// Key (coxeterLength, WeylGroupElement) Headline the length of a reduced decomposition of an element of a Weyl group Usage coxeterLength(w) Inputs w: WeylGroupElement Outputs : ZZ the number of simple reflections in a reduced decomposition of {\tt w} Description Example coxeterLength longestWeylGroupElement rootSystemF4 /// TEST /// assert(coxeterLength longestWeylGroupElement rootSystemF4==24) /// doc /// Key reflection Headline the reflection with respect to a root /// doc /// Key (reflection, RootSystem, Root) Headline the reflection with respect to a root Usage reflection(R,r) Inputs R: RootSystem r: Root Outputs : WeylGroupElement the reflection with respect to {\tt r} Description Example R=rootSystemE(8) r=addRoots(R,simpleRoot(R,1),simpleRoot(R,3)) reflection(R,r) /// TEST /// R=rootSystemE(8); r=addRoots(R,simpleRoot(R,1),simpleRoot(R,3)); assert(reducedDecomposition(reflection(R,r))=={1,3,1}) /// doc /// Key isReflection Headline checks whether an element of a Weyl group is a reflection /// doc /// Key (isReflection, WeylGroupElement) Headline checks whether an element of a Weyl group is a reflection Usage isReflection(w) Inputs w: WeylGroupElement Outputs : Boolean {\tt true} if {\tt w} is a reflection and {\tt false} otherwise Description Example R=rootSystemD(5) w=reduce(R,{3}) isReflection(w) /// TEST /// assert(isReflection(reduce(rootSystemD(3),{3}))) /// doc /// Key whoseReflection Headline the positive root whose reflection is a given element of a Weyl group /// doc /// Key (whoseReflection, WeylGroupElement) Headline the positive root whose reflection is a given element of a Weyl group Usage whoseReflection(w) Inputs w: WeylGroupElement Outputs : Root the root whose corresponding reflection is {\tt w} Description Example R=rootSystemD(5) w=reduce(R,{3}) if isReflection(w) then whoseReflection(w) Caveat If {\tt w} is not a reflection, an error occurs. /// TEST /// R=rootSystemD(5); w=reduce(R,{3}); assert(whoseReflection(w)==simpleRoot(R,3)) /// doc /// Key Parabolic Headline the class of parabolic subgroups of Weyl groups Description Text A parabolic subgroup is represented by the set of indices of generating reflections. /// doc /// Key parabolic Headline construct a parabolic /// doc /// Key (symbol ==,Parabolic,Parabolic) Headline equality of parabolics Usage P1 == P2 Inputs P1: Parabolic P2: Parabolic Outputs : Boolean {\tt true} if the underlying sets are equal Description Example R=rootSystemA(3) P1=parabolic(R,set{1,2}) P2=parabolic(R,set{1,2}) P1==P2 /// doc /// Key (parabolic, RootSystem,Set) Headline construct a parabolic from a set of simple roots Usage parabolic(R,S) Inputs R: RootSystem S: Set the subsets of simple roots defining the standard parabolic Outputs : Parabolic a standard parabolic subgroup represented by a set of simple roots Description Example parabolic(rootSystemA(5),set{1,2}) /// TEST /// assert(parabolic(rootSystemA(5),set{1,2})==new Parabolic from set{1,2}) /// doc /// Key (parabolic, WeylGroupDoubleCoset) Headline the parabolic associated to a double coset Usage parabolic(d) Inputs d: WeylGroupDoubleCoset Outputs : Parabolic a standard parabolic subgroup corresponding to the coset {\tt d} as in Carter, {\em Finite Groups of Lie Type}, p. 65, thm 2.7.4. Description Example R=rootSystemA(4) P=parabolic(R,set{1,2,4}) w=reduce(R,{3,2,4,3}) d= P % w % P parabolic(d) /// TEST /// R=rootSystemA(4); P=parabolic(R,set{1,2,4}); w=reduce(R,{3,2,4,3}); d= P % w % P; assert(parabolic(d)==parabolic(R,set{4,2})) /// doc /// Key WeylGroupLeftCoset Headline the class of left cosets of Weyl groups by parabolic subgroup Description Text a coset {wW_P} is represented by the list consisting of a parabolic subgroup {\tt P} and the representative of minimal length {\tt w} /// doc /// Key (symbol ==,WeylGroupLeftCoset,WeylGroupLeftCoset) Headline equality of left cosets Usage w1 == w2 Inputs w1: WeylGroupLeftCoset w2: WeylGroupLeftCoset Outputs : Boolean {\tt true} if {\tt w1} and {\tt w2} belong to the same quotient and coincide, and {\tt false} otherwise Description Example R=rootSystemD(5) P=parabolic(R,set{2,3,4,5}) w=longestWeylGroupElement R w1=w % P w2=(w * reduce(R,{2,3})) % P w1==w2 /// TEST /// R=rootSystemD(5); P=parabolic(R,set{2,3,4,5}); w=longestWeylGroupElement R; w1=w % P; w2=(w * reduce(R,{2,3})) % P; assert(w1==w2) /// doc /// Key WeylGroupRightCoset Headline the class of right cosets of Weyl groups by parabolic subgroups Description Text a coset {W_Pw} is represented by the list consisting of a parabolic subgroup {\tt P} and the representative of minimal length {\tt w} /// doc /// Key (symbol ==,WeylGroupRightCoset,WeylGroupRightCoset) Headline equality of right cosets Usage w1 == w2 Inputs w1: WeylGroupRightCoset w2: WeylGroupRightCoset Outputs : Boolean {\tt true} if {\tt w1} and {\tt w2} belong to the same quotient and coincide, and {\tt false} otherwise Description Example R=rootSystemD(5) P=parabolic(R,set{2,3,4,5}) w=longestWeylGroupElement R w1=P % w w2=P % (reduce(R,{2,3})*w) w1==w2 /// TEST /// R=rootSystemD(5); P=parabolic(R,set{2,3,4,5}); w=longestWeylGroupElement R; w1=P % w; w2=P % (reduce(R,{2,3})*w); assert(w1==w2) /// doc /// Key WeylGroupDoubleCoset Headline the class of double cosets of Weyl groups by pairs of parabolic subgroups Description Text a coset {W_PwW_Q} is represented by the list consisting of parabolic subgroups {\tt P} and {\tt Q}, and the representative of minimal length {\tt w} /// doc /// Key (symbol ==,WeylGroupDoubleCoset,WeylGroupDoubleCoset) Headline equality of double cosets Usage w1 == w2 Inputs w1: WeylGroupDoubleCoset w2: WeylGroupDoubleCoset Outputs : Boolean {\tt true} if {\tt w1} and {\tt w2} belong to the same quotient and coincide, and {\tt false} otherwise Description Example R=rootSystemD(5) P=parabolic(R,set{2,3,4,5}) w=longestWeylGroupElement R w1=P % (w % P) w2=P % ((reduce(R,{4}) * w * reduce(R,{2,3})) % P) w1==w2 /// TEST /// R=rootSystemD(5); P=parabolic(R,set{2,3,4,5}); w=longestWeylGroupElement R; w1=P % (w % P); w2=P % ((reduce(R,{4}) * w * reduce(R,{2,3})) % P); assert(w1==w2) /// doc /// Key (symbol %,WeylGroupElement,Parabolic) Headline the left coset defined by an element of Weyl group Usage w % P Inputs w: WeylGroupElement P: Parabolic Outputs : WeylGroupLeftCoset wW_P Description Example R=rootSystemD(5) P=parabolic(R,set{2,3,4,5}) w=longestWeylGroupElement R w % P /// doc /// Key (symbol %,Parabolic,WeylGroupElement) Headline the right coset defined by an element of Weyl group Usage P % w Inputs P: Parabolic w: WeylGroupElement Outputs : WeylGroupLeftCoset W_Pw Description Example R=rootSystemD(5) P=parabolic(R,set{2,3,4,5}) w=longestWeylGroupElement R P % w /// doc /// Key (symbol %,Parabolic,WeylGroupLeftCoset) Headline the double coset defined by a left coset Usage P % c Inputs P: Parabolic c: WeylGroupLeftCoset Outputs : WeylGroupDoubleCoset W_Pc Description Example R=rootSystemD(5) P=parabolic(R,set{2,3,4,5}) Q=parabolic(R,set{1,2,3,4}) w=longestWeylGroupElement R c = w % Q P % c /// doc /// Key (symbol %,WeylGroupRightCoset,Parabolic) Headline the double coset defined by a right coset Usage c % Q Inputs c: WeylGroupRightCoset Q: Parabolic Outputs : WeylGroupDoubleCoset cW_Q Description Example R=rootSystemD(5) P=parabolic(R,set{2,3,4,5}) Q=parabolic(R,set{1,2,3,4}) w=longestWeylGroupElement R c = P % w c % Q /// doc /// Key (symbol *,WeylGroupElement,WeylGroupLeftCoset) Headline apply an element of a Weyl group to a left coset Usage w * c Inputs w: WeylGroupElement c: WeylGroupLeftCoset Outputs : WeylGroupLeftCoset {\tt w} applied to {\tt c} Description Example R=rootSystemD(5) P=parabolic(R,set{2,3,4,5}) w=longestWeylGroupElement R c=w % P reduce(R,{1})*c /// doc /// Key (symbol *,WeylGroupRightCoset,WeylGroupElement) Headline apply an element of a Weyl group to a left coset Usage c * w Inputs c: WeylGroupRightCoset w: WeylGroupElement Outputs : WeylGroupRightCoset {\tt w} applied to {\tt c} Description Example R=rootSystemD(5) P=parabolic(R,set{2,3,4,5}) w=longestWeylGroupElement R c=P % w c*reduce(R,{1}) /// doc /// Key minimalRepresentative Headline the minimal representative of a coset /// doc /// Key (minimalRepresentative, WeylGroupLeftCoset) Headline the minimal representative of a coset Usage minimalRepresentative(c) Inputs c: WeylGroupLeftCoset Outputs : WeylGroupElement the representative of minimal length Description Example R=rootSystemF4 P=parabolic(R,set{1,2,3}) w=longestWeylGroupElement R c=w % P minimalRepresentative c /// doc /// Key (minimalRepresentative, WeylGroupRightCoset) Headline the minimal representative of a coset Usage minimalRepresentative(c) Inputs c: WeylGroupRightCoset Outputs : WeylGroupElement the representative of minimal length Description Example R=rootSystemF4 P=parabolic(R,set{1,2,3}) w=longestWeylGroupElement R c=P % w minimalRepresentative c /// doc /// Key (minimalRepresentative, WeylGroupDoubleCoset) Headline the minimal representative of a coset Usage minimalRepresentative(c) Inputs c: WeylGroupDoubleCoset Outputs : WeylGroupElement the representative of minimal length Description Example R=rootSystemF4 P=parabolic(R,set{1,2,3}) w=longestWeylGroupElement R c=P % (w % P) minimalRepresentative c /// doc /// Key isMinimalRepresentative Headline check whether an element of a Weyl group is the minimal representative of a coset /// doc /// Key (isMinimalRepresentative, WeylGroupElement, Parabolic) Headline check whether an element of a Weyl group is the minimal representative of a left coset Usage minimalRepresentative(w,P) Inputs w: WeylGroupElement P: Parabolic Outputs : Boolean {\tt true} if {\tt w} is the representative of minimal length of a left coset, and {\tt false} otherwise Description Example R=rootSystemE(6) P=parabolic(R,set{1,2,3,4,5}) w=minimalRepresentative ((longestWeylGroupElement R) % P) isMinimalRepresentative(w,P) Caveat This function is less efficient than the corresponding function for right cosets. /// doc /// Key (isMinimalRepresentative, Parabolic, WeylGroupElement) Headline check whether an element of a Weyl group is the minimal representative of a right coset Usage minimalRepresentative(P,w) Inputs P: Parabolic w: WeylGroupElement Outputs : Boolean {\tt true} if {\tt w} is the representative of minimal length of a right coset, and {\tt false} otherwise Description Example R=rootSystemE(6) P=parabolic(R,set{1,2,3,4,5}) w=minimalRepresentative (P % (longestWeylGroupElement R)) isMinimalRepresentative(P,w) /// doc /// Key (isMinimalRepresentative, Parabolic, WeylGroupElement, Parabolic) Headline check whether an element of a Weyl group is the minimal representative of a double coset Usage minimalRepresentative(P,w,Q) Inputs P: Parabolic w: WeylGroupElement Q: Parabolic Outputs : Boolean {\tt true} if {\tt w} is the representative of minimal length of a double coset, and {\tt false} otherwise Description Example R=rootSystemE(6) P=parabolic(R,set{1,2,3,4,5}) Q=parabolic(R,set{2,3,4,5,6}) w=minimalRepresentative ((P % (longestWeylGroupElement R)) % Q) isMinimalRepresentative(P,w,Q) /// TEST /// R=rootSystemD(5); P=parabolic(R,set{2,3,4,5}); w=longestWeylGroupElement R; c1=P % w; c2=w % P; d=P % c2; assert(reducedDecomposition(minimalRepresentative(c1*reduce(R,{1})))=={1,2,3,4,5,3,2}); assert(reducedDecomposition(minimalRepresentative(reduce(R,{1})*c2))=={2,3,4,5,3,2,1}); assert(reducedDecomposition(minimalRepresentative(d))=={1,2,3,4,5,3,2,1}) assert(isMinimalRepresentative(w,P)==false); assert(isMinimalRepresentative(P,w)==false); assert(isMinimalRepresentative(P,w,P)==false); /// doc /// Key DynkinDiagram Headline the class of Dynkin diagrams Description Text A Dynkin diagram contains lists representing vertices of the Dynkin diagram (in other words a simple root). Each of these lists contains sublists of end points of an edge from the vertex. There are in this order, the simple edges, double edge to a smaller root, double edge to a larger root, triple edge to a smaller root, triple edge to a larger root. If there is no such edge, we have an empty sublist. Example dynkinDiagram(rootSystemB(4)) dynkinDiagram(rootSystemD(4)) /// doc /// Key dynkinDiagram Headline produce a Dynkin Diagram /// doc /// Key (dynkinDiagram, RootSystem) Headline the Dynkin diagram of a root system Usage dynkinDiagram(R) Inputs R: RootSystem Outputs : DynkinDiagram the Dynkin diagram of the root system R Description Example R1=rootSystemA(5) dynkinDiagram(R1) R2=rootSystemF4 dynkinDiagram(R2) /// doc /// Key (dynkinDiagram, DynkinDiagram, Parabolic) Headline the Dynkin diagram of the Levy subgroup of a parabolic Usage dynkinDiagram(D,P) Inputs D: DynkinDiagram P: Parabolic Outputs : DynkinDiagram the Dynkin diagram of the root system of the Levy subgroup of the Parabolic P Description Example R=rootSystemD(5) D1=dynkinDiagram(R) P=parabolic(R,set{1,3,4,5}) D2=dynkinDiagram(D1,P) dynkinType(D2) /// TEST /// R=rootSystemD(5); D1=dynkinDiagram(R); P=parabolic(R,set{1,3,4,5}); D2=dynkinDiagram(D1,P); assert(dynkinType(D1)==dynkinType{{"D",5}}); assert(dynkinType(D2)==dynkinType{{"A",1},{"A",3}}) /// doc /// Key connectedComponents Headline get the connected components /// doc /// Key (connectedComponents,DynkinDiagram) Headline the connected components of a Dynkin diagram Usage connectedComponents(D) Inputs D: DynkinDiagram Outputs : List containing Dynkin diagrams that are connected and whose disjoint union is D Description Example R=rootSystemE(6)++rootSystemF4 D=dynkinDiagram(R) connectedComponents(D) /// TEST /// R=rootSystemE(6)++rootSystemF4 D=dynkinDiagram(R) assert(apply(connectedComponents(D),dynkinType)=={dynkinType{{"E",6}},dynkinType{{"F",4}}}) /// doc /// Key endVertices Headline the vertices with at most one edge /// doc /// Key (endVertices,DynkinDiagram) Headline the vertices of a Dynkin diagram with at most one neighbor Usage connectedComponents(D) Inputs D: DynkinDiagram Outputs : List containing the vertices of D whose removal does not disconnect any part of D. They can have at most one neighbor. Description Example R=rootSystemE(6) D=dynkinDiagram(R) endVertices(D) /// TEST /// R=rootSystemD(4); D=dynkinDiagram(R); assert(endVertices(D)===set{1,3,4}) /// doc /// Key DynkinType Headline the class of Dynkin Types Description Text A Dynkin Type is a list of items representing Dynkin types of irreducible root systems. These types are a string (the letter representing the family A, B, C, D, E, F or G) and an integer, the rank. Example R=rootSystemB(4)++rootSystemA(6) dynkinType(R) /// doc /// Key (symbol ++,DynkinType,DynkinType) Headline the disjoint union of Dynkin Types Usage T1 ++ T2 Inputs T1: DynkinType T2: DynkinType Outputs : DynkinType the disjoint union (concatenation) of {\tt T1} and {\tt T2} Description Example T1=dynkinType(rootSystemB(2)) T2=dynkinType(rootSystemA(3)) T1++T2 Text Note that it is not reordered. /// doc /// Key (symbol ==,DynkinType,DynkinType) Headline the equality of Dynkin Types Usage T1 == T2 Inputs T1: DynkinType T2: DynkinType Outputs : Boolean true if {\tt T1} is isomorphic to {\tt T2} and false if not Description Example T1=dynkinType(rootSystemB(2)) T2=dynkinType(rootSystemA(3)) (T1++T2) == (T2++T1) Text whereas Example (T1++T2) === (T2++T1) /// doc /// Key dynkinType Headline obtaining a Dynkin type /// doc /// Key (dynkinType,DynkinDiagram) Headline the Dynkin type of a Dynkin diagram Usage dynkinType(D) Inputs D: DynkinDiagram Outputs : List of types of the connected components of the Dynkin diagram {\tt D} Description Example R=rootSystemE(6)++rootSystemA(4)++rootSystemB(3)++rootSystemA(4); D=dynkinDiagram(R); dynkinType(D) /// doc /// Key (dynkinType,BasicList) Headline constructing a Dynkin type Usage dynkinType(L) Inputs L: BasicList of irreducible types that are lists containing a string of one letter from A to F and a positive integer, the rank Outputs : DynkinType Description Example dynkinType({{"A",2},{"B",3}}) Text Note that low rank isomorphisms between classical groups are automatically used so that the letter is alphabetically minimal and the elementary types are irreducible (D2=A1xA1). Example dynkinType({{"A",2},{"B",1}}) dynkinType({{"A",2},{"C",2}}) dynkinType({{"A",2},{"D",2}}) /// doc /// Key (dynkinType,RootSystem) Headline the Dynkin type of a root system Usage dynkinType(R) Inputs R: RootSystem Outputs : List of types of the irreducible components of the root system {\tt R} Description Example R=rootSystemE(6)++rootSystemA(4)++rootSystemB(3)++rootSystemA(4); dynkinType(R) /// TEST /// T1=dynkinType(rootSystemB(2)); T2=dynkinType(rootSystemA(3)); assert((T1++T2) == (T2++T1)) /// doc /// Key dynkinExponents Headline the exponents associated to a type /// doc /// Key (dynkinExponents,DynkinType) Headline the exponents of the Dynkin type Usage dynkinExponents(D) Inputs D: DynkinType Outputs : List of lists of integers, the exponents listed in the tables in Bourbaki, Lie groups and Lie algebras, following chapter 6. Description Example R=rootSystemE(6)++rootSystemA(4)++rootSystemB(3)++rootSystemA(4); dynkinExponents(dynkinType(R)) /// TEST /// R=rootSystemE(6)++rootSystemA(4)++rootSystemB(3)++rootSystemA(4); assert(dynkinExponents(dynkinType(R))=={{1, 2, 3, 4}, {1, 2, 3, 4}, {1, 3, 5}, {1, 4, 5, 7, 8, 11}}); /// doc /// Key poincareSeries Headline a generating series for number of elements in a Weyl group /// doc /// Key (poincareSeries,RootSystem,RingElement) Headline the generating series of the Weyl group by length Usage poincareSeries(R,x) Inputs R: RootSystem x: RingElement Outputs : RingElement a polynomial in the variable {\tt x} where the coefficient in front of {\tt x^i} is the number of elements in the Weyl group of R of length i. Description Example R=rootSystemA(2) ZZ[x] poincareSeries(R,x) /// doc /// Key (poincareSeries,RootSystem,Parabolic,RingElement) Headline the generating series of a quotient of the Weyl group by length Usage poincareSeries(R,P,x) Inputs R: RootSystem P: Parabolic x: RingElement Outputs : RingElement a polynomial in the variable {\tt x} where the coefficient in front of {\tt x^i} is the number of cosets in the Weyl group of R modulo the Weyl group of P where the minimal element is of length i. Description Example R=rootSystemA(3) P=parabolic(R,set{1,2}) ZZ[x] poincareSeries(R,P,x) /// TEST /// R=rootSystemA(3); P=parabolic(R,set{1,2}); ZZ[x]; assert(poincareSeries(R,x)==x^6+3*x^5+5*x^4+6*x^3+5*x^2+3*x+1); assert(poincareSeries(R,P,x)==x^3+x^2+x+1) /// doc /// Key (poincareSeries,HasseDiagram,RingElement) Headline the generating series of a Hasse diagram Usage poincareSeries(H,x) Inputs H: HasseDiagram x: RingElement Outputs : RingElement a polynomial in the variable {\tt x} where the coefficient in front of {\tt x^i} is the number of elements in the i-th row of {\tt H} (counting from 0). Description Example R=rootSystemA(2) H=intervalBruhat(neutralWeylGroupElement R, longestWeylGroupElement R) ZZ[x] poincareSeries(H,x) /// TEST /// R=rootSystemA(2); H=intervalBruhat(neutralWeylGroupElement R, longestWeylGroupElement R); ZZ[x]; assert(poincareSeries(H,x)==x^3+2*x^2+2*x+1) /// doc /// Key (rank,DynkinDiagram) Headline the rank of a Dynkin diagram Usage rank(D) Inputs D: DynkinDiagram Outputs : ZZ the number of vertices of the Dynkin diagram {\tt D} Description Example R=rootSystemE(6) D=dynkinDiagram(R); rank(D) /// TEST /// R=rootSystemE(6); D=dynkinDiagram(R); assert(rank(D)==6) /// doc /// Key isLtBruhat Headline compare two Weyl group elements in the Bruhat order /// doc /// Key (isLtBruhat,WeylGroupElement,WeylGroupElement) Headline compare two Weyl group elements in the Bruhat order Usage isLtBruhat(w1,w2) Inputs w1: WeylGroupElement w2: WeylGroupElement Outputs : Boolean {\tt true} if {\tt w1} is less then {\tt w2} in the Bruhat order Description Example R=rootSystemA(3) w1=reduce(R,{3,1,2}); w2=reduce(R,{1,2,3,2,1}); isLtBruhat(w1,w2) /// TEST /// R=rootSystemA(3); w1=reduce(R,{3,1,2}); w2=reduce(R,{1,2,3,2,1}); w3=reduce(R,{1,2,3}); assert(isLtBruhat(w1,w2)); assert(isLtBruhat(w1,w3)==false) /// doc /// Key underBruhat Headline obtain Weyl group elements less than an element for the Bruhat order /// doc /// Key (underBruhat,WeylGroupElement) Headline Weyl group elements just under a given one for the Bruhat order Usage underBruhat(w) Inputs w: WeylGroupElement Outputs : List of elements smaller than {\tt w} and of length one less together with the root whose reflection is composed with w (on the right) to obtain the element Description Example R=rootSystemA(3) L=underBruhat(longestWeylGroupElement(R)) apply(L,x->reducedDecomposition (x#0)) /// doc /// Key (underBruhat,BasicList) Headline Weyl group elements just under the ones in the list for the Bruhat order Usage underBruhat(B) Inputs B: BasicList of WeylGroupElement Outputs : List of elements smaller than the ones in {\tt B} and of length one less together with the root of the reflection composed with (on the right) to obtain the element Description Example R=rootSystemA(3) L=underBruhat(longestWeylGroupElement(R)) L1=apply(L,x->x#0) underBruhat(L1) /// doc /// Key aboveBruhat Headline obtain Weyl group elements just greater than an element for the Bruhat order /// doc /// Key (aboveBruhat,WeylGroupElement) Headline Weyl group elements just above a given one for the Bruhat order Usage aboveBruhat(w) Inputs w: WeylGroupElement Outputs : List of elements greater than {\tt w} and of length one more together with the root whose reflection is composed with w (on the right) to obtain the element Description Example R=rootSystemA(3) L=aboveBruhat(neutralWeylGroupElement(R)) apply(L,x->reducedDecomposition (x#0)) /// doc /// Key (aboveBruhat,BasicList) Headline The Weyl group elements just under the ones in the list for the Bruhat order Usage aboveBruhat(B) Inputs B: BasicList of WeylGroupElement Outputs : List of elements greater than the ones in {\tt B} and of length one more together with the root of the reflection composed with (on the right) to obtain the element Description Example R=rootSystemA(3) L=aboveBruhat(neutralWeylGroupElement(R)) L1=apply(L,x->x#0) aboveBruhat(L1) /// doc /// Key HasseDiagram Headline the class of Hasse diagrams Description Text A Hasse diagram is a list describing the connexions in a Hasse diagram. It contains sublists representing rows. Each row contains several vertices together with edges to some element in the next row given by its position in the row. This data format is intended for displaying. /// doc /// Key HasseGraph Headline the class of Hasse graphs Description Text A Hasse graph is a Hasse diagram ready for display. It contains labels instead of Weyl group elements and reflections. Subnodes hasseDiagramToGraph hasseGraphToPicture storeHasseGraph loadHasseGraph /// doc /// Key hasseGraphToPicture Headline construct the picture of a Hasse Graph /// doc /// Key (hasseGraphToPicture,HasseGraph) Headline Obtain a picture from a Hasse graph Usage hasseGraphToPicture(H) Inputs H: HasseGraph Outputs : Picture describing the Hasse graph in the picture language of the package Graphics /// doc /// Key intervalBruhat Headline obtaining an interval for the Bruhat order /// doc /// Key (intervalBruhat,WeylGroupElement,WeylGroupElement) Headline elements between two given ones for the Bruhat order on a Weyl group Usage intervalBruhat(u,v) Inputs u: WeylGroupElement the lower bound of the interval v: WeylGroupElement the upper bound of the interval Outputs : HasseDiagram of elements smaller than {\tt u} and bigger than {\tt v} together with the reflections to go from an element to the next one (on the right) attached to the corresponding edge. Description Example R=rootSystemA(3) w1 = reduce(R,{2,1,2}) w2 = reduce(R,{1,2,1,3,2}) myInterval=intervalBruhat(w1,w2) Text Each row of the Hasse diagram contains the elements of a certain length together with their links to the next row. Example myInterval#1 /// doc /// Key (intervalBruhat,WeylGroupLeftCoset,WeylGroupLeftCoset) Headline elements between two given ones for the Bruhat order on a quotient of a Weyl group Usage intervalBruhat(u,v) Inputs u: WeylGroupLeftCoset v: WeylGroupLeftCoset Outputs : HasseDiagram of elements of minimal length in their cosets, bigger than {\tt u} and smaller than {\tt v}, together with the reflections to go from an element to the next one (on the right) attached to the corresponding edge. Description Example R=rootSystemA(3) P=parabolic(R,set {3}) w1 = reduce(R,{2}) w2 = reduce(R,{1,2,1,3,2}) myInterval=intervalBruhat(w1 % P,w2 % P) Text Each row of the Hasse diagram contains the elements of a certain length together with their links to the next row. Example myInterval#1 /// doc /// Key (intervalBruhat,WeylGroupRightCoset,WeylGroupRightCoset) Headline elements between two given ones for the Bruhat order on a quotient of a Weyl group Usage intervalBruhat(u,v) Inputs u: WeylGroupRightCoset v: WeylGroupRightCoset Outputs : HasseDiagram of elements of minimal length in their coset, bigger than {\tt u} and smaller than {\tt v}, together with the reflections to go from an element to the next one (on the right) attached to the corresponding edge. Description Example R=rootSystemA(3) P=parabolic(R,set {3}) w1 = reduce(R,{2}) w2 = reduce(R,{1,2,1,3,2}) myInterval=intervalBruhat(P % w1,P % w2) Text Each row of the Hasse diagram contains the elements of a certain length together with their links to the next row. Example myInterval#1 /// TEST /// R=rootSystemA(3); P=parabolic(R,set {3}); w1 = reduce(R,{2}); w2 = reduce(R,{1,2,1,3,2}); myInterval=intervalBruhat(P % w1,P % w2); G = hasseDiagramToGraph(myInterval, "labels" => "reduced decomposition") -- the following test is dependent on the order chosen -- this test should be changed to check correctness, not the specific order of nodes assert(#G == 5) G = toList G; assert(G/length == {1,2,3,3,1}) -- check that the labels are all as expected assert(G/(x -> x/first//set) === { set{"12132"}, set{"2132", "1213"}, set{"121", "213", "123"}, set{"21", "23", "12"}, set{"2"}}) -- we should check that the links are correct too. -- the following is one possible answer, but it can change. Why?! -* assert(G#0 == {{"12132", {{"3", 0}, {"2", 1}}}}); assert(G#1 == { {"2132", {{"232", 1}, {"2", 2}}}, {"1213", {{"1", 0}, {"3", 1}, {"232", 2}}} }); assert(G#2 == { {"123", {{"3", 0}, {"12321", 2}}}, {"121", {{"1", 0}, {"2", 1}}}, {"213", {{"3", 1}, {"1", 2}}} }); assert(G#3 == {{"12", {{"121", 0}}}, {"21", {{"1", 0}}}, {"23", {{"3", 0}}}}) assert(G#4 == {{"2", {}}}) *- /// doc /// Key hasseDiagramToGraph Headline turning a hasse diagram into a graph (intended for graphic representation) /// doc /// Key (hasseDiagramToGraph,HasseDiagram) Headline turning a hasse diagram into a graph (intended for graphic representation) Usage hasseDiagramToGraph(h) Inputs h: HasseDiagram Outputs : HasseGraph Description Text By default, the HasseGraph will have vertices with empty labels. Example R=rootSystemA(3) w1 = reduce(R,{2}) w2 = reduce(R,{1,2,1,3,2}) myInterval=intervalBruhat(w1,w2) hasseDiagramToGraph(myInterval) Text It is also possible to ask for reduced decompositions as labels by changing the option "labels" as below. Example hasseDiagramToGraph(myInterval,"labels"=>"reduced decomposition") /// TEST /// R=rootSystemA(3); w1 = reduce(R,{2,1,2}); w2 = reduce(R,{1,2,1,3,2}); myInterval=intervalBruhat(w1,w2); assert(hasseDiagramToGraph(myInterval)===new HasseGraph from {{{"", {{"", 0}, {"", 1}}}}, {{"", {{"", 0}}}, {"", {{"", 0}}}}, {{"", {}}}}) /// doc /// Key storeHasseGraph Headline store a Hasse graph in a file /// doc /// Key (storeHasseGraph,HasseGraph,String) Headline store a Hasse graph in a file Usage storeHasseGraph(H,f) Inputs H: HasseGraph f: String a file name Description Text Will store the Hasse graph {\tt H} in the file {\tt f} so that it can be retrieved later with "loadHasseGraph". SeeAlso "loadHasseGraph(String)" /// doc /// Key loadHasseGraph Headline load a Hasse graph from a file /// doc /// Key (loadHasseGraph,String) Headline load a Hasse graph from a file Usage loadHasseGraph(f) Inputs f: String a file name Description Text Will load a Hasse graph from the file {\tt f}. SeeAlso "storeHasseGraph(HasseGraph,String)" ///