1 define_variable(g,'g,any)$
3 /*this block checks for a polynomial in n*/
4 polyp(g,n):=block([d,f,c],
5 g:ratexpand(g), if freeof(n,g) then return(true),
7 for i:d step -1 thru 0 do
8 (c:coeff(g,n,i), if not(freeof(n,c)) then f:false,
10 return(is(g=0 and f)))$
14 /*this block checks for a constant to a polynomial power*/
15 polyinn(x,n):=block([b,e],
16 if inpart(x,0)="*" then
17 return(polyinn(inpart(g,1),n) and polyinn(inpart(g,2),n)),
18 if inpart(x,0)#"^" then return(false),
21 if not freeof(n,b) then return(false),
26 /*this block implements the characteristic equation method*/
27 char(e,g,u,n,k,iv):=block([gensol,homsol,parsol,los,multiplicities,
32 aa[i]:coeff(e,u(n+k-i)),
36 if h#e then return("erroneous input"),
39 h:subst(u^(k-i),u(n+k-i),h),
43 for i:1 thru length(los) do
44 (r[i]:los[i], r[i]:rhs(ev(r[i])),
45 m[i]:multiplicities[i]),
47 sum(sum(a[i,j]*n^(m[i]-j),j,1,m[i])*r[i]^n,i,1,length(los)),
52 for i:1 thru length(los) do
53 for j:1 thru m[i] do v:cons(a[i,j],v),
55 for q:0 thru k-1 do l:cons(subst(q,n,homsol)=u(q),l),
57 return(u(n)=(ev(homsol,ss))))
59 else if polyp(g,n) = true then
60 (g:ratexpand(g), parsol:sum(b[j]*n^j,j,0,hipow(g,n)),
64 (l:ratexpand(subst(n+k-i,n,b[j]*n^j)),
65 v:ratexpand(subst(l,u(n+k-i),v))),
67 if v#0 then return(v) else parsol:n*parsol),
69 for i:0 thru k do (l:ratexpand(subst(n+k-i,n,parsol)),
70 v:ratexpand(subst(l,u(n+k-i),v))),
72 for i:0 thru hipow(parsol,n) do
73 l:cons(coeff(v=g,n,i),l),
75 for j:0 thru hipow(parsol,n) do
80 else if polyinn(g,n) = true then
85 (l:subst(n+k-i,n,parsol), v:subst(l,u(n+k-i),v)),
87 if v#0 then return(v) else parsol:n*parsol),
91 else if inpart(g,0)=sin or inpart(g,0) = cos then
92 (parsol:b[1]*sin(inpart(g,1)) + b[2]*cos(inpart(g,1)),
96 (l:expand(subst(n+k-i,n,parsol)),
97 v:expand(subst(l,u(n+k-i),v))),
99 if v#0 then return(v) else parsol:n*parsol),
101 for i:0 thru k do(l:expand(subst(n+k-i,n,parsol)),
102 v:expand(subst(l,u(n+k-i),v))),
105 lt:[sin(inpart(g,1)),cos(inpart(g,1))],
107 l:cons(coeff(v=g,lt[jj]),l),
112 parsol:ev(parsol,ss))
115 else return("can't be solved in closed form by program"),
117 gensol:homsol + parsol,
119 for i:1 thru length(los) do
120 for j:1 thru m[i] do v:cons(a[i,j],v),
123 l:cons(subst(q,n,gensol)=u(q),l),
124 ss:ev(solve(l,v),iv),
125 return(u(n)=(ev(gensol,ss))))$
130 /*this block implements the generating function method*/
131 genf(e,g,u,n,k,iv):=block([multiplicities,l,v,ss,vv,los,
132 nr,f,sol,p,dispflag],
136 aa[i]:coeff(e,u(n+k-i)),
140 if h#e then return("erroneous input"),
144 l:subst((f-sum(u(j)*x^j,j,0,k-i-1))*x^i,u(n+k-i),l),
150 else if polyp(g,n) = true then
152 v:subst(x^k/(1-x)*coeff(g,n,0),coeff(g,n,0),g),
153 vv:ratsimp(diff(1/(1-x),x)),
154 for i:1 thru hipow(g,n) do
155 (v:subst(x^k*x*vv*coeff(g,n,i),coeff(g,n,i)*n^i,v),
156 vv:ratsimp(diff(x*vv,x))),
161 else if polyinn(g,n) = true and hipow(inpart(g,2),n) < 2 then
162 (g1:(x^k)*(inpart(g,1)^coeff(inpart(g,2),n,0)),
163 g2:1 - x*(inpart(g,1)^coeff(inpart(g,2),n,1)),
168 else return("can't be solved in closed form by program"),
172 los:solve(newrat(f),x),
173 for i:1 thru length(los) do
174 (r[i]:los[i], r[i]:rhs(ev(r[i])),
175 m[i]:multiplicities[i]),
178 b:product((1-r[i]*x)^m[i],i,1,length(los)),
179 for i:1 thru length(los) do
181 (p[i,j]:b*a[i,j]/((1-r[i]*x)^j), v:cons(a[i,j],v)),
182 p:sum(sum(p[i,j],j,1,m[i]),i,1,length(los)),
185 nf:ratexpand(num(f)/abs(coeff(denom(f),x,0))), p:ratexpand(p),
186 for i:0 thru hipow(ratexpand(b),x)-1 do
187 l:cons(coeff(nf=p,x,i),l),
188 sss:ev(solve(l,v),iv),
190 sol:sum(sum(a[i,j]*coeff(denom(f),x,0)/abs(coeff(denom(f),x,0))*
191 binomial(j+n-1,n)*r[i]^n,j,1,m[i]),i,1,length(los)),
193 return(u(n)=(ev(sol,sss))))$
196 /*this block finds the new polynomial associated to f*/
197 newrat(f):=block([hd,cp,dp],
198 hd:hipow(denom(f),x),
199 cp:coeff(denom(f),x,hd),
200 dp:sum((coeff(denom(f),x,i))/cp*x^i,i,0,hd),
201 return(sum(coeff(dp,x,hd-i)*x^i,i,0,hd)))$
207 /*this block implements the variable coefficient method*/
208 varc1(e,g,u,n,k,iv):=block([v,vv,eq,y,cauchysum,finsol,sersol,dispflag],
209 local(a,b),dispflag:false,
211 (a[i]:coeff(e,u(n+i)),
212 a[i]:ratexpand(a[i]),
213 if polyp(a[i],n)=false then return("can't do it")),
214 if k=2 and (b:besselcheck(e,k) # false) then return(b),
216 for i:k step -1 thru 0 do
217 for j:hipow(a[i],n) step -1 thru 0 do
218 (v:ratsubst(x^j*'diff(y,x,i+j),n^j*u(n+i),v),
220 v:ratsubst(y,'diff(y,x,0),v),
222 if polyp(g,n) = true then
223 (g:ratexpand(g), vv:g,
224 for i:0 thru hipow(g,n) do
225 vv:subst(x^i,n^i,vv),
227 else return("can't do it"),
232 if k=1 then finsol:ic1(sol,x=0,y=ev(u(0),iv))
233 else if k=2 then finsol:ic2(sol,x=0,y=ev(u(0),iv),'diff(y,x)=ev(u(1),iv))
234 else return("o.d.e. can't be solved at present by macsyma"),
236 sersol:powerseries(rhs(finsol),x,0), sersol:expand(sersol),
239 if atom(b)=false then b:substpart(n,b,4),
240 return(u(n)=((n!)*b)))$
243 /*this block checks for a bessel recurrence relation*/
245 besselcheck(e,k):=block([a,ans],
248 (a[i]:coeff(e,u(n+i)),
249 a[i]:ratexpand(a[i])),
250 if not(integerp(a[0])) then return(false),
251 if not(integerp(ev(a[1],n=0))) then return(false),
252 if not(hipow(a[1],n)=1) then return(false),
253 if not(integerp(coeff(a[1],n,1))) then return(false),
254 if not(a[2]=1) then return(false),
255 ans:"a linear combination of bessel functions",
256 /*exact details are of no significance,since we are merely
257 demonstrating the feasibility of this approach*/
264 /*this block implements the first order method*/
265 varc2(e,g,u,n,k,iv):=block([h,p,v,c,sol,sj,si,pn,hi,ap],
266 p:(-1)*coeff(e,u(n))/coeff(e,u(n+1)),
270 pn:product(si,i,1,n-1),
271 hi:subst(i,n,v)/product(sj,j,1,i-1),
273 ap:ev(u(0)-subst(0,n,v),iv),
274 return(u(n)=ap*pn+pn*v1))$