###########################################################################
# #
# Quantum Calculator #
# Copyright (C) 2008 Anders S. Buch #
# (asbuch at math dot rutgers dot edu) #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see . #
# #
###########################################################################
qcalc := module()
option package;
export
set_type, get_type, Gr, IG, OG, type_string,
schub_classes, generators, point_class,
pieri, act, giambelli, mult, toS,
qpieri, qact, qgiambelli, qmult, qtoS,
dualize, type_swap, miami_swap, schub_type,
part2pair, pair2part, part2index, index2part, apply_lc;
local _k, _n, _type, _pieri, _qpieri, fail_no_type, _dcoef,
spec2num, num2spec, giambelli_rec_inner, giambelli_rec, act_lc,
pieri_set, count_comps, _pieri_fillA, _pieri_itrA,
_pieri_fill, _pieri_itr, _part_star,
_part_tilde, part2pair_inner, pair2part_inner,
type_swap_inner, miami_swap_inner, dualize_index_inner,
part2indexA_inner, part2indexC_inner, part2indexB_inner, part2indexD_inner,
index2partA_inner, index2partC_inner, index2partB_inner, index2partD_inner,
part_len, part_clip, part_conj, part_itr, part_itr_between,
all_kstrict, _first_kstrict, _itr_kstrict,
pieriA_inner, pieriC_inner, pieriB_inner, pieriD_inner,
qpieriA_inner, qpieriC_inner, qpieriB_inner, qpieriD_inner;
##################################################################
# Common interface for all types
##################################################################
fail_no_type := proc()
ERROR("Must set type with IG or OG or set_type functions.");
end:
_type := false:
_k := false:
_n := false:
_pieri := fail_no_type:
_qpieri := fail_no_type:
set_type := proc(tp, k, n)
if k<0 or n`if`(member(_k,mu), {S[op(mu)],S[op(mu),0]},
{S[op(mu)]}), all_kstrict(_k, _n+1-_k, _n+_k))));
else
map(lam -> S[op(lam)], all_kstrict(_k,_n-_k,_n+_k));
end:
end:
generators := proc()
local i;
if not type(_type,string) then fail_no_type() fi;
if _type<>"D" and _k=_n then RETURN([]); fi;
[seq(S[i],i=1.._k),`if`(_type="D" and _k>0,S[_k,0],NULL),
`if`(_type<>"A",seq(S[i],i=_k+1.._n+_k),NULL)];
end:
point_class := proc()
local i;
if not type(_type,string) then fail_no_type() fi;
if _type="A" then RETURN(S[`if`(_k>0,_k$(_n-_k),NULL)]); fi;
S[seq(_n+_k-i, i=0.._n-_k-`if`(_type="D" and _k>0,0,1))];
end:
part2pair := proc(lc)
if _type="A" then ERROR("Only types B,C,D."); fi;
if type(lc,list) then
part2pair_inner(lc);
else
apply_lc(lam->part2pair_inner(lam,_k), lc);
fi;
end:
pair2part := proc(lc)
if _type="A" then ERROR("Only types B,C,D."); fi;
if type(lc,list) and nops(lc)=2 then
pair2part_inner(lc);
else
apply_lc(pair->pair2part_inner(pair), lc);
fi;
end:
part2index := proc(lc)
if type(lc,list) then RETURN(part2index(S[op(lc)])); fi;
if _type="A" then
apply_lc(lam->part2indexA_inner(lam,_k,_n), lc);
elif _type="C" then
apply_lc(lam->part2indexC_inner(lam,_k,_n), lc);
elif _type="B" then
apply_lc(lam->part2indexB_inner(lam,_k,_n), lc);
elif _type="D" then
apply_lc(lam->part2indexD_inner(lam,_k,_n), lc);
else
fail_no_type();
fi;
end:
index2part := proc(lc)
if type(lc,list) then RETURN(index2part(S[op(lc)])); fi;
if _type="A" then
apply_lc(idx->index2partA_inner(idx,_k,_n), lc);
elif _type="C" then
apply_lc(idx->index2partC_inner(idx,_k,_n), lc);
elif _type="B" then
apply_lc(idx->index2partB_inner(idx,_k,_n), lc);
elif _type="D" then
apply_lc(idx->index2partD_inner(idx,_k,_n), lc);
else
fail_no_type();
fi;
end:
dualize := proc(lc)
local N;
N := `if`(_type="A",_n,
`if`(_type="C", 2*_n, `if`(_type="B", 2*_n+1, 2*_n+2)));
index2part(apply_lc(idx->dualize_index_inner(idx,N,_type),
part2index(lc)));
end:
type_swap := proc(lc)
if type(lc,list) then RETURN(type_swap(S[op(lc)])); fi;
if _type="D" then
apply_lc(lam->type_swap_inner(lam,_k), lc);
else
lc;
fi;
end:
miami_swap := proc(lc)
if type(lc,list) then RETURN(miami_swap(S[op(lc)])); fi;
if _type="D" then
apply_lc(lam->miami_swap_inner(lam,_k), lc);
else
lc;
fi;
end:
schub_type := proc(lam)
if not type(_type,string) then fail_no_type() fi;
if _type<>"D" or not (type(lam,list) or type(lam,indexed)) then
ERROR("No type defined.");
fi;
if not member(_k,{op(lam)}) then
0;
elif nops(lam)=0 or op(-1,lam)>0 then
1;
else
2;
fi;
end:
pieri := proc(i, lc)
if type(lc,list) then
_pieri(i, lc, _k, _n)
else
apply_lc(p->_pieri(i,p,_k,_n), lc);
fi;
end:
act := proc(expr, lc)
act_lc(expr, lc, (i,p)->_pieri(i,p,_k,_n));
end:
giambelli := proc(lc)
giambelli_rec(lc, (i,p)->_pieri(i,p,_k,_n), _k);
end:
mult := proc(lc1, lc2)
act(giambelli(lc1), lc2);
end:
toS := proc(lc)
act(giambelli(lc), S[]);
end:
qpieri := proc(i, lc)
if type(lc,list) then
_qpieri(i, lc, _k, _n)
else
apply_lc(p->_qpieri(i,p,_k,_n), lc);
fi;
end:
qact := proc(expr, lc)
act_lc(expr, lc, (i,p)->_qpieri(i,p,_k,_n));
end:
qgiambelli := proc(lc)
giambelli_rec(lc, (i,p)->_qpieri(i,p,_k,_n), _k);
end:
qmult := proc(lc1, lc2)
qact(qgiambelli(lc1), lc2);
end:
qtoS := proc(lc)
qact(qgiambelli(lc), S[]);
end:
##################################################################
# Type A: Quantum cohomology of Gr(n-k,n).
##################################################################
pieriA_inner := proc(i, lam, k,n)
option remember;
local inner, outer, mu, res;
inner := [op(lam), 0$(n-k-nops(lam))];
outer := [k,op(1..-2,inner)];
mu := _pieri_fillA(inner, inner, outer, 1, i);
res := 0;
while type(mu,list) do
res := res + S[op(part_clip(mu))];
mu := _pieri_itrA(mu, inner, outer);
od;
res;
end:
qpieriA_inner := proc(i, lam, k,n)
local res, lab, j;
res := pieriA_inner(i, lam, k,n);
if nops(lam)=n-k and lam[n-k]>0 then
lab := [seq(`if`(lam[j]>1, lam[j]-1, NULL), j=1..nops(lam))];
res := res + expand(q * apply_lc(x->_part_star(x,k-1),
pieriA_inner(i-1,lab,k-1,n)));
fi;
res;
end:
##################################################################
# Type C: Quantum cohomology of symplectic IG(n-k,2n).
##################################################################
pieriC_inner := proc(i, lam, k,n)
option remember;
convert(map(x->2^count_comps(lam,x,true,k,0)*S[op(x)],
pieri_set(i,lam,k,n,0)),`+`);
end:
qpieriC_inner := proc(i, lam, k,n)
pieriC_inner(i, lam, k,n) +
expand(q/2 * apply_lc(x->_part_star(x,n+k+1), pieriC_inner(i, lam, k, n+1)));
end:
##################################################################
# Type B: Quantum cohomology of odd orthogonal OG(n-k,2n+1).
##################################################################
pieriB_inner := proc(p, lam, k,n)
option remember;
local b;
b := `if`(p <= k, 0, 1);
convert(map(mu -> 2^(count_comps(lam,mu,false,k,0)-b) * S[op(mu)],
pieri_set(p,lam,k,n,0)), `+`);
end:
qpieriB_inner := proc(p, lam, k,n)
local res;
res := pieriB_inner(p, lam, k,n);
if k=0 then
if nops(lam)>0 and lam[1]=n+k then
res := res + q * apply_lc(x->_part_star(x,n+k),
pieriB_inner(p,[op(2..-1,lam)],k,n));
fi;
else
if nops(lam)=n-k and lam[n-k]>0 then
res := res + q * apply_lc(x->_part_tilde(x,n-k+1,n+k),
pieriB_inner(p, lam, k,n+1));
fi;
if nops(lam)>0 and lam[1]=n+k then
res := res + q^2 * apply_lc(x->_part_star(x,n+k),
pieriB_inner(p,[op(2..-1,lam)],k,n));
fi;
fi;
expand(res);
end:
##################################################################
# Type D: Quantum cohomology of even orthogonal OG(n+1-k,2n+2).
##################################################################
pieriD_inner := proc(p, lam, k,n)
option remember;
local tlam;
tlam := `if`(not member(k,lam), 0, `if`(lam[-1]=0, 2, 1));
convert(map(mu -> _dcoef(p,lam,mu,tlam,k,n),
pieri_set(abs(p),lam,k,n,1)), `+`);
end:
_dcoef := proc(p, lam, mu, tlam, k,n)
local cc, h, pmu, i, tmu, lami;
cc := count_comps(lam, mu, false, k,1) - `if`(abs(p)= 0 then
if not member(k,mu) or tlam=1 then
2^cc*S[op(mu)]
elif tlam=2 then
2^cc*S[op(mu),0]
else
2^cc*S[op(mu)] + 2^cc*S[op(mu),0]
fi;
else
# Tie breaking
h := k + tlam + `if`(p<0,1,0);
pmu := 0;
for i from nops(mu) to 1 by -1 while pmu < k do
lami := `if`(i <= nops(lam), lam[i], 0);
if lami0 and lam[1]=n+k then
res := res + q * apply_lc(x->_part_star(x,n+k),
pieriD_inner(p, [op(2..-1,lam)], k,n));
fi;
elif k=1 then
if nops(lam)>=n and lam[n]>0 then
lb := part_clip([seq(max(x-1,0),x=lam)]);
cprd := `if`(abs(p)>1, pieriD_inner(abs(p)-1,lb,0,n), S[op(lb)]);
intn := {seq(i,i=1..n)};
cprd := apply_lc(mu ->
S[op(ListTools[Reverse]([op(intn minus {op(mu)})]))], cprd);
res1 := 0;
if lam[-1]>0 and p>0 then
res1 := q1*apply_lc(mu -> S[seq(x+1,x=mu),1$(n-nops(mu))], cprd);
fi;
if (lam[-1]=0 or not member(k,lam)) and (p=-1 or p>1) then
res1:=res1 + q2*apply_lc(mu-> S[seq(x+1,x=mu),1$(n-nops(mu)),0],cprd);
fi;
res := res + dualize(res1);
fi;
if nops(lam)>0 and lam[1]=n+k then
res := res + q1*q2 * apply_lc(x->_part_star(x,n+k),
pieriD_inner(p, [op(2..-1,lam)], k,n));
fi;
else
if nops(lam)>=n+1-k and lam[n+1-k]>0 then
res := res + q * type_swap(apply_lc(x->_part_tilde(x,n-k+2,n+k),
pieriD_inner(p, lam, k,n+1)), k);
fi;
if nops(lam)>0 and lam[1]=n+k then
res := res + q^2 * apply_lc(x->_part_star(x,n+k),
pieriD_inner(p, [op(2..-1,lam)], k,n));
fi;
fi;
expand(res);
end:
##################################################################
# General cohomology calculations, depending on Pieri rule.
##################################################################
spec2num := proc(sc)
if (not type(sc,indexed)) or op(0,sc)<>`S` or nops(sc)=0 then
ERROR("special schubert class expected");
fi;
if nops(sc)>1 and (_type<>"D" or op(2,sc)<>0) then
ERROR("single part expected");
fi;
`if`(nops(sc)>1, -op(1,sc), op(1,sc));
end:
num2spec := proc(p)
`if`(p>0, S[p], S[-p,0]);
end:
apply_lc := proc(f, lc)
if type(lc, `+`) or type(lc, `*`) or type(lc, `^`) then
RETURN(expand(map2(apply_lc, f, lc)));
elif type(lc, indexed) and op(0,lc) = `S` then
RETURN(f([op(lc)]));
else
RETURN(lc);
fi;
end:
act_lc := proc(expc, lc, pieri)
local vars, v, i, expc0, expc1;
vars := indets(expc) minus {q};
if nops(vars) = 0 then
RETURN(expc * lc);
fi;
v := vars[1];
i := spec2num(v);
expc0 := subs(v=0, expc);
expc1 := expand((expc - expc0) / v);
apply_lc(p->pieri(i,p), act_lc(expc1,lc,pieri)) + act_lc(expc0,lc,pieri);
end:
giambelli_rec_inner := proc(lam, pieri, k)
option remember;
local p, lam0, stuff;
if nops(lam)=0 then RETURN(1); fi;
p := lam[1];
if p=k and lam[-1]=0 then p := -k; fi;
lam0 := [op(2..`if`(lam[-1]=0 and lam[2]giambelli_rec_inner(x,pieri,k), lc);
end:
##################################################################
# Pieri rule internals
##################################################################
_pieri_fillA := proc(lam, inner, outer, r, p)
local res, pp, rr, x;
if nops(lam) = 0 then RETURN(lam); fi;
res := array(lam);
pp := p;
rr := r;
if rr = 1 then
x := min(outer[1], inner[1]+pp);
res[1] := x;
pp := pp - x + inner[1];
rr := 2;
fi;
while rr <= nops(lam) do
x := min(outer[rr], inner[rr]+pp, res[rr-1]);
res[rr] := x;
pp := pp - x + inner[rr];
rr := rr + 1;
od;
if pp > 0 then RETURN(false); fi;
[seq(res[rr], rr=1..nops(lam))];
end:
_pieri_itrA := proc(lam, inner, outer)
local p, r, lam1;
if nops(lam) = 0 then RETURN(false); fi;
p := lam[-1] - inner[-1];
for r from nops(lam)-1 to 1 by -1 do
if lam[r] > inner[r] then
lam1 := subsop(r=lam[r]-1, lam);
lam1 := _pieri_fillA(lam1, inner, outer, r+1, p+1);
if lam1 <> false then RETURN(lam1); fi;
p := p + lam[r] - inner[r];
fi;
od;
false;
end:
count_comps := proc(lam1, lam2, skipfirst, k,d)
local top1,bot1, top2,bot2, lb2, comps, i,j,b, res, incomp, minj,maxj;
top1 := part_conj([seq(min(lam1[i],k), i=1..nops(lam1))]);
top1 := [op(top1), 0$(k-nops(top1))];
bot1 := [op(part_clip([seq(max(0,lam1[i]-k), i=1..nops(lam1))])), 0];
top2 := part_conj([seq(min(lam2[i],k), i=1..nops(lam2))]);
top2 := [op(top2), 0$(k-nops(top2))];
bot2 := part_clip([seq(max(0,lam2[i]-k), i=1..nops(lam2))]);
lb2 := nops(bot2);
if lb2 = 0 then RETURN(0); fi;
comps := array([0$bot2[1]]);
for i from 1 to lb2 do
for j from bot1[i]+1 to bot2[i] do
comps[j] := 1;
od;
od;
b := 1;
for i from 1 to k do
if top2[i] <= top1[i] then
while b < lb2 and bot1[b]+b-1 > top1[i]+k-i-d do b := b+1; od;
minj := top2[i]+k-i-b+2-d;
maxj := min(top1[i]+k-i-b+2-d, bot2[1]);
for j from minj to maxj do
comps[j] := -1;
od;
fi;
od;
res := 0;
incomp := skipfirst;
for j from 1 to bot2[1] do
if comps[j]=1 and not incomp then
res := res + 1;
fi;
incomp := evalb(comps[j]=1);
od;
RETURN(res);
end:
pieri_set := proc(p, lam, k,n,d)
local top, bot, top1, top_1, top1c, bot1, bot_1, inner, outer,
b, i, j, ti, res, p1, topk, top1k, inbot, outbot, b1, lbot, rows,cols;
rows := n+d-k;
cols := n+k;
# Split up in PR partition pairs (to reuse old code).
top := part_conj([seq(min(lam[i],k), i=1..nops(lam))]);
top := [op(top), 0$(k-nops(top))];
topk := `if`(k=0, cols, top[k]);
bot := [op(part_clip([seq(max(0,lam[i]-k), i=1..nops(lam))])), 0];
lbot := nops(bot)-1;
# Find bounds for new top partition
outer := [seq(min(rows,top[j]+1), j=1..k)];
inner := `if`(k=0, [],
[seq(max(lbot,top[j+1]), j=1..nops(top)-1), lbot]);
b := 1;
for i from 1 to k do
while b <= lbot and bot[b]+b-1 > top[i]+k-i-d do b := b+1; od;
if top[i]+k-i+2-b-d <= 0 then
inner := subsop(i=max(top[i],inner[i]), inner);
else
inner := subsop(i=max(bot[b]+b-1+i-k+d,inner[i]), inner);
fi;
od;
# Iterate through all possible top partitions
res := {};
top_1 := outer;
while type(top_1, list) do
top1 := top_1;
top_1 := part_itr_between(top1, inner, outer);
p1 := p + `+`(op(top)) - `+`(op(top1));
if p1 < 0 then next; fi;
# Obvious bounds for bottom partition
top1k := `if`(k=0, rows, top1[k]);
inbot := [op(1..lbot,bot), `if`(lbot0, [cols-k], []);
else
outbot := [cols-k,op(1..lbot-1,bot),`if`(lbot top[i]+k-i-d do b := b+1; od;
if top1[i] < top[i] then
if b > nops(inbot) then
inbot := false;
break;
fi;
inbot := subsop(b = max(inbot[b],top[i]+k-i-b+2-d), inbot);
fi;
b1 := b;
while b1 < nops(outbot) and bot[b1]+b1-1 <= top[i]+k-i-d do
outbot := subsop(b1+1 = min(outbot[b1+1],top1[i]+k-i-b1-d), outbot);
b1 := b1+1;
od;
fi;
od;
# Check if top partition didn't work after all.
if inbot = false then next; fi;
j := `+`(op(bot));
if `+`(op(outbot)) - j < p1 then next; fi;
p1 := p1 - `+`(op(inbot)) + j;
if p1 < 0 then next; fi;
# Iterate through all valid bottom partitions.
bot1 := _pieri_fill(inbot, inbot, outbot, 1, p1);
top1c := part_conj(top1);
while type(bot1, list) do
if k=0 then
res := res union {part_clip(bot1)};
else
j := min(nops(top1c), nops(bot1));
res := res union
{[seq(top1c[i]+bot1[i],i=1..j), op(j+1..nops(top1c),top1c)]};
fi;
bot1 := _pieri_itr(bot1, inbot, outbot);
od;
od;
res;
end:
_pieri_fill := proc(lam, inner, outer, r, p)
local res, pp, rr, x;
if nops(lam) = 0 then RETURN(lam); fi;
res := array(lam);
pp := p;
rr := r;
if rr = 1 then
x := min(outer[1], inner[1]+pp);
res[1] := x;
pp := pp - x + inner[1];
rr := 2;
fi;
while rr <= nops(lam) do
x := min(outer[rr], inner[rr]+pp, res[rr-1]-1);
res[rr] := x;
pp := pp - x + inner[rr];
rr := rr + 1;
od;
if pp > 0 then RETURN(false); fi;
[seq(res[rr], rr=1..nops(lam))];
end:
_pieri_itr := proc(lam, inner, outer)
local p, r, lam1;
if nops(lam) = 0 then RETURN(false); fi;
p := lam[-1] - inner[-1];
for r from nops(lam)-1 to 1 by -1 do
if lam[r] > inner[r] then
lam1 := subsop(r=lam[r]-1, lam);
lam1 := _pieri_fill(lam1, inner, outer, r+1, p+1);
if lam1 <> false then RETURN(lam1); fi;
p := p + lam[r] - inner[r];
fi;
od;
false;
end:
_part_star := proc(lam, cols)
if nops(lam)=0 or lam[1]<>cols then RETURN(0); fi;
S[op(2..-1,lam)];
end:
_part_tilde := proc(lam, rows,cols)
local r;
if part_len(lam)<>rows or lam[1]>cols then RETURN(0); fi;
r := rows + lam[1] - cols;
if r <= 0 then RETURN(0); fi;
if r1 then RETURN(0); fi;
S[op(2..r,lam), `if`(lam[-1]=0,0,NULL)];
end:
##################################################################
# Miscellaneous conversions
##################################################################
part2pair_inner := proc(lam, k)
local top, bot, i;
top := part_conj([seq(min(op(i,lam),k), i=1..nops(lam))]);
bot := part_clip([seq(max(op(i,lam)-k,0), i=1..nops(lam))]);
S[[op(top),0$(k-nops(top))],
`if`(nops(lam)>0 and op(-1,lam)=0, [op(bot),0], bot)];
end:
pair2part_inner := proc(pair)
local lam, np2, i;
if nops(op(1,pair))=0 then RETURN(S[op(op(2,pair))]); fi;
lam := part_conj(op(1,pair));
np2 := nops(op(2,pair));
S[seq(lam[i]+op(2,pair)[i], i=1..np2), op(np2+1..-1,lam),
`if`(np2>0 and op(2,pair)[-1]=0, 0, NULL)];
end:
miami_swap_inner := proc(lam, k)
local i;
if not member(k, {op(lam)}) then RETURN(S[op(lam)]); fi;
if `+`(seq(`if`(op(i,lam)>k,1,0), i=1..nops(lam))) mod 2 = 0 then
RETURN(S[op(lam)]);
fi;
if op(-1,lam)=0 then
S[op(1..-2,lam)];
else
S[op(lam),0];
fi;
end:
type_swap_inner := proc(lam, k)
if nops(lam)=0 then
S[];
elif not member(k,lam) then
# FIXME: Very ugly code to delete extra zero from typeless partitions.
# It is here to make the "illegal" k=1 case of qpieriD work.
if op(-1,lam)=0 then S[op(1..-2,lam)] else S[op(lam)]; fi;
elif op(-1,lam)=0 then
S[op(1..-2,lam)];
else
S[op(lam),0];
fi;
end:
part2indexA_inner := proc(lam, k, n)
local la, j;
la := [op(lam), 0$(n-k)];
S[seq(k+j-la[j], j=1..n-k)];
end:
part2indexC_inner := proc(lam, k, n)
local la, i, j;
la := [op(lam), 0$(n-k)];
S[seq(n+k+1-la[j]+`+`(seq(`if`(la[i]+la[j] <= 2*k+j-i,1,0),
i=1..j-1)), j=1..n-k)];
end:
part2indexB_inner := proc(lam, k, n)
local la, i, j;
la := [op(lam), 0$(n-k)];
S[seq(`if`(la[j]>k, n+k+1-la[j], n+k+2-la[j] +
`+`(seq(`if`(la[i]+la[j] <= 2*k+j-i,1,0), i=1..j-1))), j=1..n-k)];
end:
part2indexD_inner := proc(lam, k, n)
local la, i, j, nt;
la := [op(lam),0$(n+1-k)];
nt := n + `if`(nops(lam)>0 and lam[-1]=0, 2, 1);
S[seq(n+k-la[j] + `+`(seq(`if`(la[i]+la[j] <= 2*k-1+j-i, 1,0), i=1..j-1)) +
`if`(la[j]>k or (la[j]=k and (j=1 or k 2*n+1,1,0),
i=1..j-1)), j=1..n-k)];
S[op(part_clip(la))];
end:
index2partB_inner := proc(idx, k, n)
local i, j, la;
la := [seq(`if`(op(j,idx)<=n, n+k+1-op(j,idx), n+k+2-op(j,idx) +
`+`(seq(`if`(op(i,idx)+op(j,idx) > 2*n+2,1,0),i=1..j-1))), j=1..n-k)];
S[op(part_clip(la))];
end:
index2partD_inner := proc(idx, k, n)
local i, j, la, ii;
la := part_clip([seq(`if`(op(j,idx) <= n+1, n+k+1-op(j,idx),
n+k+2-op(j,idx) + `+`(seq(`if`(op(i,idx)+op(j,idx) > 2*n+3,1,0),
i=1..j-1))), j=1..n+1-k)]);
if not member(k,la) then RETURN(S[op(la)]); fi;
S[op(la), `if`(nops({ii$ii=1..n+1} minus {op(idx)}) mod 2 = 1, 0, NULL)];
end:
dualize_index_inner := proc(idx, N, tp)
local i, res;
res := S[seq(N+1-op(-i,idx),i=1..nops(idx))];
if tp="D" and N/2 mod 2 = 1 then
res := subs({N/2=N/2+1,N/2+1=N/2}, res);
fi;
res;
end:
##################################################################
# Miscellaneous conversions
##################################################################
part_len := proc(lambda)
local n;
n := nops(lambda);
while n > 0 and op(n,lambda) = 0 do n := n - 1; od;
RETURN(n);
end:
# tau < mu < lambda
part_itr_between := proc(mu, tau, lambda)
local i, j, n, m, a, res;
i := nops(mu);
while i > 0 and op(i,mu) = op(i,tau) do i := i - 1; od;
if i = 0 then
false;
else
[op(1..i-1, mu), seq(min(op(i,mu)-1, op(j,lambda)), j=i..nops(mu))];
fi;
end:
part_itr := proc(mu)
local i, a;
i := nops(mu);
while i>0 and op(i,mu)=0 do i := i-1; od;
if i=0 then RETURN(false); fi;
a := op(i,mu)-1;
[op(1..i-1,mu),a$(nops(mu)-i+1)];
end:
part_clip := proc(lambda)
local i;
i := nops(lambda);
while i > 0 and op(i, lambda) = 0 do i := i - 1; od;
[op(1..i, lambda)];
end:
part_conj := proc(lambda)
local n, m, res, i, j;
n := nops(lambda);
if n = 0 then
[];
else
m := op(1, lambda);
res := array(1..m);
j := 1;
for i from m by -1 to 1 do
while j < n and op(j+1, lambda) >= i do j := j+1; od;
res[i] := j;
od;
[seq(res[i], i=1..m)];
fi;
end:
all_kstrict := proc(k, rows, cols)
local res, lam;
res := {};
lam := _first_kstrict(k, rows, cols);
while type(lam, list) do
res := res union {part_clip(lam)};
lam := _itr_kstrict(lam, k);
od;
res;
end:
_first_kstrict := proc(k, rows, cols)
local i;
[seq(max(k,cols-i), i=0..rows-1)];
end:
_itr_kstrict := proc(lambda, k)
local i, n, li, j;
n := nops(lambda);
i := n;
while i > 0 and op(i,lambda) = 0 do i := i - 1; od;
if i = 0 then
RETURN(false);
fi;
li := op(i,lambda)-1;
if li <= k then
[op(1..i-1,lambda), li$(n-i+1)];
elif li+i-n > k then
[op(1..i-1,lambda), seq(li-j,j=0..n-i)];
else
[op(1..i-1,lambda), seq(li-j,j=0..li-k), k$n-i-li+k];
fi;
end:
##################################################################
end module:
####