Reputation: 113
I'm trying to make a recursive relation by "for loop" in Maple. Suppose we have two sequences M[i](x)
and N[i](x)
which N[0](x)=x^2
and M[i](x)=N[i-1](x)+1
and N[i](x)=M[i](x)+2
. So I tried this code:
N[0] := proc (x) options operator, arrow; x^2 end proc;
for i to 3 do M[i] := proc (x) options operator, arrow; N[i-1](x)+1 end proc; N[i] := proc (x) options operator, arrow; M[i](x)+2 end proc end do;
But it doesn't give the correct answer (e.g. N[1](x)
must be x^2+3
). By the way, for some reasons I have to define my functions by mapping x
. Is there anyway to modify this code?
Upvotes: 1
Views: 836
Reputation: 7246
The rsolve
command can easily handle this example, except that it expects functions of the independent variable i
.
And what you have is equations involving functions of x
(which doesn't bear on the recursion), with i
only appearing as an index.
You can rewrite the equations as functions of i
, call rsolve
, and then resubstitute back for the original functions.
It would be little effort to construct the substituion set S
below by simply entering it in by hand. But for fun I construct it programmatically.
restart;
R1 := N[0](x) = x^2;
2
R1 := N[0](x) = x
R2 := M[i](x) = N[i-1](x)+1;
R2 := M[i](x) = N[i - 1](x) + 1
R3 := N[i](x) = M[i](x)+2;
R3 := N[i](x) = M[i](x) + 2
S := map( u->u=op([0,0],u)(op([0,1],u)),
indets({R1,R2,R3},
specfunc(anything,{N,M})) );
S := {M[i](x) = M(i), N[0](x) = N(0), N[i](x) = N(i),
N[i - 1](x) = N(i - 1)}
newEqs := eval( {R1,R2,R3}, S );
2
newEqs := { M(i) = N(i - 1) + 1, N(0) = x , N(i) = M(i) + 2 }
newV := eval( {N[i](x),M[i](x)}, S );
newV := {M(i), N(i)}
tempans := rsolve( newEqs, newV );
2 2
tempans := { M(i) = x + 3 i - 2, N(i) = x + 3 i }
ans := eval( tempans, map(rhs=lhs,S) );
2 2
ans := { M[i](x) = x + 3 i - 2, N[i](x) = x + 3 i }
Having constructed equations for the general forms of M[i](x)
and N[i](x)
you can evaluate either of those at specific cals of i
. You can also create procedures from those results, and assign them. Eg,
for k from 1 to 3 do
N[k] := unapply(subs(i=k,eval(N[i](x),ans)), [x]);
end do:
N[3](11);
130
It seems inefficient to create all those operators (procedures separately). Why not create just on for N
and one for M
, that admits two arguments for i
and x
?
Nfunc := unapply(eval(N[i](x),ans), [i,x]);
2
Nfunc := (i, x) -> x + 3 i
Nfunc(3,x);
2
x + 9
Nfunc(3, 11);
130
[edited] I should tell you why your original attempt failed.
When you try your original attempt the i
that appears within both of the procedure bodies is not simplified to the current value of the loop index i
. And when you subsequently try and run any of the constructed procedures then it would just pick up whatever value the global i
still had. There is no link between the index value of the name N[2]
say and the i
in its assigned procedure, whenever you subsequently call N[2](x)
.
restart;
N[0] := x -> x^2:
for i to 2 do
M[i] := x -> N[i-1](x)+1;
N[i] := x -> M[i](x)+2;
end do;
M[1] := x -> N[i - 1](x) + 1
N[1] := x -> M[i](x) + 2
M[2] := x -> N[i - 1](x) + 1
N[2] := x -> M[i](x) + 2
N[2](11); # why this result, you might asK
M[3](11) + 2
i; # still the value coming out of that do-loop
3
unassign('i');
N[2](11); # no relation between the 2 and the `i`
M[i](11) + 2
You could fix up your original by constructing a recursive sequence of procedures. The following "works". But it is incredibly inefficient at run-time because every call to any of the N[..]
or M[..]
procedures will recursively call into the others in the chain. And that whole recursive set of calls will happen every time you call it. That is to say, here the recursion occurs at run-time of each of the procedures.
restart;
N[0] := x -> x^2:
for i to 3 do
M[i] := subs(ii=i, x -> N[ii-1](x)+1);
N[i] := subs(ii=i,x -> M[ii](x)+2);
end do;
M[1] := x -> N[0](x) + 1
N[1] := x -> M[1](x) + 2
M[2] := x -> N[1](x) + 1
N[2] := x -> M[2](x) + 2
M[3] := x -> N[2](x) + 1
N[3] := x -> M[3](x) + 2
N[3](11);
130
The overall performance of running such a scheme would be very poor.
Much better would be to utilize the unapply
command so that each of the N[i]
and M[i]
(for explicit i
values) is a procedure that contains its explicit formula. When using unapply
in the following way we pass it the function call which recursively evalutes to the respective formula. Here the recursion occurs only at construction time of each of the procedures.
restart;
N[0] := x -> x^2:
for i to 3 do
M[i] := unapply( N[i-1](x)+1, x);
N[i] := unapply( M[i](x)+2, x);
end do;
2
M[1] := x -> x + 1
2
N[1] := x -> x + 3
2
M[2] := x -> x + 4
2
N[2] := x -> x + 6
2
M[3] := x -> x + 7
2
N[3] := x -> x + 9
N[3](11);
130
But as I noted in my Answer above, there is no need to construct all those procedures at all. By utilizing the rsolve
command we can solve the recurrence relation for the general formula (closed in terms of both i
and x
). And then from that closed formula we can utilize the unapply
command to construct only one 2-argument procedure for N
and one for M
.
Upvotes: 1