##################################################################### ##RotaStanley: Save this file as RotaStanley to use it, # # stay in the # ## same directory, get into Maple (by typing: maple ) # ## and then type: read RotaStanley: # ## Then follow the instructions given there # ## # ## Written by Doron Zeilberger, Rutgers University , # ## zeilberg at math dot rutgers dot edu. # ###################################################################### print(`First Written: April-May 2007: tested for Maple 10 `): print(`Version of June 12, 2007: `): print(): print(`This is RotaStanley, A Maple package`): print(`accompanying Shalosh B. Ekhad and Doron Zeilberger's article: `): print(`"Using Rota's Umbral Calculus To Enumerate `): print(` Stanley's P-Partitions" `): print(): print(`The most current version is available on WWW at:`): print(` http://www.math.rutgers.edu/~zeilberg/tokhniot/RotaStanley .`): print(`Please report all bugs to: zeilberg at math dot rutgers dot edu .`): print(): print(`For general help, and a list of the MAIN functions,`): print(` type "ezra();". For specific help type "ezra(procedure_name);" `): print(``): print(``): print(`For a list of the supporting functions type: ezra1();`): print(`For a list of the functions that only do scalar umbrae `): print(`type: ezraScalar();`): print(`For a list of Checking functions type ezraCheck(); `): print(): ezraScalar:=proc() if args=NULL then print(`The procedures using Scalar Umbrae are`): print(` GFchain, GFchainQ, GFchainQMsingle, GFchainXsingle,`): print(` GFpowerSingle, GFpowerQsingle, GFpowerQMsingle, GFpowerXsingle `): print(` GFq , GFtableauQ, GFtableauQM, GFtableauX, GFxSingle, `): print(` SelfUmbraSingle, SipurGFpowerQsingle `): print(` SymmPP, SymmPPM , SymPPMstory, SymmPPstory`): print(` UmbralRecurrenceSingle `): else ezra(args): fi: end: ezraCheck:=proc() if args=NULL then print(`The checking procedures are: CheckGFchainQ , CheckGFchainX `): print(` CheckGFq, CheckGFxSingle, `): print(`CheckPercy, CheckPercyM, CheckReverse, CheckSymmPPM,`): print(`Comp, Ppartitions `): else ezra(args): fi: end: ezra1:=proc() if args=NULL then print(`The supporting procedures are`): print(` ApplyUmbra, ApplyUmbraMatrix, BooleanChain`): print(` BooleanLattice, BooleanSegmentt, BoxOfHeightTwo, CheckAllReverse,`): print(` CheckToUmbra `): print(` CompatiblePerms, GabChain, GabGFdirect,`): print(` GFchainQDirect,GFchainXDirect, GFchainXg1,`): print(` GFxInput,`): print(` Graft, GraftChainSingle, GraftG, Hafred, Hex1, Hex2 `): print(`LnChain, LnGFdirect, maj, Parek, Parek1, PPumbra, PPumbraMatrix,`): print(`PPumbraX,PPpreumbra, PPpreumbraX `): print(`SelfUmbraSingle `): print(`qWt, schum, ToUmbra, ToUmbra1, TransClosure, TwoRowedPP, `): print(` TwoRowedShiftedTableau, xWt, xWtInput `): else ezra(args): fi: end: ezra:=proc() if args=NULL then print(` RotaStanley: A Maple package for computing `): print(`generating functions for P-Partitions, and especially`): print(`families obtained by grafted chains. `): print(`The MAIN procedures are`): print(` GabGF, GabGFstory, GFq `): print(`GFx, GFchainQ , GFchainX, GFpowerQ, LnGF, LnGFstory`): print(` SelfUmbra`): print(` SipurGFpowerQ, Solid22nStory, StairCaseStory `): elif nargs=1 and args[1]=ApplyUmbra then print(`ApplyUmbra(U,f,Inpx): Applies the Umbral operator U to`): print(`the function f depending on the list of variables Inpx`): print(`For example, try: ApplyUmbra({[1,[q*x]]},x^3,[x]);`): elif nargs=1 and args[1]=ApplyUmbraMatrix then print(`ApplyUmbraMatrix(U,f,Inpx): Given an umbral matrix U`): print(`(listed as a list of lists, in the form [row1,row2, ...])`): print(`and a column-vector f of functions in Inpx `): print(`(given as a list of functions)`): print(`finds the column-vector Uf also given as a list of length nops(U)`): print(`For example, try`): print(`ApplyUmbraMatrix([[{[1,[q*x]]},{[1,[q^2*x]]}],[{[1,[q*x]]},{[1,[q^2*x]]}]],[x,x^2],[x]);`): elif nargs=1 and args[1]=BooleanChain then print(`BooleanChain(n): the chain whose graft is n-dim Boolean lattice`): print(`For example, try: BooleanChain(3);`): elif nargs=1 and args[1]=BooleanLattice then print(`BooleanLattice(n): the`): print(`n-dim Boolean Lattice . For example, try:`): print(`BooleanLattice(3);`): elif nargs=1 and args[1]=BooleanSegment then print(`BooleanSegment(n,k): the sublattice of the Boolean lattice`): print(`from subsets of size k to subsets of size k+1 .`): print(`For example, try: BooleanSegment(3,2);`): elif nargs=1 and args[1]=BoxOfHeightTwo then print(`BoxOfHeightTwo(a,b): the poset that is a box of dimensions`): print(`2 by a by b`): print(`For example, try: BoxOfHeightTwo(2,2); `): elif nargs=1 and args[1]=CheckAllReverse then print(`CheckAllReverse(n): checks whether Stanley's formula`): print(`for reverse plane partitions is true all shapes L`): print(`with <=n cells`): print(`For example, try:`): print(`CheckAllReverse(5);`): elif nargs=1 and args[1]=CheckGFq then print(`CheckGFq(P,N): checks procedure GFq by comparing it to the`): print(`first N terms of the empirically derived beginning`): print(`For example: try:`): print(`CheckGFq(BooleanLattice(3),5);`): elif nargs=1 and args[1]=CheckGFchainQ then print(`CheckGFchainQ(Li,LiI): checks GFchainQ(Li,LiI,q)`): print(`against doing it directy with GFq .`): print(`For example, do `): print(`CheckGFchainQ([[{},{1}]$3],[1,1]);`): elif nargs=1 and args[1]=CheckGFchainX then print(`CheckGFchainX(Li,LiI): checks GFchainX(Li,LiI,q)`): print(`against doing it directy with GFx .`): print(`For example, do `): print(`CheckGFchainX([[{},{1}]$3],[1,1]);`): elif nargs=1 and args[1]=CheckGFxSingle then print(`CheckGFxSingle(P,x,N): checks procedure GFxSingle by comparing`): print(` it to the first N terms of the empirically derived beginning `): print(`For example: try:`): print(`CheckGFxSingle(BooleanLattice(2),5);`): elif nargs=1 and args[1]=CheckPercy then print(`CheckPercy(n,r): Checks the generating`): print(`function for n by r by infinity plane-partition`): print(`obtained by this approach with MacMahon's formula`): print(`For example, try:`): print(`CheckPercy(3,3);`): elif nargs=1 and args[1]=CheckPercyM then print(`CheckPercyM(n,r): Checks the generating`): print(`function for n by r by m (m symbolic) plane-partition`): print(`obtained by this approach with MacMahon's formula`): print(`For example, try:`): print(`CheckPercyM(2,2);`): elif nargs=1 and args[1]=CheckReverse then print(`CheckReverse(L): checks whether Stanley's formula`): print(`for reverse plane partitions is true for the shape L`): print(`For example, try:`): print(`CheckReverse([3,2,2]);`): elif nargs=1 and args[1]=CheckSymmPPM then print(`CheckSymmPPM(n,q): Checks the Andrews-Gordon-Macdonald`): print(`formula for the generating function of symmetric plane`): print(`partitions inside an n by n by m box. For`): print(`CheckSymmPPM(4,q,M);`): elif nargs=1 and args[1]=CheckToUmbra then print(`CheckToUmbra(F,Lista): checks ToUmbra(F,Lista)`): print(`For example, try:`): print(`CheckToUmbra(x^a/(1-x),[a]);`): elif nargs=1 and args[1]=Coeffm then print(`Coeffm(R,z,m): Given a rational function R(z)`): print(`and a symbol m, finds the coeffs. of z^m`): print(`as an expression in m`): print(`for example try:`): print(`Coeffm(1/(1-q*z)/(1-q^2*z)/(1-z),z,m);`): elif nargs=1 and args[1]=CoeffM then print(`CoeffM(R,z,q,M): Given a rational function R(q,z)`): print(`and a symbol M, finds the coeffs. of z^m`): print(`as an expression in M:=q^m:`): print(`for example try:`): print(`CoeffM(1/(1-q*z)/(1-q^2*z),z,q,m);`): elif nargs=1 and args[1]=Comp then print(`Comp(N,k): The set of compositions of N into exactly k parts`): print(`For example, try: Comp(3,2);`): elif nargs=1 and args[1]=CompatiblePerms then print(`CompatiblePerms(L): Given a poset L`): print(`in the form [S1,S2, ..., Sn] (n:=nops(L)), where `): print(`Si={ji},`): print(`finds all permutations compatible with it.`): print(`for example, try: `): print(`CompatiblePerms([ {}, {1},{1,2} ] );`): elif nargs=1 and args[1]=GabChain then print(`GabChain(a,b): Gab(a,b) as a sequence of chains from one level to the`): print(`next for the Gaussion lattice Gab(a,b) `): print(`of vectors 0<=x[1]<= ...<=x[a]<=b `): print(`For example, try: GabChain(3,3) `): elif nargs=1 and args[1]=GabGF then print(`GabGF(a,b,q): The generating function, in q, for all P-partitions`): print(`of the Gaussian Lattice G(a,b), doing it the Umbral way`): print(`For example, try:`): print(`GabGF(2,2,q);`): elif nargs=1 and args[1]=GabGFdirect then print(`GabGFdirect(a,b,q): `): print(`The generating function, in q, for all P-partitions`): print(`of the Gaussian Lattice G(a,b), doing it the direct way`): print(`For example, try:`): print(`GabGFdirect(2,2,q);`): elif nargs=1 and args[1]=GabGFstory then print(`GabGFstory(N,q,N0): `): print(`The generating function, in q, for all P-partitions`): print(`of the Lattice G(a,b), for a<=<=b, N `): print(`as well as the first N0+1 terms in the enumerating sequence`): print(`For example, try:`): print(`GabGFstory(2,q,30);`): elif nargs=1 and args[1]=GFchain then print(`GFchain(Li,LiI,x,q,s): Given a chain of posets Li `): print(`(presented as a list)`): print(`and a list of interface-sizes, LiI (with nops(LiI)=nops(Li)-1)`): print(`finds the generating function for P-partitions of the glued`): print(`poset, in terms of q and only the last s variables`): print(`that we denote by x[1], ..., x[s] . For example, try:`): print(`GFchain([[{},{1}]$3],[1,1],x,q,1);`): elif nargs=1 and args[1]=GFchainQsingle then print(`GFchainQsingle(Li,LiI,q): the pure generating function, in q`): print(`alone, of all P-partitions of the poset obtained`): print(`from the chain L with the interfaces LiI. For example, try:`): print(`GFchainQsingle([[{},{1},{1},{1,2,3}]$4],[1$3],q);`): elif nargs=1 and args[1]=GFchainQ then print(`GFchainQ(Li,LiI,q): Given a chain of posets Li (presented as a list)`): print(`and a list of interface-sizes, LiI (with nops(LiI)=nops(Li)-1)`): print(`finds the generating function for P-partitions of the glued`): print(`poset, in terms of q alone`): print(`GFchainQ([[{},{1}]$3],[1,1],q);`): elif nargs=1 and args[1]=GFchainQMsingle then print(`GFchainQMsingle(Li,LiI,q,M): the pure generating function, in q`): print(`and M:=q^m, (M and m symbolic(!))`): print(`of all P-partitions, all whose parts are <=m, of the poset obtained`): print(`from the chain L with the interfaces LiI. For example, try:`): print(`GFchainQMsingle([[{},{1},{1},{1,2,3}]$4],[1$3],q,M);`): elif nargs=1 and args[1]=GFchainXsingle then print(`GFchainXsingle(Li,LiI,x): `): print(` Given a chain of posets Li (presented as a list)`): print(`and a list of interface-sizes, LiI (with nops(LiI)=nops(Li)-1)`): print(`finds the generating function for P-partitions of the glued`): print(`poset, in terms of ALL the x[i]'s. For example, try:`): print(`GFchainXsingle([[{},{1}]$3],[1,1],x);`): elif nargs=1 and args[1]=GFchainX then print(`GFchainX(Li,LiI,x): Given a chain of posets Li`): print(` (presented as a list)`): print(`and a list of interface-sizes, LiI (with nops(LiI)=nops(Li)-1)`): print(`finds the generating function for P-partitions of the glued`): print(`poset, in terms of the individual x[i]'s . For example, try:`): print(`GFchainX([[{},{1}]$3],[1,1],x); `): elif nargs=1 and args[1]=GFchainXg1 then print(`GFchainXg1(Li,LiI,x,r): Given a chain of posets Li`): print(` (presented as a list)`): print(`and a list of interface-sizes, LiI (with nops(LiI)=nops(Li)-1)`): print(`finds the generating function for P-partitions of the glued`): print(`poset, and all the states of the last r vertices of the last`): print(`post of Li,`): print(`in terms of the individual x[i]'s . For example, try:`): print(`GFchainXg1([[{},{1}]$3],[1,1],x,1);`): elif nargs=1 and args[1]=GFchainQDirect then print(`GFchainQDirect(Li,LiI,q): `): print(`The slow, direct way, of doing GFchainQsingle(Li,LiI,x)`): print(`Its only goal is to CHECK GFchainQ `): print(`Exteremly SLOW (of course!)`): print(`For example, try:`): print(`GFchainQDirect([[{},{1}]$3],[1,1],q);`): elif nargs=1 and args[1]=GFchainXDirect then print(`GFchainXDirect(Li,LiI,x): `): print(`The slow, direct way, of doing GFchainXsingle(Li,LiI,x)`): print(`Its only goal is to CHECK GFchainXsingle `): print(`Exteremly SLOW (of course!)`): print(`For example, try:`): print(`GFchainXDirect([[{},{1}]$3],[1,1],x);`): elif nargs=1 and args[1]=GFpowerSingle then print(`GFpowerSingle(L,x,q,r,n): Given a poset L, and variables x,q, and`): print(`positive integers r and n, finds the generating function`): print(`of P-partitions for the poset L^n (such that the last r`): print(`elements (assumed totally ordered) interface with`): print(`the first r elements (also assumed totally ordered)`): print(`of the next copy of L. The output is a rational function in q`): print(`and the catalytic variables x[1],x[2], ..., x[r] .`): print(`For example, try:`): print(`GFpowerSingle([{},{1}],x,q,1,5);`): elif nargs=1 and args[1]=GFpowerQ then print(`GFpowerQ(L,q,r,k): Given a poset L (presented as a list)`): print(`finds the generating function for the P-partitions of the `): print(`poset that is the k-th`): print(`power of L where the last r vertices of the preceding link`): print(`are identitied with poset, `): print(`in terms of q alone. For example, try:`): print(`GFpowerQ([{},{1}],q,1,3);`): elif nargs=1 and args[1]=GFpowerQsingle then print(`GFpowerQsingle(L,q,r,n): Given a poset L, and variable q, and`): print(`positive integers r and n, finds the generating function`): print(`of P-partitions for the poset L^n (such that the last r`): print(`elements (assumed totally ordered) interface with`): print(`the first r elements (also assumed totally ordered)`): print(`of the next copy of L. For example, try:`): print(`GFpowerQsingle([{},{1}],q,1,5);`): elif nargs=1 and args[1]=GFpowerQMsingle then print(`GFpowerQMsingle(L,q,r,n,M): Given a poset L, `): print(`and variables q,M:=q^m, and`): print(`positive integers r and n, finds the generating function`): print(`(in terms of q and M:=q^m)`): print(`of P-partitions whose last entry is <=m`): print(`for the poset L^n (such that the last r`): print(`elements (assumed totally ordered) interface with`): print(`the first r elements (also assumed totally ordered)`): print(`of the next copy of L. For example, try:`): print(`GFpowerQMsingle([{},{1}],q,1,5,M);`): elif nargs=1 and args[1]=GFpowerXsingle then print(`GFpowerXsingle(L,x,r,n): Given a poset L, and variables x,q, and`): print(`positive integers r and n, finds the FULL generating function`): print(`(in terms of all the vertices, naturally labelled)`): print(`of P-partitions for the poset L^n (such that the last r`): print(`elements (assumed totally ordered) interface with`): print(`the first r elements (also assumed totally ordered) `): print(`of the next copy of L). For example, try:`): print(`GFpowerXsingle([{},{1}],x,1,5);`): elif nargs=1 and args[1]=GFtableauQ then print(`GFtableauQ(L,q): Inputs a list of positive integers`): print(`(does not have to be increasing or decreasing)`): print(`and outputs the generating function, in the variable`): print(`q, for P-partitions`): print(`of the tableau formed from the left-justified`): print(`shape whose i-th row is L[i]. For example`): print(`to get the generating function for reverse`): print(`plane partitions of shape [2,2,1], try:`): print(`GFtableauQ([2,2,1],q);`): elif nargs=1 and args[1]=GFtableauQM then print(`GFtableauQM(L,q,M): Inputs a list of positive integers`): print(`(does not have to be increasing or decreasing)`): print(`and outputs the generating function, in the variable`): print(`q, and the symbolic variable M:=q^m, for P-partitions`): print(`whose last part (that resides in the last vertex) is all<=m,`): print(`of the tableau formed from the left-justified`): print(`shape whose i-th row is L[i]. For example`): print(`to get the generating function for reverse`): print(`plane partitions of shape [2,2,1] all of whose parts`): print(`are <=m, try:`): print(`GFtableauQM([2,2,1],q,M);`): elif nargs=1 and args[1]=GFtableauX then print(`GFtableauX(L,x): Inputs a list of positive integers`): print(`(does not have to be increasing or decreasing)`): print(`and outputs the generating function, in the variables`): print(`x[1],x[2], ... x[nops(L)], for P-partitions`): print(`of the tableau formed from the left-justified`): print(`shape whose i-th row is L[i]. For example`): print(`to get the generating function for reverse`): print(`plane partitions of shape [2,2,1], try:`): print(`GFtableauX([2,2,1],x);`): elif nargs=1 and args[1]=GFq then print(`GFq(L,q): The generating function w.r.t. to q of all`): print(`L-partitions for the poset L. For example, try:`): print(`GFq([{},{1}],q);`): elif nargs=1 and args[1]=GFxSingle then print(`GFxSingle(L,x): The generating function w.r.t. to x of all`): print(`L-partitions for the partially-ordered set L. For example, try:`): print(`GFxSingle([{},{1}],x);`): elif nargs=1 and args[1]=GFx then print(`GFx(L,x,r): The vector of generating functions w.r.t. to x of all`): print(`L-partitions for the poset L, according to the states induced`): print(`by the last r vertices of L. It also returns the list of respective`): print(`states (compatible permutations with the last r vertices)`): print(` For example, try:`): print(`GFx([{},{1}],x,2);`): elif nargs=1 and args[1]=GFxInput then print(`GFxInput(L,x,S,a): The generating function with respect to x of all`): print(`L-partitions for the poset L. `): print(`where the entries of {a[i], i in S} are fixed.`): print(`For example, try:`): print(`GFxInput([{},{1}],x,{},a);`): elif nargs=1 and args[1]=Graft then print(`Graft(L1,L2,r): Grafts the posets L1 and L2 by`): print(`combining the last r vertices with L1 with the`): print(`first r vertices of L2, assuming that these are`): print(`all linearly ordered. It returns it in the natural`): print(`labels, with a poset with nops(L1)+nops(L2)-r vertices`): print(`For example, try:`): print(`Graft([{},{1}],[{},{1}],1); `): elif nargs=1 and args[1]=GraftChainSingle then print(`GraftChainSingle(Li,LiI): `): print(`Given a chain of posets Li (presented as a list)`): print(`and a list of interface-sizes, LiI (with nops(LiI)=nops(Li)-1)`): print(`finds the resulting poset`): print(`GraftChainSingle([[{},{1}]$3],[1,1]);`): elif nargs=1 and args[1]=GraftG then print(`GraftG(L1,L2,r): Grafts the posets L1 and L2 by`): print(`combining the last r vertices with L1 with the`): print(`first r vertices of L2. `): print(`Of course the induced subposets have to be isomorphic.`): print(`It returns it in the natural`): print(`labels, with a poset with nops(L1)+nops(L2)-r vertices`): print(`For example, try:`): print(`GraftG([{},{1},{1,2}],[{},{1},{1,2}],1);`): elif nargs=1 and args[1]=Hafred then print(`Hafred(mono): splits mono into a product of something`): print(`with symbolic exponents and the rest`): print(`For example, try:`): print(`Hafred(x^a*y^3) ;`): elif nargs=1 and args[1]=Hex1 then print(`Hex1(): The hexagon without internal edges`): elif nargs=1 and args[1]=Hex2 then print(`Hex2(): The hexagon with internal edges`): elif nargs=1 and args[1]=LnChain then print(`LnChain(n): Ln(n) as a sequence of chains from one level to the`): print(`next, where Ln(n) os the lattice of distinct partitions `): print(`with largest part <=n`): print(`For example, try: LnChain(3) `): elif nargs=1 and args[1]=LnGF then print(`LnGF(n,q): The generating function, in q, for all P-partitions`): print(`of the Lattice L(n), doing it the Umbral way`): print(`For example, try:`): print(`LnGF(2,q);`): elif nargs=1 and args[1]=LnGFstory then print(`LnGFstory(N,q,N0): `): print(`The generating function, in q, for all P-partitions`): print(`of the Lattice L(n), for n<=N, `): print(`as well as the first N0+1 terms in the enumerating sequence.`): print(`For example, try:`): print(`LnGFstory(2,q,30);`): elif nargs=1 and args[1]=LnGFdirect then print(`LnGFdirect(n,q): `): print(`The generating function, in q, for all P-partitions`): print(`of the Lattice L(n), doing it the direct way`): print(`For example, try:`): print(`LnGFdirect(2,q);`): elif nargs=1 and args[1]=Parek then print(`Parek(makh): converts a product of a^b`): print(`into a set of [a,b] and (a^b)^c into [a,b*c]`): print(`For example, try: Parek(x^a*y^b); Parek((x^a)^3); `): elif nargs=1 and args[1]=Parek1 then print(`Parek1(khezka): converts a^b into [a,b] and (a^b)^c into [a,b*c]`): print(`For example, try: Parek(x^a); Parek((x^a)^3); Parek((x^4)^b);`): elif nargs=1 and args[1]=PosetToChain then print(`PosetToChain(P): Inputs a poset P, and returns `): print(`a chain [L1,L2, .., Lk], together with the interface`): print(`list. For example, try: PosetToChain(BooleanLattice(3));`): elif nargs=1 and args[1]=Ppartitions then print(`Ppartitions(P,N): The set of P-partitions of N`): print(`for the poset P`): print(`Ppartitions([{},{1},{1}],4); `): elif nargs=1 and args[1]=PPpreumbra then print(`PPpreumbra(L,Inp1,Out1,x,a,q): Given a partially ordered set L`): print(`and a list of input vertices, Inp1 and oputput vertices Out1`): print(`finds the pre-umbra`): print(`connecting the input to the output expressed in terms`): print(`of x^a1*x^a2*..->GFx with those specs but only`): print(`retaining the individuality of the output vertices`): print(`For example, try:`): print(`PPpreumbra(Hex2(),[1],[6],x,a,q);`): elif nargs=1 and args[1]=PPpreumbraX then print(`PPpreumbraX(L,Inp1,x,a): Given a partially ordered set L`): print(`and a list of input vertices, Inp1 `): print(`finds the pre-umbra`): print(`connecting the input to the output expressed in terms`): print(`of xi1^ai1*xi2^ai2*..->Gen. function for P-partions with `): print(` input vertex i1 occopied by ai1, input vertex i2 occupied`): print(` by ai2, etc. `): print(`For example, try:`): print(`PPpreumbraX(Hex2(),[1],x,a);`): elif nargs=1 and args[1]=PPumbra then print(`PPumbra(L,Inp1,Out1,q,x): Given a partially ordered set L`): print(`and a list of input vertices, Inp1, and a list of `): print(`output vertices Out1, finds the umbral operator`): print(`connecting the input to the output expressed in terms`): print(`of f(Inp1)->f(x[Out1]). For example, try:`): print(`PPumbra(Hex2(),[1],[6],q,x);`): elif nargs=1 and args[1]=PPumbraMatrix then print(`PPumbraMatrix(L,Inp1,Out1,x): Given a partially ordered set L`): print(`and a list of input vertices, Inp1, and a list of `): print(`output vertices Out1, finds the umbral operator Matrix`): print(`connecting the input to the output expressed in terms`): print(`of a matrix with states`): print(`f(Inp1)->f(x[Out1]). `): print(`It also returns the list of input states and the list of`): print(` output states. `): print(`It also returns the list of`): print(`output variables.`): print(`For example, try:`): print(`PPumbraMatrix([{},{1},{1},{1,2,3}],[2,3],[2,3],x); `): elif nargs=1 and args[1]=PPumbraX then print(`PPumbraX(L,Inp1,x): Given a partially ordered set L`): print(`and a list of input vertices, Inp1, `): print(`finds the umbral operator`): print(`connecting the input to the output expressed in terms`): print(`of xi1^ai1*xi2^ai2 ->G.F. of P-partitions where the input`): print(` vertices i1, i2, ... have ai1, ai2, ... in them`): print(`For example, try:`): print(`PPumbraX(Hex2(),[1],x);`): elif nargs=1 and args[1]=qWt then print(`qWt(pi,q): q^(maj(pi))/(q)_n`): print(`For example, try: qWt([2,1,3],q); ` ): elif nargs=1 and args[1]=schum then print(`schum(F,vars,Frozen,katan,gadol,Strict):`): print(`Given an expression F that depends on the list of `): print(`discrete variables vars=[a1, ..., an], `): print(`performs the summation of F(vars)`): print(`over katan<=a1<=a2<= ...<=an<=gadol`): print(`and the variables in the set Frozen are frozen`): print(`the output is an expression in the variables of Frozen`): print(`For example, try: `): print(`schum(x1^a1*x2^a2*x3^a3,[a1,a2,a3],{a1,a3},0,infinity,{});`): elif nargs=1 and args[1]=SelfUmbraSingle then print(`SelfUmbraSingle(L,r,q,x): Given a poset L, and a positive integer r`): print(`as well as symbols q and x, finds the Umbral operator`): print(`connecting vertices 1..r (assumed to be totally ordered)`): print(`to the last r vertices (also assumed to be totally ordered)`): print(`(using x[1], ..., x[r]). For example, try:`): print(`SelfUmbraSingle([{},{1}],1,q,x);`): elif nargs=1 and args[1]=SelfUmbra then print(`SelfUmbra(L,r,q,x): Given a partially ordered set L`): print(`and an integer r `): print(`finds the umbral operator`): print(`connecting the first r vertices to the last r vertices`): print(`of f(Inp1)->GFx. `): print(`For example, try:`): print(`SelfUmbra(Hex2(),1,q,x);`): elif nargs=1 and args[1]=SipurGFpowerQ then print(`SipurGFpowerQ(L,q,r,N,N0): Inputs a poset L and a variable q`): print(`and an integer r, and integers N, and N0`): print(`computes the rational generating functions for`): print(`the P-partitions of the power of L glued to itself`): print(`n times where the last r vectices of the precding a`): print(`link join with the first r vertices of the following link`): print(`for n=1 to n=N, and also prints out the first L `): print(`terms of its counting series. For example, try:`): print(`SipurGFpowerQ([{},{1},{1},{1,2,3}],q,2,4,20);`): elif nargs=1 and args[1]=SipurGFpowerQsingle then print(`SipurGFpowerQsingle(L,q,r,N,N0): Inputs a poset L and a variable q`): print(`and an integer r, and integers N, and N0`): print(`computes the rational generating functions for`): print(`the P-partitions of the power of L glued to itself`): print(`n times where the last r vectices of the precding a`): print(`link join with the first r vertices of the following link`): print(`Here it is being assumed that the interface is totally ordered`): print(`for n=1 to n=N, and also prints out the first L `): print(`terms of its counting series. For example, try:`): print(`SipurGFpowerQsingle([{},{1},{1},{1,2,3}],q,2,4,20);`): elif nargs=1 and args[1]=Solid22nStory then print(`Solid22nStory(N,N0,q): The story for generating functions `): print(`for solid partitions inside`): print(`a 2 by 2 by n box for (2<=n<=N), as well as the first`): print(`N0 terms in their counting sequence. For example, try:`): print(`Solid22nStory(3,40,q);`): elif nargs=1 and args[1]=StairCaseStory then print(`StairCaseStory(A,q,N,N0): The story of staircases`): print(`(powers of TwoRowedShiftedTableau(a,a,r) up to the Nth)`): print(`of up to N+1 stories of width a (a<=A) and all possible`): print(`interfaces. It outputs all relevant genearting functions`): print(`and the first N0+1 terms. For example, try:`): print(`StairCaseStory(3,q,5,30);`): elif nargs=1 and args[1]=SymmPP then print(`SymmPP(n,q): the generating function for symmetric plane partitions`): print(`bounded in n by n by infinity. For example, try: `): print(`SymmPP(4,q);`): elif nargs=1 and args[1]=SymmPPM then print(`SymmPPM(n,q,M): the generating function in q and M:=q^m `): print(`for symmetric plane`): print(` partitions bounded in n by n by m box. For example, try:`): print(`SymmPPM(4,q,M);`): elif nargs=1 and args[1]=SymmPPMstory then print(`SymmPPMstory(n,q,M): the generating function in q and M:=q^m `): print(`for all symmetric plane`): print(` partitions bounded in n by n by m box. For 2<=n<=N.`): print(`For example, try:`): print(`SymmPPM(4,q,M);`): elif nargs=1 and args[1]=SymmPPstory then print(`SymmPPstory(N,N0,q): The generating functions, in q, for`): print(`symmetric Plane Partitions bounded in an n by n by infinity box`): print(`for 2<=n<=N, as well as the first N0 terms in their`): print(`counting sequence. For example, try:`): print(`SymmPPstory(3,30,q);`): elif nargs=1 and args[1]=ToUmbra then print(`ToUmbra(F,Lista): Given a preumbra F phrased`): print(`in terms of the discrete variables in the list of`): print(`Lista, outputs the corresponding Umbral operator`): print(`For example, try:`): print(`ToUmbra(x^a/(1-x),[a]);`): elif nargs=1 and args[1]=ToUmbra1 then print(`ToUmbra1(mono,Lista): given a pure monomial mono`): print(`and a list of discrete variables, Lista, of length R, converts it to`): print(`an umbral term: [coeff,[mono1, ..., monoR]]`): print(`such that mono=coeff*mono1^Lista[1]*...*monoR^Lista[R]`): print(`For example, try: ToUmbra1(c*x^a*y^b,[a,b]);`): elif nargs=1 and args[1]=TransClosure then print(`TransClosure(P): given a poset in natural order but with only`): print(`some of its relations specified, finds its transitive closure`): print(`For example, try:`): print(`TransClosure([{},{1},{2},{3}]);`): elif nargs=1 and args[1]=TwoRowedPP then print(`TwoRowedPP(n): the poset on {1, ..., 2n} of an 2 by n plane-partition`): print(`For example, try:`): print(`TwoRowedPP(3);`): elif nargs=1 and args[1]=TwoRowedShiftedTableau then print(`TwoRowedShiftedTableau(a,b,r): the poset consisting of`): print(`a row of a cells above a row of b cells with the location`): print(`of the leftmost cell of the second row distance r from`): print(`the beginning of the first cell. Of course, r is between`): print(`-(b-1) to a-1. For example, try: `): print(`TwoRowedShiftedTableau(3,2,-1);`): elif nargs=1 and args[1]=xWt then print(`xWt(pi,x): The x-weight of a permutation `): print(`For example, try: xWt([2,1,3],x); `): elif nargs=1 and args[1]=xWtInput then print(`xWtInput(pi,x,S,a): the x-weight of a permutation pi `): print(`with input set S`): print(`e.g. try`): print(`xWtInput([1,2],x,{1},a);`): elif nargs=1 and args[1]=UmbralRecurrenceSingle then print(`UmbralRecurrenceSingle(L,r,q,VarList,aList): Expresses the`): print(`Umbral recurrence for a chain of powers of a poset L`): print(`where the last r vertices of L are grafted to the first`): print(`r vertices of the next link `): print(`(and the intersection is totally ordered)`): print(`in terms of the catalytic variables given in VarList`): print(`aList is the corresponding discrete variables`): print(`For example, try:`): print(`UmbralRecurrenceSingle([{},{1}],1,q,[x],[a]);`): else print(`There is no such thing as`, args): fi: end: with(combinat): #CompatiblePerms(L): Given a poset L #in the form [S1,S2, ..., Sn] (n:=nops(L)), where #Si=[{ji},{jj}], #finds all permutations compatible with it. #for example, try: #CompatiblePerms([ [{},{}], [{1},{}],[{1,2},{}] ] ); CompatiblePerms:=proc(L) local n,L1,P1,pi1,pi,akha,gu,i: option remember: n:=nops(L): if n=1 then RETURN({[1]}): fi: akha:=L[n]: L1:=[op(1..n-1,L)]: P1:=CompatiblePerms(L1): gu:={}: for pi1 in P1 do for i from 1 to n do pi:=[op(1..i-1,pi1),n,op(i..n-1,pi1)]: if akha minus {op(1..i,pi)}={} then gu:=gu union {pi}: fi: od: od: gu: end: #BooleanDigraphOld(n): the poset corresponding to the #n-dim Boolean Lattice . For example, try: #BooleanDiGraph (3); BooleanDigraphOld:=proc(n) local mu,mu1,i,S,gu,j,L: mu:=[]: for i from 0 to n do mu1:=convert(choose({seq(j,j=1..n)},i),list): mu:=[op(mu),op(mu1)]: od: gu:=[]: for i from 1 to nops(mu) do S:=mu[i]: L:={}: for j from 1 to i-1 do if mu[j] minus S={} then L:=L union {j}: fi: od: gu:=[op(gu),L]: od: gu: end: maj:=proc(pi) local i,s,n: s:=0: n:=nops(pi): for i from 1 to n-1 do if pi[i]>pi[i+1] then s:=s+n-i: fi: od: s: end: #qWt(pi,q): the q-weight of a permutation pi qWt:=proc(pi,q) local n,i: n:=nops(pi): q^maj(pi)/mul(1-q^i,i=1..n): end: #GFq(L,q): The generating function w.r.t. to q of all #L-partitions for the poset L. For example, try: #GFq([{},{1}],q); GFq:=proc(L,q) local gu,pi,i,n: n:=nops(L): gu:=CompatiblePerms(L): add(q^(maj(pi)),pi in gu)/mul(1-q^i,i=1..n): end: #xWt(pi,x): the x-weight of a permutation pi e.g. try #xWt([1,2],x); xWt:=proc(pi,x) local n,i,gu,a,b: option remember: n:=nops(pi): gu:=x[pi[n]]^a: if pi[n-1]>pi[n] then gu:=sum(gu,a=b+1..infinity): else gu:=sum(gu,a=b..infinity): fi: gu:=x[pi[n-1]]^a*subs(b=a,gu): for i from 2 to n-1 do if pi[n-i]>pi[n-i+1] then gu:=sum(gu,a=b+1..infinity): else gu:=sum(gu,a=b..infinity): fi: gu:=x[pi[n-i]]^a*subs(b=a,gu): od: sum(gu,a=0..infinity): end: #GFxSingle(L,x): The generating function w.r.t. to x of all #L-partitions for the poset L. For example, try: GFxSingle:=proc(L,x) local gu,pi: if L=[{}] then RETURN(1/(1-x[1])): fi: gu:=CompatiblePerms(L): add(xWt(pi,x),pi in gu): # normal(add(xWt(pi,x),pi in gu)): end: #schum(F,vars,Frozen,katan,gadol,Strict): #Given an expression F that depends on the list of #discrete variables vars=[a1, ..., an], #performs the summation of F(vars) #over katan<=a1<=a2<= ...<=an<=gadol #and the variables in the set Frozen are frozen #the output is an expression in the variables of Frozen #For example, try: #schum(x1^a1*x2^a2*x3^a3,[a1,a2,a3],{a1,a3},0,infinity,{}); schum:=proc(F,vars,Frozen,katan,gadol,Strict) local n, an,vars1,Frozen1: n:=nops(vars): if n=1 then if member(vars[1],Frozen) then RETURN(F): else RETURN(sum(F,vars[1]=katan..gadol)): fi: fi: an:=vars[n]: vars1:=[op(1..n-1,vars)]: Frozen1:=Frozen minus {an}: if member(an, Frozen) and not member(n-1,Strict) then RETURN(normal(schum(F,vars1,Frozen1,katan,an,Strict))): elif member(an, Frozen) and member(n-1,Strict) then RETURN(normal(schum(F,vars1,Frozen1,katan,an-1,Strict))): elif not member(an, Frozen) and not member(n-1,Strict) then RETURN(normal(schum(normal(sum(F,an=vars[n-1]..gadol)), vars1,Frozen1,katan,gadol,Strict))): elif not member(an, Frozen) and member(n-1,Strict) then RETURN(normal(schum(normal(sum(F,an=vars[n-1]+1..gadol)), vars1,Frozen1,katan,gadol,Strict))): else ERROR(`Something is wrong`): fi: end: #xWtInput(pi,x,S,a): the x-weight of a permutation pi #with input set S (in terms of (a[s], s in S) and (x[s], s in S) and #e.g. try #xWtInput([1,2],x,{1},a); xWtInput:=proc(pi,x,S,a) local n,i,F,vars,S1,Strict: n:=nops(pi): F:=mul(x[pi[i]]^a[pi[i]],i=1..n): vars:=[seq(a[pi[i]],i=1..n)]: S1:={seq(a[i], i in S)}: Strict:={}: for i from 1 to n-1 do if pi[i]>pi[i+1] then Strict:=Strict union {i}: fi: od: schum(F,vars,S1,0,infinity,Strict): end: #GFxInput(L,x,S,a): The generating function w.r.t. x of all #L-partitions for the poset L. #where the entries of {a[i], i in S} are fixed. #For example, try: #GFxInput([[{},{}],[{1},{}]],x,{},a); GFxInput:=proc(L,x,S,a) local gu,pi: gu:=CompatiblePerms(L): normal(add(xWtInput(pi,x,S,a),pi in gu)): end: #Hex1(): The hexagon without internal edges Hex1:=proc() [{},{1},{1},{1,2},{1,3},{1,2,3,4,5}] : end: #Hex2(): The hexagon with internal edges Hex2:=proc() [{},{1},{1},{1,2,3},{1,2,3},{1,2,3,4,5}]:end: #TwoRowedPP(n): the poset on {1, ..., 2n} of an 2 by n plane-partition #For example, try: #TwoRowedPP(3); TwoRowedPP:=proc(n) local i,j: [seq({seq(j,j=1..i-1)},i=1..n), seq({seq(j,j=1..i),seq(j,j=n+1..n+i-1)},i=1..n)]: end: #Hafred(mono): splits mono into a product of something #with symbolic exponents and the rest #For example, try: #Hafred(x^a*y^3) ; Hafred:=proc(mono) local i,mono1,gu,lu: mono1:=1: gu:=mono: if type(mono,`*`) then for i from 1 to nops(mono) do lu:=op(i,mono): if not type(lu,`^`) or type(lu,`^`) and type(op(2,lu),integer) and not type(op(1,lu),`^`) then mono1:=mono1*lu: gu:=normal(gu/lu): fi: od: RETURN([mono1,gu]): else lu:=mono: if not type(lu,`^`) or type(lu,`^`) and type(op(2,lu),integer) then mono1:=mono1*lu: gu:=normal(gu/lu): RETURN([mono1,gu]): fi: fi: end: #Parek1(khezka): converts a^b into [a,b] and (a^b)^c into [a,b*c] #For example, try: Parek(x^a); Parek((x^a)^3); Parek((x^4)^b); Parek1:=proc(khezka) : if not type(khezka, `^`) then RETURN(FAIL): fi: if not type(op(1,khezka),`^`) then RETURN([op(1,khezka),op(2,khezka)]): else RETURN([op(1,op(1,khezka)),op(2,op(1,khezka))*op(2,khezka)]): fi: end: #Parek(makh): converts a product of a^b #into a set of [a,b] and (a^b)^c into [a,b*c] #For example, try: Parek(x^a*y^b); Parek((x^a)^3); Parek:=proc(makh) local i: if type(makh,`^`) then RETURN({Parek1(makh)}): elif type(makh,`*`) then RETURN({seq(Parek1(op(i,makh)),i=1..nops(makh))}): fi: end: #ToUmbra1(mono,Lista): given a pure monomial mono #and a list of discrete variables, Lista, of length R, converts it to #an umbral term: [coeff,[mono1, ..., monoR]] #such that mono=coeff*mono1^Lista[1]*...*monoR^Lista[R] #For example, try: ToUmbra1(c*x^a*y^b,[a,b]); ToUmbra1:=proc(mono,Lista) local gu,i,coe1,gu1,mu,c,d,fu,mu1: gu:=Hafred(mono): coe1:=gu[1]: gu:=gu[2]: gu:=Parek(gu): mu:={}: for gu1 in gu do c:=op(1,gu1): d:=op(2,gu1): if type(d,`*`) and type(op(1,d),integer) then mu:=mu union {[c^op(1,d),normal(d/op(1,d))]}: else mu:=mu union {gu1}: fi: od: for i from 1 to nops(Lista) do fu[Lista[i]]:=1: od: for mu1 in mu do if not member(mu1[2],{op(Lista)}) then ERROR(`Something is wrong`): fi: fu[mu1[2]]:=fu[mu1[2]]*mu1[1]: od: [coe1,[seq(fu[Lista[i]],i=1..nops(Lista))]]: end: #CleanUpU(Umb): cleans up the umbra Umb CleanUpU:=proc(Umb) local gu,u,T,g: gu:={seq(u[2],u in Umb)}: for g in gu do T[g]:=0: od: for u in Umb do T[u[2]]:=T[u[2]]+u[1]: od: {seq([normal(T[g]),g],g in gu)}: end: #ApplyUmbra(U,f,Inpx): Applies the Umbral operator U to #the function f depending on the list of variables Inpx #For example, try: ApplyUmbra({[1,[q*x]]},x^3,[x]); ApplyUmbra:=proc(U,f,Inpx) local gu,u,i,gu1,lu,gu11: gu:=0: for u in U do lu:={seq(Inpx[i]=u[2][i],i=1..nops(Inpx))}: gu11:=subs(lu,f): gu1:=u[1]*gu11: gu:=gu+gu1: od: gu: end: #PPpreumbra(L,Inp1,Out1,x,a,q): Given a partially ordered set L #and a list of input vertices, Inp1 and oputput vertices Out1 #finds the pre-umbra #connecting the input to the output expressed in terms #of x^a1*x^a2*..->GFx with those specs but only #retaining the individuality of the output vertices #For example, try: #PPpreumbra(Hex2(),[1],[6],x,a,q); PPpreumbra:=proc(L,Inp1,Out1,x,a,q) local i,gu,Lista,Stam1,s: gu:=GFxInput(L,x,Inp1,a): Stam1:={seq(i,i=1..nops(L))} minus convert(Out1,set): gu:=subs({seq(x[s]=q,s in Stam1)},gu): gu:=subs({seq(x[s]=q*x[s],s in convert(Out1,set))},gu): Lista:=[seq(a[Inp1[i]],i=1..nops(Inp1))]: normal(gu),Lista: end: #ToUmbra(F,Lista): Given a preumbra F phrased #in terms of the discrete variables in the list of #Lista, outputs the corresponding Umbral operator #For example, try: #ToUmbra(x^a,[a]); ToUmbra:=proc(F,Lista) local U, U1, gg, gud, gun, i: if F=0 then RETURN({}): fi: gud:=denom(F): gun:=expand(numer(F)): if not type(gun,`+`) then gg:=expand(gun): U1:=ToUmbra1(gg,Lista): RETURN({[U1[1]/gud,U1[2]]}): fi: U:={}: for i from 1 to nops(gun) do gg:=expand(op(i,gun)): U1:=ToUmbra1(gg,Lista): U:=U union {[U1[1]/gud,U1[2]]}: od: CleanUpU(U): end: #PPumbra(L,Inp1,Out1,q,x): Given a partially ordered set L #and a list of input vertices, Inp1, and a list of #output vertices Out1, finds the umbral operator #connecting the input to the output expressed in terms #of f(Inp1)->f(x[Out1]). It also returns the list of #output variables. #For example, try: #PPumbra(Hex2(),[1],[6],q,x); PPumbra:=proc(L,Inp1,Out1,q,x) local a,i,gu,Lista: option remember: Lista:=[seq(a[Inp1[i]],i=1..nops(Inp1))]: gu:=PPpreumbra(L,Inp1,Out1,x,a,q)[1]: ToUmbra(gu,Lista): end: #CheckToUmbra(F,Lista): checks ToUmbra CheckToUmbra:=proc(F,Lista) local U,y,i,F1: U:=ToUmbra(F,Lista): F1:=mul(y[i]^Lista[i],i=1..nops(Lista)): F1:=normal(ApplyUmbra(U,F1,[seq(y[i],i=1..nops(Lista))])): evalb(normal(simplify(F-F1,symbolic))=0): end: #Graft(L1,L2,r): Grafts the posets L1 and L2 by #combining the last r vertices with L1 with the #first r vertices of L2, assuming that these are #all linearly ordered. It returns it in the natural #labels, with a poset with nops(L1)+nops(L2)-r vertices #For example, try: #Graft([{},{1},{1,2}],[{},{1},{1,2}],1); Graft:=proc(L1,L2,r) local i,j,L,a,gu,mu,s: if nops(L1){seq(j,j=1..i-1)} then print(`The `, i, `-th vertex of L2, is bad `): RETURN(FAIL): fi: od: for i from nops(L1)-r+1 to nops(L1) do if {seq(j,j=nops(L1)-r+1..i-1)} minus L1[i]<>{} then print(`The `, i, `-th vertex of L1, is bad `): RETURN(FAIL): fi: od: L:=L1: a:=nops(L1)-r: for i from r+1 to nops(L2) do gu:=L2[i]: gu:={seq(s+a, s in gu)}: mu:=gu: for s in gu do mu:=mu union L[s]: od: L:=[op(L),mu]: od: L: end: #PPumbraX(L,Inp1,q,x): Given a partially ordered set L #and a list of input vertices, Inp1 #finds the umbral operator #connecting the input to the output expressed in terms #of f(Inp1)->GFx. #For example, try: #PPumbraX(Hex2(),[1],q,x); PPumbraX:=proc(L,Inp1,x) local a,i,Lista,j,i1: option remember: if nops(Inp1)>nops(L) then RETURN(FAIL): fi: for j from 1 to nops(Inp1) do if {seq(Inp1[i1],i1=1..j-1)} minus L[Inp1[j]] <>{} then RETURN(FAIL): fi: od: Lista:=[seq(a[Inp1[i]],i=1..nops(Inp1))]: ToUmbra(GFxInput(L,x,Inp1,a),Lista): end: #PPpreumbraX(L,Inp1,x,a): Given a partially ordered set L #and a list of input vertices, Inp1 #finds the pre-umbra #connecting the input to the output expressed in terms #of x^a1*x^a2*..->GFx with those specs #For example, try: #PPpreumbraX(Hex2(),[1],x,a); PPpreumbraX:=proc(L,Inp1,x,a) local i,gu,Lista: gu:=GFxInput(L,x,Inp1,a): Lista:=[seq(a[Inp1[i]],i=1..nops(Inp1))]: normal(gu),Lista: end: #GFchainXsingle(Li,LiI,x): Given a chain of posets Li (presented as a list) #and a list of interface-sizes, LiI (with nops(LiI)=nops(Li)-1) #finds the generating function for P-partitions of the glued #poset, in terms of the individual x[i]'s . For example, try: #GFchainXsingle([[{},{1}]$3],[1,1],x); GFchainXsingle:=proc(Li,LiI,x) local gu,Li1,y,LiI1,godel,r,L,z,i,U,Inp1y: if nops(Li)-nops(LiI)<>1 then print(`Bad input`): RETURN(FAIL): fi: if nops(Li)=1 then RETURN(GFxSingle(Li[1],x)): fi: L:=Li[nops(Li)]: r:=LiI[nops(LiI)]: Li1:=[op(1..nops(Li)-1,Li)]: LiI1:=[op(1..nops(LiI)-1,LiI)]: gu:=GFchainXsingle(Li1,LiI1,x): godel:=add(nops(Li1[i]),i=1..nops(Li1))-convert(LiI1,`+`): gu:=subs({seq(x[i]=y[i],i=godel-r+1..godel)},gu): Inp1y:=[seq(y[i],i=godel-r+1..godel)]: U:=PPumbraX(L,[seq(i,i=1..r)],z): if U=FAIL then RETURN(FAIL): fi: U:=subs({seq(z[i]=x[godel-r+i],i=1..nops(L))},U): gu:=ApplyUmbra(U,gu,Inp1y): end: #GraftChainSingle(Li,LiI): Given a chain of posets Li (presented as a list) #and a list of interface-sizes, LiI (with nops(LiI)=nops(Li)-1) #finds the resulting poset #GraftChainSingle([[{},{1}]$3],[1,1]); GraftChainSingle:=proc(Li,LiI) local L,i: if nops(Li)-nops(LiI)<>1 then print(`Bad input`): RETURN(FAIL): fi: L:=Li[1]: for i from 2 to nops(Li) do L:=Graft(L,Li[i],LiI[i-1]): od: L: end: #GraftChain(Li,LiI): Given a chain of posets Li (presented as a list) #and a list of interface-sizes, LiI (with nops(LiI)=nops(Li)-1) #finds the resulting poset #GraftChain([[{},{1}]$3],[1,1]); GraftChain:=proc(Li,LiI) local L,i: if nops(Li)-nops(LiI)<>1 then print(`Bad input`): RETURN(FAIL): fi: L:=Li[1]: for i from 2 to nops(Li) do L:=GraftG(L,Li[i],LiI[i-1]): od: L: end: #GFchainXDirect(Li,LiI,x): Given a chain of posets Li (presented as a list) #and a list of interface-sizes, LiI (with nops(LiI)=nops(Li)-1) #finds the generating function for P-partitions of the glued #poset. It does it DIRECTLY, and hence VERY slowly. #This is only meant as a check to procedure GFchain #GFchainXDirect([[{},{1}]$3],[1,1],x); GFchainXDirect:=proc(Li,LiI,x) local L: L:=GraftChainSingle(Li,LiI): GFxSingle(L,x): end: #GFchain(Li,LiI,x,q,s): Given a chain of posets Li (presented as a list) #and a list of interface-sizes, LiI (with nops(LiI)=nops(Li)-1) #finds the generating function for P-partitions of the glued #poset, in terms of q the last s variables denoted #by x[1], ..., x[s] . For example, try: #GFchain([[{},{1}]$3],[1,1],x,q,s); GFchain:=proc(Li,LiI,x,q,s) local gu,godel,i: godel:=add(nops(Li[i]),i=1..nops(Li))-convert(LiI,`+`): gu:=GFchainXsingle(Li,LiI,x): gu:=subs({seq(x[i]=q,i=1..godel-s),seq(x[i+godel-s]=q*x[i],i=1..s)},gu): gu: end: #GFchainQsingle(Li,LiI,q): the pure generating function, in q #alone, of all P-partitions of the poset obtained #from the chain L with the interfaces LiI. For example, try: #GFchainQsingle([[{},{1},{1},{1,2,3}]$4],[1$3],q); GFchainQsingle:=proc(Li,LiI,q) local gu,x: gu:=GFchain(Li,LiI,x,q,1): gu:=subs(x[1]=1,gu): normal(gu): end: #GFpowerSingle(L,x,q,r,n): Given a poset L, and variables x,q, and #positive integers r and n, finds the generating function #of P-partitions for the poset L^n (such that the last r #elements (assumed totally ordered) interface with #the first r elements (also assumed totally ordered) #of the next copy of L. For example, try: #GFpowerSingle([{},{1}],x,q,1,5); GFpowerSingle:=proc(L,x,q,r,n) local U,i,gu: option remember: if n=1 then gu:=GFxSingle(L,x): gu:=subs({seq(x[i]=q,i=1..nops(L)-r),seq(x[i+nops(L)-r]=q*x[i], i=1..r)},gu): RETURN(gu): fi: U:=SelfUmbraSingle(L,r,q,x): if U=FAIL then RETURN(FAIL): fi: gu:=GFpowerSingle(L,x,q,r,n-1): gu:=ApplyUmbra(U,gu,[seq(x[i],i=1..r)]): gu: end: #SelfUmbraSingle(L,r,q,x): Given a partially ordered set L #and an integer r such that the first r and last r #vertices are both totally ordered, #finds the umbral operator #connecting the first r vertices to the last r vertices #of f(Inp1)->GFx. #For example, try: #SelfUmbraSingle(Hex2(),1,q,x); SelfUmbraSingle:=proc(L,r,q,x) local i,gu: option remember: gu:=PPumbraX(L,[seq(i,i=1..r)],x): if gu=FAIL then RETURN(FAIL): fi: gu:=subs({seq(x[i]=1,i=1..r)},gu): gu:=subs({seq(x[i]=q,i=r+1..nops(L)-r)},gu): gu:=subs({seq(x[i]=q*x[i],i=nops(L)-r+1..nops(L))},gu): gu:=subs({seq(x[nops(L)-r+i]=x[i],i=1..r)},gu): gu: end: #GFpowerQsingle(L,q,r,n): Given a poset L, and variable q, and #positive integers r and n, finds the generating function #of P-partitions for the poset L^n (such that the last r #elements (assumed totally ordered) interface with #the first r elements (also assumed totally ordered) #of the next copy of L. For example, try: #GFpowerQsingle([{},{1}],q,1,5); GFpowerQsingle:=proc(L,q,r,n) local i,gu,x: option remember: gu:=GFpowerSingle(L,x,q,r,n): normal(subs({seq(x[i]=1,i=1..r)},gu)): end: qfac:=proc(q,r) local gu,i: gu:=1: for i from 1 to r do gu:=gu*(1-q^i): od: gu: end: #CheckPercy(n,r): Checks the generating #function for n by r by infinity plane-partition #obtained by this approach with MacMahon's formula #For example, try: #CheckPercy(2,2); CheckPercy:=proc(n,r) local lu,mu,i,L,q: L:=TwoRowedPP(n): lu:=GFpowerQsingle(L,q,n,r-1): mu:=1: for i from 0 to n-1 do mu:=mu*qfac(q,i)/qfac(q,r+i): od: evalb(normal(lu/mu)=1): end: #GFpowerXsingle(L,x,r,n): Given a poset L, and variables x,q, and #positive integers r and n, finds the FULL generating function #(in terms of all the vertices, naturally labelled) #of P-partitions for the poset L^n (such that the last r #elements (assumed totally ordered) interface with #the first r elements (also assumed totally ordered) #of the next copy of L. For example, try: #GFpowerXsingle([{},{1}],x,1,5); GFpowerXsingle:=proc(L,x,r,n): GFchainXsingle([L$n],[r$(n-1)],x): end: #GFchainQDirect(Li,LiI,q): Given a chain of posets Li (presented as a list) #and a list of interface-sizes, LiI (with nops(LiI)=nops(Li)-1) #finds the generating function for P-partitions (only in terms of q) #of the glued #poset. It does it DIRECTLY, and hence VERY slowly. #This is only meant as a check to procedure GFchain #GFchainQDirect([[{},{1}]$3],[1,1],q); GFchainQDirect:=proc(Li,LiI,q) local L: L:=GraftChainSingle(Li,LiI): GFq(L,q): end: #TwoRowedShiftedTableau(a,b,r): the poset consisting of #a row of a cells above a row of b cells with the location #of the leftmost cell of the second row distance r from #the beginning of the first cell. Of course, r is between #-(b-1) to a-1. For example, try: #TwoRowedShiftedTableau(3,2,-1); TwoRowedShiftedTableau:=proc(a,b,r) local i,j,r1: if not {type(a,integer),type(b,integer),type(r,integer), evalb(a>0), evalb(b>0), evalb(r>=-(b-1)), evalb(r<=a-1)}={true} then print(`Bad input`): RETURN(FAIL): fi: if r<=0 then r1:=-r: if b-r1<=a then RETURN([seq({seq(j,j=1..i-1)},i=1..a), seq({seq(a+j,j=1..i-1)},i=1..r1), seq({seq(a+j,j=1..i-1),seq(j,j=1..i-r1)},i=r1+1..b)]): else RETURN([seq({seq(j,j=1..i-1)},i=1..a), seq({seq(a+j,j=1..i-1)},i=1..r1), seq({seq(a+j,j=1..i-1),seq(j,j=1..i-r1)},i=r1+1..r1+a), seq({seq(j,j=1..i-1)},i=a+r1+a+1..a+b)]): fi: else if r+b<=a then RETURN([seq({seq(j,j=1..i-1)},i=1..a), seq({seq(a+j,j=1..i-1),seq(1..r+i)},i=1..b)]): else RETURN([seq({seq(j,j=1..i-1)},i=1..a), seq({seq(a+j,j=1..i-1),seq(1..r+i)},i=1..a-r), seq({seq(j,j=1..i-1)},i=a+a-r+1..a+b)]): fi: fi: end: #GFtableauQ(L,q): Inputs a list of positive integers #(does not have to be increasing or decreasing) #and outputs the generating function, in the variable #q, for P-partitions #of the tableau formed from the left-justified #shape whose i-th row is L[i]. For example #to get the generating function for reverse #plane partitions of shape [2,2,1], try: #GFtableauQ([2,2,1],q); GFtableauQ:=proc(L,q) local Li,LiI,i: option remember: if nops(L)=1 then RETURN(mul(1/(1-q^i),i=1..L[1])): fi: Li:=[seq(TwoRowedShiftedTableau(L[i],L[i+1],0),i=1..nops(L)-1)]: LiI:=[seq(L[i],i=2..nops(L)-1)]: GFchainQsingle(Li,LiI,q): end: #GFtableauX(L,x): Inputs a list of positive integers #(does not have to be increasing or decreasing) #and outputs the generating function, in the variables #x[1],x[2], ..., x[nops(L)], for P-partitions #of the tableau formed from the left-justified #shape whose i-th row is L[i]. For example #to get the generating function for reverse #plane partitions of shape [2,2,1], try: #GFtableauX([2,2,1],x); GFtableauX:=proc(L,x) local Li,LiI,i: Li:=[seq(TwoRowedShiftedTableau(L[i],L[i+1],0),i=1..nops(L)-1)]: LiI:=[seq(L[i],i=2..nops(L)-1)]: GFchainXsingle(Li,LiI,x): end: ConjPar:=proc(lam) local i,lam1,a: if nops(lam)=1 then RETURN([1$lam[1]]): fi: a:=lam[1]: lam1:=[op(2..nops(lam),lam)]: lam1:=ConjPar(lam1): [seq(lam1[i]+1,i=1..nops(lam1)),1$(a-nops(lam1))]: end: #CheckReverse(L): checks whether Stanley's formula #for reverse plane partitions is true for the shape L #For example, try: #CheckReverse([3,2,2]); CheckReverse:=proc(L) local q,i,j,gu,mu,L1,h: L1:=ConjPar(L): mu:=1: for i from 1 to nops(L) do for j from 1 to L[i] do h:=L[i]-i+L1[j]-j+1: mu:=mu/(1-q^h): od: od: gu:=GFtableauQ(L,q): evalb(normal(gu-mu)=0): end: hafokh:=proc(L) local i: [seq(L[nops(L)-i+1],i=1..nops(L))]:end: #CheckAllReverse(n): checks whether Stanley's formula #for reverse plane partitions is true all shapes L #with <=n cells #For example, try: #CheckAllReverse(5); CheckAllReverse:=proc(n) local gu,i,g,L: gu:={seq(op(partition(i)),i=1..n)}: gu:={seq(hafokh(g), g in gu)}: evalb({seq(CheckReverse(L), L in gu)}={true}): end: #SymmPP(n,q): the generating function for symmetric plane partitions #bounded in n by n by infinity. For example, try: #SymmPP(4,q); SymmPP:=proc(n,q) local gu,x,i: gu:=GFtableauX([seq(i,i=1..n)],x): gu:=subs({seq(x[i]=q^2*x[i],i=1..n*(n+1)/2)},gu): gu:=subs({seq(x[i*(i+1)/2]=x[i*(i+1)/2]/q,i=1..n)},gu): gu:=subs({seq(x[i]=1,i=1..n*(n+1)/2)},gu): factor(gu): end: #Coeffm(R,z,m): Given a rational function R(z) #and a symbol m, finds the coeffs. of z^m #as an expression in m #for example try: #Coeffm(1/(1-q*z)/(1-q^2*z),z,m); Coeffm:=proc(R,z,m) local Q,R1,mu,P1,Q1,i,m1,A: R1:=normal(R): Q:=denom(R1): mu:={solve(Q,z)}: if nops(mu)<>degree(Q,z) then print(`Multiple roots not implemented (since I am too lazy)`): RETURN(FAIL): fi: Q1:=mul(z-m1,m1 in mu): P1:=normal(R1*Q1): if degree(denom(P1),z)<>0 then RETURN(FAIL): fi: if degree(P1,z)>=degree(Q1,z) then print(`Not implemented`): RETURN(FAIL): fi: mu:=convert(mu,list): for i from 1 to nops(mu) do A[i]:=normal(subs(z=mu[i],P1)/subs(z=mu[i],diff(Q1,z))): od: normal(simplify(normal(add(-simplify(A[i]/mu[i]^(m+1)),i=1..nops(mu))))): end: #CoeffM(R,z,q,M): Given a rational function R(q,z) #and a symbol M, finds the coeffs. of z^m #as an expression in M:=q^m: #for example try: #CoeffM(1/(1-q*z)/(1-q^2*z),z,q,m); CoeffM:=proc(R,z,q,M) local Q,R1,mu,i,m1,Mu,m,gu: R1:=normal(R): Q:=denom(R1): mu:={solve(Q,z)}: if not {seq(evalb(type(m1,`^`) or m1=q or m1=1),m1 in mu)}={true} then RETURN(FAIL): fi: Mu:=[]: for i from 1 to nops(mu) do if mu[i]=q then Mu:=[op(Mu),1]: elif mu[i]=1 then Mu:=[op(Mu),0]: elif type(mu[i],`^`) then if op(1,mu[i])<>q or not type(op(2,mu[i]), integer) then RETURN(FAIL): else Mu:=[op(Mu),op(2,mu[i])]: fi: fi: od: gu:=Coeffm(R,z,m): for i from 1 to nops(Mu) do gu:=subs((q^Mu[i])^(-m)=M^(-Mu[i]),gu): od: factor(gu): end: #GFtableauQM(L,q,M): Inputs a list of positive integers #(does not have to be increasing or decreasing) #and outputs the generating function, in the variable #q, and the symbolic variable M:=q^m, for P-partitions #whose lat part is<=m, #of the tableau formed from the left-justified #shape whose i-th row is L[i]. For example #to get the generating function for reverse #plane partitions of shape [2,2,1] all of whose parts #are <=m, try: #GFtableauQM([2,2,1],q,M); GFtableauQM:=proc(L,q,M) local Li,LiI,i: if nops(L)=1 then RETURN(mul((1-q^i*M)/(1-q^i),i=1..L[1]) ): fi: Li:=[seq(TwoRowedShiftedTableau(L[i],L[i+1],0),i=1..nops(L)-1)]: LiI:=[seq(L[i],i=2..nops(L)-1)]: GFchainQMsingle(Li,LiI,q,M): end: #GFchainQMsingle(Li,LiI,q,M): the pure generating function, in q #and M:=q^m, (M and m symbolic(!)) #of all P-partitions, whose last part is <=m, of the poset obtained #from the chain L with the interfaces LiI. For example, try: #GFchainQMsingle([[{},{1},{1},{1,2,3}]$4],[1$3],q,M); GFchainQMsingle:=proc(Li,LiI,q,M) local gu,x,N,z,i: N:=add(nops(Li[i]),i=1..nops(Li))-convert(LiI,`+`): gu:=GFchainXsingle(Li,LiI,x): gu:=subs({seq(x[i]=q,i=1..N-1),x[N]=q*z},gu)/(1-z): gu:=normal(gu): factor(CoeffM(gu,z,q,M)): end: #GFpowerQMsingle(L,q,r,n,M): Given a poset L, and variables q,M:=q^m, and #positive integers r and n, finds the generating function #(in terms of q and M:=q^m) #of P-partitions whose last entry is <=m #for the poset L^n (such that the last r #elements (assumed totally ordered) interface with #the first r elements (also assumed totally ordered) #of the next copy of L. For example, try: #GFpowerQMsingle([{},{1}],q,1,5,M); GFpowerQMsingle:=proc(L,q,r,n,M): GFchainQMsingle([L$n],[r$(n-1)],q,M): end: #CheckPercyM(n,r): Checks the generating #function for n by r by m (m symbolic) plane-partition #obtained by this approach with MacMahon's formula #For example, try: #CheckPercyM(2,2); CheckPercyM:=proc(n,r) local lu,mu,i,j,L,q,M: L:=TwoRowedPP(n): lu:=GFpowerQMsingle(L,q,n,r-1,M): mu:=1: for i from 1 to n do for j from 1 to r do mu:=mu*(1-q^(i+j-1)*M)/(1-q^(i+j-1)): od: od: evalb(normal(lu/mu)=1): end: #SymmPPM(n,q,M): the generating function for symmetric plane partitions #bounded in n by n by m . Here M:=q^m. For example, try: #SymmPPM(4,q,M); SymmPPM:=proc(n,q,M) local gu,x,i,z: gu:=GFtableauX([seq(i,i=1..n)],x): gu:=subs({seq(x[i]=q^2*x[i],i=1..n*(n+1)/2)},gu): gu:=subs({seq(x[i*(i+1)/2]=x[i*(i+1)/2]/q,i=1..n)},gu): gu:=subs({seq(x[i]=1,i=1..n*(n+1)/2-1),x[n*(n+1)/2]=z},gu)/(1-z): gu:=factor(gu): factor(CoeffM(gu,z,q,M)): end: #CheckSymmPPM(n,q): Checks the Andrews-Gordon-Macdonald #formula for the generating function of symmetric plane #partitions inside an n by n by m box. For #CheckSymmPPM(4,q,M); CheckSymmPPM:=proc(n,q,M) local gu,mu,i,j: gu:=SymmPPM(n,q,M): mu:=1: for i from 1 to n do mu:=mu*(1-q^(2*i-1)*M)/(1-q^(2*i-1)): od: for i from 1 to n do for j from i+1 to n do mu:=mu*(1-q^(2*(i+j-1))*M^2)/(1-q^(2*(i+j-1))): od: od: evalb(normal(gu-mu)=0): end: #SipurGFpowerQsingle(L,q,r,N,N0): Inputs a poset L and a variable q #and an integer r, and integers N, and N0 #computes the rational generating functions for #the P-partitions of the power of L glued to itself #n times where the last r vectices of the precding #link join with the first r vertices of the following link #for n=1 to n=N, and also prints out the first L #terms of its counting series. For example, try: #SipurGFpowerQsingle([{},{1},{1},{1,2,3}],q,r,4,20); SipurGFpowerQsingle:=proc(L,q,r,N,N0) local n,t0,gu,i: t0:=time(): print(`This is the story of the P-partitions for the n-th`): print(` power of the poset`): print(L): print(`glued by the first and last`, r, `vetrices `): print(`for n from 1 to`, N): print(`as well as the first `, N0+1, `terms of its counting series`): print(``): for n from 1 to N do gu:=GFpowerQsingle(L,q,r,n): print(`For the`, n, ` power `): print(`which is the poset`): print( GraftChainSingle([L$n],[r$(n-1)]) ): print(`the generating function for its P-partitions is`): lprint(gu): print(``): print(`The first`, N0+1, ` coefficients are`): print([seq(coeff(taylor(gu,q=0,N0+2),q,i),i=0..N0)]): print(``): od: print(`The whole thing took`, time()-t0, `seconds of CPU time `): end: #BoxOfHeightTwo(a,b): the poset that is a box of dimensions #2 by a by b BoxOfHeightTwo:=proc(a,b) local T,i,j,V,lu,pt,i1,j1,P: V:=[seq(seq([1,i,j],i=1..a),j=1..b), seq(seq([2,i,j],i=1..a),j=1..b)]: for i from 1 to nops(V) do T[V[i]]:=i: od: P:=[]: for i from 1 to nops(V)/2 do pt:=[op(2..3,V[i])]: lu:={seq(seq([1,i1,j1], i1=1..pt[1]),j1=1..pt[2])} minus {V[i]}: P:=[op(P), {seq(T[i1],i1 in lu)}]: od: for i from nops(V)/2+1 to nops(V) do pt:=[op(2..3,V[i])]: lu:={seq(seq([1,i1,j1], i1=1..pt[1]),j1=1..pt[2])} union {seq(seq([2,i1,j1], i1=1..pt[1]),j1=1..pt[2])} minus {V[i]}: P:=[op(P), {seq(T[i1],i1 in lu)}]: od: P: end: #TransClosure(P): given a poset in natural order but with only #some of its relations specified, finds its transitive closure #For example, try: #TransClosure([{},{1},{2},{3}]); TransClosure:=proc(P) local T,i,j: for i from 1 to nops(P) do if max(op(P[i]))>=i then RETURN(FAIL): fi: od: T[1]:={}: for i from 1 to nops(P) do T[i]:=P[i] union {seq(op(T[j]),j in P[i])}: od: [seq(T[i],i=1..nops(P))]: end: #GraftG(L1,L2,r): Grafts the posets L1 and L2 by #combining the last r vertices with L1 with the #first r vertices of L2. #Of course the induced subposets have to be isomorphic. #It returns it in the natural #labels, with a poset with nops(L1)+nops(L2)-r vertices #For example, try: #GraftG([{},{1},{1,2}],[{},{1},{1,2}],1); GraftG:=proc(L1,L2,r) local i,L1r,L2r,a,i1,L,L2t: if nops(L1)L2r then print(`The first`, r, `vertices of the second poset are not isomorphic`): print(`to the last `, r, `vertices of the first poset`): RETURN(FAIL): fi: L2t:=[op(r+1..nops(L2),L2)]: L2t:=subs({seq(i=i+a,i=1..nops(L2))},L2t): L:=[op(L1),op(L2t)]: TransClosure(L): end: #MaxVertices(P): the maximal elements of the poset P. #For example, try #MaxVertices([{},{1},{},{1,3}]); MaxVertices:=proc(P1) local P,i: P:=TransClosure(P1): if P=FAIL then RETURN(P): fi: {seq(i,i=1..nops(P))} minus {seq(op(P[i]),i=1..nops(P))}: end: #BooleanLattice(n): the n-dim Boolean Lattice . For example, try: #BooleanLattice(3); BooleanLattice:=proc(n) local gu1,gu2,i: if n=0 then RETURN([{}]): fi: if n=1 then RETURN([{},{1}]): fi: gu1:=BooleanLattice(n-1): gu2:=subs({seq(i=i+2^(n-1),i=1..2^(n-1))},gu1): gu2:=[seq(gu2[i] union {i},i=1..nops(gu2))]: TransClosure([op(gu1),op(gu2)]): end: ####Start Multi-Umbra############## #SubPerm(pi,R): extracts the subpermutation of pi consisting #of the members of the set R, for example, try #SubPerm([2,1,4,3],{2,3,4}); SubPerm:=proc(pi,R) local pi1,i: pi1:=[]: for i from 1 to nops(pi) do if member(pi[i],R) then pi1:=[op(pi1),pi[i]]: fi: od: pi1: end: #GFx(L,x,r): The vector of generating functions w.r.t. to x of all #L-partitions for the poset L, according to the states induced #by the last r vertices of L. It also returns the list of respective #states (compatible permutations with the last r vertices) # For example, try: #GFx([{},{1}],x,2); GFx:=proc(L,x,r) local gu,pi,Yeter,L1,i,L1a,mu,pi1,T,R: if L=[{}] then RETURN([1/(1-x[1])],[[1]] ): fi: R:=[seq(i,i=nops(L)-r+1..nops(L))]: Yeter:={seq(i,i=1..nops(L))} minus {op(R)}: L1:=[seq(L[R[i]] minus Yeter,i=1..nops(R))]: L1a:=subs({seq(R[i]=i,i=1..nops(R))},L1): mu:=convert(CompatiblePerms(L1a),list): mu:=subs({seq(i=R[i],i=1..nops(R))},mu): for i from 1 to nops(mu) do T[mu[i]]:=0: od: gu:=CompatiblePerms(L): for pi in gu do pi1:=SubPerm(pi,{op(R)}): T[pi1]:=T[pi1]+xWt(pi,x): od: [seq(T[mu[i]],i=1..nops(mu))],mu: end: #xWtInput(pi,x,S,a): the x-weight of a permutation pi #with input set S (in terms of (a[s], s in S) and (x[s], s in S) and #e.g. try #xWtInput([1,2],x,{1},a); xWtInput:=proc(pi,x,S,a) local n,i,F,vars,S1,Strict: n:=nops(pi): F:=mul(x[pi[i]]^a[pi[i]],i=1..n): vars:=[seq(a[pi[i]],i=1..n)]: S1:={seq(a[i], i in S)}: Strict:={}: for i from 1 to n-1 do if pi[i]>pi[i+1] then Strict:=Strict union {i}: fi: od: schum(F,vars,S1,0,infinity,Strict): end: #Matim(te,Inp1,Out1,pi,sig): Is the permutation te comptable with #pi on Inp1 and sig on Out1?. For example try: #Matim([2,4,1,3],[1,2],[3,4],[2,1],[4,3]); Matim:=proc(te,Inp1,Out1,pi,sig) local gu,i: gu:=hofkhi(te): if redu([seq(gu[Inp1[i]],i=1..nops(Inp1))])=hofkhi(redu(pi)) and redu([seq(gu[Out1[i]],i=1..nops(Out1))])=hofkhi(redu(sig)) then true: else false: fi: end: #GFxInputOutputG(L,x,a,Inp1,Out1,pi,sig): #The generating function w.r.t. x of all #L-partitions for the poset L. #with Inp1 compatible with pi and #Out1 compatible with sig, #where the entries of {a[i], i in Inp1} are fixed. #For example, try: #GFxInputOutputG([{},{1}],x,a,[1],[2],[1],[2]); GFxInputOutputG:=proc(L,x,a,Inp1,Out1,pi,sig) local gu,te,mu: mu:=CompatiblePerms(L): gu:={}: for te in mu do if Matim(te,Inp1,Out1,pi,sig) then gu:=gu union {te}: fi: od: add(xWtInput(te,x,Inp1,a),te in gu): end: #PPpreumbraG(L,Inp1,Out1,x,a,pi,sig): Given a partially ordered set L #and a list of input vertices, Inp1 and oputput vertices Out1 #and a permutation pi of Inp1 and a permutation sig of Out1 #finds the pre-umbra #connecting the input to the output with the #assumption that the only allowed extensions are #also compatible with pi and sig #expressed in terms #of x^a1*x^a2*..->GFx with those specs but only #retaining the individuality of the output vertices #For example, try: #PPpreumbraG(Hex2(),[1],[6],x,a,[1],[6]); PPpreumbraG:=proc(L,Inp1,Out1,x,a,pi,sig) local i,gu,Lista: gu:=GFxInputOutputG(L,x,a,Inp1,Out1,pi,sig): Lista:=[seq(a[Inp1[i]],i=1..nops(Inp1))]: normal(gu),Lista: end: #PPumbraMatrix(L,Inp1,Out1,x): Given a partially ordered set L #and a list of input vertices, Inp1, and a list of #output vertices Out1, finds the umbral operator Matrix #connecting the input to the output expressed in terms #of a matrix with states #f(Inp1)->f(x[Out1]). It also returns the list of #input states and the list of output states #It also returns the list of #output variables. #For example, try: #PPumbraMatrix([{},{1},{1},{1,2,3}],[2,3],[2,3],x); PPumbraMatrix:=proc(L,Inp1,Out1,x) local a,i,Linp,Lout, Yeter,R1,C1,j,M,lu,ku: option remember: Yeter:={seq(i,i=1..nops(L))} minus {op(Inp1)}: Linp:=[seq(L[Inp1[i]] minus Yeter,i=1..nops(Inp1))]: Yeter:={seq(i,i=1..nops(L))} minus {op(Out1)}: Lout:=[seq(L[Out1[i]] minus Yeter,i=1..nops(Out1))]: R1:=convert(CompatiblePermsG(Linp,Inp1),list): C1:=convert(CompatiblePermsG(Lout,Out1),list): M:=[]: for j from 1 to nops(C1) do lu:=[]: for i from 1 to nops(R1) do ku:=PPpreumbraG(L,Inp1,Out1,x,a,R1[i],C1[j]): lu:=[op(lu),ToUmbra(ku)]: od: M:=[op(M),lu]: od: M,R1,C1: end: #ApplyUmbraMatrix(U,f,Inpx): Given an umbral matrix U #(listed as a list of lists, in the form [row1,row2, ...]) #and a column-vector f of functions in Inpx (given as a list of functions) #finds the column-vector Uf also given as a list of length nops(U) #For example, try #ApplyUmbra([[{[1,[q*x]]},{[1,[q^2*x]]}],[{[1,[q*x]]},{[1,[q^2*x]]}]],[x,x^2],[x]); ApplyUmbraMatrix:=proc(U,f,Inpx) local i,j,gu,mu: if nops({seq(nops(U[i]),i=1..nops(U))})<>1 then print(`Bad input`): RETURN(FAIL): fi: if nops(U[1])<>nops(f) then print(`Bad input`): RETURN(FAIL): fi: gu:=[]: for i from 1 to nops(U) do mu:=0: for j from 1 to nops(f) do mu:=mu+ApplyUmbra(U[i][j],f[j],Inpx): od: gu:=[op(gu),mu]: od: gu: end: #CompatiblePermsG(L,V): Given a poset L #in the form [S1,S2, ..., Sn] (n:=nops(L)), with # a list of vertices #Si=[{ji}], #finds all permutations compatible with it. #for example, try: #CompatiblePermsG([{},{1},{1,2}],[1,2,3] ); CompatiblePermsG:=proc(L,V) local gu,L1,i: L1:=subs({seq(V[i]=i,i=1..nops(V))},L): gu:=CompatiblePerms(L1): subs({seq(i=V[i],i=1..nops(V))},gu): end: #redu(pi): the reduction of a list of integers pi redu:=proc(pi) local T,gu,i: gu:=sort(pi): for i from 1 to nops(pi) do T[gu[i]]:=i: od: [seq(T[pi[i]],i=1..nops(pi))]: end: hofkhi:=proc(pi) local T,i: for i from 1 to nops(pi) do T[pi[i]]:=i: od: [seq(T[i],i=1..nops(pi))]: end: #temura(L1,L2): Given two lists with the same set of distinct #elements finds how L2 is a permutation of L1 temura:=proc(L1,L2) local i,T: if convert(L1,set)<>convert(L2,set) then RETURN(FAIL): fi: for i from 1 to nops(L1) do T[L1[i]]:=i: od: [seq(T[L2[i]],i=1..nops(L2))]: end: #GFchainXg1(Li,LiI,x,r): Given a chain of posets Li (presented as a list) #and a list of interface-sizes, LiI (with nops(LiI)=nops(Li)-1) #finds the generating function for P-partitions of the glued #poset, and all the states of the last r vertices of the last #post of Li, #in terms of the individual x[i]'s . For example, try: #GFchainXg1([[{},{1}]$3],[1,1],x,1); GFchainXg1:=proc(Li,LiI,x,r) local gu,Li1,y,LiI1,godel,L,z,i,U,Inp1y, Seder1,Seder2,Seder3,r1,pi: option remember: if nops(Li)-nops(LiI)<>1 then print(`Bad input`): RETURN(FAIL): fi: if nops(Li)=1 then RETURN(GFx(Li[1],x,r)): fi: L:=Li[nops(Li)]: r1:=LiI[nops(LiI)]: Li1:=[op(1..nops(Li)-1,Li)]: LiI1:=[op(1..nops(LiI)-1,LiI)]: gu:=GFchainXg1(Li1,LiI1,x,r1): Seder1:=gu[2]: gu:=gu[1]: godel:=add(nops(Li1[i]),i=1..nops(Li1))-convert(LiI1,`+`): gu:=subs({seq(x[i]=y[i],i=godel-r1+1..godel)},gu): Inp1y:=[seq(y[i],i=godel-r1+1..godel)]: U:=PPumbraMatrix(L,[seq(i,i=1..r1)],[seq(i,i=nops(L)-r+1..nops(L))],z): if U=FAIL then RETURN(FAIL): fi: Seder2:=U[2]: Seder3:=U[3]: U:=U[1]: Seder2:=subs({seq(i=godel-r1+i,i=1..nops(L))},Seder2): Seder3:=subs({seq(i=godel-r1+i,i=1..nops(L))},Seder3): if convert(Seder1,set)<>convert(Seder2,set) then RETURN(FAIL): fi: pi:=temura(Seder1,Seder2): U:=subs({seq(z[i]=x[godel-r1+i],i=1..nops(L))},U): gu:=[seq(gu[pi[i]],i=1..nops(pi))]: gu:=ApplyUmbraMatrix(U,gu,Inp1y): gu,Seder3: end: #GFchainX(Li,LiI,x): Given a chain of posets Li (presented as a list) #and a list of interface-sizes, LiI (with nops(LiI)=nops(Li)-1) #finds the generating function for P-partitions of the glued #poset, #in terms of the individual x[i]'s . For example, try: #GFchainX([[{},{1}]$3],[1,1],x); GFchainX:=proc(Li,LiI,x) local gu: option remember: gu:=GFchainXg1(Li,LiI,x,1): if gu=FAIL then RETURN(FAIL): fi: gu[1][1]: end: #GFchainQ(Li,LiI,q): Given a chain of posets Li (presented as a list) #and a list of interface-sizes, LiI (with nops(LiI)=nops(Li)-1) #finds the generating function for P-partitions of the glued #poset, #in terms of q alone #GFchainQ([[{},{1}]$3],[1,1],q); GFchainQ:=proc(Li,LiI,q) local x,gu,godel,i: gu:=GFchainX(Li,LiI,x): if gu=FAIL then RETURN(FAIL): fi: godel:=add(nops(Li[i]),i=1..nops(Li))-convert(LiI,`+`): normal(subs({seq(x[i]=q,i=1..godel)},gu)): end: #SelfUmbra(L,r,q,x): Given a partially ordered set L #and an integer r #finds the umbral operator #connecting the first r vertices to the last r vertices #of f(Inp1)->GFx. #For example, try: #SelfUmbra(Hex2(),1,q,x); SelfUmbra:=proc(L,r,q,x) local i,gu,Seder2,Seder3: option remember: gu:=PPumbraMatrix(L,[seq(i,i=1..r)],[seq(i,i=nops(L)-r+1..nops(L))],x): if gu=FAIL then RETURN(FAIL): fi: Seder2:=gu[2]: Seder3:=gu[3]: gu:=gu[1]: gu:=subs({seq(x[i]=1,i=1..r)},gu): gu:=subs({seq(x[i]=q,i=r+1..nops(L)-r)},gu): gu:=subs({seq(x[i]=q*x[i],i=nops(L)-r+1..nops(L))},gu): gu:=subs({seq(x[nops(L)-r+i]=x[i],i=1..r)},gu): Seder3:=subs({seq(i+nops(L)-r=i,i=1..r)},Seder3): gu,Seder2,Seder3: end: #GFpowerQ(L,q,r,k): Given a poset L (presented as a list) #finds the generating function for the P-partitions of the #poset that is the k-th #power of L where the last r vertices of the preceding link #are identitied with #poset, #in terms of q alone #GFpowerQ([{},{1}],q,1,3); GFpowerQ:=proc(L,q,r,k) option remember: GFchainQ([L$k],[r$(k-1)],q): end: #SipurGFpowerQ(L,q,r,N,N0): Inputs a poset L and a variable q #and an integer r, and integers N, and N0 #computes the rational generating functions for #the P-partitions of the power of L glued to itself #n times where the last r vectices of the precding #link join with the first r vertices of the following link #for n=1 to n=N, and also prints out the first L #terms of its counting series. For example, try: #SipurGFpowerQ([{},{1},{1},{1,2,3}],q,r,4,20); SipurGFpowerQ:=proc(L,q,r,N,N0) local n,t0,gu,i: t0:=time(): print(`This is the story of the P-partitions for the n-th`): print(` power of the poset`): print(L): print(`glued by the first and last`, r, `vetrices `): print(`for n from 1 to`, N): print(`as well as the first `, N0+1, `terms of its counting series`): print(``): for n from 1 to N do gu:=GFpowerQ(L,q,r,n): print(`For the`, n, ` power `): print(`which is the poset`): print( GraftChain([L$n],[r$(n-1)]) ): print(`the generating function for its P-partitions is`): lprint(gu): print(``): print(`The first`, N0+1, ` coefficients are`): print([seq(coeff(taylor(gu,q=0,N0+2),q,i),i=0..N0)]): print(``): od: print(`The whole thing took`, time()-t0, `seconds of CPU time `): end: #BooleanSegment(n,k): the sublattice of the Boolean lattice #from subsets of size k to subsets of size k+1 . #For example, try: BooleanSegment(3,2); BooleanSegment:=proc(n,k) local gu1,gu2,S1,P,i,j,lu: gu1:=choose(n,k): gu2:=choose(n,k+1): P:=[{}$nops(gu1)]: for i from 1 to nops(gu2) do S1:=convert(gu2[i],set): lu:={}: for j from 1 to nops(gu1) do if convert(gu1[j],set) minus S1={} then lu:=lu union {j}: fi: od: P:=[op(P),lu]: od: P: end: #StairCaseStory(A,q,N,N0): The story of staircases #(powers of TwoRowedShiftedTableau(a,a,r) up to the Nth) #of up to N+1 stories of width a (a<=A) and all possible #interfaces. It outputs all relevant genearting functions #and the first N0+1 terms. For example, try: #StairCaseStory(3,q,5,30); StairCaseStory:=proc(A,q,N,N0) local a,r,P,t0: t0:=time(): print(`This is the list of all generating functions, and the`): print(`first `, N0+1, `terms in the enumerating series`): print(`for P-partitions of staircase shapes`): print(`(i.e. shifted-tableaux with the same number of cells in each row`): print(`and the rows are jutting-to the left or right )`): print(`of up to`, N+1, `levels `): print(`with the number of cells in each row <=`, A): for a from 2 to A do for r from -(a-1) to a-1 do P:=TwoRowedShiftedTableau(a,a,r): print(`The Two-rowed, atomic object with`, a, `cells in each row`): print(`and the second row is jutting by`, r, `cells compared to the`): print(` one above, which in our notation is the poset`): print(P): print(`The generating functions for up to`, N+1, ` rows `): print(`i.e. up to the`, N, `-th power of it are as follows`): SipurGFpowerQsingle(P,q,a,N,N0): od: od: print(`The whole saga took`, time()-t0, `seconds . `): end: #BooleanChain(n): the chain whose graft is n-dim Boolean lattice #For example, try: BooleanChain(3); BooleanChain:=proc(n) local k: [seq(BooleanSegment(n,k),k=0..n-1)],[seq(binomial(n,k),k=1..n-1)]: end: #Ln1(i): the set of distinct partitions with largest part=i Ln1:=proc(i) local gu,j,mu,m: option remember: if i=1 then RETURN({[1]}): fi: gu:={[i]}: for j from 1 to i-1 do mu:=Ln1(j): gu:=gu union {seq([op(m),i],m in mu)}: od: gu: end: #IsBiggerLn(v1,v2): is v1<=v2 in Ln and one level above it IsBiggerLn:=proc(v1,v2) local gu1,gu2: if convert(v1,set) minus convert(v2,set)={} then RETURN(true): fi: gu1:=convert(v1,set) minus convert(v2,set): gu2:=convert(v2,set) minus convert(v1,set): if nops(gu2)=1 and nops(gu1)=1 and gu2[1]-gu1[1]=1 then RETURN(true): fi: false: end: #IsBiggerLn(v1,v2): is v1<=v2 in Ln and one level above it IsBiggerLn:=proc(v1,v2) local gu1,gu2: if convert(v1,set) minus convert(v2,set)={} then RETURN(true): fi: gu1:=convert(v1,set) minus convert(v2,set): gu2:=convert(v2,set) minus convert(v1,set): if nops(gu2)=1 and nops(gu1)=1 and gu2[1]-gu1[1]=1 then RETURN(true): fi: false: end: #Ln(n): Ln(n) as a sequence of chains from one level to the #next #the Chain of Ln(n) of distinct partitions with largest part <=n Ln:=proc(n) local i: {seq(op(Ln1(i)),i=1..n)} union {[]}: end: #LnChain(n): Ln(n) as a sequence of chains from one level to the #next #the Chain of Ln(n) of distinct partitions with largest part <=n LnChain:=proc(n) local i,gu,g,T,C,Gu,P,j,lu,k1: gu:={seq(op(Ln1(i)),i=1..n)} union {[]}: for i from 0 to n*(n+1)/2 do T[i]:=[]: od: for g in gu do T[convert(g,`+`)]:=[op(T[convert(g,`+`)]), g]: od: Gu:=[seq(T[i],i=0..n*(n+1)/2)]: C:=[]: for i from 1 to nops(Gu)-1 do P:=[{}$nops(Gu[i])]: for j from 1 to nops(Gu[i+1]) do lu:={}: for k1 from 1 to nops(Gu[i]) do if IsBiggerLn(Gu[i][k1],Gu[i+1][j]) then lu:=lu union {k1}: fi: od: P:=[op(P),lu]: od: C:=[op(C),P]: od: C,[seq(nops(Gu[i]),i=2..nops(Gu)-1)]: end: #Gab(a,b): The Gaussian poset G(a,b). #of all vectors of length a such that #0<=x1<= ...<=xa<=b. For example, try: #Gab(3,2); Gab:=proc(a,b) local gu,mu,m,i: option remember: if a=1 then RETURN({seq([i],i=0..b)}): fi: if a=0 then RETURN({}): fi: if b=0 then RETURN({[0$a]}): fi: gu:=Gab(a,b-1): mu:=Gab(a-1,b): gu union {seq([op(m),b], m in mu)}: end: #IsBiggerGab(v1,v2): is v1<=v2 in Gab(a,b) and one level above it IsBiggerGab:=proc(v1,v2) local u,i: u:=[seq(v2[i]-v1[i],i=1..nops(v1))]: if convert(u,`+`)=1 and convert(u,set)={0,1} then true: else false: fi: end: #GabChain(a,b): GabChain(a,b) as a sequence of chains from one level to the #next #the Chain of Gab(a,b) of partitions with largest part <=b #with a parts. For example, try: #GabChain(3,3): GabChain:=proc(a,b) local i,gu,g,T,C,Gu,P,j,lu,k1: gu:=Gab(a,b): for i from 0 to a*b do T[i]:=[]: od: for g in gu do T[convert(g,`+`)]:=[op(T[convert(g,`+`)]), g]: od: Gu:=[seq(T[i],i=0..a*b)]: C:=[]: for i from 1 to nops(Gu)-1 do P:=[{}$nops(Gu[i])]: for j from 1 to nops(Gu[i+1]) do lu:={}: for k1 from 1 to nops(Gu[i]) do if IsBiggerGab(Gu[i][k1],Gu[i+1][j]) then lu:=lu union {k1}: fi: od: P:=[op(P),lu]: od: C:=[op(C),P]: od: C,[seq(nops(Gu[i]),i=2..nops(Gu)-1)]: end: #GabGF(a,b,q): The generating function, in q, for all P-partitions #of the Gaussian Lattice G(a,b), doing it the Umbral way #For example, try: #GabGF(2,2,q); GabGF:=proc(a,b,q) local C: C:=GabChain(a,b): GFchainQ(C,q): end: #GabGFdirect(a,b,q): The generating function, in q, for all P-partitions #of the Gaussian Lattice G(a,b), doing it the direct way #For example, try: #GabGFdirect(2,2,q); GabGFdirect:=proc(a,b,q) local C,P: C:=GabChain(a,b): P:=GraftChain(C): GFq(P,q): end: #LnGF(n,q): The generating function, in q, for all P-partitions #of the Lattice L(n), doing it the Umbral way #For example, try: #LnGF(2,q); LnGF:=proc(n,q) local C: C:=LnChain(n): factor(GFchainQ(C,q)): end: #LnGFdirect(n,q): The generating function, in q, for all P-partitions #of the Lattice L(n), doing it the direct way #For example, try: #LnGFdirect(2,q); LnGFdirect:=proc(n,q) local C,P: C:=LnChain(n): P:=GraftChain(C): factor(GFq(P,q)): end: #LnGFstory(N,q,N0): all the generating functions for #P-partitions for L(n) for n<=N, and the first #N0+1 terms. For example, try: #LnGFstory(4,q,30); LnGFstory:=proc(N,q,N0) local n,gu,mu,i: for n from 1 to N do gu:=LnGF(n,q): print(`The generating function for P-partitions of the lattice L(n) for n=`): print(n, `is the following:`): lprint(gu): mu:=taylor(gu,q=0,N0+1): print(`The first`, N0+1, `terms are `): print([seq(coeff(mu,q,i),i=0..N0)]): od: end: #GabGFstory(N,q,N0): all the generating functions for #P-partitions for G(a,b) for a<=b<=N, and the first #N0+1 terms. For example, try: #GabGFstory(4,q,30); GabGFstory:=proc(N,q,N0) local a,b,gu,mu,i: for a from 2 to N do for b from 2 to a do gu:=GabGF(a,b,q): print(`The generating function for P-partitions of the lattice L(a,b) for `): print(`a=`,a, `b=`, b, `is the following:`): lprint(gu): mu:=taylor(gu,q=0,N0+1): print(`The first`, N0+1, `terms are `): print([seq(coeff(mu,q,i),i=0..N0)]): od: od: end: #SymmPPstory(N,N0,q): The generating functions, in q, for #symmetric Plane Partitions bounded in an n by n by infinity box #for 1<=n<=N, as well as the first N0 terms in their #counting sequence. For example, try: #SymmPPstory(3,30,q); SymmPPstory:=proc(N,N0,q) local n,gu,t0,mu,i: t0:=time(): print(`This is the story for generating functions in `, q, ` for Symmetric`): print(`Plane partitions bounded in an n by n by infinity box`): print(`for n between 2 and `, N): print(`as well as the first `, N0+1, `terms in the counting series `): for n from 2 to N do gu:=SymmPP(n,q): print(`The generating function in`, q, ` when n=`, n , ` happens to be`): lprint(gu): print(`The first`, N0+1, ` terms are `): mu:=taylor(gu,q=0,N0+1): print([seq(coeff(mu,q,i),i=0..N0)]): od: print(`The whole thing took`, time()-t0, `seconds of CPU time `): end: #SymmPPMstory(N,M,q): The generating functions (in q and M"q^m) for #symmetric Plane Partitions bounded in an n by n by m box #for 2<=n<=N, as well as the first N0 terms in their #counting sequence. For example, try: #SymmPPMstory(3,M,q); SymmPPMstory:=proc(N,M,q) local n,gu,t0: t0:=time(): print(`This is the story for generating functions in `, q, M): print(`(where M:=q^m)) for Symmetric`): print(`Plane partitions bounded in an n by n by m box`): print(`for n between 2 and `, N): for n from 2 to N do gu:=SymmPPM(n,M,q): print(`The generating function in`, q, ` when n=`, n , ` happens to be`): lprint(gu): od: print(`The whole thing took`, time()-t0, `seconds of CPU time `): end: #Solid22nStory(N,N0,q): The story for generating functions #for solid partitions inside #a 2 by 2 by n box for (2<=n<=N), as well as the first #N0 terms in their counting sequence. For example, try: #Solid22nStory(3,40,q); Solid22nStory:=proc(N,N0,q) local gu,P,mu,i,t0,n: t0:=time(): P:=BooleanLattice(3): print(`This is the story for generating functions in `, q, ` for Solid`): print(`partitions bounded in a 2 by 2 by n by infinity box`): print(`for n between 2 and `, N): print(`as well as the first `, N0+1, `terms in the counting series `): for n from 2 to N do gu:=GFpowerQ(P,q,4,n-1) : print(`The generating function in`, q, ` when n=`, n , ` happens to be`): lprint(gu): print(`The first`, N0+1, ` terms are `): mu:=taylor(gu,q=0,N0+1): print([seq(coeff(mu,q,i),i=0..N0)]): od: print(`The whole thing took`, time()-t0, `seconds of CPU time `): end: ###Checking Part ez:=proc(): print(`Comp(N,k), IsGood(v,P), Ppartitions(P,n) `): print(`GFxDirectStart(P,x,N,t), CheckGFxSingle(P,N), CheckGFq(P,N) `): end: #Comp(N,k): The set of compositions of N into exactly k parts #For example, try: Comp(3,2); Comp:=proc(N,k) local gu,a1,mu,m: if k=0 then if N=0 then RETURN({[]}): else RETURN({}): fi: fi: gu:={}: for a1 from 0 to N do mu:=Comp(N-a1,k-1): gu:=gu union {seq([a1,op(m)],m in mu)}: od: gu: end: #IsGood(v,P): Is the composition v compatible with #the poset P? For example, try: #IsGood([1,2,1],[{},{1},{1}]) IsGood:=proc(v,P) local i,j: if nops(v)<>nops(P) then RETURN(false): fi: for j from 2 to nops(P) do for i in P[j] do if v[j]r then ERROR(`The last argument should be a list of variables of length `, r ): fi: gu:=SelfUmbraSingle(L,r,q,x): if gu=FAIL then RETURN(FAIL): fi: print(`A Computer-Generated Theorem by Shalosh B. Ekhad `): print(): print(`Consider the poset L:= `, L): print(`Let P[n] be the poset obtained from joining n copies `): print(` of L together, by identifying the last`, r, `vertices `): print(`of the previous link to the first`, r, `vertices of the next link`): print(`Let `, F[n](seq(VarList[i],i=1..r)), ` be the weight-enumerator of`): print(`of all P-partitions of P[n], with the weight q^(sum of entries)`): print(`times the product of `, mul(VarList[i]^aList[i],i=1..r) ): print(`where `, seq(aList[i],i=1..r), `are the last `, r, `entries `): print(`of the P-partition `): print(): print(F[n](seq(VarList[i],i=1..r)), `satisfies the following `): print(` functional-recurrence equation:`): lu:= add( gu[i][1]*subs({seq(x[j]=gu[i][2][j],j=1..r)},F[n-1](seq(x[i],i=1..r))) ,i=1..nops(gu)): lu:=subs({seq(x[j]=VarList[j],j=1..r)},lu): print(F[n](op(VarList))=lu): print(): lu:=normal(GFxSingle(L,x,r)): lu:=subs({seq(x[j]=q,j=1..nops(L)-r),seq(x[nops(L)-r+j]=q*VarList[j],j=1..r)}, lu): print(`Subject to the intial condition `): print(F[1](op(VarList))=lu): print(): print(`The pure generating function for all P-partitions is`): print(F[n](1$r)): end: