###################################################################### ##AMITAI: Save this file as AMITAI To use it, stay in the # ##same directory, get into Maple (by typing: maple ) # ##and then type: read AMITAI : # ##Then follow the instructions given there # ## # ##Written by Doron Zeilberger, Rutgers University , # #zeilberg at math dot rutgers dot edu # ###################################################################### #Created: Nov. 2006 with(combinat): print(`Created: Nov. 2006`): print(` This is AMITAI `): print(`a Maple package to study the number of`): print(`Young-tableaux of bounded height.`): print(`It accompanies the paper `): print(` Proof of a Conjecture of Amitai Regev about Three-Rowed`): print(`Young Tableaux (and much more!) `): print(`by Shalosh B. Ekhad and Doron Zeilberger,`): print(`also available from the authors' websites`): lprint(``): print(`Please report bugs to zeilberg at math dot rutgers dot edu`): lprint(``): print(`The most current version of this package and paper`): print(` are available from`): print(`http://www.math.rutgers.edu/~zeilberg .`): print(`For a list of the procedures type ezra();, for help with`): print(`a specific procedure, type ezra(procedure_name); .`): print(``): with(combinat): ezra1:=proc() if args=NULL then print(` The supporting procedures are: ApplyOper, Axkn, Bxkn, CF1,`): print(` GenOper, GuessOper1, GW1, HafelOper, nuYTwith, Pars1, Pars`): print( ` ParsWith, , RegevStyle3YTwith1, RGF, RGFt, SYTkn, YTwith `): else ezra(args): fi: end: ezra:=proc() if args=NULL then print(`The main procedures are: AR, ARa, ARaS, ARaf, CF,`): print(` GuessRegev3D, GuessRegev4D, GuessRegev4Dnice, `): print(`GuessAndProveRegev3D, `): print(` GuessAndProveRegev3Dterse`): print(`GW, GWf `): print(` ProveRegev, R , R1, RegevSummand, RegevStyle3YTwith`): print(` Sipur3, Sipur3with, Sipur4, `): print(` TnuYTodd, TnuYToddS, TnuYTwith `): elif nops([args])=1 and op(1,[args])=ApplyOper then print(`ApplyOper(S,ope,n,N): applies the operator ope(n,1/N) to the`): print(`sequence S as soon as it makes sense`): print(`For example, try: ApplyOper([a,b,c],1-n/N,n,N);`): elif nops([args])=1 and op(1,[args])=AR then print(`AR(n,k): total number of Young tableaux with at most k parts`): print(`with n cells. For example, try: AR(8,2);`): elif nops([args])=1 and op(1,[args])=ARa then print(`ARa(a,n): total number of Young tableaux with at most nops(a) parts`): print(`with n cells and such that the cells labelled 1, ... sum(a) `): print(`form shape a`): print(`For example, try: ARa([0,0],8);`): elif nops([args])=1 and op(1,[args])=ARaf then print(`ARaf(a,n): total number of Young tableaux with at most nops(a) parts`): print(`with n cells and such that the cells labelled 1, ... sum(a) `): print(`form shape a`): print(`using redunant generating functions`): print(`For example, try: ARaf([0,0],8);`): elif nops([args])=1 and op(1,[args])=ARaS then print(`ARaS(a,N): the sequence, for n=1..N for the `): print(`total number of Young tableaux with at most nops(a) parts`): print(`with n cells and such that the cells labelled 1, ... sum(a) `): print(`form shape a`): print(`For example, try: ARaS([0,0],8);`): elif nops([args])=1 and op(1,[args])=Axkn then print(`Axkn(x,k,n): The generating function for all partitions`): print(`of n, for example, try:Axkn(x,2,5);`): elif nops([args])=1 and op(1,[args])=Bxkn then print(`Bxkn(x,k,n): The generating function for all partitions`): print(`of n, times (1-x[1]/x[k)*(1-x[2]/x[k-1])*...`): print(`where all negative exponets are discarded`): print(`For example, try:Bxkn(x,2,20);`): elif nops([args])=1 and op(1,[args])=CF then print(`CF(a,A): The closed-form expression `): print(`(where k=nops(a)) for the number of good walks`): print(`that start at a`): print(`For example, try: CF([0,0],A);`): elif nops([args])=1 and op(1,[args])=CF1 then print(`CF1(a,A): The closed-form expression (divided by the`): print(`multinomial coefficient (A[1]+...+A[k])!/A[1]!/.../A[k]!`): print(`(where k=nops(a)) for the number of good walks`): print(`that start at a`): print(`For example, try: CF1([0,0],A);`): elif nops([args])=1 and op(1,[args])=GuessAndProveRegev3D then print(` GuessAndProveRegev3D(n,k,a): inputs symbols `): print(` n and k (for phrasing the output) and a lattice `): print(` point a=[a1,a2,a3] with a1>=a2>=a3>=0 integers `): print(` conjectures an expression (in terms of the Motzkin `): print(` numbers M(n)) for the number of walks of length `): print(` n-(a1+a2+a3) starting at [a1,a2,a3], with `): print(`unit positive steps ([1,0,0],[0,1,0],[0,0,1]) `): print(`always staying in x>=y>=z, and proceeds to prove`): print(`it completely rigorously. For example,for `): print(` the original Regev case try: `): print(` GuessAndProveRegev3D(n,k,[2,1,0]); `): elif nops([args])=1 and op(1,[args])=GuessAndProveRegev3Dterse then print(` GuessAndProveRegev3Dterse(n,a,M): The inputs is a symbol `): print(` n (for phrasing the output) and a lattice `): print(` point a=[a1,a2,a3] with a1>=a2>=a3>=0 integers `): print(` and a symbol M for denoting the Motzkin numbers.`): print(` The output is`): print(` an expression (in terms of the Motzkin `): print(` numbers M(n)) for the number of walks of length `): print(` n-(a1+a2+a3) starting at [a1,a2,a3], with `): print(`unit positive steps ([1,0,0],[0,1,0],[0,0,1]) `): print(`always staying in x>=y>=z, and proceeds to prove`): print(`it completely rigorously, but internally. `): print(`It only outputs the expression in terms of the Motzkin numbers`): print(`No news is good news. If it fails to prove it, it will tell you so`): print(` For example,for `): print(` the original Regev case try: `): print(` GuessAndProveRegev3Dterse(n,[2,1,0],M); `): elif nops([args])=1 and op(1,[args])=GenOper then print(`GenOper(n,N,Ord,Deg,a): a generic recurrence operator with`): print(`polynomial coefficients with symbol n and shift operator N`): print(`of order Ord and and deggree Deg, followed by the set of`): print(`coefficients. For example try: GenOper(n,N,1,1,a);`): elif nops([args])=1 and op(1,[args])=GuessOper1 then print(`GuessOper1(S1,S2,Ord,Deg,n,N): Given two sequences S1 and S2`): print(`guessesan operator P such that S1=P(n,N)S1 for example try:`): print(`GuessOper1(ARaS([0,0,0],20),ARaS([2,1,0],20),3,0,n,N);`): elif nops([args])=1 and op(1,[args])=GuessRegev3D then print(`GuessRegev3D(a,N): Given a lattice point a=[a1,a2,a3]`): print(`with a1>=a2>=a3 guesses a recurrence operaor (let's call`): print(` it P(N)`): print(`with constant coefficients (where N is the shift in n)`): print(`such that the number of walks with n-sum(a) steps starting`): print(`at a is P(n)M(n) where M(n) is the n-th Motzkin number`): print(`For example, try: GuessRegev3D([2,1,0],N);`): elif nops([args])=1 and op(1,[args])=GuessRegev4D then print(`GuessRegev4D(a,n,N): Given a lattice point a=[a1,a2,a3,a4]`): print(`with a1>=a2>=a3>=a4 guesses a recurrence operaor (let's call`): print(` it P(n,N)`): print(`with coefficients that are polynomials of degree 1 in n`): print(`(where N is the shift in n)`): print(`such that the number of walks with n-sum(a) steps starting`): print(`at a is P(n,N)M(n) where M(n) is the number of`): print(`n-step ballot-walks that start at [0,0,0,0]`): print(`For example, try: GuessRegev4D([3,2,1,0],n,N);`): elif nops([args])=1 and op(1,[args])=GuessRegev4Dnice then print(`GuessRegev4Dnice(a,n,M): Given a lattice point a=[a1,a2,a3,a4]`): print(`with a1>=a2>=a3>=a4 guesses an expression`): print(`for the number of walks with n-sum(a) steps starting`): print(`at a `): print(` in terms of M(n): the analogous quantity starting at [0,0,0,0],`): print(`For example, try: GuessRegev4Dnice([3,2,1,0],n,M);`): elif nops([args])=1 and op(1,[args])=GW then print(`GW(a,b): the number of walks from a to b with unit steps`): print(`always staying in x_1>=x_2>=...>=x_k (where k=nops(a))`): print(`For example try: GW([0,0],[4,4]);`): elif nops([args])=1 and op(1,[args])=GW1 then print(`GW1(a,b): the number of walks from a to b with unit steps`): print(`always staying in x_1>=x_2>=...>=x_k (where k=nops(a))`): print(`Using Closed-Form `): print(`For example try: GW([0,0],[4,4]);`): elif nops([args])=1 and op(1,[args])=GWf then print(`GWf(a,b): the number of walks from a to b with unit steps`): print(`always staying in x_1>=x_2>=...>=x_k (where k=nops(a))`): print(`Using the redundant generating function`): print(`For example try: GWf([0,0],[4,4]);`): elif nops([args])=1 and op(1,[args])=HafelOper then print(`HafelOper(Oper,x,k,a): applies the recurrence operator Oper`): print(`(phrased as a monomial in x[1], ..., x[k]) to the`): print(`multinomial coefficient (a[1]+...+a[k])!/a[1]!/.../a[k]!`): print(`and divides by the latter`): print(`For example, try: HafelOper(1-x[2]/x[1],x,2,a);`): elif nops([args])=1 and op(1,[args])=nuYTwith then print(`nuYTwith(shape,cell,m): the number of Young-tableaux of shape`): print(`shape with the entry in cell cell being m.`): print(`For example, try: nuYTwith([2,2],[2,2],4); `): elif nops([args])=1 and op(1,[args])=Pars then print(`Pars(n,k): all partitions of n with at most k parts.`): print(`For example, try: Pars(7,3);`): elif nops([args])=1 and op(1,[args])=Pars1 then print(`Pars1(K,n,k): all partitions of n with at most k parts.`): print(`with largest part K`): print(`For example, try: Pars1(4,7,3);`): elif nops([args])=1 and op(1,[args])=ParsWith then print(`ParsWith(n,k,cell): all partitions of n with at most k parts.`): print(`that contain the cell cell=[i,j]`): print(`For example, try: ParsWith(7,3,[2,2]);`): elif nops([args])=1 and op(1,[args])=ProveRegevOriginal then print(`ProveRegevOriginal(n,k): proves the original`): print(`Regev conjecture verbosely, for paths of length`): print(` n that start at [2,1,0]`): print(`using the symbols n and k`): elif nops([args])=1 and op(1,[args])=RegevStyle3YTwith then print(`RegevStyle3YTwith(cell,m,M,n): the explicit expression`): print(`in terms of the Motzkin number sequence M(n) for`): print(`the expression for the total number of`): print(`of 3-rowed Young-tableaux with n cells whose`): print(`entry in cell is m. For example, try:`): print(`RegevStyle3YTwith([2,1],3,M,n); `): elif nops([args])=1 and op(1,[args])=RegevStyle3YTwith1 then print(`RegevStyle3YTwith1(cell,m,N): the explicit operator`): print(`applied to the Motzkin number sequence M(n) for`): print(`the expression for the total number of`): print(`of 3-rowed Young-tableaux with n cells whose`): print(`entry in cell is m. For example, try:`): print(`RegevStyle3YTwith1([1,1],1,N); `): elif nops([args])=1 and op(1,[args])=RGF then print(`RGF(a,x): The redundant generating function (in x[1],x[2], ..)`): print(`for good walks`): print(`that start at a`): print(`For example, try: RGF([0,0],x);`): elif nops([args])=1 and op(1,[args])=RGFt then print(`RGFt(a,x,t): The redundant generating function (in x[1],x[2], ..)`): print(`for the total number of good walks`): print(`that start at a`): print(`For example, try: RGFt([0,0],x,t)`): elif nops([args])=1 and op(1,[args])=R then print(`R(a,A): The expression `): print(`in A[1],A[2],A[3]`): print(`such that the number of good walks from`): print(`a to [A[1],A[2],A[3]] can be written as`): print(`R(a;A[1],A[2],A[3])-R(a;A[1]+1,A[2],A[3]-1):`): print(`For example, try: R([0,0,0],A);`): elif nops([args])=1 and op(1,[args])=R1 then print(`R1(a,k,n): the two summands for the parts`): print(`k<=n/3 and n/3<=k<=n/2 for the Regev-style`): print(`single-sum for the the number of good walks`): print(`of length n that start at a, for example`): print(`try: R1([0,0,0],k,n);`): elif nops([args])=1 and op(1,[args])=RegevSummand then print(`RegevSummand(a,n,k): The summand for the Regev-style`): print(`single-binomial coefficient sum for good walks that`): print(`start at a. For example, try:`): print(`RegevSummand([0,0,0],n,k):`): elif nops([args])=1 and op(1,[args])=Sipur3 then print(`Sipur3(n,M,L,K): All the expressions for the number of lattice paths`): print(`of length n-(a1+a2) that start at [a1,a2,0] and stay`): print(`in x>=y>=z for L>=a1>=a2>0. `): print(`The program rigorously(!) proves each statement`): print(`It also prints out the first K terms`): print(`For example, try:`): print(`Sipur3(n,M,3,20);`): elif nops([args])=1 and op(1,[args])=Sipur3with then print(`Sipur3with(n,M,L,K): All the expressions for the number of `): print(`<=3-rowed Young-tableaux with n cells, in terms of`): print(`the Motzkin numbers M, whose [i,j] cell has m`): print(`for m<=L and i*j<=m`): print(`it all also prints out the first K terms`): print(`For example, try:`): print(`Sipur3with(n,M,3,20);`): elif nops([args])=1 and op(1,[args])=Sipur4 then print(`Sipur4(n,M,L,K): All the expressions for the number of lattice paths`): print(`of length n-(a1+a2+a3) that start at [a1,a2,a3,0] and stay`): print(`in x>=y>=z>=w for L>=a1>=a2>=a3>0. `): print(`The program semi-rigorously proves each statement`): print(`It also prints out the first K terms`): print(`For example, try:`): print(`Sipur4(n,M,3,20);`): elif nops([args])=1 and op(1,[args])=SYTkn then print(`SYTkn(k,n): the set of Standard Young Tableaux of <=k rows`): print(`with n cells. For example, try`): print(`SYTkn(3,5);`): elif nops([args])=1 and op(1,[args])=TnuYTodd then print(`TnuYTodd(k,n,cell): the total number of <=k-rowed Young-tableaux`): print(`of n cells such that cell has an odd entry`): print(`For example, try: TnuYTodd(3,10,[1,2]);`): elif nops([args])=1 and op(1,[args])=TnuYToddS then print(`TnuYToddS(k,n,cell,m): the sequence, for n=1..N`): print(`for the total number of <=k-rowed Young-tableaux`): print(`of n cells such that cell cell has an odd entry in it.`): print(`For example, try: TnuYToddS(3,10,[1,2],3);`): elif nops([args])=1 and op(1,[args])=TnuYTwith then print(`TnuYTwith(k,n,cell,m): the total number of <=k-rowed Young-tableaux`): print(`of n cells such that cell cell has m in it.`): print(`For example, try: TnuYTwith(3,10,[1,2],3);`): elif nops([args])=1 and op(1,[args])=TnuYTwithS then print(`TnuYTwithS(k,n,cell,m): the sequence, for n=m..N+m`): print(`for the total number of <=k-rowed Young-tableaux`): print(`of n cells such that cell cell has m in it.`): print(`For example, try: TnuYTwithS(3,10,[1,2],3);`): elif nops([args])=1 and op(1,[args])=YTwith then print(`YTwith(k,n,cell,m): the set of <=k-rowed Young-tableaux`): print(`of n cells such that cell cell has m in it.`): print(`for checking purposes)`): print(`For example, try: YTwith(3,10,[1,2],3);`): else print(`There is no ezra for`,args): fi: end: #GW(a,b): the number of walks from a to b with unit steps #always staying in x_1>=x_2>=...>=x_k (where k=nops(a)) #For example try: GW([0,0],[4,4]); GW:=proc(a,b) local k,i: option remember: k:=nops(a): if nops(b)<>k then ERROR(`Bad input`): fi: if not {seq(evalb(b[i]>=a[i]),i=1..k)}={true} then 0: elif b=a then 1: elif not {seq(evalb(b[i]-b[i+1]>=0),i=1..k-1)}={true} then 0: else add(GW(a,[op(1..i-1,b),b[i]-1,op(i+1..k,b)]),i=1..k): fi: end: #Pars1(K,n,k): all partitions of n with at most k parts. #and largest part K #For example, try: Pars1(3,7,3); Pars1:=proc(K,n,k) local n1,K1,mu,gu,i: option remember: if k=1 then if n=K then RETURN({[n]}): else RETURN({}): fi: fi: if n=1 and i<=k-1) then ERROR(`Bad input`): fi: [op(1..i-1,x),x[i+1]-1,x[i]+1,op(i+2..k,x)]: end: #Images(a): all the images of the vector a under reflections #w.r.t. to the hyperplanes x[i]-x[i+1]=-1 #Try: Images([a,b,c]); Images:=proc(a) local gu,gu1: gu:={[1,a]}: gu1:=OneStepImages(gu): while gu<>gu1 do gu:=gu1: gu1:=OneStepImages(gu): od: gu1: end: OneStepImages1:=proc(a) local k,i: k:=nops(a): {seq(Ref(a,i) ,i=1..k-1)}: end: #OneStepImages(S): all the reflections of elements of S #w.r.t. to ONE of the hyperplanes x[i]-x[i+1]=-1 (at a time) #Try: OneStepImages({[a,b,c]}); OneStepImages:=proc(S) local gu,w,mu,j,a,s: gu:={}: for s in S do w:=s[1]: a:=s[2]: mu:=OneStepImages1(a): gu:=gu union {seq([-w,mu[j]],j=1..nops(mu))}: od: gu union S: end: #RGF(a,x): The redundant generating function (in x[1],x[2], ..) #for good walks #that start at a #For example, try: RGF([0,0],x); RGF:=proc(a,x) local gu,k,i,j: k:=nops(a): gu:=Images(a): add(gu[i][1]*mul(x[j]^gu[i][2][j],j=1..k),i=1..nops(gu))/ (1-add(x[j],j=1..k)): end: #RGF1(a,x): The numerator of the #redundant generating function (in x[1],x[2], ..) #for good walks #that start at a #For example, try: RGF1([0,0],x); RGF1:=proc(a,x) local gu,k,i,j: k:=nops(a): gu:=Images(a): add(gu[i][1]*mul(x[j]^gu[i][2][j],j=1..k),i=1..nops(gu)): end: #GWf(a,b): the number of walks from a to b with unit steps #always staying in x_1>=x_2>=...>=x_k (where k=nops(a)) #using constant terms and generating functions #For example try: GWf([0,0],[4,4]); GWf:=proc(a,b) local gu,x,i,k: k:=nops(a): gu:=RGF(a,x): for i from 1 to k do gu:=coeff(series(gu,x[i]=0,b[i]+abs(degree(numer(gu),x[i]))+2),x[i],b[i]): gu:=normal(gu): od: gu: end: #RGFt(a,x,t): The redundant generating function (in x[1],x[2], ..) #for the total number of good walks #that start at a #For example, try: RGFt([0,0],x,t); RGFt:=proc(a,x,t) local gu,i,j,k: k:=nops(a): gu:=RGF(a,x): gu/mul(1-mul(t/x[j],j=1..i),i=1..k): end: #CT1(F,x,k): The constant term of any rational function of #form Laurent(x[1], ...,x[k])/(1-x[1]-...-x[k]) CT1:=proc(F,x,k) local mu,gu,mu1,c,i,i1: mu:=expand(normal(F*(1-add(x[i],i=1..k)))): gu:=0: for i from 1 to nops(mu) do mu1:=op(i,mu): if {seq(evalb(degree(mu1,x[i1])<=0),i1=1..k)}={true} then c:=normal(mu1/mul(x[i1]^degree(mu1,x[i1]),i1=1..k)): if not type(c,integer) then RETURN(FAIL): fi: gu:=gu+c*add(-degree(mu1,x[i1]),i1=1..k)!/ mul((-degree(mu1,x[i1]))!,i1=1..k): fi: od: gu: end: #ARf(n,k): total number of Young tableaux with at most k parts #with n cells. Using redudant generating function #For example, try: ARf(8,2); ARf:=proc(n,k) local gu,x,t: gu:=RGFt([0$k],x,t): gu:=taylor(gu,t=0,n+1): gu:=normal(coeff(gu,t,n)): CT1(gu,x,k): end: #ARaf(a,n): total number of Young tableaux with at most k parts #with n cells. #such that the the cells labelled 1, 2, ..., sum(a) has shape a #Using redudant generating function #For example, try: ARaf([0,0],8); ARaf:=proc(a,n) local gu,x,t,k: k:=nops(a): gu:=RGFt(a,x,t): gu:=taylor(gu,t=0,n+1): gu:=normal(coeff(gu,t,n)): CT1(gu,x,k): end: #Sym(f,x): the symmetrizer of f(x) (x is a list of variables) #For example, try: Sym(1/(1-x-2*y),[x,y]): Sym:=proc(f,x) local k,gu,mu,pi,i: k:=nops(x): mu:=permute(k): gu:=0: for pi in mu do gu:=gu+subs({seq(x[i]=x[pi[i]],i=1..k)},f): od: gu:=normal(gu/k!): end: #RGFtSym(a,x,t): The Symmetrized #redundant generating function (in x[1],x[2], ..) #for the total number of good walks #that start at a #For example, try: RGFtSym([0,0],x,t); RGFtSym:=proc(a,x,t) local i: Sym(RGFt(a,x,t),[seq(x[i],i=1..nops(a))]): end: #Axkn(x,k,n): The generating function for all partitions #of n, for example, try:Axkn(x,2,5); Axkn:=proc(x,k,n) local gu,i,j,t: gu:=1/mul(1-mul(t*x[j],j=1..i),i=1..k): gu:=taylor(gu,t=0,n+1): expand(coeff(gu,t,n)): end: F1abc:=proc(a1,a2,a3): (1-a2/(a1+1)-a3/(a1+1)+a2*a3/(a1+1)/(a1+2))* (a1+a2+a3)!/a1!/a2!/a3!: end: Gabc:=proc(a,b,c): (a-b+1)*(a-c+2)*(b-c+1)* (a+b+c)!/(a+2)!/(b+1)!/c!: end: GabcOld:=proc(a,b,c): (a-b+1)*(a-c+2)*(b-c+1)/(a+1)/(a+2)/(b+1)* (a+b+c)!/a!/b!/c!: end: Regev:=proc(n) local gu,a1,m: gu:=0: for a1 from 0 to trunc(n/3) do m:=n-a1: if m mod 2=0 then gu:=gu+F1abc(a1,m/2,m/2): else gu:=gu+F1abc(a1,(m+1)/2,(m-1)/2): fi: od: end: AR3:=proc(n) local gu,a,b,c,m: gu:=0: for a from trunc(n/3) to n do m:=n-a: for b from trunc(m/2) to a do c:=n-a-b: if a>=0 and b>=0 and c>=0 and a>=b and b>=c then gu:=gu+Gabc(a,b,c): fi: od: od: gu: end: AR3new:=proc(n) local gu,a: gu:=0: for a from trunc(n/3) to n do print(ifactor(AR3new1(n,a))): gu:=gu+AR3new1(n,a): od: gu: end: AR3new1:=proc(n,a) local b,m,gu,c: gu:=0: m:=n-a: for b from trunc(m/2) to a do c:=n-a-b: if a>=0 and b>=0 and c>=0 and a>=b and b>=c then gu:=gu+Gabc(a,b,c): fi: od: gu: end: ARaS:=proc(a,N) local n:[seq(ARa(a,n),n=1..N)]:end: Bxkn:=proc(x,k,n) local gu,i,j: gu:=Axkn(x,k,n): gu:=expand(gu*mul(1-x[i]/x[k+1-i],i=1..trunc(k/2))): for i from 1 to k do gu:=add(coeff(gu,x[i],j)*x[i]^j,j=0..degree(gu,x[i])): od: gu:=expand(gu): gu:=sort(gu): end: CleanUp:=proc(g,x,k) local i,j,gu: gu:=g: for i from 1 to k do gu:=add(coeff(gu,x[i],j)*x[i]^j,j=0..degree(gu,x[i])): od: gu:=expand(gu): collect(gu,x[1]): end: #HafelMono(Mono,x,k,a): applies the shift-monomial Mono #(phrased as a monomial in x[1], ..., x[k]) to the #multinomial coefficient (a[1]+...+a[k])!/a[1]!/.../a[k]! #and divides by the latter #For example, try: HafelMono(x[2]/x[1],x,2,a) HafelMono:=proc(Mono,x,k,a) local F,G,i: F:=add(a[i],i=1..k)!/mul(a[i]!,i=1..k): G:=subs({seq(a[i]=a[i]-degree(Mono,x[i]),i=1..k)},F): normal(simplify(expand(G/F))): end: #Mekadem(Mono,x,k): the coeff. of Mono Mekadem:=proc(Mono,x,k) local i: normal(Mono/mul(x[i]^degree(Mono,x[i]),i=1..k)): end: #HafelOper(Oper,x,k,a): applies the recurrence operator Oper #(phrased as a monomial in x[1], ..., x[k]) to the #multinomial coefficient (a[1]+...+a[k])!/a[1]!/.../a[k]! #and divides by the latter #For example, try: HafelOper(1-x[2]/x[1],x,2,a) HafelOper:=proc(Oper,x,k,a) local i,mu,gu: mu:=expand(Oper): if not type(mu,`+`) then RETURN(HafelMono(mu,x,k,a)): fi: gu:=0: for i from 1 to nops(mu) do gu:=gu+Mekadem(op(i,mu),x,k)*HafelMono(op(i,mu),x,k,a): od: factor(normal(gu)): end: #CF1(a,A): The closed-form expression (divided by the #multinomial coefficient (A[1]+...+A[k])!/A[1]!/.../A[k]! #(where k=nops(a)) for the number of good walks #that start at a #For example, try: RGF([0,0],A); CF1:=proc(a,A) local gu,k,x: k:=nops(a): gu:=RGF1(a,x): HafelOper(gu,x,k,A): end: #CF(a,A): The closed-form expression #(where k=nops(a)) for the number of good walks #that start at a #For example, try: CF([0,0],A); CF:=proc(a,A) local i,k: k:=nops(a): CF1(a,A)*add(A[i],i=1..k)!/mul(A[i]!,i=1..k): end: #GW1(a,b): the number of walks from a to b with unit steps #always staying in x_1>=x_2>=...>=x_k (where k=nops(a)) #using CF #For example try: GW1([0,0],[4,4]); GW1:=proc(a,b) local gu,A,i,k: gu:=CF(a,A): k:=nops(a): eval(subs({seq(A[i]=b[i],i=1..k)},gu)): end: #R(a,A): The expression #in A[1],A[2],A[3] #such that the number of good walks from #a to [A[1],A[2],A[3]] can be written as #R(a;A[1],A[2],A[3])-R(a;A[1]+1,A[2],A[3]-1): #For example, try: R([0,0,0],A); R:=proc(a,A) local gu,x: if nops(a)<>3 then ERROR(`Bad input`): fi: gu:=normal(RGF1(a,x)/(1-x[3]/x[1])): normal(HafelOper(gu,x,3,A)): end: #R1(a,k,n): the two summands for the parts #k<=n/3 and n/3<=k<=n/2 for the Regev-style #single-sum for the the number of good walks #of length n that start at a, for example #try: R1([0,0,0],k,n); R1:=proc(a,k,n) local A,gu: gu:=R(a,A); factor([subs({A[1]=n-2*k,A[2]=k,A[3]=k},gu), subs({A[1]=k,A[2]=k,A[3]=n-2*k},gu)]): end: #RegevSummand(a,n,k): The summand for the Regev-style #single-binomial coefficient sum for good walks that #start at a. For example, try: #RegevSummand([0,0,0],n,k): RegevSummand:=proc(a,n,k) local gu: gu:=R1(a,k,n): if gu[1]<>gu[2] then RETURN(FAIL): fi: gu[1]*n!/k!^2/(n-2*k)!: end: ProveRegevOriginal:=proc(n,k) local gu,mu,gu1: print(`Theorem: Let M(n) be the number of walks of length n`): print(`from (0,0,0) using unit positive steps and staying in`): print(`the region x>=y>=z>=0. Let A(n) be the number of such walks`): print(`with n-3 steps, that start at (2,1,0). Then `): print(`A(n)=M(n-1)-M(n-3) . `): print(): print(`Proof:`): print(`The summand for M(n),`): print(`let's call it F(n,k), is`): gu:=RegevSummand([0,0,0],n,k): print(gu): print(`The summand for A(n), `): print(`let's call it G(n,k), is`): mu:=RegevSummand([2,1,0],n,k): print(mu): print(`To prove Amitai Regev's conjecture we must show that`): print(`Sum(F(n-1,k)-F(n-3,k),k=0..n)=Sum(G(n,k),k=0..n).`): print(`Hence the summand of the difference,`): print(`F(n-1,k)-F(n-3,k)-G(n,k), is `): gu:=normal(simplify(expand(subs(n=n-1,gu)/gu))- simplify(expand(subs(n=n-3,gu)/gu)) - simplify(expand(mu/gu)) )*gu: print(gu): print(`But this is a telescoping sum, the summand being H(n,k+1)-H(n,k)`): print(`where H(n,k) is`): gu1:=sum(gu,k): if simplify(subs(k=k+1,gu1)-gu1-gu)<>0 then RETURN(FAIL): fi: print(gu1): print(`Check! (or believe me). This concludes the proof of Amitai Regev's`): print(`conjecture. QED.`): end: #GenOper(n,N,Ord,Deg,a): a generic recurrence operator with #polynomial coefficients with symbol n and shift operator N #of order Ord and and deggree Deg, followed by the set of #coefficients. For example try: GenOper(n,N,1,1,a); GenOper:=proc(n,N,Ord,Deg,a) local ope,i,j,var: ope:=0: var:={}: for i from 0 to Ord do for j from 0 to Deg do var:=var union {a[i,j]}: ope:=ope+a[i,j]*n^j*N^(-i): od: od: ope,var: end: #ApplyOper(S,ope,n,N): applies the operator ope(n,1/N) to the #sequence S as soon as it makes sense ApplyOper:=proc(S,ope,n,N) local gu,L,kha,n1,i: gu:=[]: L:=-ldegree(ope,N): for n1 from L+1 to nops(S) do kha:=add(S[n1-i]*subs(n=n1,coeff(ope,N,-i)),i=0..L): gu:=[op(gu),kha]: od: gu: end: #GuessOper1(S1,S2,Ord,Deg,n,N): Given two sequences S1 and S2 #guessesan operator P such that S2=P(n,N)S1 for example try: #GuessOper1(ARaS([0,0,0],20),ARaS([2,1,0],20),3,0,n,N); GuessOper1:=proc(S1,S2,Ord,Deg,n,N) local ope, var,S1t,S2t,L,var1,a,i,eq: if nops(S1)<>nops(S2) then ERROR(`Bad input`): fi: ope:=GenOper(n,N,Ord,Deg,a): var:=ope[2]: ope:=ope[1]: L:=-ldegree(ope,N): if nops(S1)-L-1-nops(var)<9 then ERROR(`Insufficient data`): fi: S1t:=ApplyOper(S1,ope,n,N): S2t:=[op(L+1..nops(S2),S2)]: eq:={seq(S1t[i]-S2t[i],i=3..nops(S1t))}: var1:=solve(eq,var): if var1=NULL then RETURN(FAIL): else RETURN(subs(var1,ope)): fi: end: #GuessRegev3D(a,N): Given a lattice point a=[a1,a2,a3] #with a1>=a2>=a3 guesses a recurrence operaor (let's call # it P(N) #with constant coefficients (where N is the shift in n) #such that the number of walks with n-sum(a) steps starting #at a is P(n)M(n) where M(n) is the n-th Motzkin number #For example, try: GuessRegev3D([2,1,0],N); GuessRegev3D:=proc(a,N) local n,L,orekh,gu: L:=convert(a,`+`): orekh:=11+2*L: gu:=GuessOper1(ARaS([0,0,0],orekh),ARaS(a,orekh),L,0,n,N) : if gu=FAIL then RETURN(FAIL): fi: sort(gu): end: #GuessAndProveRegev3D(n,k,a): inputs symbols #n and k (for phrasing the output) and a lattice #point a=[a1,a2,a3] with a1>=a2>=a3>=0 integers #conjectures an expression (in terms of the Motzkin #numbers M(n)) for the number of walks of length #n-(a1+a2+a3) starting at [a1,a2,a3], with #unit positive steps ([1,0,0],[0,1,0],[0,0,1]) #always staying in x>=y>=z, and proceeds to prove #it completely rigorously. For example,for #the original Regev case try: #GuessAndProveRegev3D(n,k,[2,1,0]); GuessAndProveRegev3D:=proc(n,k,a) local gu,mu,gu1,ope,N,i: ope:=GuessRegev3D(a,N): if ope=FAIL then RETURN(FAIL): fi: print(`Theorem: Let M(n) be the number of walks of length n`): print(`from [0,0,0], using unit positive steps and staying in`): print(`the region x>=y>=z>=0. These are the famous Motzkin numbers,`): print(`as first proved by Amitai Regev in 1981.`): print(`Let A(n) be the number of such walks`): print(`with `, n-convert(a,`+`), `steps, that start at`,a, ` Then `): print(A(n)=add(coeff(ope,N,-i)*M(n-i),i=-degree(ope,N)..-ldegree(ope,N))): print(): print(`Proof:`): print(` Thanks to Regev's seminal result (that can be reproved `): print(` with our approach), the summand for M(n),`): print(`let's call it F(n,k), is`): gu:=RegevSummand([0,0,0],n,k): print(gu): print(`The summand for A(n), `): print(`let's call it G(n,k), is`): mu:=RegevSummand(a,n,k): print(mu): print(`To prove the Theorem, we must show that`): print(`the sum (w.r.t. k), whose summand is`): print(G(n,k)-add(coeff(ope,N,-i)*F(n-i,k),i=-degree(ope,N)..-ldegree(ope,N))): print(`is identically zero`): gu:= normal( add( coeff(ope,N,-i)* normal( simplify(expand(subs(n=n-i,gu)/gu)) ), i=-degree(ope,N)..-ldegree(ope,N)) -expand(simplify(mu/gu)) )*gu: #HERE print(`But this is a telescoping sum, the summand being H(n,k+1)-H(n,k)`): print(`where H(n,k) is`): gu1:=sum(gu,k): if simplify(subs(k=k+1,gu1)-gu1-gu)<>0 then RETURN(FAIL): fi: print(gu1): print(`Check! (or believe me). This concludes the proof of our theorem`): print(` that is an analog of Amitai Regev's`): print(` original conjecture (whose starting point was [2,1,0]). QED.`): end: #GuessAndProveRegev3Dterse(n,k,a,M): inputs symbols #n (for phrasing the output) and a lattice #point a=[a1,a2,a3] with a1>=a2>=a3>=0 integers #conjectures an expression (in terms of the Motzkin #numbers M(n)) for the number of walks of length #n-(a1+a2+a3) starting at [a1,a2,a3], with #unit positive steps ([1,0,0],[0,1,0],[0,0,1]) #always staying in x>=y>=z, and proceeds to prove #it completely rigorously, but the output is terse. #the output is simply the expression in the Motzkin #numbers M(n), where M is part of the input indicationg #the symbol to be used, and if it does not complain #it means that it proved it. #the original Regev case try: #GuessAndProveRegev3Dterse(n,k,[2,1,0],M); GuessAndProveRegev3Dterse:=proc(n,a,M) local gu,mu,gu1,ope,N,i,k: ope:=GuessRegev3D(a,N): if ope=FAIL then RETURN(FAIL): fi: gu:=RegevSummand([0,0,0],n,k): mu:=RegevSummand(a,n,k): gu:= normal( add( coeff(ope,N,-i)* normal( simplify(expand(subs(n=n-i,gu)/gu)) ), i=-degree(ope,N)..-ldegree(ope,N)) -expand(simplify(mu/gu)) )*gu: gu1:=sum(gu,k): if simplify(subs(k=k+1,gu1)-gu1-gu)<>0 then RETURN(FAIL): fi: RETURN(add(coeff(ope,N,-i)*M(n-i),i=-degree(ope,N)..-ldegree(ope,N))): end: #Sipur3(n,M,L,K): All the expressions for the number of lattice paths #of length n-(a1+a2) that start at [a1,a2,0] and stay #in x>=y>=z for L>=a1>=a2>. #it all also prints out the first K terms #For example, try: #Sipur3(n,M,3,20); Sipur3:=proc(n,M,L,K) local a1, a2: print(`Let `, M(n), ` be the Motzkin numbers `): for a1 from 0 to L do for a2 from 0 to a1 do print(`The number of`,n-a1-a2, `-step 3D ballot-lattice paths starting at`, [a1,a2,0] , ` equals (and (rigorously!) proved)`): print(GuessAndProveRegev3Dterse(n,[a1,a2,0],M)): print(`The first`, K-a1-a2, `terms are `): print(op(a1+a2..K,ARaS([a1,a2,0],K))): od: od: end: #GuessRegev4D(a,n,N): Given a lattice point a=[a1,a2,a3,a4] #with a1>=a2>=a3>=a4 guesses a recurrence operaor (let's call # it P(n,N) #with coefficients that are polynomials of degree 1 in n #(where N is the shift in n) #such that the number of walks with n-sum(a) steps starting #at a is P(n,N)M(n) where M4(n) is this quantity when it #starts at [0,0,0,0] #For example, try: GuessRegev4D([3,2,1,0],n,N); GuessRegev4D:=proc(a,n,N) local L,orekh,gu: L:=convert(a,`+`): orekh:=20+4*L: gu:=GuessOper1(ARaS([0,0,0,0],orekh),ARaS(a,orekh),L,1,n,N) : if gu=FAIL then RETURN(FAIL): fi: gu: end: #GuessRegev4Dnice(a,n,M): Given a lattice point a=[a1,a2,a3,a4] #with a1>=a2>=a3>=a4 guesses an expression #for the number of walks with n-sum(a) steps starting #in terms of M(n), which is this quantity when it #starts at [0,0,0,0] #For example, try: GuessRegev4D([3,2,1,0],n,N); GuessRegev4Dnice:=proc(a,n,M) local ope,N,i: ope:=GuessRegev4D(a,n,N) : RETURN(add(factor(coeff(ope,N,-i))*M(n-i),i=-degree(ope,N)..-ldegree(ope,N))): end: #Sipur4(n,M,L,K): All the expressions for the number of lattice paths #of length n-(a1+a2+a3) that start at [a1,a2,a3,0] and stay #in x>=y>=z>=w for L>=a1>=a2>a3. For example, try: #it also prints out the first K terms #Sipur4(n,M,3,20); Sipur4:=proc(n,M,L,K) local a1, a2,a3: print(`Let `, M(n), ` be the Motzkin numbers `): for a1 from 0 to L do for a2 from 0 to a1 do for a3 from 0 to a2 do print(`The number of`,n-a1-a2-a3, `-step 3D ballot-lattice paths starting at`, [a1,a2,a3,0] , ` equals (and is provable, but we only proved it semi-rigorously)`): print(GuessRegev4Dnice([a1,a2,a3,0],n,M)): print(`The first`, K-a1-a2-a3, `terms are `): print(op(a1+a2+a3..K,ARaS([a1,a2,a3,0],K))): od: od: od: end: #ParsWith(n,k,cell): all partitions of n with at most k parts. #that contain the cell cell=[i,j] as a corner-cell #For example, try: ParsWith(7,3,[2,2]); ParsWith:=proc(n,k,cell) local gu,s,i,j,mu: i:=cell[1]: j:=cell[2]: mu:=Pars(n,k): gu:={}: for s in mu do if i<=k and j=s[i] then gu:=gu union {s}: fi: od: gu: end: #nuYTwith(shape,cell,m): the number of Young-tableaux of shape #shape with the entry in cell cell being m. #For example, try: nuYTwith([2,2],[2,2],4) nuYTwith:=proc(shape,cell,m) local gu,mu,i,j,k,sh,sh1: k:=nops(shape): i:=cell[1]: j:=cell[2]: if m=a2>=a3>=0 integers #conjectures an expression (in terms of the Motzkin #numbers M(n)) for the number of walks of length #n-(a1+a2+a3) starting at [a1,a2,a3], with #unit positive steps ([1,0,0],[0,1,0],[0,0,1]) #always staying in x>=y>=z, and proceeds to prove #it completely rigorously, but the output #just the operator (constant-coeff. in N) #it means that it proved it. #the original Regev case try: #GuessAndProveRegev3DVeryTerse([2,1,0],N); GuessAndProveRegev3DVeryTerse:=proc(a,N) local gu,mu,gu1,ope,i,n,k: ope:=GuessRegev3D(a,N): if ope=FAIL then RETURN(FAIL): fi: gu:=RegevSummand([0,0,0],n,k): mu:=RegevSummand(a,n,k): gu:= normal( add( coeff(ope,N,-i)* normal( simplify(expand(subs(n=n-i,gu)/gu)) ), i=-degree(ope,N)..-ldegree(ope,N)) -expand(simplify(mu/gu)) )*gu: gu1:=sum(gu,k): if simplify(subs(k=k+1,gu1)-gu1-gu)<>0 then RETURN(FAIL): fi: ope: end: #RegevStyle3YTwith(cell,m,N): the explicit operator #applied to the Motzkin number sequence M(n) for #the expression for the total number of #of 3-rowed Young-tableaux with n cells whose #entry in cell is m. For example, try: #RegevStyle3YTwith([1,1],1,N): RegevStyle3YTwith1:=proc(cell,m,N) local gu,mu,i,sh,sh1,ope: gu:=0: if cell[1]>3 then ERROR(`Bad input`): fi: mu:=ParsWith(m,3,cell): i:=cell[1]: gu:=0: for sh in mu do sh1:=[op(1..i-1,sh),sh[i]-1,op(i+1..3,sh)]: ope:=GuessAndProveRegev3DVeryTerse(sh,N): if ope=FAIL then print(`Something went wrong`): fi: gu:=gu+GW([0$3],sh1)*ope: od: gu: gu: end: #RegevStyle3YTwith(cell,m,M,n): gives #a (rigorously proved!) expression #in terms of the Motzkin numbers M(n) #(M and n are inputted symbols) #for the number of n-celled three-rowed Young tableaux #whose entry at cell cell is m, for example, try: #RegevStyle3YTwith([1,2],3,M,n); RegevStyle3YTwith:=proc(cell,m,M,n) local N,ope,i: ope:=RegevStyle3YTwith1(cell,m,N): add(coeff(ope,N,-i)*M(n-i),i=-degree(ope,N)..-ldegree(ope,N)): end: #Sipur3with(n,M,L,K): All the expressions for the number of #<=3-rowed Young-tableaux with n cells, in terms of #the Motzkin numbers M, whose [i,j] cell has m #for m<=L and i*j<=m #it all also prints out the first K terms #For example, try: #Sipur3with(n,M,3,20); Sipur3with:=proc(n,M,L,K) local m,Y,i,j,lu: print(`Let `, M(n), ` be the Motzkin numbers `): print(`The following are (rigorously proved!) explicit expressions`): print(`in terms of the Motzkin numbers M(n), for the number of 3-rowed`): print(` n-celled `): print(`Young-tableaux whose [i,j]-entry has m in it, for m between`): print(`1 and `, L, `and the cell [i,j], with i<=3 (of course) and`): print(` i*j<=m `): for m from 1 to L do for i from 1 to 3 do for j from 1 to trunc(m/i) do lu:=RegevStyle3YTwith([i,j],m,M,n): if lu<>0 then print(`The number of three-rowed n-celled Young tableaux Y such that`): print(Y[i,j]=m, ` equals `): print(lu): print(`The first`, K, `non-zero terms are `): print(TnuYTwithS(3,K,[i,j],m)): fi: od: od: od: end: Children:=proc(Lam) local i, temp,Lam1,k: if Lam=[] then RETURN({}): fi: temp:={}: for i from 1 to nops(Lam)-1 do if Lam[i]>Lam[i+1] then Lam1:=[op(1..i-1,Lam),Lam[i]-1,op(i+1..nops(Lam),Lam)]: temp:=temp union {[Lam1,i]}: fi: od: k:=nops(Lam): if Lam[k]>1 then Lam1:=[op(1..k-1,Lam),Lam[k]-1]: temp:=temp union {[Lam1,k]}: else Lam1:=[op(1..k-1,Lam)]: temp:=temp union {[Lam1,k]}: fi: temp: end: SYT:=proc(Lam) local ch,i,n,j,temp,temp1: option remember: n:=convert(Lam,`+`): if Lam=[] then RETURN({[]}): fi: temp:={}: ch:=Children(Lam): for i from 1 to nops(ch) do temp1:=SYT(ch[i][1]): temp:=temp union {seq(Ap(temp1[j],ch[i][2],n),j=1..nops(temp1))}: od: temp: end: Ap:=proc(Y,i,n) : if i<=nops(Y) then [op(1..i-1,Y),[op(Y[i]),n],op(i+1..nops(Y),Y)]: else [op(Y),[n]]: fi: end: Shrink:=proc(lam) local i: for i from 1 to nops(lam) do if lam[i]=0 then RETURN([op(1..i-1,lam)]): fi: od: lam: end: #SYTkn(k,n): the set of Standard Young Tableaux of <=k rows #with n cells SYTkn:=proc(k,n) local gu,mu,lam: option remember: mu:=Pars(n,k): gu:={}: for lam in mu do gu:=gu union SYT(Shrink(lam)): od: gu: end: #YTwith(k,n,cell,m): the set of <=k-rowed Young-tableaux #of n cells such that cell cell has m in it. #for checking purposes) #For example, try: YTwith(3,10,[1,2],3); YTwith:=proc(k,n,cell,m) local gu,mu,Y,i,j: i:=cell[1]: j:=cell[2]: mu:=SYTkn(k,n): gu:={}: for Y in mu do if i<=nops(Y) and j<=nops(Y[i]) and Y[i][j]=m then gu:=gu union {Y}: fi: od: gu: end: