# multsum.mpl # (C) Torsten Sprenger, University of Kassel, 2003-2005 # # Torsten Sprenger # sprenger@mathematik.uni-kassel.de # http://www.mathematik.uni-kassel.de/~sprenger _EnvSmax:=10: _EnvC:=1: _EnvP:=1: _EnvSolve:=SolveTools[Linear]: _EnvFilter:=0: ########################################################### # # # 'check_hyper' überprüft, ob ein eingegebener Term t # # hypergeometrisch ist. Ist das nicht der Fall, so wird # # ein Fehler ausgegeben, andernfalls passiert nichts. # # # ########################################################### check_hyper:=proc(t,k,n) local i,var,hyper; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; var:=[n,op(k)]; hyper:=andmap(evalb, {seq(type(ratio(t,var[i]),ratpoly(anything,var[i])), i=1..nops(var)) }); if not(hyper) then ERROR(`Term is not hypergeometric`) end if; end proc: checkhyper:=proc(t,k,n) local check; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; check:=check_hyper(t,k,n); if check=NULL then return(true) else return(false) end if; end proc: ########################################################### # # # 'check_proper' überprüft, ob ein eingegebener Term t # # zulässig (proper) ist. Ist das nicht der Fall, so # # wird ein Fehler ausgegeben, andernfalls wird das # # Polynom (pol) und der GAMMA-Ausdruck (gam) des PHT's # # (proper hypergeometric term) zurückgegeben. # # # ########################################################### check_proper:=proc(t,k,n) local i,x,term,kk,pol_den,pol_den_,den_set,var,rules,gam_den,gam_num,gam,pol; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; check_hyper(t,k,n); kk:=[op(k)]; var:=[n,op(k)]; rules:=[seq((x::freeof(var))^var[i]=1,i=1..nops(kk)+1)]; term:=applyrule(rules,simpcomb(t)); gam_num:=numer(term); pol_den:=factor(applyrule(GAMMA(x::anything)=1,denom(term))); pol_den_:=1; if type(pol_den,`*`) then for i from 1 to nops(pol_den) do if type(op(i,pol_den),freeof(var)) then gam_num:=gam_num/op(i,pol_den); pol_den_:=pol_den_*op(i,pol_den); end if; end do; end if; pol_den:=pol_den/pol_den_; gam_den:=1; if not(type(pol_den,freeof(var))) then den_set:=convert(factor(pol_den),`multiset`); for i from 1 to nops(den_set) do if degree(den_set[i,1],{op(var)})=1 then gam_den:=gam_den*(GAMMA(den_set[i,1]+1)/GAMMA(den_set[i,1]))^(den_set[i,2]) else ERROR(`Hypergeometric term is not proper`) end if end do else pol_den:=1; end if; gam_den:=gam_den*(denom(term)/pol_den); gam:=gam_num/gam_den; pol:=applyrule(GAMMA(x::anything)=1,gam); gam:=normal(gam/pol); return([pol,gam]); end proc: checkproper:=proc(t,k,n) local check; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; try check:=check_proper(t,k,n); catch: return(false); end try; return(true); end proc: ########################################################### # # # 'convertgam' extrahiert die Argumente der GAMMA- # # Funktionen des GAMMA-Ausdrucks und überführt sie in # # eine Liste für die Zähler-Ausdrücke (num_fac_ex) und # # in eine Liste für die Nenner-Ausdrücke (den_fac_ex). # # # ########################################################### convertgam:=proc(gam) local i,j,num,den,upper,lower,num_fac_ex,den_fac_ex; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; num:=convert(numer(gam),`multiset`); den:=convert(denom(gam),`multiset`); upper:=applyrule(GAMMA(x::anything)=x,num); lower:=applyrule(GAMMA(x::anything)=x,den); num_fac_ex:=[]; den_fac_ex:=[]; if not(type(num,freeof(GAMMA))) then for i from 1 to nops(upper) do num_fac_ex:=[op(num_fac_ex),seq(upper[i,1],j=1..upper[i,2])] end do; end if; if not(type(den,freeof(GAMMA))) then for i from 1 to nops(lower) do den_fac_ex:=[op(den_fac_ex),seq(lower[i,1],j=1..lower[i,2])] end do; end if; return([num_fac_ex,den_fac_ex]); end proc: ########################################################### # # # 'convertfacex' bestimmt # # die Koeffizienten der Zähler-Ausdrücke (a,b,c) und # # die Koeffizienten der Nenner-Ausdrücke (u,v,w) und # # gibt sie jeweils als Listen aus. # # # ########################################################### convertfacex:=proc(num_fac_ex,den_fac_ex,k,n) local i,j,kk,pp,qq,a,b,c,u,v,w,r,var; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; kk:=[op(k)]; var:=[n,op(k)]; r:=nops(k); pp:=nops(num_fac_ex); qq:=nops(den_fac_ex); a:=[seq(coeff(num_fac_ex[i],n,1),i=1..pp)]; b:=[seq([seq(coeff(num_fac_ex[i],var[j+1],1),i=1..pp)],j=1..r)]; c:=[]; for i from 1 to pp do if ldegree(num_fac_ex[i],var)=1 then c:=[op(c),0] else c:=[op(c),tcoeff(num_fac_ex[i],var)] end if end do; u:=[seq(coeff(den_fac_ex[i],n,1),i=1..qq)]; v:=[seq([seq(coeff(den_fac_ex[i],var[j+1],1),i=1..qq)],j=1..r)]; w:=[]; for i from 1 to qq do if ldegree(den_fac_ex[i],var)=1 then w:=[op(w),0] else w:=[op(w),tcoeff(den_fac_ex[i],var)] end if end do; if nargs>4 then return([a,b,u,v]) else return([a,b,c,u,v,w]) end if; end proc: ########################################################### # # # 'properterm' bestimmt die Bestandteile eines einge- # # gebenen Terms t. Ausgegeben wird eine Liste mit drei # # Elementen: # # (1): Polynom (pol) # # (2): die Koeffizienten der Zähler- und Nenner- # # Ausdrücke (a,b,c,u,v,w) # # (3): restliche Potenzen. # # # ########################################################### properterm:=proc(t,k,n) local pol_gam,abc_uvw,var; option remember, `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; var:=[n,op(k)]; pol_gam:=check_proper(t,k,n); abc_uvw:=convertgam(pol_gam[2]); return([pol_gam[1], convertfacex(abc_uvw[1],abc_uvw[2],k,n), simpcomb(t/(pol_gam[1]*pol_gam[2]))]); end proc: ########################################################### # # # 'facdiff' bestimmt die Fakultäts-Differenz # # und gibt sie als [A_t,B_t] aus. # # # ########################################################### facdiff:=proc(t,k,n) local i,j,r,propterm,abc_uvw,p,q,pp,qq,A,B; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; propterm:=properterm(t,k,n); r:=nops(k); pp:=nops(propterm[2,1]); qq:=nops(propterm[2,4]); abc_uvw:=propterm[2]; A:=0; for p from 1 to pp do if {seq(abc_uvw[2,j,p],j=1..r)}<>{0} then A:=A+abc_uvw[1,p] end if end do; for q from 1 to qq do if {seq(abc_uvw[5,j,q],j=1..r)}<>{0} then A:=A-abc_uvw[4,q] end if end do; for i from 1 to r do B[i]:=0; for p from 1 to pp do B[i]:=B[i]+abc_uvw[2,i,p] end do; for q from 1 to qq do B[i]:=B[i]-abc_uvw[5,i,q] end do; end do; return([A,seq(B[i],i=1..r)]); end proc: ########################################################### # # # 'structurefct' bestimmt die Parameter der Struktur- # # funktionen eines PHT's t. # # # ########################################################### structurefct:=proc(t,k,n) local i,j,r,propterm,abc_uvw,AB,p,q,pp,qq,gh_abc,gh_uvw,gh_AB; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; propterm:=properterm(t,k,n); r:=nops(k); pp:=nops(propterm[2,1]); qq:=nops(propterm[2,4]); abc_uvw:=propterm[2]; for p from 1 to pp do gh_abc[p]:=[]; if {seq(abc_uvw[2,j,p],j=1..r)}<>{0} then gh_abc[p]:=[op(gh_abc[p]),abc_uvw[1,p]/igcd(abc_uvw[1,p],seq(abc_uvw[2,j,p],j=1..r))]; for i from 1 to r do gh_abc[p]:=[op(gh_abc[p]),abc_uvw[2,i,p]/igcd(abc_uvw[1,p],seq(abc_uvw[2,j,p],j=1..r))]; end do end if end do; for q from 1 to qq do gh_uvw[q]:=[]; if {seq(abc_uvw[5,j,q],j=1..r)}<>{0} then gh_uvw[q]:=[op(gh_uvw[q]),-abc_uvw[4,q]/igcd(abc_uvw[4,q],seq(abc_uvw[5,j,q],j=1..r))]; for i from 1 to r do gh_uvw[q]:=[op(gh_uvw[q]),-abc_uvw[5,i,q]/igcd(abc_uvw[4,q],seq(abc_uvw[5,j,q],j=1..r))]; end do end if end do; gh_AB:=NULL; AB:=facdiff(t,k,n); if {op(AB)}<>{0} then gh_AB:=[seq(-AB[j]/igcd(seq(AB[i],i=1..r+1)),j=1..r+1)] end if; return(remove(x->(x=[]),[seq(gh_abc[p],p=1..pp), seq(gh_uvw[q],q=1..qq), gh_AB])); end proc: ########################################################### # # # 'boundpts_Sstd' bestimmt Randpunkte der # # Standard-Strukturmenge Sstd (bp) und gibt zusätzlich # # die zugrunde liegenden Parameter der Struktur- # # funktionen (sf) aus. # # # ########################################################### boundpts_Sstd:=proc(t,k,n,IJ) local i,j,num_IJ,sf,num_sf,bp; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; sf:=structurefct(t,k,n); num_IJ:=nops(IJ); num_sf:=nops(sf); for i from 1 to num_sf do for j from 1 to num_IJ do if type(sf[i,j],nonnegative) then bp[i,j]:=IJ[j] else bp[i,j]:=0 end if; end do; end do; return([sf,[seq([seq(bp[i,j],j=1..num_IJ)],i=1..num_sf)]]); end proc: boundptsSstd:=proc(t,k,n,IJ) option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; return(boundpts_Sstd(t,k,n,IJ)[2]); end proc: ########################################################### # # # 'boundpts_S' bestimmt Randpunkte einer # # Strukturmenge S (bp) und gibt zusätzlich # # die zugrunde liegenden Parameter der Struktur- # # funktionen (sf) aus. # # # ########################################################### boundpts_S:=proc(t,k,n,S) local i,j,num_S,sf,num_sf,bp; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; sf:=structurefct(t,k,n); num_S:=nops(S); num_sf:=nops(sf); for i from 1 to num_sf do bp[i]:=[S[1,1],S[1,2]]; for j from 2 to num_S do if bp[i][1]*sf[i,1]+bp[i][2]*sf[i,2]subsop(0=binomial_,f))); val_num:=eval(subsindets(subs({n=i,k=j},numer(t)),'specfunc(anything,binomial)',f->subsop(0=binomial_,f))); catch: val:=evalf(subsindets(subs({n=i,k=j},t),'specfunc(anything,binomial)',f->subsop(0=binomial_,f))); val_num:=evalf(subsindets(subs({n=i,k=j},numer(t)),'specfunc(anything,binomial)',f->subsop(0=binomial_,f))); end try; if hastype(val,undefined) or hastype(val_num,infinity) then undef_pts:=[op(undef_pts),[i,j]]; else if not(hastype(val,name)) then if abs(val)>epsilon then pts:=[op(pts),[i,j]] end if; else pts:=[op(pts),[i,j]] end if; end if; end do; end do; return(plots[display](seq(plottools[point](pts[i],symbol=circle,symbolsize=15,color=black),i=1..nops(pts)), seq(plottools[point](undef_pts[i],symbol=circle,symbolsize=15,color=grey),i=1..nops(undef_pts)), axes=normal,scaling=constrained,view=[0..bd,-bd..bd])); end if; if nops(k)=2 and nargs<5 then for i from 0 to bd do for j from -bd to bd do for m from -bd to bd do try val:=eval(subsindets(subs({n=i,k[1]=j,k[2]=m},t),'specfunc(anything,binomial)',f->subsop(0=binomial_,f))); val_num:=eval(subsindets(subs({n=i,k[1]=j,k[2]=m},numer(t)),'specfunc(anything,binomial)',f->subsop(0=binomial_,f))); catch: val:=evalf(subsindets(subs({n=i,k[1]=j,k[2]=m},t),'specfunc(anything,binomial)',f->subsop(0=binomial_,f))); val_num:=evalf(subsindets(subs({n=i,k[1]=j,k[2]=m},numer(t)),'specfunc(anything,binomial)',f->subsop(0=binomial_,f))); end try; if hastype(val,undefined) or hastype(val_num,infinity) then undef_pts:=[op(undef_pts),[i,j,m]]; else if not(hastype(val,name)) then if abs(val)>epsilon then pts:=[op(pts),[i,j,m]] end if; else pts:=[op(pts),[i,j,m]] end if; end if; end do; end do; end do; return(plots[display3d](seq(plottools[point](pts[i],symbol=circle,symbolsize=15,color=black),i=1..nops(pts)), seq(plottools[point](undef_pts[i],symbol=circle,symbolsize=15,color=grey),i=1..nops(undef_pts)), axes=normal,scaling=constrained,view=[0..bd,-bd..bd,-bd..bd])); end if; if nops(k)=2 and nargs>4 then for i from -bd to bd do for j from -bd to bd do try val:=eval(subsindets(subs({n=args[5],k[1]=i,k[2]=j},t),'specfunc(anything,binomial)',f->subsop(0=binomial_,f))); val_num:=eval(subsindets(subs({n=args[5],k[1]=i,k[2]=j},numer(t)),'specfunc(anything,binomial)',f->subsop(0=binomial_,f))); catch: val:=evalf(subsindets(subs({n=args[5],k[1]=i,k[2]=j},t),'specfunc(anything,binomial)',f->subsop(0=binomial_,f))); val_num:=evalf(subsindets(subs({n=args[5],k[1]=i,k[2]=j},numer(t)),'specfunc(anything,binomial)',f->subsop(0=binomial_,f))); end try; if hastype(val,undefined) or hastype(val_num,infinity) then undef_pts:=[op(undef_pts),[i,j]]; else if not(hastype(val,name)) then if abs(val)>epsilon then pts:=[op(pts),[i,j]] end if; else pts:=[op(pts),[i,j]] end if; end if; end do; end do; return(plots[display](seq(plottools[point](pts[i],symbol=circle,symbolsize=15,color=black),i=1..nops(pts)), seq(plottools[point](undef_pts[i],symbol=circle,symbolsize=15,color=grey),i=1..nops(undef_pts)), axes=normal,scaling=constrained,view=[-bd..bd,-bd..bd])); end if; end proc: ########################################################### # # # 'drawSmax' zeichnet die Punkte der P-maximalen # # Strukturmenge eines PHT's in ein zwei- bzw. drei- # # dimensionales Koordinatensystem. # # # ########################################################### drawSmax:=proc(t,k,n,IJ) local i,j,Smax_pts,Sstd_pts,extend,extend_,equat,lines,Smax_,Sstd_,num_IJ,Scov_,bdpts,bdpts_, plotlist,planes; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; if 4x-min_IJ[i],S[i][2]))),i=1..nops(S)); return(plots[display](S,symbol=circle,symbolsize=15,axes=normal, color=black,scaling=constrained,insequence=true)); end proc: ########################################################### # # # 'm_selectSmax' sortiert die P-maximalen Struktur- # # Mengen aufsteigend nach der Grösse. # # Als obere Schranke dient K. # # # ########################################################### m_selectSmax:=proc(t,k,n,K) local i,r,x,y,IJ,Smax_,Smax_sorted,num_IJ; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; r:=nops(k); IJ:=Sstd([seq(K,i=1..r+1)]) minus {[seq(0,i=1..r+1)]}; num_IJ:=nops(IJ); Smax_:=[seq([IJ[i],m_Smax(t,k,n,IJ[i])],i=1..num_IJ)]; Smax_:=sort(Smax_,(x,y)->evalb(nops(x[2])<=nops(y[2]))); Smax_sorted:=[Smax_[1]]; for i from 2 to num_IJ do if evalb(nops(Smax_[i,2])<>nops(Smax_[i-1,2])) then Smax_sorted:=[op(Smax_sorted),Smax_[i]] end if; end do; return(Smax_sorted); end proc: ########################################################### # # # 'replacevar' ersetzt die auftretenden Variablen in # # einer Rekursionsgleichung durch möglichst einfache # # Zahlen (0 oder 1). # # # ########################################################### replacevar:=proc(recurrence,F,n,a) local i,j,var,num_var,subs_S,rec_wvar,rules,recurrences; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; var:=select(has,indets(recurrence),a); num_var:=nops(var); recurrences:={}; if num_var>0 then for i from 1 to num_var do rec_wvar:=subs(var[i]=1,recurrence); rec_wvar:=subs({seq(var[j]=0,j=1..num_var)},rec_wvar); if rec_wvar<>0 then rec_wvar:=numer(rec_wvar); rec_wvar:=contentrec_(rec_wvar,F,n,a); rec_wvar:=collect(rec_wvar,F,factor); recurrences:=recurrences union {rec_wvar=0}; end if; end do; end if; return(recurrences); end proc: ########################################################### # # # 'replacevar_sum' ersetzt die auftretenden Variablen # # in einer Rekursionsgleichung so, daß möglichst viele # # Summanden wegfallen. # # # ########################################################### replacevar_sum:=proc(recurrence,S,n,a) local i,rec,max_r,min_r,eq,temp_rec; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; rec:=recurrence; min_r:=minrec(rec)[1]; max_r:=maxrec(rec)[1]; for i from min_r to max_r-2 do try eq:=coeff(collect(lhs(rec)-rhs(rec),S),S(n+i)); temp_rec:=subs(solve(eq,select(has,indets(rec),a)),rec); temp_rec:=numer(lhs(temp_rec)-rhs(temp_rec))=0; if lhs(temp_rec)<>0 or rhs(temp_rec)<>0 then rec:=temp_rec; end if; catch: end try; end do; rec:=contentrec_(lhs(rec),S,n,a); return(collect(rec,S,factor)=0); end proc: ########################################################### # # # 'contentrec' bestimmt den Inhalt einer Rekursion # # und teilt die Rekursionsgleichung durch diesen. # # # ########################################################### content_r:=proc(recurrence) local i,content,rec,F_list,F,recurrence_; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; if type(recurrence,equation) then recurrence_:=lhs(recurrence)-rhs(recurrence); else recurrence_:=recurrence; end if; F_list:=select(type,indets(recurrence_),function); F:=op(0,F_list[1]); rec:=factor(recurrence_); content:=1; if type(rec,`*`) then for i from 1 to nops(rec) do if type(op(i,rec),freeof(F)) then content:=content*op(i,rec) end if; end do; end if; return([content,collect(normal(rec/content),F,factor)=0]); end proc: contentrec:=proc(recurrence) option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; if type(recurrence,list) or type(recurrence,set) then return(map(x->content_r(x),[op(recurrence)])); else return(content_r(recurrence)); end if; end proc: ########################################################### # # # 'contentrec_' bestimmt den Inhalt einer Rekursion # # und teilt die Rekursionsgleichung durch Faktoren von # # diesen, dessen Nullstellen nichtnegativ sind. # # # ########################################################### contentrec_:=proc(recurrence,F,n,a) local i,content,rec,order; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; rec:=recurrence=0; order:=orderrec(rec)-maxrec(rec)[1]; rec:=factor(lhs(rec)); content:=1; if type(rec,`*`) then for i from 1 to nops(rec) do if type(op(i,rec),freeof(F)) then if has(op(i,rec),a) then content:=content*op(i,rec); else if nops(select(type,[solve(subs(n=n+order,op(i,rec)),n)],nonnegint))=0 then content:=content*op(i,rec); end if; end if; end if; end do; end if; return(normal(rec/content)); end proc: ########################################################### # # # 'rat_linear' gibt die Zahlen [m,l1,...,lr] bei Eingabe # # eines (m,l1,...lr)-fachen hypergeometr. Terms aus. # # # ########################################################### rat_linear:=proc(t,k,n) local term,i,m,p,q,pp,qq,r,denom_list; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; r:=nops(k); term:=convertfacex(op(convertgam(select(has,simpcomb(t),GAMMA))),k,n); pp:=nops(term[1]); qq:=nops(term[4]); for i from 1 to r+1 do denom_list[i]:=[]; end do; for p from 1 to pp do denom_list[1]:=[op(denom_list[1]),denom(term[1][p])]; for i from 1 to r do denom_list[i+1]:=[op(denom_list[i+1]),denom(term[2][i][p])]; end do; end do; for q from 1 to qq do denom_list[1]:=[op(denom_list[1]),denom(term[4][q])]; for i from 1 to r do denom_list[i+1]:=[op(denom_list[i+1]),denom(term[5][i][q])]; end do; end do; return([seq(lcm(op(denom_list[m])),m=1..r+1)]); end proc: ########################################################### # # # 'updateF' wandelt einen (m,l1,...lr)-fachen hyper- # # geometr. Terms in einen hypergeometr. Term um. # # # ########################################################### updateF:=proc(t,k,n) local rat,i,var,r; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; r:=nops(k); var:=[n,op(k)]; rat:=rat_linear(t,k,n); return(subs(seq(var[i]=rat[i]*var[i],i=1..r+1),t)); end proc: ########################################################### # # # 'updateF_back' wandelt eine Rekursion in eine # # Rekursion bzgl. des Ausgangsterms um. # # # ########################################################### updateF_back:=proc(recurrence,t,k,n,F) local i,m,new_rec,rat_,tt,pol,var,r; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; r:=nops(k); var:=[n,op(k)]; rat_:=rat_linear(t,k,n); new_rec:=0; for i from 1 to nops(recurrence) do tt:=select(has,op(i,recurrence),F); pol:=subs({seq(var[m]=var[m]/rat_[m],m=1..r+1)},normal(op(i,recurrence)/tt)); new_rec:=new_rec+pol*subs({seq(op(m,tt)=var[m]+expand(rat_[m]*(op(m,tt)-var[m])),m=1..r+1)},tt); end do; return(new_rec); end proc: ########################################################### # # # 'krec' gibt eine k-freie Rekursionsgleichung aus, # # sofern eine existiert. # # # ########################################################### krec:=proc(t_,k,n,IJ) local t,tt,i,j,m,num_IJ,num_Smax,F,a,Smax_,subs_S,var,variables,eq,IJ_, sol,recurrence,print,rat_term,arg; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; if 41 then if not(type(IJ[2],`list`)) then Smax_:=IJ[2]; else Smax_:=IJ; print:=0; end if; else Smax_:=IJ; print:=0; end if; else Smax_:=Smax(t,k,n,IJ); IJ_:=IJ; num_IJ:=nops(IJ); end if; num_Smax:=nops(Smax_); for i from 1 to num_Smax do rat_term[i]:=simpcomb(subs({seq(var[m]=var[m]-Smax_[i,m],m=1..num_IJ)},t)/t); end do; eq:=sum('a[op(Smax_[i])]*rat_term[i]','i'=1..num_Smax); variables:=select(has,indets(eq),a); eq:={coeffs(expand(numer(eq)),k)}; if _EnvP=1 then if print=1 then printf("structureset: %a \t number of equations: %d \t number of variables: %d \n", IJ_,nops(eq),nops(variables)); else printf("number of equations: %d \t number of variables: %d \n", nops(eq),nops(variables)); end if; end if; sol:=_EnvSolve(eq,variables); if {seq(op(2,sol[i]),i=1..nops(sol))}={0} then ERROR(`No k-free recurrence equation exists`) end if; for i from 1 to num_Smax do arg[i]:=seq(var[m]-Smax_[i,m],m=1..num_IJ); end do; recurrence:=sum('a[op(Smax_[i])]*F(arg[i])','i'=1..num_Smax); if _EnvFilter=1 then recurrence:=filter_back(recurrence,tt,k,n,F) end if; recurrence:=subs(sol,recurrence); recurrence:=updateF_back(recurrence,t_,k,n,F); if nargs<=5 then recurrence:=replacevar(recurrence,F,n,a); else recurrence:=numer(normal(recurrence)); recurrence:=contentrec_(recurrence,F,n,a); recurrence:=collect(recurrence,F,factor); recurrence:={recurrence=0}; end if; return(recurrence); end proc: ########################################################### # # # 'findkfreerec' versucht eine k-freie Rekursion # # zu finden. Es werden keine P-maximalen Strukturmengen # # verwendet. Die Strukturmengen werden dabei solange # # vergrössert, bis eine Rekursionsgleichung gefunden # # wird. # # # ########################################################### findkfreerec:=proc(t,k,n) local i,j,r,IJ,recurrence,F,a,S; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; F:=NULL; a:=NULL; S:=NULL; if 41 then i:=args[2]; for j from 1 to nops(F_list[1]) do if op(indets(op(j,F_list[1])))=i then nvar:=j; end if; end do; v_list:=map(x->(op(nvar,x)-i),F_list); else v_list:=map(x->(op(1,x)-op(indets(op(1,F_list[1])))),F_list); end if; return(max(op(v_list))-min(op(v_list))); end proc: orderrec:=proc(recurrence) local var; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; if nargs>1 then var:=args[2] else var:=NULL end if; if type(recurrence,list) or type(recurrence,set) then return(map(x->order_r(x,var),[op(recurrence)])); else return(order_r(recurrence,var)); end if; end proc: ########################################################### # # # 'ordercer' gibt die Ordnungen von Zertifikats- # # Rekursionen in der ersten Variablen an (optional: # # in einer bestimmten Variablen). # # # ########################################################### ordercer:=proc(certificate) local var; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; if nargs>1 then var:=args[2] else var:=NULL end if; if type(certificate,list)=true or type(certificate,set)=true then return(orderrec(map(x->torec(x),certificate),var)); else return(orderrec(torec(certificate),var)); end if; end proc: ########################################################### # # # 'checkrec' überprüft, ob t die eingegebene # # Rekursionsgleichung erfüllt. # # # ########################################################### check_r:=proc(recurrence,t) local i,j,var,l_rec,F_list,fulfilled,F,rules,subs_S,rec1,rec2,err; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; l_rec:=lhs(recurrence)-rhs(recurrence); if type(t,equation) then if orderrec(recurrence)>orderrec(t) then rec1:=t; rec2:=recurrence; else rec1:=recurrence; rec2:=t; end if; err:=0; while orderrec(rec2)>orderrec(rec1) do rec2:=addrec(rec1,rec2); err:=err+1; if err>200 then ERROR(`Recurrences must contain the same variables`) end if; end do; rec2:=addrec(rec1,rec2); if lhs(rec2)=0 and rhs(rec2)=0 then return(true) else return(false); end if; end if; if type(l_rec,`+`) then F_list:=[op(select(type,indets(l_rec),function))]; var:=[]; for i from 1 to nops(F_list[1]) do var:=[op(var),op(indets(op(i,F_list[1])))]; end do; rules:={}; for i from 1 to nops(F_list) do subs_S:={}; for j from 1 to nops(F_list[i]) do subs_S:=subs_S union {var[j]=op(j,F_list[i])}; end do; rules:=rules union {F_list[i]=subs(subs_S,t)}; end do; fulfilled:=simpcomb(subs(rules,l_rec))=0; if fulfilled then return(true) else return(false); end if; end if; end proc: checkrec:=proc(recurrence,t) option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; if type(recurrence,list) or type(recurrence,set) then return(map(x->check_r(x,t),[op(recurrence)])); else return(check_r(recurrence,t)); end if; end proc: ########################################################### # # # 'checkcer' überprüft, ob t die eingegebene # # Rekursionsgleichung erfüllt. # # # ########################################################### check_c:=proc(recurrence,t) option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; return(checkrec(torec(recurrence),t)); end proc: checkcer:=proc(recurrence,t) option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; if type(recurrence,list) or type(recurrence,set) then return(map(x->check_c(x,t),[op(recurrence)])); else return(check_c(recurrence,t)); end if; end proc: ########################################################### # # # 'prinpart' gibt den Hauptteil eines Zertifikats aus. # # # ########################################################### prinpart:=proc(certificate) local F_list,delta,l_cer,i,k; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; l_cer:=lhs(certificate)-rhs(certificate); F_list:=select(type,indets(l_cer),function); delta:={}; for i from 1 to nops(F_list) do if type(op(0,F_list[i]),indexed) then delta:=delta union {F_list[i]} end if; end do; return(l_cer-sum(delta[k],k=1..nops(delta))); end proc: ########################################################### # # # 'minrec' bestimmt die Minima der Indizes der # # zulässigen hypergeometrischen Terme. # # # ########################################################### minrec:=proc(recurrence) local i,j,min,r,l_rec,var,F_list; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; l_rec:=lhs(recurrence)-rhs(recurrence); F_list:=select(type,indets(prinpart(l_rec=0)),function); var:=[]; for i from 1 to nops(F_list[1]) do var:=[op(var),op(indets(op(i,F_list[1])))]; end do; r:=nops(var)-1; for j from 1 to r+1 do min[j]:=infinity end do; for i from 1 to nops(F_list) do for j from 1 to nops(op(i,F_list)) do if evalb(op(j,op(i,F_list))-var[j]max[j]) then max[j]:=op(j,op(i,F_list))-var[j] end if; end do; end do; return([seq(max[i],i=1..r+1)]); end proc: ########################################################### # # # 'shiftrec' führt eine Indexverschiebung aus. # # # ########################################################### shift_r:=proc(recurrence) local i,j,max,min,r,l_rec,var,F_list,a; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; l_rec:=lhs(recurrence)-rhs(recurrence); F_list:=select(type,indets(l_rec),function); var:=[]; for i from 1 to nops(F_list[1]) do var:=[op(var),op(indets(op(i,F_list[1])))]; end do; r:=nops(var)-1; if nargs>1 then min:=minrec(recurrence); l_rec:=subs(seq(var[j]=var[j]-min[j],j=1..r+1),l_rec); else max:=maxrec(recurrence); l_rec:=subs(seq(var[j]=var[j]-max[j],j=1..r+1),l_rec); end if; l_rec:=contentrec_(l_rec,op(0,F_list[1]),op(1,var),a); l_rec:=collect(l_rec,op(0,F_list[1]),factor); return(l_rec=0); end proc: shiftrec:=proc(recurrence) local args_; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; if nargs>1 then args_:=args[2]; else args_:=NULL; end if; if type(recurrence,list) or type(recurrence,set) then return(map(x->shift_r(x,args_),{op(recurrence)})); else return(shift_r(recurrence,args_)); end if; end proc: ########################################################### # # # 'shiftcer' führt eine Indexverschiebung aus. # # # ########################################################### shift_c:=proc(recurrence) local i,j,min,r,l_rec,var,F_list; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; l_rec:=lhs(recurrence)-rhs(recurrence); if nargs>1 then min:=maxrec(recurrence); min[1]:=minrec(recurrence)[1]; else min:=minrec(recurrence); min[1]:=maxrec(recurrence)[1]; end if; F_list:=select(type,indets(l_rec),function); var:=[]; j:=1; while j1 then args_:=args[2]; else args_:=NULL; end if; if type(recurrence,list) or type(recurrence,set) then return(map(x->shift_c(x,args_),{op(recurrence)})); else return(shift_c(recurrence,args_)); end if; end proc: ########################################################### # # # 'tocer' wandelt eine Rekursionsgleichung # # (nicht notwendig k-frei) in eine Rekursionsgleichung # # mit Delta-Ausdrücken (Zertifikats-Rekursion) um. # # # ########################################################### to_c:=proc(recurrence) local i,j,r,kk,l_rec,max,rec_list,F,F_list,cer_recurrence, delta,Delta,exp,p_part,p_part_test,coeff_,m; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; l_rec:=lhs(recurrence)-rhs(recurrence); if not(type(l_rec,`+`)) then ERROR(`No non-trivial certificate recurrence exists`) end if; F_list:=[]; for i from 1 to nops(l_rec) do F_list:=[op(F_list),op(select(type,indets(op(i,l_rec)),function))]; end do; F:=op(0,F_list[1]); kk:=[]; for i from 2 to nops(F_list[1]) do kk:=[op(kk),op(indets(op(i,F_list[1])))]; end do; r:=nops(kk); rec_list:=[]; for i from 1 to nops(l_rec) do rec_list:=[op(rec_list),[op(i,l_rec)/F_list[i], [op(F_list[i])]]]; end do; max:=-minrec(recurrence); cer_recurrence:=0; for i from 1 to r do delta:=0; for j from 1 to nops(rec_list) do exp:=[seq(-(rec_list[j,2,l+1]-kk[l]),l=1..r)]; delta:=delta+sum(subs({seq(kk[m]=kk[m]-(max[m+1]-exp[m]),m=1..i-1),kk[i]=kk[i]-l}, rec_list[j,1]*F(op(rec_list[j,2]))),l=0..max[i+1]-exp[i]-1); end do; delta:=collect(delta,F,factor); if delta<>0 then cer_recurrence:=cer_recurrence+Delta[kk[i]](delta); end if; end do; p_part:=0; p_part_test:=0; for j from 1 to nops(rec_list) do exp:=[seq(-(rec_list[j,2,l+1]-kk[l]),l=1..r)]; coeff_:=subs({seq(kk[m]=kk[m]-(max[m+1]-exp[m]),m=1..r)},rec_list[j,1]); p_part:=p_part+coeff_*F(rec_list[j,2,1],seq(kk[m]-max[m+1],m=1..r)); p_part_test:=p_part_test+coeff_*F(rec_list[j,2,1]); end do; p_part:=collect(p_part,F,factor); p_part_test:=collect(p_part_test,F,factor); if p_part=0 or not(type(p_part_test,freeof(kk))) then ERROR(`No non-trivial certificate recurrence exists`) end if; cer_recurrence:=p_part+cer_recurrence; if nargs>1 then return(p_part) else return(cer_recurrence=0) end if; end proc: tocer:=proc(recurrence) local opt; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; if nargs>1 then opt:=1 else opt:=NULL end if; if type(recurrence,list) or type(recurrence,set) then return(map(x->to_c(x,opt),{op(recurrence)})); else return(to_c(recurrence,opt)); end if; end proc: ########################################################### # # # 'torec' wandelt eine Rekursionsgleichung mit Delta- # # Ausdrücken (Zertifikats-Rekursion) in eine # # Rekursionsgleichung (nicht notwendig k-frei) um. # # # ########################################################### to_r:=proc(certificate) local i,m,l_cer,F_list,delta_list,F,recurrence,index; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; l_cer:=lhs(certificate)-rhs(certificate); F_list:=select(type,indets(l_cer),function); delta_list:={}; for i from 1 to nops(F_list) do if type(op(0,F_list[i]),indexed) then delta_list:=delta_list union {F_list[i]} end if; end do; F_list:=F_list minus delta_list; F:=op(0,F_list[1]); recurrence:=subs({seq(delta_list[m]=0,m=1..nops(delta_list))},l_cer); for i from 1 to nops(delta_list) do index:=op(1,op(0,delta_list[i])); recurrence:=recurrence+op(1,delta_list[i]); recurrence:=recurrence-subs(index=index-1,op(1,delta_list[i])); end do; return(collect(recurrence,F,factor)=0); end proc: torec:=proc(recurrence) option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; if type(recurrence,list) or type(recurrence,set) then return(map(x->to_r(x),{op(recurrence)})); else return(to_r(recurrence)); end if; end proc: ########################################################### # # # 'Jmax' bestimmt die Maxima der Komponenten der Punkte # # einer beliebigen Strukturmenge S, wobei die erste # # Komponente nicht betrachtet wird. # # # ########################################################### Jmax:=proc(S) local i,j,m,r,Jmax_; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; r:=nops(S[1])-1; Jmax_:=[seq(-infinity,m=1..r)]; for i from 1 to nops(S) do for j from 1 to r do if S[i][j+1]>Jmax_[j] then Jmax_[j]:=S[i][j+1] end if; end do; end do; return(Jmax_); end proc: ########################################################### # # # '_rec' versucht eine Rekursionsgleichung zu finden # # (bzgl.der P-maximalen Strukturmenge der Standard- # # Strukturmenge Sstd), bei der der Hauptteil k-frei ist. # # ( 1. Verallgemeinerung ) # # # ########################################################### _rec:=proc(t_,k,n,IJ,M) local t,tt,i,j,kk,l,m,variables,eq,var,F,a,Smax_,num_Smax,num_IJ,pol,pol_set,Jmax_, ansatz,rec_eq,reduced_eq,reduced_variables,recurrence,reduced_sol,sol,IJ_; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; if 50 then Smax_:=selectSmax(updateF(t,k,n),k,n,K); i:=1; if M=0 then while i<=nops(Smax_) do try recurrence:=krec(t,k,n,Smax_[i],F,a); if cer=1 then recurrence:=map(x->tocer(x),recurrence); end if; break; catch "No k-free recurrence equation exists": i:=i+1; end try; end do; else while i<=nops(Smax_) do try recurrence:=_rec(t,k,n,Smax_[i],M,F,a); if cer=1 then temp_rec:={}; for j from 1 to nops(recurrence) do try temp_rec:=temp_rec union {tocer(recurrence[j])}; catch "No non-trivial certificate recurrence exists": end try; end do; recurrence:=temp_rec; end if; if recurrence={} then i:=i+1; else break; end if; catch "No non-trivial certificate recurrence exists": i:=i+1; end try; end do; end if; else r:=nops(k); IJ:=[1,seq(0,i=1..r)]; i:=1; if M=0 then while i<=r+1 do try recurrence:=krec(t,k,n,IJ,F,a); if cer=1 then recurrence:=map(x->tocer(x),recurrence); end if; break; catch "No k-free recurrence equation exists": if i=r+1 then i:=1 else i:=i+1 end if; IJ[i]:=IJ[i]+1; end try; end do; else while i<=r+1 do try recurrence:=_rec(t,k,n,IJ,M,F,a); if cer=1 then temp_rec:={}; for j from 1 to nops(recurrence) do try temp_rec:=temp_rec union {tocer(recurrence[j])}; catch "No non-trivial certificate recurrence exists": end try; end do; recurrence:=temp_rec; end if; if recurrence={} then if i=r+1 then i:=1 else i:=i+1 end if; IJ[i]:=IJ[i]+1; else break; end if; catch "No non-trivial certificate recurrence exists": if i=r+1 then i:=1 else i:=i+1 end if; IJ[i]:=IJ[i]+1; end try; end do; end if; end if; end if; if recurrence={} then if M=0 then ERROR(`No k-free recurrence equation exists`) else ERROR(`No non-trivial certificate recurrence exists`) end if; end if; return(recurrence); end proc: ########################################################### # # # 'sumrec' summiert über alle Summationsvariablen # # der Rekursionsgleichungen in der Menge recurrence. # # # ########################################################### sumrec:=proc(recurrence) local i,j,m,S,rules,sum_recurrence,recurrences,p_part,F_list, minimal,sum_rec,ord,min_ord,new_rec,a; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; minimal:=true; if 11 and min_ord>1 then for i from 1 to nops(sum_rec) do for j from i+1 to nops(sum_rec) do new_rec:=addrec(sum_rec[1],sum_rec[2]); if new_rec<>(0=0) then return(new_rec); end if; end do; end do; end if; return(sum_rec[1]); end if; return(sum_recurrence); end proc: ########################################################### # # # 'sumcer' summiert über alle Summationsvariablen # # der Zertifikats-Rekursionen in der Menge certificate. # # # ########################################################### sumcer:=proc(certificate) local i,j,m,S,rules,subs_S,sum_certificate,certificates,p_part,F_list,l_cer,delta_list, minimal,sum_rec,ord,min_ord,new_rec,a; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; minimal:=true; if 11 and min_ord>1 then for i from 1 to nops(sum_rec) do for j from i+1 to nops(sum_rec) do new_rec:=addrec(sum_rec[1],sum_rec[2]); if new_rec<>(0=0) then return(new_rec); end if; end do; end do; end if; return(sum_rec[1]); end if; return(sum_certificate); end proc: ########################################################### # # # 'decomposeS' zerlegt die Strukturmenge S in Mengen # # S_0,...,S_r, wobei x ein Element von S_i ist, wenn es # # reduzibel bzgl. S und i ist (bei i=0 irreduzibel # # bzgl. S). # # # ########################################################### decomposeS:=proc(S) local i,j,k,r,de_S,S_; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; r:=nops(S[1])-1; S_:=S; for i from 1 to r do de_S[i]:={}; for j from 1 to nops(S_) do for k from 1 to nops(S) do if S_[j]=subsop(i+1=op(i+1,S[k])-1,S[k]) then de_S[i]:=de_S[i] union {S_[j]}; break; end if; end do; end do; S_:=S_ minus de_S[i]; end do; return([S_,seq(de_S[i],i=1..r)]); end proc: ########################################################### # # # '_cer' versucht eine Rekursionsgleichung zu finden # # (bzgl.der P-maximalen Strukturmenge der Standard- # # Strukturmenge Sstd), bei der der Hauptteil k-frei ist. # # ( 2. Verallgemeinerung ) # # # ########################################################### _cer:=proc(tt,k,n,IJ,M) local t,i,j,m,p,kk,var,Smax_,de_Smax,num_IJ,IJ_,F,a,ansatz,recurrence,Jmax_, ansatz_,recurrence_,reduced_variables,reduced_eq,reduced_sol,pol, eq,variables,sol,recurrences,pol_set,rules; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; if 51 then ansatz_[i,j]:=a[op(de_Smax[i,j]),seq(l[m],m=1..num_IJ-1)]* product(kk[m]^l[m],m=1..num_IJ-1)* simpcomb(subs(rules[i,j],t)/t)- subs(var[i]=var[i]-1,a[op(de_Smax[i,j]),seq(l[m],m=1..num_IJ-1)]* product(kk[m]^l[m],m=1..num_IJ-1))* simpcomb(subs(rules[i,j],subs(var[i]=var[i]-1,t))/t); else ansatz_[i,j]:=a[op(de_Smax[i,j]),seq(l[m],m=1..num_IJ-1)]* product(kk[m]^l[m],m=1..num_IJ-1)* simpcomb(subs(rules[i,j],t)/t); end if; recurrence_[i,j]:=a[op(de_Smax[i,j]),seq(l[m],m=1..num_IJ-1)]* product(kk[m]^l[m],m=1..num_IJ-1); for p from 1 to num_IJ-1 do ansatz_[i,j]:=sum(ansatz_[i,j],l[p]=0..M); recurrence_[i,j]:=sum(recurrence_[i,j],l[p]=0..M); end do; recurrence_[i,j]:=recurrence_[i,j]*F(op(var-de_Smax[i,j])); end do; ansatz_[i]:=sum(ansatz_[i,m],m=1..nops(de_Smax[i])); recurrence_[i]:=sum(recurrence_[i,m],m=1..nops(de_Smax[i])); end do; ansatz:=sum('ansatz_[i]','i'=1..num_IJ); ########################################################### for i from 1 to nops(de_Smax[1]) do pol[op(de_Smax[1,i])]:=a[op(de_Smax[1,i]),seq(l[m],m=1..num_IJ-1)]* product((kk[m]+de_Smax[1,i,m+1]-Jmax_[m])^l[m],m=1..num_IJ-1); pol[de_Smax[1,i,1]]:=0; for j from 1 to num_IJ-1 do pol[op(de_Smax[1,i])]:=sum(pol[op(de_Smax[1,i])],l[j]=0..M); end do; end do; for i from 1 to nops(de_Smax[1]) do pol[de_Smax[1,i,1]]:=expand(pol[de_Smax[1,i,1]]+pol[op(de_Smax[1,i])]) end do; pol_set:=[op({seq(pol[de_Smax[1,i,1]],i=1..nops(de_Smax[1]))})]; for i from 1 to nops(pol_set) do if ldegree(pol_set[i],{op(kk)})=0 then pol_set[i]:=pol_set[i]-tcoeff(pol_set[i],kk) end if; reduced_variables[i]:=select(has,indets(pol_set[i]),a); reduced_eq[i]:={coeffs(pol_set[i],k)}; reduced_sol[i]:=solve(reduced_eq[i],reduced_variables[i]); end do; ########################################################### eq:=subs({seq(op(reduced_sol[i]),i=1..nops(pol_set))},ansatz); variables:=select(has,indets(eq),a); eq:={coeffs(numer(eq),k)}; if _EnvP=1 then printf("structureset: %a \t number of equations: %d \t number of variables: %d \n", IJ_,nops(eq),nops(variables)); end if; sol:=_EnvSolve(eq,variables); if {seq(op(2,sol[i]),i=1..nops(sol))}={0} then ERROR(`No non-trivial certificate recurrence exists`) end if; ########################################################### recurrences:=subs({seq(op(reduced_sol[i]),i=1..nops(pol_set))}, [seq(recurrence_[i],i=1..num_IJ)]); recurrences:=subs(sol,recurrences); recurrence:=recurrences[1]; for i from 2 to num_IJ do recurrence:=recurrence+recurrences[i]-subs(var[i]=var[i]-1,recurrences[i]); end do; if _EnvFilter=1 then recurrence:=filter_back(recurrence,tt,k,n,F) end if; if nargs<=6 then recurrence:=replacevar(recurrence,F,n,a) else recurrence:=numer(normal(recurrence)); recurrence:=contentrec_(recurrence,F,n,a); recurrence:=collect(recurrence,F,factor); recurrence:={recurrence=0}; end if; return(recurrence); end proc: ########################################################### # # # 'findcer' versucht eine Rekursionsgleichung mit # # Hilfe der zweiten Verallgemeinerung zu finden. # # Die Strukturmengen werden dabei solange vergrössert, # # bis eine Rekursionsgleichung gefunden wird. # # # ########################################################### findcer:=proc(t,k,n,K,M) local i,j,r,IJ,recurrence,cer_,F,a,Smax_,temp_rec; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; cer_:=1; F:=NULL; a:=NULL; if 50 then Smax_:=selectSmax(updateF(t,k,n),k,n,K); i:=1; while i<=nops(Smax_) do try recurrence:=_cer(t,k,n,Smax_[i],M,F,a); if cer_=1 then temp_rec:={}; for j from 1 to nops(recurrence) do try temp_rec:=temp_rec union {tocer(recurrence[j])}; catch "No non-trivial certificate recurrence exists": end try; end do; recurrence:=temp_rec; end if; if recurrence={} then i:=i+1; else break; end if; catch "No non-trivial certificate recurrence exists": i:=i+1; end try; end do; else r:=nops(k); IJ:=[1,seq(0,i=1..r)]; i:=1; while i<=r+1 do try recurrence:=_cer(t,k,n,IJ,M,F,a); if cer_=1 then temp_rec:={}; for j from 1 to nops(recurrence) do try temp_rec:=temp_rec union {tocer(recurrence[j])}; catch "No non-trivial certificate recurrence exists": end try; end do; recurrence:=temp_rec; end if; if recurrence={} then if i=r+1 then i:=1 else i:=i+1 end if; IJ[i]:=IJ[i]+1; else break; end if; catch "No non-trivial certificate recurrence exists": if i=r+1 then i:=1 else i:=i+1 end if; IJ[i]:=IJ[i]+1; end try; end do; end if; end if; if recurrence={} then ERROR(`No non-trivial certificate recurrence exists`) end if; return(recurrence); end proc: ########################################################### # # # 'solverec' bestimmt die Lösung einer Rekursion, deren # # Strukturmenge genau zwei Elemente besitzt. # # # ########################################################### solverec:=proc(recurrence) local i,j,n,S,S_list,s0,rat,cont,num,den,numlist,denlist,lc,shift,sh,order,sol,m,arg_pw; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; order:=orderrec(recurrence); S_list:=select(type,indets(recurrence),function); if nops(S_list)>2 then ERROR(`solverec expects only two summands in recurrence equation`) end if; n:=op(indets(op(1,S_list[1]))); S:=op(0,S_list[1]); rat:=normal(solve(shiftrec(recurrence,1),S(n+order))/S(n)); cont:=contentrec(shiftrec(recurrence,1))[1]; num:=numer(rat)*cont; den:=denom(rat)*cont; lc:=lcoeff(num,n)/lcoeff(den,n); numlist:=normal([solve(num,n)]); numlist:=[seq(-j,j=numlist)]; denlist:=normal([solve(den,n)]); denlist:=[seq(-j,j=denlist)]; if order=1 then shift:=0; if nargs=2 then shift:=op(1,lhs(args[2])); numlist:=map(x->x+shift,numlist); denlist:=map(x->x+shift,denlist); end if; sh:=-min(1,op(select(type,{op(numlist),op(denlist)},nonposint)))+1; numlist:=map(x->x+sh,numlist); denlist:=map(x->x+sh,denlist); shift:=shift+sh; s0:=S(shift); if member(1,denlist,'i') then denlist:=subsop(i=NULL,denlist); else numlist:=[op(numlist),1]; end if; sol:=eval(subs({n=n-shift,pochhammer=`simpcomb/pochhammer`},s0*hyperterm(numlist,denlist,lc,n))); if nargs=2 then sol:=subs(args[2],sol); end if; if sol<>0 then sol:=applyrule([(-1)^(k::anything)*pochhammer(n::anything,k::anything)/(k::anything)!=binomial(-n,k), (-1)^(k::anything)*pochhammer(n::anything,k::anything)/pochhammer(1,k::anything)=binomial(-n,k)], sol); end if; #sol:=convert(sol,binomial); return(sol); else for i from 1 to nops(numlist) do numlist[i]:=(numlist[i]+l)/order; end do; for i from 1 to nops(denlist) do denlist[i]:=(denlist[i]+l)/order; end do; numlist:=[op(numlist),1]; sol:=eval(subs(pochhammer=`simpcomb/pochhammer`,S(l)*order^((nops(numlist)-1-nops(denlist))*((n-l)/order))*hyperterm(numlist,denlist,lc,(n-l)/order))); arg_pw:=[]; for m from 1 to order do arg_pw:=[op(arg_pw),irem(n,order)=m-1]; arg_pw:=[op(arg_pw),subs(l=m-1,sol)]; end do; if nargs=2 then arg_pw:=subs(args[2],arg_pw); end if; arg_pw:=applyrule([(-1)^(k::anything)*pochhammer(n::anything,k::anything)/(k::anything)!=binomial(-n,k), (-1)^(k::anything)*pochhammer(n::anything,k::anything)/pochhammer(1,k::anything)=binomial(-n,k)], arg_pw); #arg_pw:=convert(arg_pw,binomial); return(piecewise(op(arg_pw))); end if; end proc: ########################################################### # # # 'multclosedform' bestimmt zu einem zulässigen Term t # # eine geschlossene Form, falls eine Rekursion # # erster Ordnung für die Summe existiert. # # # ########################################################### multclosedform:=proc(t,k,sn,init) local i,K,j,r,M,sumrec,s0,rat,num,den,numlist,denlist,lc,S,n,F,a,hypsol; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; r:=nops(k); if type(sn,function) then S:=op(0,sn); n:=op(1,sn); else n:=sn; end if; if type(init,set) then S:=init[1]; else S:=init; end if; S:=op(0,lhs(S)); K:=1; M:=1; if 41 then opt_arg:=args[2]; if not(type(opt_arg,equation)) then return(L); end if; else opt_arg:=NULL; end if; hyper_sol:={}; for i from 1 to nops(L) do hyper_sol:={solverec(denom(L[i])*S(n+1)-numer(L[i])*S(n)=0,opt_arg)} union hyper_sol; end do; return(hyper_sol); end proc: ########################################################### # # # 'duration' misst die Zeit einer Prozedur proc. # # Als Argument erwartet die Funktion 'proc'. # # # ########################################################### duration:=proc(f) local start,sol; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; start:=time(): sol:=eval(f); return([time()-start,sol]); end proc: ########################################################### if nops([libname])>1 then multsum_LIB:=cat(libname[-1],"/multsum.dll") else multsum_LIB:=cat(libname,"/multsum.dll") end if: c_properterm:=proc(t,k,n) local pol_gam,abc_uvw,var; option remember, `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; var:=[n,op(k)]; check_hyper(t,k,n); pol_gam:=check_proper(t,k,n); abc_uvw:=convertgam(pol_gam[2]); return([nops(abc_uvw[1]), nops(abc_uvw[2]), ListTools[Flatten](convertfacex(abc_uvw[1],abc_uvw[2],k,n,1))]); end proc: try c_setfacex:= define_external( 'set_fac_ex', 'n' :: integer[4], 'pp' :: integer[4], 'qq' :: integer[4], 'ab_uv' :: ARRAY(datatype=integer[4]), LIB=multsum_LIB ): c_facdiff:= define_external( 'fac_diff', LIB=multsum_LIB ): c_structurefct:= define_external( 'structure_fct', LIB=multsum_LIB ): c_inequat:= define_external( 'inequat', 'IJ' :: ARRAY(datatype=integer[4]), LIB=multsum_LIB ): c_setminmaxIJ:= define_external( 'set_min_max_IJ', 'min_max_IJ' :: ARRAY(datatype=integer[4]), LIB=multsum_LIB ): c_getSmax:= define_external( 'Smax', 'Smax_' :: ARRAY(datatype=integer[4]), RETURN :: boolean[1], LIB=multsum_LIB ): c_getnumSmax:= define_external( 'get_num_Smax', RETURN :: integer[4], LIB=multsum_LIB ): c_getS:= define_external( 'select_Smax', 'max_IJ' :: integer[4], 'S' :: ARRAY(datatype=integer[4]), RETURN :: boolean[1], LIB=multsum_LIB ): c_getnumS:= define_external( 'get_num_S', RETURN :: integer[4], LIB=multsum_LIB ): catch: _EnvC:=0; end try: c_Smax:=proc(t,k,n,IJ) local num_IJ,propterm,IJ_,pp,qq,ab_uv,Smax_,i,j,min_max_IJ,extend,all_Smax,max_num_Smax; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; if 4evalb(nops(x[2])<=nops(y[2]))); Smax_sorted:=[S_[1]]; for i from 2 to nops(S_) do if evalb(nops(S_[i,2])<>nops(S_[i-1,2])) then Smax_sorted:=[op(Smax_sorted),S_[i]] end if; end do; return(Smax_sorted); end proc: selectSstd:=proc(t,k,n,max_IJ) local i,IJ_Smax,extend; option `Copyright 2003-2005 Torsten Sprenger, University of Kassel`; if 4