Команда rsolve
может легко обработать этот пример, за исключением того, что она ожидает функций независимой переменной i
.
А у вас есть уравнения, включающие функции x
(что не имеет отношения к рекурсии), причем i
появляется только как индекс.
Вы можете переписать уравнения как функции от i
, вызвать rsolve
, а затем снова заменить исходные функции.
Было бы несложно создать набор подстановок S
, приведенный ниже, просто введя его вручную. Но ради интереса конструирую программно.
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 }
Построив уравнения для общих форм M[i](x)
и N[i](x)
, вы можете оценить любое из них при определенных значениях i
. Вы также можете создавать процедуры из этих результатов и назначать их. Например,
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
Кажется неэффективным создавать все эти операторы (процедуры по отдельности). Почему бы не создать только один для N
и один для M
, который допускает два аргумента для i
и 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
[отредактировано] Я должен сказать вам, почему ваша первоначальная попытка не удалась.
Когда вы пробуете исходную попытку, i
, который появляется в обоих телах процедуры, не упрощается до текущего значения индекса цикла i
. И когда вы впоследствии попытаетесь запустить любую из созданных процедур, она просто получит то значение, которое все еще имеет глобальный i
. Нет связи между значением индекса имени N[2]
, скажем, и i
в назначенной ему процедуре, всякий раз, когда вы впоследствии вызываете 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
Вы можете исправить свой оригинал, построив рекурсивную последовательность процедур. Следующее "работает". Но это невероятно неэффективно во время выполнения, потому что каждый вызов любой из N[..]
или M[..]
процедур будет рекурсивно вызывать другие в цепочке. И весь этот рекурсивный набор вызовов будет происходить каждый раз, когда вы его вызываете. То есть здесь рекурсия происходит во время выполнения каждой из процедур.
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
Общая производительность при использовании такой схемы была бы очень низкой.
Намного лучше было бы использовать команду unapply
, чтобы каждая из N[i]
и M[i]
(для явных значений i
) была процедурой, содержащей свою явную формулу. При использовании unapply
следующим образом мы передаем ему вызов функции, который рекурсивно вычисляет соответствующую формулу. Здесь рекурсия происходит только во время построения каждой из процедур.
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
Но, как я отметил в своем ответе выше, нет необходимости строить все эти процедуры вообще. Используя команду rsolve
, мы можем решить рекуррентное соотношение для общей формулы (закрытой с точки зрения как i
, так и x
). А затем из этой закрытой формулы мы можем использовать команду unapply
для создания только одной процедуры с двумя аргументами для N
и одной для M
.
person
acer
schedule
25.10.2018