############################################################################### # IdentityFinder: # # A Maple package written # # to help find partition identities # # accompanying the article # # Identity Finder and some new partition identities of Rogers-Ramanujan-type # # # # by Matthew C. Russell # # # # Date: October 27, 2014 # ############################################################################### print(`IdentityFinder:`): print(`A Maple package written`): print(`to help find partition identities`): print(`accompanying the article`): print(`Identity Finder and some new partition identities of Rogers-Ramanujan-type`): print(`Requires Frank Garvan's q-series package, available at`): print(`http://www.qseries.org/fgarvan/qmaple/qseries/index.html`): print(`For help, type Help();`): Help:=proc() if args=NULL then print(`Main procedures are`): print(`ExploreCapparelli(DiffMin,DiffMax,DistMin,DistMax,smpartMin,smpartMax,numtimesMin,numtimesMax,DMin,DMax,CMin,CMax,MMin,MMax,nMax,nCheck,maxPer,q):`): print(`CapparelliSingleSeriesCalculator(Pol,Diff,Dist,smpart,numtimes,D,C,M,m,nstart,nend):`): print(``): print(`For a list of helping procedures,`): print(`type Help(Helping);`): print(``): print(`For a list of condition procedures,`): print(`type Help(Condition);`): print(``): print(`For a list of currently unused condition procedures,`): print(`type Help(UnusedCondition);`): print(``): print(`For more information about a specific function`): print(`type Help(function_name);`): print(`For example, Help(ExploreCapparelli);`): elif args=Helping then print(`Helping procedures are`): print(`S(L,k):`): print(`Minus(L1,L2):`): print(`Reverse(L):`): print(`ListToSeries(L,q):`): print(`SerToList(L,q):`): print(`IsPer(L,k):`): print(`PerFinder(L):`): print(``): print(`For more information about a specific function`): print(`type Help(function_name);`): print(`For example, Help(Reverse);`): elif args=S then print(`S(L,k):`): print(`inputs a list L`): print(`and an integer k`): print(`Shifts L by k places`): print(`(deletes first k elements)`): print(`If L is interpreted as`): print(`the coefficient list of a power series in q,`): print(`this corresponds to dividing by q^k`): print(``): print(`Try: S([1,2,3,4,5],2);`): elif args=Minus then print(`Minus(L1,L2):`): print(`Returns the difference of two lists`): print(`(taken componentwise)`): print(`If L1 and L2 are different lengths`): print(`the difference is taken to the minimum of the lengths`): print(``): print(`Try: Minus([1,2,4,8],[1,2,3,4,5]);`): elif args=Reverse then print(`Reverse(L):`): print(`Inputs a partition L,`): print(`generated by Maple`): print(`Maple generates partitions in`): print(`*nondecreasing* order`): print(`We don't like this, so we reverse the order`): print(`so that the resulting partition`): print(`is in nonincreasing order`): print(``): print(`Try: Reverse([1,1,2,5,6]);`): elif args=ListToSeries then print(`ListToSeries(L,q):`): print(`Inputs a list L`): print(`and a formal variable q`): print(`converts it to a power series in q`): print(``): print(`Try: ListToSeries([1,0,1,2,3],q);`): elif args=SerToList then print(`SerToList(L,q):`): print(`Inputs a series L`): print(`in a formal variable q`): print(`returns the list of coefficients`): print(``): print(`Try: SerToList(1+q^2+2*q^3+3*q^4,q);`): elif args=IsPer then print(`IsPer(L,k):`): print(`Inputs a list L`): print(`and a possible period k`): print(`Returns true if L is periodic`): print(`with period k`): print(``): print(`Try: IsPer([1,2,3,4,1,2,3],4);`): elif args=PerFinder then print(`PerFinder(L):`): print(`Finds the smallest period of a list L`): print(`(note that L is not periodic, it will return nops(L) )`): print(``): print(`Try: PerFinder([1,2,1,2,1,2,1,2]);`): elif args=Condition then print(`Condition procedures are`): print(`DiffDistCheck(L,Diff,Dist):`): print(`CapparelliCheck(L,D,C,M,m):`): print(`SmPartCheck(L,smpart,numtimes):`): print(``): print(`For more information about a specific function`): print(`type Help(function_name);`): print(`For example, Help(DiffDistCheck);`): elif args=DiffDistCheck then print(`DiffDistCheck(L,Diff,Dist):`): print(`inputs a partition L`): print(`(arranged in nonincreasing order)`): print(`and an integer Diff`): print(`returns true if all parts of L at distance Dist`): print(`have difference at least Diff`): print(`(that is, L[i]-L[i+Dist]>=2)`): print(`and false otherwise`): print(``): print(`Try: DiffDistCheck([5,4,3,1],3,2);`): elif args=CapparelliCheck then print(`CapparelliCheck(L,D,C,M,m):`): print(`Inputs a partition L`): print(`Checks the following condition:`): print(`If parts at distance D are within C of each other,`): print(`then the sum of the parts between those two parts (inclusive)`): print(`is congruent to m mod M.`): print(`Returns true or false, as appropriate`): print(``): print(`Try: CapparelliCheck([12,8,3,1],1,3,0,3);`): elif args=SmPartCheck then print(`SmPartCheck(L,smpart,numtimes):`): print(`inputs a partition L`): print(`(in nonincreasing order)`): print(`checks to see if:`): print(`1. Smallest part is at least smpart`): print(`2. The part smpart occurs at most numtimes`): print(``): print(`SmPartCheck([7,3,2,2],2,1);`): elif args=UnusedCondition then print(`Currently unused condition procedures are`): print(`ForbCongCheck(L,M,S):`): print(`ForbPartCheck(L, S):`): print(`CapparelliCheck2(L,D,C,M,m):`): print(``): print(`For more information about a specific function`): print(`type Help(function_name);`): print(`For example, Help(ForbCongCheck);`): elif args=ForbCongCheck then print(`ForbCongCheck(L,M,S):`): print(`Inputs a partition L`): print(`Returns false if L has any parts`): print(`congruent to s mod M`): print(`for any s in S`): print(``): print(`Try: ForbCongCheck([8,5,2],4,{2});`): elif args=ForbPartCheck then print(`ForbPartCheck(L, S):`): print(`Inputs a partition L`): print(`Returns false if L has any parts`): print(`equal to s for any s in S`): print(``): print(`Try: ForbPartCheck([8,5,2],{1,3});`): print(``): elif args=CapparelliCheck2 then print(`CapparelliCheck2(L,D,C,M,m):`): print(`Inputs a partition L`): print(`Checks the following condition:`): print(`If parts at distance D are within C of each other,`): print(`then p1+p2 (the sum of those two parts)`): print(`is congruent to 0 mod M.`): print(`Returns true or false, as appropriate`): print(``): print(`Try: CapparelliCheck2([12,8,3,1],1,3,0,3);`): elif args=ExploreCapparelli then print(`ExploreCapparelli(DiffMin,DiffMax,DistMin,DistMax,smpartMin,smpartMax,numtimesMin,numtimesMax,DMin,DMax,CMin,CMax,MMin,MMax,nMax,nCheck,maxPer,q):`): print(`Explores parameter space for Capparelli-style identities`): print(`Parameters:`): print(`DiffMin and DiffMax: minimum and maximum values for Diff`): print(`in DiffDistCheck(L,Diff,Dist)`): print(`DistMin and DistMax: minimum and maximum values for Dist`): print(`in DiffDistCheck(L,Diff,Dist)`): print(`smpartMin and smpartMax: minimum and maximum values for smpart`): print(`in SmPartCheck(L,smpart,numtimes):`): print(`numtimesMin and numtimesMax: minimum and maximum values for numtimes`): print(`in SmPartCheck(L,smpart,numtimes):`): print(`Note: it can be a good idea to allow numtimes to be 0`): print(`(this corresponds to forbidding smpart,`): print(`but not placing a restriction on smpart+1)`): print(`DMin and DMax: minimum and maximum values for D`): print(`in CapparelliCheck(L,D,C,M,m):`): print(`CMin and CMax: minimum and maximum values for C`): print(`in CapparelliCheck(L,D,C,M,m):`): print(`MMin and MMax: minimum and maximum values for M`): print(`in CapparelliCheck(L,D,C,M,m):`): print(`Note: m is assumed to run from 0 to M-1`): print(`nMax: How many terms of each series to calculate on the first pass`): print(`nCheck: How many terms of each series to calculate on the second pass`): print(`maxPer: Maximum period we are looking for`): print(`q: formal variable`): print(`Returns a list of conjectured identities`): print(``): print(`Try: ExploreCapparelli(1,3,1,3,0,3,0,0,1,3,0,3,2,4,15,31,20,q);`): elif args=CapparelliSingleSeriesCalculator then print(`CapparelliSingleSeriesCalculator(Pol,Diff,Dist,smpart,numtimes,D,C,M,m,nstart,nend):`): print(`Inputs values for:`): print(`Diff and Dist in DiffDistCheck(L1,Diff,Dist)`): print(`smpart and numtimes in SmPartCheck(L1,smpart,numtimes)`): print(`D, C, M, and m in CapparelliCheck(L1,D,C,M,m)`): print(`Starting value to calculate from nstart`): print(`Ending value to calculate to nend`): print(`Initial terms of the series Pol (for n from 0 to nstart-1)`): print(`Computes additional terms of the sum side`): print(`with the appropriate parameters above`): print(`from nstart to nend`): print(``): print(`Try: CapparelliSingleSeriesCalculator(1,3,2,0,0,1,1,3,0,1,20);`): else print(`There is no help for`,args): fi: end: ########################################################################### # # # Helping procedures # # # ########################################################################### ########################################################################### # S(L,k): # inputs a list L # and an integer k # Shifts L by k places # (deletes first k elements) # If L is interpreted as # the coefficient list of a power series in q, # this corresponds to dividing by q^k # # Try: S([1,2,3,4,5],2); S:=proc(L,k) return [op(k+1..nops(L),L)]: end: ########################################################################### # Minus(L1,L2): # Returns the difference of two lists # (taken componentwise) # If L1 and L2 are different lengths # the difference is taken to the minimum of the lengths # # Try: Minus([1,2,4,8],[1,2,3,4,5]); Minus:=proc(L1,L2) local j: return [seq(L1[j]-L2[j],j=1..min(nops(L1),nops(L2)))]: end: ########################################################################### # Reverse(L): # Inputs a partition L, # generated by Maple # Maple generates partitions in # *nondecreasing* order # We don't like this, so we reverse the order # so that the resulting partition # is in nonincreasing order # # Try: Reverse([1,1,2,5,6]); Reverse:=proc(L) return [seq(L[nops(L)-i+1],i=1..nops(L))]: end: ########################################################################### # ListToSeries(L,q): # Inputs a list L # and a formal variable q # converts it to a power series in q # # Try: ListToSeries([1,0,1,2,3],q); ListToSeries:=proc(L,q) return add(L[i]*q^(i-1),i=1..nops(L)): end: ########################################################################### # SerToList(L,q): # Inputs a series L # in a formal variable q # returns the list of coefficients # # Try: SerToList(1+q^2+2*q^3+3*q^4,q); SerToList:=proc(L,q) return [seq(coeff(L,q,i),i=0..degree(L,q))]: end: ########################################################################### # IsPer(L,k): # Inputs a list L # and a possible period k # Returns true if L is periodic # with period k # # Try: IsPer([1,2,3,4,1,2,3],4); IsPer:=proc(L,k) local i: for i from k+1 to nops(L) do if L[i]<>L[i-k] then return false: fi: od: return true: end: ########################################################################### # PerFinder(L): # Finds the smallest period of a list L # (note that L is not periodic, it will return nops(L) ) # # Try: PerFinder([1,2,1,2,1,2,1,2]); PerFinder:=proc(L) local i: for i from 1 to nops(L) do if IsPer(L,i) then return i: fi: od: return nops(L): end: ########################################################################### ########################################################################### # # # Condition procedures # # # ########################################################################### ########################################################################### # DiffDistCheck(L,Diff,Dist): # inputs a partition L # (arranged in nonincreasing order) # and an integer Diff # returns true if all parts of L at distance Dist # have difference at least Diff # (that is, L[i]-L[i+Dist]>=2) # and false otherwise # # Try: DiffDistCheck([5,4,3,1],3,2); DiffDistCheck:=proc(L,Diff,Dist) local i: for i from 1 to nops(L)-Dist do if L[i]m then return false: fi: od: return true: end: ########################################################################### # SmPartCheck(L,smpart,numtimes): # inputs a partition L # (in nonincreasing order) # checks to see if: # 1. Smallest part is at least smpart # 2. The part smpart occurs at most numtimes # # Try: SmPartCheck([7,3,2,2],2,1); SmPartCheck:=proc(L,smpart,numtimes) local i: if L[nops(L)]=nops(L) then return true: fi: return evalb(L[nops(L)-numtimes]<>smpart): end: ########################################################################### ########################################################################### # # # Unused condition procedures # # # ########################################################################### ########################################################################### # ForbCongCheck(L,M,S): # Inputs a partition L # Returns false if L has any parts # congruent to s mod M # for any s in S # # Try: ForbCongCheck([8,5,2],4,{2}); ForbCongCheck:=proc(L,M,S) local i, s: for i from 1 to nops(L) do for s in S do if L[i] mod M = s then return false: fi: od: od: return true: end: ########################################################################### # ForbPartCheck(L, S): # Inputs a partition L # Returns false if L has any parts # equal to s for any s in S # # Try: ForbPartCheck([8,5,2],{1,3}); ForbPartCheck:=proc(L,S) local i, s: for i from 1 to nops(L) do for s in S do if L[i] = s then return false: fi: od: od: return true: end: ########################################################################### # CapparelliCheck2(L,D,C,M,m): # Inputs a partition L # Checks the following condition: # If parts at distance D are within C of each other, # then p1+p2 (the sum of those two parts) # is congruent to 0 mod M. # Returns true or false, as appropriate # # Try: CapparelliCheck2([12,8,3,1],1,3,0,3); CapparelliCheck2:=proc(L,D,C,M,m) local i: for i from 1 to nops(L)-D do if L[i]<=L[i+D]+C and L[i]+L[i+D] mod M<>m then return false: fi: od: return true: end: ########################################################################### ########################################################################### # # # Main procedures # # # ########################################################################### ########################################################################### # CapparelliSingleSeriesCalculator(Pol,Diff,Dist,smpart,numtimes,D,C,M,m,nstart,nend): # Inputs values for: # Diff and Dist in DiffDistCheck(L1,Diff,Dist) # smpart and numtimes in SmPartCheck(L1,smpart,numtimes) # D, C, M, and m in CapparelliCheck(L1,D,C,M,m) # Starting value to calculate from nstart # Ending value to calculate to nend # Initial terms of the series Pol (for n from 0 to nstart-1) # Computes additional terms of the sum side # with the appropriate parameters above # from nstart to nend # # Try: CapparelliSingleSeriesCalculator(1,3,2,0,0,1,1,3,0,1,20); CapparelliSingleSeriesCalculator:=proc(Pol,Diff,Dist,smpart,numtimes,D,C,M,m,nstart,nend,q) local co, n, L, L1: co:=Pol: for n from nstart to nend do for L in combinat[partition](n) do L1:=Reverse(L): if DiffDistCheck(L1,Diff,Dist) then if SmPartCheck(L1,smpart,numtimes) then if CapparelliCheck(L1,D,C,M,m) then co:=co+q^n: fi: fi: fi: od: od: return co: end: ########################################################################### # ExploreCapparelli(DiffMin,DiffMax,DistMin,DistMax,smpartMin,smpartMax,numtimesMin,numtimesMax,DMin,DMax,CMin,CMax,MMin,MMax,nMax,nCheck,maxPer,q): # Explores parameter space for Capparelli-style identities # Parameters: # DiffMin and DiffMax: minimum and maximum values for Diff # in DiffDistCheck(L,Diff,Dist) # DistMin and DistMax: minimum and maximum values for Dist # in DiffDistCheck(L,Diff,Dist) # smpartMin and smpartMax: minimum and maximum values for smpart # in SmPartCheck(L,smpart,numtimes): # numtimesMin and numtimesMax: minimum and maximum values for numtimes # in SmPartCheck(L,smpart,numtimes): # Note: it can be a good idea to allow numtimes to be 0 # (this corresponds to forbidding smpart, # but not placing a restriction on smpart+1) # DMin and DMax: minimum and maximum values for D # in CapparelliCheck(L,D,C,M,m): # CMin and CMax: minimum and maximum values for C # in CapparelliCheck(L,D,C,M,m): # MMin and MMax: minimum and maximum values for M # in CapparelliCheck(L,D,C,M,m): # Note: m is assumed to run from 0 to M-1 # nMax: How many terms of each series to calculate on the first pass # nCheck: How many terms of each series to calculate on the second pass # maxPer: Maximum period we are looking for # q: formal variable # Returns a list of conjectured identities # # Try: ExploreCapparelli(1,3,1,3,0,3,0,0,1,3,0,3,2,4,15,31,20,q); ExploreCapparelli:=proc(DiffMin,DiffMax,DistMin,DistMax,smpartMin,smpartMax,numtimesMin,numtimesMax,DMin,DMax,CMin,CMax,MMin,MMax,nMax,nCheck,maxPer,q) local Counter, ListSet, DiffIter, DistIter, smpartIter, numtimesIter, DIter, CIter, MIter, mIter, n, L, L1, Pol, Ser, STL, A, K, K1, k: local nnn: nnn:=0: for DiffIter from DiffMin to DiffMax do for DistIter from DistMin to DistMax do for smpartIter from smpartMin to smpartMax do for numtimesIter from numtimesMin to numtimesMax do for DIter from DMin to DMax do for CIter from CMin to CMax do for MIter from MMin to MMax do for mIter from 0 to MIter-1 do nnn:=nnn+1: Counter[DiffIter][DistIter][smpartIter][numtimesIter][DIter][CIter][MIter][mIter]:=1: od: od: od: od: od: od: od: od: print(`We will examine `,nnn,` sum sides`): for n from 1 to nMax do print(`Calculating term `,n,` of sum sides`): for L in combinat[partition](n) do L1:=Reverse(L): for DiffIter from DiffMin to DiffMax do for DistIter from DistMin to DistMax do if DiffDistCheck(L1,DiffIter,DistIter) then for smpartIter from smpartMin to smpartMax do for numtimesIter from numtimesMin to numtimesMax do if SmPartCheck(L1,smpartIter,numtimesIter) then for DIter from DMin to DMax do for CIter from CMin to CMax do for MIter from MMin to MMax do for mIter from 0 to MIter-1 do if CapparelliCheck(L1,DIter,CIter,MIter,mIter) then Counter[DiffIter][DistIter][smpartIter][numtimesIter][DIter][CIter][MIter][mIter]:=Counter[DiffIter][DistIter][smpartIter][numtimesIter][DIter][CIter][MIter][mIter]+q^n: fi: od: od: od: od: fi: od: od: fi: od: od: od: od: print(`First pass through sum sides completed`): ListSet:={}: nnn:=0: for DiffIter from DiffMin to DiffMax do for DistIter from DistMin to DistMax do for smpartIter from smpartMin to smpartMax do for numtimesIter from numtimesMin to numtimesMax do for DIter from DMin to DMax do for CIter from CMin to CMax do for MIter from MMin to MMax do for mIter from 0 to MIter-1 do nnn:=nnn+1: if nnn mod 100=0 then print(`################################`): print(`Through `,nnn,` sum sides`): print(`################################`): fi: Pol:=Counter[DiffIter][DistIter][smpartIter][numtimesIter][DIter][CIter][MIter][mIter]: Ser:=qseries[prodmake](Pol,q,nMax,list): if {op(Ser),0,-1}={0,-1} then STL:=SerToList(Ser,q): if ListSet union {STL} <> ListSet then ListSet:=ListSet union {STL}: A:=CapparelliSingleSeriesCalculator(Pol,DiffIter,DistIter,smpartIter,numtimesIter,DIter,CIter,MIter,mIter,nMax+1,nCheck,q): K:=qseries[prodmake](A,q,nCheck,list): if {op(K),0,-1}={0,-1} and PerFinder(K)