##SiPerUGJ: Save this file as SiPerUGJ. To use it, stay in the # ##same directory, get into Maple (by typing: maple ) # ##and then type: read SiPerUGJ : # ##Then follow the instructions given there # ## # ##Written by Doron Zeilberger, Temple University , # #zeilberg@math.temple.edu. # ####################################################################### #Created: May 8, 2001 #This version: May 8, 2001 #SiPerUGJ: A Maple package that finds Umbral Schemes #for enumerating words that avoid as factors #an infinite family of parametrized "mistakes" #where the set of mistakes are invariant under the #group of signed permutations # #It is one of the packages that accompany Doron Zeilberger's article: #The Umbral Transfer Matrix Method. V. The Goulden-Jackson #Cluster Method for Infinitely Many Mistakes #Please report bugs to zeilberg@math.temple.edu print(`SiPerUGJ: A Maple package that finds Umbral Schemes`): print(`for enumerating words that avoid as factors`): print(` an infinite family of parametrized "mistakes"`): print(` where the set of mistakes is symmetric w.r.t. `): print(`group of signed permutations`): print(`It is one of the packages that accompany Doron Zeilberger's article:`): print(`The Umbral Transfer Matrix Method. V. The Goulden-Jackson`): print(`Cluster Method for Infinitely Many Mistakes`): print(`Please report bugs to zeilberg@math.temple.edu`): lprint(``): print(`Created: May 8, 2001`): print(`This version: May 8, 2001`): lprint(``): print(`Written by Doron Zeilberger, zeilberg@math.temple.edu`): lprint(``): print(`Please report bugs to zeilberg@math.temple.edu`): lprint(``): print(`The most current version of this package and paper`): print(` are available from`): print(`http://www.math.temple.edu/~zeilberg/`): print(`For a list of the procedures type ezra(), for help with`): print(`a specific procedure, type ezra(procedure_name)`): print(``): ezra:=proc() print(``): if nops([args])=0 then print(`The main procedures are : `): print(` CheckU, SawUm4, SawUm6 `): print(` Tony, Tony4, Tony6, UGJseries, WtUmSc,YafeUmSc .`): print(`For help with`): print(`a specific procedure, type ezra(procedure_name)`): fi: if nops([args])=1 and args[1]=CheckU then print(`CheckU(SymbMisSet,NuLet,L): Uses the Classical Goulden-`): print(`Jackson to find the first L terms of the set of words in`): print(`the alphabet {+-1,+-2, ...,+-NuLet}`): print(` that avoid factors from SymbMisSet`): print(`and all their images under the group of signed permutations`): print(`acting on the letters`): print(`where each symbolic mistake has the form [[letter1,expression1], ...]`): print(`and expression1... are affine linear expressions in the variables`): print(`of DisVars`): print(`For example, set, SymbMisSet:= `): print(`{[[[1,1],[-1,1]],[]], [[[1,a+1],[2,b+1],[-1,a+1+c],[-2,b+1],[1,c]],`): print(`[a,b,c]]}`): print(`and then type: `): print(`CheckU(SymbMisSet,2,L)`): fi: if nops([args])=1 and args[1]=FindUmb then print(`FindUmb(U,V,x,t,d): Given two symbolic words, U, and V,`): print(`and a variable x (x an index variable, for catalytic`): print(`variables), and a variable t, to keep track of length`): print(`computes the umbral edge connecting U and V`): print(` also taking account of the images of V under permutations`): print(` on d letters`): print(`For example try: FindUmb([[[1,1],[2,a],[3,a],[1,1]],[a]],`): print(`[[[1,1],[2,a],[3,a],[1,1]],[a]],x,t,d):`): fi: if nops([args])=1 and args[1]=FindUmbInt then print(`FindUmbInt(U,V,i,x,t): Given two symbolic letters U, V`): print(`expressed in symbolic frequency notation`): print(`{[[let1,AffLinExp1],[let2,AffLinExp2], ...], {set_of_symbols}}`): print(`and a location i, one of the legal interfaces of`): print(`U before V in a symbolic cluster, and a sumbol x, `): print(`for the catalytic variabes and a symbol t, find the umbra that`): print(`sends x_1^a_1*x_2^a_2 ... to the generating function of all possible`): print(`such V's `): print(`For example try: FindUmbInt([[[1,1],[2,a],[3,a],[1,1]],[a]],`): print(`[[[1,1],[2,a],[3,a],[1,1]],[a]],4,x,t):`): fi: if nops([args])=1 and args[1]=mist then print(`mist(memo,dim): all minimimally bad walks up to memory`): print(`memo and dimension dim (written by John Noonan)`): fi: if nops([args])=1 and args[1]=SawUm4 then print(`SawUm4(x,t): An Umbral Scheme for the`): print(`Cluster Generating Function for 2D walks on the`): print(`square lattice that avoid retracing and rectangular subwalks,`): fi: if nops([args])=1 and args[1]=SawUm6a then print(`SawUm6a(x,t): An Umbral Scheme for the`): print(`Cluster Generating Function for 2D walks on the`): print(`square lattice that avoid retracing , rectangles, and hexagonal`): print(`walks that start at a corner`): fi: if nops([args])=1 and args[1]=SawUm6 then print(`SawUm6(x,t): An Umbral Scheme for the`): print(`Cluster Generating Function for 2D walks on the`): print(`square lattice that avoid retracing , rectangular, and hexagonal`): print(`subwalks `): fi: if nops([args])=1 and args[1]=SpellOut then print(`SpellOut(SymbMisSet,NuLett,L): `): print(`Finds the concrete mistakes up to`): print(`length L in `): print(`the alphabet with 2*NuLet letters`): print(`-1,1,-2,2,-3,3, ..., -NuLett, NuLett that `): print(`are implied by the set of symbolic mistakess SymbMisSet`): print(`where each symbolic mistake has the form `): print(` [[letter1,expression1], ...]`): print(`and expression1... are affine linear expressions in the variables`): print(`of DisVars`): fi: if nops([args])=1 and args[1]=Tony then print(`Like UGJseries, but also gives the intermediate results`): print(`For example, set, SetSW:= `): print(`[[[[1,1],[-1,1]],[]], [[[1,a+1],[2,b+1],[-1,a+2+c],[-2,b+1],[1,c+1]],`): print(`[a,b,c]]]`): print(`and then type: `): print(`Tony( SetSW,2,20):`): fi: if nops([args])=1 and args[1]=Tony4 then print(`Tony4(n): The first n terms in the enumerating`): print(`series for 2D walks in the rectangular lattice that`): print(`avoid rectangles (that may start anywhere)`): fi: if nops([args])=1 and args[1]=Tony6 then print(`Tony6(n): The first n terms in the enumerating`): print(`series for 2D walks in the rectangular lattice that`): print(`avoid rectangles (that may start anywhere), and hexagons`): print(`that may start anywhere`): fi: if nops([args])=1 and args[1]=UGJseries then print(`UGJseries(SetSW,DIM,L): Given a set of symbolic`): print(`letters, SetSW, `): print(`in the alphabet -1,1,-2,2,...,-DIM,DIM`): print(`an integer, and an integer L, uses the Umbral Scheme`): print(`to find the first L terms of the series expansion`): print(`of words that avoid the mistakes of SetSW`): print(`and all their images under the group of signed permutations`): print(`For example, set, SetSW:= `): print(`{[[[1,1],[-1,1]],[]], [[[1,a+1],[2,b+1],[-1,a+1],[-2,b+1]],`): print(`[a,b]]}`): print(`and then type: `): print(`UGJseries( SetSW,2,20):`): fi: if nops([args])=1 and args[1]=WtUmSc then print(`WtUmSc(ListSW,x,t,d): Given a list of symbolic words`): print(`ListSW, constructs an Umbral Scheme for the Cluster`): print(`generating function `): print(`where the mistakes are the members of ListSW and all their images`): print(` under the group of signed permutations on {-1,1,-2,2,...,-d,d} `): print(`For example, type: ListSW:= `): print(`[[[[1,1],[-1,1]],[]], [[[1,a+1],[2,b+1],[-1,a+1],[-2,b+1]],`): print(`[a,b]]]`): print(`and then type: `): print(`WtUmSc( ListSW,x,t,2):`): fi: if nops([args])=1 and args[1]=YafeUmSc then print(`YafeUmSc(UmbSc,F,D): Given an umbral `): print(`Scheme UmbSc, in`): print(`Maple notation, converts it to human notation`): print(`using the symbols F[1], F[2] for the functions and D for `): print(`differntiation of respective variables`): fi: end: #############Programs Taken from ROTA############### # ToUmbra(poly1,xlist,alist): given a polynomial, poly1, in the # variables xlist with exponents that are affine-linear # expressions in the discrete variables in the # list alist, and in the variables of alist themselves # outputs the corresponding Umbra, such that # poly1 is the image, under that umbra, of the # generic monomial y[1]^alist[1]*...*y[k]^alist[k], # (where k=nops(alist), and y[1], ..., y[k] are generic # continuous variables that correspond to the disrete variables # in alist # The format of the output is a set, each element of whcih # is a list of 3-elements # [FRONT, Diffs,SubsList], where the FRONT # is a rational function in whatever, Diffs is a list of # integers of the same length as alist, and SubsList is # the list of substitutions that the continuous variables # that correspond to alist have to be substituted by # For example ToUmbra(a*x^b+b*y^a,[x,y],[a,b]) should yield # {[1, [1, 0], [1, x]], [1, [0, 1], [y, 1]]} ToUmbra:=proc(poly1,xlist,alist) local gu,i,poly2: poly2:=expand(poly1): if not type(poly2,`+`) then RETURN(SimplifyUmbra({UmbralTerm(poly2,xlist,alist)})): fi: gu:={}: for i from 1 to nops(poly2) do gu:=gu union {UmbralTerm(op(i,poly2),xlist,alist)}: od: SimplifyUmbra(gu): end: # UmbralTerm(mono,xlist,alist): given a monomial in the # variables xlist with exponents that are affine-linear # expressions in the discrete variables in the # list alist, and in the variables of alist themselves # outputs the corresponding term in the Umbra # The format of the output is a list of 3-elements # [FRONT, Diffs,SubsList], where the FRONT # is a rational function in whatever, Diffs is a list of # integers of the same length as alist, and SubsList is # the list of substitutions that the continuous variables # that correspond to alist have to be substituted by # UmbralTerm:=proc(mono,xlist,alist) local mono1,FRONT, Diffs, SubsList,i,d1,gu: mono1:=expand(mono): gu:=hafokh(mono1,xlist,alist): FRONT:=gu[2]: SubsList:=gu[1]: mono1:=expand(FRONT): Diffs:=[]: for i from 1 to nops(alist) do d1:=degree(mono1,alist[i]): mono1:=expand(normal(expand(mono1/alist[i]^d1))): Diffs:=[op(Diffs),d1]: od: [mono1,Diffs,SubsList]: end: #hafokh(mono,xlist,alist): given a monomial mono, in the form #product(x[i]^a[j]) outputs the list [p[1],...p[k]] and the #left-over monomial, lu, such that #such that it equals lu*p[1]^a[1]*...*p[k]^a[k] times hafokh:=proc(mono,xlist,alist) local mono1,i,resh,mu: mono1:=expand(mono): resh:=[]: for i from 1 to nops(alist) do mu:=grab(mono1,alist[i]): resh:=[op(resh),mu[1]]: mono1:=mu[2]: od: resh,mono1: end: #grab(mono,a): given a monomial, mono, in the variables # # exponent (discrete) variable, a, returns #the largest monomial, lu, such that lu^a is a factor of mono grab:=proc(mono,a) local mono1,mono2,i,lu,mu,mu1,mu2,khe,mu11,mu12: mono1:=expand(mono): mono2:=expand(mono1): lu:=1: if type(mono1,`*`) then for i from 1 to nops(mono1) do mu:=op(i,mono1): if type(mu,`^`) then mu1:=op(1,mu): mu2:=op(2,mu): if type(mu1,`^`) then mu11:=op(1,mu1): if type(mu11, `^`) then ERROR(`I give up`): fi: mu12:=op(2,mu1): mu1:=mu11: mu2:=mu2*mu12: fi: khe:=coeff(expand(mu2),a,1): lu:=lu*mu1^khe: mono2:=simplify(mono2/mu1^(a*khe)): fi: od: elif type(mono1,`^`) then mu1:=op(1,mono1): mu2:=op(2,mono1): if type(mu1,`^`) then mu11:=op(1,mu1): if type(mu11, `^`) then ERROR(`I give up`): fi: mu12:=op(2,mu1): mu1:=mu11: mu2:=mu2*mu12: fi: khe:=coeff(mu2,a,1): lu:=lu*mu1^khe: mono2:=simplify(mono2/mu1^(a*khe)): fi: lu,simplify(expand(mono2),symbolic): end: #SimplifyUmbra(Umb): Given an Umbra, collects like terms #and returns a simplified version SimplifyUmbra:=proc(Umb) local Umb1,gu,kv,i,mu,evar,F,pu: if Umb=0 then ERROR(FAIL): fi: Umb1:=ConvertToUmbra2(Umb): gu:=0: kv:={}: for i from 1 to nops(Umb1) do gu:=gu+Umb1[i][1]*F(Umb1[i][2]): kv:=kv union {Umb1[i][2]}: od: gu:=expand(gu): mu:={}: for i from 1 to nops(kv) do evar:=op(i,kv): pu:=normal(coeff(gu,F(evar))): if pu<>0 then mu:=mu union {[factor(pu),evar[1],evar[2]]}: fi: od: mu: end: #ConvertToUmbra2(Umb): Given an umbra Umb in the 3-list-format #i.e. as a set of 3-lists of the form #[FRONT,Orders_Of_Derivaties,Substitutions] #converts this to a set of 2-lists of the form #[FRONT,[Orders_Of_Derivaties,Substitutions]] ConvertToUmbra2:=proc(Umb) local Umb1,i,mu: Umb1:={}: for i from 1 to nops(Umb) do mu:=op(i,Umb): Umb1:=Umb1 union {[mu[1],[mu[2],mu[3]]]}: od: Umb1: end: # ApplyUmbralMatrix(UmbraM,Fvec,ylistvec): Given an Umbral matrix # UmbraM (in terms of a list of lists), a vector of expressions, # Fvec, and a vector to variable-lists corresponding to the # components of UmbraM and Fvec # ApplyUmbralMatrix:=proc(UmbraM,Fvec,ylistvec) local gu,mu,i,j,k: k:=nops(UmbraM): if k<>nops(Fvec) or k<>nops(ylistvec) then ERROR(`Bad input`): fi: gu:=[]: for i from 1 to k do mu:=0: for j from 1 to k do mu:=normal(mu+ApplyUmbra(UmbraM[i][j],Fvec[j],ylistvec[j])): od: gu:=[op(gu),mu]: od: gu: end: # ApplyUmbra(Umbra1,f,ylist): given an umbra, Umbra1, applies # it to the expression f in the variables in ylist ApplyUmbra:=proc(Umbra1,f,ylist) local i,gu: gu:=0: for i from 1 to nops(Umbra1) do gu:=normal(gu+ApplyUmbraTerm(Umbra1[i],f,ylist)): od: gu: end: # ApplyUmbraTerm(Umbra1,f,ylist): given an umbral term, Umbra1, applies # it to the expression f in the variables in ylist ApplyUmbraTerm:=proc(Umbra1,f,ylist) local i, FRONT,Diffs,SubsList,gu,bu: FRONT:=Umbra1[1]: Diffs:=Umbra1[2]: SubsList:=Umbra1[3]: if nops(Diffs)<>nops(ylist) then ERROR(`Diffs and ylist should have the same length`): fi: if nops(SubsList)<>nops(ylist) then ERROR(`SubsList and ylist should have the same length`): fi: gu:=f: for i from 1 to nops(ylist) do gu:=normal(xdiff1(gu,ylist[i],Diffs[i])): od: bu:={}: for i from 1 to nops(ylist) do bu:=bu union {ylist[i]=SubsList[i]}: od: gu:=subs(bu,gu): normal(FRONT*gu): end: # xdiff1(f,x,i): given an expression f, and a variable x, # and an integer i, finds (xD_x)^i f # xdiff1:=proc(f,x,i) local gu,j: if i=0 then RETURN(f): fi: gu:=f: for j from 1 to i do gu:=x*diff(gu,x): od: gu: end: #SerToPol(sidra,q,n): given a series, sidra, finds the polynomial #consisting of the terms up to degree n SerToPol:=proc(sidra,q,n) local lu,i,gu: lu:=taylor(sidra,q=0,n+1): gu:=0: for i from 0 to n do gu:=gu+coeff(lu,q,i)*q^i: od: gu: end: # ApplyUmSc(UmSch,q,n,var): Given an Umbral Scheme, UmSch, finds # the generating functions of creatures up to the wt. q^n #followed by substition of all x and y variables to 1 and summing #over leftmost letters ApplyUmSc:=proc(UmSch,q,n,var) local UM,INI,ylistvec,lu,gu,i,lu1,i1,kv,ku,fu,Sid,j,mu,gc: if not type(n,integer) or not n>0 then ERROR(`n>0`): fi: kv:=UmSch[1]: UM:=UmSch[2]: INI:=UmSch[3]: ylistvec:=UmSch[4]: lu:=[]: for i from 1 to nops(INI) do lu:=[op(lu),SerToPol(INI[i],q,0)]: od: if n=0 then RETURN(lu): fi: Sid:=[]: for i from 1 to n do lu1:=ApplyUmbralMatrix(UM,lu,ylistvec): gu:=[]: for i1 from 1 to nops(lu1) do gu:=[op(gu),expand(SerToPol(INI[i1],q,i)+SerToPol(normal(lu1[i1]),q,i))]: od: lu:=gu: fu:=[]: for i1 from 1 to nops(lu) do fu:=[op(fu),coeff(expand(lu[i1]),q,i)]: od: mu:=0: for j from 1 to nops(kv) do mu:=mu+kv[j]*fu[j]: od: ku:={seq(var[gc]=1,gc=1..nops(var))}: mu:=subs(ku,normal(mu)): Sid:=[op(Sid),normal(mu)]: lprint(Sid): od: lu,Sid: end: # ApplyUmSc1(UmSch,q,n,var): Same as #ApplyUmSc(UmSch,q,n,var), but no partial results #displayed ApplyUmSc1:=proc(UmSch,q,n,var) local UM,INI,ylistvec,lu,gu,i,lu1,i1,kv,ku,fu,Sid,j,mu,gc: if not type(n,integer) or not n>0 then ERROR(`n>0`): fi: kv:=UmSch[1]: UM:=UmSch[2]: INI:=UmSch[3]: ylistvec:=UmSch[4]: lu:=[]: for i from 1 to nops(INI) do lu:=[op(lu),SerToPol(INI[i],q,0)]: od: if n=0 then RETURN(lu): fi: Sid:=[]: for i from 1 to n do lu1:=ApplyUmbralMatrix(UM,lu,ylistvec): gu:=[]: for i1 from 1 to nops(lu1) do gu:=[op(gu),expand(SerToPol(INI[i1],q,i)+SerToPol(normal(lu1[i1]),q,i))]: od: lu:=gu: fu:=[]: for i1 from 1 to nops(lu) do fu:=[op(fu),coeff(expand(lu[i1]),q,i)]: od: mu:=0: for j from 1 to nops(kv) do mu:=mu+kv[j]*fu[j]: od: ku:={seq(var[gc]=1,gc=1..nops(var))}: mu:=subs(ku,normal(mu)): Sid:=[op(Sid),normal(mu)]: od: lu,Sid: end: #YafeUm(Umb1,F): Given an umbral operator, Umb1, in #Maple notation, converts it to human notation #using the symbol F for the function and D for differntiation YafeUm:=proc(Umb1,F,D) local T,gu,i,mu,lu,gu1,lu1: gu:={}: for i from 1 to nops(Umb1) do mu:=op(i,Umb1): gu:=gu union {[mu[2],mu[3]]}: od: for i from 1 to nops(gu) do T[gu[i]]:=0: od: for i from 1 to nops(Umb1) do mu:=op(i,Umb1): T[[mu[2],mu[3]]]:=normal(T[ [mu[2],mu[3]] ]+mu[1]): od: lu:=0: for i from 1 to nops(gu) do gu1:=gu[i]: lu1:=F(op(gu1[2])): if convert(gu1[1],`+`)<>0 then lu1:=lu1*D[op(gu1[1])]: fi: lu1:=lu1*factor(T[gu1]): lu:=lu+lu1: od: lu: end: #YafeUmSc(UmbSc,F,D): Given an umbral #Scheme UmbSc, in #Maple notation, converts it to human notation #using the symbols F[1], F[2] for the functions and D for differntiation #of respective variables YafeUmSc:=proc(UmbSc,F,D) local gu1,gu2,gu3,gu4,eq,eq1,n,i,j: gu1:=UmbSc[1]: gu2:=UmbSc[2]: gu3:=UmbSc[3]: gu4:=UmbSc[4]: eq:=[]: n:=nops(gu2): for i from 1 to n do eq1:=gu3[i]: for j from 1 to n do eq1:=eq1+YafeUm(gu2[i][j],F[j],D): od: eq:=[op(eq),F[i](op(gu4[i]))=eq1]: od: eq,gu1: end: #############End Programs Taken from ROTA############### #####PROGRAMS TAKEN FROM LinDiophantus #GFxt(a,E1,x,t): Given a list of symbols, a #denoting generic (symbolic) non-negative integers #and a list, E1, of affine linear expressions with integer #coeffs. in them , and symbols x and t, #finds the generating function: #sum of x[1]^a[1]*...*x[n]^a[n]*t[1]^E1[1]*...*t[r]^E1[r] #(where n=nops(a) and r=nops(E1)), and the sum is over 0<=a[1]0 and ldegree(f1,t)>=0 then 1: elif degree(f1,t) <0 then -1: else 0: fi: end: #WhoAreYouxt(f,x,t): Given a polynomial f, in the variables #x and t, looks at the `normalized' polynomial (in x) #obtained by dividing by the coeff. of x^0 #and seeing whether all the coeffs. of the powers of x #(that are Laurent polynomials in t) have consistently #coeffs that are polynomials in t, or consistently coeffs. #that are polynomials in 1/t, or none of the above #and returns 1, -1, 0 respectively WhoAreYouxt:=proc(f,x,t) local f1,lu,i1,i: f1:=expand(f): if degree(f1,t)=0 then RETURN(1): fi: if degree(f1,t)<>0 and normal(f1-subs(t=1,f1)*t^degree(f1,t))=0 then RETURN(-1): fi: if coeff(f1,x,0)<>0 then f1:=expand(f1/coeff(f1,x,0)): else f1:=f: fi: for i1 from 1 while expand(coeff(f1,x,i1))=0 do od: lu:=WhoAreYout(coeff(f1,x,i1),t): for i from i1 to degree(f1,x) do if WhoAreYout(coeff(f1,x,i),t)<>lu then RETURN(0): fi: od: lu: end: #isbad2(evar,xSet): given an expression in the variables #in the set xSet, decides whether evar has positive degree #in any of the variables of xSet isbad2:=proc(evar,xSet) local i: for i from 1 to nops(xSet) do if degree(evar,xSet[i])>0 then RETURN(true): fi: od: false: end: #CT1old(f,xSet,t): Given a rational #function f of t and a set, xSet, of x-variables #finds the constant term in t (i.e. the coeff. of t^0) #of the Laurent expansion of t, viewed as a formal Laurent #series in the x's of xSet #For example try CT1old(1/(1-x*t)/(y-t),[x,y],t); CT1old:=proc(f,xSet,t) local f1,i,lu,g,mu,BAD1: mu:=denom(normal(f)): mu:={solve(mu,t)}: BAD1:={}: for i from 1 to nops(mu) do if isbad2(mu[i],xSet) or mu[i]=0 then BAD1:=BAD1 union {mu[i]}: fi: od: f1:=convert(f,parfrac,t): g:=f1: for i from 1 to nops(f1) do lu:=op(i,f1): mu:=denom(lu): if isbad3(mu,BAD1,t) then g:=g-lu: fi: od: factor(normal(subs(t=0,g))): end: #isbad3(evar,kv,t): if any of the substitutions of t=kv[i] #into evar result in 0 isbad3:=proc(evar,kv,t) local i: for i from 1 to nops(kv) do if expand(subs(t=kv[i],evar))=0 then RETURN(true): fi: od: false: end: isbad:=proc(evar,t,xSet) local i,j,coe: for i from 0 to degree(evar,t)-1 do coe:=coeff(evar,t,i): for j from 1 to nops(xSet) do if degree(coe,xSet[j])>0 then RETURN(true): fi: od: od: false: end: #isbada(evar,BAD1,t): Given a denominator term (coming #from a single term of a prtial-fraction decomposition w.r.t t) #decides whether it is of the form BAD1[i]^(some power) for #some bad term of BAD1 isbada:=proc(evar,BAD1,t) local j,gu,d1: if normal(diff(evar,t))=0 then RETURN(false): fi: for j from 1 to nops(BAD1) do gu:=BAD1[j]: d1:=degree(evar,t)/degree(gu,t): if type(d1,integer) then gu:=normal(evar/gu^d1): if normal(diff(gu,t))=0 then RETURN(true): fi: fi: od: false: end: #CT1(f,xSet,t): Given a rational #function f of t and a set, xSet, of x-variables #finds the constant term in t (i.e. the coeff. of t^0) #of the Laurent expansion of t, viewed as a formal Laurent #series in the x's of xSet #For example try CT1(1/(1-x*t)/(y-t),[x,y],t); CT1:=proc(f,xSet,t) local f1,i,lu,g,mu,BAD1,mu1,mu11,mu11a: mu:=denom(normal(f)): BAD1:={}: if type(mu,`*`) then for i from 1 to nops(mu) do mu1:=op(i,mu): if type(mu1, `^`) then mu11:=op(1,mu1): else mu11:=mu1: fi: mu11a:=expand(mu11/coeff(mu11,t,degree(mu11,t))): if mu11a=t or isbad(mu11a,t,xSet) then BAD1:=BAD1 union {mu11}: fi: od: else mu1:=mu: if type(mu1, `^`) then mu11:=op(1,mu1): else mu11:=mu1: fi: mu11a:=expand(mu11/coeff(mu11,t,degree(mu11,t))): if mu11a=t or isbad(mu11a,t,xSet) then BAD1:=BAD1 union {mu11}: fi: fi: f1:=convert(f,parfrac,t): g:=f1: for i from 1 to nops(f1) do lu:=op(i,f1): mu:=denom(lu): if isbada(mu,BAD1,t) then g:=g-lu: fi: od: factor(normal(subs(t=0,g))): end: #GFx(a,Elist,x): Given a list of variables, a, #of type non-negative integer, and a list #of linear-diophantine equations in these variables #and a continuous indexed-variable x, outputs the #generating function of all solutions #where x[1]^a[1]*x[2]^a[2]*... shows up iff (a[1],a[2], ...) #is a solution GFx:=proc(a,Eqs,x) local f,i,t,xSet,g,fbot: f:=GFxt(a,Eqs,x,t): xSet:=[seq(x[i],i=1..nops(a))]: for i from 1 to nops(Eqs) do f:=CT1(f,xSet,t[i]): od: fbot:=denom(f): for i from 1 to nops(xSet) do fbot:=subs(xSet[i]=0,fbot): od: if fbot=0 then RETURN(0): fi: g:=f: for i from 1 to nops(a) do g:=subs(x[i]=x[a[i]],g): od: g: end: #numfacs1(mekh,x): given a product, mekh, of terms #counts how many of them depend on x numfacs1:=proc(mekh,x) local co,i: co:=0: for i from 1 to nops(mekh) do if degree(op(i,mekh),x)>0 then co:=co+1: fi: od: co: end: #ToUm1(R,x): Given a rational function R and a variable x #tries to finds an umbra that sends f(x) to Constant #term of R(x)f(1/x), it only treats the case where #the denominator of R(x) factors completely over the #rationals and there are no multiplicity and #the degree of the numerator is less than the degree of #of the denominator #if this is not the case, it returns 0 ToUm1:=proc(R,x) local mekh,gu,i,mu,p: mekh:=factor(denom(R)): if degree(numer(R),x)>=degree(denom(R),x) then RETURN(0): fi: if type(mekh, `*`) and numfacs1(mekh,x)<>degree(mekh,x) then RETURN(0): fi: gu:={solve(mekh,x)}: mu:={}: readlib(residue): for i from 1 to nops(gu) do p:=normal(-residue(R,x=gu[i])/gu[i]): mu:=mu union {[p,[0],[1/gu[i]]]}: od: mu: end: ToUm:=proc(R,xList) local gu,mu,i,xList1,mui,mui1,mui2,mui3,x,lu,j: if R=0 then RETURN({}): fi: if nops(xList)=0 then RETURN( {[R,[],[]]} ): fi: if nops(xList)=1 then RETURN(ToUm1(R,xList[1])): fi: x:=xList[nops(xList)]: xList1:=[op(1..nops(xList)-1,xList)]: mu:=ToUm(R,xList1): gu:={}: for i from 1 to nops(mu) do mui:=mu[i]: mui1:=mui[1]: mui2:=mui[2]: mui3:=mui[3]: for j from 1 to nops(mui3) do if diff(mui3[j],x)<>0 then RETURN(0): fi: od: lu:=ToUm1(mui1,x): if lu=0 then RETURN(0): fi: for j from 1 to nops(lu) do gu:=gu union {[lu[j][1],[op(mui2),0],[op(mui3),op(lu[j][3])]]} : od: od: gu: end: #######End programs taken from LinDiophantus #CoreW(SymbWord): Given a symbolic word, SymbWord #in terms of a list of pairs, [[l1,nu1],[l2,nu2], ...] extrats #the first component, in other words, it contracts all repetitions CoreW:=proc(SymbWord) local i: [seq(SymbWord[i][1],i=1..nops(SymbWord))]:end: #CompatibleInterfaces1(u,v): given two (ordinary) words #finds all the places in u such that the suffix of u starting #at the i^th letter of u equals a prefix of v CompatibleInterfaces1:=proc(u,v) local gu,i,u1,v1: gu:={}: for i from 1 to nops(u) do u1:=[op(i..nops(u),u)]: if nops(v)>=nops(u1) then v1:=[op(1..nops(u1),v)]: if u1=v1 then gu:=gu union {i}: fi: fi: od: gu: end: #CompatibleInterfaces(u,v,d): given two (ordinary) words #finds all the places in u such that the suffix of u starting #at the i^th letter of u equals a prefix of some image of v #under the permutation of d letters #it returns the set of pairs [place, image of v] CompatibleInterfaces:=proc(u,v,d) local gu,i,mu,lu,j,T,gu1: gu:={}: mu:=khaverim(u,d): for i from 1 to nops(mu) do gu:=[op(gu),op(CompatibleInterfaces1(mu[i],v))]: od: gu: gu1:=convert(gu,set): for i from 1 to nops(gu1) do T[gu1[i]]:=0: od: for i from 1 to nops(gu) do T[gu[i]]:=T[gu[i]]+1: od: {seq([gu1[i],T[gu1[i]]],i=1..nops(gu1))}; end: #FindUmbInt(U,V,i,x,t): Given two symbolic letters U, V #expressed in symbolic frequency notation #{[[let1,AffLinExp1],[let2,AffLinExp2], ...], {set_of_symbols}} #and a location i, one of the legal interfaces of #U before V in a symbolic cluster, and a sumbol x, #for the catalytic variabes and a symbol t, find the umbra that #sends x_1^a_1*x_2^a_2 ... to the generating function of all possible #such V's #For example try: FindUmbInt([[[1,1],[2,a],[3,a],[1,1]],[a]], #[[[1,1],[2,a],[3,a],[1,1]],[a]],4,x,t): FindUmbInt:=proc(U,V,i,x,t) local k1,k2,a,b,j,U1,V1,var,eq,lu,mu,m1,zanav,gu,mu1,c,j1,gu1: eq:=[]: var:=[]: U1:=U: for j from 1 to nops(U[2]) do U1:=subs(U[2][j]=a[j],U1): od: V1:=V: for j from 1 to nops(V[2]) do V1:=subs(V[2][j]=b[j],V1): od: var:=[op(var),op(U1[2]),op(V1[2]),k1,k2]: if i=nops(U1[1]) then var:=[op(var),m1]: if nops(V1[1])=1 then eq:=[op(eq),U1[1][i][2]-k1-m1-1, V1[1][1][2]-k2-m1-2]: else eq:=[op(eq),U1[1][i][2]-k1-m1-1 , V1[1][1][2]-k2-m1-1]: fi: else if i=1 then eq:=[op(eq),U1[1][i][2]-(V1[1][1][2]+k1+1)]: else eq:=[op(eq),U1[1][i][2]-(V1[1][1][2]+k1)]: fi: for j from i+1 to nops(U1[1])-1 do eq:=[op(eq), U1[1][j][2]-V1[1][j-i+1][2]]: od: j:=nops(U1[1]): if j-i+1=nops(V1[1]) then eq:=[op(eq), U1[1][j][2]+k2+1-V1[1][j-i+1][2]]: else eq:=[op(eq), U1[1][j][2]+k2-V1[1][j-i+1][2]]: fi: fi: zanav:=0: j:=nops(U1[1]): for j1 from j-i+2 to nops(V1[1]) do zanav:=zanav+V1[1][j1][2]: od: if j-i+1=nops(V1[1]) then zanav:=zanav+1: fi: lu:=GFx(var,convert(eq,set),x): mu:=[seq(x[op(j,U1[2])],j=1..nops(U1[2]))]: gu:=ToUm(lu,mu): gu:=SimplifyUmbra(gu): if gu=0 then RETURN({}): fi: gu:=subs({x[k1]=1,x[m1]=1,x[k2]=t},gu): mu1:=[seq(x[op(j,V1[2])],j=1..nops(V1[2]))]: for j1 from 1 to nops(V1[2]) do c:=coeff(zanav,op(j1,V1[2]),1): zanav:=expand(zanav-c*op(j1,V1[2])): gu:=subs(x[op(j1,V1[2])]=t^c*x[op(j1,V1[2])],gu): od: if not type(zanav,integer) then ERROR(`Something is wrong`): fi: gu:={seq([-t^zanav*gu[j1][1],gu[j1][2],gu[j1][3]],j1=1..nops(gu))}: gu1:=gu: for j1 from 1 to nops(mu1) do gu1:=subs(mu1[j1]=x[j1],gu1): od: SimplifyUmbra(gu1): end: #FindUmb(U,V,x,t,d): Given two symbolic words, U, and V, #and a variable x (x an index variable, for catalytic #variables), and a variable t, to keep track of length #computes the umbral edge connecting U and V #including interfaces with the images of V #d is the total number of letters FindUmb:=proc(U,V,x,t,d) local gu,lu,i,lu1,j: lu:=CompatibleInterfaces(CoreW(U[1]),CoreW(V[1]),d): gu:={}: for i from 1 to nops(lu) do lu1:=FindUmbInt(U,V,lu[i][1],x,t): if lu1=0 then print(`Can't find an umbra`): RETURN(FAIL): fi: lu1:={seq([lu1[j][1]*lu[i][2],lu1[j][2],lu1[j][3]],j=1..nops(lu1))}: gu:=gu union lu1: od: SimplifyUmbra(gu): end: #IniWord(SymWord,x,t): Given a symbolic word, SymWord, #and two variable symbols x (for the catalytic variables, #x[1],x[2], ...) and t (to keep track of the length) #finds the generating function for clusters consisting #just of SymWord IniWord:=proc(SymWord,x,t) local lu1,lu2,i,gu,mu,c: lu1:=SymWord[1]: lu2:=SymWord[2]: gu:=0: for i from 1 to nops(lu1) do gu:=gu+lu1[i][2]: od: gu:=expand(gu): mu:=1: for i from 1 to nops(lu2) do mu:=mu/(1-x[i]): od: for i from 1 to nops(lu2) do c:=coeff(gu,lu2[i],1): gu:=gu-c*lu2[i]: mu:=subs(x[i]=t^c*x[i],mu): od: if not ( type(gu,integer) and gu>=0 ) then ERROR(`Something is wrong`): fi: -t^gu*mu: end: #WtUmSc(ListSW,x,t,d): Given a list of symbolic words #ListSW, constructs a Weighted Umbral Scheme for the Cluster #generating function where the mistakes are #the members of ListSW and all their images under #the group of Signed Permutations on {-1,1,-2,2, ..., -d,d} #Recall that a Weighted Umbral Scheme is like an Umbral #Scheme, but the first component is a list of #weights rather then a set of WtUmSc:=proc(SetSW,x,t,d) local U,V,j,gu1,gu2,gu3,gu4,i,gu2a: option remember: gu1:=[seq(nops(khaverim(CoreW(SetSW[i][1]),d)) ,i=1..nops(SetSW))]: gu2:=[]: for i from 1 to nops(SetSW) do U:=SetSW[i]: gu2a:=[]: for j from 1 to nops(SetSW) do V:=SetSW[j]: gu2a:=[op(gu2a),FindUmb(U,V,x,t,d)]: od: gu2:=[op(gu2),gu2a]: od: gu3:=[]: gu4:=[]: for i from 1 to nops(SetSW) do U:=SetSW[i]: gu3:=[op(gu3),IniWord(U,x,t)]: gu4:=[op(gu4),[seq(x[j],j=1..nops(U[2]))]]: od: gu2:=[seq([seq(gu2[j][i],j=1..nops(gu2[i]))],i=1..nops(gu2))]: [gu1,gu2,gu3,gu4]: end: #UGJseries(SetSW,NumLetters,L): Given a set of symbolic #letters, SetSW, #in the alphabet -1,1,-2,2,...,-NumLetters,NumLetters #an integer, and an integer L, uses the Umbral Scheme #to find the first L terms of the series expansion #of words that avoid the mistakes of SetSW #and all their images under the symmetric group UGJseries:=proc(SetSW,NumLetters,L) local gu,lu,x,t,Sid,i,mu: gu:=WtUmSc(SetSW,x,t,NumLetters): lu:={}: for i from 1 to nops(gu[4]) do lu:=lu union {op(gu[4][i])}: od: Sid:=ApplyUmSc1(gu,t,L,lu)[2]: lu:=0: for i from 1 to nops(Sid) do lu:=lu+Sid[i]*t^i: od: lu:=1/(1-2*NumLetters*t-lu): lu:=taylor(lu,t=0,L+1): mu:=[]: for i from 0 to L do mu:=[op(mu),coeff(lu,t,i)]: od: mu: end: #Tony(SetSW,DIM,n): #Geared for Umbral Schemes that came from Clusters Tony:=proc(SetSW,DIM,n) local UmSch, UM,INI,ylistvec,lu,gu,i,lu1,i1,kv,ku,fu,Sid,j,mu,gc,t,x,var,kak: if not type(n,integer) or not n>0 then ERROR(`n>0`): fi: UmSch:=WtUmSc(SetSW,x,t,DIM): var:={seq(op(UmSch[4][i1]),i1=1..nops(UmSch[4]))}: kv:=UmSch[1]: UM:=UmSch[2]: INI:=UmSch[3]: ylistvec:=UmSch[4]: lu:=[]: for i from 1 to nops(INI) do lu:=[op(lu),SerToPol(INI[i],t,0)]: od: if n=0 then RETURN(lu): fi: Sid:=[]: for i from 1 to n do lu1:=ApplyUmbralMatrix(UM,lu,ylistvec): gu:=[]: for i1 from 1 to nops(lu1) do gu:=[op(gu),expand(SerToPol(INI[i1],t,i)+SerToPol(normal(lu1[i1]),t,i))]: od: lu:=gu: fu:=[]: for i1 from 1 to nops(lu) do fu:=[op(fu),coeff(expand(lu[i1]),t,i)]: od: mu:=0: for j from 1 to nops(kv) do mu:=mu+kv[j]*fu[j]: od: ku:={seq(var[gc]=1,gc=1..nops(var))}: mu:=subs(ku,normal(mu)): Sid:=[op(Sid),normal(mu)]: kak:=0: for i1 from 1 to nops(Sid) do kak:=kak+Sid[i1]*t^i1: od: kak:=1/(1-2*DIM*t-kak): kak:=taylor(kak,t=0,i+1): mu:=[]: for i1 from 0 to i do mu:=[op(mu),coeff(kak,t,i1)]: od: print(mu): od: mu: end: #######Stuff for checking using the finite Goulden-Jackson ##(transported from SPGJ) with(combinat): #CheckU(SymbMisSet,NuLett,L): Uses the Classical Goulden- #Jackson with Symmetry under the group of signed permutations #to find the first L terms of the set of words in #the alphabet with 2*NuLet letters #-1,1,-2,2,-3,3, ..., -NuLett, NuLett that avoid factors from SymbMisSet #where each symbolic mistake has the form [[letter1,expression1], ...] #and expression1... are affine linear expressions in the variables #of DisVars CheckU:=proc(SymbMisSet,NuLet,L) local MISTAKES1,i: MISTAKES1:={}: for i from 1 to nops(SymbMisSet) do MISTAKES1:=MISTAKES1 union MistSetL(SymbMisSet[i][1],SymbMisSet[i][2],L): od: SPGJseries(NuLet,MISTAKES1,L): end: #SpellOut(SymbMisSet,NuLett,L): #Finds the concrete mistakes up to #length L in #the alphabet with 2*NuLet letters #-1,1,-2,2,-3,3, ..., -NuLett, NuLett that #are implied by the set of symbolic mistakess SymbMisSet #where each symbolic mistake has the form [[letter1,expression1], ...] #and expression1... are affine linear expressions in the variables #of DisVars SpellOut:=proc(SymbMisSet,NuLet,L) local MISTAKES1,i: MISTAKES1:={}: for i from 1 to nops(SymbMisSet) do MISTAKES1:=MISTAKES1 union MistSetL(SymbMisSet[i][1],SymbMisSet[i][2],L): od: MISTAKES1: end: #MistSetL(SymbMis,DisVars,L): Given a symbolic Mistake #using the discrete variables of DisVars (denoting generic #positive integers), finds all its manifestations #of length up to L MistSetL:=proc(SymbMis,DisVars,L) local LinExp,i,mu,gu: LinExp:=0: for i from 1 to nops(SymbMis) do LinExp:= LinExp+SymbMis[i][2]: od: mu:=FeasVects(LinExp,DisVars,L): gu:={}: for i from 1 to nops(mu) do gu:=gu union {PlugSymbMis(SymbMis,DisVars,mu[i])}: od: gu: end: #FeasVects(LinExp,DisVars,L): Given a linear expression #in the list of discrete variables (denoting generic #non-negative integers), finds all solutions #for which LinExp at DisVars is <=L FeasVects:=proc(LinExp,DisVars,L) local gu,a,i,mu,L1,DisVars1,gu1,LinExp1,j: gu:={}: if nops(DisVars)=0 then RETURN({[]}): fi: if nops(DisVars)=1 then a:=DisVars[1]: if coeff(LinExp,a,1)=0 then ERROR(`LinExp does not involve `,a): fi: for i from 0 while subs(a=i,LinExp)<=L do gu:=gu union {[i]}: od: RETURN(gu): fi: a:=DisVars[nops(DisVars)]: mu:=coeff(LinExp,a,1)*a: gu:={}: for i from 0 while subs(a=i,mu)<=L do L1:=L-subs(a=i,mu): DisVars1:=[op(1..nops(DisVars)-1,DisVars)]: LinExp1:=LinExp-mu: gu1:=FeasVects(LinExp1,DisVars1,L1): for j from 1 to nops(gu1) do gu:=gu union {[op(gu1[j]),i]}: od: od: gu: end: #PlugSymbMis(SymbMis,DisVars,PlugList): plugs the values #in PlugList for the variables of DisVars, respectivelty #into the symbolic mistake SymbMis PlugSymbMis:=proc(SymbMis,DisVars,PlugList) local gu,i,j,r,lu: gu:=[]: for i from 1 to nops(SymbMis) do lu:=SymbMis[i][2]: for j from 1 to nops(DisVars) do lu:=subs(DisVars[j]=PlugList[j],lu): od: gu:=[op(gu),seq(SymbMis[i][1],r=1..lu)]: od: gu: end: SPGJseries:=proc(NUMLETTERS,MISTAKES1,L) local v,eq, var,i,lu,mu,pols,ku,MISTAKES,MISTAKESFULL,s,C: eq:=[]: var:=[]: pols:=[]: MISTAKES:={}: for i from 1 to nops(MISTAKES1) do MISTAKES:=MISTAKES union {canon(op(i,MISTAKES1))}: od: MISTAKESFULL:={}: for i from 1 to nops(MISTAKES) do MISTAKESFULL:=MISTAKESFULL union khaverim(op(i,MISTAKES),NUMLETTERS): od: for i from 1 to nops(MISTAKES) do v:=op(i,MISTAKES): mu:=findeqz_fast(v,MISTAKESFULL,C,s): eq:= [op(eq),mu[2]]: pols:= [op(pols),mu[1]]: var:=[op(var),C[op(v)]]: od: lu:=SPsolser(var,pols,eq,NUMLETTERS,L+2,s): ku:=1-2*NUMLETTERS*s: for i from 1 to L+2 do ku:=ku-op(i,lu)*s^i: od: ku:=taylor(1/ku,s=0,L+1): lu:=[]: for i from 0 to L do lu:=[op(lu),coeff(ku,s,i)]: od: lu: end: #khaverim(mila,n):Given a word mila finds the set of all its #images under the action of the group of signed permutations khaverim:=proc(mila1,n) local i,gu,r,lu,mila,mila2,gu1,j: mila:=canon(mila1): mila2:=[]: for i from 1 to nops(mila) do mila2:=[op(mila2),abs(op(i,mila))]: od: r:=nops(convert(mila2,set)): if nnops({op(1..i-1,mila1)}) then gu:=[op(gu),op(i,mila)]: fi: od: for i from 1 to nops(gu) do mu[op(i,gu)]:=i: mu[-op(i,gu)]:=-i: od: lu:=[]: for i from 1 to nops(mila) do lu:=[op(lu),mu[op(i,mila)]]: od: lu: end: simanim:=proc(r) local i,mu,gu,evar: if r=0 then RETURN([[]]): fi: gu:=[]: mu:=simanim(r-1): for i from 1 to nops(mu) do evar:=op(i,mu): gu:=[op(gu),[op(evar),1],[op(evar),-1]]: od: gu: end: #peula(mila,perm): Given a word in the alphabet {1,2,..,r} applies #to it the (partial) permutation perm i.e. i is replaced by perm[i] peula:=proc(mila,perm,siman) local gu,i: gu:=[]: if nops(perm)<>nops(siman) then ERROR(`Too bad`): fi: for i from 1 to nops(mila) do gu:=[op(gu), sign(op(i,mila))* op(abs(op(i,mila)),siman)*op(abs(op(i,mila)),perm)]: od: gu: end: #findeqz_fast sets up the equ C[v]= s+t*Sum_u overlap(u,v) *C[u] #just like findeqz but returns separately the polynomial part #and the equation part findeqz_fast:=proc(v,MISTAKES,C,s) local eq,PO,i,u: PO:=(-1)*s^nops(v): eq:=0: for i from 1 to nops(MISTAKES) do u:=op(i,MISTAKES): eq:=eq-overlapz(u,v,s)*C[op(canon(u))]: od: PO,eq: end: #overlapz is a procedure that given two words u and v #computes the weight-enumerator of all v\suffix(u), #for all suffixes of u that are prefixes of v, but with uniform weight s overlapz:=proc(u,v,s) local i,j,k,lu,gug: lu:=0: for i from 2 to nops(u) do for j from i to nops(u) while (j-i+1<=nops(v) and op(j,u)=op(j-i+1,v)) do : od: if j-i=nops(v) and u<>v then ERROR(v,`is a subword of`,u,`illegal input`): fi: if j=nops(u)+1 and (i>1 or j>2) then gug:=1: for k from j-i+1 to nops(v) do gug:=gug*s: od: lu:=lu+gug: fi: od: lu: end: SPsolser:=proc(vars,pols,equs,NUM,L,s) local Mem,i,aj,maxi,X,r,lu,gu, j, lu1, n, pij, v: #Mem is a list of the memories that each a[j] needs Mem:=[]: for j from 1 to nops(vars) do aj:=op(j,vars): maxi:=0: for i from 1 to nops(equs) do if degree(coeff(op(i,equs),aj,1),s)>maxi then maxi:=degree(coeff(op(i,equs),aj,1),s): fi: od: Mem:=[op(Mem),maxi]: od: for i from 1 to nops(vars) do X[i]:=[seq(0,j=1..op(i,Mem))]: od: lu:=[]: for n from 1 to L do for i from 1 to nops(equs) do gu[i]:=coeff(op(i,pols),s,n): for j from 1 to nops(vars) do aj:=op(j,vars): pij:=coeff(op(i,equs),aj,1): for r from 1 to degree(pij,s) do gu[i]:=gu[i]+coeff(pij,s,r)*op(nops(X[j])-r+1,X[j]): od: od: od: lu1:=0: for i from 1 to nops(vars) do v:=[op(op(i,vars))]: lu1:=lu1+ nops(khaverim(v,NUM))*gu[i]: od: lu:=[op(lu),lu1]: for i from 1 to nops(vars) do X[i]:=[op(2..nops(X[i]),X[i]),gu[i]]: od: od: lu: end: #####End part for checking that was transported from SPGJ #### ENTER Noonan's mist ###########This part was transported from GJSaw ##Written by John Noonan #mist(memo,dim): all minimimally bad walks up to memory #memo and dimension dim (written by John Noonan) #heres the main program.mist generates all canonical mistakes up to #memory=mem in dimension=dim mist:=proc(memo,dim) local mem,i,L,x: if not type(memo/2,integer) or memo=0 then ERROR(`The first argument, memo, must be a positive even integer`): fi: mem:=memo/2: L:=badlist1(mem,x,dim): for i from 1 to dim do L:=subs(x[i]=i,L): od: convert(L,set): end: badlist1:=proc(N,x,d) local ww,i,j,k,l,n,SUB,L,L1,L2,L3,LL,w,m,chk,dummy,chk2,slow: # we make a list of all sins (up to symmetry) for a self avoiding walk with # memory=2N. x is a variable you choose so that x[1] is the first # direction, # x[2] is the second direction etc. Output is a list of sins. the sin # [x[1],-x[1]] corresponds to taking one step in any direction and then # taking one step back. if N=1 then RETURN([[x[1],-x[1]]]): fi: n:=2*N: SUB:={x[1]=1}: for i from 2 to N do: SUB:={op(SUB),x[i]=1}: od: L:=badlist1(N-1,x,d): L1:=[[[x[1]],2]]: LL:=[]: for i from 3 to n do L2:=[]: for j from 1 to nops(L1) do w:=op(j,L1): L3:=grow1(w,N,x,d): m:=nops(L3): for k from 1 to m do chk:=op(1,op(k,L3)): slow:=0: chk2:=convert(chk,`+`)+ww: for l from 1 to nops(chk2) do: if op(l,chk2)<>ww then slow:=slow+abs(subs(SUB,op(l,chk2))): fi: od: if slow=n-nops(chk) then LL:=[op(LL),op(pad(chk))]: else dummy:=0: for l from 1 to nops(chk)/2 do: if convert([op(nops(chk)-2*l+1..nops(chk),chk)],`+`)=0 then dummy:=1: break: fi: od: if dummy=0 then L2:=[op(L2),op(k,L3)]: fi: fi: od: od: L1:=L2: od: [op(L),op(LL)]: end: grow1:=proc(w,n,x,d) local walk,cur,pre,i,L,chunk: walk:=op(1,w): cur:=op(2,w): pre:=op(nops(walk),walk): L:=[]: if cur<=n and cur<=d then chunk:=[op(walk),x[cur]]: if checkperm(chunk)=1 then L:=[[chunk,cur+1]]: fi: fi: for i from 1 to cur-1 do if x[i]=pre or -x[i]=pre then chunk:=[op(walk),pre]: if checkperm(chunk)=1 then L:=[op(L),[chunk,cur]]: fi: else chunk:=[op(walk),x[i]]: if checkperm(chunk)=1 then L:=[op(L),[chunk,cur]]: fi: chunk:=[op(walk),-x[i]]: if checkperm(chunk)=1 then L:=[op(L),[chunk,cur]]: fi: fi: od: L: end: checkperm:=proc(tem) local k,nn,j: nn:=nops(tem): for j from 1 to nn do for k from j+2 to nn do if convert([op(j..k,tem)],`+`)=0 and k-j<>nn-1 and k-j>0 then RETURN(0): fi: od: od: 1: end: pad:=proc(walk) local i,s,S,T,T2,check,j,dummy,l,SUB, m, n, test, zz: SUB:={}: m:=nops(walk): for i from 1 to m do if nops(op(i,walk))=1 then SUB:={op(SUB),op(i,walk)=1}: fi: od: s:=convert(zz+convert(walk,`+`),set) minus {zz}; T:=[]: for i from 1 to nops(s) do check:=op(i,s): if nops(check)=1 then T:=[op(T),-check]: else if op(1,check)<0 then for j from 1 to -op(1,check) do T:=[op(T),op(2,check)]: od: else for j from 1 to op(1,check) do T:=[op(T),-op(2,check)]: od: fi: fi: od: T2:=permute(T): #print(T2,T): n:=m+nops(T): S:=[]: for i from 1 to nops(T2) do test:=[op(walk),op(op(i,T2))]: dummy:=0: for j from 0 to nops(T)-1 do for l from 1 to (n-j)/2 do: #print([op(n-j-2*l+1..n-j,test)]); if j<>0 or l<>n/2 then if convert([op(n-j-2*l+1..n-j,test)],`+`)=0 then dummy:=1: break: fi: fi: od: od: if dummy=0 then S:=[op(S),test]: fi: od: S: end: ##End part written by John Noonan ##### Begin Part Just for 2D Self-Avoiding Walks on the Square Lattice## #SawSM4(a,b,c): The symbolic mistakes Inspired by #mistakes up to memory 4 SawSM4:=proc(a,b,c): [ [[[1,1],[-1,1]],[]], [[[1,a+1],[2,b+1],[-1,a+1],[-2,b+1]],[a,b]], [[[1,a+1],[2,b+1],[-1,a+c+2],[-2,b+1],[1,c+1]],[a,b,c]] ]: end: #SawSM6a(a,b,c,d): The symbolic mistakes Inspired by #mistakes up to memory 4 plus some of memory 8 SawSM6a:=proc(a,b,c,d): [ [[[1,1],[-1,1]],[]], [[[1,a+1],[2,b+1],[-1,a+1],[-2,b+1]],[a,b]], [[[1,a+1],[2,b+1],[-1,a+c+2],[-2,b+1],[1,c+1]],[a,b,c]], [[[1,a+1],[2,b+1],[1,c+1],[2,d+1],[-1,a+c+2],[-2,b+d+2]],[a,b,c,d]], [[[2,b+1],[1,c+1],[2,d+1],[-1,a+c+2],[-2,b+d+2],[1,a+1]],[a,b,c,d]], [[[1,c+1],[2,d+1],[-1,a+c+2],[-2,b+d+2],[1,a+1],[2,b+1]],[a,b,c,d]], [[[2,d+1],[-1,a+c+2],[-2,b+d+2],[1,a+1],[2,b+1],[1,c+1]],[a,b,c,d]], [[[-1,a+c+2],[-2,b+d+2],[1,a+1],[2,b+1],[1,c+1],[2,d+1]],[a,b,c,d]], [[[-1,a+1],[-2,b+d+2],[1,a+1],[2,b+1],[1,c+1],[2,d+1],[-1,c+1]],[a,b,c,d]], [[[-2,b+d+2],[1,a+1],[2,b+1],[1,c+1],[2,d+1],[-1,a+c+2]],[a,b,c,d]], [[[-2,b+1],[1,a+1],[2,b+1],[1,c+1],[2,d+1],[-1,a+c+2],[-2,d+1]],[a,b,c,d]] ]: end: #SawSM6(a,b,c): The symbolic mistakes Inspired by #mistakes up to memory 8 SawSM6:=proc(a,b,c,d,a1,b1,c1,d1): [ [[[1,1],[-1,1]],[]], [[[1,a+1],[2,b+1],[-1,a+1],[-2,b+1]],[a,b]], [[[1,a+1],[2,b+1],[-1,a+c+2],[-2,b+1],[1,c+1]],[a,b,c]], #leftmost-bottom corner(corner 1) [[[1,a+1],[2,b+1],[1,c+1],[2,d+1],[-1,a+c+2],[-2,b+d+2]],[a,b,c,d]], #between corner 1 and corner 2 [[[1,a+1],[2,b+1],[1,c+1],[2,d+1],[-1,a+a1+c+3],[-2,b+d+2],[1,a1+1]], [a,a1,b,c,d]], #corner 2 [[[2,b+1],[1,c+1],[2,d+1],[-1,a+c+2],[-2,b+d+2],[1,a+1]],[a,b,c,d]], #between corner 2 and corner 3 [[[2,b+1],[1,c+1],[2,d+1],[-1,a+c+2],[-2,b+b1+d+3],[1,a+1],[2,b1+1]], [a,b,b1,c,d]], #corner 3 [[[1,c+1],[2,d+1],[-1,a+c+2],[-2,b+d+2],[1,a+1],[2,b+1]],[a,b,c,d]], #between corner 3 and corner 4 [[[1,c+1],[2,d+1],[-1,a+c+c1+3],[-2,b+d+2],[1,a+1],[2,b+1],[1,c1+1]], [a,b,c,c1,d]], #corner 4 [[[2,d+1],[-1,a+c+2],[-2,b+d+2],[1,a+1],[2,b+1],[1,c+1]],[a,b,c,d]], #between corner 4 and corner 5 [[[2,d+1],[-1,a+c+2],[-2,b+d+d1+3],[1,a+1],[2,b+1],[1,c+1],[2,d1+1]], [a,b,c,d,d1]], #corner 5 [[[-1,a+c+2],[-2,b+d+2],[1,a+1],[2,b+1],[1,c+1],[2,d+1]],[a,b,c,d]], #between corner 5 and corner 5.5 [[[-1,a+c+2],[-2,b+d+2],[1,a+1],[2,b+1],[1,c+c1+2],[2,d+1],[-1,c1+1]], [a,b,c,c1,d]], #corner 5.5 [[[-1,a+1],[-2,b+d+2],[1,a+1],[2,b+1],[1,c+1],[2,d+1],[-1,c+1]],[a,b,c,d]], #between corner 5.5 and corner 6 [[[-1,a+1],[-2,b+d+2],[1,a+a1+2],[2,b+1],[1,c+1],[2,d+1],[-1,c+a1+2]], [a,a1,b,c,d]], #corner 6 [[[-2,b+d+2],[1,a+1],[2,b+1],[1,c+1],[2,d+1],[-1,a+c+2]],[a,b,c,d]], #between corner 6 and corner 6.5 [[[-2,b+d+2],[1,a+1],[2,b+1],[1,c+1],[2,d+d1+2],[-1,a+c+2],[-2,d1+1]], [a,b,c,d,d1]], #corner 6.5 [[[-2,b+1],[1,a+1],[2,b+1],[1,c+1],[2,d+1],[-1,a+c+2],[-2,d+1]],[a,b,c,d]], #between corner 6.5 and corner 1 [[[-2,b+1],[1,a+1],[2,b+b1+2],[1,c+1],[2,d+1],[-1,a+c+2],[-2,d+b1+2]], [a,b,b1,c,d]] ]: end: #WtoF: Converts a word to frequency notation WtoF:=proc(w) local w1,i,gu,a: if w=[] then RETURN([]): fi: a:=w[1]: for i from 1 to nops(w) while w[i]=a do od: i:=i-1: w1:=[op(i+1..nops(w),w)]: gu:=WtoF(w1): [[a,i],op(gu)]: end: #SawUm4(x,t): An Umbral Scheme for the #Cluster Generating Function for 2D walks on the #square lattice that avoid retracing, rectangles, #and all polygons up to perimeter memo SawUm4:=proc(x,t) local SetSW,a,b,c: SetSW:=SawSM4(a,b,c): WtUmSc(SetSW,x,t,2): end: #SawUm6(x,t): An Umbral Scheme for the #Cluster Generating Function for 2D walks on the #square lattice that avoid retracing, rectangles, #and hexagonal subwalks #and all polygons up to perimeter memo SawUm6:=proc(x,t) local SetSW,a,b,c,d: SetSW:=SawSM6(a,b,c,d): WtUmSc(SetSW,x,t,2): end: #SawUm6a(x,t): An Umbral Scheme for the #Cluster Generating Function for 2D walks on the #square lattice that avoid retracing, rectangles, #and hexagons that start at the corner SawUm6a:=proc(x,t) local SetSW,a,b,c,d: SetSW:=SawSM6a(a,b,c,d): WtUmSc(SetSW,x,t,2): end: #Tony4(n): The first n terms in the enumerating #series for 2D walks in the rectangular lattice that #avoid rectangles (that may start anywhere) Tony4:=proc(n) local a,b,c,SetSW: SetSW:=SawSM4(a,b,c): Tony(SetSW,2,n): end: #Tony6(n): The first n terms in the enumerating #series for 2D walks in the rectangular lattice that #avoid rectanglular #and hexagonal paths Tony6:=proc(n) local a,b,c,d,a1,b1,c1,d1,SetSW: SetSW:=SawSM6(a,b,c,d,a1,b1,c1,d1): Tony(SetSW,2,n): end: #Tony6a(n): The first n terms in the enumerating #series for 2D walks in the rectangular lattice that #avoid rectangles (that may start anywhere) #and hexagons (that start at corners) Tony6a:=proc(n) local a,b,c,d,SetSW: SetSW:=SawSM6a(a,b,c,d): Tony(SetSW,2,n): end: ####End Part Just for 2D Self-Avoiding Walks on the Square Lattice