#
# Count the number of maximal chains (=reduced expressions) in Bruhat order.
#
# Let W be a Weyl group with simple reflections r[1],...r[n], and longest
# element w0. This procedure counts the number of chains in Bruhat order
# from w to w0; i.e., the number of sequences [i_1,...,i_l] of minimum
# length such that w*r[i_1]*...*r[i_l] = w0. Note that this is also the
# number of reduced expressions for w^(-1) * w0  or  w0 * w.
#
# Parameters: R = a root system for W; w = a sequence of integers
# representing a product of simple reflections.
#
# Syntax:
#   ct_chains(w,R);
#   ct_chains(w,R,<name_for_a_table>);
#
# In the second form, the procedure will assign to a third argument a
# table of values of the number of maximal chains from w0 to w' for every
# w' in the Bruhat interval from w to w0. The indices of the tables are
# vectors that label the elements of W. To convert from a word to a vector,
# use the procedure 'word2vec(w,R)' provided below.
# 
# The space used will be proportional to the width of the Bruhat interval
# from w to w0. (Unless there is a third argument--in which case the space
# will be proportional to the size of the entire interval.)
#
ct_chains:=proc(w,R) local S,v,old,new,oldnum,newnum,i,j,k,res;
  S:=coxeter['base'](R);
  v:=coxeter['interior_pt'](S);
  old:=[coxeter['reflect'](seq(S[i],i=w),v)];
  oldnum:=[1]; res:=table(); 
  do;
    if nargs>2 then for j to nops(old) do res[old[j]]:=oldnum[j] od fi;
    new:=[]; newnum:=[];
    for j to nops(old) do;
      for i to nops(S) do;     
        if coxeter['iprod'](old[j],S[i])<0 then next fi;
        v:=coxeter['reflect'](S[i],old[j]);
        if member(v,new,'k') then newnum:=subsop(k=newnum[k]+oldnum[j],newnum)
          else new:=[op(new),v]; newnum:=[op(newnum),oldnum[j]] fi;
      od;  
    od;  
    if nops(new)=0 then break fi;
    old:=new; oldnum:=newnum;
  od;
  if nargs>2 then assign(args[3],op(res)) fi;
  op(oldnum);
end;  
#
word2vec:=proc(w) local S,i;
  if type(args[2],'list') then S:=args[2] else S:=coxeter['base'](args[2]) fi;
  coxeter['reflect'](seq(S[i],i=w),coxeter['interior_pt'](S));
end;
#
# Examples:
#  ct_chains([],B3);
#  ct_chains([],D4,'ct');
#  ct[word2vec([3,1,2,3,4,3,1],D4)];
#
